diff --git a/CHANGELOG.md b/CHANGELOG.md index 2575d398..d1b7e9e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ # Changelog +## Sprint 69 Data catalog action polish (2026-06-19) + +- Added recommended-action hints to each dataset card so reference and candidate layers explain their QA role. +- Reworked dataset card actions into compact two-line buttons for Inspect, Map, Export / QA and Metadata. +- Preserved existing handlers, API contracts and persistence behavior; this is UI affordance polish only. +- Added static regression coverage for the action hints, disabled-action copy and responsive action grid. +- No API contracts, migrations, backend behavior, provider fetching or AI model behavior changed. + ## Sprint 68 Data catalog density polish (2026-06-19) - Added a compact Data catalog summary for Selected, Reference, Candidate and Source layers. diff --git a/backend/tests/test_sprint69_dataset_action_polish.py b/backend/tests/test_sprint69_dataset_action_polish.py new file mode 100644 index 00000000..9ccd5b38 --- /dev/null +++ b/backend/tests/test_sprint69_dataset_action_polish.py @@ -0,0 +1,40 @@ +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[2] + + +def test_dataset_panel_explains_recommended_actions() -> None: + dataset_panel = (ROOT / "frontend" / "src" / "components" / "datasets" / "DatasetPanel.tsx").read_text( + encoding="utf-8" + ) + + assert "datasetActionHint" in dataset_panel + assert "dataset-action-hint" in dataset_panel + assert "QA reference layer" in dataset_panel + assert "QA candidate layer" in dataset_panel + assert "Open on the map or send to Export / QA." in dataset_panel + + +def test_dataset_buttons_have_scan_friendly_action_copy() -> None: + dataset_panel = (ROOT / "frontend" / "src" / "components" / "datasets" / "DatasetPanel.tsx").read_text( + encoding="utf-8" + ) + + assert "dataset-action-grid" in dataset_panel + assert "Inspect" in dataset_panel + assert "Map" in dataset_panel + assert "Export / QA" in dataset_panel + assert "Metadata" in dataset_panel + assert "Vector/GeoJSON only" in dataset_panel + assert "Raster metadata is automatic" in dataset_panel + + +def test_dataset_action_styles_keep_buttons_dense_and_responsive() -> None: + css = (ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8") + + assert ".dataset-action-hint" in css + assert ".dataset-action-grid" in css + assert "repeat(auto-fit, minmax(8.75rem, 1fr))" in css + assert ".dataset-action-button" in css + assert ".dataset-action-button small" in css diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md index 50d2da68..0d523ea1 100644 --- a/docs/CODEX_EXECUTION_LOG.md +++ b/docs/CODEX_EXECUTION_LOG.md @@ -2603,3 +2603,32 @@ Limitations: Next recommended pass: - Continue with Data workspace action polish, especially making QA/export affordances clearer once candidate and reference layers are present. + +## Sprint 69 Data catalog action polish (2026-06-19) + +Changed: +- Added role-aware recommended action hints to dataset cards. +- Reworked dataset card actions into compact two-line buttons for Inspect, Map, Export / QA and Metadata. +- Kept all existing Data workspace handlers and API calls unchanged. +- Added disabled-action explanation copy for unsupported export/QA and raster metadata refresh cases. +- Added responsive `.dataset-action-grid` and `.dataset-action-button` CSS. +- Added `backend/tests/test_sprint69_dataset_action_polish.py`. +- Updated `frontend/README.md`, `docs/TODO.md` and `CHANGELOG.md`. + +Tested: +- Red step: `python -m pytest backend/tests/test_sprint69_dataset_action_polish.py -q` failed on missing action hints, action grid and responsive styles. +- `python -m pytest backend/tests/test_sprint69_dataset_action_polish.py backend/tests/test_sprint68_dataset_catalog_density.py backend/tests/test_sprint29_dataset_components.py -q` (`9 passed`) +- `cd frontend && npm run typecheck` +- `cd frontend && npm run build` +- Local browser check against `http://127.0.0.1:5175` with live API proxy: Data workspace rendered 2 role-aware hints and 8 compact dataset actions across the demo candidate/reference datasets, no console warnings/errors and no horizontal overflow on desktop or mobile. +- Screenshots captured under `artifacts/sprint69-dataset-action-polish/`. +- `bash scripts/run_readiness_check.sh` (`246 passed`) + +Open: +- Run full readiness, redeploy Tower and verify the live Data action polish after deployment. + +Limitations: +- This is a frontend affordance/readability pass only. It does not add new workflows, change dataset persistence, change API contracts, add migrations, fetch providers or alter AI/model behavior. + +Next recommended pass: +- Continue with QA/QC workspace handoff polish, especially linking the existing candidate/reference dataset context more clearly to persisted QA results. diff --git a/docs/TODO.md b/docs/TODO.md index 3308308a..55ceb8d3 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -340,3 +340,4 @@ This file now starts with the current implementation status. Older preparation/b - [x] Polish lightweight HTML project report readability, print styling and handoff sections. - [x] Add Map empty-state quick actions for ready vector datasets. - [x] Add Data catalog role-density polish for reference/candidate/source scanning. +- [x] Add Data catalog action polish for map, metadata, export and QA affordances. diff --git a/frontend/README.md b/frontend/README.md index 9913ad1b..ed1967a2 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -236,6 +236,7 @@ The workbench now uses a task-based shell instead of a single long panel stack. - The Map workspace shows active layer source/provenance/draw-state context and selected-feature property chips before the raw JSON inspector. - When the Map workspace has no active result layer, it lists ready vector/GeoJSON datasets as direct quick actions so populated demo projects can jump straight from the empty state to map inspection. - The Data catalog shows a compact selected/reference/candidate/source summary and scan-friendly badges. Persisted `reference` datasets are shown as Reference, non-reference vector/GeoJSON layers are shown as QA Candidates for workbench scanning, and raster/other uploads remain Source. +- Dataset cards explain the recommended next action and use compact two-line action buttons for inspect, map, export/QA and metadata refresh. Disabled actions keep a visible reason, such as `Vector/GeoJSON only`. ## Raster dependency visibility diff --git a/frontend/src/components/datasets/DatasetPanel.tsx b/frontend/src/components/datasets/DatasetPanel.tsx index 4df7a86d..57c4c511 100644 --- a/frontend/src/components/datasets/DatasetPanel.tsx +++ b/frontend/src/components/datasets/DatasetPanel.tsx @@ -77,6 +77,19 @@ function datasetRoleLabel(role: string): string { return 'Source' } +function datasetActionHint(dataset: DatasetCreateResponse, role: string): string { + if (role === 'reference') { + return 'QA reference layer. Select it when comparing candidates against trusted geometry.' + } + if (role === 'candidate') { + return 'QA candidate layer. Open on the map or send to Export / QA.' + } + if (dataset.dataset_type === 'raster') { + return 'Raster source. Use the raster tools in the inspector after selecting it.' + } + return 'Source dataset. Inspect details before using it in downstream workflows.' +} + export function DatasetPanel({ selectedProjectId, selectedDatasetId, @@ -225,33 +238,44 @@ export function DatasetPanel({ features: {dataset.feature_count ?? dataset.vector_summary?.feature_count ?? 'n/a'} bbox: {formatBounds(dataset.bounds_json ?? dataset.vector_summary?.bounds_json)} -
+

{datasetActionHint(dataset, datasetRole)}

+
- +
diff --git a/frontend/src/styles/app.css b/frontend/src/styles/app.css index 6ab8962f..70abc045 100644 --- a/frontend/src/styles/app.css +++ b/frontend/src/styles/app.css @@ -1137,14 +1137,47 @@ button.entity-card { margin-top: 0.7rem; } -.dataset-card .button-row { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr)); +.dataset-action-hint { + margin: 0.65rem 0 0; + color: #36524b; + font-size: 0.84rem; + line-height: 1.35; } -.dataset-card .button-row button { +.dataset-card .button-row, +.dataset-action-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(8.75rem, 1fr)); + gap: 0.5rem; + margin-top: 0.7rem; +} + +.dataset-action-button { + display: grid; + gap: 0.12rem; + align-content: center; width: 100%; + min-height: 3.25rem; margin-top: 0; + text-align: left; +} + +.dataset-action-button span, +.dataset-action-button small { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; +} + +.dataset-action-button span { + font-weight: 850; +} + +.dataset-action-button small { + font-size: 0.73rem; + font-weight: 750; + line-height: 1.2; + opacity: 0.78; } .button-row {