# Module: `src/features/dataset/DatasetPage.tsx` > Compact module doc. Spec: `_docs/ui_design/README.md` (Dataset Explorer Layout) and parent suite `../../../../_docs/09_dataset_explorer.md` (API contract). Imports `CanvasEditor` from `../annotations/` — see cross-feature edge in `00_discovery.md §8`. ## Purpose Owns the `/dataset` route. Read-side surface for the `Annotations` table: paginated thumbnail grid, date / class / status / objects-only / name filters, inline editing through the Annotations Tab's `CanvasEditor`, and a class-distribution chart. Mirrors the legacy `Azaion.Dataset.DatasetExplorer` window (`_docs/legacy/wpf-era.md §5`). ## Public interface Default-exported page component, no props. Mounts under `/dataset` in `App.tsx`. ## Internal logic - **Tabs**: `'annotations'` (grid, default) | `'editor'` (hidden until a thumbnail is double-clicked) | `'distribution'` (bar chart). State held in component. - **Filters**: `fromDate`, `toDate`, `statusFilter` (`AnnotationStatus`), `selectedClassNum` (from `DetectionClasses`), `objectsOnly` (boolean), `search` (400 ms debounced via `useDebounce`). - **Pagination**: client `page` state, server `pageSize` fixed at 20, `totalPages = ceil(totalCount / pageSize)`. - **Selection**: `Set`. Plain click replaces; Ctrl+click toggles. Validate button appears when set is non-empty. - **Validate**: `POST endpoints.annotations.datasetBulkStatus()` (= `/api/annotations/dataset/bulk-status`) with `{ annotationIds[], status: Validated }`. - **Distribution**: lazy-loaded on tab switch via `GET endpoints.annotations.datasetClassDistribution()` (= `/api/annotations/dataset/class-distribution`). - **Editor tab** mounts `` with a synthesised `Media` stub built from `editorAnnotation.mediaId` (most fields blank). Used so `CanvasEditor` can fetch the image via `endpoints.annotations.annotationImage(id)` (= `/api/annotations/annotations/{id}/image`). ## Dependencies - Internal: `api` (barrel — `api`, `endpoints`, since AZ-485 / F4 + AZ-486 / F7), `useDebounce`, `useResizablePanel` (left panel 250 / 200–400), `FlightContext`, `DetectionClasses`, `ConfirmDialog` (imported but not used here — see Findings), `features/annotations/CanvasEditor`, `types/index`. - External: `react`, `react-i18next`. ## External integrations | Builder → Path | Where | Notes | |---|---|---| | `endpoints.annotations.dataset(qs)` → `/api/annotations/dataset?...` | `fetchItems` | Filters: `page`, `pageSize`, `fromDate`, `toDate`, `flightId`, `status`, `classNum`, `hasDetections`, `name` (caller builds `URLSearchParams.toString()`). | | `endpoints.annotations.datasetItem(id)` → `/api/annotations/dataset/{id}` | `handleDoubleClick` | Loads full `AnnotationListItem` for the editor tab. | | `endpoints.annotations.datasetBulkStatus()` → `/api/annotations/dataset/bulk-status` | `handleValidate` | Body: `{ annotationIds, status }`. | | `endpoints.annotations.datasetClassDistribution()` → `/api/annotations/dataset/class-distribution` | `loadDistribution` | Class histogram. | | `endpoints.annotations.annotationThumbnail(id)` → `/api/annotations/annotations/{id}/thumbnail` | grid tile `` | One HTTP per visible tile. | | `endpoints.annotations.annotationImage(id)` → `/api/annotations/annotations/{id}/image` | `CanvasEditor` (delegated) | When the editor is open. | Path builders live in `src/api/endpoints.ts` (since AZ-486 / F7). Spec contract is in parent suite `_docs/09_dataset_explorer.md`. ## Findings carried into Step 4 / 6 / 8 1. **No keyboard shortcuts implemented**: spec demands `1–9` (class), Enter (save), Del (delete), X (delete all), Esc (close editor), V (validate selected), Up/Down/PageUp/PageDown (navigate). Only Ctrl+click for multi-select works. The editor tab has no Save / Delete buttons either. Step 6 problem extraction. 2. **`Refresh thumbnails` button is missing** — spec calls for a status-bar action to regenerate the thumbnail database with progress. Step 6. 3. **No virtualisation in the grid**: spec says "virtualized grid" — current code renders all `items` returned by the page (max 20 due to `pageSize`). For larger pages performance would degrade. Today not a problem because `pageSize=20`. Step 8. 4. **Editor tab does not Save**: opening an annotation in the editor lets the user edit `editorDetections` locally but there's no Save / Cancel control wired up. Edits are discarded when the user changes tab. Step 6. 5. **`editorMedia` synthetic stub** — `mediaType: 1` is a magic number (`MediaType.Image = 1`); should reuse the enum import already present. Step 4. 6. **`ConfirmDialog` imported but never used** — dead import. Step 4 cleanup. 7. **`fetchItems` does `catch {}`** silently — same `coderule.mdc` violation as elsewhere. Step 4. 8. **Empty-state**: when `items.length === 0` the grid renders nothing; no "No matches" message. Step 4. 9. **`thumbnail` URL does not include a cache-buster**; if a thumbnail is regenerated server-side, the browser will keep the stale image. Step 4 / Step 8. 10. **`isSeed` red-ring is correctly rendered**, but `isSeed` is not in `AnnotationStatus` filters — the user can't filter to seeds-only. Step 6 if intended. 11. **Date inputs accept any `` string**; no validation that `fromDate ≤ toDate`. Step 4. 12. **Status filter buttons skip status `None`** (spec lists None as one of the four buttons) — current code shows `All`, `Created`, `Edited`, `Validated`, conflating `All` with "include None". Step 4. 13. **`selectedClassNum=0` is the "no filter" sentinel** but also a real class number (class 0 exists per `_docs/ui_design/README.md` → military vehicle). Selecting class 0 in `DetectionClasses` is indistinguishable from "no filter". Step 6. 14. **Inherits one cross-cutting UI fix and one cross-repo parent-doc fix** (resolved with user 2026-05-10): - **[STEP 4 — UI FIX]** `AnnotationStatus` values must change from UI `0/1/2` to spec `0/10/20/30/40` (`src/types/index.ts:23`). Every status filter button in this page (`null`/`null`/`Created`/`Edited`/`Validated`) currently sends a wrong integer. The "All" button is value `null` (no filter) — keep, but also expose a real "None" filter using the new `AnnotationStatus.None=0`. **PRIORITY** for Step 4. See annotations doc finding #27. - **[RESOLVED 2026-05-10]** `DatasetItem.isSplit` is correct on UI; parent `../../../../_docs/09_dataset_explorer.md §1` response schema now includes it. See annotations doc finding #33. ## Tests None. ## Cross-doc references - Parent suite Dataset Explorer API: `../../../../_docs/09_dataset_explorer.md` - UI spec: `../../ui_design/README.md` (Dataset Explorer Layout, Keyboard Shortcuts). - Imports `CanvasEditor` from `features/annotations/` — see `00_discovery.md §8` cross-feature edge. - Legacy WPF reference: `../../legacy/wpf-era.md §5` (Dataset Explorer window).