Add adjustable probe area for OpenSky test connection

Let the OpenSky health probe run over a chosen bounding box without
touching the saved default, so its credit cost (which scales with area)
can be checked cheaply.

- Backend: the plugin health endpoint (panel Check) and the OpenSky
  health endpoint (Web App Test connection) accept an optional ?bbox=,
  validated with validBBox and applied to a transient probe instance;
  both BFF and API forward it. Saved config is untouched.
- API panel: a "Probe area" picker beside each bbox-capable plugin's
  Check button — saved default, all countries (grouped by continent),
  or Custom. Adds a compact pv-input-sm style.
- Web App: a "Test area" picker beside Test connection, using the full
  country list (new countryGroups() helper) plus Custom. This is where
  the probe is authenticated and the credit cost is shown.

Builds pass across both Go modules and both frontends. Panel picker
verified live (186 options, defaults to saved default).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
tajniak81andClaude Opus 4.8 committed 2026-07-14 10:25:59 +02:00
1 parent 763cc67081
commit 15bff7f517
17 files changed
+233 -53

No files matched your search

+48 -2
View File
@@ -6,7 +6,7 @@ import Segmented from './settings/Segmented.vue'
import Row from './settings/Row.vue'
import { themeMode, setThemeMode } from '../theme.js'
import { prefs, formatDateTime, importPrefs, applyFontSize, applyReduceMotion } from '../prefs.js'
import { europeanCountries, regionOptions } from '../countries.js'
import { europeanCountries, regionOptions, countryGroups } from '../countries.js'
import {
getUsers, createUser, updateUser, deleteUser,
getOrgs, createOrg, updateOrg, deleteOrg,
@@ -371,10 +371,45 @@ async function saveOpenSkySettings() {
flash(osEditingOrg.value ? 'Organization OpenSky settings saved.' : 'OpenSky settings saved.')
}
// Test-connection "probe area": an optional bounding box used only for the
// Test connection probe (to check an area's credit cost) without touching the
// saved default. Full country list (World / Continents / all countries) + Custom.
const OS_PROBE_GROUPS = [
{ label: 'World', options: [{ value: '-90,-180,90,180', label: 'World' }] },
{ label: 'Continents', options: [
{ value: '34,-25,72,45', label: 'Europe' },
{ value: '-35,-18,38,52', label: 'Africa' },
{ value: '5,25,82,180', label: 'Asia' },
{ value: '7,-168,72,-52', label: 'North America' },
{ value: '-56,-82,13,-34', label: 'South America' },
{ value: '-48,110,-10,180', label: 'Oceania' },
] },
...countryGroups(),
]
const OS_PROBE_FLAT = OS_PROBE_GROUPS.flatMap((g) => g.options)
const osProbeBbox = ref('') // '' = use the saved default bounding box
const osProbeCustom = ref(false)
const osProbeSelect = computed({
get() {
if (osProbeCustom.value) return '__custom__'
if (!osProbeBbox.value) return '__default__'
const norm = osNormBbox(osProbeBbox.value)
const m = norm && OS_PROBE_FLAT.find((o) => osNormBbox(o.value) === norm)
return m ? m.value : '__custom__'
},
set(v) {
if (v === '__default__') { osProbeCustom.value = false; osProbeBbox.value = ''; return }
if (v === '__custom__') { osProbeCustom.value = true; return }
osProbeCustom.value = false
osProbeBbox.value = v
},
})
const osProbeManual = computed(() => osProbeSelect.value === '__custom__')
async function testOpenSkyConnection() {
osTesting.value = true
osHealth.value = null
const { ok, body } = await testOpenSky()
const { ok, body } = await testOpenSky((osProbeBbox.value || '').trim() || undefined)
osTesting.value = false
osHealth.value = ok && body.health ? body.health : { status: 'down', detail: body.error || 'Probe failed.' }
osHealthTs.value = Date.now()
@@ -1562,6 +1597,17 @@ onBeforeUnmount(() => {
<button v-if="!osReadOnly" class="btn-accent" :disabled="osSaving || !os.available" @click="saveOpenSkySettings">
{{ osSaving ? 'Saving…' : osEditingOrg ? 'Save organization settings' : 'Save settings' }}
</button>
<div v-if="!osEditingOrg" class="flex items-center gap-2" title="Bounding box used for Test connection — smaller areas cost fewer OpenSky credits">
<label class="text-xs text-ink-muted">Test area</label>
<select v-model="osProbeSelect" class="field w-44">
<option value="__default__">Default bounding box</option>
<optgroup v-for="g in OS_PROBE_GROUPS" :key="g.label" :label="g.label">
<option v-for="o in g.options" :key="o.value" :value="o.value">{{ o.label }}</option>
</optgroup>
<option value="__custom__">Custom…</option>
</select>
<input v-if="osProbeManual" v-model="osProbeBbox" class="field w-44 font-mono" placeholder="lamin,lomin,lamax,lomax" />
</div>
<button v-if="!osEditingOrg" class="btn-ghost" :disabled="osTesting || !os.available" @click="testOpenSkyConnection">
{{ osTesting ? 'Testing…' : 'Test connection' }}
</button>