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

Refactor TreeGrid to have typed items and data #1175

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
25 changes: 10 additions & 15 deletions ui/src/addByCode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
TreeGrid,
TreeGridColumn,
TreeGridId,
TreeGridItem,
useArrayAsTreeGridData,
} from "components/treegrid";
import ActionBar from "actionBar";
Expand All @@ -24,7 +25,7 @@ import { cohortURL, useIsSecondBlock } from "router";
import { insertCohortCriteria, useCohortContext } from "cohortContext";
import { isValid } from "util/valid";

type LookupEntryItem = {
type LookupEntryData = {
config?: JSX.Element;
code: DataKey;
name?: string;
Expand All @@ -48,7 +49,7 @@ export function AddByCode() {
[underlay.criteriaSelectors]
);

const lookupEntriesState = useSWRMutation<LookupEntryItem[]>(
const lookupEntriesState = useSWRMutation<LookupEntryData[]>(
{
component: "AddByCode",
query,
Expand Down Expand Up @@ -110,7 +111,7 @@ export function AddByCode() {
const data = useArrayAsTreeGridData(lookupEntriesState?.data ?? [], "code");

const onInsert = useCallback(() => {
const configMap = new Map<string, LookupEntryItem[]>();
const configMap = new Map<string, LookupEntryData[]>();
lookupEntriesState.data?.forEach((e) => {
if (!e.entry || !selected.has(e.code)) {
return;
Expand Down Expand Up @@ -196,19 +197,13 @@ export function AddByCode() {
</GridBox>
<Loading immediate showProgressOnMutate status={lookupEntriesState}>
{lookupEntriesState.data?.length ? (
<TreeGrid
<TreeGrid<TreeGridItem<LookupEntryData>>
columns={columns}
data={data}
rowCustomization={(id: TreeGridId) => {
if (!lookupEntriesState.data) {
return undefined;
}

const item = data.get(id)?.data as LookupEntryItem;
if (!item) {
return undefined;
}

rowCustomization={(
id: TreeGridId,
{ data }: TreeGridItem<LookupEntryData>
) => {
const sel = selected.has(id);
return [
{
Expand All @@ -218,7 +213,7 @@ export function AddByCode() {
size="small"
fontSize="inherit"
checked={sel}
disabled={!item.entry}
disabled={!data.entry}
onChange={() => {
updateSelected((selected) => {
if (sel) {
Expand Down
13 changes: 2 additions & 11 deletions ui/src/addCohort.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function AddCohort() {
const navigate = useNavigate();
const params = useBaseParams();

const cohortsState = useSWR(
const cohortsState = useSWR<CohortData[]>(
{
type: "cohorts",
studyId,
Expand Down Expand Up @@ -112,16 +112,7 @@ export function AddCohort() {
<TreeGrid
data={data}
columns={columns}
rowCustomization={(id: TreeGridId) => {
if (!cohortsState.data) {
return undefined;
}

const cohortData = data.get(id)?.data as CohortData;
if (!cohortData) {
return undefined;
}

rowCustomization={(id: TreeGridId, { data: cohortData }) => {
return [
{
column: columns.length - 2,
Expand Down
35 changes: 15 additions & 20 deletions ui/src/addCriteria.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
TreeGrid,
TreeGridId,
TreeGridItem,
TreeGridRowData,
TreeGridData,
} from "components/treegrid";
import { MergedItem } from "data/mergeLists";
import { Criteria, isTemporalSection } from "data/source";
Expand Down Expand Up @@ -352,9 +352,7 @@ function AddCriteria(props: AddCriteriaProps) {

const search = useCallback(async () => {
const children: DataKey[] = [];
const data = new Map<TreeGridId, CriteriaItem>([
["root", { data: {}, children }],
]);
const rows = new Map<TreeGridId, CriteriaItem>();

if (query) {
const res = await searchCriteria(
Expand All @@ -376,13 +374,16 @@ function AddCriteria(props: AddCriteriaProps) {
},
entry: entry,
};
data.set(key, item);
rows.set(key, item);
});
}

return data;
return {
rows,
children,
};
}, [underlaySource, query, selectedOptions, optionsMap]);
const searchState = useSWRImmutable<Map<TreeGridId, CriteriaItem>>(
const searchState = useSWRImmutable<TreeGridData<CriteriaItem>>(
{
component: "AddCriteria",
underlayName: underlay.name,
Expand Down Expand Up @@ -522,7 +523,7 @@ function AddCriteria(props: AddCriteriaProps) {
{!!query ? (
<Paper>
<Loading status={searchState}>
{!searchState.data?.get("root")?.children?.length ? (
{!searchState.data?.children?.length ? (
<Empty
minHeight="300px"
image={emptyImage}
Expand All @@ -531,17 +532,9 @@ function AddCriteria(props: AddCriteriaProps) {
) : (
<TreeGrid
columns={columns}
data={searchState.data ?? new Map()}
rowCustomization={(
id: TreeGridId,
rowData: TreeGridRowData
) => {
if (!searchState.data) {
return undefined;
}

const item = searchState.data.get(id);
const option = optionsMap.get(item?.entry?.source ?? "");
data={searchState.data}
rowCustomization={(id, item) => {
const option = optionsMap.get(item.entry?.source ?? "");
if (!option || !item?.entry?.source) {
throw new Error(
`Item source "${item?.entry?.source}" doesn't match any criteria config ID.`
Expand All @@ -554,7 +547,9 @@ function AddCriteria(props: AddCriteriaProps) {
content: (
<GridLayout colAlign="center">
<Button
data-testid={rowData[searchConfig.columns[0].key]}
data-testid={
item.data[searchConfig.columns[0].key]
}
onClick={() => onClick(option, item.entry?.data)}
variant="outlined"
>
Expand Down
11 changes: 1 addition & 10 deletions ui/src/cohortReview/cohortReviewList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -687,16 +687,7 @@ function Annotations() {
<TreeGrid
data={data}
columns={columns}
rowCustomization={(id: TreeGridId) => {
if (!annotationsState.data) {
return undefined;
}

const annotation = data.get(id)?.data;
if (!annotation) {
return undefined;
}

rowCustomization={(id: TreeGridId, { data: annotation }) => {
return [
{
column: columns.length - 1,
Expand Down
16 changes: 10 additions & 6 deletions ui/src/cohortReview/participantsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
useReviewSearchState,
} from "cohortReview/reviewHooks";
import Loading from "components/loading";
import { TreeGrid, TreeGridData, TreeGridId } from "components/treegrid";
import { TreeGrid, TreeGridId } from "components/treegrid";
import GridLayout from "layout/gridLayout";
import React, { ReactNode, useMemo, useState } from "react";

Expand Down Expand Up @@ -125,7 +125,8 @@ function ParticipantsList(props: ParticipantsListProps) {
);

const data = useMemo(() => {
const data: TreeGridData = new Map([["root", { data: {}, children: [] }]]);
const children: TreeGridId[] = [];
const rows = new Map();

instancesState.data
?.slice(
Expand All @@ -134,21 +135,24 @@ function ParticipantsList(props: ParticipantsListProps) {
)
.forEach((instance) => {
const key = instance.data.key;
data.set(key, { data: { ...instance.data } });
data.get("root")?.children?.push(key);
rows.set(key, { data: { ...instance.data } });
children.push(key);

annotationsState.data?.forEach((a) => {
const values = instance.annotations.get(a.id);
if (values) {
const valueData = data.get(key)?.data;
const valueData = rows.get(key)?.data;
if (valueData) {
valueData[`t_${a.id}`] = values[values.length - 1].value;
}
}
});
});

return data;
return {
rows,
children,
};
}, [instancesState, annotationsState, props.page, props.rowsPerPage]);

return (
Expand Down
29 changes: 15 additions & 14 deletions ui/src/cohortReview/plugins/occurrenceTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
import {
TreeGrid,
TreeGridColumn,
TreeGridData,
TreeGridSortDirection,
TreeGridSortOrder,
} from "components/treegrid";
Expand Down Expand Up @@ -62,14 +61,17 @@ function OccurrenceTable({ id, config }: { id: string; config: Config }) {

const data = useMemo(() => {
const children: DataKey[] = [];
const data: TreeGridData = new Map([["root", { data: {}, children }]]);
const rows = new Map();

context.rows[config.entity]?.forEach((o) => {
data.set(o.key, { data: o });
rows.set(o.key, { data: o });
children.push(o.key);
});

return data;
return {
rows,
children,
};
}, [context]);

const filterRegExps = useMemo(() => {
Expand All @@ -82,25 +84,24 @@ function OccurrenceTable({ id, config }: { id: string; config: Config }) {

const sortedData = useMemo(() => {
return produce(data, (data) => {
const root = data.get("root");
if (!root) {
return;
}

root.children = (root.children ?? []).filter((child) =>
data.children = (data.children ?? []).filter((child) =>
Object.entries(filterRegExps ?? {}).reduce(
(cur: boolean, [col, re]) =>
cur &&
re.test(
stringifyDataValue(data.get(child)?.data?.[col] as DataValue)
stringifyDataValue(data.rows.get(child)?.data?.[col] as DataValue)
),
true
)
);
root.children.sort((a, b) => {
data.children.sort((a, b) => {
for (const o of searchState.sortOrders ?? []) {
const valA = data.get(a)?.data?.[o.column] as DataValue | undefined;
const valB = data.get(b)?.data?.[o.column] as DataValue | undefined;
const valA = data.rows.get(a)?.data?.[o.column] as
| DataValue
| undefined;
const valB = data.rows.get(b)?.data?.[o.column] as
| DataValue
| undefined;
const c = compareDataValues(valA, valB);
if (c !== 0) {
return o.direction === TreeGridSortDirection.Asc ? c : -c;
Expand Down
68 changes: 32 additions & 36 deletions ui/src/components/treegrid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,45 +32,41 @@ test("Table renders correctly", async () => {
},
];

const data = new Map<TreeGridId, TreeGridItem>([
[
"root",
{
data: {},
children: [1, 3],
},
],
[
1,
{
data: {
col1: "1-col1",
col2: "1-col2",
const data: TreeGridData = {
children: [1, 3],
rows: new Map([
[
1,
{
data: {
col1: "1-col1",
col2: "1-col2",
},
children: [2],
},
children: [2],
},
],
[
2,
{
data: {
col1: "2-col1",
col2: "2-col2",
col3: "2-col3",
],
[
2,
{
data: {
col1: "2-col1",
col2: "2-col2",
col3: "2-col3",
},
},
},
],
[
3,
{
data: {
col1: "3-col1",
col2: "3-col2",
col3: <AccountTreeIcon />,
],
[
3,
{
data: {
col1: "3-col1",
col2: "3-col2",
col3: <AccountTreeIcon />,
},
},
},
],
]);
],
]),
};

const rowCustomization = (id: TreeGridId) => {
// Add variety to the rows.
Expand Down
Loading
Loading