mirror of
https://github.com/azaion/ui.git
synced 2026-06-21 22:21: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>
228 lines
11 KiB
Markdown
228 lines
11 KiB
Markdown
# azaion-ui
|
|
|
|
React SPA that serves as the **single front-end for the entire Azaion suite**.
|
|
It does not own data or business logic; it is the operator's window onto
|
|
every backend service that lives as a sibling submodule in the
|
|
[`azaion/suite`](../README.md) monorepo.
|
|
|
|
```
|
|
suite/
|
|
├── annotations/ .NET 10 — Annotations / Media / Datasets / Settings
|
|
├── flights/ .NET 10 — Flights, waypoints, aircrafts, GPS SSE
|
|
├── detections/ Cython — YOLO inference (ONNX / TensorRT)
|
|
├── detections-semantic/ Cython — Semantic detection
|
|
├── loader/ Cython — Encrypted resource loader
|
|
├── gps-denied-onboard/ Python — GPS-denied positioning (UAV side)
|
|
├── gps-denied-desktop/ Python — GPS-denied positioning (operator side)
|
|
├── autopilot/ Python — UAV control via MAVLink
|
|
├── admin/ .NET 10 — Users, roles, detection classes, model versions
|
|
├── ai-training/ Python — YOLO training, ONNX export
|
|
├── satellite-provider/ .NET 10 — Google Maps tile cache
|
|
└── ui/ React 19 — ◄ this repository
|
|
```
|
|
|
|
For the suite-wide architecture, deployment topology, database design, and
|
|
the legacy WPF predecessor see:
|
|
|
|
- [`suite/_docs/`](../_docs/) — system-level architecture and per-service
|
|
feature docs (canonical source of truth).
|
|
- [`_docs/legacy/wpf-era.md`](_docs/legacy/wpf-era.md) — what the
|
|
pre-rewrite Windows desktop application looked like, why the React port
|
|
exists, and which behaviours are intentionally being preserved.
|
|
- [`_docs/ui_design/`](_docs/ui_design/) — page-level wireframes
|
|
(HTML mockups + a design README) inherited from the WPF UI; the
|
|
authoritative reference for layout, keyboard shortcuts, color scheme,
|
|
affiliation icons, annotation row gradient, etc.
|
|
|
|
> **Status.** The code currently in `src/` is a **rudimentary first cut**
|
|
> mechanically translated from the legacy WPF / XAML UI. It is not yet
|
|
> fully wired to the new suite APIs and has no test coverage. Formal
|
|
> bottom-up documentation, a test specification, a testability pass, and
|
|
> the initial test suite are being produced via the
|
|
> [`/autodev` existing-code flow](.cursor/skills/autodev/SKILL.md). When
|
|
> the documentation + safety net are in place, feature work resumes
|
|
> through the same flow.
|
|
|
|
---
|
|
|
|
## What this repo is — and is not
|
|
|
|
| | this repo (`ui/`) | the suite services |
|
|
|--|---|---|
|
|
| **Owns** | rendering, routing, client-side state, i18n, drag-and-drop, the Leaflet map, `<video>` playback, optimistic UI, keyboard shortcuts, layout persistence | data, persistence, queues, inference, model delivery, telemetry, RBAC, tile caching, autopilot |
|
|
| **Talks to** | every backend submodule via REST + SSE (HTTP) | each other via REST / SSE / RabbitMQ; no shared source code |
|
|
| **Builds to** | a static bundle served by nginx (`Dockerfile`) | individual service Docker images |
|
|
| **Runs on** | operator station (laptop / tablet / mini-PC); browser of choice | edge device or remote server, per service tier (see [`suite/_docs/00_top_level_architecture.md`](../_docs/00_top_level_architecture.md)) |
|
|
| **Reaches the network** | only through the operator's browser, with the user's JWT | service-to-service inside the docker network and to `admin/` over the internet |
|
|
|
|
The React app must remain stateless beyond what `localStorage` /
|
|
`UserSettings` (Annotations API) can hold. **No business rules in the UI.**
|
|
|
|
## Pages → backend submodules
|
|
|
|
| Page | Route | Primary submodule(s) consumed |
|
|
|------|-------|-------------------------------|
|
|
| Login | `/login` | `admin/` (auth + user) |
|
|
| Flights | `/flights` | `flights/`, `gps-denied-desktop/`, `gps-denied-onboard/` (live GPS SSE), `satellite-provider/` (orthophoto reference tiles), `autopilot/` (mission status) |
|
|
| Annotations | `/annotations` | `annotations/` (media, annotations, settings), `detections/` + `detections-semantic/` (AI detect), `loader/` (model availability status only) |
|
|
| Dataset Explorer | `/dataset` | `annotations/` (queries, validation), `ai-training/` (class distribution, dataset health), `admin/` (detection classes seed) |
|
|
| Admin | `/admin` | `admin/` (users, detection classes, AI recognition + GPS device + model-version settings) |
|
|
| Settings | `/settings` | `annotations/` (tenant / directories / aircrafts), `admin/` (connection check) |
|
|
|
|
`Header` exposes a global flight selector — the **selected flight is the
|
|
application context** and most other pages auto-filter by it. The
|
|
selection is persisted server-side via `UserSettings` in the
|
|
`annotations/` API.
|
|
|
|
For the full UX spec (wireframes, interactions, keyboard shortcuts, color
|
|
tokens, affiliation icons, combat-readiness indicator, gradient annotation
|
|
list, time-window video annotation overlay, drawer behaviour, etc.) see
|
|
[`_docs/ui_design/README.md`](_docs/ui_design/README.md).
|
|
|
|
## Tech stack
|
|
|
|
- **React 19** + **TypeScript 5.7**
|
|
- **Vite 6** (`bun run dev` / `bun run build`)
|
|
- **Bun 1.3.11** as package manager and runtime (`packageManager` field)
|
|
- **Tailwind CSS 4** via `@tailwindcss/vite`
|
|
- **react-router-dom 7** for routing
|
|
- **react-i18next** for UA/EN localization (see `src/i18n/`)
|
|
- **leaflet** + **react-leaflet** + **leaflet-draw** + **leaflet-polylinedecorator**
|
|
for the Flights map
|
|
- **chart.js** + **react-chartjs-2** for telemetry / class distribution
|
|
- **@hello-pangea/dnd** for waypoint reordering
|
|
- **react-icons** for icon set
|
|
- **react-dropzone** for orthophoto upload
|
|
|
|
There is no client-side state library — local component state and
|
|
`Context` (`AuthContext`, `FlightContext`) are sufficient at this scale.
|
|
Server data is fetched on demand and not cached beyond component
|
|
lifetime; introduce TanStack Query when the test suite is in place if
|
|
the lack of caching becomes a real problem.
|
|
|
|
## Repository layout
|
|
|
|
```
|
|
src/
|
|
├── main.tsx app entry point (creates the React root)
|
|
├── App.tsx routes, AuthProvider, FlightProvider
|
|
├── index.css tailwind base + custom CSS variables
|
|
├── api/
|
|
│ ├── client.ts fetch wrapper, JWT injection, error normalization
|
|
│ └── sse.ts EventSource helper used by flights + detections
|
|
├── auth/
|
|
│ ├── AuthContext.tsx JWT lifecycle, user identity, role
|
|
│ └── ProtectedRoute.tsx route guard
|
|
├── components/ shared UI (Header, FlightContext, ConfirmDialog,
|
|
│ DetectionClasses, HelpModal …)
|
|
├── features/
|
|
│ ├── login/ LoginPage
|
|
│ ├── flights/ FlightsPage + map, sidebar, params panel,
|
|
│ │ waypoint list, altitude chart, mini-map,
|
|
│ │ wind effect, JSON editor, draw control
|
|
│ ├── annotations/ AnnotationsPage + canvas editor, video player,
|
|
│ │ media list, annotations sidebar, class colors
|
|
│ ├── dataset/ DatasetPage
|
|
│ ├── admin/ AdminPage
|
|
│ └── settings/ SettingsPage
|
|
├── hooks/ useDebounce, useResizablePanel
|
|
├── i18n/ i18n.ts + en.json + ua.json
|
|
└── types/ shared TS types
|
|
|
|
_docs/
|
|
├── legacy/ history of the WPF predecessor
|
|
└── ui_design/ page-level wireframes inherited from the WPF UI
|
|
|
|
.cursor/ workspace-scoped agents/rules/skills
|
|
.woodpecker/ CI pipeline (Woodpecker, ARM build target)
|
|
Dockerfile multi-stage: bun build → nginx static
|
|
nginx.conf production nginx config (SPA fallback to /index.html)
|
|
vite.config.ts vite + react + tailwind plugin
|
|
tsconfig.json TS config
|
|
```
|
|
|
|
The skeleton mirrors the **page-per-feature, control-per-domain**
|
|
decomposition of the legacy WPF app:
|
|
`Azaion.Annotator` → `features/annotations/`,
|
|
`Azaion.Dataset` → `features/dataset/`,
|
|
`Azaion.Suite.MainSuite` → `components/Header.tsx`, etc. See
|
|
`_docs/legacy/wpf-era.md` §10 for the per-feature mapping and §11 for
|
|
the parts that are intentionally NOT being ported.
|
|
|
|
## Local development
|
|
|
|
Prerequisites:
|
|
|
|
- [Bun](https://bun.sh/) 1.3.11+
|
|
- A reachable suite (or at least the `admin/` and `annotations/`
|
|
services). For an all-in-one local stack, see
|
|
[`suite/_infra/dev/README.md`](../_infra/dev/README.md).
|
|
|
|
```bash
|
|
# from suite/ui/
|
|
bun install --frozen-lockfile
|
|
bun run dev # http://localhost:5173 (Vite)
|
|
bun run build # tsc -b + vite build → dist/
|
|
bun run preview # serve the production build locally
|
|
```
|
|
|
|
API base URL is configured via Vite environment variables. Copy
|
|
`.env.example` (when introduced — currently the wiring is hardcoded;
|
|
this is one of the testability fixes scheduled for `/autodev` Step 4)
|
|
to `.env.local` before `bun run dev`. Until then, see
|
|
`src/api/client.ts` for the current base-URL strategy.
|
|
|
|
## Production build
|
|
|
|
The production image is a static bundle behind nginx:
|
|
|
|
```bash
|
|
docker build -t azaion-ui:dev .
|
|
docker run --rm -p 8080:80 azaion-ui:dev
|
|
# open http://localhost:8080/
|
|
```
|
|
|
|
The image expects the suite's reverse-proxy / ingress to terminate TLS
|
|
and forward `/api/*` to the appropriate backend service. See
|
|
[`suite/_infra/deploy/`](../_infra/deploy/) for per-target compose files.
|
|
|
|
## CI
|
|
|
|
CI runs in self-hosted **Woodpecker**, building the multi-arch Docker
|
|
image and pushing it to the suite's Harbor registry. Pipeline: see
|
|
[`.woodpecker/build-arm.yml`](.woodpecker/build-arm.yml). Suite-wide CI
|
|
infra: [`suite/_infra/ci/README.md`](../_infra/ci/README.md).
|
|
|
|
The build is triggered on push to `dev`, `stage`, and `main`. Image tags
|
|
are branch-tagged; no `latest` tag is published.
|
|
|
|
## How this repo is being matured
|
|
|
|
1. **Document the existing code** — bottom-up, via the `/document`
|
|
skill: `_docs/02_document/` will hold module docs, component specs,
|
|
architecture, and a final report. Triggered automatically as Step 1
|
|
of the existing-code flow.
|
|
2. **Architecture baseline scan** of the produced architecture against
|
|
the codebase (`_docs/02_document/architecture_compliance_baseline.md`).
|
|
3. **Test specifications** — produced from the documentation, not from
|
|
the code, so the tests describe intended behaviour. Output:
|
|
`_docs/02_document/tests/`.
|
|
4. **Testability revision** — the smallest possible refactor that lets
|
|
tests run (replace hardcoded API URLs with env vars, etc.).
|
|
Strictly minimal; deeper refactoring is deferred to step 8.
|
|
5. **Decompose tests** into individual tasks and **implement** them.
|
|
6. **Run tests** — green tests become the safety net.
|
|
7. **(Optional) Refactor** the codebase against the safety net.
|
|
8. From there, the project enters the existing-code feature cycle:
|
|
*new task → implement → run tests → sync test specs → update docs
|
|
→ security audit → performance test → deploy → retrospective*, and
|
|
loops.
|
|
|
|
The state machine for this is in [`_docs/_autodev_state.md`](_docs/_autodev_state.md).
|
|
The orchestration definition is in
|
|
[`.cursor/skills/autodev/SKILL.md`](.cursor/skills/autodev/SKILL.md).
|
|
|
|
## License
|
|
|
|
See the parent suite repository.
|