Show current weather on the Overview

Add a weather card to the Web App Overview, wired like the OpenSky live-map
overlay and backed by the OpenWeather plugin.

- API Server: GET /api/integrations/openweather/current resolves the
  caller's cascade, gates it (master/org/personal opt-in/key), and returns
  trimmed current conditions for the configured or a supplied ?lat=&lon=
  point; off/keyless returns {unavailable, detail} so the card degrades.
- BFF relay (forwards the location override) + route; api.js client.
- Dashboard: a Weather card stacked above Schedule showing an emoji
  condition, temperature in the resolved unit, description, location, and a
  feels-like/wind/humidity/cloud grid. Location follows the same cascade as
  the map (drone -> phone -> browser -> default) without prompting for geo;
  refreshes every 10 min while on Overview.
- validLatLon test; rebuilt embedded frontend.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
tajniak81
2026-07-14 16:34:01 +02:00
co-authored by Claude Opus 4.8
parent 522fe450eb
commit 5960fb4806
11 changed files with 348 additions and 25 deletions
+12
View File
@@ -344,6 +344,18 @@ func (a *App) handleOpenWeatherHealth(w http.ResponseWriter, r *http.Request) {
a.doRelay(w, req)
}
// GET /bff/integrations/openweather/current → API Server current conditions for the
// Overview weather card. Forwards the optional ?lat=&lon= location override.
func (a *App) handleOpenWeatherCurrent(w http.ResponseWriter, r *http.Request) {
target := a.apiBaseFor(r) + "/api/integrations/openweather/current"
if r.URL.RawQuery != "" {
target += "?" + r.URL.RawQuery
}
req, _ := http.NewRequest(http.MethodGet, target, nil)
req.Header.Set("Authorization", tokenOf(r))
a.doRelay(w, req)
}
// GET /bff/users → API Server /api/users (admin only, enforced upstream)
func (a *App) handleListUsers(w http.ResponseWriter, r *http.Request) {
req, _ := http.NewRequest(http.MethodGet, a.apiBaseFor(r)+"/api/users", nil)
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -35,8 +35,8 @@
})()
</script>
<title>PilotVault — Control Panel</title>
<script type="module" crossorigin src="./assets/index-B-DwId4e.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-Dr5W1RO_.css">
<script type="module" crossorigin src="./assets/index-DWe3LEIB.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-buxVzOVb.css">
</head>
<body>
<div id="app"></div>
+1
View File
@@ -66,6 +66,7 @@ func main() {
mux.HandleFunc("GET /bff/integrations/openweather", app.requireAuth(app.handleGetOpenWeather))
mux.HandleFunc("PUT /bff/integrations/openweather", app.requireAuth(app.handlePutOpenWeather))
mux.HandleFunc("POST /bff/integrations/openweather/health", app.requireAuth(app.handleOpenWeatherHealth))
mux.HandleFunc("GET /bff/integrations/openweather/current", app.requireAuth(app.handleOpenWeatherCurrent))
// User-management (role + org scoping enforced by the API Server)
mux.HandleFunc("GET /bff/users", app.requireAuth(app.handleListUsers))
mux.HandleFunc("POST /bff/users", app.requireAuth(app.handleCreateUser))