Files
ui/_docs/02_document/components/06_annotations/description.md
T
Oleksandr Bezdieniezhnykh 510df68bcf [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>
2026-05-11 00:38:49 +03:00

11 KiB
Raw Blame History

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 #1318):

  • 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 #2123):

  • Async progress is not streamed (no SSE subscription).
  • Errors silently console.error'd, no UI feedback.

MediaList (findings #2426):

  • 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 #2734 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 0100, 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 #1415) 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.