@databiosphere/findable-ui 2.2.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/lib/components/Detail/components/DetailViewTable/detailViewTable.js +1 -1
  2. package/lib/components/Filter/components/FilterLabel/filterLabel.styles.d.ts +1 -1
  3. package/lib/components/Index/index.d.ts +2 -1
  4. package/lib/components/Index/index.js +2 -2
  5. package/lib/components/Layout/components/Header/components/Content/components/Actions/components/Authentication/components/AuthenticationMenu/authenticationMenu.styles.d.ts +3 -3
  6. package/lib/components/Layout/components/Header/components/Content/components/Actions/components/Authentication/components/RequestAuthentication/requestAuthentication.styles.d.ts +1 -1
  7. package/lib/components/Layout/components/Header/components/Content/components/Actions/components/Search/components/SearchBar/searchBar.styles.d.ts +1 -1
  8. package/lib/components/Layout/components/Header/components/Content/components/Actions/components/Search/components/SearchButton/searchButton.styles.d.ts +1 -1
  9. package/lib/components/Layout/components/Outline/components/ContentsTab/contentsTab.styles.d.ts +1 -1
  10. package/lib/components/Layout/components/Outline/outline.styles.d.ts +1 -1
  11. package/lib/components/Table/common/utils.d.ts +6 -0
  12. package/lib/components/Table/common/utils.js +12 -1
  13. package/lib/components/Table/components/CheckboxMenu/checkboxMenu.js +2 -2
  14. package/lib/components/Table/components/CheckboxMenu/checkboxMenu.styles.d.ts +1 -1
  15. package/lib/components/Table/components/CheckboxMenu/checkboxMenu.styles.js +3 -3
  16. package/lib/components/Table/components/TableCell/common/utils.d.ts +8 -0
  17. package/lib/components/Table/components/TableCell/common/utils.js +15 -0
  18. package/lib/components/Table/components/TableCell/components/RowSelectionCell/rowSelectionCell.d.ts +6 -0
  19. package/lib/components/Table/components/TableCell/components/RowSelectionCell/rowSelectionCell.js +15 -0
  20. package/lib/components/Table/components/TableHead/components/HeadSelectionCell/headSelectionCell.d.ts +6 -0
  21. package/lib/components/Table/components/TableHead/components/HeadSelectionCell/headSelectionCell.js +16 -0
  22. package/lib/components/Table/components/TableHead/tableHead.js +2 -2
  23. package/lib/components/Table/components/TableRows/tableRows.js +2 -3
  24. package/lib/components/Table/components/TableToolbar/components/RowSelection/components/DropdownMenu/dropdownMenu.d.ts +10 -0
  25. package/lib/components/Table/components/TableToolbar/components/RowSelection/components/DropdownMenu/dropdownMenu.js +37 -0
  26. package/lib/components/Table/components/TableToolbar/components/RowSelection/components/DropdownMenu/dropdownMenu.styles.d.ts +3 -0
  27. package/lib/components/Table/components/TableToolbar/components/RowSelection/components/DropdownMenu/dropdownMenu.styles.js +13 -0
  28. package/lib/components/Table/components/TableToolbar/components/RowSelection/rowSelection.d.ts +9 -0
  29. package/lib/components/Table/components/TableToolbar/components/RowSelection/rowSelection.js +19 -0
  30. package/lib/components/Table/components/TableToolbar/components/RowSelection/rowSelection.styles.d.ts +5 -0
  31. package/lib/components/Table/components/TableToolbar/components/RowSelection/rowSelection.styles.js +13 -0
  32. package/lib/components/Table/components/TableToolbar/tableToolbar.js +5 -5
  33. package/lib/components/Table/components/TableToolbar/tableToolbar.styles.d.ts +1 -5
  34. package/lib/components/Table/components/TableToolbar/tableToolbar.styles.js +10 -7
  35. package/lib/components/Table/table.d.ts +5 -2
  36. package/lib/components/Table/table.js +13 -2
  37. package/lib/components/TableCreator/common/constants.d.ts +6 -0
  38. package/lib/components/TableCreator/common/constants.js +22 -0
  39. package/lib/components/TableCreator/common/entities.d.ts +5 -0
  40. package/lib/components/TableCreator/common/entities.js +2 -0
  41. package/lib/components/TableCreator/common/utils.d.ts +8 -0
  42. package/lib/components/TableCreator/common/utils.js +24 -0
  43. package/lib/components/TableCreator/tableCreator.d.ts +3 -1
  44. package/lib/components/TableCreator/tableCreator.js +19 -34
  45. package/lib/components/common/Alert/components/AlertText/alertText.styles.d.ts +5 -0
  46. package/lib/components/common/Alert/components/AlertText/alertText.styles.js +25 -0
  47. package/lib/components/common/Button/components/DropdownButton/dropdownButton.d.ts +4 -2
  48. package/lib/components/common/Button/components/DropdownButton/dropdownButton.js +2 -2
  49. package/lib/components/common/Button/components/DropdownButton/dropdownButton.styles.d.ts +5 -1
  50. package/lib/components/common/Button/components/DropdownButton/dropdownButton.styles.js +24 -1
  51. package/lib/components/common/CustomIcon/components/IndeterminateIcon/indeterminateIcon.d.ts +6 -0
  52. package/lib/components/common/CustomIcon/components/IndeterminateIcon/indeterminateIcon.js +29 -0
  53. package/lib/components/common/Dialog/dialog.d.ts +7 -0
  54. package/lib/components/common/Dialog/dialog.js +24 -0
  55. package/lib/components/common/DropdownMenu/common/constants.d.ts +2 -0
  56. package/lib/components/common/DropdownMenu/common/constants.js +8 -0
  57. package/lib/components/common/DropdownMenu/common/entities.d.ts +10 -0
  58. package/lib/components/common/DropdownMenu/common/entities.js +2 -0
  59. package/lib/components/common/DropdownMenu/components/MenuItem/menuItem.d.ts +7 -0
  60. package/lib/components/common/DropdownMenu/components/MenuItem/menuItem.js +25 -0
  61. package/lib/components/common/DropdownMenu/dropdownMenu.d.ts +9 -0
  62. package/lib/components/common/DropdownMenu/dropdownMenu.js +49 -0
  63. package/lib/components/common/DropdownMenu/dropdownMenu.styles.d.ts +3 -0
  64. package/lib/components/common/DropdownMenu/dropdownMenu.styles.js +13 -0
  65. package/lib/components/common/IconButton/iconButton.d.ts +4 -3
  66. package/lib/components/common/IconButton/iconButton.js +4 -4
  67. package/lib/components/common/IconButton/iconButton.styles.d.ts +34 -0
  68. package/lib/components/common/IconButton/iconButton.styles.js +27 -1
  69. package/lib/components/common/Tabs/tabs.styles.d.ts +1 -1
  70. package/lib/config/entities.d.ts +2 -0
  71. package/lib/providers/exploreState/entities.d.ts +6 -2
  72. package/lib/providers/exploreState/initializer/utils.js +20 -7
  73. package/lib/providers/exploreState/payloads/entities.d.ts +24 -6
  74. package/lib/providers/exploreState/utils.d.ts +24 -2
  75. package/lib/providers/exploreState/utils.js +52 -3
  76. package/lib/providers/exploreState.d.ts +29 -5
  77. package/lib/providers/exploreState.js +28 -7
  78. package/lib/theme/common/components.js +4 -0
  79. package/lib/views/ExploreView/exploreView.d.ts +3 -1
  80. package/lib/views/ExploreView/exploreView.js +3 -3
  81. package/package.json +1 -1
  82. package/src/components/Detail/components/DetailViewTable/detailViewTable.tsx +2 -2
  83. package/src/components/Index/index.tsx +3 -1
  84. package/src/components/Table/common/utils.ts +17 -0
  85. package/src/components/Table/components/CheckboxMenu/checkboxMenu.styles.ts +3 -3
  86. package/src/components/Table/components/CheckboxMenu/checkboxMenu.tsx +4 -2
  87. package/src/components/Table/components/TableCell/common/utils.ts +16 -0
  88. package/src/components/Table/components/TableCell/components/RowSelectionCell/rowSelectionCell.tsx +24 -0
  89. package/src/components/Table/components/TableHead/components/HeadSelectionCell/headSelectionCell.tsx +31 -0
  90. package/src/components/Table/components/TableHead/tableHead.tsx +18 -7
  91. package/src/components/Table/components/TableRows/tableRows.tsx +10 -8
  92. package/src/components/Table/components/TableToolbar/components/RowSelection/components/DropdownMenu/dropdownMenu.styles.ts +8 -0
  93. package/src/components/Table/components/TableToolbar/components/RowSelection/components/DropdownMenu/dropdownMenu.tsx +50 -0
  94. package/src/components/Table/components/TableToolbar/components/RowSelection/rowSelection.styles.ts +8 -0
  95. package/src/components/Table/components/TableToolbar/components/RowSelection/rowSelection.tsx +30 -0
  96. package/src/components/Table/components/TableToolbar/tableToolbar.styles.ts +10 -7
  97. package/src/components/Table/components/TableToolbar/tableToolbar.tsx +11 -8
  98. package/src/components/Table/table.tsx +18 -1
  99. package/src/components/TableCreator/common/constants.ts +26 -0
  100. package/src/components/TableCreator/common/entities.ts +6 -0
  101. package/src/components/TableCreator/common/utils.ts +33 -0
  102. package/src/components/TableCreator/tableCreator.tsx +38 -17
  103. package/src/components/common/Alert/components/AlertText/alertText.styles.ts +20 -0
  104. package/src/components/common/Button/components/DropdownButton/dropdownButton.styles.ts +15 -1
  105. package/src/components/common/Button/components/DropdownButton/dropdownButton.tsx +10 -2
  106. package/src/components/common/CustomIcon/components/IndeterminateIcon/indeterminateIcon.tsx +23 -0
  107. package/src/components/common/Dialog/dialog.tsx +21 -0
  108. package/src/components/common/DropdownMenu/common/constants.ts +7 -0
  109. package/src/components/common/DropdownMenu/common/entities.ts +11 -0
  110. package/src/components/common/DropdownMenu/components/MenuItem/menuItem.tsx +24 -0
  111. package/src/components/common/DropdownMenu/dropdownMenu.styles.ts +8 -0
  112. package/src/components/common/DropdownMenu/dropdownMenu.tsx +48 -0
  113. package/src/components/common/IconButton/iconButton.styles.ts +18 -0
  114. package/src/components/common/IconButton/iconButton.tsx +10 -11
  115. package/src/config/entities.ts +2 -0
  116. package/src/providers/exploreState/entities.ts +8 -2
  117. package/src/providers/exploreState/initializer/utils.ts +21 -1
  118. package/src/providers/exploreState/payloads/entities.ts +32 -7
  119. package/src/providers/exploreState/utils.ts +81 -1
  120. package/src/providers/exploreState.tsx +88 -11
  121. package/src/theme/common/components.ts +4 -0
  122. package/src/views/ExploreView/exploreView.tsx +6 -2
  123. package/types/data-explorer-ui.d.ts +10 -0
  124. package/src/components/Table/components/EntityViewToggle/entityViewToggle.tsx +0 -36
@@ -1,4 +1,5 @@
1
1
  import { CellContext, ColumnDef, ColumnSort } from "@tanstack/react-table";
2
+ import { CoreOptions, HeaderContext, RowData } from "@tanstack/table-core";
2
3
  import React, { useMemo } from "react";
3
4
  import { Pagination } from "../../common/entities";
4
5
  import { ColumnConfig, ListViewConfig } from "../../config/entities";
@@ -10,12 +11,17 @@ import {
10
11
  getInitialState,
11
12
  sortingFn,
12
13
  } from "../Table/common/utils";
14
+ import { RowSelectionCell } from "../Table/components/TableCell/components/RowSelectionCell/rowSelectionCell";
15
+ import { HeadSelectionCell } from "../Table/components/TableHead/components/HeadSelectionCell/headSelectionCell";
13
16
  import { Table } from "../Table/table";
17
+ import { COLUMN_CONFIGS } from "./common/constants";
18
+ import { buildBaseColumnDef } from "./common/utils";
14
19
  import { TableCreator as TableCreatorContainer } from "./tableCreator.styles";
15
20
 
16
21
  export interface TableCreatorProps<T> {
17
22
  columns: ColumnConfig<T>[];
18
23
  defaultSort: ColumnSort | undefined;
24
+ getRowId?: CoreOptions<T>["getRowId"];
19
25
  items: T[];
20
26
  listView?: ListViewConfig;
21
27
  loading?: boolean;
@@ -26,9 +32,8 @@ export interface TableCreatorProps<T> {
26
32
  total?: number;
27
33
  }
28
34
 
29
- const createCell = <T extends object>(config: ColumnConfig<T>) =>
30
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- We can't determine the cell type
31
- function CellCreator({ row }: CellContext<T, any>): JSX.Element {
35
+ const createCell = <T extends RowData>(config: ColumnConfig<T>) =>
36
+ function CellCreator({ row }: CellContext<T, unknown>): JSX.Element {
32
37
  return (
33
38
  <ComponentCreator
34
39
  components={[config.componentConfig]}
@@ -37,9 +42,20 @@ const createCell = <T extends object>(config: ColumnConfig<T>) =>
37
42
  );
38
43
  };
39
44
 
45
+ const createHeaderSelectionCell = <T extends RowData>() =>
46
+ function CellCreator({ table }: HeaderContext<T, unknown>): JSX.Element {
47
+ return <HeadSelectionCell tableInstance={table} />;
48
+ };
49
+
50
+ const createRowSelectionCell = <T extends RowData>() =>
51
+ function CellCreator({ row }: CellContext<T, unknown>): JSX.Element {
52
+ return <RowSelectionCell row={row} />;
53
+ };
54
+
40
55
  export const TableCreator = <T extends object>({
41
56
  columns,
42
57
  defaultSort,
58
+ getRowId,
43
59
  items,
44
60
  listView,
45
61
  loading,
@@ -51,21 +67,25 @@ export const TableCreator = <T extends object>({
51
67
  }: TableCreatorProps<T>): JSX.Element => {
52
68
  const columnDefs: ColumnDef<T>[] = useMemo(
53
69
  () =>
54
- columns.map(({ disableHiding, disableSorting, ...columnConfig }) => ({
55
- accessorKey: columnConfig.id,
56
- cell: createCell(columnConfig),
57
- enableHiding: !disableHiding,
58
- enableSorting: !disableSorting,
59
- filterFn: arrIncludesSome,
60
- header: columnConfig.header,
61
- id: columnConfig.id,
62
- meta: {
63
- columnPinned: columnConfig.columnPinned,
64
- header: columnConfig.header,
65
- width: columnConfig.width,
70
+ columns.reduce(
71
+ (acc, columnConfig) => {
72
+ acc.push({
73
+ ...buildBaseColumnDef(columnConfig),
74
+ cell: createCell(columnConfig),
75
+ filterFn: arrIncludesSome,
76
+ sortingFn: sortingFn,
77
+ });
78
+ return acc;
66
79
  },
67
- sortingFn: sortingFn,
68
- })),
80
+ [
81
+ /* Initialize column definitions with the "select" column */
82
+ {
83
+ ...buildBaseColumnDef(COLUMN_CONFIGS.SELECT),
84
+ cell: createRowSelectionCell(),
85
+ header: createHeaderSelectionCell(),
86
+ },
87
+ ] as ColumnDef<T>[]
88
+ ),
69
89
  [columns]
70
90
  );
71
91
  const initialState = getInitialState(columns, defaultSort);
@@ -79,6 +99,7 @@ export const TableCreator = <T extends object>({
79
99
  <Table<T>
80
100
  columns={columnDefs}
81
101
  count={pageCount}
102
+ getRowId={getRowId}
82
103
  initialState={initialState}
83
104
  items={items}
84
105
  listView={listView}
@@ -0,0 +1,20 @@
1
+ import styled from "@emotion/styled";
2
+
3
+ export const AlertText = styled.div`
4
+ ul {
5
+ padding-left: 24px;
6
+ margin: 8px 0;
7
+
8
+ li {
9
+ margin: 4px 0;
10
+
11
+ &:last-child {
12
+ margin-bottom: 0;
13
+ }
14
+ }
15
+ }
16
+
17
+ *:last-child {
18
+ margin-bottom: 0;
19
+ }
20
+ `;
@@ -1,11 +1,25 @@
1
+ import { css } from "@emotion/react";
1
2
  import styled from "@emotion/styled";
3
+ import { smokeLightest } from "../../../../../styles/common/mixins/colors";
2
4
  import { ButtonSecondary } from "../ButtonSecondary/buttonSecondary";
3
5
 
6
+ interface Props {
7
+ open: boolean;
8
+ }
9
+
4
10
  // Dropdown button with "secondary" styles.
5
- export const DropdownButton = styled(ButtonSecondary)`
11
+ export const DropdownButton = styled(ButtonSecondary, {
12
+ shouldForwardProp: (prop) => prop !== "open",
13
+ })<Props>`
6
14
  padding-right: 8px;
7
15
 
8
16
  .MuiButton-endIcon {
9
17
  margin-left: -6px;
10
18
  }
19
+
20
+ ${({ open, ...props }) =>
21
+ open &&
22
+ css`
23
+ background-color: ${smokeLightest(props)};
24
+ `}
11
25
  `;
@@ -3,15 +3,23 @@ import React from "react";
3
3
  import { ButtonProps } from "../../button";
4
4
  import { DropdownButton as Button } from "./dropdownButton.styles";
5
5
 
6
- export type DropdownButtonProps = Exclude<ButtonProps, "StartIcon">;
6
+ export interface DropdownButtonProps extends Exclude<ButtonProps, "StartIcon"> {
7
+ open?: boolean;
8
+ }
7
9
 
8
10
  export const DropdownButton = ({
9
11
  children,
10
12
  disabled = false,
13
+ open = false,
11
14
  ...props /* Spread props to allow for Mui ButtonProps specific prop overrides e.g. "onClick". */
12
15
  }: DropdownButtonProps): JSX.Element => {
13
16
  return (
14
- <Button disabled={disabled} EndIcon={ArrowDropDownRoundedIcon} {...props}>
17
+ <Button
18
+ disabled={disabled}
19
+ EndIcon={ArrowDropDownRoundedIcon}
20
+ open={open}
21
+ {...props}
22
+ >
15
23
  {children}
16
24
  </Button>
17
25
  );
@@ -0,0 +1,23 @@
1
+ import { SvgIcon } from "@mui/material";
2
+ import React from "react";
3
+ import { CustomSVGIconProps } from "../../common/entities";
4
+
5
+ /**
6
+ * Custom indeterminate icon.
7
+ */
8
+
9
+ export const IndeterminateIcon = ({
10
+ fontSize = "xsmall",
11
+ viewBox = "0 0 18 18",
12
+ ...props /* Spread props to allow for Mui SvgIconProps specific prop overrides e.g. "htmlColor". */
13
+ }: CustomSVGIconProps): JSX.Element => {
14
+ return (
15
+ <SvgIcon fontSize={fontSize} viewBox={viewBox} {...props}>
16
+ <path
17
+ d="M0 4C0 1.79086 1.79086 0 4 0H14C16.2091 0 18 1.79086 18 4V14C18 16.2091 16.2091 18 14 18H4C1.79086 18 0 16.2091 0 14V4Z"
18
+ fill="currentColor"
19
+ />
20
+ <rect x="5" y="8" width="8" height="2" rx="1" fill="white" />
21
+ </SvgIcon>
22
+ );
23
+ };
@@ -0,0 +1,21 @@
1
+ import { Dialog as MDialog, DialogProps as MDialogProps } from "@mui/material";
2
+ import React, { ReactNode } from "react";
3
+
4
+ export interface DialogProps extends MDialogProps {
5
+ children: ReactNode | ReactNode[];
6
+ className?: string;
7
+ }
8
+
9
+ export const Dialog = ({
10
+ children,
11
+ className,
12
+ onClose,
13
+ open,
14
+ ...props /* Spread props to allow for Mui Dialog specific prop overrides e.g. "fullWidth". */
15
+ }: DialogProps): JSX.Element => {
16
+ return (
17
+ <MDialog className={className} onClose={onClose} open={open} {...props}>
18
+ {children}
19
+ </MDialog>
20
+ );
21
+ };
@@ -0,0 +1,7 @@
1
+ import { MenuProps as MMenuProps } from "@mui/material";
2
+
3
+ export const DEFAULT_DROPDOWN_MENU_PROPS: Partial<MMenuProps> = {
4
+ anchorOrigin: { horizontal: "right", vertical: "bottom" },
5
+ slotProps: { paper: { variant: "menu" } },
6
+ transformOrigin: { horizontal: "right", vertical: "top" },
7
+ };
@@ -0,0 +1,11 @@
1
+ import {
2
+ ButtonProps as MButtonProps,
3
+ IconButtonProps as MIconButtonProps,
4
+ } from "@mui/material";
5
+
6
+ export interface DropdownMenuItemProps {
7
+ closeMenu: () => void;
8
+ }
9
+
10
+ export type DropdownMenuButtonProps = MButtonProps & { open?: boolean };
11
+ export type DropdownMenuIconButtonProps = MIconButtonProps & { open?: boolean };
@@ -0,0 +1,24 @@
1
+ import {
2
+ ListItemText as MListItemText,
3
+ MenuItem as MMenuItem,
4
+ MenuItemProps as MMenuItemProps,
5
+ } from "@mui/material";
6
+ import React, { ReactNode } from "react";
7
+
8
+ export interface MenuItemProps extends MMenuItemProps {
9
+ children: ReactNode;
10
+ className?: string;
11
+ }
12
+
13
+ export const MenuItem = ({
14
+ children,
15
+ className,
16
+ onClick,
17
+ ...props /* Spread props to allow for Mui MenuItem specific prop overrides e.g. "disableGutters". */
18
+ }: MenuItemProps): JSX.Element => {
19
+ return (
20
+ <MMenuItem className={className} onClick={onClick} {...props}>
21
+ <MListItemText disableTypography>{children}</MListItemText>
22
+ </MMenuItem>
23
+ );
24
+ };
@@ -0,0 +1,8 @@
1
+ import styled from "@emotion/styled";
2
+ import { Menu as MMenu } from "@mui/material";
3
+
4
+ export const Menu = styled(MMenu)`
5
+ .MuiPaper-menu {
6
+ margin: 4px 0;
7
+ }
8
+ `;
@@ -0,0 +1,48 @@
1
+ import { MenuProps as MMenuProps } from "@mui/material";
2
+ import React, { ElementType, Fragment, MouseEvent, useState } from "react";
3
+ import { DEFAULT_DROPDOWN_MENU_PROPS } from "./common/constants";
4
+ import {
5
+ DropdownMenuButtonProps,
6
+ DropdownMenuIconButtonProps,
7
+ DropdownMenuItemProps,
8
+ } from "./common/entities";
9
+ import { Menu } from "./dropdownMenu.styles";
10
+
11
+ export interface DropdownMenuProps
12
+ extends Omit<MMenuProps, "children" | "open"> {
13
+ Button:
14
+ | ElementType<DropdownMenuButtonProps>
15
+ | ElementType<DropdownMenuIconButtonProps>;
16
+ children?: ({ closeMenu }: DropdownMenuItemProps) => JSX.Element[];
17
+ className?: string;
18
+ }
19
+
20
+ export const DropdownMenu = ({
21
+ Button,
22
+ children,
23
+ className,
24
+ ...props /* Spread props to allow for Mui Menu specific prop overrides e.g. "anchorOrigin". */
25
+ }: DropdownMenuProps): JSX.Element => {
26
+ const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
27
+ const closeMenu = (): void => setAnchorEl(null);
28
+ return (
29
+ <Fragment>
30
+ <Button
31
+ onClick={(event: MouseEvent<HTMLButtonElement>): void =>
32
+ setAnchorEl(event.currentTarget)
33
+ }
34
+ open={Boolean(anchorEl)}
35
+ />
36
+ <Menu
37
+ {...DEFAULT_DROPDOWN_MENU_PROPS}
38
+ anchorEl={anchorEl}
39
+ className={className}
40
+ onClose={closeMenu}
41
+ open={Boolean(anchorEl)}
42
+ {...props}
43
+ >
44
+ {children ? children({ closeMenu }) : null}
45
+ </Menu>
46
+ </Fragment>
47
+ );
48
+ };
@@ -1,7 +1,25 @@
1
+ import { css } from "@emotion/react";
1
2
  import styled from "@emotion/styled";
2
3
  import { IconButton as MIconButton } from "@mui/material";
4
+ import { smokeLightest } from "../../../styles/common/mixins/colors";
3
5
  import { IconButton } from "./iconButton";
4
6
 
7
+ interface Props {
8
+ open: boolean;
9
+ }
10
+
11
+ export const Button = styled(MIconButton, {
12
+ shouldForwardProp: (prop) => prop !== "open",
13
+ })<Props>`
14
+ ${({ open, ...props }) =>
15
+ open &&
16
+ css`
17
+ &.MuiIconButton-root {
18
+ background-color: ${smokeLightest(props)};
19
+ }
20
+ `}
21
+ `;
22
+
5
23
  // Primary icon button.
6
24
  export const IconButtonPrimary = styled(IconButton)`
7
25
  background-color: ${({ theme }) => theme.palette.primary.main};
@@ -1,8 +1,9 @@
1
1
  import {
2
- IconButton as MIconButton,
3
2
  IconButtonProps as MIconButtonProps,
3
+ IconProps as MIconProps,
4
4
  } from "@mui/material";
5
5
  import React, { ElementType } from "react";
6
+ import { Button } from "./iconButton.styles";
6
7
 
7
8
  /**
8
9
  * Basic icon button component.
@@ -11,24 +12,22 @@ import React, { ElementType } from "react";
11
12
 
12
13
  export interface IconButtonProps extends MIconButtonProps {
13
14
  className?: string;
14
- disabled?: boolean;
15
15
  Icon: ElementType;
16
+ iconProps?: MIconProps;
17
+ open?: boolean;
16
18
  }
17
19
 
18
20
  export const IconButton = ({
19
21
  className,
20
- disabled = false,
21
22
  Icon,
23
+ iconProps = { fontSize: "small" },
24
+ open = false,
25
+ size = "large",
22
26
  ...props /* Spread props to allow for Mui IconButtonProps specific prop overrides e.g. "onClick". */
23
27
  }: IconButtonProps): JSX.Element => {
24
28
  return (
25
- <MIconButton
26
- className={className}
27
- disabled={disabled}
28
- size="large"
29
- {...props}
30
- >
31
- <Icon fontSize="small" />
32
- </MIconButton>
29
+ <Button className={className} open={open} size={size} {...props}>
30
+ <Icon {...iconProps} />
31
+ </Button>
33
32
  );
34
33
  };
@@ -261,8 +261,10 @@ export interface ListConfig<T = any> {
261
261
  export interface ListViewConfig {
262
262
  disablePagination?: boolean;
263
263
  enableDownload?: boolean;
264
+ enableRowSelection?: boolean;
264
265
  listHero?: ComponentsConfig;
265
266
  relatedView?: RelatedViewConfig;
267
+ rowSelectionView?: ComponentsConfig;
266
268
  subTitleHero?: ComponentsConfig;
267
269
  }
268
270
 
@@ -1,4 +1,5 @@
1
- import { ColumnSort } from "@tanstack/react-table";
1
+ import { ColumnSort, RowSelectionState } from "@tanstack/react-table";
2
+ import { VisibilityState } from "@tanstack/table-core/src/features/Visibility";
2
3
  import {
3
4
  CategoryValueKey,
4
5
  SelectCategory,
@@ -15,7 +16,9 @@ import {
15
16
 
16
17
  export interface EntityPageState {
17
18
  categoryGroupConfigKey: CategoryGroupConfigKey;
18
- columnsVisibility: Record<string, boolean>;
19
+ columnsVisibility: VisibilityState;
20
+ enableRowSelection: boolean;
21
+ rowSelection: RowSelectionState;
19
22
  sorting: ColumnSort[];
20
23
  }
21
24
 
@@ -44,6 +47,9 @@ export interface EntityStateSavedFilter extends Omit<SavedFilter, "sort"> {
44
47
  sorting?: ColumnSort[];
45
48
  }
46
49
 
50
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO revisit when adding react query or similar
51
+ export type ListItem = any;
52
+
47
53
  export type SavedFilterByCategoryValueKey = Map<
48
54
  CategoryValueKey,
49
55
  EntityStateSavedFilter
@@ -1,5 +1,7 @@
1
+ import { VisibilityState } from "@tanstack/table-core/src/features/Visibility";
1
2
  import { SelectCategory, SelectedFilter } from "../../../common/entities";
2
3
  import { getInitialTableColumnVisibility } from "../../../components/Table/common/utils";
4
+ import { ACCESSOR_KEYS } from "../../../components/TableCreator/common/constants";
3
5
  import {
4
6
  CategoryConfig,
5
7
  CategoryGroup,
@@ -138,6 +140,22 @@ function initCategoryGroups(
138
140
  ?.categoryGroups;
139
141
  }
140
142
 
143
+ /**
144
+ * Initializes column visibility for the given entity.
145
+ * @param entityConfig - Entity config.
146
+ * @returns column visibility.
147
+ */
148
+ function initColumnVisibility(entityConfig: EntityConfig): VisibilityState {
149
+ const {
150
+ list: { columns },
151
+ listView: { enableRowSelection = false } = {},
152
+ } = entityConfig;
153
+ return {
154
+ [ACCESSOR_KEYS.SELECT]: enableRowSelection,
155
+ ...getInitialTableColumnVisibility(columns),
156
+ };
157
+ }
158
+
141
159
  /**
142
160
  * Initializes entity page state.
143
161
  * @param config - Site config.
@@ -149,7 +167,9 @@ function initEntityPageState(config: SiteConfig): EntityPageStateMapper {
149
167
  ...acc,
150
168
  [entity.route]: {
151
169
  categoryGroupConfigKey: initCategoryGroupConfigKey(config, entity),
152
- columnsVisibility: getInitialTableColumnVisibility(entity.list.columns),
170
+ columnsVisibility: initColumnVisibility(entity),
171
+ enableRowSelection: Boolean(entity.listView?.enableRowSelection),
172
+ rowSelection: {},
153
173
  sorting: getDefaultSorting(entity),
154
174
  },
155
175
  };
@@ -1,4 +1,8 @@
1
- import { ColumnSort } from "@tanstack/react-table";
1
+ import {
2
+ ColumnSort,
3
+ RowSelectionState,
4
+ VisibilityState,
5
+ } from "@tanstack/react-table";
2
6
  import {
3
7
  CategoryKey,
4
8
  CategoryValueKey,
@@ -11,6 +15,7 @@ import {
11
15
  PaginationResponse,
12
16
  RelatedListItems,
13
17
  } from "../../exploreState";
18
+ import { ListItem } from "../entities";
14
19
 
15
20
  /**
16
21
  * Apply saved filter payload.
@@ -21,6 +26,19 @@ export interface ApplySavedFilterPayload {
21
26
  selectedValue: CategoryValueKey;
22
27
  }
23
28
 
29
+ /**
30
+ * Paginate table payload.
31
+ */
32
+ export type PaginateTablePayload = PaginationDirectionType;
33
+
34
+ /**
35
+ * Patch explore response payload.
36
+ */
37
+ export interface PatchExploreResponsePayload {
38
+ listItemKey: keyof ListItem;
39
+ updatedListItems: ListItems;
40
+ }
41
+
24
42
  /**
25
43
  * Process explore response payload.
26
44
  */
@@ -38,11 +56,6 @@ export interface ProcessRelatedResponsePayload {
38
56
  relatedListItems: RelatedListItems;
39
57
  }
40
58
 
41
- /**
42
- * Paginate table payload.
43
- */
44
- export type PaginateTablePayload = PaginationDirectionType;
45
-
46
59
  /**
47
60
  * Reset explore response payload.
48
61
  */
@@ -56,7 +69,14 @@ export type ToggleEntityViewPayload = ENTITY_VIEW;
56
69
  /**
57
70
  * Update column visibility payload.
58
71
  */
59
- export type UpdateColumnVisibilityPayload = Record<string, boolean>;
72
+ export type UpdateColumnVisibilityPayload = VisibilityState;
73
+
74
+ /**
75
+ * Update entity view access payload.
76
+ */
77
+ export interface UpdateEntityViewAccessPayload {
78
+ canEdit: boolean;
79
+ }
60
80
 
61
81
  /**
62
82
  * Update filter payload.
@@ -67,6 +87,11 @@ export interface UpdateFilterPayload {
67
87
  selectedValue: CategoryValueKey;
68
88
  }
69
89
 
90
+ /**
91
+ * Update row selection payload.
92
+ */
93
+ export type UpdateRowSelectionPayload = RowSelectionState;
94
+
70
95
  /**
71
96
  * Update sorting payload.
72
97
  */
@@ -4,13 +4,15 @@ import {
4
4
  CategoryValueKey,
5
5
  SelectedFilter,
6
6
  } from "../../common/entities";
7
- import { ExploreState, PaginationState } from "../exploreState";
7
+ import { ACCESSOR_KEYS } from "../../components/TableCreator/common/constants";
8
+ import { ExploreState, ListItems, PaginationState } from "../exploreState";
8
9
  import {
9
10
  CategoryGroupConfigKey,
10
11
  EntityPageState,
11
12
  EntityPageStateMapper,
12
13
  EntityState,
13
14
  EntityStateSavedFilter,
15
+ ListItem,
14
16
  } from "./entities";
15
17
  import { DEFAULT_ENTITY_STATE } from "./initializer/constants";
16
18
 
@@ -119,6 +121,28 @@ export function getFilterCount(filterState: SelectedFilter[]): number {
119
121
  return filterState.reduce((acc, filter) => acc + filter.value.length, 0);
120
122
  }
121
123
 
124
+ /**
125
+ * Returns list items with updated list items patched.
126
+ * @param listItems - List items.
127
+ * @param updatedListItems - List items to patch.
128
+ * @param listItemKey - List item key identifier to map list items.
129
+ * @returns list items with updated list items patched.
130
+ */
131
+ export function patchEntityListItems(
132
+ listItems: ListItems,
133
+ updatedListItems: ListItems,
134
+ listItemKey: keyof ListItem
135
+ ): ListItems {
136
+ if (!listItems || !updatedListItems) return listItems;
137
+ const listItemById = new Map(
138
+ listItems.map((listItem) => [listItem[listItemKey], listItem])
139
+ );
140
+ updatedListItems.forEach((listItem) => {
141
+ listItemById.set(listItem[listItemKey], listItem);
142
+ });
143
+ return [...listItemById.values()];
144
+ }
145
+
122
146
  /**
123
147
  * Resets pagination.
124
148
  * @param paginationState - Pagination state.
@@ -131,6 +155,30 @@ export function resetPage(paginationState: PaginationState): PaginationState {
131
155
  return nextPaginationState;
132
156
  }
133
157
 
158
+ /**
159
+ * Resets row selection for the current entity and entities that share the same category group config key.
160
+ * @param state - Explore state.
161
+ * @returns entity page state mapper with row selection reset.
162
+ */
163
+ export function resetRowSelection(state: ExploreState): EntityPageStateMapper {
164
+ const categoryGroupConfigKey = getEntityCategoryGroupConfigKey(
165
+ state.tabValue,
166
+ state.entityPageState
167
+ );
168
+ return Object.entries(state.entityPageState).reduce(
169
+ (acc, [entityPath, entityPageState]) => {
170
+ if (entityPageState.categoryGroupConfigKey === categoryGroupConfigKey) {
171
+ return {
172
+ ...acc,
173
+ [entityPath]: { ...entityPageState, rowSelection: {} },
174
+ };
175
+ }
176
+ return { ...acc, [entityPath]: entityPageState };
177
+ },
178
+ {} as EntityPageStateMapper
179
+ );
180
+ }
181
+
134
182
  /**
135
183
  * Sets entity state for the given category group config key.
136
184
  * @param categoryGroupConfigKey - Category group config key.
@@ -217,3 +265,35 @@ export function updateEntityStateByCategoryGroupConfigKey(
217
265
  });
218
266
  }
219
267
  }
268
+
269
+ /**
270
+ * Updates the entity page state for each entity with row selection enabled,
271
+ * by updating the visibility of the "select" column based on user access and resetting row selection state.
272
+ * @param state - Explore state.
273
+ * @param canEdit - User has edit access.
274
+ * @returns new entity page state mapper with updated column visibility and row selection state.
275
+ */
276
+ export function updateSelectColumnVisibility(
277
+ state: ExploreState,
278
+ canEdit: boolean
279
+ ): EntityPageStateMapper {
280
+ return Object.entries(state.entityPageState).reduce(
281
+ (acc, [entityPath, entityPageState]) => {
282
+ if (entityPageState.enableRowSelection) {
283
+ return {
284
+ ...acc,
285
+ [entityPath]: {
286
+ ...entityPageState,
287
+ columnsVisibility: {
288
+ ...entityPageState.columnsVisibility,
289
+ [ACCESSOR_KEYS.SELECT]: canEdit,
290
+ },
291
+ rowSelection: {},
292
+ },
293
+ };
294
+ }
295
+ return { ...acc, [entityPath]: entityPageState };
296
+ },
297
+ {} as EntityPageStateMapper
298
+ );
299
+ }