@databiosphere/findable-ui 44.0.0 → 45.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 (62) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +20 -0
  3. package/lib/components/DataDictionary/components/Table/options/core/constants.js +2 -1
  4. package/lib/components/DataDictionary/components/Table/options/hook.js +2 -0
  5. package/lib/components/Detail/components/Table/table.js +4 -1
  6. package/lib/components/Index/table/hook.js +4 -1
  7. package/lib/components/Table/common/columnDef.js +2 -0
  8. package/lib/components/Table/common/utils.d.ts +0 -6
  9. package/lib/components/Table/common/utils.js +0 -63
  10. package/lib/components/Table/components/TableFeatures/TableDownload/tableDownload.d.ts +3 -0
  11. package/lib/components/Table/components/TableFeatures/TableDownload/tableDownload.js +9 -0
  12. package/lib/components/Table/components/{DownloadEntityResults/downloadEntityResults.styles.js → TableFeatures/TableDownload/tableDownload.styles.js} +1 -1
  13. package/lib/components/Table/components/TableFeatures/TableDownload/types.d.ts +5 -0
  14. package/lib/components/Table/components/TableFeatures/TableDownload/types.js +1 -0
  15. package/lib/components/Table/components/TableToolbar/tableToolbar.js +3 -3
  16. package/lib/components/Table/components/TableToolbar2/tableToolbar2.d.ts +3 -0
  17. package/lib/components/Table/components/TableToolbar2/tableToolbar2.js +8 -0
  18. package/lib/components/Table/components/TableToolbar2/tableToolbar2.styles.d.ts +10 -0
  19. package/lib/components/Table/components/TableToolbar2/tableToolbar2.styles.js +16 -0
  20. package/lib/components/Table/components/TableToolbar2/types.d.ts +4 -0
  21. package/lib/components/Table/components/TableToolbar2/types.js +1 -0
  22. package/lib/components/Table/featureOptions/tableDownload/constants.d.ts +3 -0
  23. package/lib/components/Table/featureOptions/tableDownload/constants.js +3 -0
  24. package/lib/components/Table/features/TableDownload/constants.d.ts +2 -0
  25. package/lib/components/Table/features/TableDownload/constants.js +10 -0
  26. package/lib/components/Table/features/TableDownload/onDownload/utils.d.ts +14 -0
  27. package/lib/components/Table/features/TableDownload/onDownload/utils.js +63 -0
  28. package/lib/components/Table/features/TableDownload/types.d.ts +15 -0
  29. package/lib/components/Table/features/TableDownload/types.js +1 -0
  30. package/lib/components/Table/features/TableDownload/utils.d.ts +19 -0
  31. package/lib/components/Table/features/TableDownload/utils.js +46 -0
  32. package/lib/components/Table/features/entities.d.ts +8 -3
  33. package/lib/config/entities.d.ts +0 -1
  34. package/package.json +1 -1
  35. package/src/components/DataDictionary/components/Table/options/core/constants.ts +2 -1
  36. package/src/components/DataDictionary/components/Table/options/hook.ts +2 -0
  37. package/src/components/Detail/components/Table/table.tsx +4 -1
  38. package/src/components/Index/table/hook.ts +4 -1
  39. package/src/components/Table/common/columnDef.ts +2 -0
  40. package/src/components/Table/common/utils.ts +0 -75
  41. package/src/components/Table/components/{DownloadEntityResults/downloadEntityResults.styles.ts → TableFeatures/TableDownload/tableDownload.styles.ts} +1 -1
  42. package/src/components/Table/components/TableFeatures/TableDownload/tableDownload.tsx +23 -0
  43. package/src/components/Table/components/TableFeatures/TableDownload/types.ts +7 -0
  44. package/src/components/Table/components/TableToolbar/tableToolbar.tsx +3 -8
  45. package/src/components/Table/components/TableToolbar2/tableToolbar2.styles.ts +18 -0
  46. package/src/components/Table/components/TableToolbar2/tableToolbar2.tsx +17 -0
  47. package/src/components/Table/components/TableToolbar2/types.ts +5 -0
  48. package/src/components/Table/featureOptions/tableDownload/constants.ts +9 -0
  49. package/src/components/Table/features/TableDownload/constants.ts +24 -0
  50. package/src/components/Table/features/TableDownload/onDownload/utils.ts +76 -0
  51. package/src/components/Table/features/TableDownload/types.ts +19 -0
  52. package/src/components/Table/features/TableDownload/utils.ts +60 -0
  53. package/src/components/Table/features/entities.ts +19 -3
  54. package/src/config/entities.ts +0 -1
  55. package/types/data-explorer-ui.d.ts +16 -2
  56. package/lib/components/Table/components/DownloadEntityResults/downloadEntityResults.d.ts +0 -6
  57. package/lib/components/Table/components/DownloadEntityResults/downloadEntityResults.js +0 -18
  58. package/lib/components/common/Button/components/FileDownloadButton/fileDownloadButton.d.ts +0 -5
  59. package/lib/components/common/Button/components/FileDownloadButton/fileDownloadButton.js +0 -14
  60. package/src/components/Table/components/DownloadEntityResults/downloadEntityResults.tsx +0 -39
  61. package/src/components/common/Button/components/FileDownloadButton/fileDownloadButton.tsx +0 -27
  62. /package/lib/components/Table/components/{DownloadEntityResults/downloadEntityResults.styles.d.ts → TableFeatures/TableDownload/tableDownload.styles.d.ts} +0 -0
@@ -34,9 +34,11 @@ import {
34
34
  sortingFn,
35
35
  } from "../../Table/common/utils";
36
36
  import { getFacetedMinMaxValues } from "../../Table/featureOptions/facetedColumn/getFacetedMinMaxValues";
37
+ import { TABLE_DOWNLOAD_OPTIONS } from "../../Table/featureOptions/tableDownload/constants";
37
38
  import { ROW_POSITION } from "../../Table/features/RowPosition/constants";
38
39
  import { ROW_PREVIEW } from "../../Table/features/RowPreview/constants";
39
40
  import { RowPreviewState } from "../../Table/features/RowPreview/entities";
41
+ import { TABLE_DOWNLOAD } from "../../Table/features/TableDownload/constants";
40
42
  import { buildBaseColumnDef } from "../../TableCreator/common/utils";
41
43
  import { useTableOptions } from "../../TableCreator/options/hook";
42
44
  import { createCell } from "./coreOptions/columns/cellFactory";
@@ -162,7 +164,7 @@ UseTableProps): UseTable<T> => {
162
164
  * - This will simplify the configuration structure and centralize table state definitions, reducing redundancy and improving clarity.
163
165
  */
164
166
  const table = useReactTable<T>({
165
- _features: [ROW_POSITION, ROW_PREVIEW],
167
+ _features: [ROW_POSITION, ROW_PREVIEW, TABLE_DOWNLOAD],
166
168
  columns: columnDefs,
167
169
  data: listItems || [],
168
170
  enableColumnFilters: true, // client-side filtering.
@@ -187,6 +189,7 @@ UseTableProps): UseTable<T> => {
187
189
  onRowSelectionChange,
188
190
  onSortingChange,
189
191
  pageCount,
192
+ ...TABLE_DOWNLOAD_OPTIONS,
190
193
  state,
191
194
  ...tableOptions,
192
195
  });
@@ -12,6 +12,7 @@ export const COLUMN_DEF: Record<string, ColumnDef<RowData>> = {
12
12
  enableGrouping: false,
13
13
  enableHiding: false,
14
14
  enableSorting: false,
15
+ enableTableDownload: false,
15
16
  header: "",
16
17
  id: COLUMN_IDENTIFIER.ROW_POSITION,
17
18
  meta: {
@@ -27,6 +28,7 @@ export const COLUMN_DEF: Record<string, ColumnDef<RowData>> = {
27
28
  enableGrouping: false,
28
29
  enableHiding: false,
29
30
  enableSorting: false,
31
+ enableTableDownload: false,
30
32
  header: HeadSelectionCell,
31
33
  id: COLUMN_IDENTIFIER.ROW_SELECTION,
32
34
  meta: {
@@ -11,7 +11,6 @@ import {
11
11
  } from "@tanstack/react-table";
12
12
  import { Category } from "../../../common/categories/models/types";
13
13
  import { EXPLORE_MODE, ExploreMode } from "../../../hooks/useExploreMode/types";
14
- import { COLUMN_IDENTIFIER } from "./columnIdentifier";
15
14
 
16
15
  /**
17
16
  * Internal model of a category term count keyed by category term.
@@ -24,11 +23,6 @@ type CountByTerms = Map<any, number>;
24
23
  */
25
24
  type PinnedCell<T extends RowData> = [Cell<T, unknown>, number];
26
25
 
27
- /**
28
- * Model of possible table data values.
29
- */
30
- type TableData = number | string | string[];
31
-
32
26
  /**
33
27
  * Build view-specific models from react table faceted values function.
34
28
  * @param columns - Table columns.
@@ -100,49 +94,6 @@ export function getColumnHeader<T extends RowData>(column: Column<T>): string {
100
94
  return meta?.header || id;
101
95
  }
102
96
 
103
- /**
104
- * Format data to TSV string.
105
- * @param data - Table data.
106
- * @returns table data formatted into a TSV string.
107
- */
108
- function formatDataToTSV(data: TableData[][]): string {
109
- return data
110
- .map((row) => {
111
- return row
112
- .map((data) => {
113
- // Use empty string in place of undefined and null.
114
- if (data === undefined || data === null) return "";
115
- // Convert to string.
116
- const dataString = Array.isArray(data)
117
- ? data.join(", ")
118
- : String(data);
119
- // Quote if necessary.
120
- return /[\t\r\n"]/.test(dataString)
121
- ? `"${dataString.replaceAll('"', '""')}"`
122
- : dataString;
123
- })
124
- .join("\t");
125
- })
126
- .join("\n");
127
- }
128
-
129
- /**
130
- * Returns filtered entity results as a blob.
131
- * @param rows - Table rows.
132
- * @returns filtered entity results as a blob.
133
- */
134
- export function generateDownloadBlob<T extends RowData>(
135
- rows: Row<T>[]
136
- ): Blob | undefined {
137
- if (rows.length === 0) {
138
- return;
139
- }
140
- const tableHeaders = getHeadersTableData(rows);
141
- const tableData = getRowsTableData(rows);
142
- const tsv = formatDataToTSV([tableHeaders, ...tableData]);
143
- return new Blob([tsv], { type: "text/tab-separated-values" });
144
- }
145
-
146
97
  /**
147
98
  * Returns unique category term counts keyed by category terms.
148
99
  * Custom function based off react table function getFacetedUniqueValues, see
@@ -225,32 +176,6 @@ export function getTableStatePagination(
225
176
  };
226
177
  }
227
178
 
228
- /**
229
- * Returns the list of table headers, excluding "rowSelection" column.
230
- * @param rows - Table rows.
231
- * @returns list of headers.
232
- */
233
- function getHeadersTableData<T extends RowData>(rows: Row<T>[]): TableData[] {
234
- return rows[0]
235
- .getAllCells()
236
- .filter((cell) => cell.column.id !== COLUMN_IDENTIFIER.ROW_SELECTION)
237
- .map((cell) => cell.column.columnDef.header as TableData);
238
- }
239
-
240
- /**
241
- * Returns the list of table data, excluding "rowSelection" column.
242
- * @param rows - Table rows.
243
- * @returns list of data.
244
- */
245
- function getRowsTableData<T extends RowData>(rows: Row<T>[]): TableData[][] {
246
- return rows.map((row) =>
247
- row
248
- .getAllCells()
249
- .filter((cell) => cell.column.id !== COLUMN_IDENTIFIER.ROW_SELECTION)
250
- .map((cell) => cell.getValue() as TableData)
251
- );
252
- }
253
-
254
179
  /**
255
180
  * Returns true if any or all table rows are selected.
256
181
  * @param table - Table.
@@ -1,6 +1,6 @@
1
1
  import styled from "@emotion/styled";
2
2
  import { Button } from "@mui/material";
3
- import { bpDownSm } from "../../../../styles/common/mixins/breakpoints";
3
+ import { bpDownSm } from "../../../../../styles/common/mixins/breakpoints";
4
4
 
5
5
  export const StyledButton = styled(Button)`
6
6
  ${bpDownSm} {
@@ -0,0 +1,23 @@
1
+ import { RowData } from "@tanstack/react-table";
2
+ import React from "react";
3
+ import { BUTTON_PROPS } from "../../../../common/Button/constants";
4
+ import { DownloadIcon } from "../../../../common/CustomIcon/components/DownloadIcon/downloadIcon";
5
+ import { StyledButton } from "./tableDownload.styles";
6
+ import { TableDownloadProps } from "./types";
7
+
8
+ export const TableDownload = <T extends RowData>({
9
+ className,
10
+ table,
11
+ }: TableDownloadProps<T>): JSX.Element | null => {
12
+ if (!table.options.enableTableDownload) return null;
13
+ return (
14
+ <StyledButton
15
+ {...BUTTON_PROPS.SECONDARY_CONTAINED}
16
+ className={className}
17
+ onClick={() => table.downloadData()}
18
+ startIcon={<DownloadIcon />}
19
+ >
20
+ Download TSV
21
+ </StyledButton>
22
+ );
23
+ };
@@ -0,0 +1,7 @@
1
+ import { RowData, Table } from "@tanstack/react-table";
2
+ import { BaseComponentProps } from "../../../../types";
3
+
4
+ export interface TableDownloadProps<T extends RowData>
5
+ extends BaseComponentProps {
6
+ table: Table<T>;
7
+ }
@@ -5,8 +5,8 @@ import { ListViewConfig } from "../../../../config/entities";
5
5
  import { useExploreState } from "../../../../hooks/useExploreState";
6
6
  import { ViewToggle } from "../../../Index/components/EntityView/components/controls/ViewToggle/viewToggle";
7
7
  import { isAnyRowSelected } from "../../common/utils";
8
- import { DownloadEntityResults } from "../DownloadEntityResults/downloadEntityResults";
9
8
  import { PaginationSummary } from "../PaginationSummary/paginationSummary";
9
+ import { TableDownload } from "../TableFeatures/TableDownload/tableDownload";
10
10
  import { ColumnGrouping } from "./components/ColumnGrouping/columnGrouping";
11
11
  import { ColumnVisibility } from "./components/ColumnVisibility/columnVisibility";
12
12
  import { RowPreview } from "./components/RowPreview/rowPreview";
@@ -27,7 +27,7 @@ export const TableToolbar = <T extends RowData>({
27
27
  const { paginationState } = exploreState;
28
28
  const { currentPage, pages, pageSize, rows } = paginationState;
29
29
  const { getSelectedRowModel } = tableInstance;
30
- const { enableDownload, rowPreviewView } = listView || {};
30
+ const { rowPreviewView } = listView || {};
31
31
  return (
32
32
  <Fragment>
33
33
  <StyledToolbar>
@@ -47,12 +47,7 @@ export const TableToolbar = <T extends RowData>({
47
47
  )}
48
48
  </Grid>
49
49
  <Grid {...GRID_PROPS}>
50
- {enableDownload && (
51
- <DownloadEntityResults
52
- entityName={exploreState.tabValue}
53
- rows={tableInstance.getFilteredRowModel().rows}
54
- />
55
- )}
50
+ <TableDownload table={tableInstance} />
56
51
  <ColumnGrouping tableInstance={tableInstance} />
57
52
  <ColumnVisibility tableInstance={tableInstance} />
58
53
  </Grid>
@@ -0,0 +1,18 @@
1
+ import styled from "@emotion/styled";
2
+ import { Toolbar as MToolbar, Stack } from "@mui/material";
3
+ import { PALETTE } from "../../../../styles/common/constants/palette";
4
+
5
+ export const StyledToolbar = styled(MToolbar)`
6
+ align-items: center;
7
+ background-color: ${PALETTE.COMMON_WHITE};
8
+ display: flex;
9
+ padding: 16px;
10
+ `;
11
+
12
+ export const StyledStack = styled(Stack)`
13
+ align-items: center;
14
+ flex: 1;
15
+ flex-direction: row;
16
+ gap: 8px;
17
+ justify-content: flex-end;
18
+ `;
@@ -0,0 +1,17 @@
1
+ import { RowData } from "@tanstack/react-table";
2
+ import React from "react";
3
+ import { TableDownload } from "../TableFeatures/TableDownload/tableDownload";
4
+ import { StyledStack, StyledToolbar } from "./tableToolbar2.styles";
5
+ import { TableToolbar2Props } from "./types";
6
+
7
+ export const TableToolbar2 = <T extends RowData>({
8
+ table,
9
+ }: TableToolbar2Props<T>): JSX.Element => {
10
+ return (
11
+ <StyledToolbar>
12
+ <StyledStack>
13
+ <TableDownload table={table} />
14
+ </StyledStack>
15
+ </StyledToolbar>
16
+ );
17
+ };
@@ -0,0 +1,5 @@
1
+ import { RowData, Table } from "@tanstack/react-table";
2
+
3
+ export interface TableToolbar2Props<T extends RowData> {
4
+ table: Table<T>;
5
+ }
@@ -0,0 +1,9 @@
1
+ import { RowData } from "@tanstack/react-table";
2
+ import { TableDownloadOptions } from "../../features/TableDownload/types";
3
+
4
+ export const TABLE_DOWNLOAD_OPTIONS: Pick<
5
+ TableDownloadOptions<RowData>,
6
+ "enableTableDownload"
7
+ > = {
8
+ enableTableDownload: false,
9
+ };
@@ -0,0 +1,24 @@
1
+ import {
2
+ Column,
3
+ RowData,
4
+ Table,
5
+ TableFeature,
6
+ TableOptionsResolved,
7
+ } from "@tanstack/react-table";
8
+ import { downloadData, getCanTableDownload, onTableDownload } from "./utils";
9
+
10
+ export const TABLE_DOWNLOAD: TableFeature = {
11
+ createColumn: <TData extends RowData, TValue>(
12
+ column: Column<TData, TValue>,
13
+ table: Table<TData>
14
+ ): void => {
15
+ column.getCanTableDownload = (): boolean =>
16
+ getCanTableDownload(column, table);
17
+ },
18
+ createTable: <T extends RowData>(table: Table<T>): void => {
19
+ table.downloadData = (): void => downloadData(table);
20
+ },
21
+ getDefaultOptions: <T extends RowData>(): Partial<
22
+ TableOptionsResolved<T>
23
+ > => ({ enableTableDownload: false, onTableDownload }),
24
+ };
@@ -0,0 +1,76 @@
1
+ import { Column, RowData, Table } from "@tanstack/react-table";
2
+ import { getColumnHeader } from "../../../common/utils";
3
+
4
+ /**
5
+ * Format data to TSV string.
6
+ * @param data - Table data.
7
+ * @returns table data formatted into a TSV string.
8
+ */
9
+ export function formatDataToTSV(data: unknown[][]): string {
10
+ return data
11
+ .map((row) => {
12
+ return row
13
+ .map((value) => {
14
+ // Use empty string in place of undefined and null.
15
+ if (value === undefined || value === null) return "";
16
+
17
+ // Convert unknown value to string.
18
+ let valueStr: string;
19
+
20
+ // Test if object / array.
21
+ if (typeof value === "object") {
22
+ if (Array.isArray(value)) {
23
+ // Handle array.
24
+ valueStr = value.join(", ") || "";
25
+ } else {
26
+ // Handle object.
27
+ valueStr = JSON.stringify(value);
28
+ }
29
+ } else {
30
+ // Handle primitive.
31
+ valueStr = String(value);
32
+ }
33
+
34
+ // Quote if necessary.
35
+ return /[\t\r\n"]/.test(valueStr)
36
+ ? `"${valueStr.replaceAll('"', '""')}"`
37
+ : valueStr;
38
+ })
39
+ .join("\t");
40
+ })
41
+ .join("\n");
42
+ }
43
+
44
+ export function getBlob<T extends RowData>(table: Table<T>): Blob | undefined {
45
+ const rows = table.getRowModel().rows;
46
+
47
+ if (rows.length === 0) return;
48
+
49
+ // Get downloadable columns based on getCanDownload property.
50
+ const downloadableColumns = getDownloadableColumns(table);
51
+
52
+ // Extract column IDs for filtering.
53
+ const downloadableColumnIds = downloadableColumns.map((column) => column.id);
54
+
55
+ // Get table headers from downloadable columns.
56
+ const tableHeaders = downloadableColumns.map(getColumnHeader);
57
+
58
+ // Get row data but only for downloadable columns.
59
+ const tableData = rows.map((row) =>
60
+ downloadableColumnIds.map((columnId) => row.getValue(columnId))
61
+ );
62
+
63
+ const tsv = formatDataToTSV([tableHeaders, ...tableData]);
64
+ return new Blob([tsv], { type: "text/tab-separated-values" });
65
+ }
66
+
67
+ /**
68
+ * Filters table columns from column.getCanDownload API.
69
+ * @param table - Table.
70
+ * @returns Columns configured to be downloadable.
71
+ */
72
+ export function getDownloadableColumns<T extends RowData>(
73
+ table: Table<T>
74
+ ): Column<T>[] {
75
+ return table.getAllColumns().filter((column) => column.getCanTableDownload());
76
+ }
@@ -0,0 +1,19 @@
1
+ import { RowData, Table } from "@tanstack/react-table";
2
+
3
+ export interface TableDownloadColumn {
4
+ getCanTableDownload: () => boolean;
5
+ }
6
+
7
+ export interface TableDownloadColumnDef {
8
+ enableTableDownload?: boolean;
9
+ }
10
+
11
+ export interface TableDownloadInstance {
12
+ downloadData: () => void;
13
+ }
14
+
15
+ export interface TableDownloadOptions<T extends RowData> {
16
+ downloadFilename?: string;
17
+ enableTableDownload?: boolean;
18
+ onTableDownload?: (table: Table<T>) => void;
19
+ }
@@ -0,0 +1,60 @@
1
+ import { Column, RowData, Table } from "@tanstack/react-table";
2
+ import { getBlob } from "./onDownload/utils";
3
+
4
+ /**
5
+ * Function that downloads the table data as a TSV file.
6
+ * Uses the onDownload callback, or a custom download function if provided.
7
+ * @param table - Table.
8
+ */
9
+ export function downloadData<T extends RowData>(table: Table<T>): void {
10
+ table.options.onTableDownload?.(table);
11
+ }
12
+
13
+ /**
14
+ * Returns true if column can be downloaded.
15
+ * @param column - Column.
16
+ * @param table - Table.
17
+ * @returns True if column can be downloaded.
18
+ */
19
+ export function getCanTableDownload<T extends RowData, TValue>(
20
+ column: Column<T, TValue>,
21
+ table: Table<T>
22
+ ): boolean {
23
+ return (
24
+ (column.columnDef.enableTableDownload ?? true) &&
25
+ (table.options.enableTableDownload ?? false)
26
+ );
27
+ }
28
+
29
+ /**
30
+ * Default download function that downloads the table data as a TSV file.
31
+ * @param table - Table.
32
+ */
33
+ export function onTableDownload<T extends RowData>(table: Table<T>): void {
34
+ // Check if download is enabled.
35
+ if (!(table.options.enableTableDownload ?? false)) return;
36
+
37
+ // Generate the blob.
38
+ const blob = getBlob(table);
39
+ if (!blob) return;
40
+
41
+ // Create an object URL for the blob.
42
+ const url = URL.createObjectURL(blob);
43
+
44
+ // Create a download link.
45
+ const anchorEl = document.createElement("a");
46
+ anchorEl.href = url;
47
+ anchorEl.download = table.options.downloadFilename || "table-data.tsv";
48
+
49
+ // Append to the document body for better cross-browser support.
50
+ document.body.appendChild(anchorEl);
51
+
52
+ // Trigger the download.
53
+ anchorEl.click();
54
+
55
+ // Remove the element after triggering download.
56
+ document.body.removeChild(anchorEl);
57
+
58
+ // Clean up.
59
+ URL.revokeObjectURL(url);
60
+ }
@@ -6,9 +6,25 @@ import {
6
6
  RowPreviewRow,
7
7
  RowPreviewTableState,
8
8
  } from "./RowPreview/entities";
9
+ import {
10
+ TableDownloadColumn,
11
+ TableDownloadInstance,
12
+ TableDownloadOptions,
13
+ } from "./TableDownload/types";
14
+
15
+ export type CustomFeatureColumn = TableDownloadColumn;
16
+
17
+ export interface CustomFeatureInstance<T extends RowData>
18
+ extends TableDownloadInstance,
19
+ RowPreviewInstance<T> {}
9
20
 
10
21
  export type CustomFeatureInitialTableState = Partial<RowPreviewTableState>;
11
- export type CustomFeatureInstance<T extends RowData> = RowPreviewInstance<T>;
12
- export type CustomFeatureOptions = RowPreviewOptions & RowPositionOptions;
13
- export type CustomFeatureRow = RowPositionRow & RowPreviewRow;
22
+
23
+ export interface CustomFeatureOptions<T extends RowData>
24
+ extends TableDownloadOptions<T>,
25
+ RowPositionOptions,
26
+ RowPreviewOptions {}
27
+
28
+ export interface CustomFeatureRow extends RowPositionRow, RowPreviewRow {}
29
+
14
30
  export type CustomFeatureTableState = RowPreviewTableState;
@@ -277,7 +277,6 @@ export interface ListConfig<T extends RowData> {
277
277
  */
278
278
  export interface ListViewConfig {
279
279
  disablePagination?: boolean;
280
- enableDownload?: boolean;
281
280
  rowPreviewView?: ComponentsConfig; // Row preview view is expected to be a modal or drawer or similar.
282
281
  rowSelectionView?: ComponentsConfig;
283
282
  }
@@ -23,6 +23,7 @@ import { Components } from "rehype-react";
23
23
  import { DataLayer } from "../src/common/analytics/entities";
24
24
  import { DataDictionaryAnnotation } from "../src/common/entities";
25
25
  import {
26
+ CustomFeatureColumn,
26
27
  CustomFeatureInitialTableState,
27
28
  CustomFeatureInstance,
28
29
  CustomFeatureOptions,
@@ -244,6 +245,14 @@ declare module "@emotion/react" {
244
245
  }
245
246
 
246
247
  declare module "@tanstack/react-table" {
248
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- TData and TValue are unused variables.
249
+ interface Column<TData extends RowData, TValue> extends CustomFeatureColumn {}
250
+
251
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- TData and TValue are unused variables.
252
+ interface ColumnDefBase<TData extends RowData, TValue> {
253
+ enableTableDownload?: boolean;
254
+ }
255
+
247
256
  // eslint-disable-next-line @typescript-eslint/no-unused-vars -- TData and TValue are unused variables.
248
257
  interface ColumnMeta<TData extends RowData, TValue> {
249
258
  align?: TableCellProps["align"];
@@ -253,10 +262,13 @@ declare module "@tanstack/react-table" {
253
262
  header?: string;
254
263
  width?: GridTrackSize;
255
264
  }
265
+
256
266
  // eslint-disable-next-line @typescript-eslint/no-empty-interface -- empty interface is needed for extending.
257
267
  interface InitialTableState extends CustomFeatureInitialTableState {}
268
+
258
269
  // eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/no-unused-vars -- empty interface is needed for extending, TData is an unused variable.
259
270
  interface Row<TData extends RowData> extends CustomFeatureRow {}
271
+
260
272
  // eslint-disable-next-line @typescript-eslint/no-unused-vars -- TData is an unused variables.
261
273
  interface SortingOptions<TData extends RowData> {
262
274
  /**
@@ -265,11 +277,13 @@ declare module "@tanstack/react-table" {
265
277
  */
266
278
  enableSortingInteraction?: boolean;
267
279
  }
280
+
268
281
  // eslint-disable-next-line @typescript-eslint/no-empty-interface -- empty interface is needed for extending.
269
282
  interface Table<TData extends RowData> extends CustomFeatureInstance<TData> {}
270
- // eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/no-unused-vars -- empty interface is needed for extending, TData is an unused variable.
283
+
271
284
  interface TableOptionsResolved<TData extends RowData>
272
- extends CustomFeatureOptions {}
285
+ extends CustomFeatureOptions<TData> {}
286
+
273
287
  // eslint-disable-next-line @typescript-eslint/no-empty-interface -- empty interface is needed for extending.
274
288
  interface TableState extends CustomFeatureTableState {}
275
289
  }
@@ -1,6 +0,0 @@
1
- import { Row, RowData } from "@tanstack/react-table";
2
- export interface DownloadEntityResultsProps<T extends RowData> {
3
- entityName: string;
4
- rows: Row<T>[];
5
- }
6
- export declare const DownloadEntityResults: <T extends RowData>({ entityName, rows, }: DownloadEntityResultsProps<T>) => JSX.Element;
@@ -1,18 +0,0 @@
1
- import React from "react";
2
- import { FileDownloadButton } from "../../../common/Button/components/FileDownloadButton/fileDownloadButton";
3
- import { BUTTON_PROPS } from "../../../common/Button/constants";
4
- import { DownloadIcon } from "../../../common/CustomIcon/components/DownloadIcon/downloadIcon";
5
- import { generateDownloadBlob } from "../../common/utils";
6
- import { StyledButton } from "./downloadEntityResults.styles";
7
- export const DownloadEntityResults = ({ entityName, rows, }) => {
8
- const [fileUrl, setFileUrl] = React.useState(undefined);
9
- const onDownload = () => {
10
- const blob = generateDownloadBlob(rows);
11
- if (blob) {
12
- setFileUrl(window.URL.createObjectURL(blob));
13
- }
14
- };
15
- return (React.createElement(React.Fragment, null,
16
- React.createElement(StyledButton, { ...BUTTON_PROPS.SECONDARY_CONTAINED, onClick: () => onDownload(), startIcon: React.createElement(DownloadIcon, null) }, "Download TSV"),
17
- React.createElement(FileDownloadButton, { fileName: `${entityName}.tsv`, fileUrl: fileUrl })));
18
- };
@@ -1,5 +0,0 @@
1
- export interface FileDownloadButtonProps {
2
- fileName?: string;
3
- fileUrl?: string;
4
- }
5
- export declare const FileDownloadButton: ({ fileName, fileUrl, }: FileDownloadButtonProps) => JSX.Element;
@@ -1,14 +0,0 @@
1
- import { Box } from "@mui/material";
2
- import React, { useEffect, useRef } from "react";
3
- export const FileDownloadButton = ({ fileName, fileUrl, }) => {
4
- const downloadRef = useRef(null);
5
- // Initiates file download when file url request is successful.
6
- useEffect(() => {
7
- if (downloadRef.current && fileName && fileUrl) {
8
- downloadRef.current.setAttribute("href", fileUrl);
9
- downloadRef.current.setAttribute("download", fileName);
10
- downloadRef.current.click();
11
- }
12
- }, [fileName, fileUrl]);
13
- return (React.createElement(Box, { component: "a", download: true, ref: downloadRef, sx: { display: "none" } }));
14
- };
@@ -1,39 +0,0 @@
1
- import { Row, RowData } from "@tanstack/react-table";
2
- import React from "react";
3
- import { FileDownloadButton } from "../../../common/Button/components/FileDownloadButton/fileDownloadButton";
4
- import { BUTTON_PROPS } from "../../../common/Button/constants";
5
- import { DownloadIcon } from "../../../common/CustomIcon/components/DownloadIcon/downloadIcon";
6
- import { generateDownloadBlob } from "../../common/utils";
7
- import { StyledButton } from "./downloadEntityResults.styles";
8
-
9
- export interface DownloadEntityResultsProps<T extends RowData> {
10
- entityName: string;
11
- rows: Row<T>[];
12
- }
13
-
14
- export const DownloadEntityResults = <T extends RowData>({
15
- entityName,
16
- rows,
17
- }: DownloadEntityResultsProps<T>): JSX.Element => {
18
- const [fileUrl, setFileUrl] = React.useState<string | undefined>(undefined);
19
-
20
- const onDownload = (): void => {
21
- const blob = generateDownloadBlob(rows);
22
- if (blob) {
23
- setFileUrl(window.URL.createObjectURL(blob));
24
- }
25
- };
26
-
27
- return (
28
- <>
29
- <StyledButton
30
- {...BUTTON_PROPS.SECONDARY_CONTAINED}
31
- onClick={(): void => onDownload()}
32
- startIcon={<DownloadIcon />}
33
- >
34
- Download TSV
35
- </StyledButton>
36
- <FileDownloadButton fileName={`${entityName}.tsv`} fileUrl={fileUrl} />
37
- </>
38
- );
39
- };