From 82d42c4a814e189fe56ce931e654ec2d1d387909 Mon Sep 17 00:00:00 2001 From: Codex Date: Sat, 20 Jun 2026 01:38:39 +0200 Subject: [PATCH] Polish export and system mobile layout --- CHANGELOG.md | 8 ++ ...st_sprint76_export_system_mobile_polish.py | 41 +++++++ docs/CODEX_EXECUTION_LOG.md | 24 ++++ docs/TODO.md | 1 + frontend/README.md | 2 + .../components/providers/ProviderPanel.tsx | 59 ++++++--- frontend/src/styles/app.css | 112 ++++++++++++++++++ 7 files changed, 232 insertions(+), 15 deletions(-) create mode 100644 backend/tests/test_sprint76_export_system_mobile_polish.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e189007..9af01127 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ # Changelog +## Sprint 76 Export/System mobile visual polish (2026-06-20) + +- Added scan-friendly Provider Capabilities cards with structured status, authority, geometry, query mode and layer chips. +- Tightened mobile export action cards, export history controls and export card headers. +- Added overflow wrapping for long provider limitations, attribution text, export ids and artifact paths. +- Added static regression coverage for Export/System mobile CSS and workflow markup contracts. +- No API contracts, migrations, backend behavior, provider fetching or AI model behavior changed. + ## Sprint 75 AI Labs mobile visual polish (2026-06-20) - Tightened mobile Detection and Segmentation Lab model card, form and result-summary sizing. diff --git a/backend/tests/test_sprint76_export_system_mobile_polish.py b/backend/tests/test_sprint76_export_system_mobile_polish.py new file mode 100644 index 00000000..58e4bf25 --- /dev/null +++ b/backend/tests/test_sprint76_export_system_mobile_polish.py @@ -0,0 +1,41 @@ +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[2] + + +def test_export_and_system_mobile_density_css_contracts() -> None: + css = (ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8") + + assert ".system-provider-list" in css + assert ".system-provider-card" in css + assert ".system-provider-grid" in css + assert ".system-provider-card div" in css + assert ".provider-layer-list" in css + assert ".provider-layer-chip" in css + assert ".export-action-grid" in css + assert ".handoff-action-card p" in css + assert ".export-history-controls input" in css + assert ".export-history-controls select" in css + assert ".export-card-header" in css + assert "minmax(7.5rem, 1fr)" in css + assert "overflow-wrap: anywhere;" in css + + +def test_export_and_provider_components_keep_workflow_markup() -> None: + export_center = (ROOT / "frontend" / "src" / "components" / "exports" / "ExportCenter.tsx").read_text( + encoding="utf-8" + ) + provider_panel = (ROOT / "frontend" / "src" / "components" / "providers" / "ProviderPanel.tsx").read_text( + encoding="utf-8" + ) + + assert 'className="export-center"' in export_center + assert "export-action-grid" in export_center + assert "handoff-action-card" in export_center + assert "export-history-controls" in export_center + assert "export-card-header" in export_center + assert "system-provider-list" in provider_panel + assert "system-provider-card" in provider_panel + assert "system-provider-grid" in provider_panel + assert "provider-layer-chip" in provider_panel diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md index f678c621..bed07bfb 100644 --- a/docs/CODEX_EXECUTION_LOG.md +++ b/docs/CODEX_EXECUTION_LOG.md @@ -2824,3 +2824,27 @@ Limitations: Next recommended pass: - Continue with Export/System mobile-density polish, especially export action cards and provider capability lists. + +## Sprint 76 Export/System mobile visual polish (2026-06-20) + +Changed: +- Added scan-friendly Provider Capabilities cards with structured provider header, status badge, authority/configuration/geometry/query mode fields and layer chips. +- Added mobile-density CSS for provider cards, export action cards, export history controls and export card headers. +- Added overflow wrapping for long provider limitations, attribution/license notes, export ids and artifact paths. +- Added `backend/tests/test_sprint76_export_system_mobile_polish.py`. +- Updated `frontend/README.md`, `docs/TODO.md` and `CHANGELOG.md`. + +Tested: +- Red step: `python -m pytest backend/tests/test_sprint76_export_system_mobile_polish.py -q` failed on missing Export/System mobile CSS and provider markup contracts. +- `python -m pytest backend/tests/test_sprint76_export_system_mobile_polish.py backend/tests/test_sprint75_ai_labs_mobile_polish.py backend/tests/test_sprint74_data_map_mobile_polish.py backend/tests/test_sprint31_unraid_template.py backend/tests/test_sprint64_export_handoff_polish.py backend/tests/test_sprint7b_provider_registry.py backend/tests/test_sprint30_workbench_components.py -q` (`27 passed`) +- `cd frontend && npm run typecheck` +- `cd frontend && npm run build` + +Open: +- Run full readiness, redeploy Tower and verify live Export/System mobile polish after deployment. + +Limitations: +- Frontend presentation polish only; no export workflow, provider API, persistence, migration, provider fetching or AI/model changes. + +Next recommended pass: +- Continue with right-side inspector mobile polish, especially long dataset/vector/raster metadata and action groups. diff --git a/docs/TODO.md b/docs/TODO.md index a220e757..9c877786 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -65,6 +65,7 @@ This file now starts with the current implementation status. Older preparation/b - [x] Improve Map workspace layer provenance, empty guidance and selected-feature summary readability. - [x] Add Data/Map mobile visual polish for upload forms, action grids and map toolbar density. - [x] Add AI Labs mobile visual polish for model cards, lab forms and result tables. +- [x] Add Export/System mobile visual polish for export actions and provider capability cards. ## Sprint 8 status diff --git a/frontend/README.md b/frontend/README.md index b2f5cf9f..79eab447 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -8,6 +8,8 @@ Data and Map workspaces include mobile-density CSS for file inputs, dataset acti AI Labs uses the same mobile-density baseline for Detection and Segmentation model cards, run forms, QA/result summaries and scroll-safe result tables. This keeps long model ids, tile paths and artifact paths from widening the workbench on phones. +Exports and System provider capabilities now use compact, mobile-safe cards for handoff actions, artifact filters and provider metadata. Long provider limitations, export ids and artifact paths wrap inside their cards instead of widening the workbench. + ## Scope implemented - API client layer (`src/services/api`) - Project and area list/create flows diff --git a/frontend/src/components/providers/ProviderPanel.tsx b/frontend/src/components/providers/ProviderPanel.tsx index 1872f6d6..b337dacc 100644 --- a/frontend/src/components/providers/ProviderPanel.tsx +++ b/frontend/src/components/providers/ProviderPanel.tsx @@ -14,25 +14,54 @@ export function ProviderPanel({ onRefresh, }: ProviderPanelProps): JSX.Element { return ( -
-

Provider Capabilities

- +
+
+
+

Provider Capabilities

+

Review configured local providers and honest not-configured external sources.

+
+ +
{loadingCapabilities ?

Loading provider capabilities...

: null} {capabilitiesError ?

{capabilitiesError}

: null} {providers.length === 0 && !loadingCapabilities ?

No providers reported by backend

: null} -
    +
      {providers.map((provider) => ( -
    • - {provider.display_name} -
      provider: {provider.provider_name}
      -
      authority: {provider.authority_level}
      -
      status: {provider.status}
      -
      configured: {provider.configured ? 'yes' : 'no'}
      -
      layers: {provider.supported_layers.join(', ')}
      -
      geometry: {provider.supported_geometry_types.join(', ')}
      -
      query modes: {provider.supported_query_modes.join(', ')}
      +
    • +
      +
      + {provider.display_name} + {provider.provider_name} +
      + {provider.status} +
      +
      +
      + Authority + {provider.authority_level} +
      +
      + Configured + {provider.configured ? 'yes' : 'no'} +
      +
      + Geometry + {provider.supported_geometry_types.join(', ')} +
      +
      + Query modes + {provider.supported_query_modes.join(', ')} +
      +
      +
      + {provider.supported_layers.map((layer) => ( + + {layer} + + ))} +
      limitation: {provider.limitation_message}
      attribution: {provider.attribution}
      license: {provider.license_note}
      diff --git a/frontend/src/styles/app.css b/frontend/src/styles/app.css index e6bda2bf..ac4d9c71 100644 --- a/frontend/src/styles/app.css +++ b/frontend/src/styles/app.css @@ -1493,6 +1493,12 @@ button.entity-card { text-align: left; } +.export-history-controls input, +.export-history-controls select { + width: 100%; + min-width: 0; +} + .handoff-summary-card { display: grid; gap: 0.72rem; @@ -1575,6 +1581,7 @@ button.entity-card { color: var(--muted); font-size: 0.84rem; line-height: 1.36; + overflow-wrap: anywhere; } .handoff-action-card button { @@ -1671,6 +1678,95 @@ button.entity-card { overflow-wrap: anywhere; } +.system-provider-list { + display: grid; + gap: 0.72rem; + padding: 0; + list-style: none; +} + +.system-provider-card { + display: grid; + min-width: 0; + gap: 0.62rem; + border: 1px solid var(--line); + border-radius: 8px; + padding: 0.85rem; + background: var(--panel-soft); +} + +.system-provider-card div { + min-width: 0; + overflow-wrap: anywhere; +} + +.system-provider-header { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + gap: 0.65rem; + align-items: start; +} + +.system-provider-header strong, +.system-provider-header span { + display: block; +} + +.system-provider-header span:not(.status-badge) { + margin-top: 0.16rem; + color: var(--muted); + font-size: 0.82rem; +} + +.system-provider-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr)); + gap: 0.5rem; +} + +.system-provider-grid > div { + border: 1px solid var(--line); + border-radius: 7px; + padding: 0.55rem; + background: #ffffff; +} + +.system-provider-grid span { + display: block; + color: var(--muted); + font-size: 0.68rem; + font-weight: 800; + letter-spacing: 0.05em; + text-transform: uppercase; +} + +.system-provider-grid strong { + display: block; + margin-top: 0.18rem; + font-size: 0.88rem; + line-height: 1.25; + overflow-wrap: anywhere; +} + +.provider-layer-list { + display: flex; + flex-wrap: wrap; + gap: 0.35rem; +} + +.provider-layer-chip { + display: inline-flex; + min-height: 1.45rem; + align-items: center; + border: 1px solid rgba(15, 118, 110, 0.2); + border-radius: 999px; + padding: 0.16rem 0.5rem; + background: var(--accent-soft); + color: var(--accent-strong); + font-size: 0.74rem; + font-weight: 800; +} + .export-preview-panel .job-result { max-height: 38rem; } @@ -2114,6 +2210,22 @@ button.entity-card { min-width: 36rem; } + .export-action-grid, + .handoff-action-grid, + .system-provider-grid { + grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr)); + } + + .handoff-action-card, + .system-provider-card { + padding: 0.68rem; + } + + .system-provider-header, + .export-card-header { + grid-template-columns: minmax(0, 1fr); + } + .dataset-action-button, .map-empty-action-grid button { min-height: 3rem;