mirror of
https://github.com/azaion/ui.git
synced 2026-06-21 09:21:10 +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,132 @@
|
||||
# 06 — Annotations
|
||||
|
||||
## 1. High-Level Overview
|
||||
|
||||
**Purpose**: Image / video annotation editor — bounding boxes, classes, affiliation, combat readiness, AI detection (sync + async via SSE), and the media-list browser scoped to the active flight.
|
||||
|
||||
**Architectural Pattern**: Page composition (`AnnotationsPage`) wiring `MediaList` + `VideoPlayer` (or static image) + `CanvasEditor` + `AnnotationsSidebar` + `DetectionClasses`.
|
||||
|
||||
**Upstream dependencies**: `00_foundation`, `01_api-transport`, `03_shared-ui` (FlightContext, ConfirmDialog, DetectionClasses), `11_class-colors`.
|
||||
|
||||
**Downstream consumers**: `10_app-shell` (routed at `/annotations`); `07_dataset` imports `CanvasEditor` directly (cross-feature edge — see baseline scan).
|
||||
|
||||
## 2. Internal Interfaces
|
||||
|
||||
| Export | Notes |
|
||||
|--------|-------|
|
||||
| `AnnotationsPage()` | Top-level route component. Manages selected media, panel widths (via `useResizablePanel`), and the open annotation under edit. |
|
||||
|
||||
Internal modules:
|
||||
|
||||
| Module | Role |
|
||||
|--------|------|
|
||||
| `AnnotationsPage.tsx` | Orchestrator (route component) |
|
||||
| `MediaList.tsx` | Left panel: thumbnail browser + search/filter; consumes `useFlight()` |
|
||||
| `VideoPlayer.tsx` | HTML5 video + frame seek + per-frame annotation overlays |
|
||||
| `CanvasEditor.tsx` | Bounding-box draw / move / resize layer (also used by `07_dataset`) |
|
||||
| `AnnotationsSidebar.tsx` | Right panel: annotation list, AI-detect controls |
|
||||
|
||||
## 3. External API Specification
|
||||
|
||||
| Method | Path | Purpose |
|
||||
|--------|------|---------|
|
||||
| GET | `/api/annotations/media?flightId=...` | List media |
|
||||
| GET | `/api/annotations/media/{id}` | Media metadata |
|
||||
| GET | `/api/annotations/media/{id}/annotations` | Bbox list |
|
||||
| POST | `/api/annotations` | Create one |
|
||||
| PUT | `/api/annotations/{id}` | Update one |
|
||||
| DELETE | `/api/annotations/{id}` | Delete one |
|
||||
| POST | `/api/detect/{mediaId}` | Sync image AI-detect |
|
||||
| POST | `/api/detect/video/{mediaId}` | Async video AI-detect — should send `X-Refresh-Token`, currently does not (finding #30) |
|
||||
| GET | `/api/detect/classes` | Detection class list |
|
||||
| SSE | `/api/detect/stream/{jobId}` | Async detect progress (subscribed via `01_api-transport/sse.ts`) — but **`AnnotationsPage` does not subscribe today** (finding #10) |
|
||||
|
||||
## 5. Implementation Details
|
||||
|
||||
**State Management**: Page-local for the open annotation + selection; `useResizablePanel` for panel widths (not persisted — finding #11).
|
||||
|
||||
**Time-window math** (`CanvasEditor`, finding #6, post-cross-check correction): implementation is symmetric ±200 ms (400 ms total). Spec wants asymmetric 50 ms before + 150 ms after (200 ms total). UI is 4× too wide and not centred per spec.
|
||||
|
||||
**Gradient cap** (finding #9, post-cross-check correction): annotation row alpha gradient maxes at `0x28 = 16 %` opacity due to a `* 40` literal that is decimal, not hex. Wireframe demands `0x40 = 25 %`.
|
||||
|
||||
**`handleSave` body** (finding #32): currently `{ classNum, x, y, w, h, time }`. Suite spec requires `{ classNum, x, y, w, h, videoTime, Source, WaypointId }`. Owner: this component, also touches Foundation types.
|
||||
|
||||
**handleDownload (image export)** — risks tainting the `<canvas>` if the video is from a `blob:` URL with cross-origin frames; finding #12.
|
||||
|
||||
**Missing affordances** (findings #13–18):
|
||||
- Affiliation icons absent (spec mandates per-bbox).
|
||||
- Combat-readiness indicator absent.
|
||||
- `AFFILIATION_COLORS` defined but unused (dead).
|
||||
- No keyboard shortcuts R / V / PageUp / PageDown.
|
||||
- No camera-config side panel.
|
||||
- No tile zoom indicator for `splitTile` media.
|
||||
|
||||
**AI-detect controls** (`AnnotationsSidebar`, findings #21–23):
|
||||
- Async progress is not streamed (no SSE subscription).
|
||||
- Errors silently `console.error`'d, no UI feedback.
|
||||
|
||||
**MediaList** (findings #24–26):
|
||||
- Uses `alert()` for "no media" state.
|
||||
- `blob:` local previews ignore the search filter.
|
||||
- No virtualisation — long flights render all thumbnails.
|
||||
|
||||
**Cross-feature leak**: `07_dataset` imports `CanvasEditor` directly (caveat from `00_discovery.md` §8). The right home is a shared `components/canvas/` directory; not done in this step.
|
||||
|
||||
**Enum drift cross-link**: findings #27–34 capture the enum drift (`AnnotationStatus`, `Affiliation`, `CombatReadiness`, `MediaStatus`, `AnnotationSource`) — wire payloads using current `src/types/index.ts` values are wrong. Owner of fix: `00_foundation/types/index.ts`. Two findings (#31, #33) are **NO UI CHANGE — PARENT-DOC FIX** and have already been applied to the suite docs (state.json 02:18Z note); the rest are Step 4.
|
||||
|
||||
**Key Dependencies**: HTML5 `<canvas>` + `<video>`, `react-dropzone` (upload).
|
||||
|
||||
## 6b. WPF gap analysis (vs `suite/annotations-research`)
|
||||
|
||||
> Output of the Step 2 BLOCKING-gate cross-check (2026-05-10). The legacy WPF `Azaion.Annotator` window is the design source for this component; the file `_docs/legacy/wpf-era.md` §10 calls out which features must be ported. The list below is the delta — features that exist in the WPF source and are NOT yet present in the React port. Each entry names the WPF anchor and the React owner; numeric findings (#) come from `_docs/02_document/modules/src__features__annotations.md`.
|
||||
|
||||
| WPF feature | Anchor in `annotations-research` | React status | Owner |
|
||||
|------------|----------------------------------|--------------|-------|
|
||||
| **Time window asymmetric 50/150 ms** (interval-tree `_thresholdBefore=50ms`, `_thresholdAfter=150ms`) | `Azaion.Annotator/Annotator.xaml.cs:53-54` | Wrong (symmetric ±200 ms). Finding #6. | `CanvasEditor.tsx` |
|
||||
| **Keyboard shortcut `[Space]` = pause / resume** | `Annotator.xaml` `PauseClick` button tooltip "[Пробіл]" | Missing (no global key listener) | `VideoPlayer` + `AnnotationsPage` |
|
||||
| **Keyboard `[Left]` / `[Right]` = prev / next frame; `+Ctrl` = ±5 sec** | `PreviousFrameClick` / `NextFrameClick` tooltips | Missing | `VideoPlayer` |
|
||||
| **Keyboard `[Enter]` = save annotations and continue** | `SaveAnnotationsClick` tooltip "[Ентер]" | Missing. Finding #16 broadens this. | `AnnotationsPage` |
|
||||
| **Keyboard `[Del]` = delete selected annotations (with confirm)** | `Annotator.xaml.cs:204-222` (`DgAnnotations.KeyUp`) | Missing | `AnnotationsSidebar` + `ConfirmDialog` |
|
||||
| **Keyboard `[X]` = delete ALL annotations** | `RemoveAllClick` tooltip "[X]" | Missing | `AnnotationsPage` |
|
||||
| **Keyboard `[M]` = mute volume; also toggles GPS panel (context-sensitive)** | `TurnOffVolume` + `SwitchGpsPanel` tooltips both "[M]" | Missing | `VideoPlayer` |
|
||||
| **Keyboard `[R]` = AI Detect** | `AIDetectBtn_OnClick` tooltip "[R]" | Missing. Finding #16. | `AnnotationsSidebar` |
|
||||
| **Keyboard `[Ctrl+click]` = multi-select; `[Ctrl+drag]` = pan; `[Ctrl+wheel]` = zoom** | `Azaion.Common/Controls/CanvasEditor.cs` | Pan / zoom missing (finding listed); multi-select unverified | `CanvasEditor.tsx` |
|
||||
| **Volume slider** (`UpdatableProgressBar Volume`, range 0–100, mediator `VolumeChangedEvent`) | `Annotator.xaml:500-507` | Missing entirely | `VideoPlayer` |
|
||||
| **Status bar — clock `mm:ss / mm:ss`** | `Annotator.xaml.cs:237` `StatusClock.Text = ...` | Missing | `VideoPlayer` (display) + `AnnotationsPage` (slot) |
|
||||
| **Status bar — contextual help text** (`HelpTextEnum.{Initial, PlayVideo, PauseForAnnotations, AnnotationHelp}`, `BlinkHelp` flicker pattern) | `Azaion.Annotator/HelpTexts.cs` + `Annotator.xaml.cs:144-158` | Missing | `AnnotationsPage` (or a global toast) |
|
||||
| **Status bar — generic status text** (`StatusBarItem Status`) | `Annotator.xaml:653` | Missing | shared chrome (could live in App Shell or `AnnotationsPage`) |
|
||||
| **Sound Detections feature** ("Show objects detected by audio analysis", own button, distinct from AI Detect) | `Annotator.xaml:565-617` `SoundDetections` button + handler | **Entirely missing**. Not mentioned anywhere in `_docs/legacy/wpf-era.md §10` "What survived" — needs a user decision: port or drop. | TBD |
|
||||
| **Drone Maintenance feature** ("Аналіз стану БПЛА" — UAV state analysis, [K]) | `Annotator.xaml:618-630` `RunDroneMaintenance` button + handler | **Entirely missing**. Same status as above — port-or-drop decision required. | TBD |
|
||||
| **Resizable panel widths persisted** (left + right panels) | `Annotator.xaml.cs:243-252` `SaveUserSettings` writes `UIConfig.LeftPanelWidth` / `RightPanelWidth` | Missing — `useResizablePanel` does not persist (finding #11). | `00_foundation/useResizablePanel` + Settings backend |
|
||||
| **Camera config side panel** (altitude / focal / sensor → GSD) | `Annotator.xaml:196-203` `CameraConfigControl` | Missing (finding #17) | `AnnotationsPage` |
|
||||
| **Affiliation icons + Combat readiness indicator on bbox label** | `Azaion.Common/DTO/AffiliationEnum`, `_docs/ui_design/README.md` | Missing (findings #14–15) | `CanvasEditor.tsx` + types |
|
||||
| **Annotation list seek + zoom on double-click** | `Annotator.xaml.cs:197-202`, `OpenAnnotationResult` (seek + ZoomTo for split tiles) | Partial — seek probably works, "open split-tile zoom" not verified | `AnnotationsSidebar` |
|
||||
| **Help window "Як анотувати" (6 quality rules)** | `HelpWindow.xaml`, `_docs/legacy/wpf-era.md §10` "Help window" | `HelpModal` exists but GUIDELINES is a hardcoded string in source — not moved to i18n bundle. Step 4. | `03_shared-ui/HelpModal` |
|
||||
|
||||
### Decisions required at Step 4.5 (Architecture Vision)
|
||||
|
||||
- **Sound Detections** — port, drop, or move to a different module (e.g., a future audio-pipeline service)?
|
||||
- **Drone Maintenance** — same.
|
||||
- **Camera config** persistence — was per-`AppConfig` in WPF; in the React port should it be per-user-settings, per-flight, or per-detect-job?
|
||||
- **Status bar / help-text blinking** — keep the WPF "blink twice" UX, replace with toasts, or drop?
|
||||
|
||||
These are Architecture-Vision-level questions, not Step 2 component-graph decisions. Recorded here so Step 4.5 can pick them up.
|
||||
|
||||
## 7. Caveats & Edge Cases
|
||||
|
||||
- 26 findings in `src__features__annotations.md`. Cross-cutting blockers cluster on enum drift + `handleSave` body shape + missing `X-Refresh-Token`.
|
||||
- **Time-window** and **gradient** math wrong against spec.
|
||||
- **Video AI-detect not wired to SSE** — long-running jobs appear to hang from the user's POV.
|
||||
- **WPF gap analysis above** lists ~17 missing affordances. Highest user-impact: keyboard shortcuts, volume slider, status bar with clock + help text. Highest design-impact: Sound Detections + Drone Maintenance (both require a port-or-drop decision).
|
||||
|
||||
## 8. Dependency Graph
|
||||
|
||||
**Must be implemented after**: `00_foundation`, `01_api-transport`, `03_shared-ui`, `11_class-colors`.
|
||||
|
||||
**Can be implemented in parallel with**: every other feature page (note: `07_dataset` imports `CanvasEditor`, so a `CanvasEditor` extraction must coordinate).
|
||||
|
||||
**Blocks**: `07_dataset` (direct import dependency on `CanvasEditor`), `10_app-shell`.
|
||||
|
||||
## Module Inventory
|
||||
|
||||
Single consolidated module doc: `_docs/02_document/modules/src__features__annotations.md`. `classColors.ts` is moved into a separate component (`11_class-colors`) — its module doc is referenced from there, not here.
|
||||
Reference in New Issue
Block a user