From 60d005ec373be968133b4aa40f7c322f1feed8b3 Mon Sep 17 00:00:00 2001 From: jpople Date: Tue, 20 Aug 2024 14:36:41 -0500 Subject: [PATCH] Classifier category badge updates (#5212) --- CHANGELOG.md | 2 + .../cypress/e2e/discovery-detection.cy.ts | 24 +++++- .../results/discovery/field-list.json | 26 +++++-- .../ClassificationCategoryBadge.tsx | 33 ++++++++ .../TaxonomyDisplayAndEdit.tsx | 77 +++++++++++-------- .../tables/ResultStatusBadgeCell.tsx | 29 ++++--- 6 files changed, 140 insertions(+), 51 deletions(-) create mode 100644 clients/admin-ui/src/features/data-discovery-and-detection/ClassificationCategoryBadge.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 77334bc35a5..f666b977df8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ The types of changes are: - Ignore `404` errors on Oracle Responsys deletions [#5203](https://github.com/ethyca/fides/pull/5203) - Fix white screen issue when privacy request has null value for daysLeft [#5213](https://github.com/ethyca/fides/pull/5213) +### Changed +- Visual updates to badges in D&D result tables [#5212](https://github.com/ethyca/fides/pull/5212) ## [2.43.0](https://github.com/ethyca/fides/compare/2.42.1...2.43.0) diff --git a/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts b/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts index a5ce6884793..a155d21344a 100644 --- a/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts +++ b/clients/admin-ui/cypress/e2e/discovery-detection.cy.ts @@ -367,13 +367,31 @@ describe("discovery and detection", () => { cy.getByTestId( "row-my_bigquery_monitor-Test-col-classifications", ).within(() => { - cy.getByTestId("classification-user.contact.phone_number").should( - "exist", - ); + cy.getByTestId( + "user-classification-user.contact.phone_number", + ).should("exist"); cy.getByTestId("add-category-btn").click(); cy.get(".select-wrapper").should("exist"); }); }); + + it("shows 'None' when no categories are assigned", () => { + cy.getByTestId( + "row-my_bigquery_monitor-No_categories-col-classifications", + ).within(() => { + cy.getByTestId("no-classifications").should("exist"); + cy.getByTestId("add-category-btn").should("exist"); + }); + }); + + it("doesn't allow adding categories on fields with subfields", () => { + cy.getByTestId( + "row-my_bigquery_monitor-address-col-classifications", + ).within(() => { + cy.getByTestId("no-classifications").should("exist"); + cy.getByTestId("add-category-btn").should("not.exist"); + }); + }); }); }); }); 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 46ec0f8720b..33a1b95af33 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 @@ -290,14 +290,7 @@ "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" - } - ], + "classifications": [], "diff_status": "addition", "child_diff_statuses": {}, "table_name": "consent-reports-20", @@ -310,6 +303,23 @@ "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" ] + }, + { + "urn": "my_bigquery_monitor.prj-bigquery-418515.test_dataset_1.consent-reports-20.No_categories", + "user_assigned_data_categories": [], + "name": "No_categories", + "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", + "schema_name": "test_dataset_1", + "database_name": "prj-bigquery-418515", + "sub_field_urns": [] } ], "total": 9, diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/ClassificationCategoryBadge.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/ClassificationCategoryBadge.tsx new file mode 100644 index 00000000000..b485bceab25 --- /dev/null +++ b/clients/admin-ui/src/features/data-discovery-and-detection/ClassificationCategoryBadge.tsx @@ -0,0 +1,33 @@ +import { Flex, FlexProps } from "fidesui"; + +interface ClassificationCategoryBadgeProps extends FlexProps { + classification?: string | JSX.Element; + children: React.ReactNode; +} + +const ClassificationCategoryBadge = ({ + children, + onClick, + ...props +}: ClassificationCategoryBadgeProps) => { + return ( + + {children} + + ); +}; + +export default ClassificationCategoryBadge; diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/TaxonomyDisplayAndEdit.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/TaxonomyDisplayAndEdit.tsx index c685e4ccd6a..33306965598 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/TaxonomyDisplayAndEdit.tsx +++ b/clients/admin-ui/src/features/data-discovery-and-detection/TaxonomyDisplayAndEdit.tsx @@ -1,6 +1,6 @@ import { - Badge, Box, + ButtonProps, CloseIcon, EditIcon, IconButton, @@ -10,7 +10,9 @@ import { import { useCallback, useState } from "react"; import useTaxonomies from "~/features/common/hooks/useTaxonomies"; -import { StagedResource } from "~/types/api"; +import { SparkleIcon } from "~/features/common/Icon/SparkleIcon"; +import ClassificationCategoryBadge from "~/features/data-discovery-and-detection/ClassificationCategoryBadge"; +import { DiscoveryMonitorItem } from "~/features/data-discovery-and-detection/types/DiscoveryMonitorItem"; import TaxonomySelectDropdown, { TaxonomySelectOption, @@ -18,8 +20,22 @@ import TaxonomySelectDropdown, { import { useOutsideClick } from "../common/hooks"; import { useUpdateResourceCategoryMutation } from "./discovery-detection.slice"; +const AddCategoryButton = (props: ButtonProps) => ( + } + data-testid="add-category-btn" + aria-label="Add category" + {...props} + /> +); + interface TaxonomyDisplayAndEditProps { - resource: StagedResource; + resource: DiscoveryMonitorItem; } const TaxonomyDisplayAndEdit = ({ resource }: TaxonomyDisplayAndEditProps) => { @@ -38,9 +54,9 @@ const TaxonomyDisplayAndEdit = ({ resource }: TaxonomyDisplayAndEditProps) => { const userCategories = resource.user_assigned_data_categories ?? []; - if (!bestClassifiedCategory && !userCategories?.length) { - return None; - } + const noCategories = !bestClassifiedCategory && !userCategories?.length; + + const hasSubfields = resource.sub_field_urns?.length; const handleAddCategory = (option: TaxonomySelectOption) => { updateResourceCategoryMutation({ @@ -74,52 +90,51 @@ const TaxonomyDisplayAndEdit = ({ resource }: TaxonomyDisplayAndEditProps) => { overflowX="auto" ref={ref} > + {noCategories && ( + <> + + None + + {/* resources with child fields can't have data categories */} + {!hasSubfields && ( + setIsAdding(true)} /> + )} + + )} + {showUserCategories && ( <> {userCategories.map((category) => ( - {getDataCategoryDisplayName(category)} handleRemoveCategory(category)} icon={} size="2xs" - mt={-0.5} - ml={2} + ml={1} aria-label="Remove category" /> - + ))} - } - onClick={() => setIsAdding(true)} - data-testid="add-category-btn" - aria-label="Add category" - /> + setIsAdding(true)} /> )} {showClassificationResult && ( - setIsAdding(true)} cursor="pointer" data-testid={`classification-${bestClassifiedCategory}`} > - {getDataCategoryDisplayName(bestClassifiedCategory)}{" "} - - + + {getDataCategoryDisplayName(bestClassifiedCategory)} + + )} {isAdding && ( diff --git a/clients/admin-ui/src/features/data-discovery-and-detection/tables/ResultStatusBadgeCell.tsx b/clients/admin-ui/src/features/data-discovery-and-detection/tables/ResultStatusBadgeCell.tsx index 10c36538871..a001e95916b 100644 --- a/clients/admin-ui/src/features/data-discovery-and-detection/tables/ResultStatusBadgeCell.tsx +++ b/clients/admin-ui/src/features/data-discovery-and-detection/tables/ResultStatusBadgeCell.tsx @@ -1,9 +1,21 @@ -import { Badge } from "fidesui"; +import { Badge, BadgeProps } from "fidesui"; import { ResourceChangeType } from "~/features/data-discovery-and-detection/types/ResourceChangeType"; import findResourceChangeType from "~/features/data-discovery-and-detection/utils/findResourceChangeType"; import { StagedResource } from "~/types/api"; +interface ResultStatusBadgeProps extends BadgeProps { + colorScheme: string; +} + +const ResultStatusBadge = ({ children, ...props }: ResultStatusBadgeProps) => { + return ( + + {children} + + ); +}; + const ResultStatusBadgeCell = ({ result, changeTypeOverride, @@ -11,25 +23,24 @@ const ResultStatusBadgeCell = ({ result: StagedResource; changeTypeOverride?: ResourceChangeType; }) => { + if (result.user_assigned_data_categories?.length) { + return Reviewed; + } const changeType = changeTypeOverride ?? findResourceChangeType(result); switch (changeType) { case ResourceChangeType.MUTED: return ( - - Unmonitored - + Unmonitored ); case ResourceChangeType.MONITORED: return ( - - Monitoring - + Monitoring ); default: return ( - + Pending review - + ); } };