Polish operation form readability
This commit is contained in:
@@ -7,6 +7,14 @@
|
|||||||
|
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Sprint 80 Operation form readability polish (2026-06-20)
|
||||||
|
|
||||||
|
- Added structured headings, helper text, field wrappers and action rows to dense raster operation controls.
|
||||||
|
- Added the same form readability structure to vector clip, buffer and intersect controls.
|
||||||
|
- Added compact CSS contracts for dataset tool headings, helper text, field grids, action rows and inline error blocks.
|
||||||
|
- Added static regression coverage for raster/vector operation form readability contracts.
|
||||||
|
- No API contracts, migrations, backend behavior, provider fetching or AI model behavior changed.
|
||||||
|
|
||||||
## Sprint 79 Accessibility focus polish (2026-06-20)
|
## Sprint 79 Accessibility focus polish (2026-06-20)
|
||||||
|
|
||||||
- Added a shared visible focus-ring contract for primary buttons, workspace navigation, command chips, inspector tabs and dataset action buttons.
|
- Added a shared visible focus-ring contract for primary buttons, workspace navigation, command chips, inspector tabs and dataset action buttons.
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
|
||||||
|
|
||||||
|
def test_dataset_operation_form_css_contracts() -> None:
|
||||||
|
css = (ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
assert ".dataset-tool-heading" in css
|
||||||
|
assert ".dataset-tool-helper" in css
|
||||||
|
assert ".dataset-tool-field" in css
|
||||||
|
assert ".dataset-tool-label" in css
|
||||||
|
assert ".dataset-tool-error" in css
|
||||||
|
assert ".dataset-tool-action-row" in css
|
||||||
|
assert ".dataset-tool-grid" in css
|
||||||
|
assert "grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));" in css
|
||||||
|
assert "overflow-wrap: anywhere;" in css
|
||||||
|
|
||||||
|
|
||||||
|
def test_raster_controls_expose_readable_operation_groups() -> None:
|
||||||
|
raster_controls = (ROOT / "frontend" / "src" / "components" / "datasets" / "RasterControls.tsx").read_text(
|
||||||
|
encoding="utf-8"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert 'className="dataset-tool-heading"' in raster_controls
|
||||||
|
assert 'className="dataset-tool-helper"' in raster_controls
|
||||||
|
assert 'className="dataset-tool-grid"' in raster_controls
|
||||||
|
assert 'className="dataset-tool-field"' in raster_controls
|
||||||
|
assert 'className="dataset-tool-label"' in raster_controls
|
||||||
|
assert 'className="dataset-tool-action-row"' in raster_controls
|
||||||
|
assert 'className="dataset-tool-error"' in raster_controls
|
||||||
|
assert "Target CRS for the derived raster artifact." in raster_controls
|
||||||
|
assert "Tile size must be > 0." in raster_controls
|
||||||
|
|
||||||
|
|
||||||
|
def test_vector_controls_expose_readable_operation_groups() -> None:
|
||||||
|
vector_controls = (ROOT / "frontend" / "src" / "components" / "datasets" / "VectorControls.tsx").read_text(
|
||||||
|
encoding="utf-8"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert 'className="dataset-tool-heading"' in vector_controls
|
||||||
|
assert 'className="dataset-tool-helper"' in vector_controls
|
||||||
|
assert 'className="dataset-tool-grid"' in vector_controls
|
||||||
|
assert 'className="dataset-tool-field"' in vector_controls
|
||||||
|
assert 'className="dataset-tool-label"' in vector_controls
|
||||||
|
assert 'className="dataset-tool-action-row"' in vector_controls
|
||||||
|
assert "Clip features to the selected project area." in vector_controls
|
||||||
|
assert "Intersect with another persisted vector dataset." in vector_controls
|
||||||
@@ -2929,3 +2929,29 @@ Limitations:
|
|||||||
|
|
||||||
Next recommended pass:
|
Next recommended pass:
|
||||||
- Continue with form-level validation/readability polish for dense raster/vector operation panels.
|
- Continue with form-level validation/readability polish for dense raster/vector operation panels.
|
||||||
|
|
||||||
|
## Sprint 80 Operation form readability polish (2026-06-20)
|
||||||
|
|
||||||
|
Changed:
|
||||||
|
- Added structured headings, helper text, field wrappers, responsive field grids and action rows to raster operation controls.
|
||||||
|
- Added equivalent readability structure to vector clip, buffer and intersect controls.
|
||||||
|
- Added inline dataset tool error styling for raster clip/tile validation messages.
|
||||||
|
- Added `backend/tests/test_sprint80_operation_form_readability.py`.
|
||||||
|
- Updated `frontend/README.md`, `docs/TODO.md` and `CHANGELOG.md`.
|
||||||
|
|
||||||
|
Tested:
|
||||||
|
- Red step: `python -m pytest backend/tests/test_sprint80_operation_form_readability.py -q` failed on missing form readability CSS and markup contracts.
|
||||||
|
- `python -m pytest backend/tests/test_sprint80_operation_form_readability.py -q` (`3 passed`)
|
||||||
|
- `python -m pytest backend/tests/test_sprint80_operation_form_readability.py backend/tests/test_sprint77_inspector_mobile_polish.py backend/tests/test_sprint29_dataset_components.py backend/tests/test_sprint28_dataset_workflow_hook.py backend/tests/test_vector_operations_service.py backend/tests/test_raster_operations_service.py -q` (`37 passed`)
|
||||||
|
- `cd frontend && npm run typecheck`
|
||||||
|
- `cd frontend && npm run build`
|
||||||
|
- `bash scripts/run_readiness_check.sh` (`273 passed`; frontend typecheck/build passed; Alembic single head `202606120900`)
|
||||||
|
|
||||||
|
Open:
|
||||||
|
- Run full readiness, redeploy Tower and verify live runtime smoke after deployment.
|
||||||
|
|
||||||
|
Limitations:
|
||||||
|
- Frontend readability/presentation polish only; no raster/vector operation behavior, API contract, persistence, migration, provider fetching or AI/model changes.
|
||||||
|
|
||||||
|
Next recommended pass:
|
||||||
|
- Continue with compact empty/error-state polish across QA, exports and AI lab result panels.
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ This file now starts with the current implementation status. Older preparation/b
|
|||||||
- [x] Add inspector mobile polish for dataset metadata, raster/vector tools and action groups.
|
- [x] Add inspector mobile polish for dataset metadata, raster/vector tools and action groups.
|
||||||
- [x] Add export preview readability polish for large JSON/GeoJSON handoff artifacts.
|
- [x] Add export preview readability polish for large JSON/GeoJSON handoff artifacts.
|
||||||
- [x] Add accessibility focus polish for primary workbench keyboard navigation.
|
- [x] Add accessibility focus polish for primary workbench keyboard navigation.
|
||||||
|
- [x] Add raster/vector operation form readability polish for dense tool panels.
|
||||||
|
|
||||||
## Sprint 8 status
|
## Sprint 8 status
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ Export Preview shows a compact JSON summary before the payload and keeps large J
|
|||||||
|
|
||||||
Primary workbench navigation, overview shortcuts, inspector tabs and dataset action buttons now share visible keyboard focus styling. Inspector tabs are also bound to tab panels with ARIA metadata.
|
Primary workbench navigation, overview shortcuts, inspector tabs and dataset action buttons now share visible keyboard focus styling. Inspector tabs are also bound to tab panels with ARIA metadata.
|
||||||
|
|
||||||
|
Raster and vector operation panels use structured group headings, compact helper text, field grids, action rows and inline error blocks so dense GIS controls remain scannable in the inspector.
|
||||||
|
|
||||||
## 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
|
||||||
|
|||||||
@@ -133,29 +133,39 @@ export function RasterControls({
|
|||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
<div className="dataset-tool-group">
|
<div className="dataset-tool-group">
|
||||||
<label>
|
<h4 className="dataset-tool-heading">Reproject raster</h4>
|
||||||
Reproject CRS
|
<p className="dataset-tool-helper">Create a derived raster in a target CRS with the selected resampling method.</p>
|
||||||
|
<div className="dataset-tool-grid">
|
||||||
|
<label className="dataset-tool-field">
|
||||||
|
<span className="dataset-tool-label">Reproject CRS</span>
|
||||||
<input
|
<input
|
||||||
value={rasterReprojectCrs}
|
value={rasterReprojectCrs}
|
||||||
onChange={(event) => onSetRasterReprojectCrs(event.target.value)}
|
onChange={(event) => onSetRasterReprojectCrs(event.target.value)}
|
||||||
placeholder="EPSG:31370"
|
placeholder="EPSG:31370"
|
||||||
/>
|
/>
|
||||||
|
<span className="dataset-tool-helper">Target CRS for the derived raster artifact.</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label className="dataset-tool-field">
|
||||||
Resampling
|
<span className="dataset-tool-label">Resampling</span>
|
||||||
<select value={rasterReprojectResampling} onChange={(event) => onSetRasterReprojectResampling(event.target.value)}>
|
<select value={rasterReprojectResampling} onChange={(event) => onSetRasterReprojectResampling(event.target.value)}>
|
||||||
<option value="nearest">nearest</option>
|
<option value="nearest">nearest</option>
|
||||||
<option value="bilinear">bilinear</option>
|
<option value="bilinear">bilinear</option>
|
||||||
<option value="cubic">cubic</option>
|
<option value="cubic">cubic</option>
|
||||||
</select>
|
</select>
|
||||||
|
<span className="dataset-tool-helper">Nearest preserves classes; bilinear/cubic smooth continuous rasters.</span>
|
||||||
</label>
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="dataset-tool-action-row">
|
||||||
<button type="button" onClick={onRunRasterReproject}>
|
<button type="button" onClick={onRunRasterReproject}>
|
||||||
Reproject raster
|
Reproject raster
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div className="dataset-tool-group">
|
<div className="dataset-tool-group">
|
||||||
<label>
|
<h4 className="dataset-tool-heading">Clip raster</h4>
|
||||||
Clip area
|
<p className="dataset-tool-helper">Clip the selected raster to an existing project area.</p>
|
||||||
|
<label className="dataset-tool-field">
|
||||||
|
<span className="dataset-tool-label">Clip area</span>
|
||||||
<select value={selectedClipAreaId} onChange={(event) => onSetSelectedClipAreaId(event.target.value)}>
|
<select value={selectedClipAreaId} onChange={(event) => onSetSelectedClipAreaId(event.target.value)}>
|
||||||
{areas.map((area) => (
|
{areas.map((area) => (
|
||||||
<option key={area.id} value={area.id}>
|
<option key={area.id} value={area.id}>
|
||||||
@@ -164,43 +174,54 @@ export function RasterControls({
|
|||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
<div className="dataset-tool-action-row">
|
||||||
<button type="button" onClick={onRunRasterClip} disabled={areas.length === 0}>
|
<button type="button" onClick={onRunRasterClip} disabled={areas.length === 0}>
|
||||||
Clip raster by area
|
Clip raster by area
|
||||||
</button>
|
</button>
|
||||||
{areas.length === 0 ? <p className="error">Create an area before raster clipping.</p> : null}
|
</div>
|
||||||
|
{areas.length === 0 ? <p className="dataset-tool-error">Create an area before raster clipping.</p> : null}
|
||||||
</div>
|
</div>
|
||||||
<div className="dataset-tool-group">
|
<div className="dataset-tool-group">
|
||||||
<label>
|
<h4 className="dataset-tool-heading">Generate tiles</h4>
|
||||||
Tile size
|
<p className="dataset-tool-helper">Create a tile manifest for downstream detection or segmentation runs.</p>
|
||||||
|
<div className="dataset-tool-grid">
|
||||||
|
<label className="dataset-tool-field">
|
||||||
|
<span className="dataset-tool-label">Tile size</span>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
min={1}
|
min={1}
|
||||||
value={rasterTileSize}
|
value={rasterTileSize}
|
||||||
onChange={(event) => onSetRasterTileSize(Number(event.target.value))}
|
onChange={(event) => onSetRasterTileSize(Number(event.target.value))}
|
||||||
/>
|
/>
|
||||||
|
<span className="dataset-tool-helper">{'Tile size must be > 0.'}</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label className="dataset-tool-field">
|
||||||
Overlap
|
<span className="dataset-tool-label">Overlap</span>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
min={0}
|
min={0}
|
||||||
value={rasterTileOverlap}
|
value={rasterTileOverlap}
|
||||||
onChange={(event) => onSetRasterTileOverlap(Number(event.target.value))}
|
onChange={(event) => onSetRasterTileOverlap(Number(event.target.value))}
|
||||||
/>
|
/>
|
||||||
|
<span className="dataset-tool-helper">Overlap must be smaller than tile size.</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label className="dataset-tool-field">
|
||||||
Tile basename
|
<span className="dataset-tool-label">Tile basename</span>
|
||||||
<input
|
<input
|
||||||
value={rasterTileOutputName}
|
value={rasterTileOutputName}
|
||||||
onChange={(event) => onSetRasterTileOutputName(event.target.value)}
|
onChange={(event) => onSetRasterTileOutputName(event.target.value)}
|
||||||
placeholder="optional"
|
placeholder="optional"
|
||||||
/>
|
/>
|
||||||
|
<span className="dataset-tool-helper">Optional artifact name prefix for generated tiles.</span>
|
||||||
</label>
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="dataset-tool-action-row">
|
||||||
<button type="button" onClick={onRunRasterTile} disabled={!isRasterTileInputValid}>
|
<button type="button" onClick={onRunRasterTile} disabled={!isRasterTileInputValid}>
|
||||||
Generate tiles
|
Generate tiles
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
{!isRasterTileInputValid ? (
|
{!isRasterTileInputValid ? (
|
||||||
<p className="error">
|
<p className="dataset-tool-error">
|
||||||
Tile size must be {'>'} 0 and overlap must be {'>='} 0 and smaller than tile size.
|
Tile size must be {'>'} 0 and overlap must be {'>='} 0 and smaller than tile size.
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
@@ -209,48 +230,63 @@ export function RasterControls({
|
|||||||
<div>
|
<div>
|
||||||
<p>Use available band indexes from the raster file (1-based).</p>
|
<p>Use available band indexes from the raster file (1-based).</p>
|
||||||
<div className="dataset-tool-group">
|
<div className="dataset-tool-group">
|
||||||
<p>NDVI</p>
|
<h4 className="dataset-tool-heading">NDVI</h4>
|
||||||
<label>
|
<p className="dataset-tool-helper">Vegetation index from NIR and red bands.</p>
|
||||||
Nir band
|
<div className="dataset-tool-grid">
|
||||||
|
<label className="dataset-tool-field">
|
||||||
|
<span className="dataset-tool-label">NIR band</span>
|
||||||
<input type="number" min={1} value={ndviNirBand} onChange={(event) => onSetNdviNirBand(Number(event.target.value))} />
|
<input type="number" min={1} value={ndviNirBand} onChange={(event) => onSetNdviNirBand(Number(event.target.value))} />
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label className="dataset-tool-field">
|
||||||
Red band
|
<span className="dataset-tool-label">Red band</span>
|
||||||
<input type="number" min={1} value={ndviRedBand} onChange={(event) => onSetNdviRedBand(Number(event.target.value))} />
|
<input type="number" min={1} value={ndviRedBand} onChange={(event) => onSetNdviRedBand(Number(event.target.value))} />
|
||||||
</label>
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="dataset-tool-action-row">
|
||||||
<button type="button" onClick={onRunRasterNdvi}>
|
<button type="button" onClick={onRunRasterNdvi}>
|
||||||
Compute NDVI
|
Compute NDVI
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div className="dataset-tool-group">
|
<div className="dataset-tool-group">
|
||||||
<p>NDWI</p>
|
<h4 className="dataset-tool-heading">NDWI</h4>
|
||||||
<label>
|
<p className="dataset-tool-helper">Water index from NIR and green bands.</p>
|
||||||
Nir band
|
<div className="dataset-tool-grid">
|
||||||
|
<label className="dataset-tool-field">
|
||||||
|
<span className="dataset-tool-label">NIR band</span>
|
||||||
<input type="number" min={1} value={ndwiNirBand} onChange={(event) => onSetNdwiNirBand(Number(event.target.value))} />
|
<input type="number" min={1} value={ndwiNirBand} onChange={(event) => onSetNdwiNirBand(Number(event.target.value))} />
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label className="dataset-tool-field">
|
||||||
Green band
|
<span className="dataset-tool-label">Green band</span>
|
||||||
<input type="number" min={1} value={ndwiGreenBand} onChange={(event) => onSetNdwiGreenBand(Number(event.target.value))} />
|
<input type="number" min={1} value={ndwiGreenBand} onChange={(event) => onSetNdwiGreenBand(Number(event.target.value))} />
|
||||||
</label>
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="dataset-tool-action-row">
|
||||||
<button type="button" onClick={onRunRasterNdwi}>
|
<button type="button" onClick={onRunRasterNdwi}>
|
||||||
Compute NDWI
|
Compute NDWI
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div className="dataset-tool-group">
|
<div className="dataset-tool-group">
|
||||||
<p>NDBI</p>
|
<h4 className="dataset-tool-heading">NDBI</h4>
|
||||||
<label>
|
<p className="dataset-tool-helper">Built-up index from SWIR and NIR bands.</p>
|
||||||
Swir band
|
<div className="dataset-tool-grid">
|
||||||
|
<label className="dataset-tool-field">
|
||||||
|
<span className="dataset-tool-label">SWIR band</span>
|
||||||
<input type="number" min={1} value={ndbiSwirBand} onChange={(event) => onSetNdbiSwirBand(Number(event.target.value))} />
|
<input type="number" min={1} value={ndbiSwirBand} onChange={(event) => onSetNdbiSwirBand(Number(event.target.value))} />
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label className="dataset-tool-field">
|
||||||
Nir band
|
<span className="dataset-tool-label">NIR band</span>
|
||||||
<input type="number" min={1} value={ndbiNirBand} onChange={(event) => onSetNdbiNirBand(Number(event.target.value))} />
|
<input type="number" min={1} value={ndbiNirBand} onChange={(event) => onSetNdbiNirBand(Number(event.target.value))} />
|
||||||
</label>
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="dataset-tool-action-row">
|
||||||
<button type="button" onClick={onRunRasterNdbi}>
|
<button type="button" onClick={onRunRasterNdbi}>
|
||||||
Compute NDBI
|
Compute NDBI
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,11 @@ export function VectorControls({
|
|||||||
<div className="dataset-tool-panel vector-tool-panel">
|
<div className="dataset-tool-panel vector-tool-panel">
|
||||||
<h3>Vector operations</h3>
|
<h3>Vector operations</h3>
|
||||||
<div className="dataset-tool-group">
|
<div className="dataset-tool-group">
|
||||||
<label>
|
<h4 className="dataset-tool-heading">Clip vector</h4>
|
||||||
Clip area
|
<p className="dataset-tool-helper">Clip features to the selected project area.</p>
|
||||||
|
<div className="dataset-tool-grid">
|
||||||
|
<label className="dataset-tool-field">
|
||||||
|
<span className="dataset-tool-label">Clip area</span>
|
||||||
<select value={selectedClipAreaId} onChange={(event) => onSetSelectedClipAreaId(event.target.value)}>
|
<select value={selectedClipAreaId} onChange={(event) => onSetSelectedClipAreaId(event.target.value)}>
|
||||||
{areas.map((area) => (
|
{areas.map((area) => (
|
||||||
<option key={area.id} value={area.id}>
|
<option key={area.id} value={area.id}>
|
||||||
@@ -37,16 +40,28 @@ export function VectorControls({
|
|||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="dataset-tool-action-row">
|
||||||
<button type="button" onClick={onRunVectorClip} disabled={areas.length === 0}>
|
<button type="button" onClick={onRunVectorClip} disabled={areas.length === 0}>
|
||||||
Run clip
|
Run clip
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="dataset-tool-group">
|
||||||
|
<h4 className="dataset-tool-heading">Buffer vector</h4>
|
||||||
|
<p className="dataset-tool-helper">Create a 25m buffer using the existing vector operation defaults.</p>
|
||||||
|
<div className="dataset-tool-action-row">
|
||||||
<button type="button" onClick={onRunVectorBuffer}>
|
<button type="button" onClick={onRunVectorBuffer}>
|
||||||
Run buffer (25m)
|
Run buffer (25m)
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="dataset-tool-group">
|
<div className="dataset-tool-group">
|
||||||
<label>
|
<h4 className="dataset-tool-heading">Intersect vector</h4>
|
||||||
Intersect target
|
<p className="dataset-tool-helper">Intersect with another persisted vector dataset.</p>
|
||||||
|
<div className="dataset-tool-grid">
|
||||||
|
<label className="dataset-tool-field">
|
||||||
|
<span className="dataset-tool-label">Intersect target</span>
|
||||||
<select value={selectedIntersectTargetId} onChange={(event) => onSetSelectedIntersectTargetId(event.target.value)}>
|
<select value={selectedIntersectTargetId} onChange={(event) => onSetSelectedIntersectTargetId(event.target.value)}>
|
||||||
<option value="">auto first vector</option>
|
<option value="">auto first vector</option>
|
||||||
{availableVectorTargets.map((target) => (
|
{availableVectorTargets.map((target) => (
|
||||||
@@ -55,11 +70,15 @@ export function VectorControls({
|
|||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
<span className="dataset-tool-helper">Leave automatic to use the first available vector target.</span>
|
||||||
</label>
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="dataset-tool-action-row">
|
||||||
<button type="button" onClick={onRunVectorIntersect}>
|
<button type="button" onClick={onRunVectorIntersect}>
|
||||||
Run intersect
|
Run intersect
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2148,16 +2148,69 @@ button.entity-card {
|
|||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dataset-tool-heading {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.92rem;
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataset-tool-helper {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 0.82rem;
|
||||||
|
line-height: 1.38;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataset-tool-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
|
||||||
|
gap: 0.52rem;
|
||||||
|
}
|
||||||
|
|
||||||
.dataset-tool-group label {
|
.dataset-tool-group label {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dataset-tool-field {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.22rem;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataset-tool-label {
|
||||||
|
color: var(--text);
|
||||||
|
font-size: 0.78rem;
|
||||||
|
font-weight: 800;
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
||||||
|
|
||||||
.dataset-tool-group input,
|
.dataset-tool-group input,
|
||||||
.dataset-tool-group select {
|
.dataset-tool-group select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dataset-tool-error {
|
||||||
|
margin: 0;
|
||||||
|
border: 1px solid rgba(153, 27, 27, 0.24);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 0.52rem 0.62rem;
|
||||||
|
background: rgba(153, 27, 27, 0.07);
|
||||||
|
color: var(--danger);
|
||||||
|
font-size: 0.82rem;
|
||||||
|
font-weight: 750;
|
||||||
|
line-height: 1.35;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataset-tool-action-row {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.dataset-tool-group button {
|
.dataset-tool-group button {
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|||||||
Reference in New Issue
Block a user