From 7089368e401a4591e319cf7557786734da18fd3c Mon Sep 17 00:00:00 2001 From: Sebastian Sangervasi Date: Wed, 14 Sep 2022 12:44:32 -0700 Subject: [PATCH 1/4] ui/plus: Classifications grouped by dataset fides key --- .../src/features/common/features.slice.ts | 6 +-- .../src/features/common/plus.slice.ts | 39 ++++++++++++++++++- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/clients/ctl/admin-ui/src/features/common/features.slice.ts b/clients/ctl/admin-ui/src/features/common/features.slice.ts index 85192f77b6..260d931cac 100644 --- a/clients/ctl/admin-ui/src/features/common/features.slice.ts +++ b/clients/ctl/admin-ui/src/features/common/features.slice.ts @@ -1,4 +1,4 @@ -import { useGetHealthQuery } from "./plus.slice"; +import { useHasPlus } from "./plus.slice"; /** * Features are currently stateless and only use the Plus API. However, this a ".slice" file because @@ -9,9 +9,9 @@ export interface Features { } export const useFeatures = (): Features => { - const { isSuccess } = useGetHealthQuery(); + const hasPlus = useHasPlus(); return { - plus: isSuccess, + plus: hasPlus, }; }; diff --git a/clients/ctl/admin-ui/src/features/common/plus.slice.ts b/clients/ctl/admin-ui/src/features/common/plus.slice.ts index 6045d30200..e1ca9938d0 100644 --- a/clients/ctl/admin-ui/src/features/common/plus.slice.ts +++ b/clients/ctl/admin-ui/src/features/common/plus.slice.ts @@ -1,3 +1,4 @@ +import { createSelector } from "@reduxjs/toolkit"; import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; import { Dataset } from "~/types/api"; @@ -50,7 +51,43 @@ export const plusApi = createApi({ body, }), }), + getAllClassifications: build.query({ + query: () => `classification/`, + }), }), }); -export const { useGetHealthQuery, useCreateClassificationMutation } = plusApi; +export const { + useGetHealthQuery, + useCreateClassificationMutation, + useGetAllClassificationsQuery, +} = plusApi; + +export const useHasPlus = () => { + const { isSuccess: hasPlus } = useGetHealthQuery(); + return hasPlus; +}; + +const emptyClassifications: ClassificationResponse[] = []; +const selectClassificationsMap = createSelector( + ({ data }: { data?: ClassificationResponse[] }) => + data ?? emptyClassifications, + (dataCategories) => ({ + map: new Map(dataCategories.map((c) => [c.fides_key, c])), + }) +); + +/** + * Convenience hook for looking up a Classification by Dataset key. + */ +export const useClassificationsMap = (): Map< + string, + ClassificationResponse +> => { + const hasPlus = useHasPlus(); + const { map } = useGetAllClassificationsQuery(undefined, { + skip: !hasPlus, + selectFromResult: selectClassificationsMap, + }); + return map; +}; From 76523c1bdc5779c29f68233494ac90722b339162 Mon Sep 17 00:00:00 2001 From: Sebastian Sangervasi Date: Wed, 14 Sep 2022 12:45:33 -0700 Subject: [PATCH 2/4] ui/dataset: Show status badge for datasets using classification results --- .../src/features/dataset/DatasetTable.tsx | 44 ++++++++++++++++--- .../src/features/dataset/constants.ts | 29 ++++++++++++ .../ctl/admin-ui/src/pages/dataset/index.tsx | 15 +------ 3 files changed, 68 insertions(+), 20 deletions(-) diff --git a/clients/ctl/admin-ui/src/features/dataset/DatasetTable.tsx b/clients/ctl/admin-ui/src/features/dataset/DatasetTable.tsx index 23bc403911..ef7df2ee96 100644 --- a/clients/ctl/admin-ui/src/features/dataset/DatasetTable.tsx +++ b/clients/ctl/admin-ui/src/features/dataset/DatasetTable.tsx @@ -1,18 +1,32 @@ -import { Table, Tbody, Td, Th, Thead, Tr } from "@fidesui/react"; +import { + Badge, + Table, + Tbody, + Td, + Th, + Thead, + Tooltip, + Tr, +} from "@fidesui/react"; import { useDispatch, useSelector } from "react-redux"; +import { useClassificationsMap } from "~/features/common/plus.slice"; import { Dataset } from "~/types/api"; -import { selectActiveDataset, setActiveDataset } from "./dataset.slice"; +import { STATUS_DISPLAY } from "./constants"; +import { + selectActiveDataset, + setActiveDataset, + useGetAllDatasetsQuery, +} from "./dataset.slice"; -interface Props { - datasets: Dataset[] | undefined; -} - -const DatasetsTable = ({ datasets }: Props) => { +const DatasetsTable = () => { const dispatch = useDispatch(); const activeDataset = useSelector(selectActiveDataset); + const { data: datasets } = useGetAllDatasetsQuery(); + const classificationsMap = useClassificationsMap(); + const handleRowClick = (dataset: Dataset) => { // toggle the active dataset if (dataset.fides_key === activeDataset?.fides_key) { @@ -32,6 +46,7 @@ const DatasetsTable = ({ datasets }: Props) => { Name Fides Key Description + Status @@ -39,6 +54,10 @@ const DatasetsTable = ({ datasets }: Props) => { const isActive = activeDataset && activeDataset.fides_key === dataset.fides_key; + const classification = classificationsMap.get(dataset.fides_key); + const statusDisplay = + STATUS_DISPLAY[classification?.status ?? "default"]; + return ( { {dataset.name} {dataset.fides_key} {dataset.description} + + + + {statusDisplay.title} + + + ); })} diff --git a/clients/ctl/admin-ui/src/features/dataset/constants.ts b/clients/ctl/admin-ui/src/features/dataset/constants.ts index f2314a3d35..36abfb3fde 100644 --- a/clients/ctl/admin-ui/src/features/dataset/constants.ts +++ b/clients/ctl/admin-ui/src/features/dataset/constants.ts @@ -77,3 +77,32 @@ export const FIELD = { "Arrays of Data Category resources, identified by fides_key, that apply to this field.", }, }; + +/** + * Details to display about datasets based on status. Status is currently only determined by the + * classification feature. + */ +export const STATUS_DISPLAY = { + processing: { + title: "Processing", + tooltip: + "This dataset is currently being generated and classified. You will be notified when this process is complete", + color: "orange", + }, + review: { + title: "Awaiting Review", + tooltip: + "This dataset has been automatically classified. Review the results and update the dataset.", + color: "orange", + }, + classified: { + title: "Classified", + tooltip: "This dataset has been classified.", + color: "green", + }, + default: { + title: "Unknown", + tooltip: "This dataset must be manually updated.", + color: "gray", + }, +}; diff --git a/clients/ctl/admin-ui/src/pages/dataset/index.tsx b/clients/ctl/admin-ui/src/pages/dataset/index.tsx index 226291ac86..ebd3e2b7f2 100644 --- a/clients/ctl/admin-ui/src/pages/dataset/index.tsx +++ b/clients/ctl/admin-ui/src/pages/dataset/index.tsx @@ -20,17 +20,8 @@ import { } from "~/features/dataset/dataset.slice"; import DatasetsTable from "~/features/dataset/DatasetTable"; -const useDatasetsTable = () => { - const { data, isLoading } = useGetAllDatasetsQuery(); - - return { - isLoading, - datasets: data, - }; -}; - const DataSets: NextPage = () => { - const { isLoading, datasets } = useDatasetsTable(); + const { isLoading } = useGetAllDatasetsQuery(); const activeDataset = useSelector(selectActiveDataset); const router = useRouter(); const toast = useToast(); @@ -57,9 +48,7 @@ const DataSets: NextPage = () => { - - {isLoading ? : } - + {isLoading ? : }