Skip to content

Commit

Permalink
Merge pull request #49 from EyeSeeTea/feature/717-indicators-alerts-c…
Browse files Browse the repository at this point in the history
…ards-dashboards

Create 717 Indicator Cards (Alerts) - Dashboard
  • Loading branch information
bhavananarayanan authored Jan 14, 2025
2 parents ce92dd2 + 398ca6a commit b23dbe5
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 100 deletions.
5 changes: 4 additions & 1 deletion i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,15 @@ msgstr ""
msgid "All public health events"
msgstr ""

msgid "7-1-7 performance"
msgid "Alerts 7-1-7 performance"
msgstr ""

msgid "events"
msgstr ""

msgid "7-1-7 performance"
msgstr ""

msgid "Performance overview"
msgstr ""

Expand Down
5 changes: 4 additions & 1 deletion i18n/es.po
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,15 @@ msgstr ""
msgid "All public health events"
msgstr ""

msgid "7-1-7 performance"
msgid "Alerts 7-1-7 performance"
msgstr ""

msgid "events"
msgstr ""

msgid "7-1-7 performance"
msgstr ""

msgid "Performance overview"
msgstr ""

Expand Down
179 changes: 105 additions & 74 deletions src/data/repositories/PerformanceOverviewD2Repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
DiseaseNames,
PerformanceMetrics717,
IncidentStatus,
PerformanceMetrics717Key,
} from "../../domain/entities/disease-outbreak-event/PerformanceOverviewMetrics";
import { Id } from "../../domain/entities/Ref";
import { OverviewCard } from "../../domain/entities/PerformanceOverview";
Expand All @@ -47,7 +48,12 @@ const ALERTS_PROGRAM_EVENT_TRACKER_OVERVIEW_DATASTORE_KEY =
"alerts-program-event-tracker-overview-ids";
const CASES_PROGRAM_EVENT_TRACKER_OVERVIEW_DATASTORE_KEY =
"cases-program-event-tracker-overview-ids";
const PERFORMANCE_717_PROGRAM_INDICATORS_DATASTORE_KEY = "717-performance-program-indicators";
const NATIONAL_PERFORMANCE_717_PROGRAM_INDICATORS_DATASTORE_KEY =
"national-717-performance-program-indicators";
const EVENT_TRACKER_PERFORMANCE_717_PROGRAM_INDICATORS_DATASTORE_KEY =
"event-tracker-717-performance-program-indicators";
const ALERTS_PERFORMANCE_717_PROGRAM_INDICATORS_DATASTORE_KEY =
"alerts-717-performance-program-indicators";
const PERFORMANCE_OVERVIEW_DIMENSIONS_DATASTORE_KEY = "performance-overview-dimensions";

type EventTrackerOverviewInDataStore = {
Expand Down Expand Up @@ -606,87 +612,112 @@ export class PerformanceOverviewD2Repository implements PerformanceOverviewRepos
.value();
}

getDashboard717Performance(): FutureData<PerformanceMetrics717[]> {
return this.datastore
.getObject<PerformanceMetrics717[]>(PERFORMANCE_717_PROGRAM_INDICATORS_DATASTORE_KEY)
.flatMap(nullable717PerformanceProgramIndicators => {
return assertOrError(
nullable717PerformanceProgramIndicators,
PERFORMANCE_717_PROGRAM_INDICATORS_DATASTORE_KEY
).flatMap(performance717ProgramIndicators => {
const dashboard717PerformanceIndicator = performance717ProgramIndicators.filter(
indicator => indicator.key === "dashboard"
getNational717Performance(): FutureData<PerformanceMetrics717[]> {
return this.get717PerformanceIndicators("national").flatMap(
performance717ProgramIndicators => {
return apiToFuture(
this.api.analytics.get({
dimension: [
`dx:${performance717ProgramIndicators.map(({ id }) => id).join(";")}`,
],
startDate: DEFAULT_START_DATE,
endDate: DEFAULT_END_DATE,
includeMetadataDetails: true,
})
).map(res => {
return this.mapIndicatorsTo717PerformanceMetrics(
res.rows,
performance717ProgramIndicators
);
return apiToFuture(
this.api.analytics.get({
dimension: [
`dx:${dashboard717PerformanceIndicator
.map(({ id }) => id)
.join(";")}`,
],
startDate: DEFAULT_START_DATE,
endDate: DEFAULT_END_DATE,
includeMetadataDetails: true,
})
).map(res => {
return this.mapIndicatorsTo717PerformanceMetrics(
res.rows,
dashboard717PerformanceIndicator
);
});
});
});
}
);
}

getEventTracker717Performance(diseaseOutbreakEventId: Id): FutureData<PerformanceMetrics717[]> {
return this.datastore
.getObject<PerformanceMetrics717[]>(PERFORMANCE_717_PROGRAM_INDICATORS_DATASTORE_KEY)
.flatMap(nullable717PerformanceProgramIndicators => {
return assertOrError(
nullable717PerformanceProgramIndicators,
PERFORMANCE_717_PROGRAM_INDICATORS_DATASTORE_KEY
).flatMap(performance717ProgramIndicators => {
const eventTracker717PerformanceIndicator =
performance717ProgramIndicators.filter(
indicator => indicator.key === "event_tracker"
);
return apiToFuture(
this.api.analytics.getEnrollmentsQuery({
programId: RTSL_ZEBRA_PROGRAM_ID,
dimension: [...eventTracker717PerformanceIndicator.map(({ id }) => id)],
startDate: DEFAULT_START_DATE,
endDate: DEFAULT_END_DATE,
})
).flatMap(response => {
const filteredRow = filterAnalyticsEnrollmentDataByDiseaseOutbreakEvent(
diseaseOutbreakEventId,
response.rows,
response.headers
);
getAlerts717Performance(): FutureData<PerformanceMetrics717[]> {
return this.get717PerformanceIndicators("alerts").flatMap(
performance717ProgramIndicators => {
return apiToFuture(
this.api.analytics.get({
dimension: [
`dx:${performance717ProgramIndicators.map(({ id }) => id).join(";")}`,
],
startDate: DEFAULT_START_DATE,
endDate: DEFAULT_END_DATE,
includeMetadataDetails: true,
})
).map(res => {
return this.mapIndicatorsTo717PerformanceMetrics(
res.rows,
performance717ProgramIndicators
);
});
}
);
}

if (!filteredRow)
return Future.error(
new Error("No data found for event tracker 7-1-7 performance")
);
getEvent717Performance(diseaseOutbreakEventId: Id): FutureData<PerformanceMetrics717[]> {
return this.get717PerformanceIndicators("event").flatMap(
performance717ProgramIndicators => {
return apiToFuture(
this.api.analytics.getEnrollmentsQuery({
programId: RTSL_ZEBRA_PROGRAM_ID,
dimension: [...performance717ProgramIndicators.map(({ id }) => id)],
startDate: DEFAULT_START_DATE,
endDate: DEFAULT_END_DATE,
})
).flatMap(response => {
const filteredRow = filterAnalyticsEnrollmentDataByDiseaseOutbreakEvent(
diseaseOutbreakEventId,
response.rows,
response.headers
);

const mappedIndicatorsToRows: string[][] =
eventTracker717PerformanceIndicator.map(({ id }) => {
return [
id,
filteredRow[
response.headers.findIndex(header => header.name === id)
] || "",
];
});

return Future.success(
this.mapIndicatorsTo717PerformanceMetrics(
mappedIndicatorsToRows,
eventTracker717PerformanceIndicator
)
if (!filteredRow)
return Future.error(
new Error("No data found for event tracker 7-1-7 performance")
);
});

const mappedIndicatorsToRows: string[][] = performance717ProgramIndicators.map(
({ id }) => {
return [
id,
filteredRow[
response.headers.findIndex(header => header.name === id)
] || "",
];
}
);

return Future.success(
this.mapIndicatorsTo717PerformanceMetrics(
mappedIndicatorsToRows,
performance717ProgramIndicators
)
);
});
}
);
}

private get717PerformanceIndicators(
key: PerformanceMetrics717Key
): FutureData<PerformanceMetrics717[]> {
const datastoreKey =
key === "national"
? NATIONAL_PERFORMANCE_717_PROGRAM_INDICATORS_DATASTORE_KEY
: key === "alerts"
? ALERTS_PERFORMANCE_717_PROGRAM_INDICATORS_DATASTORE_KEY
: EVENT_TRACKER_PERFORMANCE_717_PROGRAM_INDICATORS_DATASTORE_KEY;

return this.datastore
.getObject<PerformanceMetrics717[]>(datastoreKey)
.flatMap(nullable717PerformanceProgramIndicators => {
return assertOrError(nullable717PerformanceProgramIndicators, datastoreKey).flatMap(
performance717ProgramIndicators => {
return Future.success(performance717ProgramIndicators);
}
);
});
}

Expand Down
10 changes: 6 additions & 4 deletions src/data/repositories/test/PerformanceOverviewTestRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import { PerformanceOverviewRepository } from "../../../domain/repositories/Perf
import { FutureData } from "../../api-futures";

export class PerformanceOverviewTestRepository implements PerformanceOverviewRepository {
getEventTracker717Performance(
_diseaseOutbreakEventId: Id
): FutureData<PerformanceMetrics717[]> {
getEvent717Performance(_diseaseOutbreakEventId: Id): FutureData<PerformanceMetrics717[]> {
return Future.success([]);
}
getEventTrackerOverviewMetrics(): FutureData<OverviewCard[]> {
Expand All @@ -17,7 +15,11 @@ export class PerformanceOverviewTestRepository implements PerformanceOverviewRep
getTotalCardCounts(): FutureData<any> {
return Future.success(0);
}
getDashboard717Performance(): FutureData<any> {
getNational717Performance(): FutureData<any> {
return Future.success(0);
}

getAlerts717Performance(): FutureData<any> {
return Future.success(0);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,12 @@ type HazardCounts = BaseCounts & {

export type TotalCardCounts = DiseaseCounts | HazardCounts;

export type PerformanceMetrics717Key = "national" | "event" | "alerts";

export type PerformanceMetrics717 = {
id: string;
name: string;
type: "primary" | "secondary";
value?: number | "Inc";
key: "dashboard" | "event_tracker";
key: PerformanceMetrics717Key;
};
5 changes: 3 additions & 2 deletions src/domain/repositories/PerformanceOverviewRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ export interface PerformanceOverviewRepository {
multiSelectFilters?: Record<string, string[]>,
dateRangeFilter?: string[]
): FutureData<TotalCardCounts[]>;
getDashboard717Performance(): FutureData<PerformanceMetrics717[]>;
getEventTracker717Performance(diseaseOutbreakEventId: Id): FutureData<PerformanceMetrics717[]>;
getNational717Performance(): FutureData<PerformanceMetrics717[]>;
getEvent717Performance(diseaseOutbreakEventId: Id): FutureData<PerformanceMetrics717[]>;
getAlerts717Performance(): FutureData<PerformanceMetrics717[]>;
getEventTrackerOverviewMetrics(
type: string,
casesDataSource: CasesDataSource
Expand Down
17 changes: 11 additions & 6 deletions src/domain/usecases/Get717PerformanceUseCase.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { FutureData } from "../../data/api-futures";
import { PerformanceMetrics717 } from "../entities/disease-outbreak-event/PerformanceOverviewMetrics";
import {
PerformanceMetrics717,
PerformanceMetrics717Key,
} from "../entities/disease-outbreak-event/PerformanceOverviewMetrics";
import { Id } from "../entities/Ref";
import { PerformanceOverviewRepository } from "../repositories/PerformanceOverviewRepository";

Expand All @@ -11,15 +14,17 @@ export class Get717PerformanceUseCase {
) {}

public execute(
type: "dashboard" | "event_tracker",
type: PerformanceMetrics717Key,
diseaseOutbreakEventId: Id | undefined
): FutureData<PerformanceMetrics717[]> {
if (type === "event_tracker" && diseaseOutbreakEventId) {
return this.options.performanceOverviewRepository.getEventTracker717Performance(
if (type === "event" && diseaseOutbreakEventId) {
return this.options.performanceOverviewRepository.getEvent717Performance(
diseaseOutbreakEventId
);
} else if (type === "dashboard") {
return this.options.performanceOverviewRepository.getDashboard717Performance();
} else if (type === "national") {
return this.options.performanceOverviewRepository.getNational717Performance();
} else if (type === "alerts") {
return this.options.performanceOverviewRepository.getAlerts717Performance();
} else throw new Error(`Unknown 717 type: ${type} `);
}
}
30 changes: 27 additions & 3 deletions src/webapp/pages/dashboard/DashboardPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,14 @@ export const DashboardPage: React.FC = React.memo(() => {
isLoading: performanceOverviewLoading,
} = usePerformanceOverview();

const { performanceMetrics717, isLoading: _717CardsLoading } = use717Performance("dashboard");
const {
performanceMetrics717: nationalPerformanceMetrics717,
isLoading: national717CardsLoading,
} = use717Performance("national");

const { performanceMetrics717: alertsPerformanceMetrics717, isLoading: alerts717CardsLoading } =
use717Performance("alerts");

const { cardCounts, isLoading: cardCountsLoading } = useCardCounts(
singleSelectFilters,
multiSelectFilters,
Expand All @@ -55,7 +62,7 @@ export const DashboardPage: React.FC = React.memo(() => {
resetCurrentEventTrackerId();
}, [resetCurrentEventTrackerId]);

return performanceOverviewLoading || _717CardsLoading ? (
return performanceOverviewLoading || national717CardsLoading || alerts717CardsLoading ? (
<Loader />
) : (
<Layout
Expand Down Expand Up @@ -125,9 +132,26 @@ export const DashboardPage: React.FC = React.memo(() => {
dateRangeFilter={dateRangeFilter.value}
/>
</Section>
<Section title={i18n.t("Alerts 7-1-7 performance")}>
<GridWrapper>
{alertsPerformanceMetrics717.map(
(perfMetric717: PerformanceMetric717, index: number) => (
<StatsCard
key={index}
stat={`${perfMetric717.primaryValue}`}
title={perfMetric717.title}
pretitle={`${perfMetric717.secondaryValue} ${i18n.t("events")}`}
color={perfMetric717.color}
fillParent
isPercentage
/>
)
)}
</GridWrapper>
</Section>
<Section title={i18n.t("7-1-7 performance")}>
<GridWrapper>
{performanceMetrics717.map(
{nationalPerformanceMetrics717.map(
(perfMetric717: PerformanceMetric717, index: number) => (
<StatsCard
key={index}
Expand Down
Loading

0 comments on commit b23dbe5

Please sign in to comment.