Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix resume analysis states #279

Merged
merged 5 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions django_project/frontend/src/components/Map/DataTypes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export interface AnalysisData {
period?: AnalysisDataPeriod;
comparisonPeriod?: AnalysisDataPeriod;
community?: string;
communityName?: string;
communityFeatureId?: string;
reference_layer?: object;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,46 @@ export const AnalysisCustomGeometrySelector = forwardRef((
const { map } = useMap();
const drawingRef = useRef(null);

const drawGeom = (geom: FeatureCollection) => {
// add geom to map
map.addSource(
CUSTOM_GEOM_ID, {
type: 'geojson',
data: geom
}
);
map.addLayer({
'id': CUSTOM_GEOM_ID,
'type': 'line',
'source': CUSTOM_GEOM_ID,
'paint': {
"line-color": "#D20C0C",
"line-width": 2
}
});
map.addLayer({
'id': CUSTOM_GEOM_FILL_ID,
'type': 'fill',
'source': CUSTOM_GEOM_ID,
'paint': {
"fill-color": "#D20C0C",
"fill-outline-color": "#D20C0C",
"fill-opacity": 0.1
}
});
}

useImperativeHandle(ref, () => ({
/** Remove layer */
removeLayer() {
if (map) {
removeSource(map, CUSTOM_GEOM_ID);
}
},
drawLayer(geom: FeatureCollection) {
if (map) {
drawGeom(geom);
}
}
}));

Expand Down Expand Up @@ -164,32 +198,7 @@ export const AnalysisCustomGeometrySelector = forwardRef((
if (area === 0) {
onSelected(null, 0)
} else {
// add geom to map
map.addSource(
CUSTOM_GEOM_ID, {
type: 'geojson',
data: geom
}
);
map.addLayer({
'id': CUSTOM_GEOM_ID,
'type': 'line',
'source': CUSTOM_GEOM_ID,
'paint': {
"line-color": "#D20C0C",
"line-width": 2
}
});
map.addLayer({
'id': CUSTOM_GEOM_FILL_ID,
'type': 'fill',
'source': CUSTOM_GEOM_ID,
'paint': {
"fill-color": "#D20C0C",
"fill-outline-color": "#D20C0C",
"fill-opacity": 0.1
}
});
drawGeom(geom);
onSelected(geom, area);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface Props {
landscape: Landscape;
enableSelection: boolean;
onSelected: (value: Community) => void;
featureId?: string;
}

let hoverFunction: (ev: maplibregl.MapMouseEvent & {
Expand All @@ -21,7 +22,7 @@ let clickFunction: (ev: maplibregl.MapMouseEvent & {

/** Landscape geometry selector. */
export default function AnalysisLandscapeGeometrySelector(
{ landscape, enableSelection, onSelected }: Props
{ landscape, enableSelection, onSelected, featureId }: Props
) {
const { map } = useMap();

Expand Down Expand Up @@ -131,6 +132,7 @@ export default function AnalysisLandscapeGeometrySelector(
name: hit.properties['community_name'],
latitude: e.lngLat.lat,
longitude: e.lngLat.lng,
featureId: hit.properties.id
}
)
map.setFilter(
Expand Down Expand Up @@ -158,13 +160,22 @@ export default function AnalysisLandscapeGeometrySelector(
map.on('mousemove', COMMUNITY_ID, hoverFunction);
}

if (featureId) {
map.setFilter(
(COMMUNITY_ID + '-highlight'), ["==", "id", featureId]
);
} else {
map.setFilter(
(COMMUNITY_ID + '-highlight'), ["==", "id", '']
);
}

return () => {
map.off('click', COMMUNITY_FILL_ID, clickFunction);
map.off('mousemove', COMMUNITY_ID, hoverFunction);
}

}, [map, landscape, enableSelection])
}, [map, landscape, featureId, enableSelection])

return <></>
}

112 changes: 67 additions & 45 deletions django_project/frontend/src/components/Map/LeftSide/Analysis/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,27 @@ enum MapAnalysisInteraction {
CUSTOM_GEOMETRY_DRAWING
}

function checkPropertyEqualsXAndOthersNull<T>(
obj: T,
keyToCheck: keyof T,
valueToMatch: unknown
): boolean {
return Object.entries(obj).every(([key, value]) => {
if (key === keyToCheck) {
return value === valueToMatch;
}
return value === null || value === undefined;
});
}


/** Layer Checkbox component of map. */
export default function Analysis({ landscapes, layers, onLayerChecked, onLayerUnchecked }: Props) {
const { session, saveSession, loadingSession,loadSession } = useSession();
const { session, saveSession, loadingSession, loadSession, clearAnalysisState } = useSession();
const dispatch = useDispatch<AppDispatch>();
const [data, setData] = useState<AnalysisData>(
{ analysisType: Types.BASELINE }
);
const [communitySelected, setCommunitySelected] = useState<Community | null>(null);
const { loading, referenceLayerDiff } = useSelector((state: RootState) => state.analysis);
const { mapConfig } = useSelector((state: RootState) => state.mapConfig);
const [mapInteraction, setMapInteraction] = useState(MapAnalysisInteraction.NO_INTERACTION);
Expand Down Expand Up @@ -79,19 +92,37 @@ export default function Analysis({ landscapes, layers, onLayerChecked, onLayerUn
}
}, [savedAnalysisFlag]);




useEffect(() => {
// load saved session once
loadSession()
}, [])

useEffect(() => {
if (session && session?.analysisState) {
setData(session.analysisState);
if (session && session?.analysisState && checkPropertyEqualsXAndOthersNull(data, 'analysisType', Types.BASELINE)) {
setData(session.analysisState)
if (session.analysisState.analysisType === Types.SPATIAL && session.analysisState.reference_layer) {
// draw reference layer for spatial analysis
geometrySelectorRef?.current?.drawLayer({
'type': 'FeatureCollection',
'features': [{
'type': 'Feature',
'geometry': session.analysisState.reference_layer
}]
});
// trigger relative layer diff
dispatch(doAnalysis({
...session.analysisState,
latitude: null,
longitude: null
}))
}
// pop stored state
clearAnalysisState()
}
if(!loadingSession && session?.lastPage !== '/'){
saveSession('/map', { activity: "Visited Analysis Page"});
}

}, [loadingSession]);
}, [loadingSession, data]);


/** When data changed */
Expand All @@ -105,49 +136,29 @@ export default function Analysis({ landscapes, layers, onLayerChecked, onLayerUn
}

useEffect(() => {
setData({
...data,
community: communitySelected?.id ? '' + communitySelected?.id : null,
latitude: communitySelected?.latitude ? communitySelected?.latitude : null,
longitude: communitySelected?.longitude ? communitySelected?.longitude : null
})
}, [communitySelected]);

useEffect(() => {
if (
data.analysisType === 'Baseline' &&
data.community === null &&
data.latitude === null &&
data.longitude === null
) {
if(!session?.analysisState)
loadSession()
}


if (data.landscape && data.analysisType === Types.BASELINE) {
setMapInteraction(MapAnalysisInteraction.LANDSCAPE_SELECTOR)
saveSession('/map', { activity: "Visited Analysis Page"}, data);

} else if (data.landscape && data.analysisType === Types.TEMPORAL) {
if (data.temporalResolution === TemporalResolution.ANNUAL && data.period?.year && data.comparisonPeriod?.year) {
setMapInteraction(MapAnalysisInteraction.LANDSCAPE_SELECTOR)
saveSession('/map', { activity: "Visited Analysis Page"}, data);
setMapInteraction(MapAnalysisInteraction.LANDSCAPE_SELECTOR);
} else if (data.temporalResolution === TemporalResolution.QUARTERLY && data.period?.year
&& data.period?.quarter && data.comparisonPeriod?.year && data.comparisonPeriod?.quarter) {
setMapInteraction(MapAnalysisInteraction.LANDSCAPE_SELECTOR)
saveSession('/map', { activity: "Visited Analysis Page"}, data);
} else {
setMapInteraction(MapAnalysisInteraction.NO_INTERACTION)
saveSession('/map', { activity: "Visited Analysis Page"}, data);
}
saveSession('/map', { activity: "Visited Analysis Page"}, data);
} else if (data.landscape && data.analysisType === Types.SPATIAL) {
if (mapInteraction === MapAnalysisInteraction.NO_INTERACTION && data.reference_layer && data.variable) {
if (mapInteraction === MapAnalysisInteraction.NO_INTERACTION && data.reference_layer && data.variable && data.latitude === null && data.longitude === null) {
// trigger relative layer diff
dispatch(doAnalysis(data))
saveSession('/map', { activity: "Visited Analysis Page"}, data);
} else if (mapInteraction === MapAnalysisInteraction.LANDSCAPE_SELECTOR && !data.reference_layer) {
setMapInteraction(MapAnalysisInteraction.NO_INTERACTION)
}
saveSession('/map', { activity: "Visited Analysis Page"}, data);
}

}, [mapInteraction, data])

useEffect(() => {
Expand Down Expand Up @@ -184,7 +195,7 @@ export default function Analysis({ landscapes, layers, onLayerChecked, onLayerUn
dataError = false
}
} else if (
data.landscape && data.analysisType === Types.SPATIAL && data.variable && data.reference_layer !== null
data.landscape && data.analysisType === Types.SPATIAL && data.variable && data.reference_layer
) {
dataError = false
}
Expand All @@ -196,7 +207,6 @@ export default function Analysis({ landscapes, layers, onLayerChecked, onLayerUn
disableSubmit = true;
}


return (
<Box fontSize='13px'>
<Accordion allowMultiple defaultIndex={[0, 1, 2, 3, 4, 5]}>
Expand All @@ -211,11 +221,22 @@ export default function Analysis({ landscapes, layers, onLayerChecked, onLayerUn
/>
<AnalysisLandscapeGeometrySelector
landscape={landscapes.find(landscape => landscape.name === data.landscape)}
featureId={data.communityFeatureId}
enableSelection={mapInteraction === MapAnalysisInteraction.LANDSCAPE_SELECTOR}
onSelected={(value) => setCommunitySelected(value)}
onSelected={(value) => {
setData({
...data,
community: value?.id ? '' + value?.id : null,
latitude: value?.latitude ? value?.latitude : null,
longitude: value?.longitude ? value?.longitude : null,
communityName: value?.name ? value?.name : null,
communityFeatureId: value?.featureId ? value?.featureId : null
})
}
}
/>
<AnalysisCustomGeometrySelector
ref={geometrySelectorRef}
ref={geometrySelectorRef}
isDrawing={mapInteraction === MapAnalysisInteraction.CUSTOM_GEOMETRY_DRAWING}
onSelected={(geometry, area) => {
if (area > mapConfig.spatial_reference_layer_max_area) {
Expand Down Expand Up @@ -290,9 +311,10 @@ export default function Analysis({ landscapes, layers, onLayerChecked, onLayerUn
reference_layer: null,
community: null,
latitude: null,
longitude: null
longitude: null,
communityName: null,
communityFeatureId: null
})
setCommunitySelected(null)
setMapInteraction(MapAnalysisInteraction.CUSTOM_GEOMETRY_DRAWING)
dispatch(resetAnalysisResult())
}}
Expand Down Expand Up @@ -417,8 +439,8 @@ export default function Analysis({ landscapes, layers, onLayerChecked, onLayerUn
!dataError ?
<Box mb={4} color={'green'}>
Click polygons on the
map {communitySelected ?
<Box>{communitySelected.name}</Box> : null}
map {data?.communityName ?
<Box>{data?.communityName}</Box> : null}
</Box> :
null
}
Expand All @@ -434,10 +456,10 @@ export default function Analysis({ landscapes, layers, onLayerChecked, onLayerUn
disabled={loading}
onClick={() => {
setData({ analysisType: Types.BASELINE });
setCommunitySelected(null);
setMapInteraction(MapAnalysisInteraction.NO_INTERACTION);
geometrySelectorRef?.current?.removeLayer();
dispatch(resetAnalysisResult());
saveSession('/map', { activity: "Visited Analysis Page"}, { analysisType: Types.BASELINE });
}}
>
Reset Form
Expand Down
Loading
Loading