@teselagen/ui 0.5.23-beta.26 → 0.5.23-beta.28
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/EditableCell.d.ts +7 -0
- package/index.cjs.js +2 -2
- package/index.es.js +2 -2
- package/package.json +1 -1
- package/src/DataTable/Columns.js +399 -520
- package/src/DataTable/EditableCell.js +44 -0
- package/src/DataTable/RenderCell.js +191 -0
- package/src/TgSelect/index.js +2 -2
package/index.cjs.js
CHANGED
|
@@ -31027,11 +31027,11 @@ const _TgSelect = class _TgSelect extends React$1.Component {
|
|
|
31027
31027
|
return true;
|
|
31028
31028
|
});
|
|
31029
31029
|
}
|
|
31030
|
-
return onChange([...valArray, item]);
|
|
31030
|
+
return onChange([...valArray, item], e2);
|
|
31031
31031
|
} else {
|
|
31032
31032
|
this.setOpenState(false);
|
|
31033
31033
|
this.input && this.input.blur();
|
|
31034
|
-
return onChange(item);
|
|
31034
|
+
return onChange(item, e2);
|
|
31035
31035
|
}
|
|
31036
31036
|
}, "handleItemSelect"));
|
|
31037
31037
|
__publicField(this, "handleTagRemove", /* @__PURE__ */ __name((e2, tagProps) => {
|
package/index.es.js
CHANGED
|
@@ -31009,11 +31009,11 @@ const _TgSelect = class _TgSelect extends React__default.Component {
|
|
|
31009
31009
|
return true;
|
|
31010
31010
|
});
|
|
31011
31011
|
}
|
|
31012
|
-
return onChange([...valArray, item]);
|
|
31012
|
+
return onChange([...valArray, item], e2);
|
|
31013
31013
|
} else {
|
|
31014
31014
|
this.setOpenState(false);
|
|
31015
31015
|
this.input && this.input.blur();
|
|
31016
|
-
return onChange(item);
|
|
31016
|
+
return onChange(item, e2);
|
|
31017
31017
|
}
|
|
31018
31018
|
}, "handleItemSelect"));
|
|
31019
31019
|
__publicField(this, "handleTagRemove", /* @__PURE__ */ __name((e2, tagProps) => {
|
package/package.json
CHANGED
package/src/DataTable/Columns.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { isValidElement } from "react";
|
|
1
|
+
import React, { isValidElement, useCallback } from "react";
|
|
2
2
|
import classNames from "classnames";
|
|
3
3
|
import { Button, Classes, Checkbox, Icon } from "@blueprintjs/core";
|
|
4
4
|
import {
|
|
@@ -24,7 +24,6 @@ import {
|
|
|
24
24
|
getIdOrCodeOrIndex,
|
|
25
25
|
getNumberStrAtEnd,
|
|
26
26
|
getSelectedRowsFromEntities,
|
|
27
|
-
isBottomRightCornerOfRectangle,
|
|
28
27
|
PRIMARY_SELECTED_VAL,
|
|
29
28
|
stripNumberAtEnd
|
|
30
29
|
} from "./utils";
|
|
@@ -33,12 +32,11 @@ import { ColumnFilterMenu } from "./ColumnFilterMenu";
|
|
|
33
32
|
import getTextFromEl from "../utils/getTextFromEl";
|
|
34
33
|
import rowClick, { finalizeSelection } from "./utils/rowClick";
|
|
35
34
|
import { editCellHelper } from "./editCellHelper";
|
|
36
|
-
import { DropdownCell } from "./DropdownCell";
|
|
37
|
-
import { EditableCell } from "./EditabelCell";
|
|
38
|
-
import { getVals } from "./getVals";
|
|
39
|
-
import { CellDragHandle } from "./CellDragHandle";
|
|
40
35
|
import { getCellVal } from "./getCellVal";
|
|
41
36
|
import { getCCDisplayName } from "./utils/queryParams";
|
|
37
|
+
import { useDispatch } from "react-redux";
|
|
38
|
+
import { change as _change } from "redux-form";
|
|
39
|
+
import { RenderCell } from "./RenderCell";
|
|
42
40
|
|
|
43
41
|
dayjs.extend(localizedFormat);
|
|
44
42
|
|
|
@@ -311,479 +309,425 @@ const renderCheckboxHeader = ({
|
|
|
311
309
|
) : null;
|
|
312
310
|
};
|
|
313
311
|
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
finishCellEdit,
|
|
321
|
-
noEllipsis,
|
|
312
|
+
export const useColumns = ({
|
|
313
|
+
addFilters,
|
|
314
|
+
cellRenderer,
|
|
315
|
+
columns,
|
|
316
|
+
currentParams,
|
|
317
|
+
compact,
|
|
322
318
|
editingCell,
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
319
|
+
editingCellSelectAll,
|
|
320
|
+
entities,
|
|
321
|
+
expandedEntityIdMap,
|
|
322
|
+
extraCompact,
|
|
323
|
+
filters,
|
|
324
|
+
formName,
|
|
326
325
|
getCellHoverText,
|
|
327
|
-
|
|
326
|
+
isCellEditable,
|
|
327
|
+
isEntityDisabled,
|
|
328
|
+
isLocalCall,
|
|
329
|
+
isSimple,
|
|
330
|
+
isSingleSelect,
|
|
328
331
|
isSelectionARectangle,
|
|
332
|
+
noDeselectAll,
|
|
333
|
+
noSelect,
|
|
334
|
+
noUserSelect,
|
|
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,
|
|
347
|
+
selectedCells,
|
|
348
|
+
setExpandedEntityIdMap,
|
|
349
|
+
setNewParams,
|
|
350
|
+
setOrder = noop,
|
|
351
|
+
setSelectedCells,
|
|
352
|
+
shouldShowSubComponent,
|
|
329
353
|
startCellEdit,
|
|
354
|
+
SubComponent,
|
|
330
355
|
tableRef,
|
|
331
|
-
|
|
332
|
-
|
|
356
|
+
updateEntitiesHelper,
|
|
357
|
+
updateValidation,
|
|
358
|
+
withCheckboxes,
|
|
359
|
+
withExpandAndCollapseAllButton,
|
|
360
|
+
withFilter: _withFilter,
|
|
361
|
+
withSort = true
|
|
333
362
|
}) => {
|
|
334
|
-
const
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
|
|
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
|
-
</>
|
|
363
|
+
const dispatch = useDispatch();
|
|
364
|
+
const change = useCallback(
|
|
365
|
+
(...args) => dispatch(_change(formName, ...args)),
|
|
366
|
+
[dispatch, formName]
|
|
483
367
|
);
|
|
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
|
-
|
|
542
368
|
const withFilter = _withFilter === undefined ? !isSimple : _withFilter;
|
|
543
369
|
|
|
544
|
-
const onDragEnd =
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
allSelectedPaths
|
|
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
|
-
};
|
|
370
|
+
const onDragEnd = useCallback(
|
|
371
|
+
cellsToSelect => {
|
|
372
|
+
const [primaryRowId, primaryCellPath] = primarySelectedCellId.split(":");
|
|
373
|
+
const pathToField = getFieldPathToField(schema);
|
|
374
|
+
const { selectedPaths, selectionGrid } = isSelectionARectangle();
|
|
375
|
+
let allSelectedPaths = selectedPaths;
|
|
376
|
+
if (!allSelectedPaths) {
|
|
377
|
+
allSelectedPaths = [primaryCellPath];
|
|
563
378
|
}
|
|
564
379
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
380
|
+
updateEntitiesHelper(entities, entities => {
|
|
381
|
+
let newSelectedCells;
|
|
382
|
+
if (selectedPaths) {
|
|
383
|
+
newSelectedCells = {
|
|
384
|
+
...selectedCells
|
|
385
|
+
};
|
|
386
|
+
} else {
|
|
387
|
+
newSelectedCells = {
|
|
388
|
+
[primarySelectedCellId]: PRIMARY_SELECTED_VAL
|
|
389
|
+
};
|
|
390
|
+
}
|
|
576
391
|
|
|
577
|
-
const
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
392
|
+
const newCellValidate = {
|
|
393
|
+
...reduxFormCellValidation
|
|
394
|
+
};
|
|
395
|
+
const entityMap = getEntityIdToEntity(entities);
|
|
396
|
+
const { e: selectedEnt } = entityMap[primaryRowId];
|
|
397
|
+
const firstCellToSelectRowIndex =
|
|
398
|
+
entityMap[cellsToSelect[0]?.split(":")[0]]?.i;
|
|
399
|
+
const pathToIndex = getFieldPathToIndex(schema);
|
|
400
|
+
|
|
401
|
+
allSelectedPaths.forEach(selectedPath => {
|
|
402
|
+
const column = pathToField[selectedPath];
|
|
403
|
+
|
|
404
|
+
const selectedCellVal = getCellVal(selectedEnt, selectedPath, column);
|
|
405
|
+
const cellIndexOfSelectedPath = pathToIndex[selectedPath];
|
|
406
|
+
let incrementStart;
|
|
407
|
+
let incrementPrefix;
|
|
408
|
+
let incrementPad = 0;
|
|
409
|
+
if (column.type === "string" || column.type === "number") {
|
|
410
|
+
const cellNumStr = getNumberStrAtEnd(selectedCellVal);
|
|
411
|
+
const cellNum = Number(cellNumStr);
|
|
412
|
+
const entityAbovePrimaryCell =
|
|
413
|
+
entities[entityMap[primaryRowId].i - 1];
|
|
414
|
+
if (cellNumStr !== null && !isNaN(cellNum)) {
|
|
415
|
+
if (
|
|
416
|
+
entityAbovePrimaryCell &&
|
|
417
|
+
(!selectionGrid || selectionGrid.length <= 1)
|
|
418
|
+
) {
|
|
419
|
+
const cellAboveVal = get(
|
|
420
|
+
entityAbovePrimaryCell,
|
|
421
|
+
selectedPath,
|
|
422
|
+
""
|
|
423
|
+
);
|
|
424
|
+
const cellAboveNumStr = getNumberStrAtEnd(cellAboveVal);
|
|
425
|
+
const cellAboveNum = Number(cellAboveNumStr);
|
|
426
|
+
if (!isNaN(cellAboveNum)) {
|
|
427
|
+
const isIncremental = cellNum - cellAboveNum === 1;
|
|
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
|
+
}
|
|
610
438
|
}
|
|
611
439
|
}
|
|
612
440
|
}
|
|
613
441
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
442
|
+
if (incrementStart === undefined) {
|
|
443
|
+
const draggingDown =
|
|
444
|
+
firstCellToSelectRowIndex > selectionGrid?.[0][0].rowIndex;
|
|
445
|
+
if (selectedPaths && draggingDown) {
|
|
446
|
+
let checkIncrement;
|
|
447
|
+
let prefix;
|
|
448
|
+
let maybePad;
|
|
449
|
+
// determine if all the cells in this column of the selectionGrid are incrementing
|
|
450
|
+
const allAreIncrementing = selectionGrid.every(row => {
|
|
451
|
+
// see if cell is selected
|
|
452
|
+
const cellInfo = row[cellIndexOfSelectedPath];
|
|
453
|
+
if (!cellInfo) return false;
|
|
454
|
+
const { cellId } = cellInfo;
|
|
455
|
+
const [rowId] = cellId.split(":");
|
|
456
|
+
const cellVal = getCellVal(
|
|
457
|
+
entityMap[rowId].e,
|
|
458
|
+
selectedPath,
|
|
459
|
+
pathToField[selectedPath]
|
|
460
|
+
);
|
|
461
|
+
const cellNumStr = getNumberStrAtEnd(cellVal);
|
|
462
|
+
const cellNum = Number(cellNumStr);
|
|
463
|
+
const cellTextNoNum = stripNumberAtEnd(cellVal);
|
|
464
|
+
if (cellNumStr?.startsWith("0")) {
|
|
465
|
+
maybePad = cellNumStr.length;
|
|
466
|
+
}
|
|
467
|
+
if (cellTextNoNum && !prefix) {
|
|
468
|
+
prefix = cellTextNoNum;
|
|
469
|
+
}
|
|
470
|
+
if (cellTextNoNum && prefix !== cellTextNoNum) {
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
if (!isNaN(cellNum)) {
|
|
474
|
+
if (!checkIncrement) {
|
|
475
|
+
checkIncrement = cellNum;
|
|
476
|
+
return true;
|
|
477
|
+
} else {
|
|
478
|
+
return ++checkIncrement === cellNum;
|
|
479
|
+
}
|
|
650
480
|
} else {
|
|
651
|
-
return
|
|
481
|
+
return false;
|
|
652
482
|
}
|
|
653
|
-
}
|
|
654
|
-
return false;
|
|
655
|
-
}
|
|
656
|
-
});
|
|
483
|
+
});
|
|
657
484
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
485
|
+
if (allAreIncrementing) {
|
|
486
|
+
incrementStart = checkIncrement + 1;
|
|
487
|
+
incrementPrefix = prefix || "";
|
|
488
|
+
incrementPad = maybePad;
|
|
489
|
+
}
|
|
662
490
|
}
|
|
663
491
|
}
|
|
664
492
|
}
|
|
665
493
|
}
|
|
666
|
-
}
|
|
667
494
|
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
495
|
+
let firstSelectedCellRowIndex;
|
|
496
|
+
if (selectionGrid) {
|
|
497
|
+
selectionGrid[0].some(cell => {
|
|
498
|
+
if (cell) {
|
|
499
|
+
firstSelectedCellRowIndex = cell.rowIndex;
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
return false;
|
|
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
|
+
}
|
|
678
539
|
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
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;
|
|
540
|
+
const [rowIdToCopy, cellPathToCopy] = cellIdToCopy.split(":");
|
|
541
|
+
newVal = getCellVal(
|
|
542
|
+
entityMap[rowIdToCopy].e,
|
|
543
|
+
cellPathToCopy,
|
|
544
|
+
pathToField[cellPathToCopy]
|
|
545
|
+
);
|
|
704
546
|
} else {
|
|
705
|
-
|
|
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;
|
|
547
|
+
newVal = selectedCellVal;
|
|
711
548
|
}
|
|
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;
|
|
721
549
|
}
|
|
550
|
+
const { error } = editCellHelper({
|
|
551
|
+
entity: entityToUpdate,
|
|
552
|
+
path: cellPath,
|
|
553
|
+
schema,
|
|
554
|
+
newVal
|
|
555
|
+
});
|
|
556
|
+
newCellValidate[cellId] = error;
|
|
722
557
|
}
|
|
723
|
-
|
|
724
|
-
entity: entityToUpdate,
|
|
725
|
-
path: cellPath,
|
|
726
|
-
schema,
|
|
727
|
-
newVal
|
|
728
|
-
});
|
|
729
|
-
newCellValidate[cellId] = error;
|
|
730
|
-
}
|
|
558
|
+
});
|
|
731
559
|
});
|
|
732
|
-
});
|
|
733
|
-
|
|
734
|
-
// select the new cells
|
|
735
|
-
updateValidation(entities, newCellValidate);
|
|
736
|
-
setSelectedCells(newSelectedCells);
|
|
737
|
-
});
|
|
738
|
-
};
|
|
739
560
|
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
561
|
+
// select the new cells
|
|
562
|
+
updateValidation(entities, newCellValidate);
|
|
563
|
+
setSelectedCells(newSelectedCells);
|
|
564
|
+
});
|
|
565
|
+
},
|
|
566
|
+
[
|
|
567
|
+
entities,
|
|
568
|
+
isSelectionARectangle,
|
|
569
|
+
primarySelectedCellId,
|
|
570
|
+
reduxFormCellValidation,
|
|
571
|
+
schema,
|
|
572
|
+
selectedCells,
|
|
573
|
+
setSelectedCells,
|
|
574
|
+
updateEntitiesHelper,
|
|
575
|
+
updateValidation
|
|
576
|
+
]
|
|
577
|
+
);
|
|
743
578
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
579
|
+
const getCopyTextForCell = useCallback(
|
|
580
|
+
(val, row = {}, column = {}) => {
|
|
581
|
+
// TODOCOPY we need a way to potentially omit certain columns from being added as a \t element (talk to taoh about this)
|
|
582
|
+
let text = typeof val !== "string" ? row.value : val;
|
|
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
|
+
}
|
|
767
616
|
} else {
|
|
768
|
-
return
|
|
617
|
+
return text;
|
|
769
618
|
}
|
|
770
|
-
}
|
|
771
|
-
|
|
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;
|
|
772
627
|
}
|
|
773
|
-
};
|
|
774
|
-
text = getTextFromElementOrLink(text);
|
|
775
628
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
629
|
+
const stringText = toString(text);
|
|
630
|
+
if (stringText === "[object Object]") return "";
|
|
631
|
+
return stringText;
|
|
632
|
+
},
|
|
633
|
+
[cellRenderer, currentParams, setNewParams]
|
|
634
|
+
);
|
|
782
635
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
636
|
+
const renderCheckboxCell = useCallback(
|
|
637
|
+
row => {
|
|
638
|
+
const rowIndex = row.index;
|
|
639
|
+
const checkedRows = getSelectedRowsFromEntities(
|
|
640
|
+
entities,
|
|
641
|
+
reduxFormSelectedEntityIdMap
|
|
642
|
+
);
|
|
643
|
+
|
|
644
|
+
const isSelected = checkedRows.some(rowNum => {
|
|
645
|
+
return rowNum === rowIndex;
|
|
646
|
+
});
|
|
647
|
+
if (rowIndex >= entities.length) {
|
|
648
|
+
return <div />;
|
|
649
|
+
}
|
|
650
|
+
const entity = entities[rowIndex];
|
|
651
|
+
return (
|
|
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
|
+
);
|
|
692
|
+
|
|
693
|
+
const finishCellEdit = useCallback(
|
|
694
|
+
(cellId, newVal, doNotStopEditing) => {
|
|
695
|
+
const [rowId, path] = cellId.split(":");
|
|
696
|
+
!doNotStopEditing && change("reduxFormEditingCell", null);
|
|
697
|
+
updateEntitiesHelper(entities, entities => {
|
|
698
|
+
const entity = entities.find((e, i) => {
|
|
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
|
+
|
|
709
|
+
updateValidation(entities, {
|
|
710
|
+
...reduxFormCellValidation,
|
|
711
|
+
[cellId]: error
|
|
712
|
+
});
|
|
713
|
+
});
|
|
714
|
+
!doNotStopEditing && refocusTable();
|
|
715
|
+
},
|
|
716
|
+
[
|
|
717
|
+
change,
|
|
718
|
+
entities,
|
|
719
|
+
reduxFormCellValidation,
|
|
720
|
+
refocusTable,
|
|
721
|
+
schema,
|
|
722
|
+
updateEntitiesHelper,
|
|
723
|
+
updateValidation
|
|
724
|
+
]
|
|
725
|
+
);
|
|
726
|
+
|
|
727
|
+
const cancelCellEdit = useCallback(() => {
|
|
728
|
+
change("reduxFormEditingCell", null);
|
|
729
|
+
refocusTable();
|
|
730
|
+
}, [change, refocusTable]);
|
|
787
731
|
|
|
788
732
|
if (!columns.length) {
|
|
789
733
|
return columns;
|
|
@@ -848,72 +792,6 @@ export const RenderColumns = props => {
|
|
|
848
792
|
});
|
|
849
793
|
}
|
|
850
794
|
|
|
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
|
-
|
|
917
795
|
if (withCheckboxes) {
|
|
918
796
|
columnsToRender.push({
|
|
919
797
|
Header: renderCheckboxHeader({
|
|
@@ -947,7 +825,7 @@ export const RenderColumns = props => {
|
|
|
947
825
|
});
|
|
948
826
|
}
|
|
949
827
|
|
|
950
|
-
columns.
|
|
828
|
+
const tableColumns = columns.map(column => {
|
|
951
829
|
const tableColumn = {
|
|
952
830
|
...column,
|
|
953
831
|
Header: RenderColumnHeader({
|
|
@@ -982,17 +860,18 @@ export const RenderColumns = props => {
|
|
|
982
860
|
}
|
|
983
861
|
if (cellRenderer && cellRenderer[column.path]) {
|
|
984
862
|
tableColumn.Cell = row => {
|
|
985
|
-
const val = cellRenderer[column.path](
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
props
|
|
990
|
-
);
|
|
863
|
+
const val = cellRenderer[column.path](row.value, row.original, row, {
|
|
864
|
+
currentParams,
|
|
865
|
+
setNewParams
|
|
866
|
+
});
|
|
991
867
|
return val;
|
|
992
868
|
};
|
|
993
869
|
} else if (column.render) {
|
|
994
870
|
tableColumn.Cell = row => {
|
|
995
|
-
const val = column.render(row.value, row.original, row,
|
|
871
|
+
const val = column.render(row.value, row.original, row, {
|
|
872
|
+
currentParams,
|
|
873
|
+
setNewParams
|
|
874
|
+
});
|
|
996
875
|
return val;
|
|
997
876
|
};
|
|
998
877
|
} else if (column.type === "timestamp") {
|
|
@@ -1040,6 +919,7 @@ export const RenderColumns = props => {
|
|
|
1040
919
|
tableColumn.Cell = (...args) => (
|
|
1041
920
|
<RenderCell
|
|
1042
921
|
oldFunc={oldFunc}
|
|
922
|
+
formName={formName}
|
|
1043
923
|
getCopyTextForCell={getCopyTextForCell}
|
|
1044
924
|
column={column}
|
|
1045
925
|
isCellEditable={isCellEditable}
|
|
@@ -1048,8 +928,6 @@ export const RenderColumns = props => {
|
|
|
1048
928
|
noEllipsis={noEllipsis}
|
|
1049
929
|
editingCell={editingCell}
|
|
1050
930
|
cancelCellEdit={cancelCellEdit}
|
|
1051
|
-
editableCellValue={editableCellValue}
|
|
1052
|
-
setEditableCellValue={setEditableCellValue}
|
|
1053
931
|
editingCellSelectAll={editingCellSelectAll}
|
|
1054
932
|
getCellHoverText={getCellHoverText}
|
|
1055
933
|
selectedCells={selectedCells}
|
|
@@ -1060,7 +938,8 @@ export const RenderColumns = props => {
|
|
|
1060
938
|
args={args}
|
|
1061
939
|
/>
|
|
1062
940
|
);
|
|
1063
|
-
|
|
941
|
+
return tableColumn;
|
|
1064
942
|
});
|
|
1065
|
-
|
|
943
|
+
|
|
944
|
+
return columnsToRender.concat(tableColumns);
|
|
1066
945
|
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
2
|
+
|
|
3
|
+
export const EditableCell = ({
|
|
4
|
+
cancelEdit,
|
|
5
|
+
dataTest,
|
|
6
|
+
finishEdit,
|
|
7
|
+
isNumeric,
|
|
8
|
+
initialValue
|
|
9
|
+
}) => {
|
|
10
|
+
const [value, setValue] = useState(initialValue);
|
|
11
|
+
const inputRef = useRef(null);
|
|
12
|
+
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (inputRef.current) {
|
|
15
|
+
inputRef.current.focus();
|
|
16
|
+
}
|
|
17
|
+
}, [isNumeric]);
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<input
|
|
21
|
+
style={{
|
|
22
|
+
border: 0,
|
|
23
|
+
width: "95%",
|
|
24
|
+
fontSize: 12,
|
|
25
|
+
background: "none"
|
|
26
|
+
}}
|
|
27
|
+
ref={inputRef}
|
|
28
|
+
{...dataTest}
|
|
29
|
+
autoFocus
|
|
30
|
+
onKeyDown={e => {
|
|
31
|
+
e.stopPropagation();
|
|
32
|
+
if (e.key === "Enter") {
|
|
33
|
+
e.target.blur();
|
|
34
|
+
} else if (e.key === "Escape") {
|
|
35
|
+
cancelEdit();
|
|
36
|
+
}
|
|
37
|
+
}}
|
|
38
|
+
onBlur={() => finishEdit(value)}
|
|
39
|
+
onChange={e => setValue(e.target.value)}
|
|
40
|
+
type={isNumeric ? "number" : undefined}
|
|
41
|
+
value={value}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useSelector } from "react-redux";
|
|
3
|
+
import { Checkbox, Icon } from "@blueprintjs/core";
|
|
4
|
+
import {
|
|
5
|
+
getIdOrCodeOrIndex,
|
|
6
|
+
isBottomRightCornerOfRectangle,
|
|
7
|
+
PRIMARY_SELECTED_VAL
|
|
8
|
+
} from "./utils";
|
|
9
|
+
import { DropdownCell } from "./DropdownCell";
|
|
10
|
+
import { EditableCell } from "./EditableCell";
|
|
11
|
+
import { getVals } from "./getVals";
|
|
12
|
+
import { CellDragHandle } from "./CellDragHandle";
|
|
13
|
+
|
|
14
|
+
export const RenderCell = ({
|
|
15
|
+
oldFunc,
|
|
16
|
+
getCopyTextForCell,
|
|
17
|
+
column,
|
|
18
|
+
isCellEditable,
|
|
19
|
+
isEntityDisabled,
|
|
20
|
+
finishCellEdit,
|
|
21
|
+
formName,
|
|
22
|
+
noEllipsis,
|
|
23
|
+
cancelCellEdit,
|
|
24
|
+
getCellHoverText,
|
|
25
|
+
selectedCells,
|
|
26
|
+
isSelectionARectangle,
|
|
27
|
+
startCellEdit,
|
|
28
|
+
tableRef,
|
|
29
|
+
onDragEnd,
|
|
30
|
+
args
|
|
31
|
+
}) => {
|
|
32
|
+
const editingCell = useSelector(
|
|
33
|
+
state => state.form?.[formName]?.values?.reduxFormEditingCell
|
|
34
|
+
);
|
|
35
|
+
const initialValue = useSelector(
|
|
36
|
+
state => state.form?.[formName]?.values?.reduxFormInitialValue
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const [row] = args;
|
|
40
|
+
const rowId = getIdOrCodeOrIndex(row.original, row.index);
|
|
41
|
+
const cellId = `${rowId}:${row.column.path}`;
|
|
42
|
+
const isEditingCell = editingCell === cellId;
|
|
43
|
+
let val = oldFunc(...args);
|
|
44
|
+
const oldVal = val;
|
|
45
|
+
const text = getCopyTextForCell(val, row, column);
|
|
46
|
+
const dataTest = {
|
|
47
|
+
"data-test": "tgCell_" + column.path
|
|
48
|
+
};
|
|
49
|
+
const fullValue = row.original?.[row.column.path];
|
|
50
|
+
|
|
51
|
+
if (isEditingCell) {
|
|
52
|
+
if (column.type === "genericSelect") {
|
|
53
|
+
const GenericSelectComp = column.GenericSelectComp;
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<GenericSelectComp
|
|
57
|
+
rowId={rowId}
|
|
58
|
+
fullValue={fullValue}
|
|
59
|
+
initialValue={text}
|
|
60
|
+
{...dataTest}
|
|
61
|
+
finishEdit={(newVal, doNotStopEditing) => {
|
|
62
|
+
finishCellEdit(cellId, newVal, doNotStopEditing);
|
|
63
|
+
}}
|
|
64
|
+
dataTest={dataTest}
|
|
65
|
+
cancelEdit={cancelCellEdit}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
if (column.type === "dropdown" || column.type === "dropdownMulti") {
|
|
70
|
+
return (
|
|
71
|
+
<DropdownCell
|
|
72
|
+
isMulti={dataTest.isMulti || column.type === "dropdownMulti"}
|
|
73
|
+
initialValue={dataTest.initialValue || text}
|
|
74
|
+
options={getVals(column.values)}
|
|
75
|
+
finishEdit={(newVal, doNotStopEditing) => {
|
|
76
|
+
finishCellEdit(cellId, newVal, doNotStopEditing);
|
|
77
|
+
}}
|
|
78
|
+
dataTest={dataTest}
|
|
79
|
+
cancelEdit={cancelCellEdit}
|
|
80
|
+
/>
|
|
81
|
+
);
|
|
82
|
+
} else {
|
|
83
|
+
return (
|
|
84
|
+
<EditableCell
|
|
85
|
+
dataTest={dataTest}
|
|
86
|
+
cancelEdit={cancelCellEdit}
|
|
87
|
+
isNumeric={column.type === "number"}
|
|
88
|
+
initialValue={initialValue || text}
|
|
89
|
+
finishEdit={newVal => {
|
|
90
|
+
finishCellEdit(cellId, newVal);
|
|
91
|
+
}}
|
|
92
|
+
/>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const isBool = column.type === "boolean";
|
|
98
|
+
if (isCellEditable && isBool) {
|
|
99
|
+
val = (
|
|
100
|
+
<Checkbox
|
|
101
|
+
disabled={isEntityDisabled(row.original)}
|
|
102
|
+
className="tg-cell-edit-boolean-checkbox"
|
|
103
|
+
checked={oldVal === "True"}
|
|
104
|
+
onChange={e => {
|
|
105
|
+
const checked = e.target.checked;
|
|
106
|
+
finishCellEdit(cellId, checked);
|
|
107
|
+
}}
|
|
108
|
+
/>
|
|
109
|
+
);
|
|
110
|
+
noEllipsis = true;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
//wrap the original tableColumn.Cell function in another div in order to add a title attribute
|
|
114
|
+
let title = text;
|
|
115
|
+
if (getCellHoverText) title = getCellHoverText(...args);
|
|
116
|
+
else if (column.getTitleAttr) title = column.getTitleAttr(...args);
|
|
117
|
+
const isSelectedCell = selectedCells?.[cellId];
|
|
118
|
+
const {
|
|
119
|
+
isRect,
|
|
120
|
+
selectionGrid,
|
|
121
|
+
lastRowIndex,
|
|
122
|
+
lastCellIndex,
|
|
123
|
+
entityMap,
|
|
124
|
+
pathToIndex
|
|
125
|
+
} = isSelectionARectangle();
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<>
|
|
129
|
+
<div
|
|
130
|
+
style={{
|
|
131
|
+
...(!noEllipsis && {
|
|
132
|
+
textOverflow: "ellipsis",
|
|
133
|
+
overflow: "hidden"
|
|
134
|
+
})
|
|
135
|
+
}}
|
|
136
|
+
{...dataTest}
|
|
137
|
+
className="tg-cell-wrapper"
|
|
138
|
+
data-copy-text={text}
|
|
139
|
+
data-copy-json={JSON.stringify(
|
|
140
|
+
//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
|
|
141
|
+
column.type === "genericSelect"
|
|
142
|
+
? {
|
|
143
|
+
__strVal: fullValue,
|
|
144
|
+
__genSelCol: column.path
|
|
145
|
+
}
|
|
146
|
+
: { __strVal: text }
|
|
147
|
+
)}
|
|
148
|
+
title={title || undefined}
|
|
149
|
+
>
|
|
150
|
+
{val}
|
|
151
|
+
</div>
|
|
152
|
+
{isCellEditable &&
|
|
153
|
+
(column.type === "dropdown" ||
|
|
154
|
+
column.type === "dropdownMulti" ||
|
|
155
|
+
column.type === "genericSelect") && (
|
|
156
|
+
<Icon
|
|
157
|
+
icon="caret-down"
|
|
158
|
+
style={{
|
|
159
|
+
position: "absolute",
|
|
160
|
+
right: 5,
|
|
161
|
+
opacity: 0.3
|
|
162
|
+
}}
|
|
163
|
+
className="cell-edit-dropdown"
|
|
164
|
+
onClick={() => {
|
|
165
|
+
startCellEdit(cellId);
|
|
166
|
+
}}
|
|
167
|
+
/>
|
|
168
|
+
)}
|
|
169
|
+
|
|
170
|
+
{isSelectedCell &&
|
|
171
|
+
(isRect
|
|
172
|
+
? isBottomRightCornerOfRectangle({
|
|
173
|
+
cellId,
|
|
174
|
+
selectionGrid,
|
|
175
|
+
lastRowIndex,
|
|
176
|
+
lastCellIndex,
|
|
177
|
+
entityMap,
|
|
178
|
+
pathToIndex
|
|
179
|
+
})
|
|
180
|
+
: isSelectedCell === PRIMARY_SELECTED_VAL) && (
|
|
181
|
+
<CellDragHandle
|
|
182
|
+
key={cellId}
|
|
183
|
+
thisTable={tableRef.current.tableRef}
|
|
184
|
+
cellId={cellId}
|
|
185
|
+
isSelectionARectangle={isSelectionARectangle}
|
|
186
|
+
onDragEnd={onDragEnd}
|
|
187
|
+
/>
|
|
188
|
+
)}
|
|
189
|
+
</>
|
|
190
|
+
);
|
|
191
|
+
};
|
package/src/TgSelect/index.js
CHANGED
|
@@ -93,11 +93,11 @@ class TgSelect extends React.Component {
|
|
|
93
93
|
return true;
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
|
-
return onChange([...valArray, item]);
|
|
96
|
+
return onChange([...valArray, item], e);
|
|
97
97
|
} else {
|
|
98
98
|
this.setOpenState(false);
|
|
99
99
|
this.input && this.input.blur();
|
|
100
|
-
return onChange(item);
|
|
100
|
+
return onChange(item, e);
|
|
101
101
|
}
|
|
102
102
|
};
|
|
103
103
|
|