Let OpenWeather Units fall through the settings cascade
The Units field carried a Default of "metric" and had no blank option, so the global panel layer always set a value and locked organizations and users out of changing it. Mirror the fix already applied to OpenSky's plan. - Plugin descriptor: drop the "metric" Default and add a blank "Not set" option; runtime still falls back to metric when no layer sets it. - Web App: add a "Not set" choice to the Units control and stop forcing metric back into the form on load. - Test guards that the units field has no Default and offers a blank option. - Rebuilt embedded frontend. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
6231b43076
commit
285551fe8a
@@ -71,13 +71,14 @@ func (p *Plugin) Descriptor() plugins.Descriptor {
|
|||||||
ConfigFields: []plugins.ConfigField{
|
ConfigFields: []plugins.ConfigField{
|
||||||
{Key: "apiKey", Label: "API key", Type: "password", Secret: true,
|
{Key: "apiKey", Label: "API key", Type: "password", Secret: true,
|
||||||
Help: "Your OpenWeather API key (the appid query parameter). Required for any live request — OpenWeather has no anonymous tier. Leave blank to enable the plugin as a master switch and supply the key at another layer."},
|
Help: "Your OpenWeather API key (the appid query parameter). Required for any live request — OpenWeather has no anonymous tier. Leave blank to enable the plugin as a master switch and supply the key at another layer."},
|
||||||
{Key: "units", Label: "Units", Type: "select", Default: "metric",
|
{Key: "units", Label: "Units", Type: "select",
|
||||||
Options: []plugins.SelectOption{
|
Options: []plugins.SelectOption{
|
||||||
|
{Value: "", Label: "Not set — let organizations and users choose"},
|
||||||
{Value: "standard", Label: "Standard — Kelvin, m/s"},
|
{Value: "standard", Label: "Standard — Kelvin, m/s"},
|
||||||
{Value: "metric", Label: "Metric — °C, m/s"},
|
{Value: "metric", Label: "Metric — °C, m/s"},
|
||||||
{Value: "imperial", Label: "Imperial — °F, mph"},
|
{Value: "imperial", Label: "Imperial — °F, mph"},
|
||||||
},
|
},
|
||||||
Help: "Measurement system for temperatures and wind speed in responses."},
|
Help: "Measurement system for temperatures and wind speed in responses. Leave it unset to let each organization or user pick their own; set a value only to force one for everyone. Runtime falls back to metric when no layer sets it."},
|
||||||
{Key: "lat", Label: "Default latitude", Type: "text", Default: defaultLat,
|
{Key: "lat", Label: "Default latitude", Type: "text", Default: defaultLat,
|
||||||
Help: "Latitude used by the health probe and by calls that supply no location (−90…90)."},
|
Help: "Latitude used by the health probe and by calls that supply no location (−90…90)."},
|
||||||
{Key: "lon", Label: "Default longitude", Type: "text", Default: defaultLon,
|
{Key: "lon", Label: "Default longitude", Type: "text", Default: defaultLon,
|
||||||
|
|||||||
@@ -38,6 +38,23 @@ func TestDescriptor(t *testing.T) {
|
|||||||
if f.Required {
|
if f.Required {
|
||||||
t.Errorf("config field %q must not be Required", f.Key)
|
t.Errorf("config field %q must not be Required", f.Key)
|
||||||
}
|
}
|
||||||
|
// Units must be blank-able so the value can fall through the settings
|
||||||
|
// cascade: a blank "" option and no Default, otherwise the global layer
|
||||||
|
// always sets it and locks organizations/users out.
|
||||||
|
if f.Key == "units" {
|
||||||
|
if f.Default != "" {
|
||||||
|
t.Errorf("units field must not carry a Default (got %q) — it would lock lower cascade layers", f.Default)
|
||||||
|
}
|
||||||
|
hasBlank := false
|
||||||
|
for _, o := range f.Options {
|
||||||
|
if o.Value == "" {
|
||||||
|
hasBlank = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !hasBlank {
|
||||||
|
t.Error("units field must offer a blank \"\" (Not set) option so it can fall through the cascade")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+5
-5
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+2
-2
@@ -35,8 +35,8 @@
|
|||||||
})()
|
})()
|
||||||
</script>
|
</script>
|
||||||
<title>PilotVault — Control Panel</title>
|
<title>PilotVault — Control Panel</title>
|
||||||
<script type="module" crossorigin src="./assets/index-BK_MuFN4.js"></script>
|
<script type="module" crossorigin src="./assets/index-CpDOSPL4.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="./assets/index-D7rbxd3q.css">
|
<link rel="stylesheet" crossorigin href="./assets/index-DIbxnHR0.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|||||||
@@ -741,6 +741,7 @@ const owHealthTs = ref(null)
|
|||||||
const OW_HEALTH_KEY = 'pv.openweather.health'
|
const OW_HEALTH_KEY = 'pv.openweather.health'
|
||||||
|
|
||||||
const OW_UNITS_OPTS = [
|
const OW_UNITS_OPTS = [
|
||||||
|
{ value: '', label: 'Not set' },
|
||||||
{ value: 'metric', label: 'Metric (°C)' },
|
{ value: 'metric', label: 'Metric (°C)' },
|
||||||
{ value: 'imperial', label: 'Imperial (°F)' },
|
{ value: 'imperial', label: 'Imperial (°F)' },
|
||||||
{ value: 'standard', label: 'Standard (K)' },
|
{ value: 'standard', label: 'Standard (K)' },
|
||||||
@@ -766,7 +767,6 @@ function owSourceLabel(k) {
|
|||||||
|
|
||||||
function fillOwForm() {
|
function fillOwForm() {
|
||||||
for (const k of OW_KEYS) owForm[k] = owField(k).own || ''
|
for (const k of OW_KEYS) owForm[k] = owField(k).own || ''
|
||||||
if (!owForm.units) owForm.units = 'metric'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyOpenWeatherView(body) {
|
function applyOpenWeatherView(body) {
|
||||||
|
|||||||
Reference in New Issue
Block a user