mirror of
https://github.com/azaion/ui.git
synced 2026-06-21 15:31:11 +00:00
510df68bcf
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>
464 lines
29 KiB
Markdown
464 lines
29 KiB
Markdown
# 00 — Codebase Discovery
|
||
|
||
> **Step 0 output for `/document`.** Read by Step 1 (per-module docs) to drive
|
||
> processing order, by Step 2 (component assembly) to seed groupings, and by
|
||
> Step 3 (system synthesis) for the tech-stack table.
|
||
>
|
||
> **Scope** (chosen at the autodev gate, 2026-05-10):
|
||
> - `src/` — Azaion UI (React 19 SPA, the live front-end of the suite).
|
||
> - `mission-planner/` — embedded React 18 + MUI sub-project (port-source for
|
||
> `src/features/flights/`). Documented as a separate component group.
|
||
> - `_docs/` already contained user-curated reference content
|
||
> (`legacy/wpf-era.md`, `ui_design/`, `_autodev_state.md`); the document
|
||
> skill writes alongside, not over.
|
||
>
|
||
> **Out of scope**: `node_modules/`, `dist/`, `bun.lock`, `package-lock.json`,
|
||
> `.git/`, `.cursor/`, `_docs/` (read-only inputs), `.idea/`, `.claude/`,
|
||
> `.superpowers/`, `mission-planner/public/` static assets.
|
||
|
||
---
|
||
|
||
## 1. Workspace at a glance
|
||
|
||
```
|
||
suite/ui/ ← Cursor workspace root
|
||
├── src/ ← Azaion UI (React 19, the live SPA)
|
||
├── mission-planner/ ← embedded port-source (React 18 + MUI)
|
||
├── _docs/ ← user-curated + autodev artifacts
|
||
│ ├── legacy/wpf-era.md read-only reference (WPF predecessor)
|
||
│ ├── ui_design/ read-only reference (HTML wireframes)
|
||
│ ├── _autodev_state.md autodev state pointer
|
||
│ └── 02_document/ ← this folder (autodev outputs)
|
||
├── .cursor/ skills/rules/agents
|
||
├── .woodpecker/build-arm.yml CI: arm64 Docker build → Harbor
|
||
├── Dockerfile multi-stage: bun build → nginx static
|
||
├── nginx.conf /api/* reverse proxy → suite services
|
||
├── index.html SPA shell (mounts /src/main.tsx)
|
||
├── package.json react 19, bun 1.3.11, vite 6, tw 4
|
||
├── tsconfig.json strict ESM, `@/*` → `src/*`
|
||
├── vite.config.ts react + tailwind plugin, /api proxy
|
||
├── README.md repo overview + maturation plan
|
||
└── .gitignore node_modules, .env.*, playwright-report/
|
||
```
|
||
|
||
`src/` and `mission-planner/` are **disjoint** — no file in one imports from
|
||
the other. The Vite alias `@ → src` is defined only in the workspace
|
||
`vite.config.ts`; `mission-planner/vite.config.ts` has no aliases. Each has
|
||
its own `package.json`, `tsconfig`, `index.html`, and entry point. The
|
||
production bundle (`Dockerfile`) builds **only the workspace**, not
|
||
`mission-planner/`.
|
||
|
||
`mission-planner/` ships a (mostly) functional flight-mission UI that the
|
||
`src/features/flights/*` files are mechanically translating into the new
|
||
SPA. Per the workspace `README.md`, `mission-planner/` is **not** part of
|
||
the deployed product.
|
||
|
||
## 2. Tech stack
|
||
|
||
### 2a. Workspace `src/` (Azaion UI)
|
||
|
||
| Concern | Choice | Source |
|
||
|----------------|-------------------------------------|--------------------------|
|
||
| Language | TypeScript 5.7 (`strict: true`) | `tsconfig.json` |
|
||
| UI framework | React 19 (`react-dom/client`) | `package.json` |
|
||
| Bundler | Vite 6 | `package.json`, `vite.config.ts` |
|
||
| Pkg manager | Bun 1.3.11 (declared via `packageManager`) | `package.json` |
|
||
| Styling | Tailwind CSS 4 (`@tailwindcss/vite`) + custom `az-*` tokens in `src/index.css` | `package.json`, `vite.config.ts` |
|
||
| Routing | `react-router-dom` 7 | `src/App.tsx` |
|
||
| i18n | `i18next` + `react-i18next` (UA / EN) | `src/i18n/i18n.ts` |
|
||
| Map | `leaflet` 1.9 + `react-leaflet` 5 + `leaflet-draw` + `leaflet-polylinedecorator` | `package.json`, `src/features/flights/*` |
|
||
| Charts | `chart.js` 4 + `react-chartjs-2` | `package.json` |
|
||
| DnD | `@hello-pangea/dnd` 18 | `package.json` |
|
||
| File upload | `react-dropzone` | `package.json` |
|
||
| Icon set | `react-icons` | `package.json` |
|
||
| HTTP transport | native `fetch` (custom thin wrapper) | `src/api/client.ts` |
|
||
| Realtime | native `EventSource` (SSE) | `src/api/sse.ts` |
|
||
| State mgmt | React Context only — `AuthContext`, `FlightContext`. **No** Redux / Zustand / TanStack Query. | `src/auth/`, `src/components/FlightContext.tsx` |
|
||
| Tests | **none** (no test framework configured) | (verified via Glob) |
|
||
| Build target | static bundle → nginx (multi-stage Dockerfile) | `Dockerfile`, `nginx.conf` |
|
||
| Runtime | nginx in container, ARM64 image | `.woodpecker/build-arm.yml` |
|
||
|
||
### 2b. `mission-planner/` (port-source)
|
||
|
||
| Concern | Choice | Source |
|
||
|----------------|------------------------------------------|------------------------------|
|
||
| Language | TypeScript 5.7 (`strict: true`) | `mission-planner/tsconfig.app.json` |
|
||
| UI framework | React 18 | `mission-planner/package.json` |
|
||
| Bundler | Vite 6 | `mission-planner/vite.config.ts` |
|
||
| Pkg manager | npm (lockfile not committed) | (no `bun.lock` in `mission-planner/`) |
|
||
| UI library | MUI 5 (`@mui/material` + `@mui/icons-material` + `@emotion/*`) | `mission-planner/package.json` |
|
||
| Map | `leaflet` 1.9 + `react-leaflet` 4.2 + `leaflet-draw` + `leaflet-polylinedecorator` | `mission-planner/package.json` |
|
||
| Charts | `chart.js` 4 + `react-chartjs-2` | `mission-planner/package.json` |
|
||
| DnD | `@hello-pangea/dnd` 16 | `mission-planner/package.json` |
|
||
| Flags | `react-world-flags` | `mission-planner/package.json` |
|
||
| Tests | Jest implied (`@testing-library/jest-dom` import in `setupTests.ts`, `describe/it/expect` in `src/test/jsonImport.test.ts`) but **no** Jest dep nor config in `package.json` — test currently cannot run as-is. | `mission-planner/package.json`, `src/setupTests.ts`, `src/test/jsonImport.test.ts` |
|
||
| Env config | `.env.example` declares `VITE_SATELLITE_TILE_URL` | `mission-planner/.env.example` |
|
||
| Build target | not built or shipped by the suite | (Dockerfile copies only workspace `src/`) |
|
||
|
||
## 3. Configuration & infrastructure files
|
||
|
||
| Path | Role |
|
||
|-------------------------------------|----------------------------------------------------------------------|
|
||
| `package.json` (workspace) | scripts: `dev`, `build` (`tsc -b && vite build`), `preview`. No `test`. |
|
||
| `tsconfig.json` | `strict: true`, `noUnusedLocals/Parameters: false` (lax), `paths: {"@/*": ["./src/*"]}`. |
|
||
| `vite.config.ts` | `@vitejs/plugin-react` + `@tailwindcss/vite`. Dev proxy `/api → http://localhost:8080`. |
|
||
| `index.html` | `<div id="root"></div>` + `<script type="module" src="/src/main.tsx">`. Body class hardcodes `bg-[#1e1e1e] text-[#adb5bd]`. |
|
||
| `Dockerfile` | Stage 1: `oven/bun:1.3.11-alpine`, `bun install --frozen-lockfile`, `bun run build`. Stage 2: `nginx:alpine`, copies `dist/` to `/usr/share/nginx/html`, exposes 80. `ENV AZAION_REVISION=$CI_COMMIT_SHA`. |
|
||
| `nginx.conf` | Reverse-proxies 9 `/api/<service>/` paths → `http://<service>:8080/`. Enumerates: annotations, flights, admin, resource, detect, loader, gps-denied-desktop, gps-denied-onboard, autopilot. SPA fallback `/index.html`. `client_max_body_size 500M`. |
|
||
| `.woodpecker/build-arm.yml` | Triggers on push to `dev`/`stage`/`main`. Builds + pushes `${REGISTRY_HOST}/azaion/ui:${branch}-arm` with OCI labels (revision, created, source). |
|
||
| `.gitignore` | `node_modules/`, `.env.local`, `.env.development.local`, `.env.test.local`, `.env.production.local`, `package-lock.json`, `yarn.lock`, `/test-results/`, `/playwright-report/`, `/blob-report/`, `/playwright/.cache/`, `/playwright/.auth/`. (Playwright entries are aspirational — no Playwright installed.) |
|
||
| `.env.example` (workspace) | **absent** — README §"Local development" notes this as a testability fix scheduled for Step 4. API base URL is currently hardcoded via the dev proxy + nginx routing. |
|
||
| `mission-planner/package.json` | scripts: `dev`, `build`, `preview`. **No** `test` script despite the test file. |
|
||
| `mission-planner/tsconfig.app.json` | `exclude: ["src/**/*.test.ts", "src/**/*.test.tsx", "src/setupTests.ts"]`. |
|
||
| `mission-planner/.env.example` | `VITE_SATELLITE_TILE_URL` only. |
|
||
| `mission-planner/public/manifest.json` | PWA manifest (vestigial CRA scaffolding). |
|
||
|
||
## 4. Entry points
|
||
|
||
| Project | File | Mounts |
|
||
|------------------|-------------------------------------------------|---------------------------------------------------------------------|
|
||
| `src/` | `src/main.tsx` | `<StrictMode><BrowserRouter><App /></BrowserRouter></StrictMode>` into `#root`. Imports `./i18n/i18n` for side effects (i18next init) and `./index.css`. |
|
||
| `src/` | `src/App.tsx` | Top-level `Routes`. `/login` is public; everything under `/*` is wrapped in `AuthProvider → ProtectedRoute → FlightProvider → Header + nested Routes` (`/flights`, `/annotations`, `/dataset`, `/admin`, `/settings`, `*` → `/flights`). |
|
||
| `mission-planner/` | `mission-planner/src/main.tsx` | `<StrictMode><LanguageProvider><FlightPlan /></LanguageProvider></StrictMode>` into `#root`. Imports `leaflet/dist/leaflet.css` and `leaflet-draw/dist/leaflet.draw.css`. |
|
||
| `mission-planner/` | `mission-planner/src/App.tsx` | Empty CRA stub — **not used** by `main.tsx`. (Vestigial.) |
|
||
|
||
## 5. Test structure
|
||
|
||
| Project | Test file(s) | Framework | Status |
|
||
|----------------|---------------------------------------------|--------------|-------------------------------------------------------------|
|
||
| `src/` | none | n/a | **Zero test coverage.** Confirmed via Glob over `src/**/*.{test,spec}.*`. |
|
||
| `mission-planner/` | `mission-planner/src/test/jsonImport.test.ts` | Jest (implied — uses `describe/it/expect`) | **Cannot run** — Jest is not in `package.json`; only `@testing-library/jest-dom` is imported in `setupTests.ts`. |
|
||
| `mission-planner/` | `mission-planner/src/setupTests.ts` | - | One-line `import '@testing-library/jest-dom'`. |
|
||
|
||
This vacancy is the explicit input for autodev Steps 3–7 (test-spec, testability revision, decompose tests, implement tests, run tests).
|
||
|
||
## 6. Existing documentation
|
||
|
||
| Path | Status | Owner / used by |
|
||
|---------------------------------------|----------------|----------------------------------------------------------------------------|
|
||
| `README.md` (workspace) | maintained | Single source of truth for repo intent + maturation plan. |
|
||
| `_docs/legacy/wpf-era.md` | reference | Captures WPF predecessor (`Azaion.Annotator`, `Azaion.Dataset`, Cython sidecars) at commit `22529c2`. Authoritative for §10 "What survived into the new world" and §11 "What is intentionally NOT being ported". |
|
||
| `_docs/ui_design/README.md` | reference | Authoritative UX spec: pages, breakpoints, panel layouts, keyboard shortcuts, color tokens, affiliation icons, combat readiness, annotation row gradient, video time-window display, confirmation dialogs. |
|
||
| `_docs/ui_design/{flights,annotations,dataset_explorer,admin,settings}.html` | reference | HTML wireframes for each page (inherited from WPF UI mockups). |
|
||
| `_docs/_autodev_state.md` | maintained | autodev state pointer (this document is being produced under it). |
|
||
| `mission-planner/README.md` | stale | CRA boilerplate; does not describe the actual app. |
|
||
| Suite-level `../_docs/` | external | Suite-wide architecture, schema, deployment topology. Not owned by this workspace; consulted as needed during Step 3. |
|
||
|
||
## 7. Dependency graph
|
||
|
||
`src/` and `mission-planner/` are independent dependency islands. Each is
|
||
acyclic by inspection (verified by following the import chains in §8 and §9
|
||
from leaves outward).
|
||
|
||
### 7a. Workspace `src/` (intra-repo edges only; React/leaflet/etc. omitted)
|
||
|
||
```mermaid
|
||
graph LR
|
||
main[main.tsx] --> App[App.tsx]
|
||
main --> i18n_init[i18n/i18n.ts]
|
||
i18n_init --> en[i18n/en.json]
|
||
i18n_init --> ua[i18n/ua.json]
|
||
|
||
App --> AuthProvider[auth/AuthContext.tsx]
|
||
App --> FlightProvider[components/FlightContext.tsx]
|
||
App --> ProtectedRoute[auth/ProtectedRoute.tsx]
|
||
App --> Header[components/Header.tsx]
|
||
App --> LoginPage[features/login/LoginPage.tsx]
|
||
App --> FlightsPage[features/flights/FlightsPage.tsx]
|
||
App --> AnnotationsPage[features/annotations/AnnotationsPage.tsx]
|
||
App --> DatasetPage[features/dataset/DatasetPage.tsx]
|
||
App --> AdminPage[features/admin/AdminPage.tsx]
|
||
App --> SettingsPage[features/settings/SettingsPage.tsx]
|
||
|
||
AuthProvider --> apiClient[api/client.ts]
|
||
AuthProvider --> typesIdx[types/index.ts]
|
||
ProtectedRoute --> AuthProvider
|
||
FlightProvider --> apiClient
|
||
FlightProvider --> typesIdx
|
||
|
||
Header --> AuthProvider
|
||
Header --> FlightProvider
|
||
Header --> HelpModal[components/HelpModal.tsx]
|
||
Header --> typesIdx
|
||
|
||
sse[api/sse.ts] --> apiClient
|
||
|
||
ConfirmDialog[components/ConfirmDialog.tsx]
|
||
DetectionClasses[components/DetectionClasses.tsx] --> apiClient
|
||
DetectionClasses --> classColors[features/annotations/classColors.ts]
|
||
DetectionClasses --> typesIdx
|
||
|
||
LoginPage --> AuthProvider
|
||
|
||
AdminPage --> apiClient
|
||
AdminPage --> ConfirmDialog
|
||
AdminPage --> typesIdx
|
||
|
||
SettingsPage --> apiClient
|
||
SettingsPage --> typesIdx
|
||
|
||
classColors
|
||
flightsTypes[features/flights/types.ts]
|
||
flightPlanUtils[features/flights/flightPlanUtils.ts] --> flightsTypes
|
||
mapIcons[features/flights/mapIcons.ts]
|
||
|
||
WaypointList[features/flights/WaypointList.tsx] --> flightsTypes
|
||
AltitudeChart[features/flights/AltitudeChart.tsx] --> flightsTypes
|
||
WindEffect[features/flights/WindEffect.tsx] --> flightsTypes
|
||
MiniMap[features/flights/MiniMap.tsx] --> flightsTypes
|
||
MapPoint[features/flights/MapPoint.tsx] --> flightsTypes
|
||
MapPoint --> mapIcons
|
||
DrawControl[features/flights/DrawControl.tsx] --> flightsTypes
|
||
DrawControl --> flightPlanUtils
|
||
AltitudeDialog[features/flights/AltitudeDialog.tsx] --> flightsTypes
|
||
FlightListSidebar[features/flights/FlightListSidebar.tsx] --> typesIdx
|
||
JsonEditorDialog[features/flights/JsonEditorDialog.tsx]
|
||
|
||
FlightParamsPanel[features/flights/FlightParamsPanel.tsx] --> WaypointList
|
||
FlightParamsPanel --> AltitudeChart
|
||
FlightParamsPanel --> WindEffect
|
||
FlightParamsPanel --> flightsTypes
|
||
FlightParamsPanel --> typesIdx
|
||
FlightMap[features/flights/FlightMap.tsx] --> DrawControl
|
||
FlightMap --> MapPoint
|
||
FlightMap --> MiniMap
|
||
FlightMap --> mapIcons
|
||
FlightMap --> flightsTypes
|
||
FlightsPage --> FlightProvider
|
||
FlightsPage --> apiClient
|
||
FlightsPage --> sse
|
||
FlightsPage --> ConfirmDialog
|
||
FlightsPage --> FlightListSidebar
|
||
FlightsPage --> FlightParamsPanel
|
||
FlightsPage --> FlightMap
|
||
FlightsPage --> AltitudeDialog
|
||
FlightsPage --> JsonEditorDialog
|
||
FlightsPage --> flightPlanUtils
|
||
FlightsPage --> flightsTypes
|
||
FlightsPage --> typesIdx
|
||
|
||
CanvasEditor[features/annotations/CanvasEditor.tsx] --> typesIdx
|
||
CanvasEditor --> classColors
|
||
VideoPlayer[features/annotations/VideoPlayer.tsx] --> typesIdx
|
||
AnnotationsSidebar[features/annotations/AnnotationsSidebar.tsx] --> apiClient
|
||
AnnotationsSidebar --> sse
|
||
AnnotationsSidebar --> classColors
|
||
AnnotationsSidebar --> typesIdx
|
||
MediaList[features/annotations/MediaList.tsx] --> FlightProvider
|
||
MediaList --> apiClient
|
||
MediaList --> useDebounce[hooks/useDebounce.ts]
|
||
MediaList --> ConfirmDialog
|
||
MediaList --> typesIdx
|
||
AnnotationsPage --> useResizablePanel[hooks/useResizablePanel.ts]
|
||
AnnotationsPage --> apiClient
|
||
AnnotationsPage --> MediaList
|
||
AnnotationsPage --> VideoPlayer
|
||
AnnotationsPage --> CanvasEditor
|
||
AnnotationsPage --> AnnotationsSidebar
|
||
AnnotationsPage --> DetectionClasses
|
||
AnnotationsPage --> classColors
|
||
AnnotationsPage --> typesIdx
|
||
|
||
DatasetPage --> apiClient
|
||
DatasetPage --> useDebounce
|
||
DatasetPage --> useResizablePanel
|
||
DatasetPage --> FlightProvider
|
||
DatasetPage --> DetectionClasses
|
||
DatasetPage --> ConfirmDialog
|
||
DatasetPage --> CanvasEditor
|
||
DatasetPage --> typesIdx
|
||
```
|
||
|
||
### 7b. `mission-planner/src/`
|
||
|
||
```mermaid
|
||
graph LR
|
||
mp_main[main.tsx] --> flightPlan[flightPlanning/flightPlan.tsx]
|
||
mp_main --> LanguageProvider[flightPlanning/LanguageContext.tsx]
|
||
|
||
mp_types[types/index.ts]
|
||
mp_config[config.ts]
|
||
mp_utils[utils.ts]
|
||
|
||
translations[constants/translations.ts] --> mp_types
|
||
languages[constants/languages.ts] --> mp_types
|
||
purposes[constants/purposes.ts] --> mp_types
|
||
actionModes[constants/actionModes.ts]
|
||
maptypes[constants/maptypes.ts]
|
||
tileUrls[constants/tileUrls.ts]
|
||
|
||
mapIcons[icons/MapIcons.tsx]
|
||
pointIcons[icons/PointIcons.tsx]
|
||
sidebarIcons[icons/SidebarIcons.tsx]
|
||
phoneIcon[icons/PhoneIcon.tsx]
|
||
|
||
calcDistance[services/calculateDistance.ts] --> mp_types
|
||
AircraftService[services/AircraftService.ts] --> mp_types
|
||
WeatherService[services/WeatherService.ts] --> mp_types
|
||
calcBattery[services/calculateBatteryUsage.ts] --> AircraftService
|
||
calcBattery --> WeatherService
|
||
calcBattery --> mp_types
|
||
|
||
Aircraft[flightPlanning/Aircraft.ts] --> mp_utils
|
||
WindEffect2[flightPlanning/WindEffect.tsx] --> LanguageProvider
|
||
WindEffect2 --> translations
|
||
AltitudeChart2[flightPlanning/AltitudeChart.tsx] --> LanguageProvider
|
||
AltitudeChart2 --> translations
|
||
AltitudeChart2 --> mp_types
|
||
AltitudeDialog2[flightPlanning/AltitudeDialog.tsx] --> LanguageProvider
|
||
AltitudeDialog2 --> mp_config
|
||
AltitudeDialog2 --> translations
|
||
AltitudeDialog2 --> purposes
|
||
DrawControl2[flightPlanning/DrawControl.tsx] --> mp_types
|
||
JsonEditorDialog2[flightPlanning/JsonEditorDialog.tsx] --> LanguageProvider
|
||
JsonEditorDialog2 --> translations
|
||
TotalDistance[flightPlanning/TotalDistance.tsx] --> LanguageProvider
|
||
TotalDistance --> calcDistance
|
||
TotalDistance --> translations
|
||
TotalDistance --> mp_types
|
||
LanguageSwitcher[flightPlanning/LanguageSwitcher.tsx] --> LanguageProvider
|
||
LanguageSwitcher --> languages
|
||
LanguageSwitcher --> translations
|
||
MapPoint2[flightPlanning/MapPoint.tsx] --> LanguageProvider
|
||
MapPoint2 --> purposes
|
||
MapPoint2 --> translations
|
||
MapPoint2 --> pointIcons
|
||
MapPoint2 --> mp_types
|
||
MiniMap2[flightPlanning/MiniMap.tsx] --> MapView2
|
||
MiniMap2 --> maptypes
|
||
MiniMap2 --> tileUrls
|
||
MiniMap2 --> mp_types
|
||
PointsList[flightPlanning/PointsList.tsx] --> AltitudeDialog2
|
||
PointsList --> mp_utils
|
||
PointsList --> LanguageProvider
|
||
PointsList --> translations
|
||
PointsList --> calcBattery
|
||
PointsList --> calcDistance
|
||
PointsList --> mp_types
|
||
MapView2[flightPlanning/MapView.tsx] --> DrawControl2
|
||
MapView2 --> mp_utils
|
||
MapView2 --> AltitudeDialog2
|
||
MapView2 --> LanguageProvider
|
||
MapView2 --> pointIcons
|
||
MapView2 --> translations
|
||
MapView2 --> actionModes
|
||
MapView2 --> MiniMap2
|
||
MapView2 --> MapPoint2
|
||
MapView2 --> mapIcons
|
||
MapView2 --> maptypes
|
||
MapView2 --> purposes
|
||
MapView2 --> tileUrls
|
||
MapView2 --> mp_types
|
||
LeftBoard[flightPlanning/LeftBoard.tsx] --> LanguageProvider
|
||
LeftBoard --> PointsList
|
||
LeftBoard --> AltitudeChart2
|
||
LeftBoard --> TotalDistance
|
||
LeftBoard --> LanguageSwitcher
|
||
LeftBoard --> translations
|
||
LeftBoard --> actionModes
|
||
LeftBoard --> sidebarIcons
|
||
LeftBoard --> mp_config
|
||
LeftBoard --> mp_types
|
||
flightPlan --> mp_utils
|
||
flightPlan --> MapView2
|
||
flightPlan --> AltitudeDialog2
|
||
flightPlan --> JsonEditorDialog2
|
||
flightPlan --> LeftBoard
|
||
flightPlan --> mp_config
|
||
flightPlan --> actionModes
|
||
flightPlan --> AircraftService
|
||
flightPlan --> phoneIcon
|
||
flightPlan --> purposes
|
||
flightPlan --> mp_types
|
||
```
|
||
|
||
> **Note** — `MiniMap2` imports `UpdateMapCenter` (a *named* helper) **from**
|
||
> `MapView2`, while `MapView2` imports `MiniMap2` as a child component. They
|
||
> import in opposite directions, which would normally form a dependency
|
||
> cycle, but module-level execution is non-circular because each side only
|
||
> uses the *type/handle* exposed by the other at call time. **Flagged for
|
||
> Step 1** (will document the named export contract precisely) and surfaced
|
||
> in §11 below as a structural caveat.
|
||
|
||
## 8. Cross-feature edges in `src/` (architectural caveats)
|
||
|
||
These are edges where a "lower-layer" module imports from a "higher-layer"
|
||
sibling. Surfaced now so Step 2 (Component Assembly) and Step 2.5
|
||
(module-layout.md) can decide whether to formalise them in the layering
|
||
table or flag them for the architecture baseline scan (Step 2 of autodev).
|
||
|
||
| Edge | Direction | Comment |
|
||
|-------------------------------------------------------------------------------------|---------------------------------|---------|
|
||
| `components/DetectionClasses.tsx` → `features/annotations/classColors.ts` | shared ← feature-specific | A `shared/` component depends on `features/annotations/`. The shared layer should not know about a specific feature. **Likely candidate for refactor**: extract `classColors.ts` into a feature-neutral location (e.g. `src/components/detection/classColors.ts`) or into a `shared/` module. |
|
||
| `features/dataset/DatasetPage.tsx` → `features/annotations/CanvasEditor.tsx` | feature ← sibling feature | Cross-feature import, but consistent with the legacy WPF design where `Azaion.Dataset` reused `CanvasEditor` from `Azaion.Common.Controls` (see `_docs/legacy/wpf-era.md` §5). The proper fix is to lift `CanvasEditor` out of `features/annotations/` into a shared location. |
|
||
| (none observed) | back-edge from `App` to `main` | - |
|
||
|
||
Also: every page calls `api/client.ts` directly with **string-literal URLs**
|
||
(`/api/admin/auth/login`, `/api/flights?...`, `/api/annotations/settings/user`,
|
||
etc.). There is no per-service API client module. This is the testability
|
||
issue the workspace `README.md` calls out for Step 4 — but since it does
|
||
not yet break compilation or layering, it is recorded here, not blocked.
|
||
|
||
## 9. Topological processing order — `src/` (40 modules, 8 batches)
|
||
|
||
Layer = max distance from leaves. Step 1 of `/document` MUST process modules
|
||
in this order (leaves first), batched by ~5 with a session-break heuristic
|
||
between batches.
|
||
|
||
> JSON files (`i18n/en.json`, `i18n/ua.json`) and `vite-env.d.ts` are
|
||
> **inputs**, not modules — they are not separately documented; their content
|
||
> is summarised inside the consumers (`i18n/i18n.ts`, the global TS env).
|
||
> Counted modules: 40.
|
||
|
||
| Batch | Modules | Layer |
|
||
|-------|--------------------------------------------------------------------------------------|-------|
|
||
| **B1** | `types/index.ts`, `hooks/useDebounce.ts`, `hooks/useResizablePanel.ts`, `features/flights/types.ts`, `features/annotations/classColors.ts` | 0 |
|
||
| **B2** | `features/flights/mapIcons.ts`, `features/flights/flightPlanUtils.ts`, `api/client.ts`, `i18n/i18n.ts`, `components/HelpModal.tsx` | 0–1 |
|
||
| **B3** | `components/ConfirmDialog.tsx`, `components/DetectionClasses.tsx`, `auth/AuthContext.tsx`, `components/FlightContext.tsx`, `api/sse.ts` | 1–2 |
|
||
| **B4** | `auth/ProtectedRoute.tsx`, `components/Header.tsx`, `features/login/LoginPage.tsx`, `features/admin/AdminPage.tsx`, `features/settings/SettingsPage.tsx` | 2–3 |
|
||
| **B5** | `features/flights/{WaypointList,AltitudeChart,WindEffect,MiniMap,AltitudeDialog}.tsx` | 1–2 |
|
||
| **B6** | `features/flights/{MapPoint,DrawControl,FlightListSidebar,JsonEditorDialog,FlightParamsPanel}.tsx` | 2 |
|
||
| **B7** | `features/flights/FlightMap.tsx`, `features/annotations/{CanvasEditor,VideoPlayer,AnnotationsSidebar,MediaList}.tsx` | 2–3 |
|
||
| **B8** | `features/flights/FlightsPage.tsx`, `features/annotations/AnnotationsPage.tsx`, `features/dataset/DatasetPage.tsx`, `App.tsx`, `main.tsx` | 3–5 |
|
||
|
||
## 10. Topological processing order — `mission-planner/` (37 modules, 8 batches)
|
||
|
||
Excluded from analysis: `vite-env.d.ts`, `types/leaflet-polylinedecorator.d.ts`,
|
||
`types/react-world-flags.d.ts` (type shims for external libs), `setupTests.ts`,
|
||
`App.tsx` (vestigial CRA stub — flagged for delete in §11), and `index.css`,
|
||
`*.css` files. The Jest test (`src/test/jsonImport.test.ts`) is documented
|
||
inline with `flightPlanning/flightPlan.tsx` (its target), not as a standalone
|
||
module. Counted modules: 37.
|
||
|
||
| Batch | Modules | Layer |
|
||
|-------|-----------------------------------------------------------------------------------------------------------------------------------------------|-------|
|
||
| **MP-B1** | `types/index.ts`, `utils.ts`, `config.ts`, `constants/{actionModes,maptypes,tileUrls}.ts` | 0 |
|
||
| **MP-B2** | `constants/{translations,languages,purposes}.ts`, `services/{calculateDistance,AircraftService,WeatherService}.ts` | 1 |
|
||
| **MP-B3** | `services/calculateBatteryUsage.ts`, `flightPlanning/Aircraft.ts`, `flightPlanning/LanguageContext.tsx`, `icons/{MapIcons,PointIcons}.tsx` | 1–2 |
|
||
| **MP-B4** | `icons/{SidebarIcons,PhoneIcon}.tsx`, `flightPlanning/{WindEffect,DrawControl,LanguageSwitcher}.tsx` | 2 |
|
||
| **MP-B5** | `flightPlanning/{AltitudeChart,AltitudeDialog,JsonEditorDialog,TotalDistance,MapPoint}.tsx` | 2–3 |
|
||
| **MP-B6** | `flightPlanning/MapView.tsx` (cycle group with `MiniMap.tsx`), `flightPlanning/MiniMap.tsx`, `flightPlanning/PointsList.tsx` | 3–4 |
|
||
| **MP-B7** | `flightPlanning/LeftBoard.tsx`, `flightPlanning/flightPlan.tsx` | 5–6 |
|
||
| **MP-B8** | `main.tsx`, `test/jsonImport.test.ts` (analysis only — covered by `flightPlan.tsx` doc) | 7 |
|
||
|
||
## 11. Discovery findings to carry forward
|
||
|
||
The following observations are not documentation gaps; they are **inputs**
|
||
for downstream steps. Each lists the step that owns the follow-up.
|
||
|
||
1. **Workspace `src/` has zero tests.** → Owned by `/test-spec` (Step 3 of autodev) and `/decompose-tests` + `/implement` (Steps 5–6).
|
||
2. **Hardcoded API URL paths** (`/api/admin/...`, `/api/flights/...`, `/api/annotations/...`) inlined throughout features. → Testability fix scheduled by autodev Step 4 (workspace `README.md` §"Local development" already calls this out).
|
||
3. **No `.env.example` in workspace.** → Same — Step 4.
|
||
4. **Cross-layer imports** (§8): `components/DetectionClasses.tsx` → `features/annotations/classColors.ts`, `features/dataset/DatasetPage.tsx` → `features/annotations/CanvasEditor.tsx`. → Surface to autodev Step 2 (Architecture Baseline Scan); the testability refactor (Step 4) may also lift these.
|
||
5. **`mission-planner/src/test/jsonImport.test.ts` cannot run** — Jest is not installed and there is no test script. → Out of scope for the live SPA test plan; document in `mission-planner/` component spec but do **not** add Jest just to run this one legacy test.
|
||
6. **`mission-planner/src/App.tsx`** is an unused CRA stub; `main.tsx` mounts `FlightPlan` directly. → Note in `mission-planner/` component spec; deletion candidate but only after the `mission-planner` → `src/features/flights/` port is complete (out of `/document` scope).
|
||
7. **`mission-planner/src/flightPlanning/MapView.tsx ↔ MiniMap.tsx`** import each other (`MiniMap` imports the *named* `UpdateMapCenter` helper from `MapView`; `MapView` imports `MiniMap` as a JSX child). → Document the contract precisely in Step 1; analyse together as a 2-module group in MP-B6 per the Step 1 cycle-handling rule.
|
||
8. **`react-i18next` is used only in workspace `src/`**; `mission-planner/` uses its own `LanguageContext` + raw translation tables. → Capture the divergence in Step 5 (Solution Extraction) — the port to `src/features/flights/` should consume `react-i18next` instead.
|
||
9. **No CI test step** in `.woodpecker/build-arm.yml` — only build + push. → To be added by autodev Step 7 (Run Tests) once the test suite exists.
|
||
10. **The body of `index.html`** hardcodes Tailwind arbitrary-value classes for the global background and text color rather than using the `az-bg` / `az-text` tokens defined in `src/index.css`. → Cosmetic; record in the workspace component spec but no action required.
|
||
|
||
---
|
||
|
||
**Step 0 status**: complete. Proceeding to Step 1 (per-module documentation,
|
||
batch B1).
|