Complete the V1 analysis handoff
This commit is contained in:
@@ -1079,6 +1079,8 @@ function App(): JSX.Element {
|
||||
onRunOrthophotoAnalysis={mapOrthophotoAnalysis.run}
|
||||
onSelectOrthophotoProduct={mapOrthophotoAnalysis.setSelectedProductKey}
|
||||
onClearQualityEvidence={clearQualityEvidenceGeoJson}
|
||||
onOpenAssistant={() => setActiveWorkspace('assistant')}
|
||||
onOpenExports={() => setActiveWorkspace('exports')}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
|
||||
@@ -625,8 +625,8 @@ function copyText(text: string): void {
|
||||
fallbackCopyText(text)
|
||||
}
|
||||
|
||||
function downloadJsonFile(filename: string, payload: unknown): void {
|
||||
const blob = new Blob([JSON.stringify(payload, null, 2)], { type: 'application/geo+json' })
|
||||
function downloadJsonFile(filename: string, payload: unknown, contentType = 'application/json'): void {
|
||||
const blob = new Blob([JSON.stringify(payload, null, 2)], { type: contentType })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
@@ -716,6 +716,8 @@ interface MapWorkspaceProps {
|
||||
onRunOrthophotoAnalysis: (bbox: VectorSelectionBBox) => Promise<boolean>
|
||||
onSelectOrthophotoProduct: (productKey: string) => void
|
||||
onClearQualityEvidence?: () => void
|
||||
onOpenAssistant: () => void
|
||||
onOpenExports: () => void
|
||||
}
|
||||
|
||||
export function MapWorkspace({
|
||||
@@ -797,6 +799,8 @@ export function MapWorkspace({
|
||||
onRunOrthophotoAnalysis,
|
||||
onSelectOrthophotoProduct,
|
||||
onClearQualityEvidence,
|
||||
onOpenAssistant,
|
||||
onOpenExports,
|
||||
}: MapWorkspaceProps): JSX.Element {
|
||||
const [advancedMode, setAdvancedMode] = useState(false)
|
||||
const [activeThemeId, setActiveThemeId] = useState<DataThemeId>(() => {
|
||||
@@ -1135,7 +1139,7 @@ export function MapWorkspace({
|
||||
if (!selectedFeatureGeoJson) {
|
||||
return
|
||||
}
|
||||
downloadJsonFile(selectedFeatureFilename, selectedFeatureGeoJson)
|
||||
downloadJsonFile(selectedFeatureFilename, selectedFeatureGeoJson, 'application/geo+json')
|
||||
}
|
||||
|
||||
const copySelectedMapFeatureProperties = () => {
|
||||
@@ -1192,22 +1196,46 @@ export function MapWorkspace({
|
||||
if (!mapSelectionResult) {
|
||||
return
|
||||
}
|
||||
downloadJsonFile(DEFAULT_AREA_SELECTION_FILENAME, mapSelectionResult.geojson)
|
||||
downloadJsonFile(DEFAULT_AREA_SELECTION_FILENAME, mapSelectionResult.geojson, 'application/geo+json')
|
||||
}
|
||||
|
||||
const copyAreaSelection = () => {
|
||||
copyText(JSON.stringify(mapSelectionResult?.geojson ?? { type: 'FeatureCollection', features: [] }, null, 2))
|
||||
}
|
||||
|
||||
const downloadActiveThemeSelection = () => {
|
||||
const downloadActiveThemeResult = () => {
|
||||
if (!activeSelectionResult) {
|
||||
return
|
||||
}
|
||||
downloadJsonFile(`${activeTheme.id}-selection.geojson`, activeSelectionResult.geojson)
|
||||
if (activeThemeDataset?.dataset_type === 'raster') {
|
||||
downloadJsonFile(`${activeTheme.id}-analysis.json`, {
|
||||
project_id: selectedProjectId,
|
||||
area_id: selectedMapArea?.id ?? null,
|
||||
area_name: selectedMapArea?.name ?? null,
|
||||
theme: activeTheme,
|
||||
dataset_id: activeThemeDataset.id,
|
||||
dataset_name: activeThemeDataset.name,
|
||||
source_name: activeThemeDataset.source_name,
|
||||
result: activeSelectionResult,
|
||||
})
|
||||
return
|
||||
}
|
||||
downloadJsonFile(`${activeTheme.id}-selection.geojson`, activeSelectionResult.geojson, 'application/geo+json')
|
||||
}
|
||||
|
||||
const copyActiveThemeSelection = () => {
|
||||
copyText(JSON.stringify(activeSelectionResult?.geojson ?? { type: 'FeatureCollection', features: [] }, null, 2))
|
||||
const copyActiveThemeResult = () => {
|
||||
copyText(JSON.stringify(activeSelectionResult ?? {}, null, 2))
|
||||
}
|
||||
|
||||
const downloadTemporalComparison = () => {
|
||||
if (!temporalComparison) {
|
||||
return
|
||||
}
|
||||
downloadJsonFile(`${activeTheme.id}-evolution-${temporalComparison.earlier.observed_at.slice(0, 10)}-${temporalComparison.later.observed_at.slice(0, 10)}.json`, temporalComparison)
|
||||
}
|
||||
|
||||
const copyTemporalComparison = () => {
|
||||
copyText(JSON.stringify(temporalComparison ?? {}, null, 2))
|
||||
}
|
||||
|
||||
const saveAreaSelectionExport = () => {
|
||||
@@ -1888,7 +1916,10 @@ export function MapWorkspace({
|
||||
<strong>{theme.label}</strong>
|
||||
<small>{dataset ? getDatasetSourceDisplayName(dataset) : 'Geen bron gekoppeld'}</small>
|
||||
</span>
|
||||
<b>{item ? resultMetricLabel(item.result) : dataset ? 'Niet bevraagd' : 'Bron ontbreekt'}</b>
|
||||
<span className="geo-theme-result-value">
|
||||
<b>{item ? resultMetricLabel(item.result) : dataset ? 'Niet bevraagd' : 'Bron ontbreekt'}</b>
|
||||
{item?.result.summary ? <small>{item.result.summary.metric_label}</small> : null}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
@@ -1930,8 +1961,28 @@ export function MapWorkspace({
|
||||
|
||||
{analysisMode === 'current' ? (
|
||||
<div className="geo-result-actions">
|
||||
<button className="secondary-action" disabled={!activeSelectionResult || activeThemeDataset?.dataset_type === 'raster'} type="button" onClick={downloadActiveThemeSelection}>Download GeoJSON</button>
|
||||
<button className="secondary-action" disabled={!activeSelectionResult} type="button" onClick={copyActiveThemeSelection}>Kopieer gegevens</button>
|
||||
<button className="secondary-action" disabled={!activeSelectionResult} type="button" onClick={downloadActiveThemeResult}>
|
||||
{activeThemeDataset?.dataset_type === 'raster' ? 'Download analyse' : 'Download GeoJSON'}
|
||||
</button>
|
||||
<button className="secondary-action" disabled={!activeSelectionResult} type="button" onClick={copyActiveThemeResult}>Kopieer gegevens</button>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{analysisMode === 'evolution' && temporalComparison ? (
|
||||
<div className="geo-result-actions">
|
||||
<button className="secondary-action" type="button" onClick={downloadTemporalComparison}>Download vergelijking</button>
|
||||
<button className="secondary-action" type="button" onClick={copyTemporalComparison}>Kopieer vergelijking</button>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{activeSelectionResult || temporalComparison ? (
|
||||
<div className="geo-result-next-actions" aria-label="Volgende stap">
|
||||
<span>
|
||||
<strong>Analyse klaar</strong>
|
||||
<small>Stel een vraag over dit gebied of open je bewaarde resultaten.</small>
|
||||
</span>
|
||||
<button className="primary-action" type="button" onClick={onOpenAssistant}>Stel AI-vraag</button>
|
||||
<button className="secondary-action" type="button" onClick={onOpenExports}>Open downloads</button>
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
|
||||
@@ -6459,6 +6459,17 @@ section {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.geo-theme-result-value {
|
||||
display: grid;
|
||||
justify-items: end;
|
||||
min-width: 8.5rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.geo-theme-result-value small {
|
||||
max-width: 13rem;
|
||||
}
|
||||
|
||||
.geo-data-notice {
|
||||
margin: 0;
|
||||
border-left: 3px solid #b17a31;
|
||||
@@ -6542,6 +6553,27 @@ section {
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.geo-result-next-actions {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto auto;
|
||||
gap: 0.45rem;
|
||||
align-items: center;
|
||||
border-top: 1px solid #dfe7e3;
|
||||
padding-top: 0.65rem;
|
||||
}
|
||||
|
||||
.geo-result-next-actions > span {
|
||||
display: grid;
|
||||
gap: 0.12rem;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.geo-result-next-actions small {
|
||||
color: #687570;
|
||||
font-size: 0.66rem;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.geo-explorer-footer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -6581,7 +6613,8 @@ section {
|
||||
.geo-results-panel > .geo-panel-heading,
|
||||
.geo-results-panel > .error,
|
||||
.geo-results-panel > .geo-data-notice,
|
||||
.geo-results-panel > .geo-result-actions {
|
||||
.geo-results-panel > .geo-result-actions,
|
||||
.geo-results-panel > .geo-result-next-actions {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
@@ -6661,7 +6694,8 @@ section {
|
||||
}
|
||||
|
||||
.geo-map-actions,
|
||||
.geo-result-actions {
|
||||
.geo-result-actions,
|
||||
.geo-result-next-actions {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user