The OpenSky "Default bounding box" now follows where flying happens.
A new "Automatic" picker mode (the default) resolves the live-map area
from a location cascade — drone telemetry → phone GPS → browser
geolocation → the user's Region country → Europe — instead of a fixed
box. Manual presets and Custom coordinates still work.
- Web App: new shared countries.js dataset (all countries + bbox,
offline point→country); the bbox picker gains all European countries
and an Automatic option (client pref prefs.autoBbox); the Region
setting expands from 6 locale entries to all countries; the live map
resolves the cascade each poll and sends it as ?bbox=.
- API Server: the states endpoint accepts and validates a ?bbox=
override (validBBox); the Web App BFF forwards the query; the hub
relays new phoneLatitude/phoneLongitude telemetry to the Web App.
- Fly App: reports the phone's own GPS (geolocator) alongside
telemetry, used as the "your location" fallback.
- API panel: the OpenSky bbox picker lists all European countries.
Builds verified across web, panel, both Go modules and the Fly App
APK. Region list, Automatic default and the cascade ?bbox= override
verified in the browser.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Give the superadmin Plugins panel the same OpenSky "Default bounding
box" experience as the Web App: a grouped preset dropdown (World /
Continents / Countries) plus a Custom option for manual
lamin,lomin,lamax,lomax entry.
Introduce a "bbox" config-field type (rendering hint only; unknown
types still degrade to a text input) and mark the OpenSky bbox field
with it. Values that match a preset render as the region name.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
startPluginEdit pre-filled any empty field with its descriptor default,
treating an explicitly cleared field (stored "") the same as one never set
(undefined). So a saved-blank OpenSky bounding box reappeared as the
default 50.5,3.2,53.7,7.3 on reopen (and would be re-persisted on save).
Only inject a default when the field has never been stored (undefined), so
intentional blanks stay blank.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reorder the Status card meta() detail so HTTP status and URL come
first and the latency (ms) reads last, e.g. "HTTP 200 · <url> · 12ms".
Rebuild the embedded panel assets.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The superadmin panel had backend CRUD for users/orgs (internal/api/users.go,
orgs.go) but no UI. Add two tabs to panel/src/App.vue:
- Users: create form (email/password/role/org), list with role + org badges,
inline editor (email/role/org/verified/password reset), and delete. Self-role
change and self-delete are suppressed to mirror the server-side guards.
- Organizations: create, inline rename, and delete, with client-derived member
counts; delete is disabled while an org still has members.
PocketBase validation errors are unwrapped into a readable line via a shared
apiError() helper. Rebuilds the embedded panel bundle (dist).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add API Server (Go/PocketBase), Web App (Go BFF + Vue), Fly App
(Flutter/DJI MSDK), Adobe Plugin, and Docker/Docker AIO deployment
configs. Design assets and build artifacts are gitignored.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>