Skip to content

Commit

Permalink
Add orgUnits in app context to use them in maps
Browse files Browse the repository at this point in the history
  • Loading branch information
anagperal committed Sep 12, 2024
1 parent a620d36 commit f77b8af
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 38 deletions.
2 changes: 2 additions & 0 deletions src/CompositionRoot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { MapConfigD2Repository } from "./data/repositories/MapConfigD2Repository
import { MapConfigTestRepository } from "./data/repositories/test/MapConfigTestRepository";
import { GetMapConfigUseCase } from "./domain/usecases/GetMapConfigUseCase";
import { GetProvincesOrgUnits } from "./domain/usecases/GetProvincesOrgUnits";
import { GetAllOrgUnits } from "./domain/usecases/GetAllOrgUnits";

export type CompositionRoot = ReturnType<typeof getCompositionRoot>;

Expand Down Expand Up @@ -61,6 +62,7 @@ function getCompositionRoot(repositories: Repositories) {
getConfig: new GetMapConfigUseCase(repositories.mapConfigRepository),
},
orgUnits: {
getAll: new GetAllOrgUnits(repositories.orgUnitRepository),
getProvinces: new GetProvincesOrgUnits(repositories.orgUnitRepository),
},
};
Expand Down
11 changes: 11 additions & 0 deletions src/domain/usecases/GetAllOrgUnits.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { FutureData } from "../../data/api-futures";
import { OrgUnit } from "../entities/OrgUnit";
import { OrgUnitRepository } from "../repositories/OrgUnitRepository";

export class GetAllOrgUnits {
constructor(private orgUnitRepository: OrgUnitRepository) {}

public execute(): FutureData<OrgUnit[]> {
return this.orgUnitRepository.getAll();
}
}
1 change: 1 addition & 0 deletions src/utils/tests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export function getTestContext() {
currentUser: createAdminUser(),
compositionRoot: getTestCompositionRoot(),
api: {} as D2Api,
orgUnits: [],
isDev: true,
};

Expand Down
2 changes: 2 additions & 0 deletions src/webapp/contexts/app-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import React, { useContext } from "react";
import { CompositionRoot } from "../../CompositionRoot";
import { User } from "../../domain/entities/User";
import { D2Api } from "../../types/d2-api";
import { OrgUnit } from "../../domain/entities/OrgUnit";

export interface AppContextState {
api: D2Api;
isDev: boolean;
currentUser: User;
compositionRoot: CompositionRoot;
orgUnits: OrgUnit[];
}

export const AppContext = React.createContext<AppContextState | null>(null);
Expand Down
4 changes: 2 additions & 2 deletions src/webapp/pages/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ function App(props: AppProps) {
const isShareButtonVisible = appConfig.appearance.showShareButton;
const currentUser = await compositionRoot.users.getCurrent.execute().toPromise();
if (!currentUser) throw new Error("User not logged in");

const orgUnits = await compositionRoot.orgUnits.getAll.execute().toPromise();
const isDev = process.env.NODE_ENV === "development";
setAppContext({ currentUser, compositionRoot, isDev, api });
setAppContext({ currentUser, compositionRoot, isDev, api, orgUnits });
setShowShareButton(isShareButtonVisible);
setLoading(false);
}
Expand Down
11 changes: 1 addition & 10 deletions src/webapp/pages/dashboard/DashboardPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useMemo } from "react";
import React from "react";

import i18n from "../../../utils/i18n";
import { Layout } from "../../components/layout/Layout";
Expand Down Expand Up @@ -71,14 +71,6 @@ export const DashboardPage: React.FC = React.memo(() => {
},
];

const allProvinceOptionsIds = useMemo(
() =>
filtersConfig
.find(filter => filter.id === "province")
?.options.map(option => option.value),
[filtersConfig]
);

return (
<Layout title={i18n.t("Dashboard")} showCreateEvent>
<Section title={i18n.t("Respond, alert, watch")}>
Expand Down Expand Up @@ -130,7 +122,6 @@ export const DashboardPage: React.FC = React.memo(() => {
mapKey="dashboard"
singleSelectFilters={singleSelectFilters}
multiSelectFilters={multiSelectFilters}
allProvinces={allProvinceOptionsIds}
/>
</Section>
<Section title={i18n.t("7-1-7 performance")}>
Expand Down
27 changes: 16 additions & 11 deletions src/webapp/pages/dashboard/map/MapSection.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,36 @@
import React, { useEffect } from "react";
import React, { useEffect, useMemo } from "react";
import styled from "styled-components";
import { useSnackbar } from "@eyeseetea/d2-ui-components";

import { Map } from "../../../components/map/Map";
import { useMap } from "./useMap";
import { MapKey } from "../../../../domain/entities/MapConfig";
import LoaderContainer from "../../../components/loader/LoaderContainer";
import { Maybe } from "../../../../utils/ts-utils";
import { useAppContext } from "../../../contexts/app-context";

type MapSectionProps = {
mapKey: MapKey;
singleSelectFilters?: Record<string, string>;
multiSelectFilters?: Record<string, string[]>;
allProvinces: Maybe<string[]>;
};

export const MapSection: React.FC<MapSectionProps> = React.memo(props => {
const { mapKey, singleSelectFilters, multiSelectFilters, allProvinces } = props;
const { mapKey, singleSelectFilters, multiSelectFilters } = props;
const { orgUnits } = useAppContext();
const snackbar = useSnackbar();

const { mapConfigState } = useMap(
mapKey,
allProvinces,
singleSelectFilters,
multiSelectFilters
const allProvincesIds = useMemo(
() => orgUnits.filter(orgUnit => orgUnit.level === "Province").map(orgUnit => orgUnit.id),
[orgUnits]
);

const { mapConfigState } = useMap({
mapKey: mapKey,
allOrgUnitsIds: allProvincesIds,
singleSelectFilters: singleSelectFilters,
multiSelectFilters: multiSelectFilters,
});

useEffect(() => {
if (mapConfigState.kind === "error") {
snackbar.error(mapConfigState.message);
Expand All @@ -39,9 +44,9 @@ export const MapSection: React.FC<MapSectionProps> = React.memo(props => {
return (
<MapContainer>
<LoaderContainer
loading={mapConfigState.kind === "loading" || allProvinces?.length === 0}
loading={mapConfigState.kind === "loading" || allProvincesIds.length === 0}
>
{mapConfigState.kind === "loaded" && allProvinces?.length !== 0 ? (
{mapConfigState.kind === "loaded" && allProvincesIds.length !== 0 ? (
<Map
key={`${JSON.stringify(singleSelectFilters)}_${JSON.stringify(
multiSelectFilters
Expand Down
27 changes: 12 additions & 15 deletions src/webapp/pages/dashboard/map/useMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@ type MapState = {
mapConfigState: MapConfigState;
};

export function useMap(
mapKey: MapKey,
allOrgUnitsIds: Maybe<string[]>,
singleSelectFilters?: Record<string, string>,
multiSelectFilters?: Record<string, string[]>
): MapState {
export function useMap(params: {
mapKey: MapKey;
allOrgUnitsIds: string[];
singleSelectFilters?: Record<string, string>;
multiSelectFilters?: Record<string, string[]>;
}): MapState {
const { mapKey, allOrgUnitsIds, singleSelectFilters, multiSelectFilters } = params;
const { compositionRoot } = useAppContext();
const [mapProgramIndicators, setMapProgramIndicators] = useState<MapProgramIndicator[]>([]);
const [mapConfigState, setMapConfigState] = useState<MapConfigState>({
Expand All @@ -59,7 +60,7 @@ export function useMap(
useEffect(() => {
if (
mapConfigState.kind === "loaded" &&
allOrgUnitsIds?.length &&
allOrgUnitsIds.length &&
(!!singleSelectFilters || !!multiSelectFilters)
) {
const mapProgramIndicator = getFilteredMapProgramIndicator(
Expand All @@ -71,7 +72,7 @@ export function useMap(
if (
multiSelectFilters &&
multiSelectFilters?.province?.length &&
provincesHaveChanged(multiSelectFilters?.province, mapConfigState.data.orgUnits)
orgUnitsHaveChanged(multiSelectFilters?.province, mapConfigState.data.orgUnits)
) {
const provinceFilterValues = multiSelectFilters.province;
setMapConfigState(prevMapConfigState => {
Expand All @@ -90,7 +91,7 @@ export function useMap(
return;
} else if (
!multiSelectFilters?.province?.length &&
provincesHaveChanged(allOrgUnitsIds, mapConfigState.data.orgUnits)
orgUnitsHaveChanged(allOrgUnitsIds, mapConfigState.data.orgUnits)
) {
setMapConfigState(prevMapConfigState => {
if (prevMapConfigState.kind === "loaded") {
Expand Down Expand Up @@ -152,18 +153,14 @@ export function useMap(

const mapProgramIndicator = getMainMapProgramIndicator(config.programIndicators);

if (!mapProgramIndicator) {
if (!mapProgramIndicator || allOrgUnitsIds.length === 0) {
setMapConfigState({
kind: "error",
message: i18n.t("Map not found."),
});
return;
}

if (!allOrgUnitsIds || allOrgUnitsIds.length === 0) {
return;
}

setMapConfigState({
kind: "loaded",
data: {
Expand Down Expand Up @@ -257,7 +254,7 @@ function getFilteredMapProgramIndicator(
}
}

function provincesHaveChanged(provincesFilter: string[], currentOrgUnits: string[]): boolean {
function orgUnitsHaveChanged(provincesFilter: string[], currentOrgUnits: string[]): boolean {
if (provincesFilter.length !== currentOrgUnits.length) {
return true;
}
Expand Down

0 comments on commit f77b8af

Please sign in to comment.