Skip to content

Commit

Permalink
Bulk add vendors disable state (#4498)
Browse files Browse the repository at this point in the history
  • Loading branch information
allisonking authored Dec 8, 2023
1 parent bcfe528 commit 23f8720
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 104 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ The types of changes are:

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

### Added
- Tooltip and styling for disabled rows in add multiple vendor view [#4498](https://github.com/ethyca/fides/pull/4498)

## [2.26.0](https://github.com/ethyca/fides/compare/2.25.0...main)

### Added
Expand Down
90 changes: 52 additions & 38 deletions clients/admin-ui/src/features/common/table/v2/FidesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import {
Td,
Th,
Thead,
Tooltip,
Tr,
} from "@fidesui/react";
import {
flexRender,
Row,
RowData,
Table as TableInstance,
} from "@tanstack/react-table";
Expand Down Expand Up @@ -44,13 +46,15 @@ type Props<T> = {
rowActionBar?: ReactNode;
footer?: ReactNode;
onRowClick?: (row: T) => void;
renderRowTooltipLabel?: (row: Row<T>) => string | undefined;
};

export const FidesTableV2 = <T,>({
tableInstance,
rowActionBar,
footer,
onRowClick,
renderRowTooltipLabel,
}: Props<T>) => (
<TableContainer
data-testid="fidesTable"
Expand Down Expand Up @@ -109,46 +113,56 @@ export const FidesTableV2 = <T,>({
<Tbody data-testid="fidesTable-body">
{rowActionBar}
{tableInstance.getRowModel().rows.map((row) => (
<Tr
key={row.id}
height="36px"
_hover={
onRowClick
? { backgroundColor: "gray.50", cursor: "pointer" }
: undefined
<Tooltip
key={`tooltip-${row.id}`}
label={
renderRowTooltipLabel ? renderRowTooltipLabel(row) : undefined
}
data-testid={`row-${row.id}`}
hasArrow
placement="top"
>
{row.getVisibleCells().map((cell) => (
<Td
key={cell.id}
width={
cell.column.columnDef.meta?.width
? cell.column.columnDef.meta.width
: "unset"
}
borderBottomWidth="1px"
borderBottomColor="gray.200"
borderRightWidth="1px"
borderRightColor="gray.200"
_first={{
borderLeftWidth: "1px",
borderLeftColor: "gray.200",
}}
height="inherit"
style={getTableTHandTDStyles(cell.column.id)}
onClick={
cell.column.columnDef.header !== "Enable" && onRowClick
? () => {
onRowClick(row.original);
}
: undefined
}
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</Td>
))}
</Tr>
<Tr
key={row.id}
height="36px"
_hover={
onRowClick
? { backgroundColor: "gray.50", cursor: "pointer" }
: undefined
}
data-testid={`row-${row.id}`}
backgroundColor={row.getCanSelect() ? undefined : "gray.50"}
>
{row.getVisibleCells().map((cell) => (
<Td
key={cell.id}
width={
cell.column.columnDef.meta?.width
? cell.column.columnDef.meta.width
: "unset"
}
borderBottomWidth="1px"
borderBottomColor="gray.200"
borderRightWidth="1px"
borderRightColor="gray.200"
_first={{
borderLeftWidth: "1px",
borderLeftColor: "gray.200",
}}
height="inherit"
style={getTableTHandTDStyles(cell.column.id)}
onClick={
cell.column.columnDef.header !== "Enable" && onRowClick
? () => {
onRowClick(row.original);
}
: undefined
}
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</Td>
))}
</Tr>
</Tooltip>
))}
</Tbody>
{footer}
Expand Down
41 changes: 11 additions & 30 deletions clients/admin-ui/src/features/common/table/v2/cells.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import {
ArrowDownIcon,
ArrowUpIcon,
Badge,
Box,
Checkbox,
CheckboxProps,
Flex,
Text,
} from "@fidesui/react";
import { HeaderContext } from "@tanstack/react-table";
import { HTMLProps, ReactNode, useState } from "react";
import { ReactNode } from "react";

export const DefaultCell = ({ value }: { value: string }) => (
<Flex alignItems="center" height="100%">
Expand All @@ -33,37 +33,18 @@ export const BadgeCell = ({
</Flex>
);

type IndeterminateCheckboxCellProps = {
indeterminate?: boolean;
initialValue?: boolean;
manualDisable?: boolean;
dataTestId?: string;
} & HTMLProps<HTMLInputElement>;

export const IndeterminateCheckboxCell = ({
indeterminate,
initialValue,
manualDisable,
dataTestId,
...rest
}: IndeterminateCheckboxCellProps) => {
const [initialCheckBoxValue] = useState(initialValue);

return (
<Flex alignItems="center" justifyContent="center">
<Box backgroundColor="white">
<Checkbox
data-testid={dataTestId || undefined}
isChecked={initialCheckBoxValue || rest.checked}
isDisabled={initialCheckBoxValue || manualDisable}
onChange={rest.onChange}
isIndeterminate={!rest.checked && indeterminate}
colorScheme="purple"
/>
</Box>
</Flex>
);
};
}: CheckboxProps & { dataTestId?: string }) => (
<Flex alignItems="center" justifyContent="center">
<Checkbox
data-testid={dataTestId || undefined}
{...rest}
colorScheme="purple"
/>
</Flex>
);

type DefaultHeaderCellProps<T, V> = {
value: V;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
RowSelectionState,
useReactTable,
} from "@tanstack/react-table";
import { useFeatures } from "common/features";
Expand All @@ -41,7 +42,7 @@ import {
} from "common/table/v2";
import { errorToastParams, successToastParams } from "common/toast";
import { useRouter } from "next/router";
import { useMemo, useState } from "react";
import { useEffect, useMemo, useState } from "react";

import { useAppSelector } from "~/app/hooks";
import ConfirmationModal from "~/features/common/modals/ConfirmationModal";
Expand All @@ -67,6 +68,9 @@ export const VendorSourceCell = ({ value }: { value: string }) => {
);
};

const ADDED_VENDOR_TOOLTIP_LABEL =
"This vendor has already beed added. You can view the properties of this vendor by going to View Systems.";

type MultipleSystemTable = DictSystems;

const columnHelper = createColumnHelper<MultipleSystemTable>();
Expand Down Expand Up @@ -107,35 +111,40 @@ export const AddMultipleSystems = ({ redirectRoute }: Props) => {
id: "select",
header: ({ table }) => (
<IndeterminateCheckboxCell
{...{
dataTestId: "select-page-checkbox",
checked: table.getIsAllPageRowsSelected(),
indeterminate: table
dataTestId="select-page-checkbox"
isChecked={table.getIsAllPageRowsSelected()}
isDisabled={
allRowsLinkedToSystem ||
table
.getPaginationRowModel()
.rows.filter((r) => !r.original.linked_system)
.some((r) => r.getIsSelected()),
onChange: (e) => {
table.getToggleAllPageRowsSelectedHandler()(e);
setIsRowSelectionBarOpen((prev) => !prev);
},
manualDisable:
allRowsLinkedToSystem ||
table
.getPaginationRowModel()
.rows.filter((r) => r.original.linked_system).length ===
table.getState().pagination.pageSize,
.rows.filter((r) => r.original.linked_system).length ===
table.getState().pagination.pageSize
}
isIndeterminate={table
.getPaginationRowModel()
.rows.filter((r) => r.getCanSelect())
.some((r) => !r.getIsSelected())}
onChange={() => {
table.setRowSelection((old) => {
const rowSelection: RowSelectionState = { ...old };
table.getRowModel().rows.forEach((row) => {
if (row.getCanSelect()) {
rowSelection[row.id] = !rowSelection[row.id];
}
});

return rowSelection;
});
setIsRowSelectionBarOpen((prev) => !prev);
}}
/>
),
cell: ({ row }) => (
<IndeterminateCheckboxCell
{...{
checked: row.getIsSelected(),
disabled: !row.getCanSelect(),
indeterminate: row.getIsSomeSelected(),
onChange: row.getToggleSelectedHandler(),
initialValue: row.original.linked_system,
}}
isChecked={row.getIsSelected()}
isDisabled={!row.getCanSelect()}
isIndeterminate={row.getIsSomeSelected()}
onChange={row.getToggleSelectedHandler()}
/>
),
meta: {
Expand All @@ -161,16 +170,6 @@ export const AddMultipleSystems = ({ redirectRoute }: Props) => {
[allRowsLinkedToSystem, systemText, isTcfEnabled]
);

const rowSelection = useMemo(() => {
const innerRowSelection: Record<string, boolean> = {};
dictionaryOptions.forEach((ds, index) => {
if (ds.linked_system) {
innerRowSelection[index] = true;
}
});
return innerRowSelection;
}, [dictionaryOptions]);

const tableInstance = useReactTable<MultipleSystemTable>({
columns,
data: dictionaryOptions,
Expand All @@ -179,7 +178,7 @@ export const AddMultipleSystems = ({ redirectRoute }: Props) => {
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
onGlobalFilterChange: setGlobalFilter,
enableRowSelection: true,
enableRowSelection: (row) => !row.original.linked_system,
enableSorting: true,
enableGlobalFilter: true,
state: {
Expand All @@ -189,13 +188,25 @@ export const AddMultipleSystems = ({ redirectRoute }: Props) => {
},
},
initialState: {
rowSelection,
pagination: {
pageSize: PAGE_SIZES[0],
},
},
});

useEffect(() => {
const innerRowSelection: RowSelectionState = {};
dictionaryOptions.forEach((ds, index) => {
if (ds.linked_system) {
innerRowSelection[index] = true;
}
});
// Set on the table instance once this is ready
if (Object.keys(innerRowSelection).length) {
tableInstance.setRowSelection(innerRowSelection);
}
}, [dictionaryOptions, tableInstance]);

const {
totalRows,
onPreviousPageClick,
Expand Down Expand Up @@ -365,6 +376,12 @@ export const AddMultipleSystems = ({ redirectRoute }: Props) => {
isOpen={isRowSelectionBarOpen}
/>
}
renderRowTooltipLabel={(row) => {
if (!row.getCanSelect()) {
return ADDED_VENDOR_TOOLTIP_LABEL;
}
return undefined;
}}
/>
<PaginationBar
pageSizes={PAGE_SIZES}
Expand Down

0 comments on commit 23f8720

Please sign in to comment.