@teselagen/ui 0.8.6 → 0.9.1
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/DataTable/EditabelCell.d.ts +10 -0
- package/DataTable/defaultProps.d.ts +43 -0
- package/DataTable/utils/computePresets.d.ts +1 -0
- package/DataTable/utils/getAllRows.d.ts +1 -1
- package/DataTable/utils/handleCopyColumn.d.ts +1 -1
- package/DataTable/utils/handleCopyTable.d.ts +1 -1
- package/DataTable/utils/initializeHasuraWhereAndFilter.d.ts +0 -1
- package/DataTable/utils/queryParams.d.ts +16 -12
- package/DataTable/utils/tableQueryParamsToHasuraClauses.d.ts +1 -1
- package/README.md +1 -1
- package/index.cjs.js +1139 -1040
- package/index.d.ts +2 -0
- package/index.es.js +1139 -1040
- package/package.json +2 -2
- package/src/DataTable/Columns.js +2 -2
- package/src/DataTable/DisplayOptions.js +1 -1
- package/src/DataTable/EditabelCell.js +55 -0
- package/src/DataTable/FilterAndSortMenu.js +27 -30
- package/src/DataTable/defaultProps.js +45 -0
- package/src/DataTable/index.js +101 -84
- package/src/DataTable/style.css +1 -1
- package/src/DataTable/utils/computePresets.js +42 -0
- package/src/DataTable/utils/filterLocalEntitiesToHasura.js +128 -8
- package/src/DataTable/utils/filterLocalEntitiesToHasura.test.js +719 -21
- package/src/DataTable/utils/getAllRows.js +2 -6
- package/src/DataTable/utils/handleCopyColumn.js +2 -2
- package/src/DataTable/utils/handleCopyTable.js +2 -2
- package/src/DataTable/utils/initializeHasuraWhereAndFilter.js +1 -12
- package/src/DataTable/utils/queryParams.js +153 -770
- package/src/DataTable/utils/tableQueryParamsToHasuraClauses.js +185 -168
- package/src/DataTable/utils/tableQueryParamsToHasuraClauses.test.js +50 -11
- package/src/DataTable/utils/withTableParams.js +3 -16
- package/src/ExcelCell.js +38 -0
- package/src/FormComponents/Uploader.js +5 -1
- package/src/FormComponents/index.js +2 -2
- package/src/TgSelect/index.js +15 -0
- package/src/autoTooltip.js +1 -0
- package/src/index.js +2 -0
- package/src/utils/determineBlackOrWhiteTextColor.js +8 -1
- package/style.css +10537 -0
- package/ui.css +1 -1
- package/utils/determineBlackOrWhiteTextColor.d.ts +1 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teselagen/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"main": "./src/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"@dnd-kit/core": "^6.1.0",
|
|
18
18
|
"@dnd-kit/modifiers": "^7.0.0",
|
|
19
19
|
"@dnd-kit/sortable": "^8.0.0",
|
|
20
|
-
"@teselagen/react-table": "6.10.
|
|
20
|
+
"@teselagen/react-table": "6.10.18",
|
|
21
21
|
"classnames": "^2.3.2",
|
|
22
22
|
"color": "^3.2.1",
|
|
23
23
|
"copy-to-clipboard": "^3.3.1",
|
package/src/DataTable/Columns.js
CHANGED
|
@@ -33,10 +33,10 @@ import getTextFromEl from "../utils/getTextFromEl";
|
|
|
33
33
|
import rowClick, { finalizeSelection } from "./utils/rowClick";
|
|
34
34
|
import { editCellHelper } from "./editCellHelper";
|
|
35
35
|
import { getCellVal } from "./getCellVal";
|
|
36
|
-
import { getCCDisplayName } from "./utils/queryParams";
|
|
37
36
|
import { useDispatch } from "react-redux";
|
|
38
37
|
import { change as _change } from "redux-form";
|
|
39
38
|
import { RenderCell } from "./RenderCell";
|
|
39
|
+
import { getCCDisplayName } from "./utils/tableQueryParamsToHasuraClauses";
|
|
40
40
|
|
|
41
41
|
dayjs.extend(localizedFormat);
|
|
42
42
|
|
|
@@ -104,7 +104,7 @@ const RenderColumnHeader = ({
|
|
|
104
104
|
if (order && order.length) {
|
|
105
105
|
order.forEach(order => {
|
|
106
106
|
const orderField = order.replace("-", "");
|
|
107
|
-
if (orderField ===
|
|
107
|
+
if (orderField === path) {
|
|
108
108
|
if (orderField === order) {
|
|
109
109
|
ordering = "asc";
|
|
110
110
|
} else {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
2
|
+
|
|
3
|
+
export const EditableCell = ({
|
|
4
|
+
cancelEdit,
|
|
5
|
+
dataTest,
|
|
6
|
+
finishEdit,
|
|
7
|
+
initialValue,
|
|
8
|
+
isEditableCellInitialValue,
|
|
9
|
+
isNumeric,
|
|
10
|
+
shouldSelectAll,
|
|
11
|
+
stopSelectAll
|
|
12
|
+
}) => {
|
|
13
|
+
const [value, setValue] = useState(initialValue);
|
|
14
|
+
const inputRef = useRef(null);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
if (inputRef.current) {
|
|
18
|
+
inputRef.current.focus();
|
|
19
|
+
if (isEditableCellInitialValue && !isNumeric) {
|
|
20
|
+
inputRef.current.selectionStart = inputRef.current.value.length;
|
|
21
|
+
inputRef.current.selectionEnd = inputRef.current.value.length;
|
|
22
|
+
} else if (shouldSelectAll) {
|
|
23
|
+
inputRef.current.select();
|
|
24
|
+
stopSelectAll();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}, [isEditableCellInitialValue, isNumeric, shouldSelectAll, stopSelectAll]);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<input
|
|
31
|
+
style={{
|
|
32
|
+
border: 0,
|
|
33
|
+
width: "95%",
|
|
34
|
+
fontSize: 12,
|
|
35
|
+
background: "none"
|
|
36
|
+
}}
|
|
37
|
+
ref={inputRef}
|
|
38
|
+
{...dataTest}
|
|
39
|
+
autoFocus
|
|
40
|
+
onKeyDown={e => {
|
|
41
|
+
if (e.key === "Enter") {
|
|
42
|
+
finishEdit(value);
|
|
43
|
+
e.stopPropagation();
|
|
44
|
+
} else if (e.key === "Escape") {
|
|
45
|
+
e.stopPropagation();
|
|
46
|
+
cancelEdit();
|
|
47
|
+
}
|
|
48
|
+
}}
|
|
49
|
+
onBlur={() => finishEdit(value)}
|
|
50
|
+
onChange={e => setValue(e.target.value)}
|
|
51
|
+
type={isNumeric ? "number" : undefined}
|
|
52
|
+
value={value}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
55
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useState } from "react";
|
|
2
2
|
import { DateInput, DateRangeInput } from "@blueprintjs/datetime";
|
|
3
|
-
import { camelCase } from "lodash-es";
|
|
3
|
+
import { camelCase, startCase } from "lodash-es";
|
|
4
4
|
import classNames from "classnames";
|
|
5
5
|
import {
|
|
6
6
|
Menu,
|
|
@@ -349,43 +349,40 @@ function getFilterMenuItems(dataType) {
|
|
|
349
349
|
let filterMenuItems = [];
|
|
350
350
|
if (dataType === "string") {
|
|
351
351
|
filterMenuItems = [
|
|
352
|
-
"
|
|
353
|
-
"
|
|
354
|
-
"
|
|
355
|
-
"
|
|
356
|
-
"
|
|
357
|
-
"
|
|
358
|
-
"
|
|
359
|
-
"
|
|
360
|
-
"
|
|
361
|
-
"
|
|
352
|
+
"contains",
|
|
353
|
+
"notContains",
|
|
354
|
+
"startsWith",
|
|
355
|
+
"endsWith",
|
|
356
|
+
"isExactly",
|
|
357
|
+
"regex",
|
|
358
|
+
"inList",
|
|
359
|
+
"notInList",
|
|
360
|
+
"isEmpty",
|
|
361
|
+
"notEmpty"
|
|
362
362
|
];
|
|
363
363
|
} else if (dataType === "lookup") {
|
|
364
364
|
filterMenuItems = [
|
|
365
|
-
"
|
|
366
|
-
"
|
|
367
|
-
"
|
|
368
|
-
"
|
|
369
|
-
"
|
|
370
|
-
"
|
|
365
|
+
"contains",
|
|
366
|
+
"notContains",
|
|
367
|
+
"startsWith",
|
|
368
|
+
"endsWith",
|
|
369
|
+
"isExactly",
|
|
370
|
+
"regex"
|
|
371
371
|
];
|
|
372
372
|
} else if (dataType === "boolean") {
|
|
373
|
-
filterMenuItems = ["
|
|
373
|
+
filterMenuItems = ["true", "false"];
|
|
374
374
|
} else if (dataType === "number" || dataType === "integer") {
|
|
375
|
-
// else if (dataType === "lookup") {
|
|
376
|
-
// filterMenuItems = ["None"];
|
|
377
|
-
// }
|
|
378
375
|
filterMenuItems = [
|
|
379
|
-
"
|
|
380
|
-
"
|
|
381
|
-
"
|
|
382
|
-
"
|
|
383
|
-
"
|
|
384
|
-
"
|
|
385
|
-
"
|
|
376
|
+
"greaterThan",
|
|
377
|
+
"lessThan",
|
|
378
|
+
"inRange",
|
|
379
|
+
"outsideRange",
|
|
380
|
+
"equalTo",
|
|
381
|
+
"inList",
|
|
382
|
+
"notInList"
|
|
386
383
|
];
|
|
387
384
|
} else if (dataType === "timestamp") {
|
|
388
|
-
filterMenuItems = ["
|
|
385
|
+
filterMenuItems = ["isBetween", "notBetween", "isBefore", "isAfter"];
|
|
389
386
|
}
|
|
390
|
-
return filterMenuItems;
|
|
387
|
+
return filterMenuItems.map(item => startCase(item));
|
|
391
388
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { noop } from "lodash-es";
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line import/no-anonymous-default-export
|
|
4
|
+
export default {
|
|
5
|
+
//NOTE: DO NOT SET DEFAULTS HERE FOR PROPS THAT GET COMPUTED AS PART OF PRESET GROUPS IN computePresets
|
|
6
|
+
addFilters: noop,
|
|
7
|
+
className: "",
|
|
8
|
+
clearFilters: noop,
|
|
9
|
+
contextMenu: noop,
|
|
10
|
+
disabled: false,
|
|
11
|
+
entities: [],
|
|
12
|
+
extraClasses: "",
|
|
13
|
+
filters: [],
|
|
14
|
+
isCopyable: true,
|
|
15
|
+
isEntityDisabled: noop,
|
|
16
|
+
isLoading: false,
|
|
17
|
+
isSimple: false,
|
|
18
|
+
isSingleSelect: false,
|
|
19
|
+
maxHeight: 600,
|
|
20
|
+
noHeader: false,
|
|
21
|
+
noSelect: false,
|
|
22
|
+
noUserSelect: false,
|
|
23
|
+
onDeselect: noop,
|
|
24
|
+
onMultiRowSelect: noop,
|
|
25
|
+
onRowClick: noop,
|
|
26
|
+
onRowSelect: noop,
|
|
27
|
+
onSingleRowSelect: noop,
|
|
28
|
+
page: 1,
|
|
29
|
+
pageSize: 10,
|
|
30
|
+
reduxFormExpandedEntityIdMap: {},
|
|
31
|
+
reduxFormSearchInput: "",
|
|
32
|
+
reduxFormSelectedEntityIdMap: {},
|
|
33
|
+
removeSingleFilter: noop,
|
|
34
|
+
resized: [],
|
|
35
|
+
resizePersist: noop,
|
|
36
|
+
setFilter: noop,
|
|
37
|
+
setOrder: noop,
|
|
38
|
+
setPage: noop,
|
|
39
|
+
setPageSize: noop,
|
|
40
|
+
setSearchTerm: noop,
|
|
41
|
+
showCount: false,
|
|
42
|
+
style: {},
|
|
43
|
+
withCheckboxes: false,
|
|
44
|
+
withSort: true
|
|
45
|
+
};
|
package/src/DataTable/index.js
CHANGED
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
import { arrayMove } from "@dnd-kit/sortable";
|
|
44
44
|
import classNames from "classnames";
|
|
45
45
|
import scrollIntoView from "dom-scroll-into-view";
|
|
46
|
-
import ReactTable from "@teselagen/react-table";
|
|
46
|
+
import ReactTable, { VIRTUALIZE_CUTOFF_LENGTH } from "@teselagen/react-table";
|
|
47
47
|
import immer, { produceWithPatches, enablePatches, applyPatches } from "immer";
|
|
48
48
|
import papaparse from "papaparse";
|
|
49
49
|
import { useDispatch, useSelector } from "react-redux";
|
|
@@ -92,10 +92,9 @@ import { viewColumn, openColumn, multiViewColumn } from "./viewColumn";
|
|
|
92
92
|
import convertSchema from "./utils/convertSchema";
|
|
93
93
|
import TableFormTrackerContext from "./TableFormTrackerContext";
|
|
94
94
|
import {
|
|
95
|
-
getCCDisplayName,
|
|
96
|
-
getCurrentParamsFromUrl,
|
|
97
95
|
getQueryParams,
|
|
98
96
|
makeDataTableHandlers,
|
|
97
|
+
getCurrentParamsFromUrl,
|
|
99
98
|
setCurrentParamsOnUrl
|
|
100
99
|
} from "./utils/queryParams";
|
|
101
100
|
import { useColumns } from "./Columns";
|
|
@@ -103,6 +102,7 @@ import { formValueSelector, change as _change } from "redux-form";
|
|
|
103
102
|
import { throwFormError } from "../throwFormError";
|
|
104
103
|
import { isObservableArray, toJS } from "mobx";
|
|
105
104
|
import { isBeingCalledExcessively } from "../utils/isBeingCalledExcessively";
|
|
105
|
+
import { getCCDisplayName } from "./utils/tableQueryParamsToHasuraClauses";
|
|
106
106
|
|
|
107
107
|
enablePatches();
|
|
108
108
|
const IS_LINUX = window.navigator.platform.toLowerCase().search("linux") > -1;
|
|
@@ -141,6 +141,7 @@ const DataTable = ({
|
|
|
141
141
|
);
|
|
142
142
|
const tableRef = useRef();
|
|
143
143
|
const alreadySelected = useRef(false);
|
|
144
|
+
const [noVirtual, setNoVirtual] = useState(false);
|
|
144
145
|
const [onlyShowRowsWErrors, setOnlyShowRowsWErrors] = useState(false);
|
|
145
146
|
const [entitiesUndoRedoStack, setEntitiesUndoRedoStack] = useState({
|
|
146
147
|
currentVersion: 0
|
|
@@ -337,16 +338,6 @@ const DataTable = ({
|
|
|
337
338
|
|
|
338
339
|
const queryParams = useMemo(() => {
|
|
339
340
|
if (!isTableParamsConnected) {
|
|
340
|
-
const additionalFilterToUse =
|
|
341
|
-
typeof props.additionalFilter === "function"
|
|
342
|
-
? props.additionalFilter
|
|
343
|
-
: () => props.additionalFilter;
|
|
344
|
-
|
|
345
|
-
const additionalOrFilterToUse =
|
|
346
|
-
typeof props.additionalOrFilter === "function"
|
|
347
|
-
? props.additionalOrFilter
|
|
348
|
-
: () => props.additionalOrFilter;
|
|
349
|
-
|
|
350
341
|
return getQueryParams({
|
|
351
342
|
doNotCoercePageSize,
|
|
352
343
|
currentParams,
|
|
@@ -356,8 +347,7 @@ const DataTable = ({
|
|
|
356
347
|
schema: convertedSchema,
|
|
357
348
|
isInfinite,
|
|
358
349
|
isLocalCall,
|
|
359
|
-
additionalFilter:
|
|
360
|
-
additionalOrFilter: additionalOrFilterToUse,
|
|
350
|
+
additionalFilter: props.additionalFilter,
|
|
361
351
|
noOrderError: props.noOrderError,
|
|
362
352
|
isCodeModel: props.isCodeModel,
|
|
363
353
|
ownProps: props
|
|
@@ -614,7 +604,7 @@ const DataTable = ({
|
|
|
614
604
|
: !val;
|
|
615
605
|
});
|
|
616
606
|
}
|
|
617
|
-
if (noValsForField) {
|
|
607
|
+
if (noValsForField && entities.length) {
|
|
618
608
|
return {
|
|
619
609
|
...field,
|
|
620
610
|
isHidden: true,
|
|
@@ -1156,70 +1146,94 @@ const DataTable = ({
|
|
|
1156
1146
|
updateValidation
|
|
1157
1147
|
]);
|
|
1158
1148
|
|
|
1159
|
-
const
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
let firstRowIndex;
|
|
1168
|
-
let firstCellIndex;
|
|
1169
|
-
Object.keys(selectedCells).forEach(key => {
|
|
1170
|
-
const [rowId, path] = key.split(":");
|
|
1171
|
-
const eInfo = entityIdToEntity[rowId];
|
|
1172
|
-
if (eInfo) {
|
|
1173
|
-
if (firstRowIndex === undefined || eInfo.i < firstRowIndex) {
|
|
1174
|
-
firstRowIndex = eInfo.i;
|
|
1175
|
-
}
|
|
1176
|
-
if (!selectionGrid[eInfo.i]) {
|
|
1177
|
-
selectionGrid[eInfo.i] = [];
|
|
1178
|
-
}
|
|
1179
|
-
const cellIndex = pathToIndex[path];
|
|
1180
|
-
if (firstCellIndex === undefined || cellIndex < firstCellIndex) {
|
|
1181
|
-
firstCellIndex = cellIndex;
|
|
1182
|
-
}
|
|
1183
|
-
selectionGrid[eInfo.i][cellIndex] = true;
|
|
1149
|
+
const waitUntilAllRowsAreRendered = useCallback(() => {
|
|
1150
|
+
return new Promise(resolve => {
|
|
1151
|
+
const interval = setInterval(() => {
|
|
1152
|
+
const allRowEls =
|
|
1153
|
+
tableRef.current?.tableRef?.querySelectorAll(".rt-tr-group");
|
|
1154
|
+
if (allRowEls?.length === entities.length) {
|
|
1155
|
+
clearInterval(interval);
|
|
1156
|
+
resolve();
|
|
1184
1157
|
}
|
|
1185
|
-
});
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1158
|
+
}, 50);
|
|
1159
|
+
});
|
|
1160
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1161
|
+
}, []);
|
|
1162
|
+
|
|
1163
|
+
const handleCopySelectedCells = useCallback(async () => {
|
|
1164
|
+
// if the current selection is consecutive cells then copy with
|
|
1165
|
+
// tabs between. if not then just select primary selected cell
|
|
1166
|
+
if (isEmpty(selectedCells)) return;
|
|
1167
|
+
|
|
1168
|
+
// Temporarily disable virtualization for large tables
|
|
1169
|
+
if (entities.length > VIRTUALIZE_CUTOFF_LENGTH) {
|
|
1170
|
+
setNoVirtual(true);
|
|
1171
|
+
await waitUntilAllRowsAreRendered();
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
const pathToIndex = getFieldPathToIndex(schema);
|
|
1175
|
+
const entityIdToEntity = getEntityIdToEntity(entities);
|
|
1176
|
+
const selectionGrid = [];
|
|
1177
|
+
let firstRowIndex;
|
|
1178
|
+
let firstCellIndex;
|
|
1179
|
+
Object.keys(selectedCells).forEach(key => {
|
|
1180
|
+
const [rowId, path] = key.split(":");
|
|
1181
|
+
const eInfo = entityIdToEntity[rowId];
|
|
1182
|
+
if (eInfo) {
|
|
1183
|
+
if (firstRowIndex === undefined || eInfo.i < firstRowIndex) {
|
|
1184
|
+
firstRowIndex = eInfo.i;
|
|
1194
1185
|
}
|
|
1195
|
-
if (!
|
|
1196
|
-
|
|
1197
|
-
} else {
|
|
1198
|
-
const jsonRow = [];
|
|
1199
|
-
// ignore header
|
|
1200
|
-
let [rowCopyText, json] = getRowCopyText(allRows[i + 1]);
|
|
1201
|
-
rowCopyText = rowCopyText.split("\t");
|
|
1202
|
-
times(row.length, i => {
|
|
1203
|
-
const cell = row[i];
|
|
1204
|
-
if (cell) {
|
|
1205
|
-
fullCellText += rowCopyText[i];
|
|
1206
|
-
jsonRow.push(json[i]);
|
|
1207
|
-
}
|
|
1208
|
-
if (i !== row.length - 1 && i >= firstCellIndex)
|
|
1209
|
-
fullCellText += "\t";
|
|
1210
|
-
});
|
|
1211
|
-
fullJson.push(jsonRow);
|
|
1186
|
+
if (!selectionGrid[eInfo.i]) {
|
|
1187
|
+
selectionGrid[eInfo.i] = [];
|
|
1212
1188
|
}
|
|
1213
|
-
|
|
1214
|
-
|
|
1189
|
+
const cellIndex = pathToIndex[path];
|
|
1190
|
+
if (firstCellIndex === undefined || cellIndex < firstCellIndex) {
|
|
1191
|
+
firstCellIndex = cellIndex;
|
|
1192
|
+
}
|
|
1193
|
+
selectionGrid[eInfo.i][cellIndex] = true;
|
|
1194
|
+
}
|
|
1195
|
+
});
|
|
1196
|
+
if (firstRowIndex === undefined) return;
|
|
1197
|
+
const allRows = getAllRows(tableRef);
|
|
1198
|
+
let fullCellText = "";
|
|
1199
|
+
const fullJson = [];
|
|
1200
|
+
times(selectionGrid.length, i => {
|
|
1201
|
+
const row = selectionGrid[i];
|
|
1202
|
+
if (fullCellText) {
|
|
1203
|
+
fullCellText += "\n";
|
|
1204
|
+
}
|
|
1205
|
+
if (!row) {
|
|
1206
|
+
return;
|
|
1207
|
+
} else {
|
|
1208
|
+
const jsonRow = [];
|
|
1209
|
+
// ignore header
|
|
1210
|
+
let [rowCopyText, json] = getRowCopyText(allRows[i + 1]);
|
|
1211
|
+
rowCopyText = rowCopyText.split("\t");
|
|
1212
|
+
times(row.length, i => {
|
|
1213
|
+
const cell = row[i];
|
|
1214
|
+
if (cell) {
|
|
1215
|
+
fullCellText += rowCopyText[i];
|
|
1216
|
+
jsonRow.push(json[i]);
|
|
1217
|
+
}
|
|
1218
|
+
if (i !== row.length - 1 && i >= firstCellIndex) fullCellText += "\t";
|
|
1219
|
+
});
|
|
1220
|
+
fullJson.push(jsonRow);
|
|
1221
|
+
}
|
|
1222
|
+
});
|
|
1223
|
+
if (!fullCellText) return window.toastr.warning("No text to copy");
|
|
1215
1224
|
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1225
|
+
handleCopyHelper(fullCellText, fullJson, "Selected cells copied");
|
|
1226
|
+
|
|
1227
|
+
// Re-enable virtualization if it was disabled
|
|
1228
|
+
setNoVirtual(false);
|
|
1229
|
+
}, [entities, selectedCells, schema, waitUntilAllRowsAreRendered]);
|
|
1220
1230
|
|
|
1221
1231
|
const handleCopySelectedRows = useCallback(
|
|
1222
|
-
|
|
1232
|
+
async selectedRecords => {
|
|
1233
|
+
if (entities.length > VIRTUALIZE_CUTOFF_LENGTH) {
|
|
1234
|
+
setNoVirtual(true);
|
|
1235
|
+
await waitUntilAllRowsAreRendered();
|
|
1236
|
+
}
|
|
1223
1237
|
const idToIndex = entities.reduce((acc, e, i) => {
|
|
1224
1238
|
acc[e.id || e.code] = i;
|
|
1225
1239
|
return acc;
|
|
@@ -1234,10 +1248,10 @@ const DataTable = ({
|
|
|
1234
1248
|
if (!rowNumbersToCopy.length) return;
|
|
1235
1249
|
rowNumbersToCopy.unshift(0); //add in the header row
|
|
1236
1250
|
try {
|
|
1237
|
-
const allRowEls = getAllRows(
|
|
1251
|
+
const allRowEls = getAllRows(tableRef);
|
|
1238
1252
|
if (!allRowEls) return;
|
|
1239
1253
|
const rowEls = rowNumbersToCopy.map(i => allRowEls[i]);
|
|
1240
|
-
|
|
1254
|
+
if (window.Cypress) window.Cypress.__copiedRowsLength = rowEls.length;
|
|
1241
1255
|
handleCopyRows(rowEls, {
|
|
1242
1256
|
onFinishMsg: "Selected rows copied"
|
|
1243
1257
|
});
|
|
@@ -1245,8 +1259,9 @@ const DataTable = ({
|
|
|
1245
1259
|
console.error(`error:`, error);
|
|
1246
1260
|
window.toastr.error("Error copying rows.");
|
|
1247
1261
|
}
|
|
1262
|
+
setNoVirtual(false);
|
|
1248
1263
|
},
|
|
1249
|
-
[entities]
|
|
1264
|
+
[entities, waitUntilAllRowsAreRendered]
|
|
1250
1265
|
);
|
|
1251
1266
|
|
|
1252
1267
|
const handleCopyHotkey = useCallback(
|
|
@@ -2107,7 +2122,7 @@ const DataTable = ({
|
|
|
2107
2122
|
<MenuItem
|
|
2108
2123
|
key="copyColumn"
|
|
2109
2124
|
onClick={() => {
|
|
2110
|
-
handleCopyColumn(
|
|
2125
|
+
handleCopyColumn(tableRef, cellWrapper);
|
|
2111
2126
|
}}
|
|
2112
2127
|
text="Column"
|
|
2113
2128
|
/>
|
|
@@ -2117,7 +2132,7 @@ const DataTable = ({
|
|
|
2117
2132
|
<MenuItem
|
|
2118
2133
|
key="copyColumnSelected"
|
|
2119
2134
|
onClick={() => {
|
|
2120
|
-
handleCopyColumn(
|
|
2135
|
+
handleCopyColumn(tableRef, cellWrapper, selectedRecords);
|
|
2121
2136
|
}}
|
|
2122
2137
|
text="Column (Selected)"
|
|
2123
2138
|
/>
|
|
@@ -2157,7 +2172,7 @@ const DataTable = ({
|
|
|
2157
2172
|
<MenuItem
|
|
2158
2173
|
key="copyFullTableRows"
|
|
2159
2174
|
onClick={() => {
|
|
2160
|
-
handleCopyTable(
|
|
2175
|
+
handleCopyTable(tableRef);
|
|
2161
2176
|
// loop through each cell in the row
|
|
2162
2177
|
}}
|
|
2163
2178
|
text="Table"
|
|
@@ -2765,6 +2780,7 @@ const DataTable = ({
|
|
|
2765
2780
|
<ReactTable
|
|
2766
2781
|
data={filteredEnts}
|
|
2767
2782
|
ref={tableRef}
|
|
2783
|
+
noVirtual={noVirtual}
|
|
2768
2784
|
className={classNames({
|
|
2769
2785
|
isCellEditable,
|
|
2770
2786
|
"tg-table-loading": isLoading,
|
|
@@ -2846,7 +2862,8 @@ const DataTable = ({
|
|
|
2846
2862
|
resizePersist,
|
|
2847
2863
|
resized,
|
|
2848
2864
|
rowsToShow,
|
|
2849
|
-
style
|
|
2865
|
+
style,
|
|
2866
|
+
noVirtual
|
|
2850
2867
|
]
|
|
2851
2868
|
);
|
|
2852
2869
|
|
|
@@ -3089,7 +3106,7 @@ const DataTable = ({
|
|
|
3089
3106
|
try {
|
|
3090
3107
|
const allEntities = await safeQuery(fragment, {
|
|
3091
3108
|
variables: {
|
|
3092
|
-
|
|
3109
|
+
where: variables.where,
|
|
3093
3110
|
sort: variables.sort
|
|
3094
3111
|
},
|
|
3095
3112
|
canCancel: true
|
|
@@ -3163,8 +3180,8 @@ const DataTable = ({
|
|
|
3163
3180
|
)}
|
|
3164
3181
|
</div>
|
|
3165
3182
|
<Button
|
|
3166
|
-
onClick={
|
|
3167
|
-
handleCopyTable(
|
|
3183
|
+
onClick={() => {
|
|
3184
|
+
handleCopyTable(tableRef, { isDownload: true });
|
|
3168
3185
|
}}
|
|
3169
3186
|
data-tip="Download Table as CSV"
|
|
3170
3187
|
minimal
|
package/src/DataTable/style.css
CHANGED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { omitBy, isNil } from "lodash-es";
|
|
2
|
+
//we use this to make adding preset prop groups simpler
|
|
3
|
+
export default function computePresets(props = {}) {
|
|
4
|
+
const { isSimple } = props;
|
|
5
|
+
let toReturn = omitBy(props, isNil);
|
|
6
|
+
toReturn.pageSize = toReturn.controlled_pageSize || toReturn.pageSize;
|
|
7
|
+
if (isSimple) {
|
|
8
|
+
//isSimplePreset
|
|
9
|
+
toReturn = {
|
|
10
|
+
noHeader: true,
|
|
11
|
+
noFooter: !props.withPaging,
|
|
12
|
+
noPadding: true,
|
|
13
|
+
noFullscreenButton: true,
|
|
14
|
+
hidePageSizeWhenPossible: !props.withPaging,
|
|
15
|
+
isInfinite: !props.withPaging,
|
|
16
|
+
hideSelectedCount: true,
|
|
17
|
+
withTitle: false,
|
|
18
|
+
withSearch: false,
|
|
19
|
+
compact: true,
|
|
20
|
+
withPaging: false,
|
|
21
|
+
withFilter: false,
|
|
22
|
+
...toReturn
|
|
23
|
+
};
|
|
24
|
+
} else {
|
|
25
|
+
toReturn = {
|
|
26
|
+
// the usual defaults:
|
|
27
|
+
noFooter: false,
|
|
28
|
+
noPadding: false,
|
|
29
|
+
compact: true,
|
|
30
|
+
noFullscreenButton: false,
|
|
31
|
+
hidePageSizeWhenPossible: false,
|
|
32
|
+
isInfinite: false,
|
|
33
|
+
hideSelectedCount: false,
|
|
34
|
+
withTitle: true,
|
|
35
|
+
withSearch: true,
|
|
36
|
+
withPaging: true,
|
|
37
|
+
withFilter: true,
|
|
38
|
+
...toReturn
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return toReturn || {};
|
|
42
|
+
}
|