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 AA layer loading mechanism #1400

Draft
wants to merge 34 commits into
base: feat/display-panel-AA-storm
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
889f3fb
centralize data fetch in state for AA storm
Doniaab Dec 11, 2024
077f4b1
fix conflicts
Doniaab Dec 11, 2024
f0eec72
fix landfall severity
Doniaab Dec 11, 2024
d29a4f7
Add riskArea
ericboucher Dec 11, 2024
9251dcb
Update index.tsx
ericboucher Dec 11, 2024
5304913
add storm date and name panel
Doniaab Dec 11, 2024
d07cad6
Merge branch 'fetch-data-in-state' of github.com:WFP-VAM/prism-app in…
Doniaab Dec 11, 2024
b48b029
Update index.test.tsx.snap
ericboucher Dec 11, 2024
11e45b7
Merge branch 'fetch-data-in-state' of https://github.com/WFP-VAM/pris…
ericboucher Dec 11, 2024
fc14085
Update utils.ts
ericboucher Dec 11, 2024
c4a776a
Use reference time from the file
ericboucher Dec 11, 2024
ce222e5
Fix missing landfall
ericboucher Dec 11, 2024
587cb9a
Fix timeline shift
ericboucher Dec 11, 2024
851163b
Update index.tsx
ericboucher Dec 11, 2024
d492c6d
Update index.tsx
ericboucher Dec 11, 2024
affcd01
Fix active and NA titles
ericboucher Dec 11, 2024
0a07f33
updated select style in panel
Doniaab Dec 12, 2024
9eb498e
fix review
Doniaab Dec 12, 2024
4d70728
fix risks data and add fill color by categories
Doniaab Dec 12, 2024
960df43
show na districts fill on map
Doniaab Dec 12, 2024
e00144e
add time with date in panel
Doniaab Dec 12, 2024
ba55d78
fix undefined panel wind
Doniaab Dec 12, 2024
12e4758
fix fill color district
Doniaab Dec 12, 2024
c4b0ff0
fix date with hour in panel
Doniaab Dec 12, 2024
12a215a
fix load AA layer from url or on reload page WIP
Doniaab Dec 12, 2024
3847acc
Tentative cleanup
ericboucher Dec 13, 2024
9159c37
try to fix aa loading
Doniaab Dec 13, 2024
bd3b171
fix loading mechanism
Doniaab Dec 19, 2024
3c72fca
fix conflicts
Doniaab Dec 20, 2024
aba4b50
fix load apply custom date
Doniaab Dec 20, 2024
9577354
fix lint
Doniaab Dec 20, 2024
bdc3ab7
fix glitch due to over rendering
Doniaab Dec 20, 2024
53a1f23
fix lint
Doniaab Dec 20, 2024
81847b0
fix dates load
Doniaab Dec 21, 2024
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
102 changes: 70 additions & 32 deletions frontend/src/components/MapView/DateSelector/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ import { format } from 'date-fns';
import { leftPanelTabValueSelector } from 'context/leftPanelStateSlice';
import { updateDateRange } from 'context/mapStateSlice';
import { getRequestDate } from 'utils/server-utils';
import { AAAvailableDatesSelector } from 'context/anticipatoryAction/AADroughtStateSlice';
import { isAnticipatoryActionLayer, isWindowedDates } from 'config/utils';
import { getAAConfig } from 'context/anticipatoryAction/config';
import { RootState } from 'context/store';
import TickSvg from './tick.svg';
import DateSelectorInput from './DateSelectorInput';
import TimelineItems from './TimelineItems';
Expand All @@ -59,7 +61,9 @@ const calculateStartAndEndDates = (startDate: Date, selectedTab: string) => {
(selectedTab === Panel.AnticipatoryActionDrought && startDate.getMonth() < 3
? 1
: 0);
const startMonth = selectedTab === Panel.AnticipatoryActionDrought ? 3 : 0; // April for anticipatory_action, January otherwise

const startMonth = isAnticipatoryActionLayer(selectedTab) ? 3 : 0; // April for anticipatory_action, January otherwise

const start = new Date(year, startMonth, 1);
const end = new Date(year, startMonth + 11, 31);

Expand Down Expand Up @@ -119,32 +123,56 @@ const DateSelector = memo(() => {
[availableDates],
);

const AAAvailableDates = useSelector(AAAvailableDatesSelector);
const AAConfig = useMemo(() => {
const anticipatoryLayer = selectedLayers.find(layer =>
isAnticipatoryActionLayer(layer.type),
);
if (anticipatoryLayer) {
return getAAConfig(anticipatoryLayer.type as AnticipatoryAction);
}
return null;
}, [selectedLayers]);

// Create a temporary layer for each AA window
const AALayers: DateCompatibleLayerWithDateItems[] = useMemo(
() =>
AAAvailableDates
? [
{
id: 'anticipatory_action_window_1',
title: 'Window 1',
dateItems: AAAvailableDates['Window 1'],
type: AnticipatoryAction.drought,
opacity: 1,
},
{
id: 'anticipatory_action_window_2',
title: 'Window 2',
dateItems: AAAvailableDates['Window 2'],
type: AnticipatoryAction.drought,
opacity: 1,
},
]
: [],
[AAAvailableDates],
const AAAvailableDates = useSelector((state: RootState) =>
AAConfig ? AAConfig.availableDatesSelector(state) : null,
);

// Create a temporary layer for each AA window
const AALayers: DateCompatibleLayerWithDateItems[] = useMemo(() => {
if (!AAAvailableDates) {
return [];
}

if (isWindowedDates(AAAvailableDates)) {
return [
{
id: 'anticipatory_action_window_1',
title: 'Window 1',
dateItems: AAAvailableDates['Window 1'],
type: AnticipatoryAction.drought,
opacity: 1,
},
{
id: 'anticipatory_action_window_2',
title: 'Window 2',
dateItems: AAAvailableDates['Window 2'],
type: AnticipatoryAction.drought,
opacity: 1,
},
];
}

return [
{
id: 'anticipatory_action_storm',
title: 'Anticipatory Action Storm',
dateItems: AAAvailableDates,
type: AnticipatoryAction.storm,
opacity: 1,
},
];
}, [AAAvailableDates]);

// Replace anticipatory action unique layer by window1 and window2 layers
// Keep anticipatory actions at the top of the timeline
const orderedLayers: DateCompatibleLayerWithDateItems[] = useMemo(
Expand All @@ -162,7 +190,12 @@ const DateSelector = memo(() => {
}
return 0;
})
.map(l => (l.id === 'anticipatory_action_drought' ? AALayers : l))
.map(layer => {
if (isAnticipatoryActionLayer(layer.type)) {
return AALayers.filter(al => al.type === layer.type);
}
return layer;
})
.flat(),
[selectedLayers, AALayers],
);
Expand Down Expand Up @@ -337,12 +370,17 @@ const DateSelector = memo(() => {
);

// All dates in AA windows should be selectable, regardless of overlap
if (panelTab === Panel.AnticipatoryActionDrought && AAAvailableDates) {
// eslint-disable-next-line fp/no-mutating-methods
dates.push(
AAAvailableDates?.['Window 1']?.map(d => d.displayDate) ?? [],
AAAvailableDates?.['Window 2']?.map(d => d.displayDate) ?? [],
);
if (isAnticipatoryActionLayer(panelTab) && AAAvailableDates) {
if (isWindowedDates(AAAvailableDates)) {
// eslint-disable-next-line fp/no-mutating-methods
dates.push(
AAAvailableDates?.['Window 1']?.map(d => d.displayDate) ?? [],
AAAvailableDates?.['Window 2']?.map(d => d.displayDate) ?? [],
);
} else {
// eslint-disable-next-line fp/no-mutating-methods
dates.push(AAAvailableDates?.map(d => d.displayDate) ?? []);
}

// eslint-disable-next-line fp/no-mutating-methods
return dates
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const AnticipatoryActionStormLayer = React.memo(
useDefaultDate(layer.id);
const map = useSelector(mapSelector);
const { viewType, selectedDate } = useSelector(AAFiltersSelector);
const AAStormData = useSelector(AADataSelector);
const stormData = useSelector(AADataSelector);
const boundaryLayerState = useSelector(
layerDataSelector(boundaryLayer.id),
) as LayerData<BoundaryLayerProps> | undefined;
Expand Down Expand Up @@ -117,8 +117,8 @@ const AnticipatoryActionStormLayer = React.memo(
}

const timeSeries: any =
AAStormData && AAStormData.timeSeries
? enhanceTimeSeries(AAStormData.timeSeries as unknown as TimeSeries)
stormData && stormData.timeSeries
? enhanceTimeSeries(stormData.timeSeries as unknown as TimeSeries)
: null;

function getIconNameByWindType(windType: string) {
Expand Down Expand Up @@ -249,7 +249,7 @@ const AnticipatoryActionStormLayer = React.memo(
.map(feature => {
const districtName =
feature.properties?.[boundaryLayer.adminLevelLocalNames[1]];
const colorInfo = getDistrictColor(districtName, AAStormData);
const colorInfo = getDistrictColor(districtName, stormData);

if (!colorInfo) {
return null;
Expand All @@ -266,9 +266,9 @@ const AnticipatoryActionStormLayer = React.memo(
})
.filter(Boolean),
};
}, [boundaryData, AAStormData]);
}, [boundaryData, stormData]);

if (!boundaryData || !AAStormData) {
if (!boundaryData || !stormData) {
return null;
}

Expand Down Expand Up @@ -305,7 +305,7 @@ const AnticipatoryActionStormLayer = React.memo(
{viewType === 'forecast' && (
<>
<Source
data={AAStormData.activeDistricts?.Moderate?.polygon}
data={stormData.activeDistricts?.Moderate?.polygon}
type="geojson"
>
<Layer
Expand All @@ -320,7 +320,7 @@ const AnticipatoryActionStormLayer = React.memo(
/>
</Source>
<Source
data={AAStormData.activeDistricts?.Severe?.polygon}
data={stormData.activeDistricts?.Severe?.polygon}
type="geojson"
>
<Layer
Expand All @@ -340,7 +340,7 @@ const AnticipatoryActionStormLayer = React.memo(
{/* Storm Risk Map view */}
{viewType === 'risk' && (
<Source
data={AAStormData.activeDistricts?.Risk?.polygon}
data={stormData.activeDistricts?.Risk?.polygon}
type="geojson"
>
<Layer
Expand Down Expand Up @@ -386,11 +386,11 @@ const AnticipatoryActionStormLayer = React.memo(

<AAStormDatePopup />

{selectedFeature && AAStormData.landfall && selectedDate && (
{selectedFeature && stormData.landfall && selectedDate && (
<AAStormLandfallPopup
point={selectedFeature.geometry}
reportDate={selectedFeature.properties?.time}
landfallInfo={AAStormData.landfall}
landfallInfo={stormData.landfall}
onClose={() => landfallPopupCloseHandler()}
timelineDate={selectedDate}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ import {
} from 'context/anticipatoryAction/AADroughtStateSlice/types';
import { AAWindowKeys } from 'config/utils';
import {
AAAvailableDatesSelector,
AADataSelector,
AAFiltersSelector,
AAMonitoredDistrictsSelector,
AASelectedDistrictSelector,
Expand All @@ -32,20 +30,16 @@ import {
setAAView,
} from 'context/anticipatoryAction/AADroughtStateSlice';
import { dateRangeSelector } from 'context/mapStateSlice/selectors';
import {
getAAAvailableDatesCombined,
getRequestDate,
} from 'utils/server-utils';
import { getFormattedDate } from 'utils/date-utils';
import { DateFormat } from 'utils/name-utils';
import { PanelSize } from 'config/types';
import { AnticipatoryAction, PanelSize } from 'config/types';
import { StyledCheckboxLabel, StyledRadioLabel } from './utils';
import { StyledSelect } from '../utils';
import DistrictView from './DistrictView/index';
import HomeTable from './HomeTable';
import HowToReadModal from '../HowToReadModal';
import Timeline from './Timeline';
import Forecast from './Forecast';
import { useAnticipatoryAction } from '../useAnticipatoryAction';

const isZimbabwe = safeCountry === 'zimbabwe';

Expand All @@ -67,13 +61,12 @@ function AnticipatoryActionDroughtPanel() {
const classes = useStyles();
const dispatch = useDispatch();
const { t } = useSafeTranslation();
const { AAData } = useAnticipatoryAction(AnticipatoryAction.drought);
const monitoredDistricts = useSelector(AAMonitoredDistrictsSelector);
const AAAvailableDates = useSelector(AAAvailableDatesSelector);
const selectedDistrict = useSelector(AASelectedDistrictSelector);
const { categories: categoryFilters, selectedIndex } =
useSelector(AAFiltersSelector);
const { startDate: selectedDate } = useSelector(dateRangeSelector);
const aaData = useSelector(AADataSelector);
const view = useSelector(AAViewSelector);
const [indexOptions, setIndexOptions] = React.useState<string[]>([]);
const [howToReadModalOpen, setHowToReadModalOpen] = React.useState(false);
Expand All @@ -89,25 +82,14 @@ function AnticipatoryActionDroughtPanel() {
if (!selectedDistrict) {
return;
}
const entries = Object.values(aaData)
const entries = Object.values(AAData)
.map(x => x[selectedDistrict])
.flat()
.filter(x => x);

const options = [...new Set(entries.map(x => x.index))];
setIndexOptions(options);
}, [aaData, selectedDistrict]);

const layerAvailableDates =
AAAvailableDates !== undefined
? getAAAvailableDatesCombined(AAAvailableDates)
: [];
const queryDate = getRequestDate(layerAvailableDates, selectedDate);
const date = getFormattedDate(queryDate, DateFormat.Default) as string;

React.useEffect(() => {
dispatch(setAAFilters({ selectedDate: date }));
}, [date, dispatch]);
}, [AAData, selectedDistrict]);

return (
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,27 @@ import {
import React from 'react';
import { useSafeTranslation } from 'i18n';
import { useDispatch, useSelector } from 'react-redux';
import {
AAAvailableDatesSelector,
AADataSelector,
setAAFilters,
} from 'context/anticipatoryAction/AAStormStateSlice';
import { PanelSize } from 'config/types';
import { updateDateRange } from 'context/mapStateSlice';
import { useDefaultDate } from 'utils/useDefaultDate';
import { setAAFilters } from 'context/anticipatoryAction/AAStormStateSlice';
import { AnticipatoryAction, PanelSize } from 'config/types';
import { getFormattedDate } from 'utils/date-utils';
import { getRequestDate } from 'utils/server-utils';
import { DateFormat } from 'utils/name-utils';
import { dateRangeSelector } from 'context/mapStateSlice/selectors';
import HowToReadModal from '../HowToReadModal';
import ActivationTrigger from './ActivationTriggerView';
import { StyledSelect } from '../utils';
import { useAnticipatoryAction } from '../useAnticipatoryAction';

function AnticipatoryActionStormPanel() {
const classes = useStyles();
const dispatch = useDispatch();
const { t } = useSafeTranslation();
const AAAvailableDates = useSelector(AAAvailableDatesSelector);
const AAData = useSelector(AADataSelector);
const { AAData, AAAvailableDates } = useAnticipatoryAction(
AnticipatoryAction.storm,
);
const [howToReadModalOpen, setHowToReadModalOpen] = React.useState(false);

const selectedDate = useDefaultDate('anticipatory_action_storm');
const { startDate: selectedDate } = useSelector(dateRangeSelector);

const [viewType, setViewType] = React.useState<'forecast' | 'risk'>(
'forecast',
Expand All @@ -49,15 +46,10 @@ function AnticipatoryActionStormPanel() {
dispatch(
setAAFilters({
viewType,
selectedDate: getFormattedDate(selectedDate, 'default'),
}),
);
dispatch(updateDateRange({ startDate: selectedDate }));
}, [viewType, selectedDate, dispatch]);

if (!selectedDate) {
return null;
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [viewType]);

return (
<div
Expand Down
Loading
Loading