diff --git a/CHANGELOG.md b/CHANGELOG.md index e2f0faba..8f649eec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ # Changelog +## Sprint 84 Data workspace density polish (2026-06-20) + +- Added selected-summary regions to Project, AOI and Dataset panels so active context is visible before forms. +- Split Data workspace panels into named form/list/catalog blocks to reduce form-first scanning friction. +- Restyled dataset upload as an embedded source-data block while preserving the existing upload flow. +- Added static regression coverage for Data workspace selected-summary, upload and catalog density contracts. +- No API contracts, migrations, backend behavior, provider fetching or AI model behavior changed. + ## Sprint 83 Workspace panel hierarchy polish (2026-06-20) - Made the Overview readiness strip a calmer section surface with tighter status tiles. diff --git a/backend/tests/test_sprint84_data_workspace_density.py b/backend/tests/test_sprint84_data_workspace_density.py new file mode 100644 index 00000000..61afddf4 --- /dev/null +++ b/backend/tests/test_sprint84_data_workspace_density.py @@ -0,0 +1,49 @@ +from __future__ import annotations + +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[2] + + +def test_project_and_area_panels_expose_selected_summary_regions() -> None: + project_panel = (ROOT / "frontend" / "src" / "components" / "project" / "ProjectPanel.tsx").read_text( + encoding="utf-8" + ) + area_panel = (ROOT / "frontend" / "src" / "components" / "project" / "AreaPanel.tsx").read_text( + encoding="utf-8" + ) + + assert "const selectedProject = projects.find" in project_panel + assert 'className="data-selection-summary data-selection-summary-project"' in project_panel + assert 'className="data-panel-form-block"' in project_panel + assert 'className="data-panel-list-block"' in project_panel + assert "const selectedArea = areas.find" in area_panel + assert 'className="data-selection-summary data-selection-summary-area"' in area_panel + assert 'className="data-panel-form-block"' in area_panel + assert 'className="data-panel-list-block"' in area_panel + + +def test_dataset_panel_separates_selected_upload_and_catalog_regions() -> None: + dataset_panel = (ROOT / "frontend" / "src" / "components" / "datasets" / "DatasetPanel.tsx").read_text( + encoding="utf-8" + ) + + assert "const selectedDataset = datasets.find" in dataset_panel + assert 'className="data-selection-summary data-selection-summary-dataset"' in dataset_panel + assert 'className="dataset-upload-block data-panel-form-block"' in dataset_panel + assert 'className="data-panel-list-block dataset-catalog-block"' in dataset_panel + assert 'className="data-section-label"' in dataset_panel + + +def test_data_workspace_density_css_contracts() -> None: + css = (ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8") + + assert ".data-selection-summary" in css + assert ".data-selection-summary strong" in css + assert ".data-panel-form-block" in css + assert ".data-panel-list-block" in css + assert ".data-section-label" in css + assert "grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));" in css + assert "background: linear-gradient(180deg, #ffffff, #f7fbf8);" in css + assert "border-left: 4px solid var(--accent);" in css diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md index 0d16f0df..5d5a58b6 100644 --- a/docs/CODEX_EXECUTION_LOG.md +++ b/docs/CODEX_EXECUTION_LOG.md @@ -3044,3 +3044,30 @@ Limitations: Next recommended pass: - Continue with Data workspace panel hierarchy and selected-item density after this pass is deployed and visually checked. + +## Sprint 84 Data workspace density polish (2026-06-20) + +Changed: +- Added selected-summary regions to Project, AOI and Dataset panels so the active data context appears before creation/upload forms. +- Split Project and AOI panels into `data-panel-form-block` and `data-panel-list-block` regions. +- Split Dataset catalog into selected dataset, upload source data and available dataset regions. +- Restyled dataset upload as an embedded source-data block while preserving the existing upload flow. +- Added `backend/tests/test_sprint84_data_workspace_density.py`. +- Updated `frontend/README.md`, `docs/TODO.md` and `CHANGELOG.md`. + +Tested: +- Live browser pre-check against `http://192.168.10.150:1202` showed Data workspace had no console errors or horizontal overflow, but the first Data viewport was still form-first and visually heavy. +- Red step: `python -m pytest backend/tests/test_sprint84_data_workspace_density.py -q` failed on missing selected-summary and named form/list/catalog regions. +- `python -m pytest backend/tests/test_sprint84_data_workspace_density.py -q` (`3 passed`) +- `python -m pytest backend/tests/test_sprint84_data_workspace_density.py backend/tests/test_sprint83_workspace_panel_hierarchy.py backend/tests/test_sprint50_workspace_usability_polish.py backend/tests/test_sprint29_dataset_components.py backend/tests/test_sprint68_dataset_catalog_density.py backend/tests/test_sprint69_dataset_action_polish.py backend/tests/test_sprint47_workbench_interaction_smoke.py -q` (`20 passed`) +- `cd frontend && npm run typecheck` +- `cd frontend && npm run build` + +Open: +- Full readiness, deployment and live browser verification still need to run for this pass. + +Limitations: +- Frontend Data workspace presentation hierarchy only; no upload behavior, API contract, persistence, migration, provider fetching or AI/model changes. + +Next recommended pass: +- Continue with Map workspace panel hierarchy and layer-control density after this pass is deployed and visually checked. diff --git a/docs/TODO.md b/docs/TODO.md index 1a4bc92b..6c4c45cb 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -73,6 +73,7 @@ This file now starts with the current implementation status. Older preparation/b - [x] Add compact loading/error/empty/result state polish across QA, exports and AI labs. - [x] Add compact shell density polish for topbar context, mobile navigation and workspace skip flow. - [x] Add Overview workspace panel hierarchy polish for readiness and recommended-action regions. +- [x] Add Data workspace selected-summary and panel density polish. ## Sprint 8 status diff --git a/frontend/README.md b/frontend/README.md index 4e1e5075..bfc8b52e 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -238,6 +238,7 @@ QA/QC, exports and AI lab result panels use shared loading, error, empty and rea - The workbench shell includes a compact command bar, consistent raised/sunken surfaces, structured empty states and scroll-safe AI result tables to keep the V1 workflow usable across desktop and mobile widths. - The shell includes a keyboard skip link, an explicit primary workspace navigation label and compact horizontal context/navigation rails on narrow screens so active workspace content is reachable without a tall preamble. - The Overview workspace separates readiness, status tiles and recommended next actions into distinct visual hierarchy regions, keeping the first screen scannable without changing workflow behavior. +- The Data workspace surfaces selected project, AOI and dataset context before creation/upload forms, then separates form and catalog/list regions for faster scanning. - The Export Center includes a handoff readiness summary, grouped artifact actions and provenance-rich export cards so report/GeoJSON handoff stays understandable in long-running demo projects. ## Workbench shell refactor diff --git a/frontend/src/components/datasets/DatasetPanel.tsx b/frontend/src/components/datasets/DatasetPanel.tsx index 57c4c511..e1b36882 100644 --- a/frontend/src/components/datasets/DatasetPanel.tsx +++ b/frontend/src/components/datasets/DatasetPanel.tsx @@ -105,6 +105,7 @@ export function DatasetPanel({ onOpenDatasetExport, }: DatasetPanelProps) { const readyDatasets = datasets.filter((dataset) => dataset.status === 'ready').length + const selectedDataset = datasets.find((dataset) => dataset.id === selectedDatasetId) const roleSummaries = [ { key: 'selected', @@ -146,52 +147,61 @@ export function DatasetPanel({ {readyDatasets}/{datasets.length} ready -
- - - - - -
+
+ Selected dataset + {selectedDataset?.name ?? 'No dataset selected'} + {selectedDataset ? `${datasetRoleLabel(normalizeDatasetRole(selectedDataset))} / ${selectedDataset.status}` : 'Inspect a dataset to load details and tools.'} +
+ +
+

Upload source data

+
+ + + + + +
+
{roleSummaries.map((summary) => ( @@ -210,78 +220,81 @@ export function DatasetPanel({

Upload vector, GeoJSON or raster data after selecting a project.

) : null} - +
+ size: {formatBytes(dataset.size_bytes)} + 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/components/project/AreaPanel.tsx b/frontend/src/components/project/AreaPanel.tsx index d0f6b6bf..b8a28038 100644 --- a/frontend/src/components/project/AreaPanel.tsx +++ b/frontend/src/components/project/AreaPanel.tsx @@ -30,6 +30,8 @@ export function AreaPanel({ onUpdateAreaForm, onSelectMapArea, }: AreaPanelProps): JSX.Element { + const selectedArea = areas.find((area) => area.id === selectedMapAreaId) + return (
@@ -41,58 +43,70 @@ export function AreaPanel({

{selectedProject ? `Project: ${selectedProject.name}` : 'Select a project first'}

-
- - -