Oleksandr Bezdieniezhnykh ef56d9c207 [AZ-512] chore: reactivate for cycle 4 (Option B path)
User authorized Option B from the original AZ-512 Cross-Workspace
Verification gate: implement UI form with MSW-stubbed tests in
parallel with AZ-513 shipping on admin/. Task spec moved from
backlog/ → todo/. STATUS line updated. Leftover record re-opened
until AZ-513 deploys live.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 04:21:32 +03:00
2026-05-09 05:18:10 +03:00

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 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/ — system-level architecture and per-service feature docs (canonical source of truth).
  • _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/ — 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. 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)
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.

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.Annotatorfeatures/annotations/, Azaion.Datasetfeatures/dataset/, Azaion.Suite.MainSuitecomponents/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 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.
# 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:

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/ 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. Suite-wide CI infra: suite/_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. The orchestration definition is in .cursor/skills/autodev/SKILL.md.

License

See the parent suite repository.

S
Description
No description provided
Readme 5.2 MiB
Languages
TypeScript 74.1%
HTML 22%
CSS 3.7%
Dockerfile 0.2%