Skip to content

Commit

Permalink
fix: do not show existing diseases and hazard in create event dropdown
Browse files Browse the repository at this point in the history
  • Loading branch information
9sneha-n committed Oct 31, 2024
1 parent eca4afa commit d8d4d41
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 46 deletions.
14 changes: 7 additions & 7 deletions src/webapp/contexts/CurrentEventTrackerProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { PropsWithChildren, useState } from "react";
import { PropsWithChildren, useCallback, useState } from "react";
import { CurrentEventTrackerContext } from "./current-event-tracker-context";
import { DiseaseOutbreakEvent } from "../../domain/entities/disease-outbreak-event/DiseaseOutbreakEvent";
import { Maybe } from "../../utils/ts-utils";

export const CurrentEventTrackerContextProvider: React.FC<PropsWithChildren> = ({ children }) => {
const [currentEventTracker, setCurrentEventTracker] = useState<DiseaseOutbreakEvent>();

const changeCurrentEventTracker = (EventTrackerDetails: DiseaseOutbreakEvent) => {
const changeCurrentEventTracker = useCallback((EventTrackerDetails: DiseaseOutbreakEvent) => {
setCurrentEventTracker(EventTrackerDetails);
localStorage.setItem("currentEventTracker", JSON.stringify(EventTrackerDetails));
};
const resetCurrentEventTracker = () => {
}, []);
const resetCurrentEventTracker = useCallback(() => {
setCurrentEventTracker(undefined);
localStorage.removeItem("currentEventTracker");
};
}, []);

const getCurrentEventTracker = (): Maybe<DiseaseOutbreakEvent> => {
const getCurrentEventTracker = useCallback((): Maybe<DiseaseOutbreakEvent> => {
if (currentEventTracker) {
return currentEventTracker;
}
Expand All @@ -24,7 +24,7 @@ export const CurrentEventTrackerContextProvider: React.FC<PropsWithChildren> = (
return JSON.parse(localCurrentEventTracker);
}
return undefined;
};
}, [currentEventTracker]);

return (
<CurrentEventTrackerContext.Provider
Expand Down
30 changes: 30 additions & 0 deletions src/webapp/contexts/ExistingEventTrackerTypes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { PropsWithChildren, useCallback, useState } from "react";
import {
DiseaseNames,
HazardNames,
} from "../../domain/entities/disease-outbreak-event/PerformanceOverviewMetrics";
import { ExistingEventTrackerTypesContext } from "./existing-event-tracker-types-context";

export const ExistingEventTrackerTypesProvider: React.FC<PropsWithChildren> = ({ children }) => {
const [existingEventTrackerTypes, setExistingEventTrackerTypes] = useState<
(DiseaseNames | HazardNames)[]
>([]);

const changeExistingEventTrackerTypes = useCallback(
(updatedExistingEventTrackerTypes: (DiseaseNames | HazardNames)[]) => {
setExistingEventTrackerTypes(updatedExistingEventTrackerTypes);
},
[]
);

return (
<ExistingEventTrackerTypesContext.Provider
value={{
existingEventTrackerTypes,
changeExistingEventTrackerTypes,
}}
>
{children}
</ExistingEventTrackerTypesContext.Provider>
);
};
26 changes: 26 additions & 0 deletions src/webapp/contexts/existing-event-tracker-types-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { createContext, useContext } from "react";
import {
DiseaseNames,
HazardNames,
} from "../../domain/entities/disease-outbreak-event/PerformanceOverviewMetrics";

export interface ExistingEventTrackerTypesProps {
existingEventTrackerTypes: (DiseaseNames | HazardNames)[];
changeExistingEventTrackerTypes: (
existingEventTrackerTypes: (DiseaseNames | HazardNames)[]
) => void;
}

export const ExistingEventTrackerTypesContext = createContext<ExistingEventTrackerTypesProps>({
existingEventTrackerTypes: [],
changeExistingEventTrackerTypes: () => {},
});

export function useExistingEventTrackerTypes() {
const context = useContext(ExistingEventTrackerTypesContext);
if (context) {
return context;
} else {
throw new Error("Existing Event Tracker Types context uninitialized");
}
}
5 changes: 4 additions & 1 deletion src/webapp/pages/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { HeaderBar } from "../../components/layout/header-bar/HeaderBar";
import { D2Api } from "../../../types/d2-api";
import "./App.css";
import { CurrentEventTrackerContextProvider } from "../../contexts/CurrentEventTrackerProvider";
import { ExistingEventTrackerTypesProvider } from "../../contexts/ExistingEventTrackerTypes";

export interface AppProps {
compositionRoot: CompositionRoot;
Expand Down Expand Up @@ -73,7 +74,9 @@ function App(props: AppProps) {
<div id="app" className="content">
<AppContext.Provider value={appContext}>
<CurrentEventTrackerContextProvider>
<Router />
<ExistingEventTrackerTypesProvider>
<Router />
</ExistingEventTrackerTypesProvider>
</CurrentEventTrackerContextProvider>
</AppContext.Provider>
</div>
Expand Down
63 changes: 37 additions & 26 deletions src/webapp/pages/dashboard/usePerformanceOverview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { FiltersConfig, TableColumn } from "../../components/table/statistic-tab
import { Maybe } from "../../../utils/ts-utils";
import { PerformanceOverviewMetrics } from "../../../domain/entities/disease-outbreak-event/PerformanceOverviewMetrics";
import { NationalIncidentStatus } from "../../../domain/entities/disease-outbreak-event/DiseaseOutbreakEvent";
import { useExistingEventTrackerTypes } from "../../contexts/existing-event-tracker-types-context";

type State = {
columns: TableColumn[];
Expand All @@ -27,28 +28,7 @@ export function usePerformanceOverview(): State {
>([]);
const [isLoading, setIsLoading] = useState(false);
const [order, setOrder] = useState<Order>();

useEffect(() => {
if (dataPerformanceOverview.length && order) {
setDataPerformanceOverview(
(prevDataPerformanceOverview: PerformanceOverviewMetrics[]) => {
const newDataPerformanceOverview = _(prevDataPerformanceOverview)
.orderBy([
[
item =>
Number.isNaN(Number(item[order.name]))
? item[order.name]
: Number(item[order.name]),
order.direction,
],
])
.toArray();

return newDataPerformanceOverview;
}
);
}
}, [order, dataPerformanceOverview]);
const { changeExistingEventTrackerTypes } = useExistingEventTrackerTypes();

const getNationalIncidentStatusString = useCallback((status: string): string => {
switch (status as NationalIncidentStatus) {
Expand Down Expand Up @@ -77,12 +57,39 @@ export function usePerformanceOverview(): State {
},
[getNationalIncidentStatusString]
);

useEffect(() => {
if (dataPerformanceOverview.length && order) {
setDataPerformanceOverview(
(prevDataPerformanceOverview: PerformanceOverviewMetrics[]) => {
const newDataPerformanceOverview = _(prevDataPerformanceOverview)
.orderBy([
[
item =>
Number.isNaN(Number(item[order.name]))
? item[order.name]
: Number(item[order.name]),
order.direction,
],
])
.toArray();

return newDataPerformanceOverview;
}
);
}
}, [order, dataPerformanceOverview]);

useEffect(() => {
setIsLoading(true);
compositionRoot.performanceOverview.getPerformanceOverviewMetrics.execute().run(
programIndicators => {
const mappedData = programIndicators.map((data: PerformanceOverviewMetrics) =>
mapEntityToTableData(data)
performanceOverviewMetrics => {
const existingEventTrackerTypes = performanceOverviewMetrics.map(
metric => metric.suspectedDisease || metric.hazardType
);
changeExistingEventTrackerTypes(existingEventTrackerTypes);
const mappedData = performanceOverviewMetrics.map(
(data: PerformanceOverviewMetrics) => mapEntityToTableData(data)
);
setDataPerformanceOverview(mappedData);
setIsLoading(false);
Expand All @@ -92,7 +99,11 @@ export function usePerformanceOverview(): State {
setIsLoading(false);
}
);
}, [compositionRoot.performanceOverview.getPerformanceOverviewMetrics, mapEntityToTableData]);
}, [
changeExistingEventTrackerTypes,
compositionRoot.performanceOverview.getPerformanceOverviewMetrics,
mapEntityToTableData,
]);

const columns: TableColumn[] = [
{ label: "Event", value: "event" },
Expand Down
7 changes: 3 additions & 4 deletions src/webapp/pages/event-tracker/EventTrackerPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ export const EventTrackerPage: React.FC = React.memo(() => {
const { goTo } = useRoutes();
const { formSummary, summaryError, riskAssessmentRows, eventTrackerDetails } =
useDiseaseOutbreakEvent(id);
const { changeCurrentEventTracker: changeCurrentEventTrackerId, getCurrentEventTracker } =
useCurrentEventTracker();
const { changeCurrentEventTracker, getCurrentEventTracker } = useCurrentEventTracker();
const currentEventTracker = getCurrentEventTracker();
const { lastAnalyticsRuntime } = useLastAnalyticsRuntime();

Expand All @@ -67,9 +66,9 @@ export const EventTrackerPage: React.FC = React.memo(() => {

useEffect(() => {
if (eventTrackerDetails) {
changeCurrentEventTrackerId(eventTrackerDetails);
changeCurrentEventTracker(eventTrackerDetails);
}
}, [changeCurrentEventTrackerId, eventTrackerDetails]);
}, [changeCurrentEventTracker, eventTrackerDetails]);

return (
<Layout title={i18n.t("Event Tracker")} lastAnalyticsRuntime={lastAnalyticsRuntime}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import { FormState } from "../../../components/form/FormState";
import { User } from "../../../components/user-selector/UserSelector";
import { Option as PresentationOption } from "../../../components/utils/option";
import { mapToPresentationOptions } from "../mapEntityToFormState";
import {
DiseaseNames,
HazardNames,
} from "../../../../domain/entities/disease-outbreak-event/PerformanceOverviewMetrics";

export const diseaseOutbreakEventFieldIds = {
name: "name",
Expand Down Expand Up @@ -83,7 +87,8 @@ type ResponseActionsSubsectionKeys =
// TODO: Thinking for the future about generate this FormState by iterating over Object.Keys(diseaseOutbreakEvent)
export function mapDiseaseOutbreakEventToInitialFormState(
diseaseOutbreakEventWithOptions: DiseaseOutbreakEventFormData,
editMode: boolean
editMode: boolean,
existingEventTrackerTypes: (DiseaseNames | HazardNames)[]
): FormState {
const { entity: diseaseOutbreakEvent, options } = diseaseOutbreakEventWithOptions;
const {
Expand All @@ -96,13 +101,21 @@ export function mapDiseaseOutbreakEventToInitialFormState(
incidentStatus,
} = options;

const teamMemberOptions: User[] = incidentManagers.map(tm => mapTeamMemberToUser(tm));
//If An Event Tracker has already been created for a given suspected disease or harzd type,
//then do not allow to create another one. Remove it from dropwdown options
const filteredHazardTypes = hazardTypes.filter(hazardType => {
return !existingEventTrackerTypes.includes(hazardType.name as HazardNames);
});
const filteredSuspectedDiseases = suspectedDiseases.filter(suspectedDisease => {
return !existingEventTrackerTypes.includes(suspectedDisease.name as DiseaseNames);
});

const teamMemberOptions: User[] = incidentManagers.map(tm => mapTeamMemberToUser(tm));
const dataSourcesOptions: PresentationOption[] = mapToPresentationOptions(dataSources);
const hazardTypesOptions: PresentationOption[] = mapToPresentationOptions(hazardTypes);
const hazardTypesOptions: PresentationOption[] = mapToPresentationOptions(filteredHazardTypes);
const mainSyndromesOptions: PresentationOption[] = mapToPresentationOptions(mainSyndromes);
const suspectedDiseasesOptions: PresentationOption[] =
mapToPresentationOptions(suspectedDiseases);
mapToPresentationOptions(filteredSuspectedDiseases);
const notificationSourcesOptions: PresentationOption[] =
mapToPresentationOptions(notificationSources);
const incidentStatusOptions: PresentationOption[] = mapToPresentationOptions(incidentStatus);
Expand Down
13 changes: 11 additions & 2 deletions src/webapp/pages/form-page/mapEntityToFormState.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { ConfigurableForm } from "../../../domain/entities/ConfigurableForm";
import {
DiseaseNames,
HazardNames,
} from "../../../domain/entities/disease-outbreak-event/PerformanceOverviewMetrics";
import { TeamMember } from "../../../domain/entities/incident-management-team/TeamMember";
import { Option } from "../../../domain/entities/Ref";
import { FormState } from "../../components/form/FormState";
Expand All @@ -18,11 +22,16 @@ import {

export function mapEntityToFormState(
configurableForm: ConfigurableForm,
editMode?: boolean
editMode?: boolean,
existingEventTrackerTypes?: (DiseaseNames | HazardNames)[]
): FormState {
switch (configurableForm.type) {
case "disease-outbreak-event":
return mapDiseaseOutbreakEventToInitialFormState(configurableForm, editMode ?? false);
return mapDiseaseOutbreakEventToInitialFormState(
configurableForm,
editMode ?? false,
existingEventTrackerTypes ?? []
);
case "risk-assessment-grading":
return mapRiskGradingToInitialFormState(configurableForm);
case "risk-assessment-summary":
Expand Down
6 changes: 4 additions & 2 deletions src/webapp/pages/form-page/useForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
addNewResponseActionSection,
getAnotherResponseActionSection,
} from "./incident-action/mapIncidentActionToInitialFormState";
import { useExistingEventTrackerTypes } from "../../contexts/existing-event-tracker-types-context";

export type GlobalMessage = {
text: string;
Expand Down Expand Up @@ -65,6 +66,7 @@ export function useForm(formType: FormType, id?: Id): State {
const [formLabels, setFormLabels] = useState<FormLables>();
const [isLoading, setIsLoading] = useState(false);
const currentEventTracker = getCurrentEventTracker();
const { existingEventTrackerTypes } = useExistingEventTrackerTypes();

useEffect(() => {
compositionRoot.getConfigurableForm
Expand All @@ -75,7 +77,7 @@ export function useForm(formType: FormType, id?: Id): State {
setFormLabels(formData.labels);
setFormState({
kind: "loaded",
data: mapEntityToFormState(formData, !!id),
data: mapEntityToFormState(formData, !!id, existingEventTrackerTypes),
});
},
error => {
Expand All @@ -89,7 +91,7 @@ export function useForm(formType: FormType, id?: Id): State {
});
}
);
}, [compositionRoot.getConfigurableForm, formType, id, currentEventTracker, configurations]);
}, [compositionRoot.getConfigurableForm, formType, id, currentEventTracker, configurations, existingEventTrackerTypes]);

const handleAddNew = useCallback(() => {
if (formState.kind !== "loaded" || !configurableForm) return;
Expand Down

0 comments on commit d8d4d41

Please sign in to comment.