Skip to content

Commit

Permalink
feat: scorecard view
Browse files Browse the repository at this point in the history
Initial implementation of scorecard view
  • Loading branch information
nnkogift committed Sep 1, 2024
1 parent e44b07d commit 831e15a
Show file tree
Hide file tree
Showing 14 changed files with 214 additions and 154 deletions.
6 changes: 0 additions & 6 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,29 +1,26 @@
import { colors } from "@dhis2/ui";
import {
ScorecardCardImage as holderImage,
truncateDescription,
} from "@scorecard/shared";
import { getOrgUnitIdsFromOrgUnitSelection, ScorecardCardImage as holderImage, truncateDescription } from "@scorecard/shared";
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import { ScorecardListItem } from "../../types";
import { useScorecardSharingSettings } from "../../hooks/authority";
import { ScorecardListCardActions } from "./ScorecardListCardActions";
import { OrgUnitSelection } from "@hisptz/dhis2-utils";

export default function ScorecardListCard({
scorecard,
grid,
}: {
scorecard,
grid
}: {
scorecard: ScorecardListItem;
grid: boolean;
}) {
const { write, read } = useScorecardSharingSettings(scorecard);

const { title, description, id } = scorecard ?? {};
const { title, description, id, orgUnitSelection, periodSelection } = scorecard ?? {};
const [showFullDescription, setShowFullDescription] = useState(false);
const navigate = useNavigate();

const onView = () => {
navigate(`/view/${id}`);
const orgUnitIds = getOrgUnitIdsFromOrgUnitSelection(orgUnitSelection as OrgUnitSelection).join(";");
const periodIds = periodSelection.periods.map(({ id }) => id).join(";");
navigate(`/view/${id}?ou=${orgUnitIds}&pe=${periodIds}`);
};

return grid ? (
Expand Down Expand Up @@ -52,7 +49,7 @@ export default function ScorecardListCard({
onClick={(event) => {
event.stopPropagation();
setShowFullDescription(
(prevState) => !prevState,
(prevState) => !prevState
);
}}
className="row space-between align-content-end"
Expand Down Expand Up @@ -98,7 +95,7 @@ export default function ScorecardListCard({
onClick={(event) => {
event.stopPropagation();
setShowFullDescription(
(prevState) => !prevState,
(prevState) => !prevState
);
}}
className="row space-between align-content-end"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,13 @@
import { Pagination } from "@dhis2/ui";
import React from "react";
import { ScorecardListItem } from "../types";
import { useSetting } from "@dhis2/app-service-datastore";
import GridScorecardDisplay from "./GridScorecardDisplay";
import ListScorecardDisplay from "./ListScorecardDisplay";

export default function PaginatedDisplay({
pager,
scorecards = [],
scorecards = [],
}: {
scorecards: ScorecardListItem[];
pager: {
page?: number;
pageSize?: number;
totalPages: number;
total: number;
onPageChange: (page: number) => void;
onPageSizeChange: (size: number) => void;
};
}) {
const [scorecardViewType] = useSetting("scorecardViewType");

Expand All @@ -29,15 +19,6 @@ export default function PaginatedDisplay({
{scorecardViewType === "list" && (
<ListScorecardDisplay scorecards={scorecards} />
)}
{pager.totalPages > 1 && (
<div className="p-16">
<Pagination
page={pager.page ?? 1}
pageSize={pager.pageSize ?? 8}
{...pager}
/>
</div>
)}
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,60 @@ import EmptySearchList from "./EmptySearchList";
import EmptyScoreCardList from "../../EmptyScoreCardList";
import PaginatedDisplay from "./PaginatedDisplay";
import { useSearchParams } from "react-router-dom";
import { Pagination } from "@dhis2/ui";

export function ScorecardListArea() {
const [searchParams] = useSearchParams();
const keyword = searchParams.get("query");
const { scorecards, pager, refetch, error, loading } =
useScorecardListData();

if (loading) {
return <FullPageLoader />;
}

if (error) {
return (
<FullPageError error={error} resetErrorBoundary={() => refetch()} />
);
}

return (
<Suspense fallback={<FullPageLoader />}>
{isEmpty(scorecards) ? (
keyword ? (
<div className="flex-1">
<EmptySearchList keyword={keyword} />
</div>
) : (
<div className="flex-1 h-100 column center align-center">
<EmptyScoreCardList />
</div>
)
) : (
<div className="column h-100">
{scorecards ? (
<PaginatedDisplay
pager={pager}
scorecards={scorecards}
/>
) : null}
<div style={{ gap: 16, justifyContent: "space-between", height: "100%" }} className="column ">
<Suspense fallback={<FullPageLoader />}>
<div style={{ flex: 1 }}>
{
loading ? <div style={{ width: "100%", height: "100%", display: "flex", alignItems: "center", justifyContent: "center" }}>
<FullPageLoader />
</div> : (isEmpty(scorecards) ? (
keyword ? (
<div className="flex-1">
<EmptySearchList keyword={keyword} />
</div>
) : (
<div className="flex-1 h-100 column center align-center">
<EmptyScoreCardList />
</div>
)
) : (
<div className="column h-100">
{scorecards ? (
<PaginatedDisplay
scorecards={scorecards}
/>
) : null}
</div>
))
}
</div>
)}
</Suspense>
{
(pager.totalPages > 1 && (
<div className="p-16">
<Pagination
page={pager.page ?? 1}
pageSize={pager.pageSize ?? 10}
{...pager}
/>
</div>
))
}
</Suspense>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,31 @@ const query: any = {
resource: "dataStore",
id: "hisptz-scorecard",
params: ({
keyword,
page,
pageSize,
}: {
keyword,
page,
pageSize
}: {
keyword: string;
page: number;
pageSize: number;
}) => {
return {
filter: keyword
? ["title", "description", "additionalLabels"].map(
(key) => `${key}:ilike:${keyword}`,
)
(key) => `${key}:ilike:${keyword}`
)
: undefined,
rootJunction: "or",
page,
pageSize,
fields: ["id", "title", "description", "additionalLabels"],
fields: ["id", "title", "description", "additionalLabels", "orgUnitSelection", "periodSelection"]
};
},
}
},
keys: {
resource: "dataStore",
id: "hisptz-scorecard",
},
id: "hisptz-scorecard"
}
};

type ListDataQueryResponse = {
Expand All @@ -55,8 +55,8 @@ export function useScorecardListData() {
variables: {
keyword: searchParams.get("query"),
page: 1,
pageSize: 8,
},
pageSize: 10
}
});

const scorecards = useMemo(() => {
Expand All @@ -67,17 +67,17 @@ export function useScorecardListData() {
const keys =
data?.keys?.filter(
(key) =>
!["savedObjects", "settings", "scorecard-sumary"].includes(
key,
),
!["savedObjects", "settings", "scorecard-summary"].includes(
key
)
) ?? [];

return {
...(data?.list?.pager ?? {}),
total: keys.length,
totalPages: Math.ceil(
keys.length / (data?.list.pager.pageSize ?? 1),
),
keys.length / (data?.list.pager.pageSize ?? 1)
)
};
}, [data]);

Expand All @@ -87,27 +87,27 @@ export function useScorecardListData() {
refetch({
keyword,
page: 1,
pageSize: 10,
pageSize: 10
});
} else {
refetch({
keyword: undefined,
page: 1,
pageSize: 10,
pageSize: 10
});
}
}, 800),
}, 800)
);

const onPageChange = (page: number) => {
refetch({
page,
page
});
};
const onPageSizeChange = (pageSize: number) => {
refetch({
pageSize,
page: 1,
page: 1
});
};

Expand All @@ -120,10 +120,10 @@ export function useScorecardListData() {
pager: {
...pager,
onPageChange,
onPageSizeChange,
onPageSizeChange
},
error,
loading,
refetch,
refetch
};
}
21 changes: 9 additions & 12 deletions packages/app/src/modules/Main/components/ScorecardList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import i18n from "@dhis2/d2-i18n";
import {
Button,
ButtonStrip,
DropdownButton,
IconQuestion24,
Tooltip,
} from "@dhis2/ui";
import { Button, ButtonStrip, DropdownButton, IconQuestion24, Tooltip } from "@dhis2/ui";
import { IconAdd24, IconApps24, IconList24 } from "@dhis2/ui-icons";
import { SCORECARD_LIST_HELP_STEPS, STEP_OPTIONS } from "@scorecard/shared";
import { FullPageError, SCORECARD_LIST_HELP_STEPS, STEP_OPTIONS } from "@scorecard/shared";
import { Steps } from "intro.js-react";
import React, { useState } from "react";
import HelpMenu from "./components/HelpMenu";
Expand All @@ -16,13 +10,14 @@ import { useSetting } from "@dhis2/app-service-datastore";
import { useAlert } from "@dhis2/app-runtime";
import { useNavigate } from "react-router-dom";
import { ScorecardListArea } from "./components/ScorecardListArea";
import { ErrorBoundary } from "react-error-boundary";

export default function ScorecardList() {
const [scorecardViewType, { set }] = useSetting("scorecardViewType");
const [helpEnabled, setHelpEnabled] = useState<boolean>(false);
const { show } = useAlert(
({ message }) => message,
({ type }) => ({ ...type, duration: 3000 }),
({ type }) => ({ ...type, duration: 3000 })
);
const onViewChange = () => {
try {
Expand All @@ -34,7 +29,7 @@ export default function ScorecardList() {
} catch (e: any) {
show({
message: e.message ?? e.toString(),
type: { critical: true },
type: { critical: true }
});
}
};
Expand Down Expand Up @@ -81,7 +76,7 @@ export default function ScorecardList() {
viewType:
scorecardViewType === "grid"
? i18n.t("list")
: i18n.t("grid"),
: i18n.t("grid")
})}
>
<Button
Expand Down Expand Up @@ -110,7 +105,9 @@ export default function ScorecardList() {
</div>
</div>
<div className="flex-1">
<ScorecardListArea />
<ErrorBoundary FallbackComponent={FullPageError}>
<ScorecardListArea />
</ErrorBoundary>
</div>
</div>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import { ScorecardConfig } from "@hisptz/dhis2-analytics";

export type ScorecardListItem = Pick<
ScorecardConfig,
"id" | "title" | "additionalLabels" | "description"
"id" | "title" | "additionalLabels" | "description" | "orgUnitSelection" | "periodSelection"
>;
Loading

0 comments on commit 831e15a

Please sign in to comment.