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

[1073] ui/dataset: Show status badge for datasets using classification results #1074

Merged
merged 4 commits into from
Sep 15, 2022
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The types of changes are:
* Dataset generation enhancements using Fides Classify for Plus users:
* Added toggle for enabling classify during generation. [#1057](https://github.com/ethyca/fides/pull/1057)
* Initial implementation of API request to kick off classify, with confirmation modal. [#1069](https://github.com/ethyca/fides/pull/1069)
* Initial Classification & Review status for generated datasets. [#1074](https://github.com/ethyca/fides/pull/1074)
* New page to add a system via yaml [#1062](https://github.com/ethyca/fides/pull/1062)
* Skeleton of page to add a system manually [#1068](https://github.com/ethyca/fides/pull/1068)

Expand Down
28 changes: 28 additions & 0 deletions clients/ctl/admin-ui/cypress/e2e/datasets-classify.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,32 @@ describe("Datasets with Fides Classify", () => {
cy.getByTestId("toast-success-msg");
});
});

describe("List of datasets with classifications", () => {
beforeEach(() => {
cy.intercept("GET", "/api/v1/dataset", { fixture: "datasets.json" }).as(
"getDatasets"
);
cy.intercept("GET", "/api/v1/plus/classification", {
fixture: "classification/list.json",
}).as("getClassificationList");
});

it("Shows the each dataset's classification status", () => {
cy.visit("/dataset");
cy.wait("@getDatasets");
cy.wait("@getClassificationList");
cy.getByTestId("dataset-table");
cy.getByTestId("dataset-status-demo_users_dataset").contains("Unknown");
cy.getByTestId("dataset-status-demo_users_dataset_2").contains(
"Processing"
);
cy.getByTestId("dataset-status-demo_users_dataset_3").contains(
"Awaiting Review"
);
cy.getByTestId("dataset-status-demo_users_dataset_4").contains(
"Classified"
);
});
});
});
45 changes: 45 additions & 0 deletions clients/ctl/admin-ui/cypress/fixtures/classification/list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
[
{
"id": "2",
"fides_key": "demo_users_dataset_2",
"status": "processing"
},
{
"id": "3",
"fides_key": "demo_users_dataset_3",
"status": "review",
"classification": {
"data_categories": ["user"],
"collections": [
{
"name": "users",
"fields": [
{
"name": "device",
"data_categories": ["user.device"]
}
]
}
]
}
},
{
"id": "4",
"fides_key": "demo_users_dataset_4",
"status": "classified",
"classification": {
"data_categories": ["user"],
"collections": [
{
"name": "users",
"fields": [
{
"name": "device",
"data_categories": ["user.device"]
}
]
}
]
}
}
]
6 changes: 3 additions & 3 deletions clients/ctl/admin-ui/src/features/common/features.slice.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -9,9 +9,9 @@ export interface Features {
}

export const useFeatures = (): Features => {
const { isSuccess } = useGetHealthQuery();
const hasPlus = useHasPlus();

return {
plus: isSuccess,
plus: hasPlus,
};
};
39 changes: 38 additions & 1 deletion clients/ctl/admin-ui/src/features/common/plus.slice.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { createSelector } from "@reduxjs/toolkit";
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

import { Dataset } from "~/types/api";
Expand Down Expand Up @@ -50,7 +51,43 @@ export const plusApi = createApi({
body,
}),
}),
getAllClassifications: build.query<ClassificationResponse[], void>({
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,
ssangervasi marked this conversation as resolved.
Show resolved Hide resolved
selectFromResult: selectClassificationsMap,
});
return map;
};
44 changes: 37 additions & 7 deletions clients/ctl/admin-ui/src/features/dataset/DatasetTable.tsx
Original file line number Diff line number Diff line change
@@ -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) {
Expand All @@ -32,13 +46,18 @@ const DatasetsTable = ({ datasets }: Props) => {
<Th pl={1}>Name</Th>
<Th pl={1}>Fides Key</Th>
<Th pl={1}>Description</Th>
<Th pl={1}>Status</Th>
ssangervasi marked this conversation as resolved.
Show resolved Hide resolved
</Tr>
</Thead>
<Tbody>
{datasets.map((dataset) => {
const isActive =
activeDataset && activeDataset.fides_key === dataset.fides_key;

const classification = classificationsMap.get(dataset.fides_key);
const statusDisplay =
STATUS_DISPLAY[classification?.status ?? "default"];

return (
<Tr
key={dataset.fides_key}
Expand All @@ -57,6 +76,17 @@ const DatasetsTable = ({ datasets }: Props) => {
<Td pl={1}>{dataset.name}</Td>
<Td pl={1}>{dataset.fides_key}</Td>
<Td pl={1}>{dataset.description}</Td>
<Td pl={1}>
<Tooltip label={statusDisplay.tooltip}>
<Badge
variant="solid"
colorScheme={statusDisplay.color}
data-testid={`dataset-status-${dataset.fides_key}`}
>
{statusDisplay.title}
</Badge>
</Tooltip>
</Td>
</Tr>
);
})}
Expand Down
29 changes: 29 additions & 0 deletions clients/ctl/admin-ui/src/features/dataset/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
},
};
15 changes: 2 additions & 13 deletions clients/ctl/admin-ui/src/pages/dataset/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
ssangervasi marked this conversation as resolved.
Show resolved Hide resolved
const activeDataset = useSelector(selectActiveDataset);
const router = useRouter();
const toast = useToast();
Expand All @@ -57,9 +48,7 @@ const DataSets: NextPage = () => {
</BreadcrumbItem>
</Breadcrumb>
</Box>
<Box mb={4}>
{isLoading ? <Spinner /> : <DatasetsTable datasets={datasets} />}
</Box>
<Box mb={4}>{isLoading ? <Spinner /> : <DatasetsTable />}</Box>
<Box>
<Button
size="sm"
Expand Down