From c31f7b7c32e1012391e0399fe9698b582818b483 Mon Sep 17 00:00:00 2001 From: Timothy Jennison Date: Mon, 21 Oct 2024 19:33:48 +0000 Subject: [PATCH] Add exclusion support to FilterableGroup UI --- ui/src/components/search.tsx | 3 + ui/src/criteria/filterableGroup.tsx | 181 +++++++++++++++++++++------- 2 files changed, 140 insertions(+), 44 deletions(-) diff --git a/ui/src/components/search.tsx b/ui/src/components/search.tsx index d6e3715c9..ae26cc7a8 100644 --- a/ui/src/components/search.tsx +++ b/ui/src/components/search.tsx @@ -19,6 +19,7 @@ export type SearchProps = { searchKey?: string; delayMs?: number; + disabled?: boolean; showSearchButton?: boolean; }; @@ -70,6 +71,7 @@ export function Search(props: SearchProps) {
{ form.reset(); onSearch(""); diff --git a/ui/src/criteria/filterableGroup.tsx b/ui/src/criteria/filterableGroup.tsx index 573d136d3..ddf4e4aee 100644 --- a/ui/src/criteria/filterableGroup.tsx +++ b/ui/src/criteria/filterableGroup.tsx @@ -1,5 +1,7 @@ import AddIcon from "@mui/icons-material/Add"; +import ClearIcon from "@mui/icons-material/Clear"; import DeleteIcon from "@mui/icons-material/Delete"; +import EditIcon from "@mui/icons-material/Edit"; import FilterListIcon from "@mui/icons-material/FilterList"; import Button from "@mui/material/Button"; import IconButton from "@mui/material/IconButton"; @@ -11,6 +13,7 @@ import Typography from "@mui/material/Typography"; import { CriteriaPlugin, generateId, registerCriteriaPlugin } from "cohort"; import Checkbox from "components/checkbox"; import Empty from "components/empty"; +import { containedIconButtonSx } from "components/iconButton"; import Loading from "components/loading"; import { Search } from "components/search"; import { useSimpleDialog } from "components/simpleDialog"; @@ -188,6 +191,9 @@ function FilterableGroupEdit(props: FilterableGroupEditProps) { const [rowsPerPage, setRowsPerPage] = useState(25); const [filters, setFilters] = useState([]); + const [selectedExclusion, setSelectedExclusion] = useState< + string | undefined + >(); const [unconfirmedChangesDialog, showUnconfirmedChangesDialog] = useSimpleDialog(); @@ -330,6 +336,7 @@ function FilterableGroupEdit(props: FilterableGroupEditProps) { > { updateSearchState((data: SearchState) => { data.query = query; @@ -349,48 +356,62 @@ function FilterableGroupEdit(props: FilterableGroupEditProps) { {instancesState.data?.length && instancesState.data?.[0]?.total ? ( - - - - - - + {!selectedExclusion ? ( + + ) : null} + {!selectedExclusion ? ( + + + + + + ) : null} + {selectedExclusion ? ( + + ) : null} {instancesState.data[currentPage] ? ( ) : null} @@ -459,6 +480,7 @@ function FilterableGroupEdit(props: FilterableGroupEditProps) { {selectionTitle(s)} updateLocalCriteria((data) => { data.selected.splice(i, 1); @@ -472,6 +494,21 @@ function FilterableGroupEdit(props: FilterableGroupEditProps) { { + const all = s.all; + + setSelectedExclusion( + selected ? s.id : undefined + ); + if (selected && all) { + updateSearchState((data: SearchState) => { + data.query = all.query; + }); + + setFilters(all.values); + } + }} /> ) : null} @@ -508,6 +545,8 @@ type ResultsPageProps = { columns: TreeGridColumn[]; nodes: EntityNode[]; selectedSet: Set; + selectedExclusion?: string; + localCriteria: Data; updateLocalCriteria: (fn: (data: Data) => void) => void; }; @@ -517,17 +556,52 @@ function ResultsPage(props: ResultsPageProps) { "key" ); + const selectAll = useMemo(() => { + return props.localCriteria.selected.find( + (s) => s.id === props.selectedExclusion + )?.all; + }, [props.localCriteria, props.selectedExclusion]); + return ( { - const found = !!props.selectedSet.has(key); + const found = selectAll + ? !!selectAll.exclusions.find((e) => e.key === key) + : props.selectedSet.has(key); + const newSelection = { + key, + name: String(rowData[props.columns[0].key] ?? "Unknown"), + }; return [ { column: 0, - prefixElements: ( + prefixElements: selectAll ? ( + { + props.updateLocalCriteria((data) => { + const all = data.selected.find( + (s) => s.id === props.selectedExclusion + )?.all; + if (all) { + if (found) { + all.exclusions = all.exclusions.filter( + (e) => e.key !== key + ); + } else { + all.exclusions.push(newSelection); + } + } + }); + }} + > + + + ) : ( void; }; function SelectAllStats(props: SelectAllStatsProps) { @@ -656,6 +727,28 @@ function SelectAllStats(props: SelectAllStatsProps) { ); })} + + {props.setSelected ? ( + { + if (props.setSelected) { + props.setSelected(!props.selected); + } + }} + > + + + ) : null} + + {"Exclusions: "} + + {props.selectAll.exclusions.length + ? props.selectAll.exclusions.map((e) => e.name).join(", ") + : "None"} + + + ); }