mirror of
https://github.com/azaion/ui.git
synced 2026-06-21 18:41:11 +00:00
[AZ-447] autodev Steps 1-4 baseline: docs, tests, refactor specs
Captures the full output of autodev existing-code Phase A through Step 4 (Code Testability Revision) for the Azaion UI workspace: - Step 1 Document: _docs/02_document/ (FINAL_report, architecture, glossary, components/, modules/, diagrams/, system-flows, module-layout) plus _docs/00_problem/ + _docs/01_solution/ + _docs/legacy/ + _docs/how_to_test + README. - Step 2 Architecture Baseline: architecture_compliance_baseline.md. - Step 3 Test Spec: _docs/02_document/tests/ (environment, test-data, blackbox/performance/resilience/security/ resource-limit tests, traceability-matrix), enum_spec_snapshot, expected_results/results_report.md (98 rows), plus the run-tests.sh + run-performance-tests.sh runners. - Step 4 Code Testability Revision: 01-testability-refactoring/ run dir (list-of-changes C01-C07, deferred_to_refactor, analysis/research_findings + refactoring_roadmap) and the 7 child task specs AZ-448..AZ-454 under _docs/02_tasks/todo/ plus _dependencies_table.md. - _docs/_autodev_state.md pins the cursor at Step 4 / refactor Phase 4 entry so /autodev resumes cleanly. Epic AZ-447 (UI testability gates) tracks the 7 child tasks that will land in subsequent commits. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
# 05 — Flights & Mission Planning
|
||||
|
||||
## 1. High-Level Overview
|
||||
|
||||
**Purpose**: One logical component covering everything mission/flight related — flight CRUD, waypoint editing, altitude profile, wind/battery calc, raw mission JSON I/O, and **GPS-Denied** operations (incl. an end-to-end **test mode** that simulates a real flight from a tlog + video pair). It is currently **physically split** across two codebases that the project intends to converge.
|
||||
|
||||
**Architectural Pattern**: Page composition (`FlightsPage`) wiring three sibling panels — `FlightListSidebar`, `FlightParamsPanel`, `FlightMap` — plus modals (`AltitudeDialog`, `JsonEditorDialog`) and a GPS-Denied sub-page.
|
||||
|
||||
**Implementation status — two trees, one component**:
|
||||
|
||||
| Tree | What it is | Deployed? |
|
||||
|------|------------|-----------|
|
||||
| `src/features/flights/` (15 modules, React 19 + Tailwind) | The **target** implementation. Mostly a mechanical port-in-progress of the tree below. | **Yes** — Dockerfile builds `src/` only. |
|
||||
| `mission-planner/` (37 modules, React 18 + MUI 5) | The **port source / reference**. The richer, more battle-tested mission planner that the new SPA is being adapted from. | **No.** Disjoint dependency island. Deletion candidate after parity. |
|
||||
|
||||
The two trees are intentionally disjoint at the file level (no cross-imports — `00_discovery.md` §1) but they are **one component in the design**: same domain, same data model, same intent. Findings, port plan, and architecture decisions are tracked in this single component spec. Mission-planner files are listed in §"Module Inventory" below alongside the new SPA files; per-finding origin is preserved.
|
||||
|
||||
**Upstream dependencies** (target tree): `00_foundation`, `01_api-transport`, `03_shared-ui` (FlightContext, ConfirmDialog).
|
||||
|
||||
**Downstream consumers**: `10_app-shell` (routes `/flights` and the GPS-Denied sub-page).
|
||||
|
||||
## 2. Internal Interfaces
|
||||
|
||||
### Page entries (target tree, `src/features/flights/`)
|
||||
|
||||
| Export | Notes |
|
||||
|--------|-------|
|
||||
| `FlightsPage()` | Top-level route component for `/flights`. Uses `useFlight()`, fetches flight detail by id, exposes save/delete/duplicate. Wires `react-leaflet`, `leaflet-draw`, and `chart.js`. |
|
||||
| `GpsDeniedPage()` *(planned route, see §6)* | Sub-page for GPS-denied operations and test mode. Today a partial inline panel inside `FlightsPage` (finding #25) — slated to become its own route. |
|
||||
|
||||
### Internal modules — target tree (`src/features/flights/`)
|
||||
|
||||
| Module | Role |
|
||||
|--------|------|
|
||||
| `FlightsPage.tsx` | Orchestrator (route component) |
|
||||
| `FlightMap.tsx` | Leaflet map + draw control + waypoint markers + minimap |
|
||||
| `FlightListSidebar.tsx` | Left panel: flight list, search, new/duplicate/delete |
|
||||
| `FlightParamsPanel.tsx` | Right panel: name, aircraft, takeoff/landing, altitude chart, waypoint list, wind effect |
|
||||
| `WaypointList.tsx` | DnD-sortable waypoints (`@hello-pangea/dnd`) |
|
||||
| `AltitudeChart.tsx` | `chart.js` altitude profile |
|
||||
| `WindEffect.tsx` | Wind-vector visualisation |
|
||||
| `MiniMap.tsx` | Inline overview map |
|
||||
| `MapPoint.tsx` | Single waypoint marker |
|
||||
| `DrawControl.tsx` | `leaflet-draw` integration |
|
||||
| `AltitudeDialog.tsx` | Per-waypoint altitude/purpose modal |
|
||||
| `JsonEditorDialog.tsx` | Raw mission-JSON editor |
|
||||
| `flightPlanUtils.ts` | Distance / battery / weather computation helpers |
|
||||
| `mapIcons.ts` | Leaflet icon factory |
|
||||
| `types.ts` | Local feature types (waypoint shape, mission JSON shape) |
|
||||
|
||||
### Internal modules — port source (`mission-planner/`)
|
||||
|
||||
| Group | Modules | Role / what the target should learn |
|
||||
|-------|---------|-------------------------------------|
|
||||
| Entry | `main.tsx`, `App.tsx` (vestigial CRA stub) | Composition root + LanguageProvider. The CRA stub `App.tsx` is a deletion candidate post-port. |
|
||||
| Page composition | `flightPlanning/flightPlan.tsx`, `LeftBoard.tsx` | Canonical page shape (sidebar + map). |
|
||||
| Map | `flightPlanning/MapView.tsx` (cycle-paired with `MiniMap.tsx`), `MiniMap.tsx`, `DrawControl.tsx`, `MapPoint.tsx` | Reference Leaflet integration. **Cycle**: `MiniMap` imports the *named* helper `UpdateMapCenter` from `MapView`; `MapView` imports `MiniMap` as JSX child. Document the contract precisely if porting both at once. |
|
||||
| Panels | `flightPlanning/PointsList.tsx`, `AltitudeChart.tsx`, `AltitudeDialog.tsx`, `WindEffect.tsx`, `TotalDistance.tsx`, `JsonEditorDialog.tsx`, `LanguageSwitcher.tsx`, `Aircraft.ts` | Reference panel shapes. Several have richer behaviour than the current SPA siblings. |
|
||||
| Services | `services/calculateBatteryUsage.ts`, `AircraftService.ts`, `WeatherService.ts`, `calculateDistance.ts` | **Authoritative** battery / weather / distance logic. The target's `flightPlanUtils.ts` is currently an inferior port (silent errors, sequential `await`, hardcoded API key). |
|
||||
| i18n | `flightPlanning/LanguageContext.tsx`, `constants/translations.ts`, `constants/languages.ts` | Local translation pattern. The port should converge to `00_foundation/i18n` instead. |
|
||||
| Constants | `constants/{actionModes,maptypes,tileUrls,purposes}.ts` | Reference constant tables. |
|
||||
| Icons | `icons/{MapIcons,PointIcons,SidebarIcons,PhoneIcon}.tsx` | Reference icon factory. |
|
||||
| Utilities | `utils.ts`, `config.ts`, `types/index.ts` | Reference helpers + types. |
|
||||
| Test (vestigial) | `test/jsonImport.test.ts`, `setupTests.ts` | One Jest test that **cannot run today** (Jest not in `package.json`). Out of scope for the live SPA test plan. |
|
||||
|
||||
## 3. External API Specification
|
||||
|
||||
Endpoints consumed (target tree + planned for GPS-Denied):
|
||||
|
||||
| Method | Path | Purpose |
|
||||
|--------|------|---------|
|
||||
| GET | `/api/flights` | List + page (`pageSize=1000` ceiling from `FlightContext`) |
|
||||
| GET | `/api/flights/{id}` | Detail + waypoints |
|
||||
| POST | `/api/flights` | Create |
|
||||
| PUT | `/api/flights/{id}` | Update flight metadata |
|
||||
| DELETE | `/api/flights/{id}` | Delete |
|
||||
| POST/DELETE | `/api/flights/{id}/waypoints` | Add / remove waypoints |
|
||||
| POST | `/api/gps-denied-desktop/...` | GPS-denied desktop service (mission setup, plan upload) — partial today |
|
||||
| POST | `/api/gps-denied-onboard/...` | GPS-denied onboard service (frame + IMU consumer) — target of test-mode SITL output |
|
||||
| GET | OpenWeatherMap (third-party, **direct from browser**) | Wind/temperature lookup. **Will be proxied via suite** as part of Step 4 (hardcoded key removal). |
|
||||
|
||||
Concrete GPS-Denied endpoint shapes are **not yet finalised** in the suite spec — flagged for confirmation in autodev Step 3 (Test Spec) and Step 6 (Problem Extraction).
|
||||
|
||||
## 5. Implementation Details
|
||||
|
||||
**State Management**: Page-local React state for the active flight; `FlightContext` (in `03_shared-ui`) for the list of flights.
|
||||
|
||||
**Save model — current shape, target tree** (finding #19): on Save, the UI deletes all existing waypoints and POSTs each one again. N delete + M POST round-trips. **Lossy** — concurrent edits race; if a POST fails halfway through, the saved flight is left with truncated waypoints. The `mission-planner/` reference does this differently (single mission-JSON PUT) and is the recommended target shape.
|
||||
|
||||
**Waypoint POST shape mismatch (PRIORITY, finding #20)**: target tree sends `{name, latitude, longitude, order}`; suite spec wants `{Geopoint:{Lat,Lon,MGRS}, Source, Objective, OrderNum, Height}`. Strict server returns 400. Owner of fix: this component + `00_foundation/types/index.ts::Waypoint`.
|
||||
|
||||
**Battery / weather calc** (target tree `flightPlanUtils.ts`):
|
||||
- **Hardcoded OpenWeather API key in source** (`'335799082893fad97fa36118b131f919'`) — committed secret. Step 4 fix.
|
||||
- Sequential `await` per segment — perf trap on long missions.
|
||||
- Silent `try/catch` swallows weather errors.
|
||||
- Mixes km / m altitudes; ambiguous battery-capacity unit (Wh vs Ws).
|
||||
- Port source (`mission-planner/services/`) has a cleaner, more correct implementation — use it as the reference.
|
||||
|
||||
**Map / icons**:
|
||||
- Target tree `mapIcons.ts::defaultIcon` CDN URL pinned to `leaflet@1.7.1` while `package.json` has 1.9.4.
|
||||
- `MiniMap` map-tile licence attribution missing in some configurations.
|
||||
|
||||
**Modal a11y** (`AltitudeDialog`, `JsonEditorDialog`) — no `aria-modal` / `role="dialog"` / focus trap. Step 4. Same gap on the port-source counterparts.
|
||||
|
||||
**Tech-stack divergence between the two trees** (carry into the port plan):
|
||||
|
||||
| Concern | `mission-planner/` | `src/features/flights/` (target) |
|
||||
|---------|-------------------|----------------------------------|
|
||||
| React | 18 | 19 |
|
||||
| UI library | MUI 5 | Tailwind 4 + custom `az-*` tokens |
|
||||
| i18n | local `LanguageContext` | `react-i18next` (Foundation) |
|
||||
| `react-leaflet` | 4.2 | 5 |
|
||||
| `@hello-pangea/dnd` | 16 | 18 |
|
||||
|
||||
**Key Dependencies** (target tree): `leaflet` 1.9, `react-leaflet` 5, `leaflet-draw`, `leaflet-polylinedecorator`, `chart.js` 4, `@hello-pangea/dnd` 18.
|
||||
|
||||
## 6. GPS-Denied sub-feature
|
||||
|
||||
Today a **partial** UI panel exists inside `FlightsPage` (target tree finding #25). The component design promotes this to a first-class sub-page with two tabs.
|
||||
|
||||
### 6a. Operations tab — current intent (already present, partial)
|
||||
|
||||
- Upload / select a mission plan.
|
||||
- Configure GPS-denied desktop parameters.
|
||||
- Hand off to onboard.
|
||||
|
||||
The exact endpoints are partially wired today and tracked under "External API Specification" above.
|
||||
|
||||
### 6b. **Test mode** — new subitem (per `_docs/how_to_test.md`)
|
||||
|
||||
> **Source of truth**: `_docs/how_to_test.md`. Architecture Vision artifact (`/document` Step 4.5) MUST surface this verbatim.
|
||||
|
||||
**Goal**: enable end-to-end testing of the GPS-denied onboard system **without a real flight**, using a recorded telemetry log + video pair.
|
||||
|
||||
**User journey**:
|
||||
|
||||
1. **Upload tlog file** (MAVLink telemetry log).
|
||||
2. **Upload video** synced with the tlog (the two are **usually not** time-aligned at the file level — the system aligns them).
|
||||
3. The system:
|
||||
- Extracts **timestamps, IMU, and GPS** samples from the tlog.
|
||||
- **Auto-syncs** video to tlog by detecting the take-off moment in the IMU stream and matching it to the corresponding frame in the video. Most test sessions are quadcopter "ground-to-ground" flights; the start-on-ground signature in the IMU is the alignment anchor.
|
||||
- Spawns a **SITL** (Software-In-The-Loop) instance.
|
||||
- **Feeds IMU samples + video frames** into the GPS-denied **onboard** system in lockstep.
|
||||
4. The user observes the onboard system's outputs (position estimate, drift, GPS-recovery moments) on the same map / chart components used for live flights — reusing `FlightMap`, `AltitudeChart`, and a results overlay.
|
||||
|
||||
**Scope notes for downstream skills**:
|
||||
|
||||
- This sub-feature is **not implemented today**. It is a planned addition that this component will own.
|
||||
- The tlog parser, IMU/video sync, and SITL controller are **suite-side services**; this component contributes the upload UI, the run controller, and the result overlay.
|
||||
- Test-mode I/O endpoints will live under `/api/gps-denied-desktop/test/...` (proposed; confirm in `autodev` Step 3 / Step 6).
|
||||
- The existing `/document` Step 1 finding "GPS-Denied panel partial" remains valid for the Operations tab and is broadened to track the Test mode tab as well.
|
||||
|
||||
## 7. Caveats & Edge Cases
|
||||
|
||||
26 numbered findings consolidated in `src__features__flights.md`. Highest-priority Step 4 items:
|
||||
|
||||
1. **Hardcoded OpenWeather API key** — rotate + remove + proxy via suite.
|
||||
2. **Waypoint POST shape mismatch + delete-then-recreate save model** — likely-broken on a strict suite server. Reference port-source's PUT-mission-JSON model.
|
||||
3. **`flightPlanUtils.ts` units / silent errors / sequential awaits.** Replace with port-source services.
|
||||
4. **Modal a11y** + **flight dropdown a11y** (overlap with Shared UI).
|
||||
5. **Leaflet 1.7.1 CDN URL drift.**
|
||||
|
||||
Mission-planner-side caveats (port-only):
|
||||
|
||||
- `mission-planner/src/test/jsonImport.test.ts` cannot run (Jest absent). **Do not** add Jest just for this one test.
|
||||
- `mission-planner/src/App.tsx` is a CRA stub. Delete only after parity.
|
||||
- `MapView.tsx ↔ MiniMap.tsx` named-handle cycle. Document precisely.
|
||||
|
||||
GPS-Denied-side caveats:
|
||||
|
||||
- Operations tab is partial (finding #25 unchanged).
|
||||
- **Test mode** is unimplemented — no risk of regression today, but the design must accommodate the eventual test-mode entry point in routing and in `FlightContext`.
|
||||
|
||||
## 8. Dependency Graph
|
||||
|
||||
**Must be implemented after**: `00_foundation`, `01_api-transport`, `03_shared-ui`.
|
||||
|
||||
**Can be implemented in parallel with**: every other feature page.
|
||||
|
||||
**Blocks**: `10_app-shell` (routes to `/flights` as default authenticated landing; will also host the GPS-Denied sub-route).
|
||||
|
||||
**Internal port order** (within this component): port `services/` (battery/weather/distance) → port `flightPlanning/` panels (`AltitudeChart`, `WindEffect`, `PointsList`) → port `MapView/MiniMap` cycle group → fold the `mission-planner/` tree out as the target reaches parity.
|
||||
|
||||
## Module Inventory
|
||||
|
||||
| Tree | Module Doc |
|
||||
|------|------------|
|
||||
| `src/features/flights/*` (15 modules) | `_docs/02_document/modules/src__features__flights.md` |
|
||||
| `mission-planner/*` (37 modules) | `_docs/02_document/modules/mission-planner.md` |
|
||||
Reference in New Issue
Block a user