@databiosphere/findable-ui 3.1.0 → 4.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.
- package/lib/components/Detail/components/DetailViewTable/detailViewTable.d.ts +3 -2
- package/lib/components/Detail/components/DetailViewTable/detailViewTable.js +14 -2
- package/lib/components/Detail/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.js +4 -1
- package/lib/components/Detail/components/Table/components/TableRows/tableRows.d.ts +1 -1
- package/lib/components/Detail/components/Table/components/TableRows/tableRows.js +21 -2
- package/lib/components/Detail/components/Table/table.d.ts +3 -1
- package/lib/components/Detail/components/Table/table.js +3 -7
- package/lib/components/Links/common/constants.d.ts +1 -0
- package/lib/components/Links/common/constants.js +4 -0
- package/lib/components/Links/common/entities.d.ts +8 -0
- package/lib/components/Links/common/utils.d.ts +13 -0
- package/lib/components/Links/common/utils.js +21 -1
- package/lib/components/Links/components/Link/components/ExploreViewLink/exploreViewLink.d.ts +7 -0
- package/lib/components/Links/components/Link/components/ExploreViewLink/exploreViewLink.js +148 -0
- package/lib/components/Links/components/Link/link.d.ts +2 -2
- package/lib/components/Links/components/Link/link.js +22 -6
- package/lib/components/Table/common/gridTable.styles.js +9 -1
- package/lib/components/Table/common/utils.d.ts +6 -0
- package/lib/components/Table/common/utils.js +10 -1
- package/lib/components/Table/components/TableCell/components/CollapsableCell/collapsableCell.d.ts +4 -3
- package/lib/components/Table/components/TableCell/components/CollapsableCell/collapsableCell.js +21 -3
- package/lib/components/Table/components/TableCell/components/CollapsableCell/collapsableCell.styles.js +4 -0
- package/lib/components/Table/components/TableHead/tableHead.js +4 -1
- package/lib/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.js +2 -1
- package/lib/components/TableCreator/common/utils.js +1 -5
- package/lib/components/common/CustomIcon/components/AddLinkIcon/addLinkIcon.d.ts +3 -0
- package/lib/components/common/CustomIcon/components/AddLinkIcon/addLinkIcon.js +25 -0
- package/lib/components/common/CustomIcon/components/UnLinkIcon/unLinkIcon.d.ts +3 -0
- package/lib/components/common/CustomIcon/components/UnLinkIcon/unLinkIcon.js +25 -0
- package/lib/components/common/Progress/components/CircularProgress/circularProgress.d.ts +7 -0
- package/lib/components/common/Progress/components/CircularProgress/circularProgress.js +28 -0
- package/lib/components/common/Progress/components/CircularProgress/circularProgress.styles.d.ts +5 -0
- package/lib/components/common/Progress/components/CircularProgress/circularProgress.styles.js +11 -0
- package/lib/components/common/Progress/components/CircularProgress/components/CircularProgressTrack/circularProgressTrack.d.ts +7 -0
- package/lib/components/common/Progress/components/CircularProgress/components/CircularProgressTrack/circularProgressTrack.js +44 -0
- package/lib/components/common/Progress/components/CircularProgress/components/CircularProgressTrack/circularProgressTrack.styles.d.ts +3 -0
- package/lib/components/common/Progress/components/CircularProgress/components/CircularProgressTrack/circularProgressTrack.styles.js +32 -0
- package/lib/providers/exploreState/initializer/constants.d.ts +2 -0
- package/lib/providers/exploreState/initializer/constants.js +7 -1
- package/lib/providers/exploreState/initializer/utils.js +1 -8
- package/lib/providers/exploreState/payloads/entities.d.ts +8 -1
- package/lib/providers/exploreState/utils.d.ts +4 -2
- package/lib/providers/exploreState/utils.js +4 -4
- package/lib/providers/exploreState.d.ts +10 -2
- package/lib/providers/exploreState.js +13 -0
- package/lib/styles/common/mixins/colors.d.ts +3 -3
- package/lib/styles/common/mixins/colors.js +7 -7
- package/lib/theme/common/components.d.ts +6 -0
- package/lib/theme/common/components.js +31 -1
- package/lib/theme/theme.js +1 -0
- package/package.json +1 -1
- package/src/components/Detail/components/DetailViewTable/detailViewTable.tsx +4 -2
- package/src/components/Detail/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.tsx +6 -1
- package/src/components/Detail/components/Table/components/TableRows/tableRows.tsx +29 -6
- package/src/components/Detail/components/Table/table.tsx +6 -1
- package/src/components/Links/common/constants.ts +1 -0
- package/src/components/Links/common/entities.ts +11 -0
- package/src/components/Links/common/utils.ts +28 -0
- package/src/components/Links/components/Link/components/ExploreViewLink/exploreViewLink.tsx +172 -0
- package/src/components/Links/components/Link/link.tsx +36 -14
- package/src/components/Table/common/gridTable.styles.ts +9 -1
- package/src/components/Table/common/utils.ts +9 -0
- package/src/components/Table/components/TableCell/components/CollapsableCell/collapsableCell.styles.ts +4 -0
- package/src/components/Table/components/TableCell/components/CollapsableCell/collapsableCell.tsx +26 -4
- package/src/components/Table/components/TableHead/tableHead.tsx +32 -21
- package/src/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.tsx +5 -1
- package/src/components/TableCreator/common/utils.ts +1 -0
- package/src/components/common/CustomIcon/components/AddLinkIcon/addLinkIcon.tsx +18 -0
- package/src/components/common/CustomIcon/components/UnLinkIcon/unLinkIcon.tsx +18 -0
- package/src/components/common/Progress/components/CircularProgress/circularProgress.styles.ts +6 -0
- package/src/components/common/Progress/components/CircularProgress/circularProgress.tsx +26 -0
- package/src/components/common/Progress/components/CircularProgress/components/CircularProgressTrack/circularProgressTrack.styles.ts +33 -0
- package/src/components/common/Progress/components/CircularProgress/components/CircularProgressTrack/circularProgressTrack.tsx +23 -0
- package/src/providers/exploreState/initializer/constants.ts +8 -0
- package/src/providers/exploreState/initializer/utils.ts +6 -9
- package/src/providers/exploreState/payloads/entities.ts +8 -0
- package/src/providers/exploreState/utils.ts +11 -7
- package/src/providers/exploreState.tsx +33 -0
- package/src/styles/common/mixins/colors.ts +6 -6
- package/src/theme/common/components.ts +32 -0
- package/src/theme/theme.ts +1 -0
- package/types/data-explorer-ui.d.ts +12 -0
- package/src/components/Detail/components/Table/components/TableHead/tableHead.tsx +0 -34
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { TableCell, TableRow as MTableRow } from "@mui/material";
|
|
2
|
-
import { flexRender, Table } from "@tanstack/react-table";
|
|
1
|
+
import { TableCell as MTableCell, TableRow as MTableRow } from "@mui/material";
|
|
2
|
+
import { flexRender, Row, Table } from "@tanstack/react-table";
|
|
3
|
+
import { RowData } from "@tanstack/table-core";
|
|
3
4
|
import React, { Fragment } from "react";
|
|
5
|
+
import { getTableCellPadding } from "../../../../../Table/components/TableCell/common/utils";
|
|
4
6
|
import { TableView } from "../../table";
|
|
5
7
|
|
|
6
8
|
export interface TableRowsProps<T> {
|
|
@@ -8,7 +10,7 @@ export interface TableRowsProps<T> {
|
|
|
8
10
|
tableView?: TableView;
|
|
9
11
|
}
|
|
10
12
|
|
|
11
|
-
export const TableRows = <T extends
|
|
13
|
+
export const TableRows = <T extends RowData>({
|
|
12
14
|
tableInstance,
|
|
13
15
|
tableView,
|
|
14
16
|
}: TableRowsProps<T>): JSX.Element => {
|
|
@@ -20,12 +22,18 @@ export const TableRows = <T extends object>({
|
|
|
20
22
|
<Fragment>
|
|
21
23
|
{rows.map((row) => {
|
|
22
24
|
return (
|
|
23
|
-
<MTableRow key={row.id}>
|
|
25
|
+
<MTableRow id={getRowId(row)} key={row.id}>
|
|
24
26
|
{row.getVisibleCells().map((cell) => {
|
|
27
|
+
if (cell.getIsAggregated()) return null; // Display of aggregated cells is currently not supported.
|
|
28
|
+
if (cell.getIsPlaceholder()) return null; // Display of placeholder cells is currently not supported.
|
|
25
29
|
return (
|
|
26
|
-
<
|
|
30
|
+
<MTableCell
|
|
31
|
+
key={cell.id}
|
|
32
|
+
padding={getTableCellPadding(cell.column.id)}
|
|
33
|
+
size={tableCellSize}
|
|
34
|
+
>
|
|
27
35
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
28
|
-
</
|
|
36
|
+
</MTableCell>
|
|
29
37
|
);
|
|
30
38
|
})}
|
|
31
39
|
</MTableRow>
|
|
@@ -34,3 +42,18 @@ export const TableRows = <T extends object>({
|
|
|
34
42
|
</Fragment>
|
|
35
43
|
);
|
|
36
44
|
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Returns identifier for a row.
|
|
48
|
+
* @param row - Row.
|
|
49
|
+
* @returns row identifier.
|
|
50
|
+
*/
|
|
51
|
+
function getRowId<T extends RowData>(row: Row<T>): string | undefined {
|
|
52
|
+
const { depth, getIsGrouped, id } = row;
|
|
53
|
+
if (getIsGrouped()) {
|
|
54
|
+
return `grouped-row-${id}`;
|
|
55
|
+
}
|
|
56
|
+
if (depth > 0) {
|
|
57
|
+
return `sub-row-${id}`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
getCoreRowModel,
|
|
10
10
|
useReactTable,
|
|
11
11
|
} from "@tanstack/react-table";
|
|
12
|
+
import { TableOptions } from "@tanstack/table-core";
|
|
12
13
|
import React from "react";
|
|
13
14
|
import {
|
|
14
15
|
BREAKPOINT_FN_NAME,
|
|
@@ -16,10 +17,10 @@ import {
|
|
|
16
17
|
} from "../../../../hooks/useBreakpointHelper";
|
|
17
18
|
import { TABLET } from "../../../../theme/common/breakpoints";
|
|
18
19
|
import { ROW_DIRECTION } from "../../../Table/common/entities";
|
|
20
|
+
import { TableHead } from "../../../Table/components/TableHead/tableHead";
|
|
19
21
|
import { GridTable } from "../../../Table/table.styles";
|
|
20
22
|
import { generateColumnDefinitions } from "./common/utils";
|
|
21
23
|
import { TableBody } from "./components/TableBody/tableBody";
|
|
22
|
-
import { TableHead } from "./components/TableHead/tableHead";
|
|
23
24
|
|
|
24
25
|
export interface TableView {
|
|
25
26
|
table?: Partial<MTableProps>;
|
|
@@ -33,6 +34,7 @@ export interface TableProps<T extends object> {
|
|
|
33
34
|
columns: ColumnDef<T>[];
|
|
34
35
|
gridTemplateColumns: string;
|
|
35
36
|
items: T[];
|
|
37
|
+
tableOptions?: Partial<TableOptions<T>>;
|
|
36
38
|
tableView?: TableView;
|
|
37
39
|
}
|
|
38
40
|
|
|
@@ -42,6 +44,7 @@ export const Table = <T extends object>({
|
|
|
42
44
|
columns,
|
|
43
45
|
gridTemplateColumns,
|
|
44
46
|
items,
|
|
47
|
+
tableOptions,
|
|
45
48
|
tableView,
|
|
46
49
|
}: TableProps<T>): JSX.Element => {
|
|
47
50
|
const tabletDown = useBreakpointHelper(BREAKPOINT_FN_NAME.DOWN, TABLET);
|
|
@@ -53,7 +56,9 @@ export const Table = <T extends object>({
|
|
|
53
56
|
const tableInstance = useReactTable({
|
|
54
57
|
columns: generateColumnDefinitions(columns),
|
|
55
58
|
data: items,
|
|
59
|
+
enableSorting: false,
|
|
56
60
|
getCoreRowModel: getCoreRowModel(),
|
|
61
|
+
...tableOptions,
|
|
57
62
|
});
|
|
58
63
|
return (
|
|
59
64
|
<TableContainer className={className} sx={tableContainerSx}>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const URL_OBJECT_KEYS = ["href", "query"];
|
|
@@ -1,4 +1,15 @@
|
|
|
1
|
+
import { UrlObject } from "url";
|
|
2
|
+
|
|
1
3
|
export enum ANCHOR_TARGET {
|
|
2
4
|
BLANK = "_blank",
|
|
3
5
|
SELF = "_self",
|
|
4
6
|
}
|
|
7
|
+
|
|
8
|
+
export type StrictUrlObject = Omit<UrlObject, "href" | "query"> & {
|
|
9
|
+
href: string;
|
|
10
|
+
query: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type Url = string | UrlObjectWithHrefAndQuery;
|
|
14
|
+
|
|
15
|
+
export type UrlObjectWithHrefAndQuery = Pick<StrictUrlObject, "href" | "query">;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { URL_OBJECT_KEYS } from "./constants";
|
|
2
|
+
import { Url, UrlObjectWithHrefAndQuery } from "./entities";
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* Returns true if the given link is an internal link.
|
|
3
6
|
* @param link - Link.
|
|
@@ -6,3 +9,28 @@
|
|
|
6
9
|
export function isClientSideNavigation(link: string): boolean {
|
|
7
10
|
return /^\/(?!\/)/.test(link);
|
|
8
11
|
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Returns true if the given url is a URL object with href and query.
|
|
15
|
+
* @param value - URL.
|
|
16
|
+
* @returns true if the given url is a URL object with href and query.
|
|
17
|
+
*/
|
|
18
|
+
export function isURLObjectWithHrefAndQuery(
|
|
19
|
+
value: Url
|
|
20
|
+
): value is UrlObjectWithHrefAndQuery {
|
|
21
|
+
return (
|
|
22
|
+
typeof value !== "string" &&
|
|
23
|
+
Object.entries(value).every(
|
|
24
|
+
([key, value]) => URL_OBJECT_KEYS.includes(key) && !!value
|
|
25
|
+
)
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Returns true if the given url is a string.
|
|
31
|
+
* @param value - URL.
|
|
32
|
+
* @returns true if the given url is a string.
|
|
33
|
+
*/
|
|
34
|
+
export function isURLString(value: Url): value is string {
|
|
35
|
+
return typeof value === "string";
|
|
36
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import Link from "next/link";
|
|
2
|
+
import React, { useCallback } from "react";
|
|
3
|
+
import { UrlObject } from "url";
|
|
4
|
+
import { SelectedFilter } from "../../../../../../common/entities";
|
|
5
|
+
import { useExploreState } from "../../../../../../hooks/useExploreState";
|
|
6
|
+
import {
|
|
7
|
+
ExploreActionKind,
|
|
8
|
+
ExploreState,
|
|
9
|
+
} from "../../../../../../providers/exploreState";
|
|
10
|
+
import {
|
|
11
|
+
ANCHOR_TARGET,
|
|
12
|
+
UrlObjectWithHrefAndQuery,
|
|
13
|
+
} from "../../../../common/entities";
|
|
14
|
+
import { LinkProps } from "../../link";
|
|
15
|
+
|
|
16
|
+
const PARAM_FILTER = "filter";
|
|
17
|
+
|
|
18
|
+
export interface ExploreViewLinkProps
|
|
19
|
+
extends Omit<LinkProps, "copyable" | "noWrap" | "url"> {
|
|
20
|
+
url: UrlObjectWithHrefAndQuery;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const ExploreViewLink = ({
|
|
24
|
+
className,
|
|
25
|
+
label,
|
|
26
|
+
onClick,
|
|
27
|
+
target = ANCHOR_TARGET.SELF,
|
|
28
|
+
url,
|
|
29
|
+
}: ExploreViewLinkProps): JSX.Element => {
|
|
30
|
+
const { exploreDispatch, exploreState } = useExploreState();
|
|
31
|
+
|
|
32
|
+
if (!isValidExploreURL(url, exploreState)) {
|
|
33
|
+
throwError(url);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const onNavigate = useCallback(() => {
|
|
37
|
+
const entityListType = getEntityListType(url.href);
|
|
38
|
+
const filters = getSelectedFilters(url.query);
|
|
39
|
+
exploreDispatch({
|
|
40
|
+
payload: { entityListType, filters },
|
|
41
|
+
type: ExploreActionKind.UpdateEntityFilters,
|
|
42
|
+
});
|
|
43
|
+
onClick?.();
|
|
44
|
+
}, [exploreDispatch, onClick, url]);
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Link
|
|
48
|
+
className={className}
|
|
49
|
+
href={url.href}
|
|
50
|
+
onClick={onNavigate}
|
|
51
|
+
rel="noopener"
|
|
52
|
+
target={target}
|
|
53
|
+
>
|
|
54
|
+
{label}
|
|
55
|
+
</Link>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Returns the entity list type "entityListType" inferred from the given href.
|
|
61
|
+
* @param href - Href.
|
|
62
|
+
* @returns entity list type.
|
|
63
|
+
*/
|
|
64
|
+
function getEntityListType(href: UrlObjectWithHrefAndQuery["href"]): string {
|
|
65
|
+
return href.substring(1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Returns the selected filters from the given query.
|
|
70
|
+
* @param query - Query.
|
|
71
|
+
* @returns selected filters.
|
|
72
|
+
*/
|
|
73
|
+
function getSelectedFilters(
|
|
74
|
+
query: UrlObjectWithHrefAndQuery["query"]
|
|
75
|
+
): SelectedFilter[] {
|
|
76
|
+
const decodedQuery = decodeURIComponent(query);
|
|
77
|
+
const parsedQuery = JSON.parse(decodedQuery);
|
|
78
|
+
return parsedQuery[PARAM_FILTER];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Returns true if the given value is a SelectedFilter.
|
|
83
|
+
* @param value - Value.
|
|
84
|
+
* @returns true if the given value is a SelectedFilter.
|
|
85
|
+
*/
|
|
86
|
+
function isSelectedFilter(value: unknown): value is SelectedFilter {
|
|
87
|
+
return (
|
|
88
|
+
typeof value === "object" &&
|
|
89
|
+
value !== null &&
|
|
90
|
+
"categoryKey" in value &&
|
|
91
|
+
"value" in value
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Returns true if the given query string is a valid JSON string.
|
|
97
|
+
* @param query - Query string.
|
|
98
|
+
* @returns true if the given query string is a valid JSON string.
|
|
99
|
+
*/
|
|
100
|
+
function isValidJsonString(query: string): boolean {
|
|
101
|
+
try {
|
|
102
|
+
JSON.parse(query);
|
|
103
|
+
return true;
|
|
104
|
+
} catch (e) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Returns true if the given explore link is valid.
|
|
111
|
+
* @param url - Explore link URL.
|
|
112
|
+
* @param exploreState - Explore state.
|
|
113
|
+
* @returns true if the given explore link is valid.
|
|
114
|
+
*/
|
|
115
|
+
function isValidExploreURL(
|
|
116
|
+
url: UrlObjectWithHrefAndQuery,
|
|
117
|
+
exploreState: ExploreState
|
|
118
|
+
): boolean {
|
|
119
|
+
const validHref = isValidHref(url, exploreState);
|
|
120
|
+
const validQuery = isValidQuery(url);
|
|
121
|
+
return validHref && validQuery;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Returns true if the given href is a configured key in the explore state's entityPageState.
|
|
126
|
+
* @param url - Explore link URL.
|
|
127
|
+
* @param exploreState - Explore state.
|
|
128
|
+
* @returns true if the given href is configured in the explore state.
|
|
129
|
+
*/
|
|
130
|
+
function isValidHref(
|
|
131
|
+
url: UrlObjectWithHrefAndQuery,
|
|
132
|
+
exploreState: ExploreState
|
|
133
|
+
): boolean {
|
|
134
|
+
const { entityPageState } = exploreState;
|
|
135
|
+
const { href } = url;
|
|
136
|
+
return href.startsWith("/") && href.substring(1) in entityPageState;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Returns true if the given explore query is valid.
|
|
141
|
+
* @param url - Explore link URL.
|
|
142
|
+
* @returns true if the given explore query is valid.
|
|
143
|
+
*/
|
|
144
|
+
function isValidQuery(url: UrlObjectWithHrefAndQuery): boolean {
|
|
145
|
+
const { query } = url;
|
|
146
|
+
// Decode and parse the query.
|
|
147
|
+
const decodedQuery = decodeURIComponent(query);
|
|
148
|
+
// Query should be a valid JSON string.
|
|
149
|
+
if (isValidJsonString(decodedQuery)) {
|
|
150
|
+
const parsedQuery = JSON.parse(decodedQuery);
|
|
151
|
+
// Query should contain "filter" key.
|
|
152
|
+
if (PARAM_FILTER in parsedQuery) {
|
|
153
|
+
const filters = parsedQuery[PARAM_FILTER];
|
|
154
|
+
// Filter should be an array.
|
|
155
|
+
if (Array.isArray(filters)) {
|
|
156
|
+
// Filter should contain only SelectedFilter objects.
|
|
157
|
+
return filters.every(isSelectedFilter);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Throws an error with the given URL object.
|
|
166
|
+
* @param url - URL object.
|
|
167
|
+
*/
|
|
168
|
+
function throwError(url: UrlObject): never {
|
|
169
|
+
throw new Error(
|
|
170
|
+
`Invalid explore URL href or query: ${url.href}, ${url.query}`
|
|
171
|
+
);
|
|
172
|
+
}
|
|
@@ -3,8 +3,13 @@ import NLink from "next/link";
|
|
|
3
3
|
import React, { ReactNode } from "react";
|
|
4
4
|
import { isValidUrl } from "../../../../common/utils";
|
|
5
5
|
import { CopyToClipboard } from "../../../common/CopyToClipboard/copyToClipboard";
|
|
6
|
-
import { ANCHOR_TARGET } from "../../common/entities";
|
|
7
|
-
import {
|
|
6
|
+
import { ANCHOR_TARGET, Url } from "../../common/entities";
|
|
7
|
+
import {
|
|
8
|
+
isClientSideNavigation,
|
|
9
|
+
isURLObjectWithHrefAndQuery,
|
|
10
|
+
isURLString,
|
|
11
|
+
} from "../../common/utils";
|
|
12
|
+
import { ExploreViewLink } from "./components/ExploreViewLink/exploreViewLink";
|
|
8
13
|
|
|
9
14
|
export interface LinkProps {
|
|
10
15
|
className?: string;
|
|
@@ -13,7 +18,7 @@ export interface LinkProps {
|
|
|
13
18
|
noWrap?: MLinkProps["noWrap"];
|
|
14
19
|
onClick?: () => void;
|
|
15
20
|
target?: ANCHOR_TARGET;
|
|
16
|
-
url:
|
|
21
|
+
url: Url /* url specified as UrlObject with href and query defined, and is currently only used for internal links */;
|
|
17
22
|
}
|
|
18
23
|
|
|
19
24
|
export const Link = ({
|
|
@@ -25,9 +30,22 @@ export const Link = ({
|
|
|
25
30
|
target,
|
|
26
31
|
url,
|
|
27
32
|
}: LinkProps): JSX.Element => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
if (isURLObjectWithHrefAndQuery(url)) {
|
|
34
|
+
/* Internal navigation - explore link */
|
|
35
|
+
return (
|
|
36
|
+
<ExploreViewLink
|
|
37
|
+
className={className}
|
|
38
|
+
label={label}
|
|
39
|
+
onClick={onClick}
|
|
40
|
+
target={target}
|
|
41
|
+
url={url}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
if (isURLString(url)) {
|
|
46
|
+
if (isClientSideNavigation(url)) {
|
|
47
|
+
/* Client-side navigation */
|
|
48
|
+
return (
|
|
31
49
|
<>
|
|
32
50
|
<NLink href={url} legacyBehavior passHref>
|
|
33
51
|
<MLink
|
|
@@ -42,23 +60,27 @@ export const Link = ({
|
|
|
42
60
|
</NLink>
|
|
43
61
|
{copyable && <CopyToClipboard copyStr={url} />}
|
|
44
62
|
</>
|
|
45
|
-
)
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
if (isValidUrl(url)) {
|
|
66
|
+
/* External navigation */
|
|
67
|
+
return (
|
|
46
68
|
<>
|
|
47
69
|
<MLink
|
|
48
70
|
className={className}
|
|
49
71
|
href={url}
|
|
50
|
-
rel="noopener noreferrer"
|
|
51
72
|
noWrap={noWrap}
|
|
52
|
-
target={target || ANCHOR_TARGET.BLANK}
|
|
53
73
|
onClick={onClick}
|
|
74
|
+
rel="noopener noreferrer"
|
|
75
|
+
target={target || ANCHOR_TARGET.BLANK}
|
|
54
76
|
>
|
|
55
77
|
{label}
|
|
56
78
|
</MLink>
|
|
57
79
|
{copyable && <CopyToClipboard copyStr={url} />}
|
|
58
80
|
</>
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/* Invalid URL */
|
|
85
|
+
return <>{label}</>;
|
|
64
86
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import styled from "@emotion/styled";
|
|
2
2
|
import { Table as MTable } from "@mui/material";
|
|
3
|
+
import { smokeLightest, white } from "../../../styles/common/mixins/colors";
|
|
3
4
|
|
|
4
5
|
export interface GridTableProps {
|
|
5
6
|
gridTemplateColumns: string;
|
|
@@ -21,7 +22,7 @@ export const GridTable = styled(MTable, {
|
|
|
21
22
|
|
|
22
23
|
td,
|
|
23
24
|
th {
|
|
24
|
-
background-color: ${
|
|
25
|
+
background-color: ${white};
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
td,
|
|
@@ -35,4 +36,11 @@ export const GridTable = styled(MTable, {
|
|
|
35
36
|
min-width: 0; /* required; flexbox child min-width property is "auto" by default making overflow-wrap ineffectual */
|
|
36
37
|
}
|
|
37
38
|
}
|
|
39
|
+
|
|
40
|
+
[id^="grouped-row"] {
|
|
41
|
+
td {
|
|
42
|
+
background-color: ${smokeLightest};
|
|
43
|
+
grid-column: 1 / -1;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
38
46
|
`;
|
|
@@ -363,6 +363,15 @@ export function isClientFilteringEnabled(exploreMode: ExploreMode): boolean {
|
|
|
363
363
|
);
|
|
364
364
|
}
|
|
365
365
|
|
|
366
|
+
/**
|
|
367
|
+
* Returns true if the collapsable row is disabled; i.e. only one column is visible.
|
|
368
|
+
* @param tableInstance - Table instance.
|
|
369
|
+
* @returns true if the collapsable row is disabled.
|
|
370
|
+
*/
|
|
371
|
+
export function isCollapsableRowDisabled<T>(tableInstance: Table<T>): boolean {
|
|
372
|
+
return tableInstance.getVisibleLeafColumns().length === 1;
|
|
373
|
+
}
|
|
374
|
+
|
|
366
375
|
/**
|
|
367
376
|
* Returns true if column has a sort direction.
|
|
368
377
|
* @param sortDirection - Column sort direction.
|
package/src/components/Table/components/TableCell/components/CollapsableCell/collapsableCell.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Collapse, IconButton, Typography } from "@mui/material";
|
|
2
|
-
import { flexRender, Row } from "@tanstack/react-table";
|
|
2
|
+
import { Cell, flexRender, Row, RowData } from "@tanstack/react-table";
|
|
3
3
|
import React, { useState } from "react";
|
|
4
4
|
import { TEXT_BODY_400_2_LINES } from "../../../../../../theme/common/typography";
|
|
5
5
|
import { UnfoldMoreIcon } from "../../../../../common/CustomIcon/components/UnfoldMoreIcon/unfoldMoreIcon";
|
|
@@ -11,11 +11,13 @@ import {
|
|
|
11
11
|
TableCell,
|
|
12
12
|
} from "./collapsableCell.styles";
|
|
13
13
|
|
|
14
|
-
export interface CollapsableCellProps<T> {
|
|
14
|
+
export interface CollapsableCellProps<T extends RowData> {
|
|
15
|
+
isDisabled?: boolean;
|
|
15
16
|
row: Row<T>;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
export const CollapsableCell = <T extends
|
|
19
|
+
export const CollapsableCell = <T extends RowData>({
|
|
20
|
+
isDisabled = false,
|
|
19
21
|
row,
|
|
20
22
|
}: CollapsableCellProps<T>): JSX.Element => {
|
|
21
23
|
const [isExpanded, setIsExpanded] = useState<boolean>(false);
|
|
@@ -32,6 +34,7 @@ export const CollapsableCell = <T extends object>({
|
|
|
32
34
|
{flexRender(pinnedCell.column.columnDef.cell, pinnedCell.getContext())}
|
|
33
35
|
<IconButton
|
|
34
36
|
color="ink"
|
|
37
|
+
disabled={isDisabled}
|
|
35
38
|
edge="end"
|
|
36
39
|
onClick={onToggleExpanded}
|
|
37
40
|
size="large"
|
|
@@ -41,7 +44,9 @@ export const CollapsableCell = <T extends object>({
|
|
|
41
44
|
</PinnedCell>
|
|
42
45
|
<Collapse in={isExpanded}>
|
|
43
46
|
<CollapsedContents>
|
|
44
|
-
{row
|
|
47
|
+
{getRowVisibleCells(row).map((cell, i) => {
|
|
48
|
+
if (cell.getIsAggregated()) return null; // Display of aggregated cells is currently not supported.
|
|
49
|
+
if (cell.getIsPlaceholder()) return null; // Display of placeholder cells is currently not supported.
|
|
45
50
|
const header = cell.column.columnDef.meta?.header;
|
|
46
51
|
return (
|
|
47
52
|
i !== pinnedIndex && (
|
|
@@ -65,3 +70,20 @@ export const CollapsableCell = <T extends object>({
|
|
|
65
70
|
</TableCell>
|
|
66
71
|
);
|
|
67
72
|
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Returns row or sub row visible cells.
|
|
76
|
+
* @param row - Row.
|
|
77
|
+
* @returns row or sub row visible cells.
|
|
78
|
+
*/
|
|
79
|
+
function getRowVisibleCells<T extends RowData>(
|
|
80
|
+
row: Row<T>
|
|
81
|
+
): Cell<T, unknown>[] {
|
|
82
|
+
if (row.getIsGrouped()) {
|
|
83
|
+
return row
|
|
84
|
+
.getLeafRows()
|
|
85
|
+
.map((leafRow) => leafRow.getVisibleCells())
|
|
86
|
+
.flat();
|
|
87
|
+
}
|
|
88
|
+
return row.getVisibleCells();
|
|
89
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TableCell as MTableCell,
|
|
3
3
|
TableHead as MTableHead,
|
|
4
|
-
TableRow,
|
|
4
|
+
TableRow as MTableRow,
|
|
5
5
|
TableSortLabel,
|
|
6
6
|
} from "@mui/material";
|
|
7
7
|
import { flexRender, Table } from "@tanstack/react-table";
|
|
@@ -24,28 +24,39 @@ export const TableHead = <T extends object>({
|
|
|
24
24
|
{rowDirection === ROW_DIRECTION.DEFAULT &&
|
|
25
25
|
tableInstance.getHeaderGroups().map((headerGroup) => (
|
|
26
26
|
<MTableHead key={headerGroup.id}>
|
|
27
|
-
<
|
|
28
|
-
{headerGroup.headers.map((header) =>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
<MTableRow>
|
|
28
|
+
{headerGroup.headers.map((header) => {
|
|
29
|
+
const {
|
|
30
|
+
column: {
|
|
31
|
+
columnDef: {
|
|
32
|
+
meta: { enableSortingInteraction = true } = {},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
} = header;
|
|
36
|
+
return header.column.getIsGrouped() ? null : (
|
|
37
|
+
<MTableCell
|
|
38
|
+
key={header.id}
|
|
39
|
+
padding={getTableCellPadding(header.id)}
|
|
40
|
+
>
|
|
41
|
+
{header.column.getCanSort() && enableSortingInteraction ? (
|
|
42
|
+
<TableSortLabel
|
|
43
|
+
{...getTableSortLabelProps(header.column)}
|
|
44
|
+
>
|
|
45
|
+
{flexRender(
|
|
46
|
+
header.column.columnDef.header,
|
|
47
|
+
header.getContext()
|
|
48
|
+
)}
|
|
49
|
+
</TableSortLabel>
|
|
50
|
+
) : (
|
|
51
|
+
flexRender(
|
|
36
52
|
header.column.columnDef.header,
|
|
37
53
|
header.getContext()
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
)
|
|
45
|
-
)}
|
|
46
|
-
</MTableCell>
|
|
47
|
-
))}
|
|
48
|
-
</TableRow>
|
|
54
|
+
)
|
|
55
|
+
)}
|
|
56
|
+
</MTableCell>
|
|
57
|
+
);
|
|
58
|
+
})}
|
|
59
|
+
</MTableRow>
|
|
49
60
|
</MTableHead>
|
|
50
61
|
))}
|
|
51
62
|
</Fragment>
|
package/src/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import { TableRow as MTableRow } from "@mui/material";
|
|
|
2
2
|
import { Row, Table } from "@tanstack/react-table";
|
|
3
3
|
import { Virtualizer } from "@tanstack/react-virtual";
|
|
4
4
|
import React, { Fragment } from "react";
|
|
5
|
+
import { isCollapsableRowDisabled } from "../../../../common/utils";
|
|
5
6
|
import { CollapsableCell } from "../../../TableCell/components/CollapsableCell/collapsableCell";
|
|
6
7
|
|
|
7
8
|
export interface CollapsableRowsProps<T> {
|
|
@@ -26,7 +27,10 @@ export const CollapsableRows = <T extends object>({
|
|
|
26
27
|
data-index={virtualRow.index}
|
|
27
28
|
ref={virtualizer.measureElement}
|
|
28
29
|
>
|
|
29
|
-
<CollapsableCell
|
|
30
|
+
<CollapsableCell
|
|
31
|
+
isDisabled={isCollapsableRowDisabled(tableInstance)}
|
|
32
|
+
row={row}
|
|
33
|
+
/>
|
|
30
34
|
</MTableRow>
|
|
31
35
|
);
|
|
32
36
|
})}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SvgIcon } from "@mui/material";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { CustomSVGIconProps } from "../../common/entities";
|
|
4
|
+
|
|
5
|
+
export const AddLinkIcon = ({
|
|
6
|
+
fontSize = "xsmall",
|
|
7
|
+
viewBox = "0 0 18 18",
|
|
8
|
+
...props /* Spread props to allow for Mui SvgIconProps specific prop overrides e.g. "htmlColor". */
|
|
9
|
+
}: CustomSVGIconProps): JSX.Element => {
|
|
10
|
+
return (
|
|
11
|
+
<SvgIcon fontSize={fontSize} viewBox={viewBox} {...props}>
|
|
12
|
+
<path
|
|
13
|
+
d="M12.8248 12.6004H11.4561C11.2811 12.6004 11.1279 12.5357 10.9967 12.4063C10.8654 12.277 10.7998 12.1166 10.7998 11.9254C10.7998 11.7504 10.8645 11.5941 10.9939 11.4566C11.1232 11.3191 11.2836 11.2504 11.4748 11.2504H12.8248V9.90039C12.8248 9.70914 12.8891 9.54883 13.0177 9.41945C13.1464 9.29008 13.3057 9.22539 13.4959 9.22539C13.686 9.22539 13.8459 9.29008 13.9755 9.41945C14.1052 9.54883 14.1701 9.70914 14.1701 9.90039V11.2504H15.5233C15.7149 11.2504 15.8756 11.3151 16.0054 11.4445C16.135 11.5738 16.1998 11.7341 16.1998 11.9254C16.1998 12.1166 16.135 12.277 16.0054 12.4063C15.8756 12.5357 15.7149 12.6004 15.5233 12.6004H14.1701V13.9504C14.1701 14.1416 14.1052 14.302 13.9755 14.4313C13.8459 14.5607 13.686 14.6254 13.4959 14.6254C13.3057 14.6254 13.1464 14.5607 13.0177 14.4313C12.8891 14.302 12.8248 14.1416 12.8248 13.9504V12.6004ZM7.4248 12.6004H5.3998C4.4038 12.6004 3.5548 12.249 2.8528 11.5461C2.1508 10.8433 1.7998 9.99333 1.7998 8.99608C1.7998 7.99895 2.1508 7.15039 2.8528 6.45039C3.5548 5.75039 4.4038 5.40039 5.3998 5.40039H7.4248C7.5998 5.40039 7.75605 5.46914 7.89355 5.60664C8.03105 5.74414 8.0998 5.90352 8.0998 6.08477C8.0998 6.26602 8.03105 6.42227 7.89355 6.55352C7.75605 6.68477 7.5998 6.75039 7.4248 6.75039H5.3998C4.7748 6.75039 4.24355 6.96914 3.80605 7.40664C3.36855 7.84414 3.1498 8.37539 3.1498 9.00039C3.1498 9.62539 3.36855 10.1566 3.80605 10.5941C4.24355 11.0316 4.7748 11.2504 5.3998 11.2504H7.4248C7.5998 11.2504 7.75605 11.3191 7.89355 11.4566C8.03105 11.5941 8.0998 11.7535 8.0998 11.9348C8.0998 12.116 8.03105 12.2723 7.89355 12.4035C7.75605 12.5348 7.5998 12.6004 7.4248 12.6004ZM6.98005 9.67539C6.78905 9.67539 6.62793 9.61108 6.49668 9.48245C6.36543 9.35383 6.2998 9.19445 6.2998 9.00433C6.2998 8.8142 6.36443 8.65352 6.49368 8.52227C6.62293 8.39102 6.78305 8.32539 6.97405 8.32539H11.0196C11.2106 8.32539 11.3717 8.3897 11.5029 8.51833C11.6342 8.64695 11.6998 8.80633 11.6998 8.99645C11.6998 9.18658 11.6352 9.34727 11.5059 9.47852C11.3767 9.60977 11.2166 9.67539 11.0256 9.67539H6.98005ZM16.1998 9.00039H14.8498C14.8498 8.37539 14.6311 7.84414 14.1936 7.40664C13.7561 6.96914 13.2248 6.75039 12.5998 6.75039H10.5561C10.3811 6.75039 10.2279 6.6857 10.0967 6.55633C9.96543 6.42695 9.8998 6.26664 9.8998 6.07539C9.8998 5.90039 9.96449 5.74414 10.0939 5.60664C10.2232 5.46914 10.3836 5.40039 10.5748 5.40039H12.5998C13.5958 5.40039 14.4448 5.75139 15.1468 6.45339C15.8488 7.15539 16.1998 8.00439 16.1998 9.00039Z"
|
|
14
|
+
fill="currentColor"
|
|
15
|
+
/>
|
|
16
|
+
</SvgIcon>
|
|
17
|
+
);
|
|
18
|
+
};
|