Skip to content

Commit

Permalink
Initial systems management page (#1054)
Browse files Browse the repository at this point in the history
* Rename SystemsTable to SystemsGrid

* Add BorderGrid component to abstract out grid

* Build out SystemCard

* Add search feature

* Pull SystemCard out into its own component

* Add cypress tests for system management page

* Update changelog

* Fix nav bar test
  • Loading branch information
allisonking authored Sep 9, 2022
1 parent b9e127a commit 6352fd9
Show file tree
Hide file tree
Showing 13 changed files with 354 additions and 62 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ The types of changes are:

## [Unreleased](https://github.com/ethyca/fides/compare/1.8.3...main)

### Added

* Initial system management page [#1054](https://github.com/ethyca/fides/pull/1054)

### Changed

* Deleting a taxonomy field with children will now cascade delete all of its children as well. [#1042](https://github.com/ethyca/fides/pull/1042)
Expand Down
23 changes: 0 additions & 23 deletions clients/ctl/admin-ui/__tests__/features/system.test.tsx

This file was deleted.

3 changes: 2 additions & 1 deletion clients/ctl/admin-ui/cypress/e2e/nav-bar.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ describe("Nav Bar", () => {
// Enabled links
cy.getByTestId("nav-link-Datasets");
cy.getByTestId("nav-link-Taxonomy");
cy.getByTestId("nav-link-Systems");

// Disabled links
cy.getByTestId("nav-link-Systems").should("have.attr", "disabled");

cy.getByTestId("nav-link-Policies").should("have.attr", "disabled");
cy.getByTestId("nav-link-User Management").should("have.attr", "disabled");
cy.getByTestId("nav-link-More").should("have.attr", "disabled");
Expand Down
43 changes: 43 additions & 0 deletions clients/ctl/admin-ui/cypress/e2e/systems.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
describe("System management page", () => {
beforeEach(() => {
cy.intercept("GET", "/api/v1/system", { fixture: "systems.json" }).as(
"getSystems"
);
});

it("Can navigate to the system management page", () => {
cy.visit("/");
cy.getByTestId("nav-link-Systems").click();
cy.wait("@getSystems");
cy.getByTestId("system-management");
});

describe("Can view data", () => {
beforeEach(() => {
cy.visit("/system");
});

it("Can render system cards", () => {
cy.getByTestId("system-fidesctl_system").within(() => {
cy.getByTestId("more-btn").click();
cy.getByTestId("edit-btn");
cy.getByTestId("delete-btn");
});
cy.getByTestId("system-demo_analytics_system");
cy.getByTestId("system-demo_marketing_system");
});

it("Can search and filter cards", () => {
cy.getByTestId("system-search").type("demo m");
cy.getByTestId("system-fidesctl_system").should("not.exist");
cy.getByTestId("system-demo_analytics_system").should("not.exist");
cy.getByTestId("system-demo_marketing_system");

// erase "m" so that search input is "demo "
cy.getByTestId("system-search").type("{backspace}");
cy.getByTestId("system-fidesctl_system").should("not.exist");
cy.getByTestId("system-demo_analytics_system");
cy.getByTestId("system-demo_marketing_system");
});
});
});
95 changes: 95 additions & 0 deletions clients/ctl/admin-ui/cypress/fixtures/systems.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
[
{
"fides_key": "fidesctl_system",
"organization_fides_key": "default_organization",
"tags": null,
"name": "Fidesctl System",
"description": "Software that functionally applies Fides.",
"registry_id": null,
"meta": null,
"fidesctl_meta": null,
"system_type": "Service",
"data_responsibility_title": "Controller",
"privacy_declarations": [
{
"name": "Store system data.",
"data_categories": ["system.operations", "user.contact"],
"data_use": "improve.system",
"data_qualifier": "aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified",
"data_subjects": ["anonymous_user"],
"dataset_references": ["public"]
}
],
"system_dependencies": null,
"joint_controller": null,
"third_country_transfers": null,
"administrating_department": "Not defined",
"data_protection_impact_assessment": {
"is_required": false,
"progress": null,
"link": null
}
},
{
"fides_key": "demo_analytics_system",
"organization_fides_key": "default_organization",
"tags": null,
"name": "Demo Analytics System",
"description": "A system used for analyzing customer behaviour.",
"registry_id": null,
"meta": null,
"fidesctl_meta": null,
"system_type": "Service",
"data_responsibility_title": "Controller",
"privacy_declarations": [
{
"name": "Analyze customer behaviour for improvements.",
"data_categories": ["user.contact", "user.device.cookie_id"],
"data_use": "improve.system",
"data_qualifier": "aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified",
"data_subjects": ["customer"],
"dataset_references": ["demo_users_dataset"]
}
],
"system_dependencies": null,
"joint_controller": null,
"third_country_transfers": ["USA", "CAN"],
"administrating_department": "Engineering",
"data_protection_impact_assessment": {
"is_required": true,
"progress": "Complete",
"link": "https://example.org/analytics_system_data_protection_impact_assessment"
}
},
{
"fides_key": "demo_marketing_system",
"organization_fides_key": "default_organization",
"tags": null,
"name": "Demo Marketing System",
"description": "Collect data about our users for marketing.",
"registry_id": null,
"meta": null,
"fidesctl_meta": null,
"system_type": "Service",
"data_responsibility_title": "Processor",
"privacy_declarations": [
{
"name": "Collect data for marketing",
"data_categories": ["user.device.cookie_id"],
"data_use": "advertising",
"data_qualifier": "aggregated.anonymized.unlinked_pseudonymized.pseudonymized.identified",
"data_subjects": ["customer"],
"dataset_references": null
}
],
"system_dependencies": ["demo_analytics_system"],
"joint_controller": null,
"third_country_transfers": null,
"administrating_department": "Marketing",
"data_protection_impact_assessment": {
"is_required": false,
"progress": null,
"link": null
}
}
]
15 changes: 15 additions & 0 deletions clients/ctl/admin-ui/src/features/common/BorderGrid.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.grid-row {
border-top-width: 0.5px;
border-color: var(--chakra-colors-blackAlpha-300);
box-sizing: border-box;
}

.grid-item {
border-right-width: 0.5px;
border-color: var(--chakra-colors-blackAlpha-300);
box-sizing: border-box;
}

.grid-item:nth-child(3n) {
border-right-width: 0px;
}
45 changes: 45 additions & 0 deletions clients/ctl/admin-ui/src/features/common/BorderGrid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { chunk } from "@chakra-ui/utils";
import { Box, SimpleGrid } from "@fidesui/react";
import { ReactNode } from "react";

import classes from "./BorderGrid.module.css";

interface Props<T> {
columns: number;
items: T[];
renderItem: (item: T) => ReactNode;
}
const BorderGrid = <T extends unknown>({
columns,
items,
renderItem,
}: Props<T>) => {
const chunks = chunk(items, columns);

return (
<Box>
{chunks.map((parent, index, { length }) => (
<Box
key={JSON.stringify(parent)}
className={classes["grid-row"]}
// Add bottom border only if last row is complete and there is more than 1 row rendered
borderBottomWidth={
length > 1 && index === length - 1 && parent.length === columns
? "0.5px"
: undefined
}
>
<SimpleGrid columns={columns}>
{parent.map((child) => (
<Box key={JSON.stringify(child)} className={classes["grid-item"]}>
{renderItem(child)}
</Box>
))}
</SimpleGrid>
</Box>
))}
</Box>
);
};

export default BorderGrid;
38 changes: 38 additions & 0 deletions clients/ctl/admin-ui/src/features/common/SearchBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {
Input,
InputGroup,
InputLeftElement,
InputProps,
} from "@fidesui/react";

import { SearchLineIcon } from "~/features/common/Icon";

interface Props extends Omit<InputProps, "onChange"> {
search?: string;
onChange: (value: string) => void;
}
const SearchBar = ({ search, onChange, ...props }: Props) => {
const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) =>
onChange(event.target.value);

return (
<InputGroup size="sm" minWidth="308px">
<InputLeftElement pointerEvents="none">
<SearchLineIcon color="gray.300" w="17px" h="17px" />
</InputLeftElement>
<Input
autoComplete="off"
type="search"
minWidth={200}
size="sm"
borderRadius="md"
value={search}
name="search"
onChange={handleSearchChange}
{...props}
/>
</InputGroup>
);
};

export default SearchBar;
2 changes: 1 addition & 1 deletion clients/ctl/admin-ui/src/features/common/nav/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const NavBar = () => {
borderColor="gray.100"
>
<nav>
<NavLink title="Systems" href="/system" disabled />
<NavLink title="Systems" href="/system" />
<NavLink title="Datasets" href="/dataset" />

{/* Links under the datamap zone: */}
Expand Down
55 changes: 55 additions & 0 deletions clients/ctl/admin-ui/src/features/system/SystemCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {
Box,
Heading,
IconButton,
Menu,
MenuButton,
MenuItem,
MenuList,
Text,
} from "@fidesui/react";

import { MoreIcon } from "~/features/common/Icon";
import { System } from "~/types/api";

interface SystemCardProps {
system: System;
}
const SystemCard = ({ system }: SystemCardProps) => {
// TODO fides#1035, fides#1036
const handleEdit = () => {};
const handleDelete = () => {};

return (
<Box display="flex" p={4} data-testid={`system-${system.fides_key}`}>
<Box flexGrow={1}>
<Heading as="h2" fontSize="16px" mb={2}>
{system.name}
</Heading>
<Box color="gray.600" fontSize="14px">
<Text>{system.description}</Text>
</Box>
</Box>
<Menu>
<MenuButton
as={IconButton}
icon={<MoreIcon />}
aria-label="more actions"
variant="unstyled"
size="sm"
data-testid="more-btn"
/>
<MenuList>
<MenuItem onClick={handleEdit} data-testid="edit-btn">
Edit
</MenuItem>
<MenuItem onClick={handleDelete} data-testid="delete-btn">
Delete
</MenuItem>
</MenuList>
</Menu>
</Box>
);
};

export default SystemCard;
32 changes: 0 additions & 32 deletions clients/ctl/admin-ui/src/features/system/SystemTable.tsx

This file was deleted.

Loading

0 comments on commit 6352fd9

Please sign in to comment.