From 2b15040ddd2449eace1b5b8bd7d5909da6592331 Mon Sep 17 00:00:00 2001 From: Allison King Date: Tue, 31 May 2022 14:24:03 -0400 Subject: [PATCH] Dataset detail view (#711) * Pull individual dataset info * Add a view for individual datasets * Add breadcrumbs and style Select * Clean up * Update changelog --- CHANGELOG.md | 1 + clients/admin-ui/next.config.js | 14 ++-- .../dataset/DatasetCollectionView.tsx | 71 +++++++++++++++++++ .../features/dataset/DatasetFieldsTable.tsx | 30 ++++++++ .../src/features/dataset/DatasetTable.tsx | 10 +-- .../src/features/dataset/dataset.slice.ts | 7 +- clients/admin-ui/src/pages/dataset/[id].tsx | 39 ++++++++++ clients/admin-ui/src/pages/dataset/index.tsx | 21 +++++- 8 files changed, 180 insertions(+), 13 deletions(-) create mode 100644 clients/admin-ui/src/features/dataset/DatasetCollectionView.tsx create mode 100644 clients/admin-ui/src/features/dataset/DatasetFieldsTable.tsx create mode 100644 clients/admin-ui/src/pages/dataset/[id].tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index f32b0c4e0f..7115eaad51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ The types of changes are: * New `generate` endpoint to enable capturing systems from infrastructure from the UI [#642](https://github.com/ethyca/fides/pull/642) * Navigation bar for management UI * Dataset backend integration for management UI +* Initial dataset collection UI view * Okta, aws and database credentials can now come from `fidesctl.toml` config [#694](https://github.com/ethyca/fides/pull/694) ### Changed diff --git a/clients/admin-ui/next.config.js b/clients/admin-ui/next.config.js index 3d682b5242..f0838dd42f 100644 --- a/clients/admin-ui/next.config.js +++ b/clients/admin-ui/next.config.js @@ -21,14 +21,16 @@ const nextConfig = { return config; }, async rewrites() { + // these paths are unnecessarily complicated due to our backend being + // picky about trailing slashes https://github.com/ethyca/fides/issues/690 return [ { - source: `/api/v1/:path*`, - // note: we may need to be careful about this in the future - // our backend paths are picky about trailing slashes, and - // nextjs automatically removes trailing slashes. may have to - // be careful when there are query parameters. - destination: "http://0.0.0.0:8080/api/v1/:path*/", + source: `/api/v1/:path`, + destination: "http://0.0.0.0:8080/api/v1/:path/", + }, + { + source: `/api/v1/:first/:second*`, + destination: "http://0.0.0.0:8080/api/v1/:first/:second*", }, ]; }, diff --git a/clients/admin-ui/src/features/dataset/DatasetCollectionView.tsx b/clients/admin-ui/src/features/dataset/DatasetCollectionView.tsx new file mode 100644 index 0000000000..69cf815a11 --- /dev/null +++ b/clients/admin-ui/src/features/dataset/DatasetCollectionView.tsx @@ -0,0 +1,71 @@ +import { Box, Select, Spinner } from "@fidesui/react"; +import { ChangeEvent, useEffect, useState } from "react"; + +import { FidesKey } from "../common/fides-types"; +import { useGetDatasetByKeyQuery } from "./dataset.slice"; +import DatasetFieldsTable from "./DatasetFieldsTable"; +import { DatasetCollection } from "./types"; + +const useDataset = (key: FidesKey) => { + const { data, isLoading } = useGetDatasetByKeyQuery(key); + + return { + isLoading, + dataset: data, + }; +}; + +interface Props { + fidesKey: FidesKey; +} + +const DatasetCollectionView = ({ fidesKey }: Props) => { + const { dataset, isLoading } = useDataset(fidesKey); + const [activeCollection, setActiveCollection] = useState< + DatasetCollection | undefined + >(); + + useEffect(() => { + if (dataset) { + setActiveCollection(dataset.collections[0]); + } else { + setActiveCollection(undefined); + } + }, [dataset]); + + if (!dataset) { + return
Dataset not found
; + } + + const { collections } = dataset; + + const handleChangeCollection = (event: ChangeEvent) => { + const collection = collections.filter( + (c) => c.name === event.target.value + )[0]; + setActiveCollection(collection); + }; + + if (isLoading) { + return ; + } + + return ( + + + + + {activeCollection && ( + + )} + + ); +}; + +export default DatasetCollectionView; diff --git a/clients/admin-ui/src/features/dataset/DatasetFieldsTable.tsx b/clients/admin-ui/src/features/dataset/DatasetFieldsTable.tsx new file mode 100644 index 0000000000..35863d0036 --- /dev/null +++ b/clients/admin-ui/src/features/dataset/DatasetFieldsTable.tsx @@ -0,0 +1,30 @@ +import { Table, Tbody, Td, Th, Thead, Tr } from "@fidesui/react"; + +import { DatasetField } from "./types"; + +interface Props { + fields: DatasetField[]; +} + +const DatasetFieldsTable = ({ fields }: Props) => ( + + + + + + + + + + {fields.map((field) => ( + + + + + + ))} + +
Field NameDescriptionIdentifiability
{field.name}{field.description}{field.data_qualifier}
+); + +export default DatasetFieldsTable; diff --git a/clients/admin-ui/src/features/dataset/DatasetTable.tsx b/clients/admin-ui/src/features/dataset/DatasetTable.tsx index 129702f535..0b06bc527c 100644 --- a/clients/admin-ui/src/features/dataset/DatasetTable.tsx +++ b/clients/admin-ui/src/features/dataset/DatasetTable.tsx @@ -14,15 +14,17 @@ const DatasetsTable = ({ datasets }: Props) => { - - + + + {datasets.map((dataset) => ( - - + + + ))} diff --git a/clients/admin-ui/src/features/dataset/dataset.slice.ts b/clients/admin-ui/src/features/dataset/dataset.slice.ts index 696ce12d9b..934195bc95 100644 --- a/clients/admin-ui/src/features/dataset/dataset.slice.ts +++ b/clients/admin-ui/src/features/dataset/dataset.slice.ts @@ -2,6 +2,7 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; import { HYDRATE } from "next-redux-wrapper"; +import { FidesKey } from "../common/fides-types"; import { Dataset } from "./types"; export interface State { @@ -23,10 +24,14 @@ export const datasetApi = createApi({ query: () => ({ url: `dataset/` }), providesTags: () => ["Dataset"], }), + getDatasetByKey: build.query({ + query: (key) => ({ url: `dataset/${key}` }), + providesTags: () => ["Dataset"], + }), }), }); -export const { useGetAllDatasetsQuery } = datasetApi; +export const { useGetAllDatasetsQuery, useGetDatasetByKeyQuery } = datasetApi; export const datasetSlice = createSlice({ name: "dataset", diff --git a/clients/admin-ui/src/pages/dataset/[id].tsx b/clients/admin-ui/src/pages/dataset/[id].tsx new file mode 100644 index 0000000000..5d7963ecc5 --- /dev/null +++ b/clients/admin-ui/src/pages/dataset/[id].tsx @@ -0,0 +1,39 @@ +import { Box, Breadcrumb, BreadcrumbItem, Heading } from "@fidesui/react"; +import type { NextPage } from "next"; +import NextLink from "next/link"; +import { useRouter } from "next/router"; + +import Layout from "~/features/common/Layout"; +import DatasetCollectionView from "~/features/dataset/DatasetCollectionView"; + +const DatasetDetail: NextPage = () => { + const router = useRouter(); + const { id } = router.query; + + if (!id) { + return Dataset not found; + } + + const fidesKey = Array.isArray(id) ? id[0] : id; + + return ( + + + Dataset + + + + + Datasets + + + {id} + + + + + + ); +}; + +export default DatasetDetail; diff --git a/clients/admin-ui/src/pages/dataset/index.tsx b/clients/admin-ui/src/pages/dataset/index.tsx index cc0c35a954..42345677d4 100644 --- a/clients/admin-ui/src/pages/dataset/index.tsx +++ b/clients/admin-ui/src/pages/dataset/index.tsx @@ -1,5 +1,12 @@ -import { Heading, Spinner } from "@fidesui/react"; +import { + Box, + Breadcrumb, + BreadcrumbItem, + Heading, + Spinner, +} from "@fidesui/react"; import type { NextPage } from "next"; +import NextLink from "next/link"; import React from "react"; import Layout from "~/features/common/Layout"; @@ -20,9 +27,19 @@ const DataSets: NextPage = () => { return ( - + Datasets + + + + Datasets + + + Select dataset + + + {isLoading ? : } );
NameDescriptionNameFides KeyDescription
{dataset.name}{dataset.description}{dataset.name}{dataset.fides_key}{dataset.description}