From b129547dc6489957c54f39047813ef315297c247 Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Mon, 29 Jul 2024 09:00:44 -0400 Subject: [PATCH 01/17] WIP: new breadcrumbs --- .../DatabaseIcon.tsx | 12 +++ .../DatasetIcon.tsx | 12 +++ .../TableIcon.tsx | 12 +++ .../DiscoveryMonitorBreadcrumbs.tsx | 1 - .../DnDBreadcrumbsV2.tsx | 80 +++++++++++++++++++ .../hooks/useDiscoveryResultColumns.tsx | 34 ++++++++ .../tables/DetectionResultTable.tsx | 2 + .../types/StagedResourceType.ts | 1 + .../utils/findResourceType.ts | 5 +- .../src/pages/data-discovery/activity.tsx | 7 +- .../detection/[resourceUrn].tsx | 15 +++- .../pages/data-discovery/detection/index.tsx | 15 ++-- .../discovery/[resourceUrn].tsx | 5 ++ .../pages/data-discovery/discovery/index.tsx | 12 +-- .../admin-ui/src/types/api/models/Field.ts | 2 + 15 files changed, 194 insertions(+), 21 deletions(-) create mode 100644 clients/admin-ui/src/features/common/Icon/detection-discovery-resource-types/DatabaseIcon.tsx create mode 100644 clients/admin-ui/src/features/common/Icon/detection-discovery-resource-types/DatasetIcon.tsx create mode 100644 clients/admin-ui/src/features/common/Icon/detection-discovery-resource-types/TableIcon.tsx create mode 100644 clients/admin-ui/src/features/data-discovery-and-detection/DnDBreadcrumbsV2.tsx diff --git a/clients/admin-ui/src/features/common/Icon/detection-discovery-resource-types/DatabaseIcon.tsx b/clients/admin-ui/src/features/common/Icon/detection-discovery-resource-types/DatabaseIcon.tsx new file mode 100644 index 0000000000..f8dd5ede7b --- /dev/null +++ b/clients/admin-ui/src/features/common/Icon/detection-discovery-resource-types/DatabaseIcon.tsx @@ -0,0 +1,12 @@ +import { createIcon } from "fidesui"; + +export const DatabaseIcon = createIcon({ + displayName: "DatabaseIcon", + viewBox: "0 0 12 12", + path: ( + + ), +}); diff --git a/clients/admin-ui/src/features/common/Icon/detection-discovery-resource-types/DatasetIcon.tsx b/clients/admin-ui/src/features/common/Icon/detection-discovery-resource-types/DatasetIcon.tsx new file mode 100644 index 0000000000..1650b70bec --- /dev/null +++ b/clients/admin-ui/src/features/common/Icon/detection-discovery-resource-types/DatasetIcon.tsx @@ -0,0 +1,12 @@ +import { createIcon } from "fidesui"; + +export const DatasetIcon = createIcon({ + displayName: "DatasetIcon", + viewBox: "0 0 16 16", + path: ( + + ), +}); diff --git a/clients/admin-ui/src/features/common/Icon/detection-discovery-resource-types/TableIcon.tsx b/clients/admin-ui/src/features/common/Icon/detection-discovery-resource-types/TableIcon.tsx new file mode 100644 index 0000000000..49ca7377dc --- /dev/null +++ b/clients/admin-ui/src/features/common/Icon/detection-discovery-resource-types/TableIcon.tsx @@ -0,0 +1,12 @@ +import { createIcon } from "fidesui"; + +export const TableIcon = createIcon({ + displayName: "TableIcon", + viewBox: "0 0 16 16", + path: ( + + ), +}); diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs.tsx index 1f43203c61..e12745b642 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs.tsx +++ b/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs.tsx @@ -19,7 +19,6 @@ const DiscoveryMonitorBreadcrumbs = ({ return ( void; +} + +const MONITOR_BREADCRUMB_ICONS = [ + , + , + , +]; + +const DnDBreadcrumbsV2 = ({ + resourceUrn, + parentLink, + onPathClick = () => {}, +}: DiscoveryMonitorBreadcrumbsProps) => { + const router = useRouter(); + + if (!resourceUrn) { + return ( + + + All activity + + + ); + } + + const urnParts = resourceUrn.split("."); + + return ( + + {urnParts.map((urnPart, index) => { + // don't render anything at the monitor level because there's no view for it + if (index === 0) { + return null; + } + + // at the database level, link should go to "all activity" view + const isDatabase = index === 1; + const isLastPart = index === urnParts.length - 1; + + return ( + + {MONITOR_BREADCRUMB_ICONS[index - 1]} + + isDatabase + ? router.push(parentLink) + : onPathClick(urnParts.slice(0, index + 1).join(".")) + } + > + {urnPart} + + + ); + })} + + ); +}; + +export default DnDBreadcrumbsV2; diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/hooks/useDiscoveryResultColumns.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/hooks/useDiscoveryResultColumns.tsx index 53f4879d2c..c67df3c9c2 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/hooks/useDiscoveryResultColumns.tsx +++ b/clients/admin-ui/src/features/data-discovery-and-detection/hooks/useDiscoveryResultColumns.tsx @@ -179,6 +179,40 @@ const useDiscoveryResultColumns = ({ return { columns }; } + if (resourceType === StagedResourceType.NESTED_FIELD) { + const columns = [ + columnHelper.accessor((row) => row.name, { + id: "name", + cell: (props) => , + header: (props) => ( + + ), + }), + columnHelper.display({ + id: "type", + cell: () => , + header: "Type", + }), + columnHelper.accessor((row) => row.monitor_config_id, { + id: "monitor", + cell: (props) => , + header: (props) => , + }), + columnHelper.accessor((row) => row.source_modified, { + id: "time", + cell: (props) => , + header: (props) => , + }), + columnHelper.display({ + id: "actions", + cell: (props) => , + header: "Actions", + }), + ]; + + return { columns }; + } + return { columns: defaultColumns }; }; diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/tables/DetectionResultTable.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/tables/DetectionResultTable.tsx index ad095e5f9e..c521886cac 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/tables/DetectionResultTable.tsx +++ b/clients/admin-ui/src/features/data-discovery-and-detection/tables/DetectionResultTable.tsx @@ -127,6 +127,8 @@ const DetectionResultTable = ({ resourceUrn }: MonitorResultTableProps) => { pages: totalPages, } = useMemo(() => resources ?? EMPTY_RESPONSE, [resources]); + console.log(data); + useEffect(() => { setTotalPages(totalPages); }, [totalPages, setTotalPages]); diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/types/StagedResourceType.ts b/clients/admin-ui/src/features/data-discovery-and-detection/types/StagedResourceType.ts index 1b4afbabf3..7a0d0ab2f5 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/types/StagedResourceType.ts +++ b/clients/admin-ui/src/features/data-discovery-and-detection/types/StagedResourceType.ts @@ -3,5 +3,6 @@ export enum StagedResourceType { SCHEMA = "Schema", TABLE = "Table", FIELD = "Field", + NESTED_FIELD = "Nested Field", NONE = "none", } diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/utils/findResourceType.ts b/clients/admin-ui/src/features/data-discovery-and-detection/utils/findResourceType.ts index 5974a5e43f..cf272577b5 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/utils/findResourceType.ts +++ b/clients/admin-ui/src/features/data-discovery-and-detection/utils/findResourceType.ts @@ -15,5 +15,8 @@ export const findResourceType = (item: DiscoveryMonitorItem | undefined) => { if (item.fields) { return StagedResourceType.TABLE; } - return StagedResourceType.FIELD; + if (item.parent_table_urn) { + return StagedResourceType.FIELD; + } + return StagedResourceType.NESTED_FIELD; }; diff --git a/clients/admin-ui/src/pages/data-discovery/activity.tsx b/clients/admin-ui/src/pages/data-discovery/activity.tsx index c6e126d919..8a1c4a881b 100644 --- a/clients/admin-ui/src/pages/data-discovery/activity.tsx +++ b/clients/admin-ui/src/pages/data-discovery/activity.tsx @@ -30,12 +30,7 @@ const DataDiscoveryAndDetectionActivityPage = () => { padding: "0 40px 48px", }} > - + { padding: "20px 40px 48px", }} > - + Data detection + + {/* navigateToDetectionResults({ resourceUrn: newResourceUrn }) } + /> */} + + navigateToDetectionResults({ resourceUrn: newResourceUrn }) + } /> diff --git a/clients/admin-ui/src/pages/data-discovery/detection/index.tsx b/clients/admin-ui/src/pages/data-discovery/detection/index.tsx index c1c0cd2d6b..0bf571fffc 100644 --- a/clients/admin-ui/src/pages/data-discovery/detection/index.tsx +++ b/clients/admin-ui/src/pages/data-discovery/detection/index.tsx @@ -1,7 +1,9 @@ +import { Heading } from "fidesui"; import React from "react"; import FixedLayout from "~/features/common/FixedLayout"; import PageHeader from "~/features/common/PageHeader"; +import DiscoveryMonitorBreadcrumbs from "~/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs"; import DetectionResultTable from "~/features/data-discovery-and-detection/tables/DetectionResultTable"; const DataDetectionActivityPage = () => ( @@ -11,12 +13,13 @@ const DataDetectionActivityPage = () => ( padding: "0 40px 48px", }} > - + + + Data detection + + + {/* TEMPORARY HACK */} + ); diff --git a/clients/admin-ui/src/pages/data-discovery/discovery/[resourceUrn].tsx b/clients/admin-ui/src/pages/data-discovery/discovery/[resourceUrn].tsx index b7f636f0b9..64d180c555 100644 --- a/clients/admin-ui/src/pages/data-discovery/discovery/[resourceUrn].tsx +++ b/clients/admin-ui/src/pages/data-discovery/discovery/[resourceUrn].tsx @@ -1,7 +1,9 @@ +import { Heading } from "fidesui"; import React from "react"; import FixedLayout from "~/features/common/FixedLayout"; import { DATA_DISCOVERY_ROUTE } from "~/features/common/nav/v2/routes"; +import PageHeader from "~/features/common/PageHeader"; import DiscoveryMonitorBreadcrumbs from "~/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs"; import useDiscoveryRoutes from "~/features/data-discovery-and-detection/hooks/useDiscoveryRoutes"; import DiscoveryResultTable from "~/features/data-discovery-and-detection/tables/DiscoveryResultTable"; @@ -16,6 +18,9 @@ const DataDiscoveryActivityPage = () => { padding: "20px 40px 48px", }} > + + Data discovery + ( padding: "0 40px 48px", }} > - + + + Data discovery + + ); diff --git a/clients/admin-ui/src/types/api/models/Field.ts b/clients/admin-ui/src/types/api/models/Field.ts index 93569874ad..51a3239bc9 100644 --- a/clients/admin-ui/src/types/api/models/Field.ts +++ b/clients/admin-ui/src/types/api/models/Field.ts @@ -30,4 +30,6 @@ export type Field = { parent_table_urn: string; table_name: string; data_type?: string; + // TEMP: until real API is available + child_fields: string[]; }; From 79927279cf28485a751bd0cb0722cd72a949e06e Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Tue, 30 Jul 2024 11:18:04 -0400 Subject: [PATCH 02/17] finish breadcrumbs --- .../DiscoveryMonitorBreadcrumbs.tsx | 65 ++++++++++++------- .../detection/[resourceUrn].tsx | 11 +--- .../pages/data-discovery/detection/index.tsx | 4 +- .../discovery/[resourceUrn].tsx | 1 - .../pages/data-discovery/discovery/index.tsx | 3 + 5 files changed, 46 insertions(+), 38 deletions(-) diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs.tsx index e12745b642..1e03298fb3 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs.tsx +++ b/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs.tsx @@ -1,57 +1,71 @@ import { Breadcrumb, BreadcrumbItem, BreadcrumbLink } from "fidesui"; -import NextLink from "next/link"; +import { useRouter } from "next/router"; + +import { DatabaseIcon } from "~/features/common/Icon/detection-discovery-resource-types/DatabaseIcon"; +import { DatasetIcon } from "~/features/common/Icon/detection-discovery-resource-types/DatasetIcon"; +import { TableIcon } from "~/features/common/Icon/detection-discovery-resource-types/TableIcon"; interface DiscoveryMonitorBreadcrumbsProps { resourceUrn?: string; - parentTitle: string; parentLink: string; onPathClick?: (urn: string) => void; } +const MONITOR_BREADCRUMB_ICONS = [ + , + , + , +]; + const DiscoveryMonitorBreadcrumbs = ({ resourceUrn, - parentTitle, parentLink, onPathClick = () => {}, }: DiscoveryMonitorBreadcrumbsProps) => { - const urnParts = resourceUrn ? resourceUrn.split(".") : []; - - return ( - - - - {parentTitle} - - + const router = useRouter(); - {!resourceUrn ? ( - + if (!resourceUrn) { + return ( + + All activity - ) : null} + + ); + } + const urnParts = resourceUrn.split("."); + + return ( + {urnParts.map((urnPart, index) => { - // don't display the first or second parts of the URN (monitor ID or - // database) because there's no table view for them - if (index === 0 || index === 1) { + // don't render anything at the monitor level because there's no view for it + if (index === 0) { return null; } + // at the database level, link should go to "all activity" view + const isDatabase = index === 1; const isLastPart = index === urnParts.length - 1; return ( + {MONITOR_BREADCRUMB_ICONS[index - 1]} - onPathClick(urnParts.slice(0, index + 1).join(".")) + isDatabase + ? router.push(parentLink) + : onPathClick(urnParts.slice(0, index + 1).join(".")) } > {urnPart} @@ -62,4 +76,5 @@ const DiscoveryMonitorBreadcrumbs = ({ ); }; + export default DiscoveryMonitorBreadcrumbs; diff --git a/clients/admin-ui/src/pages/data-discovery/detection/[resourceUrn].tsx b/clients/admin-ui/src/pages/data-discovery/detection/[resourceUrn].tsx index 2b166b1e56..7173fc4725 100644 --- a/clients/admin-ui/src/pages/data-discovery/detection/[resourceUrn].tsx +++ b/clients/admin-ui/src/pages/data-discovery/detection/[resourceUrn].tsx @@ -5,7 +5,6 @@ import FixedLayout from "~/features/common/FixedLayout"; import { DATA_DETECTION_ROUTE } from "~/features/common/nav/v2/routes"; import PageHeader from "~/features/common/PageHeader"; import DiscoveryMonitorBreadcrumbs from "~/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs"; -import DnDBreadcrumbsV2 from "~/features/data-discovery-and-detection/DnDBreadcrumbsV2"; import useDiscoveryRoutes from "~/features/data-discovery-and-detection/hooks/useDiscoveryRoutes"; import DetectionResultTable from "~/features/data-discovery-and-detection/tables/DetectionResultTable"; @@ -22,15 +21,7 @@ const DataDetectionActivityPage = () => { Data detection - {/* - navigateToDetectionResults({ resourceUrn: newResourceUrn }) - } - /> */} - diff --git a/clients/admin-ui/src/pages/data-discovery/detection/index.tsx b/clients/admin-ui/src/pages/data-discovery/detection/index.tsx index 0bf571fffc..de55a503ad 100644 --- a/clients/admin-ui/src/pages/data-discovery/detection/index.tsx +++ b/clients/admin-ui/src/pages/data-discovery/detection/index.tsx @@ -2,6 +2,7 @@ import { Heading } from "fidesui"; import React from "react"; import FixedLayout from "~/features/common/FixedLayout"; +import { DATA_DETECTION_ROUTE } from "~/features/common/nav/v2/routes"; import PageHeader from "~/features/common/PageHeader"; import DiscoveryMonitorBreadcrumbs from "~/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs"; import DetectionResultTable from "~/features/data-discovery-and-detection/tables/DetectionResultTable"; @@ -18,8 +19,7 @@ const DataDetectionActivityPage = () => ( Data detection - {/* TEMPORARY HACK */} - + ); diff --git a/clients/admin-ui/src/pages/data-discovery/discovery/[resourceUrn].tsx b/clients/admin-ui/src/pages/data-discovery/discovery/[resourceUrn].tsx index 64d180c555..67d72ee12d 100644 --- a/clients/admin-ui/src/pages/data-discovery/discovery/[resourceUrn].tsx +++ b/clients/admin-ui/src/pages/data-discovery/discovery/[resourceUrn].tsx @@ -22,7 +22,6 @@ const DataDiscoveryActivityPage = () => { Data discovery diff --git a/clients/admin-ui/src/pages/data-discovery/discovery/index.tsx b/clients/admin-ui/src/pages/data-discovery/discovery/index.tsx index 68ab63958a..c407256eef 100644 --- a/clients/admin-ui/src/pages/data-discovery/discovery/index.tsx +++ b/clients/admin-ui/src/pages/data-discovery/discovery/index.tsx @@ -2,7 +2,9 @@ import { Heading } from "fidesui"; import React from "react"; import FixedLayout from "~/features/common/FixedLayout"; +import { DATA_DISCOVERY_ROUTE } from "~/features/common/nav/v2/routes"; import PageHeader from "~/features/common/PageHeader"; +import DiscoveryMonitorBreadcrumbs from "~/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs"; import DiscoveryResultTable from "~/features/data-discovery-and-detection/tables/DiscoveryResultTable"; const DataDiscoveryActivityPage = () => ( @@ -17,6 +19,7 @@ const DataDiscoveryActivityPage = () => ( Data discovery + ); From 6164e77a550a2c3dc8c0d546cdd8a2d3fc839d57 Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Fri, 9 Aug 2024 01:21:07 -0500 Subject: [PATCH 03/17] update table behavior for nested fields --- .../FieldIcon.tsx | 12 +++ .../features/common/table/v2/FidesTable.tsx | 52 +++++++----- .../DiscoveryMonitorBreadcrumbs.tsx | 2 + .../DnDBreadcrumbsV2.tsx | 80 ------------------- .../tables/DetectionResultTable.tsx | 20 ++--- .../tables/DiscoveryResultTable.tsx | 13 +-- .../tables/ResultStatusCell.tsx | 3 +- .../utils/isNestedField.ts | 15 ++++ .../utils/resourceHasChildren.ts | 14 ++++ clients/admin-ui/src/types/api/index.ts | 1 + .../src/types/api/models/ConsentableItem.ts | 14 ++-- .../api/models/ExperienceConfigCreate.ts | 2 +- .../api/models/ExperienceConfigResponse.ts | 2 +- .../ExperienceConfigResponseNoNotices.ts | 2 +- .../api/models/ExperienceConfigUpdate.ts | 2 +- .../admin-ui/src/types/api/models/Field.ts | 4 +- .../types/api/models/Layer1ButtonOption.ts | 11 +++ .../api/models/PrivacyExperienceResponse.ts | 1 + .../types/api/models/SnowflakeDocsSchema.ts | 12 ++- 19 files changed, 131 insertions(+), 131 deletions(-) create mode 100644 clients/admin-ui/src/features/common/Icon/detection-discovery-resource-types/FieldIcon.tsx delete mode 100644 clients/admin-ui/src/features/data-discovery-and-detection/DnDBreadcrumbsV2.tsx create mode 100644 clients/admin-ui/src/features/data-discovery-and-detection/utils/isNestedField.ts create mode 100644 clients/admin-ui/src/features/data-discovery-and-detection/utils/resourceHasChildren.ts create mode 100644 clients/admin-ui/src/types/api/models/Layer1ButtonOption.ts diff --git a/clients/admin-ui/src/features/common/Icon/detection-discovery-resource-types/FieldIcon.tsx b/clients/admin-ui/src/features/common/Icon/detection-discovery-resource-types/FieldIcon.tsx new file mode 100644 index 0000000000..948054ce4a --- /dev/null +++ b/clients/admin-ui/src/features/common/Icon/detection-discovery-resource-types/FieldIcon.tsx @@ -0,0 +1,12 @@ +import { createIcon } from "fidesui"; + +export const FieldIcon = createIcon({ + displayName: "FieldIcon", + viewBox: "0 0 16 16", + path: ( + + ), +}); diff --git a/clients/admin-ui/src/features/common/table/v2/FidesTable.tsx b/clients/admin-ui/src/features/common/table/v2/FidesTable.tsx index 803dfbcb4c..eb1ce36068 100644 --- a/clients/admin-ui/src/features/common/table/v2/FidesTable.tsx +++ b/clients/admin-ui/src/features/common/table/v2/FidesTable.tsx @@ -188,6 +188,7 @@ type Props = { rowActionBar?: ReactNode; footer?: ReactNode; onRowClick?: (row: T, e: React.MouseEvent) => void; + rowIsClickable?: (row: T) => boolean; renderRowTooltipLabel?: (row: Row) => string | undefined; emptyTableNotice?: ReactNode; overflow?: "auto" | "visible" | "hidden"; @@ -199,32 +200,38 @@ const TableBody = ({ tableInstance, rowActionBar, onRowClick, + rowIsClickable, renderRowTooltipLabel, displayAllColumns, emptyTableNotice, }: Omit, "footer" | "enableSorting" | "onSort"> & { displayAllColumns: string[]; -}) => ( - - {rowActionBar} - {tableInstance.getRowModel().rows.map((row) => ( - - key={row.id} - row={row} - onRowClick={onRowClick} - renderRowTooltipLabel={renderRowTooltipLabel} - displayAllColumns={displayAllColumns} - /> - ))} - {tableInstance.getRowModel().rows.length === 0 && - !tableInstance.getState()?.globalFilter && - emptyTableNotice && ( - - {emptyTableNotice} - - )} - -); +}) => { + const getRowClickHandler = (row: T) => + rowIsClickable && rowIsClickable(row) ? onRowClick : undefined; + + return ( + + {rowActionBar} + {tableInstance.getRowModel().rows.map((row) => ( + + key={row.id} + row={row} + onRowClick={getRowClickHandler(row.original)} + renderRowTooltipLabel={renderRowTooltipLabel} + displayAllColumns={displayAllColumns} + /> + ))} + {tableInstance.getRowModel().rows.length === 0 && + !tableInstance.getState()?.globalFilter && + emptyTableNotice && ( + + {emptyTableNotice} + + )} + + ); +}; const MemoizedTableBody = React.memo( TableBody, @@ -244,6 +251,7 @@ export const FidesTableV2 = ({ rowActionBar, footer, onRowClick, + rowIsClickable, renderRowTooltipLabel, emptyTableNotice, overflow = "auto", @@ -366,6 +374,7 @@ export const FidesTableV2 = ({ tableInstance={tableInstance} rowActionBar={rowActionBar} onRowClick={onRowClick} + rowIsClickable={rowIsClickable} renderRowTooltipLabel={renderRowTooltipLabel} displayAllColumns={displayAllColumns} emptyTableNotice={emptyTableNotice} @@ -375,6 +384,7 @@ export const FidesTableV2 = ({ tableInstance={tableInstance} rowActionBar={rowActionBar} onRowClick={onRowClick} + rowIsClickable={rowIsClickable} renderRowTooltipLabel={renderRowTooltipLabel} displayAllColumns={displayAllColumns} emptyTableNotice={emptyTableNotice} diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs.tsx index 1e03298fb3..1173390310 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs.tsx +++ b/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryMonitorBreadcrumbs.tsx @@ -3,6 +3,7 @@ import { useRouter } from "next/router"; import { DatabaseIcon } from "~/features/common/Icon/detection-discovery-resource-types/DatabaseIcon"; import { DatasetIcon } from "~/features/common/Icon/detection-discovery-resource-types/DatasetIcon"; +import { FieldIcon } from "~/features/common/Icon/detection-discovery-resource-types/FieldIcon"; import { TableIcon } from "~/features/common/Icon/detection-discovery-resource-types/TableIcon"; interface DiscoveryMonitorBreadcrumbsProps { @@ -15,6 +16,7 @@ const MONITOR_BREADCRUMB_ICONS = [ , , , + , ]; const DiscoveryMonitorBreadcrumbs = ({ diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/DnDBreadcrumbsV2.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/DnDBreadcrumbsV2.tsx deleted file mode 100644 index 55f2a363c8..0000000000 --- a/clients/admin-ui/src/features/data-discovery-and-detection/DnDBreadcrumbsV2.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { Breadcrumb, BreadcrumbItem, BreadcrumbLink } from "fidesui"; -import { useRouter } from "next/router"; - -import { DatabaseIcon } from "~/features/common/Icon/detection-discovery-resource-types/DatabaseIcon"; -import { DatasetIcon } from "~/features/common/Icon/detection-discovery-resource-types/DatasetIcon"; -import { TableIcon } from "~/features/common/Icon/detection-discovery-resource-types/TableIcon"; - -interface DiscoveryMonitorBreadcrumbsProps { - resourceUrn?: string; - parentLink: string; - onPathClick?: (urn: string) => void; -} - -const MONITOR_BREADCRUMB_ICONS = [ - , - , - , -]; - -const DnDBreadcrumbsV2 = ({ - resourceUrn, - parentLink, - onPathClick = () => {}, -}: DiscoveryMonitorBreadcrumbsProps) => { - const router = useRouter(); - - if (!resourceUrn) { - return ( - - - All activity - - - ); - } - - const urnParts = resourceUrn.split("."); - - return ( - - {urnParts.map((urnPart, index) => { - // don't render anything at the monitor level because there's no view for it - if (index === 0) { - return null; - } - - // at the database level, link should go to "all activity" view - const isDatabase = index === 1; - const isLastPart = index === urnParts.length - 1; - - return ( - - {MONITOR_BREADCRUMB_ICONS[index - 1]} - - isDatabase - ? router.push(parentLink) - : onPathClick(urnParts.slice(0, index + 1).join(".")) - } - > - {urnPart} - - - ); - })} - - ); -}; - -export default DnDBreadcrumbsV2; diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/tables/DetectionResultTable.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/tables/DetectionResultTable.tsx index c521886cac..bec468e2f9 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/tables/DetectionResultTable.tsx +++ b/clients/admin-ui/src/features/data-discovery-and-detection/tables/DetectionResultTable.tsx @@ -26,6 +26,7 @@ import { DiscoveryMonitorItem } from "~/features/data-discovery-and-detection/ty import { StagedResourceType } from "~/features/data-discovery-and-detection/types/StagedResourceType"; import { findResourceType } from "~/features/data-discovery-and-detection/utils/findResourceType"; import getResourceRowName from "~/features/data-discovery-and-detection/utils/getResourceRowName"; +import isNestedField from "~/features/data-discovery-and-detection/utils/isNestedField"; import { DiffStatus, StagedResource } from "~/types/api"; import { SearchInput } from "../SearchInput"; @@ -127,8 +128,6 @@ const DetectionResultTable = ({ resourceUrn }: MonitorResultTableProps) => { pages: totalPages, } = useMemo(() => resources ?? EMPTY_RESPONSE, [resources]); - console.log(data); - useEffect(() => { setTotalPages(totalPages); }, [totalPages, setTotalPages]); @@ -140,14 +139,14 @@ const DetectionResultTable = ({ resourceUrn }: MonitorResultTableProps) => { const { navigateToDetectionResults } = useDiscoveryRoutes(); - const handleRowClicked = - resourceType !== StagedResourceType.FIELD - ? (row: StagedResource) => - navigateToDetectionResults({ - resourceUrn: row.urn, - showFullSchema: isShowingFullSchema, - }) - : undefined; + const handleRowClicked = (row: StagedResource) => + navigateToDetectionResults({ + resourceUrn: row.urn, + showFullSchema: isShowingFullSchema, + }); + + const getRowIsClickable = (row: StagedResource) => + resourceType !== StagedResourceType.FIELD || isNestedField(row); const tableInstance = useReactTable({ getCoreRowModel: getCoreRowModel(), @@ -195,6 +194,7 @@ const DetectionResultTable = ({ resourceUrn }: MonitorResultTableProps) => { } /> { resources?.items[0] as DiscoveryMonitorItem, ); - const isField = resourceType === StagedResourceType.FIELD; - const { items: data, total: totalRows, @@ -130,10 +129,11 @@ const DiscoveryResultTable = ({ resourceUrn }: MonitorResultTableProps) => { const { navigateToDiscoveryResults } = useDiscoveryRoutes(); - const handleRowClicked = !isField - ? (row: StagedResource) => - navigateToDiscoveryResults({ resourceUrn: row.urn }) - : undefined; + const handleRowClicked = (row: StagedResource) => + navigateToDiscoveryResults({ resourceUrn: row.urn }); + + const getRowIsClickable = (row: StagedResource) => + resourceType !== StagedResourceType.FIELD || isNestedField(row); const tableInstance = useReactTable({ getCoreRowModel: getCoreRowModel(), @@ -178,6 +178,7 @@ const DiscoveryResultTable = ({ resourceUrn }: MonitorResultTableProps) => { } overflow="visible" /> diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/tables/ResultStatusCell.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/tables/ResultStatusCell.tsx index 3c13efa3c9..554eb7b3ab 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/tables/ResultStatusCell.tsx +++ b/clients/admin-ui/src/features/data-discovery-and-detection/tables/ResultStatusCell.tsx @@ -3,6 +3,7 @@ import { Flex, Text, Tooltip } from "fidesui"; import { STATUS_INDICATOR_MAP } from "~/features/data-discovery-and-detection/statusIndicators"; import { ResourceChangeType } from "~/features/data-discovery-and-detection/types/ResourceChangeType"; import findResourceChangeType from "~/features/data-discovery-and-detection/utils/findResourceChangeType"; +import resourceHasChildren from "~/features/data-discovery-and-detection/utils/resourceHasChildren"; import { StagedResource } from "~/types/api"; const ResultStatusCell = ({ @@ -22,7 +23,7 @@ const ResultStatusCell = ({ diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/utils/isNestedField.ts b/clients/admin-ui/src/features/data-discovery-and-detection/utils/isNestedField.ts new file mode 100644 index 0000000000..1de853738f --- /dev/null +++ b/clients/admin-ui/src/features/data-discovery-and-detection/utils/isNestedField.ts @@ -0,0 +1,15 @@ +import { DiscoveryMonitorItem } from "~/features/data-discovery-and-detection/types/DiscoveryMonitorItem"; + +const isNestedField = (resource: DiscoveryMonitorItem): boolean => { + if (!resource.parent_table_urn) { + // resource is not a field + return false; + } + if (!resource.sub_field_urns?.length) { + return false; + } + // make sure field is not a subfield + return resource.urn.split(".").length === 5; +}; + +export default isNestedField; diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/utils/resourceHasChildren.ts b/clients/admin-ui/src/features/data-discovery-and-detection/utils/resourceHasChildren.ts new file mode 100644 index 0000000000..9a238b7c3a --- /dev/null +++ b/clients/admin-ui/src/features/data-discovery-and-detection/utils/resourceHasChildren.ts @@ -0,0 +1,14 @@ +import { DiscoveryMonitorItem } from "~/features/data-discovery-and-detection/types/DiscoveryMonitorItem"; +import { StagedResourceType } from "~/features/data-discovery-and-detection/types/StagedResourceType"; +import { findResourceType } from "~/features/data-discovery-and-detection/utils/findResourceType"; +import isNestedField from "~/features/data-discovery-and-detection/utils/isNestedField"; + +const resourceHasChildren = (resource: DiscoveryMonitorItem): boolean => { + const resourceType = findResourceType(resource); + if (resourceType === StagedResourceType.FIELD) { + return isNestedField(resource); + } + return true; +}; + +export default resourceHasChildren; diff --git a/clients/admin-ui/src/types/api/index.ts b/clients/admin-ui/src/types/api/index.ts index ca4e469f5c..b895676364 100644 --- a/clients/admin-ui/src/types/api/index.ts +++ b/clients/admin-ui/src/types/api/index.ts @@ -197,6 +197,7 @@ export type { IdentityTypes } from "./models/IdentityTypes"; export type { IdentityVerificationConfigResponse } from "./models/IdentityVerificationConfigResponse"; export { IncludeExcludeEnum } from "./models/IncludeExcludeEnum"; export type { Language } from "./models/Language"; +export { Layer1ButtonOption } from "./models/Layer1ButtonOption"; export { LegalBasisForProcessingEnum } from "./models/LegalBasisForProcessingEnum"; export { LegalBasisForProfilingEnum } from "./models/LegalBasisForProfilingEnum"; export type { LimitedPrivacyNoticeResponseSchema } from "./models/LimitedPrivacyNoticeResponseSchema"; diff --git a/clients/admin-ui/src/types/api/models/ConsentableItem.ts b/clients/admin-ui/src/types/api/models/ConsentableItem.ts index c5b046c0bc..2d424e33fb 100644 --- a/clients/admin-ui/src/types/api/models/ConsentableItem.ts +++ b/clients/admin-ui/src/types/api/models/ConsentableItem.ts @@ -1,11 +1,15 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + /** - * 3rd-party consentable item and privacy notice relationships + * Schema to represent 3rd-party consentable items and privacy notice relationships. */ -export interface ConsentableItem { +export type ConsentableItem = { external_id: string; type: string; name: string; - notice_id?: string | null; - children?: ConsentableItem[]; + notice_id?: string; + children?: Array; unmapped?: boolean; -} +}; diff --git a/clients/admin-ui/src/types/api/models/ExperienceConfigCreate.ts b/clients/admin-ui/src/types/api/models/ExperienceConfigCreate.ts index 4e69244ffa..080b5c76f3 100644 --- a/clients/admin-ui/src/types/api/models/ExperienceConfigCreate.ts +++ b/clients/admin-ui/src/types/api/models/ExperienceConfigCreate.ts @@ -2,9 +2,9 @@ /* tslint:disable */ /* eslint-disable */ -import { Layer1ButtonOption } from "~/features/privacy-experience/form/constants"; import type { ComponentType } from "./ComponentType"; import type { ExperienceTranslationCreate } from "./ExperienceTranslationCreate"; +import type { Layer1ButtonOption } from "./Layer1ButtonOption"; import type { MinimalProperty } from "./MinimalProperty"; import type { PrivacyNoticeRegion } from "./PrivacyNoticeRegion"; diff --git a/clients/admin-ui/src/types/api/models/ExperienceConfigResponse.ts b/clients/admin-ui/src/types/api/models/ExperienceConfigResponse.ts index e27cd0119e..90a346b016 100644 --- a/clients/admin-ui/src/types/api/models/ExperienceConfigResponse.ts +++ b/clients/admin-ui/src/types/api/models/ExperienceConfigResponse.ts @@ -2,9 +2,9 @@ /* tslint:disable */ /* eslint-disable */ -import { Layer1ButtonOption } from "~/features/privacy-experience/form/constants"; import type { ComponentType } from "./ComponentType"; import type { ExperienceTranslationResponse } from "./ExperienceTranslationResponse"; +import type { Layer1ButtonOption } from "./Layer1ButtonOption"; import type { MinimalProperty } from "./MinimalProperty"; import type { PrivacyNoticeRegion } from "./PrivacyNoticeRegion"; import type { PrivacyNoticeResponse } from "./PrivacyNoticeResponse"; diff --git a/clients/admin-ui/src/types/api/models/ExperienceConfigResponseNoNotices.ts b/clients/admin-ui/src/types/api/models/ExperienceConfigResponseNoNotices.ts index 8b4cc25ae2..6e2bc81f97 100644 --- a/clients/admin-ui/src/types/api/models/ExperienceConfigResponseNoNotices.ts +++ b/clients/admin-ui/src/types/api/models/ExperienceConfigResponseNoNotices.ts @@ -2,9 +2,9 @@ /* tslint:disable */ /* eslint-disable */ -import { Layer1ButtonOption } from "~/features/privacy-experience/form/constants"; import type { ComponentType } from "./ComponentType"; import type { ExperienceTranslationResponse } from "./ExperienceTranslationResponse"; +import type { Layer1ButtonOption } from "./Layer1ButtonOption"; import type { MinimalProperty } from "./MinimalProperty"; import type { PrivacyNoticeRegion } from "./PrivacyNoticeRegion"; import type { SupportedLanguage } from "./SupportedLanguage"; diff --git a/clients/admin-ui/src/types/api/models/ExperienceConfigUpdate.ts b/clients/admin-ui/src/types/api/models/ExperienceConfigUpdate.ts index 71c63403dd..87eef69aae 100644 --- a/clients/admin-ui/src/types/api/models/ExperienceConfigUpdate.ts +++ b/clients/admin-ui/src/types/api/models/ExperienceConfigUpdate.ts @@ -2,8 +2,8 @@ /* tslint:disable */ /* eslint-disable */ -import { Layer1ButtonOption } from "~/features/privacy-experience/form/constants"; import type { ExperienceTranslation } from "./ExperienceTranslation"; +import type { Layer1ButtonOption } from "./Layer1ButtonOption"; import type { MinimalProperty } from "./MinimalProperty"; import type { PrivacyNoticeRegion } from "./PrivacyNoticeRegion"; diff --git a/clients/admin-ui/src/types/api/models/Field.ts b/clients/admin-ui/src/types/api/models/Field.ts index 51a3239bc9..528bf9e5e7 100644 --- a/clients/admin-ui/src/types/api/models/Field.ts +++ b/clients/admin-ui/src/types/api/models/Field.ts @@ -30,6 +30,6 @@ export type Field = { parent_table_urn: string; table_name: string; data_type?: string; - // TEMP: until real API is available - child_fields: string[]; + sub_field_urns?: Array; + direct_child_urns?: Array; }; diff --git a/clients/admin-ui/src/types/api/models/Layer1ButtonOption.ts b/clients/admin-ui/src/types/api/models/Layer1ButtonOption.ts new file mode 100644 index 0000000000..62f85a90cb --- /dev/null +++ b/clients/admin-ui/src/types/api/models/Layer1ButtonOption.ts @@ -0,0 +1,11 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +/** + * Layer 1 button options - not formalized in the db + */ +export enum Layer1ButtonOption { + ACKNOWLEDGE = "acknowledge", + OPT_IN_OPT_OUT = "opt_in_opt_out", +} diff --git a/clients/admin-ui/src/types/api/models/PrivacyExperienceResponse.ts b/clients/admin-ui/src/types/api/models/PrivacyExperienceResponse.ts index fcb6b5532a..507319f409 100644 --- a/clients/admin-ui/src/types/api/models/PrivacyExperienceResponse.ts +++ b/clients/admin-ui/src/types/api/models/PrivacyExperienceResponse.ts @@ -57,6 +57,7 @@ export type PrivacyExperienceResponse = { */ experience_config?: ExperienceConfigResponseNoNotices; gvl?: any; + gvl_translations?: any; available_locales?: Array; meta?: ExperienceMeta; }; diff --git a/clients/admin-ui/src/types/api/models/SnowflakeDocsSchema.ts b/clients/admin-ui/src/types/api/models/SnowflakeDocsSchema.ts index 8379feebdd..0036047ecd 100644 --- a/clients/admin-ui/src/types/api/models/SnowflakeDocsSchema.ts +++ b/clients/admin-ui/src/types/api/models/SnowflakeDocsSchema.ts @@ -15,9 +15,17 @@ export type SnowflakeDocsSchema = { */ user_login_name: string; /** - * The password used to authenticate and access the database. + * The password used to authenticate and access the database. You can use a password or a private key, but not both. */ - password: string; + password?: string; + /** + * The private key used to authenticate and access the database. If a `private_key_passphrase` is also provided, it is assumed to be encrypted; otherwise, it is assumed to be unencrypted. + */ + private_key?: string; + /** + * The passphrase used for the encrypted private key. + */ + private_key_passphrase?: string; /** * The name of the Snowflake warehouse where your queries will be executed. */ From 5c89a82738b4380bbbc9f8fdd21cee4c40859482 Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Fri, 9 Aug 2024 13:41:27 -0500 Subject: [PATCH 04/17] fix getRowIsClickable --- .../cypress/e2e/discovery-detection.cy.ts | 4 +++- .../features/common/table/v2/FidesTable.tsx | 22 +++++++++++++------ .../tables/DetectionResultTable.tsx | 4 +++- .../tables/DiscoveryResultTable.tsx | 2 +- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts b/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts index 6f6364bd71..f277d9ca30 100644 --- a/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts +++ b/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts @@ -250,7 +250,7 @@ describe("discovery and detection", () => { }); }); - describe("field-level view", () => { + describe.only("field-level view", () => { beforeEach(() => { cy.intercept("GET", "/api/v1/plus/discovery-monitor/results?*", { fixture: "detection-discovery/results/detection/field-list.json", @@ -258,9 +258,11 @@ describe("discovery and detection", () => { cy.visit( `${DATA_DETECTION_ROUTE}/my_bigquery_monitor.prj-bigquery-418515.test_dataset_1.consent-reports-20`, ); + cy.wait("@getDetectionFields"); }); it("should show columns for fields", () => { + cy.getByTestId("fidesTable-body").should("exist"); cy.getByTestId("column-name").should("contain", "Field name"); }); diff --git a/clients/admin-ui/src/features/common/table/v2/FidesTable.tsx b/clients/admin-ui/src/features/common/table/v2/FidesTable.tsx index eb1ce36068..b591281b62 100644 --- a/clients/admin-ui/src/features/common/table/v2/FidesTable.tsx +++ b/clients/admin-ui/src/features/common/table/v2/FidesTable.tsx @@ -188,7 +188,11 @@ type Props = { rowActionBar?: ReactNode; footer?: ReactNode; onRowClick?: (row: T, e: React.MouseEvent) => void; - rowIsClickable?: (row: T) => boolean; + /** + * Optional function to filter whether onRowClick should be enabled based on + * the row data. If not provided, onRowClick will be enabled for all rows. + */ + getRowIsClickable?: (row: T) => boolean; renderRowTooltipLabel?: (row: Row) => string | undefined; emptyTableNotice?: ReactNode; overflow?: "auto" | "visible" | "hidden"; @@ -200,15 +204,19 @@ const TableBody = ({ tableInstance, rowActionBar, onRowClick, - rowIsClickable, + getRowIsClickable, renderRowTooltipLabel, displayAllColumns, emptyTableNotice, }: Omit, "footer" | "enableSorting" | "onSort"> & { displayAllColumns: string[]; }) => { - const getRowClickHandler = (row: T) => - rowIsClickable && rowIsClickable(row) ? onRowClick : undefined; + const getRowClickHandler = (row: T) => { + if (!getRowIsClickable) { + return onRowClick; + } + return getRowIsClickable(row) ? onRowClick : undefined; + }; return ( @@ -251,7 +259,7 @@ export const FidesTableV2 = ({ rowActionBar, footer, onRowClick, - rowIsClickable, + getRowIsClickable, renderRowTooltipLabel, emptyTableNotice, overflow = "auto", @@ -374,7 +382,7 @@ export const FidesTableV2 = ({ tableInstance={tableInstance} rowActionBar={rowActionBar} onRowClick={onRowClick} - rowIsClickable={rowIsClickable} + getRowIsClickable={getRowIsClickable} renderRowTooltipLabel={renderRowTooltipLabel} displayAllColumns={displayAllColumns} emptyTableNotice={emptyTableNotice} @@ -384,7 +392,7 @@ export const FidesTableV2 = ({ tableInstance={tableInstance} rowActionBar={rowActionBar} onRowClick={onRowClick} - rowIsClickable={rowIsClickable} + getRowIsClickable={getRowIsClickable} renderRowTooltipLabel={renderRowTooltipLabel} displayAllColumns={displayAllColumns} emptyTableNotice={emptyTableNotice} diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/tables/DetectionResultTable.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/tables/DetectionResultTable.tsx index bec468e2f9..0b5eee70ca 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/tables/DetectionResultTable.tsx +++ b/clients/admin-ui/src/features/data-discovery-and-detection/tables/DetectionResultTable.tsx @@ -122,6 +122,8 @@ const DetectionResultTable = ({ resourceUrn }: MonitorResultTableProps) => { const { columns } = useDetectionResultColumns({ resourceType }); + console.log(columns); + const { items: data, total: totalRows, @@ -194,7 +196,7 @@ const DetectionResultTable = ({ resourceUrn }: MonitorResultTableProps) => { } /> { } overflow="visible" /> From 3b2136a57297d6ecb04193c8472d5be8074cac9c Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Fri, 9 Aug 2024 14:41:50 -0500 Subject: [PATCH 05/17] update tests --- .../cypress/e2e/discovery-detection.cy.ts | 16 ++++++++-- .../results/detection/field-list.json | 24 ++++++++++++++- .../results/discovery/field-list.json | 29 +++++++++++++++++++ .../tables/DetectionResultTable.tsx | 2 -- .../types/StagedResourceType.ts | 1 - .../utils/findResourceType.ts | 5 +--- 6 files changed, 66 insertions(+), 11 deletions(-) diff --git a/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts b/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts index f277d9ca30..d88b714924 100644 --- a/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts +++ b/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts @@ -250,7 +250,7 @@ describe("discovery and detection", () => { }); }); - describe.only("field-level view", () => { + describe("field-level view", () => { beforeEach(() => { cy.intercept("GET", "/api/v1/plus/discovery-monitor/results?*", { fixture: "detection-discovery/results/detection/field-list.json", @@ -266,7 +266,12 @@ describe("discovery and detection", () => { cy.getByTestId("column-name").should("contain", "Field name"); }); - it("should not allow navigation via row clicking", () => { + it("should allow navigation via row clicking on nested fields", () => { + cy.getByTestId("row-my_bigquery_monitor-address").click(); + cy.url().should("contain", "address"); + }); + + it("should not allow navigation via row clicking on non-nested fields", () => { cy.getByTestId("row-my_bigquery_monitor-User_geography").click(); cy.url().should("not.contain", "User_geography"); }); @@ -353,7 +358,12 @@ describe("discovery and detection", () => { }); }); - it("should not allow navigation via row clicking", () => { + it("should allow navigation via row clicking on nested fields", () => { + cy.getByTestId("row-my_bigquery_monitor-address").click(); + cy.url().should("contain", "address"); + }); + + it("should not allow navigation via row clicking on non-nested fields", () => { cy.getByTestId( "row-my_bigquery_monitor-User_geography-col-name", ).click(); diff --git a/clients/admin-ui/cypress/fixtures/detection-discovery/results/detection/field-list.json b/clients/admin-ui/cypress/fixtures/detection-discovery/results/detection/field-list.json index 4a7046dc42..7437d2d6dd 100644 --- a/clients/admin-ui/cypress/fixtures/detection-discovery/results/detection/field-list.json +++ b/clients/admin-ui/cypress/fixtures/detection-discovery/results/detection/field-list.json @@ -152,9 +152,31 @@ "data_type": "string", "schema_name": "test_dataset_1", "database_name": "prj-bigquery-418515" + }, + { + "urn": "my_bigquery_monitor.prj-bigquery-418515.test_dataset_1.consent-reports-20.address", + "user_assigned_data_categories": [], + "name": "address", + "description": null, + "monitor_config_id": "my_bigquery_monitor", + "updated_at": null, + "source_modified": null, + "classifications": [], + "diff_status": "addition", + "child_diff_statuses": {}, + "table_name": "consent-reports-20", + "parent_table_urn": "my_bigquery_monitor.prj-bigquery-418515.test_dataset_1.consent-reports-20", + "data_type": "string", + "schema_name": "test_dataset_1", + "database_name": "prj-bigquery-418515", + "sub_field_urns": [ + "my_bigquery_monitor.prj-bigquery-418515.test_dataset_1.consent-reports-20.address.City", + "my_bigquery_monitor.prj-bigquery-418515.test_dataset_1.consent-reports-20.address.State", + "my_bigquery_monitor.prj-bigquery-418515.test_dataset_1.consent-reports-20.address.Zip" + ] } ], - "total": 9, + "total": 10, "page": 1, "size": 25, "pages": 1 diff --git a/clients/admin-ui/cypress/fixtures/detection-discovery/results/discovery/field-list.json b/clients/admin-ui/cypress/fixtures/detection-discovery/results/discovery/field-list.json index 1e5f6c7696..46ec0f8720 100644 --- a/clients/admin-ui/cypress/fixtures/detection-discovery/results/discovery/field-list.json +++ b/clients/admin-ui/cypress/fixtures/detection-discovery/results/discovery/field-list.json @@ -281,6 +281,35 @@ "data_type": "string", "schema_name": "test_dataset_1", "database_name": "prj-bigquery-418515" + }, + { + "urn": "my_bigquery_monitor.prj-bigquery-418515.test_dataset_1.consent-reports-20.address", + "user_assigned_data_categories": [], + "name": "address", + "description": null, + "monitor_config_id": "my_bigquery_monitor", + "updated_at": null, + "source_modified": null, + "classifications": [ + { + "label": "system", + "score": 1.0, + "aggregated_score": 0.55, + "classification_paradigm": "context" + } + ], + "diff_status": "addition", + "child_diff_statuses": {}, + "table_name": "consent-reports-20", + "parent_table_urn": "my_bigquery_monitor.prj-bigquery-418515.test_dataset_1.consent-reports-20", + "schema_name": "test_dataset_1", + "database_name": "prj-bigquery-418515", + "sub_field_urns": [ + "my_bigquery_monitor.prj-bigquery-418515.test_dataset_1.consent-reports-20.address.city", + "my_bigquery_monitor.prj-bigquery-418515.test_dataset_1.consent-reports-20.address.country", + "my_bigquery_monitor.prj-bigquery-418515.test_dataset_1.consent-reports-20.address.postal_code", + "my_bigquery_monitor.prj-bigquery-418515.test_dataset_1.consent-reports-20.address.state" + ] } ], "total": 9, diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/tables/DetectionResultTable.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/tables/DetectionResultTable.tsx index 0b5eee70ca..3371e2b708 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/tables/DetectionResultTable.tsx +++ b/clients/admin-ui/src/features/data-discovery-and-detection/tables/DetectionResultTable.tsx @@ -122,8 +122,6 @@ const DetectionResultTable = ({ resourceUrn }: MonitorResultTableProps) => { const { columns } = useDetectionResultColumns({ resourceType }); - console.log(columns); - const { items: data, total: totalRows, diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/types/StagedResourceType.ts b/clients/admin-ui/src/features/data-discovery-and-detection/types/StagedResourceType.ts index 7a0d0ab2f5..1b4afbabf3 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/types/StagedResourceType.ts +++ b/clients/admin-ui/src/features/data-discovery-and-detection/types/StagedResourceType.ts @@ -3,6 +3,5 @@ export enum StagedResourceType { SCHEMA = "Schema", TABLE = "Table", FIELD = "Field", - NESTED_FIELD = "Nested Field", NONE = "none", } diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/utils/findResourceType.ts b/clients/admin-ui/src/features/data-discovery-and-detection/utils/findResourceType.ts index cf272577b5..5974a5e43f 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/utils/findResourceType.ts +++ b/clients/admin-ui/src/features/data-discovery-and-detection/utils/findResourceType.ts @@ -15,8 +15,5 @@ export const findResourceType = (item: DiscoveryMonitorItem | undefined) => { if (item.fields) { return StagedResourceType.TABLE; } - if (item.parent_table_urn) { - return StagedResourceType.FIELD; - } - return StagedResourceType.NESTED_FIELD; + return StagedResourceType.FIELD; }; From 120be20267ae720c2df60fe3e16dba49a0aac1ee Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Fri, 9 Aug 2024 15:05:18 -0500 Subject: [PATCH 06/17] unify header appearances --- .../admin-ui/src/pages/data-discovery/detection/index.tsx | 6 ++---- .../admin-ui/src/pages/data-discovery/discovery/index.tsx | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/clients/admin-ui/src/pages/data-discovery/detection/index.tsx b/clients/admin-ui/src/pages/data-discovery/detection/index.tsx index de55a503ad..04c1b887f5 100644 --- a/clients/admin-ui/src/pages/data-discovery/detection/index.tsx +++ b/clients/admin-ui/src/pages/data-discovery/detection/index.tsx @@ -11,13 +11,11 @@ const DataDetectionActivityPage = () => ( - - Data detection - + Data detection diff --git a/clients/admin-ui/src/pages/data-discovery/discovery/index.tsx b/clients/admin-ui/src/pages/data-discovery/discovery/index.tsx index c407256eef..ac38ac1dd3 100644 --- a/clients/admin-ui/src/pages/data-discovery/discovery/index.tsx +++ b/clients/admin-ui/src/pages/data-discovery/discovery/index.tsx @@ -11,13 +11,11 @@ const DataDiscoveryActivityPage = () => ( - - Data discovery - + Data discovery From 53d4d856120ef993d2889f86f2856f5f6b379727 Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Fri, 9 Aug 2024 15:13:18 -0500 Subject: [PATCH 07/17] add docstring --- .../data-discovery-and-detection/utils/isNestedField.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/utils/isNestedField.ts b/clients/admin-ui/src/features/data-discovery-and-detection/utils/isNestedField.ts index 1de853738f..33dd1d92c4 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/utils/isNestedField.ts +++ b/clients/admin-ui/src/features/data-discovery-and-detection/utils/isNestedField.ts @@ -1,5 +1,10 @@ import { DiscoveryMonitorItem } from "~/features/data-discovery-and-detection/types/DiscoveryMonitorItem"; +/** + * Helper method to determine whether a resource is a "top-level" field. + * `true` if the resource is at top-level nested field; `false`if the + * resource is not a field, has no subfields, or is a subfield of another field + */ const isNestedField = (resource: DiscoveryMonitorItem): boolean => { if (!resource.parent_table_urn) { // resource is not a field From eea84a78b364ddf9148c9e24d771aaafa40abd94 Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Fri, 9 Aug 2024 15:18:24 -0500 Subject: [PATCH 08/17] remove deprecated column defs --- .../hooks/useDiscoveryResultColumns.tsx | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/hooks/useDiscoveryResultColumns.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/hooks/useDiscoveryResultColumns.tsx index ed005669cf..17f8b87571 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/hooks/useDiscoveryResultColumns.tsx +++ b/clients/admin-ui/src/features/data-discovery-and-detection/hooks/useDiscoveryResultColumns.tsx @@ -169,40 +169,6 @@ const useDiscoveryResultColumns = ({ return { columns }; } - if (resourceType === StagedResourceType.NESTED_FIELD) { - const columns = [ - columnHelper.accessor((row) => row.name, { - id: "name", - cell: (props) => , - header: (props) => ( - - ), - }), - columnHelper.display({ - id: "type", - cell: () => , - header: "Type", - }), - columnHelper.accessor((row) => row.monitor_config_id, { - id: "monitor", - cell: (props) => , - header: (props) => , - }), - columnHelper.accessor((row) => row.source_modified, { - id: "time", - cell: (props) => , - header: (props) => , - }), - columnHelper.display({ - id: "actions", - cell: (props) => , - header: "Actions", - }), - ]; - - return { columns }; - } - return { columns: defaultColumns }; }; From 1179568d265351bac846d469e1265bfdead0676c Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Fri, 9 Aug 2024 15:35:37 -0500 Subject: [PATCH 09/17] regenerate types --- clients/admin-ui/src/types/api/models/Field.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/clients/admin-ui/src/types/api/models/Field.ts b/clients/admin-ui/src/types/api/models/Field.ts index 528bf9e5e7..75938d15ad 100644 --- a/clients/admin-ui/src/types/api/models/Field.ts +++ b/clients/admin-ui/src/types/api/models/Field.ts @@ -32,4 +32,5 @@ export type Field = { data_type?: string; sub_field_urns?: Array; direct_child_urns?: Array; + top_level_field_name?: string; }; From 9b71ae7148a43cf35f6ea73731e7d9ccf272ed82 Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Fri, 9 Aug 2024 15:46:07 -0500 Subject: [PATCH 10/17] disable row click on data category picker --- .../hooks/useDiscoveryResultColumns.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/hooks/useDiscoveryResultColumns.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/hooks/useDiscoveryResultColumns.tsx index 17f8b87571..1a35a2e32a 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/hooks/useDiscoveryResultColumns.tsx +++ b/clients/admin-ui/src/features/data-discovery-and-detection/hooks/useDiscoveryResultColumns.tsx @@ -151,7 +151,7 @@ const useDiscoveryResultColumns = ({ cell: ({ row }) => { return ; }, - meta: { overflow: "visible" }, + meta: { overflow: "visible", disableRowClick: true }, header: "Data category", minSize: 280, // keep a minimum width so the Select has space to display the options properly }), From 708912acb4b2e78b6ab3c37eb1061b6746d81cef Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Mon, 12 Aug 2024 09:59:44 -0500 Subject: [PATCH 11/17] don't show discovery actions for subfields --- .../DiscoveryItemActions.tsx | 14 ++++++++++---- .../utils/isNestedField.ts | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryItemActions.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryItemActions.tsx index a3f60aa5d8..04ec84e19f 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryItemActions.tsx +++ b/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryItemActions.tsx @@ -1,6 +1,7 @@ import { ButtonSpinner, CheckIcon, HStack, ViewOffIcon } from "fidesui"; import { useState } from "react"; +import { TOP_LEVEL_FIELD_URN_LENGTH } from "~/features/data-discovery-and-detection/utils/isNestedField"; import { DiffStatus, StagedResource } from "~/types/api"; import ActionButton from "./ActionButton"; @@ -22,11 +23,16 @@ const DiscoveryItemActions = ({ resource }: DiscoveryItemActionsProps) => { const [isProcessingAction, setIsProcessingAction] = useState(false); - const { diff_status: diffStatus, child_diff_statuses: childDiffStatus } = - resource; + const { + diff_status: diffStatus, + child_diff_statuses: childDiffStatus, + urn, + } = resource; - // No actions for database level - if (resourceType === StagedResourceType.DATABASE) { + const isSubField = urn.split(".").length > TOP_LEVEL_FIELD_URN_LENGTH; + + // No actions for database level or for nested field subfields + if (resourceType === StagedResourceType.DATABASE || isSubField) { return null; } diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/utils/isNestedField.ts b/clients/admin-ui/src/features/data-discovery-and-detection/utils/isNestedField.ts index 33dd1d92c4..23c36077ae 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/utils/isNestedField.ts +++ b/clients/admin-ui/src/features/data-discovery-and-detection/utils/isNestedField.ts @@ -1,5 +1,7 @@ import { DiscoveryMonitorItem } from "~/features/data-discovery-and-detection/types/DiscoveryMonitorItem"; +export const TOP_LEVEL_FIELD_URN_LENGTH = 5; + /** * Helper method to determine whether a resource is a "top-level" field. * `true` if the resource is at top-level nested field; `false`if the From f1eeebba52af26c6c9293a47f009aa6d3104a86e Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Mon, 12 Aug 2024 13:40:26 -0500 Subject: [PATCH 12/17] fix type error --- clients/admin-ui/src/mocks/data.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/clients/admin-ui/src/mocks/data.ts b/clients/admin-ui/src/mocks/data.ts index 2cbb3f877c..080d980ad2 100644 --- a/clients/admin-ui/src/mocks/data.ts +++ b/clients/admin-ui/src/mocks/data.ts @@ -273,13 +273,11 @@ export const mockConsentableItems: ConsentableItem[] = [ external_id: "34419", type: "Channel", name: "Default SMS channel (SMS)", - notice_id: null, children: [ { external_id: "40007", type: "Message type", name: "Default SMS message type", - notice_id: null, children: [], unmapped: true, }, @@ -290,13 +288,11 @@ export const mockConsentableItems: ConsentableItem[] = [ external_id: "34415", type: "Channel", name: "Default InApp channel (InApp)", - notice_id: null, children: [ { external_id: "40003", type: "Message type", name: "Default InApp message type", - notice_id: null, children: [], unmapped: true, }, @@ -307,13 +303,11 @@ export const mockConsentableItems: ConsentableItem[] = [ external_id: "33843", type: "Channel", name: "Push Marketing Channel (Push)", - notice_id: null, children: [ { external_id: "39240", type: "Message type", name: "Push Marketing Message", - notice_id: null, children: [], unmapped: true, }, @@ -324,13 +318,11 @@ export const mockConsentableItems: ConsentableItem[] = [ external_id: "33842", type: "Channel", name: "Transactional Channel (Email)", - notice_id: null, children: [ { external_id: "39239", type: "Message type", name: "Transactional Message", - notice_id: null, children: [], unmapped: true, }, @@ -341,13 +333,11 @@ export const mockConsentableItems: ConsentableItem[] = [ external_id: "33841", type: "Channel", name: "Marketing Channel (Email)", - notice_id: null, children: [ { external_id: "40000", type: "Message type", name: "Untitled message type", - notice_id: null, children: [], unmapped: true, }, @@ -355,7 +345,6 @@ export const mockConsentableItems: ConsentableItem[] = [ external_id: "39238", type: "Message type", name: "Marketing Message", - notice_id: null, children: [], unmapped: true, }, From 5e74301deac32f291e4552534b61d84022a859b8 Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Mon, 12 Aug 2024 14:00:14 -0500 Subject: [PATCH 13/17] fix Cypress test --- clients/admin-ui/cypress/e2e/discovery-detection.cy.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts b/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts index d88b714924..b84a6c8ad2 100644 --- a/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts +++ b/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts @@ -358,8 +358,8 @@ describe("discovery and detection", () => { }); }); - it("should allow navigation via row clicking on nested fields", () => { - cy.getByTestId("row-my_bigquery_monitor-address").click(); + it.only("should allow navigation via row clicking on nested fields", () => { + cy.getByTestId("row-my_bigquery_monitor-address-col-name").click(); cy.url().should("contain", "address"); }); From 9a09d711159b90680844b19457bdd0deb6d376fa Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Mon, 12 Aug 2024 14:01:25 -0500 Subject: [PATCH 14/17] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae49f41321..466a85008e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ The types of changes are: ### Added - Added support for mapping a system's inegration's consentable items to privacy notices [#5156](https://github.com/ethyca/fides/pull/5156) +- Added support for nested fields in BigQuery in D&D result views [#5175](https://github.com/ethyca/fides/pull/5175) ### Fixed - Fixed the OAuth2 configuration for the Snap integration [#5158](https://github.com/ethyca/fides/pull/5158) From 2bca10a4cba505fee0463c07982456d9e367ddc9 Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Mon, 12 Aug 2024 14:01:39 -0500 Subject: [PATCH 15/17] remove .only --- clients/admin-ui/cypress/e2e/discovery-detection.cy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts b/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts index b84a6c8ad2..ddc7a91007 100644 --- a/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts +++ b/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts @@ -358,7 +358,7 @@ describe("discovery and detection", () => { }); }); - it.only("should allow navigation via row clicking on nested fields", () => { + it("should allow navigation via row clicking on nested fields", () => { cy.getByTestId("row-my_bigquery_monitor-address-col-name").click(); cy.url().should("contain", "address"); }); From 625f60abf8f281ba3986c369aade26fd6992a802 Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Tue, 13 Aug 2024 13:41:30 -0500 Subject: [PATCH 16/17] remove button to confirm subfields --- .../DiscoveryItemActions.tsx | 16 +++++++++------- .../tables/DiscoveryResultTable.tsx | 1 - .../types/DiscoveryMonitorItem.ts | 4 +++- .../utils/isNestedField.ts | 7 +++---- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryItemActions.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryItemActions.tsx index 04ec84e19f..de66468596 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryItemActions.tsx +++ b/clients/admin-ui/src/features/data-discovery-and-detection/DiscoveryItemActions.tsx @@ -1,8 +1,8 @@ import { ButtonSpinner, CheckIcon, HStack, ViewOffIcon } from "fidesui"; import { useState } from "react"; -import { TOP_LEVEL_FIELD_URN_LENGTH } from "~/features/data-discovery-and-detection/utils/isNestedField"; -import { DiffStatus, StagedResource } from "~/types/api"; +import { DiscoveryMonitorItem } from "~/features/data-discovery-and-detection/types/DiscoveryMonitorItem"; +import { DiffStatus } from "~/types/api"; import ActionButton from "./ActionButton"; import { @@ -13,7 +13,7 @@ import { StagedResourceType } from "./types/StagedResourceType"; import { findResourceType } from "./utils/findResourceType"; interface DiscoveryItemActionsProps { - resource: StagedResource; + resource: DiscoveryMonitorItem; } const DiscoveryItemActions = ({ resource }: DiscoveryItemActionsProps) => { @@ -26,13 +26,14 @@ const DiscoveryItemActions = ({ resource }: DiscoveryItemActionsProps) => { const { diff_status: diffStatus, child_diff_statuses: childDiffStatus, - urn, + // eslint-disable-next-line @typescript-eslint/naming-convention + top_level_field_name, } = resource; - const isSubField = urn.split(".").length > TOP_LEVEL_FIELD_URN_LENGTH; + const isSubField = !!top_level_field_name; // No actions for database level or for nested field subfields - if (resourceType === StagedResourceType.DATABASE || isSubField) { + if (resourceType === StagedResourceType.DATABASE) { return null; } @@ -46,7 +47,8 @@ const DiscoveryItemActions = ({ resource }: DiscoveryItemActionsProps) => { childDiffStatus[DiffStatus.CLASSIFICATION_UPDATE]); const showPromoteAction = - itemHasClassificationChanges || childItemsHaveClassificationChanges; + (itemHasClassificationChanges || childItemsHaveClassificationChanges) && + !isSubField; const showMuteAction = itemHasClassificationChanges || childItemsHaveClassificationChanges; diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/tables/DiscoveryResultTable.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/tables/DiscoveryResultTable.tsx index 695cab0aa3..b6d10b007d 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/tables/DiscoveryResultTable.tsx +++ b/clients/admin-ui/src/features/data-discovery-and-detection/tables/DiscoveryResultTable.tsx @@ -176,7 +176,6 @@ const DiscoveryResultTable = ({ resourceUrn }: MonitorResultTableProps) => { onRowClick={handleRowClicked} getRowIsClickable={getRowIsClickable} emptyTableNotice={} - overflow="visible" /> ; diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/utils/isNestedField.ts b/clients/admin-ui/src/features/data-discovery-and-detection/utils/isNestedField.ts index 23c36077ae..183538b2e9 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/utils/isNestedField.ts +++ b/clients/admin-ui/src/features/data-discovery-and-detection/utils/isNestedField.ts @@ -1,7 +1,5 @@ import { DiscoveryMonitorItem } from "~/features/data-discovery-and-detection/types/DiscoveryMonitorItem"; -export const TOP_LEVEL_FIELD_URN_LENGTH = 5; - /** * Helper method to determine whether a resource is a "top-level" field. * `true` if the resource is at top-level nested field; `false`if the @@ -13,10 +11,11 @@ const isNestedField = (resource: DiscoveryMonitorItem): boolean => { return false; } if (!resource.sub_field_urns?.length) { + // resource has no children return false; } - // make sure field is not a subfield - return resource.urn.split(".").length === 5; + // only true if resource is not a child of another field + return !resource.top_level_field_name; }; export default isNestedField; From d1b9603ae95f7164be967ead7688d05ecfc91ecf Mon Sep 17 00:00:00 2001 From: Jeremy Pople Date: Wed, 14 Aug 2024 09:18:31 -0500 Subject: [PATCH 17/17] fix changelog --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96a1dfc8f0..d335832f58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,6 @@ The types of changes are: ## [Unreleased](https://github.com/ethyca/fides/compare/2.42.1...main) ### Added -- Added support for mapping a system's inegration's consentable items to privacy notices [#5156](https://github.com/ethyca/fides/pull/5156) - Added support for mapping a system's integration's consentable items to privacy notices [#5156](https://github.com/ethyca/fides/pull/5156) - Added support for SSO Login with multiple providers (Fides Plus feature) [#5134](https://github.com/ethyca/fides/pull/5134) - Adds user_read scope to approver role so that they can update their own password [#5178](https://github.com/ethyca/fides/pull/5178)