@teselagen/ui 0.5.23-beta.23 → 0.5.23-beta.25
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/FormComponents/AbstractField.d.ts +1 -0
- package/index.cjs.js +94 -64
- package/index.es.js +94 -64
- package/package.json +1 -1
- package/src/DataTable/Columns.js +520 -398
- package/src/DataTable/EditabelCell.js +4 -4
- package/src/DataTable/FilterAndSortMenu.js +4 -2
- package/src/DataTable/utils/useTableParams.js +1 -0
- package/src/DataTable/utils/withTableParams.js +2 -1
- package/src/FormComponents/AbstractField.js +388 -0
package/src/DataTable/Columns.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { isValidElement
|
|
1
|
+
import React, { isValidElement } from "react";
|
|
2
2
|
import classNames from "classnames";
|
|
3
3
|
import { Button, Classes, Checkbox, Icon } from "@blueprintjs/core";
|
|
4
4
|
import {
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
getIdOrCodeOrIndex,
|
|
25
25
|
getNumberStrAtEnd,
|
|
26
26
|
getSelectedRowsFromEntities,
|
|
27
|
+
isBottomRightCornerOfRectangle,
|
|
27
28
|
PRIMARY_SELECTED_VAL,
|
|
28
29
|
stripNumberAtEnd
|
|
29
30
|
} from "./utils";
|
|
@@ -32,11 +33,12 @@ import { ColumnFilterMenu } from "./ColumnFilterMenu";
|
|
|
32
33
|
import getTextFromEl from "../utils/getTextFromEl";
|
|
33
34
|
import rowClick, { finalizeSelection } from "./utils/rowClick";
|
|
34
35
|
import { editCellHelper } from "./editCellHelper";
|
|
36
|
+
import { DropdownCell } from "./DropdownCell";
|
|
37
|
+
import { EditableCell } from "./EditabelCell";
|
|
38
|
+
import { getVals } from "./getVals";
|
|
39
|
+
import { CellDragHandle } from "./CellDragHandle";
|
|
35
40
|
import { getCellVal } from "./getCellVal";
|
|
36
41
|
import { getCCDisplayName } from "./utils/queryParams";
|
|
37
|
-
import { useDispatch } from "react-redux";
|
|
38
|
-
import { change as _change } from "redux-form";
|
|
39
|
-
import { RenderCell } from "./RenderCell";
|
|
40
42
|
|
|
41
43
|
dayjs.extend(localizedFormat);
|
|
42
44
|
|
|
@@ -309,424 +311,479 @@ const renderCheckboxHeader = ({
|
|
|
309
311
|
) : null;
|
|
310
312
|
};
|
|
311
313
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
currentParams,
|
|
317
|
-
compact,
|
|
318
|
-
editingCell,
|
|
319
|
-
editingCellSelectAll,
|
|
320
|
-
entities,
|
|
321
|
-
expandedEntityIdMap,
|
|
322
|
-
extraCompact,
|
|
323
|
-
filters,
|
|
324
|
-
formName,
|
|
325
|
-
getCellHoverText,
|
|
314
|
+
const RenderCell = ({
|
|
315
|
+
oldFunc,
|
|
316
|
+
getCopyTextForCell,
|
|
317
|
+
column,
|
|
326
318
|
isCellEditable,
|
|
327
319
|
isEntityDisabled,
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
onDeselect,
|
|
336
|
-
onMultiRowSelect,
|
|
337
|
-
onRowClick,
|
|
338
|
-
onRowSelect,
|
|
339
|
-
onSingleRowSelect,
|
|
340
|
-
order,
|
|
341
|
-
primarySelectedCellId,
|
|
342
|
-
reduxFormCellValidation,
|
|
343
|
-
reduxFormSelectedEntityIdMap,
|
|
344
|
-
refocusTable,
|
|
345
|
-
removeSingleFilter = noop,
|
|
346
|
-
schema,
|
|
320
|
+
finishCellEdit,
|
|
321
|
+
noEllipsis,
|
|
322
|
+
editingCell,
|
|
323
|
+
cancelCellEdit,
|
|
324
|
+
editableCellValue,
|
|
325
|
+
setEditableCellValue,
|
|
326
|
+
getCellHoverText,
|
|
347
327
|
selectedCells,
|
|
348
|
-
|
|
349
|
-
setNewParams,
|
|
350
|
-
setOrder = noop,
|
|
351
|
-
setSelectedCells,
|
|
352
|
-
shouldShowSubComponent,
|
|
328
|
+
isSelectionARectangle,
|
|
353
329
|
startCellEdit,
|
|
354
|
-
SubComponent,
|
|
355
330
|
tableRef,
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
withCheckboxes,
|
|
359
|
-
withExpandAndCollapseAllButton,
|
|
360
|
-
withFilter: _withFilter,
|
|
361
|
-
withSort = true
|
|
331
|
+
onDragEnd,
|
|
332
|
+
args
|
|
362
333
|
}) => {
|
|
363
|
-
const
|
|
364
|
-
const
|
|
365
|
-
|
|
366
|
-
|
|
334
|
+
const [row] = args;
|
|
335
|
+
const rowId = getIdOrCodeOrIndex(row.original, row.index);
|
|
336
|
+
const cellId = `${rowId}:${row.column.path}`;
|
|
337
|
+
let val = oldFunc(...args);
|
|
338
|
+
const oldVal = val;
|
|
339
|
+
const text = getCopyTextForCell(val, row, column);
|
|
340
|
+
const isBool = column.type === "boolean";
|
|
341
|
+
const dataTest = {
|
|
342
|
+
"data-test": "tgCell_" + column.path
|
|
343
|
+
};
|
|
344
|
+
const fullValue = row.original?.[row.column.path];
|
|
345
|
+
if (isCellEditable && isBool) {
|
|
346
|
+
val = (
|
|
347
|
+
<Checkbox
|
|
348
|
+
disabled={isEntityDisabled(row.original)}
|
|
349
|
+
className="tg-cell-edit-boolean-checkbox"
|
|
350
|
+
checked={oldVal === "True"}
|
|
351
|
+
onChange={e => {
|
|
352
|
+
const checked = e.target.checked;
|
|
353
|
+
finishCellEdit(cellId, checked);
|
|
354
|
+
}}
|
|
355
|
+
/>
|
|
356
|
+
);
|
|
357
|
+
noEllipsis = true;
|
|
358
|
+
} else if (editingCell === cellId) {
|
|
359
|
+
if (column.type === "genericSelect") {
|
|
360
|
+
const GenericSelectComp = column.GenericSelectComp;
|
|
361
|
+
|
|
362
|
+
return (
|
|
363
|
+
<GenericSelectComp
|
|
364
|
+
rowId={rowId}
|
|
365
|
+
fullValue={fullValue}
|
|
366
|
+
initialValue={text}
|
|
367
|
+
{...dataTest}
|
|
368
|
+
finishEdit={(newVal, doNotStopEditing) => {
|
|
369
|
+
finishCellEdit(cellId, newVal, doNotStopEditing);
|
|
370
|
+
}}
|
|
371
|
+
dataTest={dataTest}
|
|
372
|
+
cancelEdit={cancelCellEdit}
|
|
373
|
+
/>
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
if (column.type === "dropdown" || column.type === "dropdownMulti") {
|
|
377
|
+
return (
|
|
378
|
+
<DropdownCell
|
|
379
|
+
isMulti={dataTest.isMulti || column.type === "dropdownMulti"}
|
|
380
|
+
initialValue={dataTest.initialValue || text}
|
|
381
|
+
options={getVals(column.values)}
|
|
382
|
+
finishEdit={(newVal, doNotStopEditing) => {
|
|
383
|
+
finishCellEdit(cellId, newVal, doNotStopEditing);
|
|
384
|
+
}}
|
|
385
|
+
dataTest={dataTest}
|
|
386
|
+
cancelEdit={cancelCellEdit}
|
|
387
|
+
/>
|
|
388
|
+
);
|
|
389
|
+
} else {
|
|
390
|
+
return (
|
|
391
|
+
<EditableCell
|
|
392
|
+
value={editableCellValue}
|
|
393
|
+
setValue={setEditableCellValue}
|
|
394
|
+
dataTest={dataTest}
|
|
395
|
+
cancelEdit={cancelCellEdit}
|
|
396
|
+
isNumeric={column.type === "number"}
|
|
397
|
+
initialValue={text}
|
|
398
|
+
finishEdit={newVal => {
|
|
399
|
+
finishCellEdit(cellId, newVal);
|
|
400
|
+
}}
|
|
401
|
+
/>
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
//wrap the original tableColumn.Cell function in another div in order to add a title attribute
|
|
407
|
+
let title = text;
|
|
408
|
+
if (getCellHoverText) title = getCellHoverText(...args);
|
|
409
|
+
else if (column.getTitleAttr) title = column.getTitleAttr(...args);
|
|
410
|
+
const isSelectedCell = selectedCells?.[cellId];
|
|
411
|
+
const {
|
|
412
|
+
isRect,
|
|
413
|
+
selectionGrid,
|
|
414
|
+
lastRowIndex,
|
|
415
|
+
lastCellIndex,
|
|
416
|
+
entityMap,
|
|
417
|
+
pathToIndex
|
|
418
|
+
} = isSelectionARectangle();
|
|
419
|
+
|
|
420
|
+
return (
|
|
421
|
+
<>
|
|
422
|
+
<div
|
|
423
|
+
style={{
|
|
424
|
+
...(!noEllipsis && {
|
|
425
|
+
textOverflow: "ellipsis",
|
|
426
|
+
overflow: "hidden"
|
|
427
|
+
})
|
|
428
|
+
}}
|
|
429
|
+
{...dataTest}
|
|
430
|
+
className="tg-cell-wrapper"
|
|
431
|
+
data-copy-text={text}
|
|
432
|
+
data-copy-json={JSON.stringify(
|
|
433
|
+
//tnw: eventually we'll parse these back out and use either the fullValue (for the generic selects) or the regular text vals for everything else
|
|
434
|
+
column.type === "genericSelect"
|
|
435
|
+
? {
|
|
436
|
+
__strVal: fullValue,
|
|
437
|
+
__genSelCol: column.path
|
|
438
|
+
}
|
|
439
|
+
: { __strVal: text }
|
|
440
|
+
)}
|
|
441
|
+
title={title || undefined}
|
|
442
|
+
>
|
|
443
|
+
{val}
|
|
444
|
+
</div>
|
|
445
|
+
{isCellEditable &&
|
|
446
|
+
(column.type === "dropdown" ||
|
|
447
|
+
column.type === "dropdownMulti" ||
|
|
448
|
+
column.type === "genericSelect") && (
|
|
449
|
+
<Icon
|
|
450
|
+
icon="caret-down"
|
|
451
|
+
style={{
|
|
452
|
+
position: "absolute",
|
|
453
|
+
right: 5,
|
|
454
|
+
opacity: 0.3
|
|
455
|
+
}}
|
|
456
|
+
className="cell-edit-dropdown"
|
|
457
|
+
onClick={() => {
|
|
458
|
+
startCellEdit(cellId);
|
|
459
|
+
}}
|
|
460
|
+
/>
|
|
461
|
+
)}
|
|
462
|
+
|
|
463
|
+
{isSelectedCell &&
|
|
464
|
+
(isRect
|
|
465
|
+
? isBottomRightCornerOfRectangle({
|
|
466
|
+
cellId,
|
|
467
|
+
selectionGrid,
|
|
468
|
+
lastRowIndex,
|
|
469
|
+
lastCellIndex,
|
|
470
|
+
entityMap,
|
|
471
|
+
pathToIndex
|
|
472
|
+
})
|
|
473
|
+
: isSelectedCell === PRIMARY_SELECTED_VAL) && (
|
|
474
|
+
<CellDragHandle
|
|
475
|
+
key={cellId}
|
|
476
|
+
thisTable={tableRef.current.tableRef}
|
|
477
|
+
cellId={cellId}
|
|
478
|
+
isSelectionARectangle={isSelectionARectangle}
|
|
479
|
+
onDragEnd={onDragEnd}
|
|
480
|
+
/>
|
|
481
|
+
)}
|
|
482
|
+
</>
|
|
367
483
|
);
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
export const RenderColumns = props => {
|
|
487
|
+
const {
|
|
488
|
+
addFilters,
|
|
489
|
+
cellRenderer,
|
|
490
|
+
change,
|
|
491
|
+
columns,
|
|
492
|
+
currentParams,
|
|
493
|
+
compact,
|
|
494
|
+
editableCellValue,
|
|
495
|
+
editingCell,
|
|
496
|
+
editingCellSelectAll,
|
|
497
|
+
entities,
|
|
498
|
+
expandedEntityIdMap,
|
|
499
|
+
extraCompact,
|
|
500
|
+
filters,
|
|
501
|
+
getCellHoverText,
|
|
502
|
+
isCellEditable,
|
|
503
|
+
isEntityDisabled,
|
|
504
|
+
isLocalCall,
|
|
505
|
+
isSimple,
|
|
506
|
+
isSingleSelect,
|
|
507
|
+
isSelectionARectangle,
|
|
508
|
+
noDeselectAll,
|
|
509
|
+
noSelect,
|
|
510
|
+
noUserSelect,
|
|
511
|
+
onDeselect,
|
|
512
|
+
onMultiRowSelect,
|
|
513
|
+
onRowClick,
|
|
514
|
+
onRowSelect,
|
|
515
|
+
onSingleRowSelect,
|
|
516
|
+
order,
|
|
517
|
+
primarySelectedCellId,
|
|
518
|
+
reduxFormCellValidation,
|
|
519
|
+
reduxFormSelectedEntityIdMap,
|
|
520
|
+
refocusTable,
|
|
521
|
+
removeSingleFilter = noop,
|
|
522
|
+
schema,
|
|
523
|
+
selectedCells,
|
|
524
|
+
setEditableCellValue,
|
|
525
|
+
setEditingCell,
|
|
526
|
+
setExpandedEntityIdMap,
|
|
527
|
+
setNewParams,
|
|
528
|
+
setOrder = noop,
|
|
529
|
+
setSelectedCells,
|
|
530
|
+
shouldShowSubComponent,
|
|
531
|
+
startCellEdit,
|
|
532
|
+
SubComponent,
|
|
533
|
+
tableRef,
|
|
534
|
+
updateEntitiesHelper,
|
|
535
|
+
updateValidation,
|
|
536
|
+
withCheckboxes,
|
|
537
|
+
withExpandAndCollapseAllButton,
|
|
538
|
+
withFilter: _withFilter,
|
|
539
|
+
withSort = true
|
|
540
|
+
} = props;
|
|
541
|
+
|
|
368
542
|
const withFilter = _withFilter === undefined ? !isSimple : _withFilter;
|
|
369
543
|
|
|
370
|
-
const onDragEnd =
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
544
|
+
const onDragEnd = cellsToSelect => {
|
|
545
|
+
const [primaryRowId, primaryCellPath] = primarySelectedCellId.split(":");
|
|
546
|
+
const pathToField = getFieldPathToField(schema);
|
|
547
|
+
const { selectedPaths, selectionGrid } = isSelectionARectangle();
|
|
548
|
+
let allSelectedPaths = selectedPaths;
|
|
549
|
+
if (!allSelectedPaths) {
|
|
550
|
+
allSelectedPaths = [primaryCellPath];
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
updateEntitiesHelper(entities, entities => {
|
|
554
|
+
let newSelectedCells;
|
|
555
|
+
if (selectedPaths) {
|
|
556
|
+
newSelectedCells = {
|
|
557
|
+
...selectedCells
|
|
558
|
+
};
|
|
559
|
+
} else {
|
|
560
|
+
newSelectedCells = {
|
|
561
|
+
[primarySelectedCellId]: PRIMARY_SELECTED_VAL
|
|
562
|
+
};
|
|
378
563
|
}
|
|
379
564
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
[primarySelectedCellId]: PRIMARY_SELECTED_VAL
|
|
389
|
-
};
|
|
390
|
-
}
|
|
565
|
+
const newCellValidate = {
|
|
566
|
+
...reduxFormCellValidation
|
|
567
|
+
};
|
|
568
|
+
const entityMap = getEntityIdToEntity(entities);
|
|
569
|
+
const { e: selectedEnt } = entityMap[primaryRowId];
|
|
570
|
+
const firstCellToSelectRowIndex =
|
|
571
|
+
entityMap[cellsToSelect[0]?.split(":")[0]]?.i;
|
|
572
|
+
const pathToIndex = getFieldPathToIndex(schema);
|
|
391
573
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
const
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
if (isIncremental) {
|
|
429
|
-
const cellTextNoNum = stripNumberAtEnd(selectedCellVal);
|
|
430
|
-
const sameText =
|
|
431
|
-
stripNumberAtEnd(cellAboveVal) === cellTextNoNum;
|
|
432
|
-
if (sameText) {
|
|
433
|
-
incrementStart = cellNum + 1;
|
|
434
|
-
incrementPrefix = cellTextNoNum || "";
|
|
435
|
-
if (cellNumStr && cellNumStr.startsWith("0")) {
|
|
436
|
-
incrementPad = cellNumStr.length;
|
|
437
|
-
}
|
|
574
|
+
allSelectedPaths.forEach(selectedPath => {
|
|
575
|
+
const column = pathToField[selectedPath];
|
|
576
|
+
|
|
577
|
+
const selectedCellVal = getCellVal(selectedEnt, selectedPath, column);
|
|
578
|
+
const cellIndexOfSelectedPath = pathToIndex[selectedPath];
|
|
579
|
+
let incrementStart;
|
|
580
|
+
let incrementPrefix;
|
|
581
|
+
let incrementPad = 0;
|
|
582
|
+
if (column.type === "string" || column.type === "number") {
|
|
583
|
+
const cellNumStr = getNumberStrAtEnd(selectedCellVal);
|
|
584
|
+
const cellNum = Number(cellNumStr);
|
|
585
|
+
const entityAbovePrimaryCell =
|
|
586
|
+
entities[entityMap[primaryRowId].i - 1];
|
|
587
|
+
if (cellNumStr !== null && !isNaN(cellNum)) {
|
|
588
|
+
if (
|
|
589
|
+
entityAbovePrimaryCell &&
|
|
590
|
+
(!selectionGrid || selectionGrid.length <= 1)
|
|
591
|
+
) {
|
|
592
|
+
const cellAboveVal = get(
|
|
593
|
+
entityAbovePrimaryCell,
|
|
594
|
+
selectedPath,
|
|
595
|
+
""
|
|
596
|
+
);
|
|
597
|
+
const cellAboveNumStr = getNumberStrAtEnd(cellAboveVal);
|
|
598
|
+
const cellAboveNum = Number(cellAboveNumStr);
|
|
599
|
+
if (!isNaN(cellAboveNum)) {
|
|
600
|
+
const isIncremental = cellNum - cellAboveNum === 1;
|
|
601
|
+
if (isIncremental) {
|
|
602
|
+
const cellTextNoNum = stripNumberAtEnd(selectedCellVal);
|
|
603
|
+
const sameText =
|
|
604
|
+
stripNumberAtEnd(cellAboveVal) === cellTextNoNum;
|
|
605
|
+
if (sameText) {
|
|
606
|
+
incrementStart = cellNum + 1;
|
|
607
|
+
incrementPrefix = cellTextNoNum || "";
|
|
608
|
+
if (cellNumStr && cellNumStr.startsWith("0")) {
|
|
609
|
+
incrementPad = cellNumStr.length;
|
|
438
610
|
}
|
|
439
611
|
}
|
|
440
612
|
}
|
|
441
613
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
return ++checkIncrement === cellNum;
|
|
479
|
-
}
|
|
614
|
+
}
|
|
615
|
+
if (incrementStart === undefined) {
|
|
616
|
+
const draggingDown =
|
|
617
|
+
firstCellToSelectRowIndex > selectionGrid?.[0][0].rowIndex;
|
|
618
|
+
if (selectedPaths && draggingDown) {
|
|
619
|
+
let checkIncrement;
|
|
620
|
+
let prefix;
|
|
621
|
+
let maybePad;
|
|
622
|
+
// determine if all the cells in this column of the selectionGrid are incrementing
|
|
623
|
+
const allAreIncrementing = selectionGrid.every(row => {
|
|
624
|
+
// see if cell is selected
|
|
625
|
+
const cellInfo = row[cellIndexOfSelectedPath];
|
|
626
|
+
if (!cellInfo) return false;
|
|
627
|
+
const { cellId } = cellInfo;
|
|
628
|
+
const [rowId] = cellId.split(":");
|
|
629
|
+
const cellVal = getCellVal(
|
|
630
|
+
entityMap[rowId].e,
|
|
631
|
+
selectedPath,
|
|
632
|
+
pathToField[selectedPath]
|
|
633
|
+
);
|
|
634
|
+
const cellNumStr = getNumberStrAtEnd(cellVal);
|
|
635
|
+
const cellNum = Number(cellNumStr);
|
|
636
|
+
const cellTextNoNum = stripNumberAtEnd(cellVal);
|
|
637
|
+
if (cellNumStr?.startsWith("0")) {
|
|
638
|
+
maybePad = cellNumStr.length;
|
|
639
|
+
}
|
|
640
|
+
if (cellTextNoNum && !prefix) {
|
|
641
|
+
prefix = cellTextNoNum;
|
|
642
|
+
}
|
|
643
|
+
if (cellTextNoNum && prefix !== cellTextNoNum) {
|
|
644
|
+
return false;
|
|
645
|
+
}
|
|
646
|
+
if (!isNaN(cellNum)) {
|
|
647
|
+
if (!checkIncrement) {
|
|
648
|
+
checkIncrement = cellNum;
|
|
649
|
+
return true;
|
|
480
650
|
} else {
|
|
481
|
-
return
|
|
651
|
+
return ++checkIncrement === cellNum;
|
|
482
652
|
}
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
if (allAreIncrementing) {
|
|
486
|
-
incrementStart = checkIncrement + 1;
|
|
487
|
-
incrementPrefix = prefix || "";
|
|
488
|
-
incrementPad = maybePad;
|
|
653
|
+
} else {
|
|
654
|
+
return false;
|
|
489
655
|
}
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
if (allAreIncrementing) {
|
|
659
|
+
incrementStart = checkIncrement + 1;
|
|
660
|
+
incrementPrefix = prefix || "";
|
|
661
|
+
incrementPad = maybePad;
|
|
490
662
|
}
|
|
491
663
|
}
|
|
492
664
|
}
|
|
493
665
|
}
|
|
666
|
+
}
|
|
494
667
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
cellsToSelect.forEach(cellId => {
|
|
507
|
-
const [rowId, cellPath] = cellId.split(":");
|
|
508
|
-
if (cellPath !== selectedPath) return;
|
|
509
|
-
newSelectedCells[cellId] = true;
|
|
510
|
-
const { e: entityToUpdate, i: rowIndex } = entityMap[rowId] || {};
|
|
511
|
-
if (entityToUpdate) {
|
|
512
|
-
delete entityToUpdate._isClean;
|
|
513
|
-
let newVal;
|
|
514
|
-
if (incrementStart !== undefined) {
|
|
515
|
-
const num = incrementStart++;
|
|
516
|
-
newVal = incrementPrefix + padStart(num, incrementPad, "0");
|
|
517
|
-
} else {
|
|
518
|
-
if (selectionGrid && selectionGrid.length > 1) {
|
|
519
|
-
// if there are multiple cells selected then we want to copy them repeating
|
|
520
|
-
// ex: if we have 1,2,3 selected and we drag for 5 more rows we want it to
|
|
521
|
-
// be 1,2,3,1,2 for the new row cells in this column
|
|
522
|
-
const draggingDown = rowIndex > firstSelectedCellRowIndex;
|
|
523
|
-
const cellIndex = pathToIndex[cellPath];
|
|
524
|
-
let cellIdToCopy;
|
|
525
|
-
if (draggingDown) {
|
|
526
|
-
const { cellId } = selectionGrid[
|
|
527
|
-
(rowIndex - firstSelectedCellRowIndex) %
|
|
528
|
-
selectionGrid.length
|
|
529
|
-
].find(g => g && g.cellIndex === cellIndex);
|
|
530
|
-
cellIdToCopy = cellId;
|
|
531
|
-
} else {
|
|
532
|
-
const lastIndexInGrid =
|
|
533
|
-
selectionGrid[selectionGrid.length - 1][0].rowIndex;
|
|
534
|
-
const { cellId } = selectionGrid[
|
|
535
|
-
(rowIndex + lastIndexInGrid + 1) % selectionGrid.length
|
|
536
|
-
].find(g => g.cellIndex === cellIndex);
|
|
537
|
-
cellIdToCopy = cellId;
|
|
538
|
-
}
|
|
668
|
+
let firstSelectedCellRowIndex;
|
|
669
|
+
if (selectionGrid) {
|
|
670
|
+
selectionGrid[0].some(cell => {
|
|
671
|
+
if (cell) {
|
|
672
|
+
firstSelectedCellRowIndex = cell.rowIndex;
|
|
673
|
+
return true;
|
|
674
|
+
}
|
|
675
|
+
return false;
|
|
676
|
+
});
|
|
677
|
+
}
|
|
539
678
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
679
|
+
cellsToSelect.forEach(cellId => {
|
|
680
|
+
const [rowId, cellPath] = cellId.split(":");
|
|
681
|
+
if (cellPath !== selectedPath) return;
|
|
682
|
+
newSelectedCells[cellId] = true;
|
|
683
|
+
const { e: entityToUpdate, i: rowIndex } = entityMap[rowId] || {};
|
|
684
|
+
if (entityToUpdate) {
|
|
685
|
+
delete entityToUpdate._isClean;
|
|
686
|
+
let newVal;
|
|
687
|
+
if (incrementStart !== undefined) {
|
|
688
|
+
const num = incrementStart++;
|
|
689
|
+
newVal = incrementPrefix + padStart(num, incrementPad, "0");
|
|
690
|
+
} else {
|
|
691
|
+
if (selectionGrid && selectionGrid.length > 1) {
|
|
692
|
+
// if there are multiple cells selected then we want to copy them repeating
|
|
693
|
+
// ex: if we have 1,2,3 selected and we drag for 5 more rows we want it to
|
|
694
|
+
// be 1,2,3,1,2 for the new row cells in this column
|
|
695
|
+
const draggingDown = rowIndex > firstSelectedCellRowIndex;
|
|
696
|
+
const cellIndex = pathToIndex[cellPath];
|
|
697
|
+
let cellIdToCopy;
|
|
698
|
+
if (draggingDown) {
|
|
699
|
+
const { cellId } = selectionGrid[
|
|
700
|
+
(rowIndex - firstSelectedCellRowIndex) %
|
|
701
|
+
selectionGrid.length
|
|
702
|
+
].find(g => g && g.cellIndex === cellIndex);
|
|
703
|
+
cellIdToCopy = cellId;
|
|
546
704
|
} else {
|
|
547
|
-
|
|
705
|
+
const lastIndexInGrid =
|
|
706
|
+
selectionGrid[selectionGrid.length - 1][0].rowIndex;
|
|
707
|
+
const { cellId } = selectionGrid[
|
|
708
|
+
(rowIndex + lastIndexInGrid + 1) % selectionGrid.length
|
|
709
|
+
].find(g => g.cellIndex === cellIndex);
|
|
710
|
+
cellIdToCopy = cellId;
|
|
548
711
|
}
|
|
712
|
+
|
|
713
|
+
const [rowIdToCopy, cellPathToCopy] = cellIdToCopy.split(":");
|
|
714
|
+
newVal = getCellVal(
|
|
715
|
+
entityMap[rowIdToCopy].e,
|
|
716
|
+
cellPathToCopy,
|
|
717
|
+
pathToField[cellPathToCopy]
|
|
718
|
+
);
|
|
719
|
+
} else {
|
|
720
|
+
newVal = selectedCellVal;
|
|
549
721
|
}
|
|
550
|
-
const { error } = editCellHelper({
|
|
551
|
-
entity: entityToUpdate,
|
|
552
|
-
path: cellPath,
|
|
553
|
-
schema,
|
|
554
|
-
newVal
|
|
555
|
-
});
|
|
556
|
-
newCellValidate[cellId] = error;
|
|
557
722
|
}
|
|
558
|
-
|
|
723
|
+
const { error } = editCellHelper({
|
|
724
|
+
entity: entityToUpdate,
|
|
725
|
+
path: cellPath,
|
|
726
|
+
schema,
|
|
727
|
+
newVal
|
|
728
|
+
});
|
|
729
|
+
newCellValidate[cellId] = error;
|
|
730
|
+
}
|
|
559
731
|
});
|
|
560
|
-
|
|
561
|
-
// select the new cells
|
|
562
|
-
updateValidation(entities, newCellValidate);
|
|
563
|
-
setSelectedCells(newSelectedCells);
|
|
564
732
|
});
|
|
565
|
-
},
|
|
566
|
-
[
|
|
567
|
-
entities,
|
|
568
|
-
isSelectionARectangle,
|
|
569
|
-
primarySelectedCellId,
|
|
570
|
-
reduxFormCellValidation,
|
|
571
|
-
schema,
|
|
572
|
-
selectedCells,
|
|
573
|
-
setSelectedCells,
|
|
574
|
-
updateEntitiesHelper,
|
|
575
|
-
updateValidation
|
|
576
|
-
]
|
|
577
|
-
);
|
|
578
733
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
// We should try to take out the props from here, it produces
|
|
585
|
-
// unnecessary rerenders
|
|
586
|
-
const record = row.original;
|
|
587
|
-
if (column.getClipboardData) {
|
|
588
|
-
text = column.getClipboardData(row.value, record, row);
|
|
589
|
-
} else if (column.getValueToFilterOn) {
|
|
590
|
-
text = column.getValueToFilterOn(record);
|
|
591
|
-
} else if (column.render) {
|
|
592
|
-
text = column.render(row.value, record, row, {
|
|
593
|
-
currentParams,
|
|
594
|
-
setNewParams
|
|
595
|
-
});
|
|
596
|
-
} else if (cellRenderer && cellRenderer[column.path]) {
|
|
597
|
-
text = cellRenderer[column.path](row.value, row.original, row, {
|
|
598
|
-
currentParams,
|
|
599
|
-
setNewParams
|
|
600
|
-
});
|
|
601
|
-
} else if (text) {
|
|
602
|
-
text = isValidElement(text) ? text : String(text);
|
|
603
|
-
}
|
|
604
|
-
const getTextFromElementOrLink = text => {
|
|
605
|
-
if (isValidElement(text)) {
|
|
606
|
-
if (text.props?.to) {
|
|
607
|
-
// this will convert Link elements to url strings
|
|
608
|
-
return joinUrl(
|
|
609
|
-
window.location.origin,
|
|
610
|
-
window.frontEndConfig?.clientBasePath || "",
|
|
611
|
-
text.props.to
|
|
612
|
-
);
|
|
613
|
-
} else {
|
|
614
|
-
return getTextFromEl(text);
|
|
615
|
-
}
|
|
616
|
-
} else {
|
|
617
|
-
return text;
|
|
618
|
-
}
|
|
619
|
-
};
|
|
620
|
-
text = getTextFromElementOrLink(text);
|
|
621
|
-
|
|
622
|
-
if (Array.isArray(text)) {
|
|
623
|
-
let arrText = text.map(getTextFromElementOrLink).join(", ");
|
|
624
|
-
// because we sometimes insert commas after links when mapping over an array of elements we will have double ,'s
|
|
625
|
-
arrText = arrText.replace(/, ,/g, ",");
|
|
626
|
-
text = arrText;
|
|
627
|
-
}
|
|
734
|
+
// select the new cells
|
|
735
|
+
updateValidation(entities, newCellValidate);
|
|
736
|
+
setSelectedCells(newSelectedCells);
|
|
737
|
+
});
|
|
738
|
+
};
|
|
628
739
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
},
|
|
633
|
-
[cellRenderer, currentParams, setNewParams]
|
|
634
|
-
);
|
|
740
|
+
const getCopyTextForCell = (val, row = {}, column = {}) => {
|
|
741
|
+
// TODOCOPY we need a way to potentially omit certain columns from being added as a \t element (talk to taoh about this)
|
|
742
|
+
let text = typeof val !== "string" ? row.value : val;
|
|
635
743
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
);
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
744
|
+
// We should try to take out the props from here, it produces
|
|
745
|
+
// unnecessary rerenders
|
|
746
|
+
const record = row.original;
|
|
747
|
+
if (column.getClipboardData) {
|
|
748
|
+
text = column.getClipboardData(row.value, record, row, props);
|
|
749
|
+
} else if (column.getValueToFilterOn) {
|
|
750
|
+
text = column.getValueToFilterOn(record, props);
|
|
751
|
+
} else if (column.render) {
|
|
752
|
+
text = column.render(row.value, record, row, props);
|
|
753
|
+
} else if (cellRenderer && cellRenderer[column.path]) {
|
|
754
|
+
text = cellRenderer[column.path](row.value, row.original, row, props);
|
|
755
|
+
} else if (text) {
|
|
756
|
+
text = isValidElement(text) ? text : String(text);
|
|
757
|
+
}
|
|
758
|
+
const getTextFromElementOrLink = text => {
|
|
759
|
+
if (isValidElement(text)) {
|
|
760
|
+
if (text.props?.to) {
|
|
761
|
+
// this will convert Link elements to url strings
|
|
762
|
+
return joinUrl(
|
|
763
|
+
window.location.origin,
|
|
764
|
+
window.frontEndConfig?.clientBasePath || "",
|
|
765
|
+
text.props.to
|
|
766
|
+
);
|
|
767
|
+
} else {
|
|
768
|
+
return getTextFromEl(text);
|
|
769
|
+
}
|
|
770
|
+
} else {
|
|
771
|
+
return text;
|
|
649
772
|
}
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
<Checkbox
|
|
653
|
-
name={`${getIdOrCodeOrIndex(entity, rowIndex)}-checkbox`}
|
|
654
|
-
disabled={noSelect || noUserSelect || isEntityDisabled(entity)}
|
|
655
|
-
onClick={e => {
|
|
656
|
-
rowClick(e, row, entities, {
|
|
657
|
-
reduxFormSelectedEntityIdMap,
|
|
658
|
-
isSingleSelect,
|
|
659
|
-
noSelect,
|
|
660
|
-
onRowClick,
|
|
661
|
-
isEntityDisabled,
|
|
662
|
-
withCheckboxes,
|
|
663
|
-
onDeselect,
|
|
664
|
-
onSingleRowSelect,
|
|
665
|
-
onMultiRowSelect,
|
|
666
|
-
noDeselectAll,
|
|
667
|
-
onRowSelect,
|
|
668
|
-
change
|
|
669
|
-
});
|
|
670
|
-
}}
|
|
671
|
-
checked={isSelected}
|
|
672
|
-
/>
|
|
673
|
-
);
|
|
674
|
-
},
|
|
675
|
-
[
|
|
676
|
-
change,
|
|
677
|
-
entities,
|
|
678
|
-
isEntityDisabled,
|
|
679
|
-
isSingleSelect,
|
|
680
|
-
noDeselectAll,
|
|
681
|
-
noSelect,
|
|
682
|
-
noUserSelect,
|
|
683
|
-
onDeselect,
|
|
684
|
-
onMultiRowSelect,
|
|
685
|
-
onRowClick,
|
|
686
|
-
onRowSelect,
|
|
687
|
-
onSingleRowSelect,
|
|
688
|
-
reduxFormSelectedEntityIdMap,
|
|
689
|
-
withCheckboxes
|
|
690
|
-
]
|
|
691
|
-
);
|
|
773
|
+
};
|
|
774
|
+
text = getTextFromElementOrLink(text);
|
|
692
775
|
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
return getIdOrCodeOrIndex(e, i) === rowId;
|
|
700
|
-
});
|
|
701
|
-
delete entity._isClean;
|
|
702
|
-
const { error } = editCellHelper({
|
|
703
|
-
entity,
|
|
704
|
-
path,
|
|
705
|
-
schema,
|
|
706
|
-
newVal
|
|
707
|
-
});
|
|
708
|
-
updateValidation(entities, {
|
|
709
|
-
...reduxFormCellValidation,
|
|
710
|
-
[cellId]: error
|
|
711
|
-
});
|
|
712
|
-
});
|
|
713
|
-
!doNotStopEditing && refocusTable();
|
|
714
|
-
},
|
|
715
|
-
[
|
|
716
|
-
change,
|
|
717
|
-
entities,
|
|
718
|
-
reduxFormCellValidation,
|
|
719
|
-
refocusTable,
|
|
720
|
-
schema,
|
|
721
|
-
updateEntitiesHelper,
|
|
722
|
-
updateValidation
|
|
723
|
-
]
|
|
724
|
-
);
|
|
776
|
+
if (Array.isArray(text)) {
|
|
777
|
+
let arrText = text.map(getTextFromElementOrLink).join(", ");
|
|
778
|
+
// because we sometimes insert commas after links when mapping over an array of elements we will have double ,'s
|
|
779
|
+
arrText = arrText.replace(/, ,/g, ",");
|
|
780
|
+
text = arrText;
|
|
781
|
+
}
|
|
725
782
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
}
|
|
783
|
+
const stringText = toString(text);
|
|
784
|
+
if (stringText === "[object Object]") return "";
|
|
785
|
+
return stringText;
|
|
786
|
+
};
|
|
730
787
|
|
|
731
788
|
if (!columns.length) {
|
|
732
789
|
return columns;
|
|
@@ -791,6 +848,72 @@ export const useColumns = ({
|
|
|
791
848
|
});
|
|
792
849
|
}
|
|
793
850
|
|
|
851
|
+
const renderCheckboxCell = row => {
|
|
852
|
+
const rowIndex = row.index;
|
|
853
|
+
const checkedRows = getSelectedRowsFromEntities(
|
|
854
|
+
entities,
|
|
855
|
+
reduxFormSelectedEntityIdMap
|
|
856
|
+
);
|
|
857
|
+
|
|
858
|
+
const isSelected = checkedRows.some(rowNum => {
|
|
859
|
+
return rowNum === rowIndex;
|
|
860
|
+
});
|
|
861
|
+
if (rowIndex >= entities.length) {
|
|
862
|
+
return <div />;
|
|
863
|
+
}
|
|
864
|
+
const entity = entities[rowIndex];
|
|
865
|
+
return (
|
|
866
|
+
<Checkbox
|
|
867
|
+
name={`${getIdOrCodeOrIndex(entity, rowIndex)}-checkbox`}
|
|
868
|
+
disabled={noSelect || noUserSelect || isEntityDisabled(entity)}
|
|
869
|
+
onClick={e => {
|
|
870
|
+
rowClick(e, row, entities, {
|
|
871
|
+
reduxFormSelectedEntityIdMap,
|
|
872
|
+
isSingleSelect,
|
|
873
|
+
noSelect,
|
|
874
|
+
onRowClick,
|
|
875
|
+
isEntityDisabled,
|
|
876
|
+
withCheckboxes,
|
|
877
|
+
onDeselect,
|
|
878
|
+
onSingleRowSelect,
|
|
879
|
+
onMultiRowSelect,
|
|
880
|
+
noDeselectAll,
|
|
881
|
+
onRowSelect,
|
|
882
|
+
change
|
|
883
|
+
});
|
|
884
|
+
}}
|
|
885
|
+
checked={isSelected}
|
|
886
|
+
/>
|
|
887
|
+
);
|
|
888
|
+
};
|
|
889
|
+
|
|
890
|
+
const finishCellEdit = (cellId, newVal, doNotStopEditing) => {
|
|
891
|
+
const [rowId, path] = cellId.split(":");
|
|
892
|
+
!doNotStopEditing && setEditingCell(null);
|
|
893
|
+
updateEntitiesHelper(entities, entities => {
|
|
894
|
+
const entity = entities.find((e, i) => {
|
|
895
|
+
return getIdOrCodeOrIndex(e, i) === rowId;
|
|
896
|
+
});
|
|
897
|
+
delete entity._isClean;
|
|
898
|
+
const { error } = editCellHelper({
|
|
899
|
+
entity,
|
|
900
|
+
path,
|
|
901
|
+
schema,
|
|
902
|
+
newVal
|
|
903
|
+
});
|
|
904
|
+
updateValidation(entities, {
|
|
905
|
+
...reduxFormCellValidation,
|
|
906
|
+
[cellId]: error
|
|
907
|
+
});
|
|
908
|
+
});
|
|
909
|
+
!doNotStopEditing && refocusTable();
|
|
910
|
+
};
|
|
911
|
+
|
|
912
|
+
const cancelCellEdit = () => {
|
|
913
|
+
setEditingCell(null);
|
|
914
|
+
refocusTable();
|
|
915
|
+
};
|
|
916
|
+
|
|
794
917
|
if (withCheckboxes) {
|
|
795
918
|
columnsToRender.push({
|
|
796
919
|
Header: renderCheckboxHeader({
|
|
@@ -824,7 +947,7 @@ export const useColumns = ({
|
|
|
824
947
|
});
|
|
825
948
|
}
|
|
826
949
|
|
|
827
|
-
|
|
950
|
+
columns.forEach(column => {
|
|
828
951
|
const tableColumn = {
|
|
829
952
|
...column,
|
|
830
953
|
Header: RenderColumnHeader({
|
|
@@ -859,18 +982,17 @@ export const useColumns = ({
|
|
|
859
982
|
}
|
|
860
983
|
if (cellRenderer && cellRenderer[column.path]) {
|
|
861
984
|
tableColumn.Cell = row => {
|
|
862
|
-
const val = cellRenderer[column.path](
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
985
|
+
const val = cellRenderer[column.path](
|
|
986
|
+
row.value,
|
|
987
|
+
row.original,
|
|
988
|
+
row,
|
|
989
|
+
props
|
|
990
|
+
);
|
|
866
991
|
return val;
|
|
867
992
|
};
|
|
868
993
|
} else if (column.render) {
|
|
869
994
|
tableColumn.Cell = row => {
|
|
870
|
-
const val = column.render(row.value, row.original, row,
|
|
871
|
-
currentParams,
|
|
872
|
-
setNewParams
|
|
873
|
-
});
|
|
995
|
+
const val = column.render(row.value, row.original, row, props);
|
|
874
996
|
return val;
|
|
875
997
|
};
|
|
876
998
|
} else if (column.type === "timestamp") {
|
|
@@ -918,7 +1040,6 @@ export const useColumns = ({
|
|
|
918
1040
|
tableColumn.Cell = (...args) => (
|
|
919
1041
|
<RenderCell
|
|
920
1042
|
oldFunc={oldFunc}
|
|
921
|
-
formName={formName}
|
|
922
1043
|
getCopyTextForCell={getCopyTextForCell}
|
|
923
1044
|
column={column}
|
|
924
1045
|
isCellEditable={isCellEditable}
|
|
@@ -927,6 +1048,8 @@ export const useColumns = ({
|
|
|
927
1048
|
noEllipsis={noEllipsis}
|
|
928
1049
|
editingCell={editingCell}
|
|
929
1050
|
cancelCellEdit={cancelCellEdit}
|
|
1051
|
+
editableCellValue={editableCellValue}
|
|
1052
|
+
setEditableCellValue={setEditableCellValue}
|
|
930
1053
|
editingCellSelectAll={editingCellSelectAll}
|
|
931
1054
|
getCellHoverText={getCellHoverText}
|
|
932
1055
|
selectedCells={selectedCells}
|
|
@@ -937,8 +1060,7 @@ export const useColumns = ({
|
|
|
937
1060
|
args={args}
|
|
938
1061
|
/>
|
|
939
1062
|
);
|
|
940
|
-
|
|
1063
|
+
columnsToRender.push(tableColumn);
|
|
941
1064
|
});
|
|
942
|
-
|
|
943
|
-
return columnsToRender.concat(tableColumns);
|
|
1065
|
+
return columnsToRender;
|
|
944
1066
|
};
|