Polish Data Map mobile layout
This commit is contained in:
@@ -7,6 +7,14 @@
|
|||||||
|
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Sprint 74 Data/Map mobile visual polish (2026-06-20)
|
||||||
|
|
||||||
|
- Tightened mobile Data workspace upload form, file input and dataset action button sizing.
|
||||||
|
- Kept desktop dataset action grid width contract while adding compact mobile tracks.
|
||||||
|
- Tightened Map toolbar, layer control sliders and empty-map quick actions for narrow screens.
|
||||||
|
- Added static regression coverage for Data/Map mobile CSS contracts.
|
||||||
|
- No API contracts, migrations, backend behavior, provider fetching or AI model behavior changed.
|
||||||
|
|
||||||
## Sprint 73 QA/QC result filtering (2026-06-20)
|
## Sprint 73 QA/QC result filtering (2026-06-20)
|
||||||
|
|
||||||
- Added client-side QA/QC result search, status and check-type filters.
|
- Added client-side QA/QC result search, status and check-type filters.
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
|
||||||
|
|
||||||
|
def test_data_and_map_mobile_polish_css_contracts() -> None:
|
||||||
|
css = (ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
assert ".file-input-label input[type='file']" in css
|
||||||
|
assert ".dataset-upload-form label" in css
|
||||||
|
assert ".dataset-action-grid" in css
|
||||||
|
assert ".dataset-action-button" in css
|
||||||
|
assert ".map-toolbar" in css
|
||||||
|
assert ".layer-control-card input[type='range']" in css
|
||||||
|
assert ".map-empty-action-grid" in css
|
||||||
|
assert ".map-empty-action-grid button" in css
|
||||||
|
assert "minmax(7.25rem, 1fr)" in css
|
||||||
|
assert "touch-action: pan-x;" in css
|
||||||
|
|
||||||
|
|
||||||
|
def test_data_and_map_components_keep_existing_workflow_markup() -> None:
|
||||||
|
dataset_panel = (ROOT / "frontend" / "src" / "components" / "datasets" / "DatasetPanel.tsx").read_text(
|
||||||
|
encoding="utf-8"
|
||||||
|
)
|
||||||
|
map_workspace = (ROOT / "frontend" / "src" / "components" / "map" / "MapWorkspace.tsx").read_text(
|
||||||
|
encoding="utf-8"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert 'className="dataset-upload-form"' in dataset_panel
|
||||||
|
assert 'className="file-input-label"' in dataset_panel
|
||||||
|
assert "dataset-action-grid" in dataset_panel
|
||||||
|
assert "dataset-action-button" in dataset_panel
|
||||||
|
assert "map-toolbar" in map_workspace
|
||||||
|
assert "layer-control-card" in map_workspace
|
||||||
|
assert "map-empty-action-grid" in map_workspace
|
||||||
@@ -2763,3 +2763,30 @@ Limitations:
|
|||||||
|
|
||||||
Next recommended pass:
|
Next recommended pass:
|
||||||
- Continue with Data/Map mobile visual polish, especially dataset upload/action forms and map toolbar density on narrow screens.
|
- Continue with Data/Map mobile visual polish, especially dataset upload/action forms and map toolbar density on narrow screens.
|
||||||
|
|
||||||
|
## Sprint 74 Data/Map mobile visual polish (2026-06-20)
|
||||||
|
|
||||||
|
Changed:
|
||||||
|
- Added mobile-density CSS for Data workspace upload forms, file input sizing and dataset action grids.
|
||||||
|
- Kept the desktop dataset action grid width contract intact while adding compact mobile tracks.
|
||||||
|
- Added touch/width containment for map toolbar controls, range sliders and empty-map quick actions.
|
||||||
|
- Reduced mobile map container height to keep controls and map visible together on narrow screens.
|
||||||
|
- Added `backend/tests/test_sprint74_data_map_mobile_polish.py`.
|
||||||
|
- Updated `frontend/README.md`, `docs/TODO.md` and `CHANGELOG.md`.
|
||||||
|
|
||||||
|
Tested:
|
||||||
|
- Red step: `python -m pytest backend/tests/test_sprint74_data_map_mobile_polish.py -q` failed on missing mobile Data/Map CSS contracts.
|
||||||
|
- `python -m pytest backend/tests/test_sprint74_data_map_mobile_polish.py backend/tests/test_sprint72_mobile_overflow_hardening.py backend/tests/test_sprint69_dataset_action_polish.py backend/tests/test_sprint68_dataset_catalog_density.py backend/tests/test_sprint67_map_empty_state_quick_actions.py backend/tests/test_sprint63_map_overlay_ergonomics.py backend/tests/test_sprint50_workspace_usability_polish.py backend/tests/test_sprint30_workbench_components.py -q` (`21 passed`)
|
||||||
|
- `cd frontend && npm run typecheck`
|
||||||
|
- `cd frontend && npm run build`
|
||||||
|
- Local browser check against `http://127.0.0.1:5178` with live API proxy at a 390px viewport: Data upload form, file input and 8 dataset action buttons stayed within the viewport with no body-level horizontal overflow; Map toolbar, 2 layer controls, range sliders and empty-map quick actions also stayed within the viewport.
|
||||||
|
- Screenshots captured under `artifacts/sprint74-data-map-mobile-polish/`.
|
||||||
|
|
||||||
|
Open:
|
||||||
|
- Run full readiness, redeploy Tower and verify live Data/Map mobile polish after deployment.
|
||||||
|
|
||||||
|
Limitations:
|
||||||
|
- Frontend CSS polish only; no Data/Map workflow, API, persistence, migration, provider or AI/model changes.
|
||||||
|
|
||||||
|
Next recommended pass:
|
||||||
|
- Continue with AI Labs mobile/density polish, especially detection and segmentation forms/tables.
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ This file now starts with the current implementation status. Older preparation/b
|
|||||||
- [x] Expand golden QA/QC benchmark coverage across partial, perfect, no-overlap and MultiPolygon scenarios.
|
- [x] Expand golden QA/QC benchmark coverage across partial, perfect, no-overlap and MultiPolygon scenarios.
|
||||||
- [x] Improve workbench shell visual polish, mobile navigation density and AI result readability.
|
- [x] Improve workbench shell visual polish, mobile navigation density and AI result readability.
|
||||||
- [x] Improve Map workspace layer provenance, empty guidance and selected-feature summary readability.
|
- [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.
|
||||||
|
|
||||||
## Sprint 8 status
|
## Sprint 8 status
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ React + TypeScript + MapLibre foundation for project/area/dataset workflow.
|
|||||||
|
|
||||||
The workbench now uses a task-based shell instead of a single long panel stack. `App.tsx` still owns shared orchestration state, but the UI is organized into Overview, Data, Map, QA/QC, AI Labs, Exports and System workspaces with a persistent top context bar and right-side dataset inspector.
|
The workbench now uses a task-based shell instead of a single long panel stack. `App.tsx` still owns shared orchestration state, but the UI is organized into Overview, Data, Map, QA/QC, AI Labs, Exports and System workspaces with a persistent top context bar and right-side dataset inspector.
|
||||||
|
|
||||||
|
Data and Map workspaces include mobile-density CSS for file inputs, dataset action buttons, map toolbar controls, range sliders and empty-map quick actions so narrow screens avoid accidental viewport overflow.
|
||||||
|
|
||||||
## Scope implemented
|
## Scope implemented
|
||||||
- API client layer (`src/services/api`)
|
- API client layer (`src/services/api`)
|
||||||
- Project and area list/create flows
|
- Project and area list/create flows
|
||||||
|
|||||||
@@ -284,9 +284,11 @@ section {
|
|||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: 0.72rem;
|
margin-top: 0.72rem;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox-row input {
|
.checkbox-row input {
|
||||||
|
flex: 0 0 auto;
|
||||||
width: auto;
|
width: auto;
|
||||||
min-height: auto;
|
min-height: auto;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -951,6 +953,19 @@ section th {
|
|||||||
background: var(--panel-soft);
|
background: var(--panel-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dataset-upload-form label,
|
||||||
|
.file-input-label {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-input-label input[type='file'] {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
.data-density-grid {
|
.data-density-grid {
|
||||||
border: 1px solid var(--line);
|
border: 1px solid var(--line);
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
@@ -1173,6 +1188,7 @@ button.entity-card {
|
|||||||
min-height: 3.25rem;
|
min-height: 3.25rem;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
touch-action: pan-x;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dataset-action-button span,
|
.dataset-action-button span,
|
||||||
@@ -1424,17 +1440,19 @@ button.entity-card {
|
|||||||
|
|
||||||
.map-empty-action-grid {
|
.map-empty-action-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(7.25rem, 1fr));
|
||||||
gap: 0.55rem;
|
gap: 0.55rem;
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.map-empty-action-grid button {
|
.map-empty-action-grid button {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
min-width: 0;
|
||||||
min-height: 4.2rem;
|
min-height: 4.2rem;
|
||||||
gap: 0.18rem;
|
gap: 0.18rem;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
touch-action: pan-x;
|
||||||
}
|
}
|
||||||
|
|
||||||
.map-empty-action-grid span,
|
.map-empty-action-grid span,
|
||||||
@@ -1646,7 +1664,7 @@ button.entity-card {
|
|||||||
|
|
||||||
.map-toolbar {
|
.map-toolbar {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
align-items: end;
|
align-items: end;
|
||||||
margin-bottom: 0.85rem;
|
margin-bottom: 0.85rem;
|
||||||
@@ -1655,17 +1673,22 @@ button.entity-card {
|
|||||||
.layer-control-card {
|
.layer-control-card {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
min-width: 0;
|
||||||
padding: 0.58rem 0.65rem;
|
padding: 0.58rem 0.65rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layer-control-card input[type='range'] {
|
.layer-control-card input[type='range'] {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
min-height: auto;
|
min-height: auto;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
touch-action: pan-x;
|
||||||
}
|
}
|
||||||
|
|
||||||
.map-status {
|
.map-status {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
|
min-width: 0;
|
||||||
border: 1px solid var(--line);
|
border: 1px solid var(--line);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 0.62rem 0.72rem;
|
padding: 0.62rem 0.72rem;
|
||||||
@@ -2029,4 +2052,32 @@ button.entity-card {
|
|||||||
.status-strip-grid {
|
.status-strip-grid {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dataset-upload-form {
|
||||||
|
gap: 0.55rem;
|
||||||
|
padding: 0.68rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataset-action-grid,
|
||||||
|
.map-empty-action-grid {
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(7.25rem, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataset-action-button,
|
||||||
|
.map-empty-action-grid button {
|
||||||
|
min-height: 3rem;
|
||||||
|
padding: 0.48rem 0.56rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-toolbar {
|
||||||
|
gap: 0.55rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-control-card {
|
||||||
|
padding: 0.52rem 0.58rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workbench-main .map-container {
|
||||||
|
height: 22rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user