From 9888014becf0b5b0526c4f7f537dfad518e216de Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 17 Jun 2026 23:03:27 +0200 Subject: [PATCH] Polish populated workbench states --- CHANGELOG.md | 10 +++++ .../test_sprint51_quality_export_polish.py | 3 ++ .../test_sprint53_selection_ergonomics.py | 9 ++++ docs/CODEX_EXECUTION_LOG.md | 24 +++++++++++ docs/TODO.md | 3 +- .../src/components/exports/ExportCenter.tsx | 26 +++++++++++- .../src/components/exports/ExportPreview.tsx | 15 ++++--- frontend/src/styles/app.css | 42 ++++++++++++++++++- 8 files changed, 121 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00edefd1..9925d32c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -604,3 +604,13 @@ Added: - Preserved existing dataset detail loading, map layer state, export actions and API client behavior. - Added regression coverage for dataset quick actions and inspector navigation wiring. - No API contracts, migrations, product capabilities, live provider fetching or AI/model dependency changes were introduced. + +## Sprint 54 populated-state UI polish (2026-06-17) + +- Ran the live demo/export workflow against Tower and audited populated Data and Exports states. +- Changed the Data workspace to keep Project and AOI side by side while giving the Dataset catalog a full-width row. +- Compacted the Exports history to show the latest 10 artifacts by default with an explicit show-all toggle. +- Kept a visible Export Preview panel even before preview content is selected. +- Shortened displayed export paths while preserving the full path in the element title. +- Added regression coverage for populated-state Data layout, export limiting and export preview empty state. +- No API contracts, migrations, product capabilities, live provider fetching or AI/model dependency changes were introduced. diff --git a/backend/tests/test_sprint51_quality_export_polish.py b/backend/tests/test_sprint51_quality_export_polish.py index 960918a0..cfe9b1af 100644 --- a/backend/tests/test_sprint51_quality_export_polish.py +++ b/backend/tests/test_sprint51_quality_export_polish.py @@ -31,8 +31,11 @@ def test_export_center_uses_artifact_actions_and_cards() -> None: assert 'className="latest-export-card"' in export_center assert 'className="export-list"' in export_center assert 'className="export-card"' in export_center + assert "visibleExports = showAllExports ? exports : exports.slice(0, 10)" in export_center + assert "Show all exports" in export_center assert "onExportDataset" in export_center assert "onExportDetectionRun" in export_center assert "onExportSegmentationRun" in export_center assert "download-only HTML artifact" in export_center assert 'className="export-preview-panel"' in export_preview + assert "No export preview selected." in export_preview diff --git a/backend/tests/test_sprint53_selection_ergonomics.py b/backend/tests/test_sprint53_selection_ergonomics.py index e91c077a..27d48e15 100644 --- a/backend/tests/test_sprint53_selection_ergonomics.py +++ b/backend/tests/test_sprint53_selection_ergonomics.py @@ -18,6 +18,15 @@ def test_dataset_panel_exposes_map_and_export_quick_actions() -> None: assert "disabled={!(dataset.dataset_type === 'vector' || dataset.dataset_type === 'geojson')}" in panel +def test_data_workspace_keeps_catalog_wide_enough_for_populated_state() -> None: + css = (ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8") + + assert ".workspace-grid-data {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n}" in css + assert ".workspace-grid-data > section:nth-child(3)" in css + assert "grid-column: 1 / -1" in css + assert ".dataset-card .button-row" in css + + def test_app_wires_dataset_quick_actions_to_existing_workspaces() -> None: app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md index db390f8e..a8af485e 100644 --- a/docs/CODEX_EXECUTION_LOG.md +++ b/docs/CODEX_EXECUTION_LOG.md @@ -2175,3 +2175,27 @@ Limitations: Next recommended pass: - Verify dataset quick actions with demo data on Tower, then improve populated map/detail readability if needed. + +## Sprint 54 populated-state UI polish (2026-06-17) + +Changed: +- Ran the live demo/export workflow against the Tower deployment to inspect real populated workbench states. +- Adjusted the Data workspace so Project and AOI remain side by side while the Dataset catalog spans the full row for readable populated dataset cards. +- Made dataset-card action rows responsive so Map/Exports/detail actions do not crowd or clip on populated cards. +- Limited the Exports artifact history to the latest 10 entries by default with an explicit show-all toggle. +- Kept the Export Preview panel visible even before an artifact is selected, avoiding a blank middle column in the Exports workspace. +- Shortened displayed export storage paths while keeping the full path available in the title attribute. +- Added regression coverage for the populated Data layout and Exports populated-state behavior. + +Tested: +- `bash scripts/verify_demo_export_workflow.sh http://192.168.10.150:1202` +- Local Vite visual audit using the live Tower API proxy on `http://127.0.0.1:5176` + +Open: +- Run full readiness, deploy Tower, then verify the polished populated states on `http://192.168.10.150:1202`. + +Limitations: +- This pass remains UI polish only. It does not add features, change API contracts, alter migrations, fetch live providers or enable new AI models. + +Next recommended pass: +- Add export history filtering or retention controls if artifact history continues to grow during demo runs. diff --git a/docs/TODO.md b/docs/TODO.md index 89d8774b..084d9421 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -323,4 +323,5 @@ This file now starts with the current implementation status. Older preparation/b - [x] Polish QA/QC and Exports workspaces. - [x] Add selected-object inspector detail tabs for project, AOI, dataset, QA check, export and AI run context. - [x] Improve map/dataset selection ergonomics from the workbench canvas and inspector. -- [ ] Improve populated map/detail readability after a demo workflow run. +- [x] Improve populated Data/Exports readability after a demo workflow run. +- [ ] Add export history filtering or retention controls for long-running demo environments. diff --git a/frontend/src/components/exports/ExportCenter.tsx b/frontend/src/components/exports/ExportCenter.tsx index 42679dee..0d3ffc48 100644 --- a/frontend/src/components/exports/ExportCenter.tsx +++ b/frontend/src/components/exports/ExportCenter.tsx @@ -1,3 +1,4 @@ +import { useState } from 'react' import type { DatasetCreateResponse, ExportCreateResponse, ExportRead } from '../../types' interface ExportCenterProps { @@ -34,6 +35,14 @@ function canPreviewJson(item: ExportRead): boolean { return true } +function compactPath(value: string): string { + const parts = value.split('/').filter(Boolean) + if (parts.length <= 2) { + return value + } + return parts.slice(-2).join('/') +} + export function ExportCenter({ selectedProjectId, selectedDataset, @@ -53,9 +62,12 @@ export function ExportCenter({ onPreviewContent, onDownload, }: ExportCenterProps): JSX.Element { + const [showAllExports, setShowAllExports] = useState(false) const canExportDataset = Boolean(selectedDataset && isVectorDatasetType(selectedDataset.dataset_type)) const geojsonExports = exports.filter((item) => item.export_type.includes('geojson')).length const reportExports = exports.filter((item) => item.export_type === 'project_report_html').length + const visibleExports = showAllExports ? exports : exports.slice(0, 10) + const hiddenExportCount = Math.max(exports.length - visibleExports.length, 0) return (
@@ -126,8 +138,18 @@ export function ExportCenter({

Create metadata, GeoJSON or HTML report artifacts once the active project has data to hand off.

) : null} + {exports.length > 10 ? ( +
+ + Showing {visibleExports.length} latest exports. {hiddenExportCount > 0 ? `${hiddenExportCount} older artifacts hidden.` : 'All artifacts shown.'} + + +
+ ) : null}
) } diff --git a/frontend/src/styles/app.css b/frontend/src/styles/app.css index 1105c208..a0e8a20f 100644 --- a/frontend/src/styles/app.css +++ b/frontend/src/styles/app.css @@ -679,7 +679,7 @@ section li strong + div { } .workspace-grid-data { - grid-template-columns: minmax(16rem, 0.75fr) minmax(18rem, 0.95fr) minmax(22rem, 1.35fr); + grid-template-columns: repeat(2, minmax(0, 1fr)); } .workspace-grid-analysis, @@ -701,6 +701,10 @@ section li strong + div { overflow: visible; } +.workspace-grid-data > section:nth-child(3) { + grid-column: 1 / -1; +} + .workspace-grid-ai > section { align-self: stretch; } @@ -943,6 +947,16 @@ button.entity-card { margin-top: 0.7rem; } +.dataset-card .button-row { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr)); +} + +.dataset-card .button-row button { + width: 100%; + margin-top: 0; +} + .button-row { display: flex; flex-wrap: wrap; @@ -1068,6 +1082,29 @@ button.entity-card { background: var(--accent-soft); } +.list-limit-banner { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + gap: 0.7rem; + align-items: center; + margin-top: 0.8rem; + border: 1px solid var(--line); + border-radius: 8px; + padding: 0.62rem 0.72rem; + background: #ffffff; +} + +.list-limit-banner span { + color: var(--muted); + font-size: 0.86rem; + line-height: 1.35; +} + +.list-limit-banner button { + width: auto; + min-height: 2.15rem; +} + .export-list { margin-top: 0.8rem; } @@ -1311,7 +1348,8 @@ button.entity-card { .quality-summary-grid, .quality-score-row, .export-action-grid, - .inspector-action-bar { + .inspector-action-bar, + .list-limit-banner { grid-template-columns: 1fr; }