@teselagen/ui 0.3.77 → 0.3.79

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.
@@ -29,8 +29,7 @@ import {
29
29
  times,
30
30
  some,
31
31
  isFunction,
32
- every,
33
- uniq
32
+ every
34
33
  } from "lodash";
35
34
  import joinUrl from "url-join";
36
35
 
@@ -45,8 +44,7 @@ import {
45
44
  Popover,
46
45
  Intent,
47
46
  Callout,
48
- Tooltip,
49
- Divider
47
+ Tooltip
50
48
  } from "@blueprintjs/core";
51
49
  import classNames from "classnames";
52
50
  import scrollIntoView from "dom-scroll-into-view";
@@ -59,6 +57,7 @@ import ReactMarkdown from "react-markdown";
59
57
  import immer, { produceWithPatches, enablePatches, applyPatches } from "immer";
60
58
  import papaparse from "papaparse";
61
59
  import remarkGfm from "remark-gfm";
60
+
62
61
  import TgSelect from "../TgSelect";
63
62
  import { withHotkeys } from "../utils/hotkeyUtils";
64
63
  import InfoHelper from "../InfoHelper";
@@ -75,6 +74,7 @@ import SearchBar from "./SearchBar";
75
74
  import DisplayOptions from "./DisplayOptions";
76
75
  import DisabledLoadingComponent from "./DisabledLoadingComponent";
77
76
  import SortableColumns from "./SortableColumns";
77
+ import computePresets from "./utils/computePresets";
78
78
  import dataTableEnhancer from "./dataTableEnhancer";
79
79
  import defaultProps from "./defaultProps";
80
80
 
@@ -86,16 +86,10 @@ import { CellDragHandle } from "./CellDragHandle";
86
86
  import { nanoid } from "nanoid";
87
87
  import { SwitchField } from "../FormComponents";
88
88
  import { validateTableWideErrors } from "./validateTableWideErrors";
89
- import {
90
- editCellHelper,
91
- getCellAlphaNumHelper,
92
- getColLetFromIndex,
93
- replaceFormulaRanges
94
- } from "./editCellHelper";
89
+ import { editCellHelper } from "./editCellHelper";
95
90
  import { getCellVal } from "./getCellVal";
96
91
  import { getVals } from "./getVals";
97
92
  import { throwFormError } from "../throwFormError";
98
- import showConfirmationDialog from "../showConfirmationDialog";
99
93
  enablePatches();
100
94
 
101
95
  const PRIMARY_SELECTED_VAL = "main_cell";
@@ -227,10 +221,8 @@ class DataTable extends React.Component {
227
221
  reduxFormEntitiesUndoRedoStack.currentVersion
228
222
  ].inversePatches
229
223
  );
230
- this.buildDepGraph(nextState);
231
224
  const { newEnts, validationErrors } =
232
225
  this.formatAndValidateEntities(nextState);
233
-
234
226
  change("reduxFormEntities", newEnts);
235
227
  this.updateValidation(newEnts, validationErrors);
236
228
  change("reduxFormEntitiesUndoRedoStack", {
@@ -253,10 +245,8 @@ class DataTable extends React.Component {
253
245
  entities,
254
246
  reduxFormEntitiesUndoRedoStack[nextV].patches
255
247
  );
256
- this.buildDepGraph(nextState);
257
248
  const { newEnts, validationErrors } =
258
249
  this.formatAndValidateEntities(nextState);
259
-
260
250
  change("reduxFormEntities", newEnts);
261
251
  this.updateValidation(newEnts, validationErrors);
262
252
  change("reduxFormEntitiesUndoRedoStack", {
@@ -409,16 +399,15 @@ class DataTable extends React.Component {
409
399
  };
410
400
  formatAndValidateEntities = (
411
401
  entities,
412
- { useDefaultValues, indexToStartAt, depGraphToUse } = {}
402
+ { useDefaultValues, indexToStartAt } = {}
413
403
  ) => {
414
- const { schema, allowFormulas } = this.props;
404
+ const { schema } = this.props;
415
405
  const editableFields = schema.fields.filter(f => !f.isNotEditable);
416
406
  const validationErrors = {};
417
- const updateGroup = {};
418
- const depGraph = depGraphToUse || this.depGraph;
407
+
419
408
  const newEnts = immer(entities, entities => {
420
409
  entities.forEach((e, index) => {
421
- editableFields.forEach((columnSchema, colIndex) => {
410
+ editableFields.forEach(columnSchema => {
422
411
  if (useDefaultValues) {
423
412
  if (e[columnSchema.path] === undefined) {
424
413
  if (isFunction(columnSchema.defaultValue)) {
@@ -430,18 +419,15 @@ class DataTable extends React.Component {
430
419
  }
431
420
  }
432
421
  //mutative
433
- const { errors } = editCellHelper({
434
- _cellAlphaNum: getCellAlphaNumHelper(colIndex, index),
435
- allowFormulas,
436
- updateGroup,
437
- depGraph,
438
- entities,
422
+ const { error } = editCellHelper({
439
423
  entity: e,
440
- schema,
441
424
  columnSchema,
442
425
  newVal: e[columnSchema.path]
443
426
  });
444
- Object.assign(validationErrors, errors);
427
+ if (error) {
428
+ const rowId = getIdOrCodeOrIndex(e, index);
429
+ validationErrors[`${rowId}:${columnSchema.path}`] = error;
430
+ }
445
431
  });
446
432
  });
447
433
  });
@@ -450,43 +436,6 @@ class DataTable extends React.Component {
450
436
  validationErrors
451
437
  };
452
438
  };
453
- buildDepGraph = ents => {
454
- const { schema, allowFormulas } = this.props;
455
- if (!allowFormulas) return;
456
- const depGraph = {};
457
- schema.fields.forEach((field, fi) => {
458
- if (field.allowFormulas) {
459
- ents.forEach((ent, i) => {
460
- const val = ent[field.path];
461
- const formula =
462
- val &&
463
- (val.formula || (typeof val === "string" && val[0] === "=" && val));
464
- if (formula) {
465
- const { replacedFormula } = replaceFormulaRanges({
466
- formula,
467
- entities: ents,
468
- schema
469
- });
470
- const deps = replacedFormula.match(/[A-Z]+[0-9]+/gi);
471
- if (deps) {
472
- deps.forEach(_dep => {
473
- const dep = _dep.toUpperCase();
474
-
475
- if (!depGraph[dep]) {
476
- depGraph[dep] = [];
477
- }
478
- // convert the field index to a letter
479
- const fieldLetter = getColLetFromIndex(fi);
480
- depGraph[dep].push(`${fieldLetter}${i + 1}`);
481
- });
482
- }
483
- }
484
- });
485
- }
486
- });
487
- this.depGraph = depGraph;
488
- };
489
-
490
439
  formatAndValidateTableInitial = () => {
491
440
  const {
492
441
  _origEntities,
@@ -495,11 +444,10 @@ class DataTable extends React.Component {
495
444
  change,
496
445
  reduxFormCellValidation
497
446
  } = this.props;
498
- const ents =
447
+ const { newEnts, validationErrors } = this.formatAndValidateEntities(
499
448
  initialEntities ||
500
- (entities && entities.length ? entities : _origEntities);
501
- this.buildDepGraph(ents);
502
- const { newEnts, validationErrors } = this.formatAndValidateEntities(ents);
449
+ (entities && entities.length ? entities : _origEntities)
450
+ );
503
451
  change("reduxFormEntities", newEnts);
504
452
  const toKeep = {};
505
453
  //on the initial load we want to keep any async table wide errors
@@ -523,7 +471,7 @@ class DataTable extends React.Component {
523
471
  setShowForcedHidden
524
472
  } = this.props;
525
473
  isCellEditable && this.formatAndValidateTableInitial();
526
- this.updateFromProps({}, this.props);
474
+ this.updateFromProps({}, computePresets(this.props));
527
475
  document.addEventListener("paste", this.handlePaste);
528
476
 
529
477
  if (!entities.length && !isLoading && !showForcedHiddenColumns) {
@@ -551,7 +499,7 @@ class DataTable extends React.Component {
551
499
  // }
552
500
  // }
553
501
 
554
- this.updateFromProps(oldProps, this.props);
502
+ this.updateFromProps(computePresets(oldProps), computePresets(this.props));
555
503
 
556
504
  // comment in to test what is causing re-render
557
505
  // Object.entries(this.props).forEach(
@@ -567,7 +515,7 @@ class DataTable extends React.Component {
567
515
  handleRowMove = (type, shiftHeld) => e => {
568
516
  e.preventDefault();
569
517
  e.stopPropagation();
570
- const props = this.props;
518
+ const props = computePresets(this.props);
571
519
  const {
572
520
  noSelect,
573
521
  entities,
@@ -637,7 +585,9 @@ class DataTable extends React.Component {
637
585
  });
638
586
  };
639
587
  handleCopyHotkey = e => {
640
- const { isCellEditable, reduxFormSelectedEntityIdMap } = this.props;
588
+ const { isCellEditable, reduxFormSelectedEntityIdMap } = computePresets(
589
+ this.props
590
+ );
641
591
 
642
592
  if (isCellEditable) {
643
593
  this.handleCopySelectedCells(e);
@@ -665,10 +615,9 @@ class DataTable extends React.Component {
665
615
  reduxFormCellValidation,
666
616
  change,
667
617
  schema,
668
- entities,
669
- allowFormulas
670
- } = this.props;
671
- const updateGroup = {};
618
+ entities
619
+ } = computePresets(this.props);
620
+
672
621
  if (isCellEditable) {
673
622
  if (isEmpty(reduxFormSelectedCells)) return;
674
623
  try {
@@ -681,8 +630,6 @@ class DataTable extends React.Component {
681
630
  toPaste = e.clipboardData.getData("text/plain");
682
631
  }
683
632
  const jsonToPaste = e.clipboardData.getData("application/json");
684
- let hasReplace = false;
685
-
686
633
  try {
687
634
  const pastedJson = [];
688
635
  JSON.parse(jsonToPaste).forEach(row => {
@@ -703,14 +650,6 @@ class DataTable extends React.Component {
703
650
  pasteData = pasteData.slice(1);
704
651
  }
705
652
  } catch (e) {
706
- if (toPaste.includes("=") && allowFormulas) {
707
- // replace any commas inside brackets with %%comma%% so that we can parse it out later
708
- toPaste = toPaste.replace(/\(([^)]+)\)/g, match => {
709
- hasReplace = true;
710
- const toRet = match.replace(/,/g, "%%comma%%");
711
- return toRet;
712
- });
713
- }
714
653
  if (toPaste.includes(",")) {
715
654
  //try papaparsing it out as a csv if it contains commas
716
655
  try {
@@ -726,19 +665,11 @@ class DataTable extends React.Component {
726
665
  }
727
666
  }
728
667
  pasteData = pasteData.length ? pasteData : defaultParsePaste(toPaste);
729
- if (hasReplace) {
730
- // put the commas back in
731
668
 
732
- pasteData = pasteData.map(row => {
733
- return row.map(cell => {
734
- return cell.replace(/%%comma%%/g, ",");
735
- });
736
- });
737
- }
738
669
  if (!pasteData || !pasteData.length) return;
739
670
 
740
671
  if (pasteData.length === 1 && pasteData[0].length === 1) {
741
- let newCellValidate = {
672
+ const newCellValidate = {
742
673
  ...reduxFormCellValidation
743
674
  };
744
675
  // single paste value, fill all cells with value
@@ -750,29 +681,25 @@ class DataTable extends React.Component {
750
681
 
751
682
  const entity = entityIdToEntity[rowId].e;
752
683
  delete entity._isClean;
753
- const { errors } = editCellHelper({
754
- allowFormulas,
755
- updateGroup,
756
- depGraph: this.depGraph,
757
- entities,
684
+ const { error } = editCellHelper({
758
685
  entity,
759
686
  path,
760
687
  schema,
761
688
  newVal: formatPasteData({ newVal, path, schema })
762
689
  });
763
- newCellValidate = {
764
- ...newCellValidate,
765
- ...errors
766
- };
690
+ if (error) {
691
+ newCellValidate[cellId] = error;
692
+ } else {
693
+ delete newCellValidate[cellId];
694
+ }
767
695
  });
768
- this.buildDepGraph(entities);
769
696
  this.updateValidation(entities, newCellValidate);
770
697
  });
771
698
  } else {
772
699
  // handle paste in same format
773
700
  const primarySelectedCell = this.getPrimarySelectedCellId();
774
701
  if (primarySelectedCell) {
775
- let newCellValidate = {
702
+ const newCellValidate = {
776
703
  ...reduxFormCellValidation
777
704
  };
778
705
 
@@ -801,11 +728,7 @@ class DataTable extends React.Component {
801
728
  delete entity._isClean;
802
729
  const path = indexToPath[cellIndexToChange];
803
730
  if (path) {
804
- const { errors } = editCellHelper({
805
- allowFormulas,
806
- updateGroup,
807
- depGraph: this.depGraph,
808
- entities,
731
+ const { error } = editCellHelper({
809
732
  entity,
810
733
  path,
811
734
  schema,
@@ -819,16 +742,16 @@ class DataTable extends React.Component {
819
742
  if (!newSelectedCells[cellId]) {
820
743
  newSelectedCells[cellId] = true;
821
744
  }
822
- newCellValidate = {
823
- ...newCellValidate,
824
- ...errors
825
- };
745
+ if (error) {
746
+ newCellValidate[cellId] = error;
747
+ } else {
748
+ delete newCellValidate[cellId];
749
+ }
826
750
  }
827
751
  }
828
752
  }
829
753
  });
830
754
  });
831
- this.buildDepGraph(entities);
832
755
  this.updateValidation(entities, newCellValidate);
833
756
  });
834
757
  change("reduxFormSelectedCells", newSelectedCells);
@@ -847,7 +770,7 @@ class DataTable extends React.Component {
847
770
  isSingleSelect,
848
771
  isCellEditable,
849
772
  schema
850
- } = this.props;
773
+ } = computePresets(this.props);
851
774
  if (isSingleSelect) return;
852
775
  e.preventDefault();
853
776
 
@@ -873,17 +796,17 @@ class DataTable extends React.Component {
873
796
  finalizeSelection({
874
797
  idMap: newIdMap,
875
798
  entities,
876
- props: this.props
799
+ props: computePresets(this.props)
877
800
  });
878
801
  }
879
802
  };
880
803
  updateValidationHelper = () => {
881
- const { entities, reduxFormCellValidation } = this.props;
804
+ const { entities, reduxFormCellValidation } = computePresets(this.props);
882
805
  this.updateValidation(entities, reduxFormCellValidation);
883
806
  };
884
807
 
885
808
  updateValidation = (entities, newCellValidate) => {
886
- const { change, schema } = this.props;
809
+ const { change, schema } = computePresets(this.props);
887
810
  const tableWideErr = validateTableWideErrors({
888
811
  entities,
889
812
  schema,
@@ -898,15 +821,12 @@ class DataTable extends React.Component {
898
821
  reduxFormSelectedCells,
899
822
  reduxFormCellValidation,
900
823
  schema,
901
- entities,
902
- allowFormulas
903
- } = this.props;
904
- let newCellValidate = {
824
+ entities
825
+ } = computePresets(this.props);
826
+ const newCellValidate = {
905
827
  ...reduxFormCellValidation
906
828
  };
907
829
  if (isEmpty(reduxFormSelectedCells)) return;
908
- const updateGroup = {};
909
-
910
830
  const rowIds = [];
911
831
  this.updateEntitiesHelper(entities, entities => {
912
832
  const entityIdToEntity = getEntityIdToEntity(entities);
@@ -915,22 +835,18 @@ class DataTable extends React.Component {
915
835
  rowIds.push(rowId);
916
836
  const entity = entityIdToEntity[rowId].e;
917
837
  delete entity._isClean;
918
- const { errors } = editCellHelper({
919
- allowFormulas,
920
- updateGroup,
921
- depGraph: this.depGraph,
922
- entities,
838
+ const { error } = editCellHelper({
923
839
  entity,
924
840
  path,
925
841
  schema,
926
842
  newVal: ""
927
843
  });
928
- newCellValidate = {
929
- ...newCellValidate,
930
- ...errors
931
- };
844
+ if (error) {
845
+ newCellValidate[cellId] = error;
846
+ } else {
847
+ delete newCellValidate[cellId];
848
+ }
932
849
  });
933
- this.buildDepGraph(entities);
934
850
  this.updateValidation(entities, newCellValidate);
935
851
  });
936
852
  };
@@ -940,17 +856,16 @@ class DataTable extends React.Component {
940
856
  this.handleCopyHotkey(e);
941
857
  };
942
858
 
943
- getCellCopyText = (cellWrapper, isFormulaCopy) => {
944
- // note - all copy/download functions use this helper to get the text to copy
859
+ getCellCopyText = cellWrapper => {
945
860
  const text = cellWrapper && cellWrapper.getAttribute("data-copy-text");
946
- const formula = cellWrapper && cellWrapper.getAttribute("data-formula");
947
861
  const jsonText = cellWrapper && cellWrapper.getAttribute("data-copy-json");
862
+
948
863
  const textContent = text || cellWrapper.textContent || "";
949
- return [(isFormulaCopy && formula) || textContent, jsonText];
864
+ return [textContent, jsonText];
950
865
  };
951
866
 
952
- handleCopyColumn = ({ e, cellWrapper, selectedRecords, opts }) => {
953
- const specificColumn = cellWrapper.getAttribute("data-column");
867
+ handleCopyColumn = (e, cellWrapper, selectedRecords) => {
868
+ const specificColumn = cellWrapper.getAttribute("data-test");
954
869
  let rowElsToCopy = getAllRows(e);
955
870
  if (!rowElsToCopy) return;
956
871
  if (selectedRecords) {
@@ -963,21 +878,17 @@ class DataTable extends React.Component {
963
878
  if (!rowElsToCopy) return;
964
879
  this.handleCopyRows(rowElsToCopy, {
965
880
  specificColumn,
966
- onFinishMsg: "Column Copied",
967
- ...opts
881
+ onFinishMsg: "Column Copied"
968
882
  });
969
883
  };
970
884
  handleCopyRows = (
971
885
  rowElsToCopy,
972
- { specificColumn, onFinishMsg, isDownload, isFormulaCopy } = {}
886
+ { specificColumn, onFinishMsg, isDownload } = {}
973
887
  ) => {
974
888
  let textToCopy = [];
975
889
  const jsonToCopy = [];
976
890
  forEach(rowElsToCopy, rowEl => {
977
- const [t, j] = this.getRowCopyText(rowEl, {
978
- specificColumn,
979
- isFormulaCopy
980
- });
891
+ const [t, j] = this.getRowCopyText(rowEl, { specificColumn });
981
892
  textToCopy.push(t);
982
893
  jsonToCopy.push(j);
983
894
  });
@@ -998,7 +909,6 @@ class DataTable extends React.Component {
998
909
  this.props;
999
910
  const [nextState, patches, inversePatches] = produceWithPatches(ents, fn);
1000
911
  if (!inversePatches.length) return;
1001
-
1002
912
  const thatNewNew = [...nextState];
1003
913
  thatNewNew.isDirty = true;
1004
914
  change("reduxFormEntities", thatNewNew);
@@ -1014,7 +924,7 @@ class DataTable extends React.Component {
1014
924
  });
1015
925
  };
1016
926
 
1017
- getRowCopyText = (rowEl, { specificColumn, isFormulaCopy } = {}) => {
927
+ getRowCopyText = (rowEl, { specificColumn } = {}) => {
1018
928
  //takes in a row element
1019
929
  if (!rowEl) return [];
1020
930
  const textContent = [];
@@ -1028,11 +938,11 @@ class DataTable extends React.Component {
1028
938
  }
1029
939
  if (
1030
940
  specificColumn &&
1031
- cellChild.getAttribute("data-column") !== specificColumn
941
+ cellChild.getAttribute("data-test") !== specificColumn
1032
942
  ) {
1033
943
  return [];
1034
944
  }
1035
- const [t, j] = this.getCellCopyText(cellChild, isFormulaCopy);
945
+ const [t, j] = this.getCellCopyText(cellChild);
1036
946
  textContent.push(t);
1037
947
  jsonText.push(j);
1038
948
  });
@@ -1041,15 +951,10 @@ class DataTable extends React.Component {
1041
951
  };
1042
952
 
1043
953
  handleCopyHelper = (stringToCopy, jsonToCopy, message) => {
1044
- const jToC = JSON.stringify(jsonToCopy);
1045
- if (window.Cypress) {
1046
- window.Cypress.__savedClipboardData = stringToCopy;
1047
- window.Cypress.__savedClipboardDataJson = jToC;
1048
- }
1049
954
  !window.Cypress &&
1050
955
  copy(stringToCopy, {
1051
956
  onCopy: clipboardData => {
1052
- clipboardData.setData("application/json", jToC);
957
+ clipboardData.setData("application/json", JSON.stringify(jsonToCopy));
1053
958
  },
1054
959
  // keep this so that pasting into spreadsheets works.
1055
960
  format: "text/plain"
@@ -1059,10 +964,9 @@ class DataTable extends React.Component {
1059
964
  }
1060
965
  };
1061
966
 
1062
- handleCopyTable = (e, opts = {}) => {
967
+ handleCopyTable = (e, opts) => {
1063
968
  try {
1064
- let allRowEls = getAllRows(e);
1065
- if (opts.noHeader) allRowEls = [...allRowEls].slice(1);
969
+ const allRowEls = getAllRows(e);
1066
970
  if (!allRowEls) return;
1067
971
  this.handleCopyRows(allRowEls, {
1068
972
  ...opts,
@@ -1073,12 +977,15 @@ class DataTable extends React.Component {
1073
977
  window.toastr.error("Error copying rows.");
1074
978
  }
1075
979
  };
1076
- handleCopySelectedCells = (e, opts) => {
1077
- const { entities = [], reduxFormSelectedCells, schema } = this.props;
980
+ handleCopySelectedCells = e => {
981
+ const {
982
+ entities = [],
983
+ reduxFormSelectedCells,
984
+ schema
985
+ } = computePresets(this.props);
1078
986
  // if the current selection is consecutive cells then copy with
1079
987
  // tabs between. if not then just select primary selected cell
1080
- const getEmptyMsg = () => window.toastr.warning("No text to copy");
1081
- if (isEmpty(reduxFormSelectedCells)) return getEmptyMsg();
988
+ if (isEmpty(reduxFormSelectedCells)) return;
1082
989
  const pathToIndex = getFieldPathToIndex(schema);
1083
990
  const entityIdToEntity = getEntityIdToEntity(entities);
1084
991
  const selectionGrid = [];
@@ -1101,7 +1008,7 @@ class DataTable extends React.Component {
1101
1008
  selectionGrid[eInfo.i][cellIndex] = true;
1102
1009
  }
1103
1010
  });
1104
- if (firstRowIndex === undefined) return getEmptyMsg();
1011
+ if (firstRowIndex === undefined) return;
1105
1012
  const allRows = getAllRows(e);
1106
1013
  let fullCellText = "";
1107
1014
  const fullJson = [];
@@ -1115,7 +1022,7 @@ class DataTable extends React.Component {
1115
1022
  } else {
1116
1023
  const jsonRow = [];
1117
1024
  // ignore header
1118
- let [rowCopyText, json] = this.getRowCopyText(allRows[i + 1], opts);
1025
+ let [rowCopyText, json] = this.getRowCopyText(allRows[i + 1]);
1119
1026
  rowCopyText = rowCopyText.split("\t");
1120
1027
  times(row.length, i => {
1121
1028
  const cell = row[i];
@@ -1128,17 +1035,13 @@ class DataTable extends React.Component {
1128
1035
  fullJson.push(jsonRow);
1129
1036
  }
1130
1037
  });
1131
- if (!fullCellText) return getEmptyMsg();
1038
+ if (!fullCellText) return window.toastr.warning("No text to copy");
1132
1039
 
1133
- this.handleCopyHelper(
1134
- fullCellText,
1135
- fullJson,
1136
- `Selected cell${Object.values(reduxFormSelectedCells).length === 1 ? "" : "s"} copied`
1137
- );
1040
+ this.handleCopyHelper(fullCellText, fullJson, "Selected cells copied");
1138
1041
  };
1139
1042
 
1140
- handleCopySelectedRows = (selectedRecords, e, opts) => {
1141
- const { entities = [] } = this.props;
1043
+ handleCopySelectedRows = (selectedRecords, e) => {
1044
+ const { entities = [] } = computePresets(this.props);
1142
1045
  const idToIndex = entities.reduce((acc, e, i) => {
1143
1046
  acc[e.id || e.code] = i;
1144
1047
  return acc;
@@ -1158,8 +1061,7 @@ class DataTable extends React.Component {
1158
1061
  const rowEls = rowNumbersToCopy.map(i => allRowEls[i]);
1159
1062
 
1160
1063
  this.handleCopyRows(rowEls, {
1161
- onFinishMsg: "Selected rows copied",
1162
- ...opts
1064
+ onFinishMsg: "Selected rows copied"
1163
1065
  });
1164
1066
  } catch (error) {
1165
1067
  console.error(`error:`, error);
@@ -1198,7 +1100,7 @@ class DataTable extends React.Component {
1198
1100
  moveColumnPersist,
1199
1101
  syncDisplayOptionsToDb,
1200
1102
  change
1201
- } = this.props;
1103
+ } = computePresets(this.props);
1202
1104
  let moveColumnPersistToUse = moveColumnPersist;
1203
1105
  if (moveColumnPersist && withDisplayOptions && !syncDisplayOptionsToDb) {
1204
1106
  //little hack to make localstorage changes get reflected in UI (we force an update to get the enhancers to run again :)
@@ -1236,7 +1138,7 @@ class DataTable extends React.Component {
1236
1138
  ));
1237
1139
 
1238
1140
  addEntitiesToSelection = entities => {
1239
- const propPresets = this.props;
1141
+ const propPresets = computePresets(this.props);
1240
1142
  const { isEntityDisabled, reduxFormSelectedEntityIdMap } = propPresets;
1241
1143
  const idMap = reduxFormSelectedEntityIdMap || {};
1242
1144
  const newIdMap = cloneDeep(idMap) || {};
@@ -1254,7 +1156,7 @@ class DataTable extends React.Component {
1254
1156
 
1255
1157
  render() {
1256
1158
  const { fullscreen } = this.state;
1257
- const propPresets = this.props;
1159
+ const propPresets = computePresets(this.props);
1258
1160
  const {
1259
1161
  extraClasses,
1260
1162
  className,
@@ -1577,13 +1479,16 @@ class DataTable extends React.Component {
1577
1479
  // if (isArrowKey && e.target?.tagName !== "INPUT") {
1578
1480
  const isTabKey = e.keyCode === 9;
1579
1481
  // const isEnter = e.keyCode === 13;
1482
+ // console.log(`onKeydown datatable inner`);
1483
+ // console.log(`isEnter:`, isEnter)
1580
1484
  const isArrowKey = e.keyCode >= 37 && e.keyCode <= 40;
1485
+ // console.log(`e.target?.tagName:`,e.target?.tagName)
1581
1486
  if (
1582
1487
  (isArrowKey && e.target?.tagName !== "INPUT") ||
1583
1488
  isTabKey
1584
1489
  // || (isEnter && e.target?.tagName === "INPUT")
1585
1490
  ) {
1586
- const { schema, entities } = this.props;
1491
+ const { schema, entities } = computePresets(this.props);
1587
1492
  const left = e.keyCode === 37;
1588
1493
  const up = e.keyCode === 38;
1589
1494
  const down = e.keyCode === 40 || e.keyCode === 13;
@@ -1681,8 +1586,7 @@ class DataTable extends React.Component {
1681
1586
  const rowDisabled = isEntityDisabled(entity);
1682
1587
  const isNum = e.keyCode >= 48 && e.keyCode <= 57;
1683
1588
  const isLetter = e.keyCode >= 65 && e.keyCode <= 90;
1684
- const isEqlSign = e.keyCode === 187;
1685
- if (!isNum && !isLetter && !isEqlSign) return;
1589
+ if (!isNum && !isLetter) return;
1686
1590
  if (rowDisabled) return;
1687
1591
  this.startCellEdit(cellId, { shouldSelectAll: true });
1688
1592
  e.stopPropagation();
@@ -1818,7 +1722,7 @@ class DataTable extends React.Component {
1818
1722
  finalizeSelection({
1819
1723
  idMap: {},
1820
1724
  entities,
1821
- props: this.props
1725
+ props: computePresets(this.props)
1822
1726
  });
1823
1727
  }}
1824
1728
  />
@@ -1977,7 +1881,7 @@ class DataTable extends React.Component {
1977
1881
  change,
1978
1882
  getRowClassName,
1979
1883
  isCellEditable
1980
- } = this.props;
1884
+ } = computePresets(this.props);
1981
1885
  if (!rowInfo) {
1982
1886
  return {
1983
1887
  className: "no-row-data"
@@ -2009,7 +1913,7 @@ class DataTable extends React.Component {
2009
1913
  if (e.detail > 1) {
2010
1914
  return; //cancel multiple quick clicks
2011
1915
  }
2012
- rowClick(e, rowInfo, entities, this.props);
1916
+ rowClick(e, rowInfo, entities, computePresets(this.props));
2013
1917
  },
2014
1918
  //row right click
2015
1919
  onContextMenu: e => {
@@ -2036,7 +1940,7 @@ class DataTable extends React.Component {
2036
1940
  finalizeSelection({
2037
1941
  idMap: newIdMap,
2038
1942
  entities,
2039
- props: this.props
1943
+ props: computePresets(this.props)
2040
1944
  });
2041
1945
  }
2042
1946
  this.showContextMenu(e, newIdMap);
@@ -2066,7 +1970,7 @@ class DataTable extends React.Component {
2066
1970
  change,
2067
1971
  reduxFormSelectedCells = {},
2068
1972
  reduxFormEditingCell
2069
- } = this.props;
1973
+ } = computePresets(this.props);
2070
1974
  const newSelectedCells = { ...reduxFormSelectedCells };
2071
1975
  newSelectedCells[cellId] = PRIMARY_SELECTED_VAL;
2072
1976
  //check if the cell is already selected and editing and if so, don't change it
@@ -2090,7 +1994,7 @@ class DataTable extends React.Component {
2090
1994
  reduxFormSelectedCells = {},
2091
1995
  isEntityDisabled,
2092
1996
  change
2093
- } = this.props;
1997
+ } = computePresets(this.props);
2094
1998
  if (!isCellEditable) return {}; //only allow cell selection to do stuff here
2095
1999
  if (!rowInfo) return {};
2096
2000
  const entity = rowInfo.original;
@@ -2102,7 +2006,8 @@ class DataTable extends React.Component {
2102
2006
  cellIdToRight,
2103
2007
  cellIdBelow,
2104
2008
  cellIdToLeft,
2105
- rowDisabled
2009
+ rowDisabled,
2010
+ columnIndex
2106
2011
  } = getCellInfo({
2107
2012
  columnIndex: column.index,
2108
2013
  columnPath: column.path,
@@ -2122,18 +2027,18 @@ class DataTable extends React.Component {
2122
2027
  selectedRightBorder,
2123
2028
  selectedBottomBorder,
2124
2029
  selectedLeftBorder;
2125
- const isSelected = reduxFormSelectedCells[cellId];
2126
- if (isSelected) {
2030
+ if (reduxFormSelectedCells[cellId]) {
2127
2031
  selectedTopBorder = !reduxFormSelectedCells[cellIdAbove];
2128
2032
  selectedRightBorder = !reduxFormSelectedCells[cellIdToRight];
2129
2033
  selectedBottomBorder = !reduxFormSelectedCells[cellIdBelow];
2130
2034
  selectedLeftBorder = !reduxFormSelectedCells[cellIdToLeft];
2131
2035
  }
2132
- const isPrimarySelected = isSelected === PRIMARY_SELECTED_VAL;
2036
+ const isPrimarySelected =
2037
+ reduxFormSelectedCells[cellId] === PRIMARY_SELECTED_VAL;
2133
2038
  const className = classNames({
2134
- isSelectedCell: isSelected,
2039
+ isSelectedCell: reduxFormSelectedCells[cellId],
2135
2040
  isPrimarySelected,
2136
- isSecondarySelected: isSelected === true,
2041
+ isSecondarySelected: reduxFormSelectedCells[cellId] === true,
2137
2042
  noSelectedTopBorder: !selectedTopBorder,
2138
2043
  isCleanRow: _isClean,
2139
2044
  noSelectedRightBorder: !selectedRightBorder,
@@ -2142,12 +2047,8 @@ class DataTable extends React.Component {
2142
2047
  isDropdownCell: column.type === "dropdown",
2143
2048
  isEditingCell: reduxFormEditingCell === cellId,
2144
2049
  hasCellError: !!err,
2145
- "no-data-tip": isSelected
2050
+ "no-data-tip": reduxFormSelectedCells[cellId]
2146
2051
  });
2147
- const clickProps = {
2148
- isRowIndexColumn: column.isRowIndexColumn,
2149
- cellId
2150
- };
2151
2052
  return {
2152
2053
  onDoubleClick: () => {
2153
2054
  // cell double click
@@ -2159,12 +2060,7 @@ class DataTable extends React.Component {
2159
2060
  "data-no-child-data-tip": true
2160
2061
  }),
2161
2062
  onContextMenu: e => {
2162
- if (!isSelected) {
2163
- this.handleCellClick({
2164
- event: e,
2165
- ...clickProps
2166
- });
2167
- } else if (!isPrimarySelected) {
2063
+ if (!isPrimarySelected) {
2168
2064
  const primaryCellId = this.getPrimarySelectedCellId();
2169
2065
  const newSelectedCells = { ...reduxFormSelectedCells };
2170
2066
  if (primaryCellId) {
@@ -2181,14 +2077,17 @@ class DataTable extends React.Component {
2181
2077
  onClick: event => {
2182
2078
  this.handleCellClick({
2183
2079
  event,
2184
- ...clickProps
2080
+ cellId,
2081
+ rowDisabled,
2082
+ rowIndex,
2083
+ columnIndex
2185
2084
  });
2186
2085
  },
2187
2086
  className
2188
2087
  };
2189
2088
  };
2190
2089
 
2191
- handleCellClick = ({ event, cellId, isRowIndexColumn }) => {
2090
+ handleCellClick = ({ event, cellId }) => {
2192
2091
  if (!cellId) return;
2193
2092
  // cell click, cellclick
2194
2093
  const {
@@ -2198,7 +2097,7 @@ class DataTable extends React.Component {
2198
2097
  reduxFormEditingCell,
2199
2098
  reduxFormSelectedCells = {},
2200
2099
  isEntityDisabled
2201
- } = this.props;
2100
+ } = computePresets(this.props);
2202
2101
  const [rowId, cellPath] = cellId.split(":");
2203
2102
  const entityMap = getEntityIdToEntity(entities);
2204
2103
  const { e: entity, i: rowIndex } = entityMap[rowId];
@@ -2207,36 +2106,10 @@ class DataTable extends React.Component {
2207
2106
  const rowDisabled = isEntityDisabled(entity);
2208
2107
 
2209
2108
  if (rowDisabled) return;
2210
-
2211
2109
  let newSelectedCells = {
2212
2110
  ...reduxFormSelectedCells
2213
2111
  };
2214
- if (isRowIndexColumn) {
2215
- // it's like the whole row is being selected
2216
- let isThereAnUnselectedCell = false;
2217
- const allCellsInRow = {};
2218
- schema.fields.forEach(f => {
2219
- const toSelectId = `${rowId}:${f.path}`;
2220
- if (!reduxFormSelectedCells[toSelectId]) {
2221
- isThereAnUnselectedCell = true;
2222
- }
2223
- allCellsInRow[toSelectId] = true;
2224
- });
2225
- if (event.metaKey || event.shiftKey) {
2226
- if (isThereAnUnselectedCell) {
2227
- newSelectedCells = {
2228
- ...newSelectedCells,
2229
- ...allCellsInRow
2230
- };
2231
- } else {
2232
- forEach(allCellsInRow, (c, key) => {
2233
- delete newSelectedCells[key];
2234
- });
2235
- }
2236
- } else {
2237
- newSelectedCells = allCellsInRow;
2238
- }
2239
- } else if (newSelectedCells[cellId] && !event.shiftKey) {
2112
+ if (newSelectedCells[cellId] && !event.shiftKey) {
2240
2113
  // don't deselect if editing
2241
2114
  if (reduxFormEditingCell === cellId) return;
2242
2115
  if (event.metaKey) {
@@ -2313,7 +2186,7 @@ class DataTable extends React.Component {
2313
2186
  noUserSelect,
2314
2187
  entities,
2315
2188
  isEntityDisabled
2316
- } = this.props;
2189
+ } = computePresets(this.props);
2317
2190
  const checkedRows = getSelectedRowsFromEntities(
2318
2191
  entities,
2319
2192
  reduxFormSelectedEntityIdMap
@@ -2353,7 +2226,7 @@ class DataTable extends React.Component {
2353
2226
  finalizeSelection({
2354
2227
  idMap: newIdMap,
2355
2228
  entities,
2356
- props: this.props
2229
+ props: computePresets(this.props)
2357
2230
  });
2358
2231
  }}
2359
2232
  /* eslint-enable react/jsx-no-bind */
@@ -2370,7 +2243,7 @@ class DataTable extends React.Component {
2370
2243
  noUserSelect,
2371
2244
  entities,
2372
2245
  isEntityDisabled
2373
- } = this.props;
2246
+ } = computePresets(this.props);
2374
2247
  const checkedRows = getSelectedRowsFromEntities(
2375
2248
  entities,
2376
2249
  reduxFormSelectedEntityIdMap
@@ -2387,7 +2260,7 @@ class DataTable extends React.Component {
2387
2260
  <Checkbox
2388
2261
  disabled={noSelect || noUserSelect || isEntityDisabled(entity)}
2389
2262
  onClick={e => {
2390
- rowClick(e, row, entities, this.props);
2263
+ rowClick(e, row, entities, computePresets(this.props));
2391
2264
  }}
2392
2265
  checked={isSelected}
2393
2266
  />
@@ -2399,11 +2272,8 @@ class DataTable extends React.Component {
2399
2272
  entities = [],
2400
2273
  change,
2401
2274
  schema,
2402
- reduxFormCellValidation,
2403
- allowFormulas
2404
- } = this.props;
2405
- const updateGroup = {};
2406
-
2275
+ reduxFormCellValidation
2276
+ } = computePresets(this.props);
2407
2277
  const [rowId, path] = cellId.split(":");
2408
2278
  !doNotStopEditing && change("reduxFormEditingCell", null);
2409
2279
  this.updateEntitiesHelper(entities, entities => {
@@ -2411,33 +2281,22 @@ class DataTable extends React.Component {
2411
2281
  return getIdOrCodeOrIndex(e, i) === rowId;
2412
2282
  });
2413
2283
  delete entity._isClean;
2414
- const { errors } = editCellHelper({
2415
- allowFormulas,
2416
- updateGroup,
2417
- depGraph: this.depGraph,
2418
- entities,
2284
+ const { error } = editCellHelper({
2419
2285
  entity,
2420
2286
  path,
2421
2287
  schema,
2422
2288
  newVal
2423
2289
  });
2424
- this.buildDepGraph(entities);
2425
2290
  this.updateValidation(entities, {
2426
2291
  ...reduxFormCellValidation,
2427
- ...errors
2292
+ [cellId]: error
2428
2293
  });
2429
2294
  });
2430
- setTimeout(() => {
2431
- // do not try to refocus the table if another cell has already been selected
2432
- const isCellIdStillSelected = this.props.reduxFormSelectedCells[cellId];
2433
- if (isCellIdStillSelected) {
2434
- !doNotStopEditing && this.refocusTable();
2435
- }
2436
- }, 0);
2295
+ !doNotStopEditing && this.refocusTable();
2437
2296
  };
2438
2297
 
2439
2298
  cancelCellEdit = () => {
2440
- const { change } = this.props;
2299
+ const { change } = computePresets(this.props);
2441
2300
  change("reduxFormEditingCell", null);
2442
2301
  this.refocusTable();
2443
2302
  };
@@ -2451,7 +2310,9 @@ class DataTable extends React.Component {
2451
2310
  };
2452
2311
 
2453
2312
  isSelectionARectangle = () => {
2454
- const { entities, reduxFormSelectedCells, schema } = this.props;
2313
+ const { entities, reduxFormSelectedCells, schema } = computePresets(
2314
+ this.props
2315
+ );
2455
2316
  if (
2456
2317
  reduxFormSelectedCells &&
2457
2318
  Object.keys(reduxFormSelectedCells).length > 1
@@ -2531,7 +2392,6 @@ class DataTable extends React.Component {
2531
2392
  isCellEditable,
2532
2393
  cellRenderer,
2533
2394
  withCheckboxes,
2534
- allowFormulas,
2535
2395
  SubComponent,
2536
2396
  shouldShowSubComponent,
2537
2397
  entities,
@@ -2543,7 +2403,7 @@ class DataTable extends React.Component {
2543
2403
  change,
2544
2404
  reduxFormSelectedCells,
2545
2405
  reduxFormEditingCell
2546
- } = this.props;
2406
+ } = computePresets(this.props);
2547
2407
  const { columns } = this.state;
2548
2408
  if (!columns.length) {
2549
2409
  return columns;
@@ -2606,88 +2466,6 @@ class DataTable extends React.Component {
2606
2466
  }
2607
2467
  });
2608
2468
  }
2609
- if (allowFormulas) {
2610
- columnsToRender.push({
2611
- isRowIndexColumn: true,
2612
- Header: () => {
2613
- return (
2614
- <InfoHelper
2615
- content="Formulas"
2616
- isButton
2617
- minimal
2618
- small
2619
- style={{ padding: 2 }}
2620
- popoverProps={{
2621
- modifiers: {
2622
- preventOverflow: { enabled: false },
2623
- hide: { enabled: false }
2624
- }
2625
- }}
2626
- onClick={() => {
2627
- showConfirmationDialog({
2628
- text: (
2629
- <div
2630
- style={{
2631
- padding: 10,
2632
- width: 500,
2633
- overflow: "auto"
2634
- }}
2635
- >
2636
- <h3>Formulas</h3>
2637
- <div>
2638
- <p>
2639
- Formulas are supported in the following columns:
2640
- <ul>
2641
- {columns.map((c, i) => {
2642
- if (c.allowFormulas) {
2643
- return <li>{this.renderColumnHeader(c, i)}</li>;
2644
- }
2645
- return null;
2646
- })}
2647
- </ul>
2648
- </p>
2649
- </div>
2650
- </div>
2651
- ),
2652
- confirmButtonText: "Ok",
2653
- noCancelButton: true,
2654
- canOutsideClickClose: true,
2655
- canEscapeKeyClose: true
2656
- });
2657
- }}
2658
- // className={classNames("tg-expander-all")}
2659
- icon="help"
2660
- />
2661
- );
2662
- },
2663
- Cell: props => {
2664
- return (
2665
- <div
2666
- style={{
2667
- display: "flex",
2668
- justifyContent: "center",
2669
- width: "100%"
2670
- }}
2671
- >
2672
- {props.index + 1}
2673
- </div>
2674
- );
2675
- },
2676
- width: 35,
2677
- resizable: false,
2678
- getHeaderProps: () => {
2679
- return {
2680
- className: "tg-react-table-checkbox-header-container",
2681
- immovable: "true"
2682
- };
2683
- },
2684
- getProps: (p, b) => {
2685
- return {
2686
- className: `tg-row-index-${b.index}`
2687
- };
2688
- }
2689
- });
2690
- }
2691
2469
 
2692
2470
  if (withCheckboxes) {
2693
2471
  columnsToRender.push({
@@ -2709,10 +2487,10 @@ class DataTable extends React.Component {
2709
2487
  });
2710
2488
  }
2711
2489
 
2712
- columns.forEach((column, i) => {
2490
+ columns.forEach(column => {
2713
2491
  const tableColumn = {
2714
2492
  ...column,
2715
- Header: this.renderColumnHeader(column, i),
2493
+ Header: this.renderColumnHeader(column),
2716
2494
  accessor: column.path,
2717
2495
  getHeaderProps: () => ({
2718
2496
  // needs to be a string because it is getting passed
@@ -2735,17 +2513,6 @@ class DataTable extends React.Component {
2735
2513
  );
2736
2514
  return val;
2737
2515
  };
2738
- } else if (column.allowFormulas) {
2739
- tableColumn.Cell = row => {
2740
- const val = row.value;
2741
-
2742
- if (!val) return "";
2743
- if (typeof val === "number") return val;
2744
- if (val.formula) {
2745
- return val.value;
2746
- }
2747
- return val;
2748
- };
2749
2516
  } else if (column.render) {
2750
2517
  tableColumn.Cell = row => {
2751
2518
  const val = column.render(row.value, row.original, row, this.props);
@@ -2799,20 +2566,14 @@ class DataTable extends React.Component {
2799
2566
  const [row] = args;
2800
2567
  const rowId = getIdOrCodeOrIndex(row.original, row.index);
2801
2568
  const cellId = `${rowId}:${row.column.path}`;
2802
- const alphaNum = getCellAlphaNumHelper(i, row.index);
2803
2569
  let val = oldFunc(...args);
2804
2570
  const oldVal = val;
2805
2571
  const text = this.getCopyTextForCell(val, row, column);
2806
2572
  const isBool = column.type === "boolean";
2807
- const fullValue = row.original?.[row.column.path];
2808
2573
  const dataTest = {
2809
- "data-column": column.path,
2810
- "data-test": "tgCell_" + column.path,
2811
- "data-cell-alpha": alphaNum,
2812
- ...(fullValue?.formula && {
2813
- "data-formula": fullValue.formula
2814
- })
2574
+ "data-test": "tgCell_" + column.path
2815
2575
  };
2576
+ const fullValue = row.original?.[row.column.path];
2816
2577
  if (isCellEditable && isBool) {
2817
2578
  val = (
2818
2579
  <Checkbox
@@ -2873,7 +2634,7 @@ class DataTable extends React.Component {
2873
2634
  shouldSelectAll={reduxFormEditingCellSelectAll}
2874
2635
  cancelEdit={this.cancelCellEdit}
2875
2636
  isNumeric={column.type === "number"}
2876
- initialValue={fullValue?.formula || text}
2637
+ initialValue={text}
2877
2638
  finishEdit={newVal => {
2878
2639
  this.finishCellEdit(cellId, newVal);
2879
2640
  }}
@@ -2923,9 +2684,7 @@ class DataTable extends React.Component {
2923
2684
  __strVal: fullValue,
2924
2685
  __genSelCol: column.path
2925
2686
  }
2926
- : allowFormulas
2927
- ? { __strVal: fullValue }
2928
- : { __strVal: text }
2687
+ : { __strVal: text }
2929
2688
  )}
2930
2689
  title={title || undefined}
2931
2690
  >
@@ -3003,8 +2762,7 @@ class DataTable extends React.Component {
3003
2762
  schema,
3004
2763
  reduxFormCellValidation,
3005
2764
  change,
3006
- reduxFormSelectedCells,
3007
- allowFormulas
2765
+ reduxFormSelectedCells
3008
2766
  } = this.props;
3009
2767
  const primaryCellId = this.getPrimarySelectedCellId();
3010
2768
  const [primaryRowId, primaryCellPath] = primaryCellId.split(":");
@@ -3014,8 +2772,7 @@ class DataTable extends React.Component {
3014
2772
  if (!allSelectedPaths) {
3015
2773
  allSelectedPaths = [primaryCellPath];
3016
2774
  }
3017
- const updateGroup = {};
3018
- const prevEnts = entities;
2775
+
3019
2776
  this.updateEntitiesHelper(entities, entities => {
3020
2777
  let newReduxFormSelectedCells;
3021
2778
  if (selectedPaths) {
@@ -3028,11 +2785,10 @@ class DataTable extends React.Component {
3028
2785
  };
3029
2786
  }
3030
2787
 
3031
- let newCellValidate = {
2788
+ const newCellValidate = {
3032
2789
  ...reduxFormCellValidation
3033
2790
  };
3034
- const entityMap = getEntityIdToEntity(prevEnts);
3035
- const updateAbleEntityMap = getEntityIdToEntity(entities);
2791
+ const entityMap = getEntityIdToEntity(entities);
3036
2792
  const { e: selectedEnt } = entityMap[primaryRowId];
3037
2793
  const firstCellToSelectRowIndex =
3038
2794
  entityMap[cellsToSelect[0]?.split(":")[0]]?.i;
@@ -3081,8 +2837,7 @@ class DataTable extends React.Component {
3081
2837
  }
3082
2838
  if (incrementStart === undefined) {
3083
2839
  const draggingDown =
3084
- firstCellToSelectRowIndex >
3085
- selectionGrid?.[0]?.[cellIndexOfSelectedPath]?.rowIndex;
2840
+ firstCellToSelectRowIndex > selectionGrid?.[0][0].rowIndex;
3086
2841
  if (selectedPaths && draggingDown) {
3087
2842
  let checkIncrement;
3088
2843
  let prefix;
@@ -3148,8 +2903,7 @@ class DataTable extends React.Component {
3148
2903
  const [rowId, cellPath] = cellId.split(":");
3149
2904
  if (cellPath !== selectedPath) return;
3150
2905
  newReduxFormSelectedCells[cellId] = true;
3151
- const { e: entityToUpdate, i: rowIndex } =
3152
- updateAbleEntityMap[rowId] || {};
2906
+ const { e: entityToUpdate, i: rowIndex } = entityMap[rowId] || {};
3153
2907
  if (entityToUpdate) {
3154
2908
  delete entityToUpdate._isClean;
3155
2909
  let newVal;
@@ -3189,31 +2943,24 @@ class DataTable extends React.Component {
3189
2943
  newVal = selectedCellVal;
3190
2944
  }
3191
2945
  }
3192
- const { errors } = editCellHelper({
3193
- allowFormulas,
3194
- updateGroup,
3195
- depGraph: this.depGraph,
3196
- entities,
2946
+ const { error } = editCellHelper({
3197
2947
  entity: entityToUpdate,
3198
2948
  path: cellPath,
3199
2949
  schema,
3200
2950
  newVal
3201
2951
  });
3202
- newCellValidate = {
3203
- ...newCellValidate,
3204
- ...errors
3205
- };
2952
+ newCellValidate[cellId] = error;
3206
2953
  }
3207
2954
  });
3208
2955
  });
3209
- this.buildDepGraph(entities);
2956
+
3210
2957
  // select the new cells
3211
2958
  this.updateValidation(entities, newCellValidate);
3212
2959
  change("reduxFormSelectedCells", newReduxFormSelectedCells);
3213
2960
  });
3214
2961
  };
3215
2962
  getCopyTextForCell = (val, row = {}, column = {}) => {
3216
- const { cellRenderer } = this.props;
2963
+ const { cellRenderer } = computePresets(this.props);
3217
2964
  // TODOCOPY we need a way to potentially omit certain columns from being added as a \t element (talk to taoh about this)
3218
2965
  let text = typeof val !== "string" ? row.value : val;
3219
2966
 
@@ -3265,7 +3012,9 @@ class DataTable extends React.Component {
3265
3012
  };
3266
3013
 
3267
3014
  addEditableTableEntities = incomingEnts => {
3268
- const { entities = [], reduxFormCellValidation } = this.props;
3015
+ const { entities = [], reduxFormCellValidation } = computePresets(
3016
+ this.props
3017
+ );
3269
3018
 
3270
3019
  this.updateEntitiesHelper(entities, entities => {
3271
3020
  const newEntities = incomingEnts.map(e => ({
@@ -3288,7 +3037,7 @@ class DataTable extends React.Component {
3288
3037
  } else {
3289
3038
  entities.splice(entities.length, 0, ...newEnts);
3290
3039
  }
3291
- this.buildDepGraph(entities);
3040
+
3292
3041
  this.updateValidation(entities, {
3293
3042
  ...reduxFormCellValidation,
3294
3043
  ...validationErrors
@@ -3296,7 +3045,8 @@ class DataTable extends React.Component {
3296
3045
  });
3297
3046
  };
3298
3047
  getEditableTableInfoAndThrowFormError = () => {
3299
- const { schema, reduxFormEntities, reduxFormCellValidation } = this.props;
3048
+ const { schema, reduxFormEntities, reduxFormCellValidation } =
3049
+ computePresets(this.props);
3300
3050
  const { entsToUse, validationToUse } = removeCleanRows(
3301
3051
  reduxFormEntities,
3302
3052
  reduxFormCellValidation
@@ -3325,11 +3075,9 @@ class DataTable extends React.Component {
3325
3075
  };
3326
3076
 
3327
3077
  insertRows = ({ above, numRows = 1, appendToBottom } = {}) => {
3328
- const {
3329
- entities = [],
3330
- reduxFormCellValidation,
3331
- allowFormulas
3332
- } = this.props;
3078
+ const { entities = [], reduxFormCellValidation } = computePresets(
3079
+ this.props
3080
+ );
3333
3081
 
3334
3082
  const primaryCellId = this.getPrimarySelectedCellId();
3335
3083
  const [rowId] = primaryCellId?.split(":") || [];
@@ -3341,50 +3089,6 @@ class DataTable extends React.Component {
3341
3089
  });
3342
3090
  const insertIndex = above ? indexToInsert : indexToInsert + 1;
3343
3091
  const insertIndexToUse = appendToBottom ? entities.length : insertIndex;
3344
- let { newEnts, validationErrors } = this.formatAndValidateEntities(
3345
- newEntities,
3346
- {
3347
- useDefaultValues: true,
3348
- indexToStartAt: insertIndexToUse,
3349
- depGraphToUse: {}
3350
- }
3351
- );
3352
-
3353
- newEnts = newEnts.map(e => ({
3354
- ...e,
3355
- _isClean: true
3356
- }));
3357
- allowFormulas &&
3358
- updateEntityFormulasToInsertDelete({
3359
- entities,
3360
- insertIndex: insertIndexToUse,
3361
- numEnts: newEnts.length
3362
- });
3363
-
3364
- this.updateValidation(entities, {
3365
- ...reduxFormCellValidation,
3366
- ...validationErrors
3367
- });
3368
- // we need to make sure any entities with formulas are updated
3369
-
3370
- entities.splice(insertIndexToUse, 0, ...newEnts);
3371
- this.buildDepGraph(entities);
3372
- });
3373
- this.refocusTable();
3374
- };
3375
- insertColumns = ({ toTheLeft, numColumns = 1, appendToEnd } = {}) => {
3376
- const { entities = [], reduxFormCellValidation } = this.props;
3377
-
3378
- const primaryCellId = this.getPrimarySelectedCellId();
3379
- const [rowId] = primaryCellId?.split(":") || [];
3380
- this.updateEntitiesHelper(entities, entities => {
3381
- const newEntities = times(numColumns).map(() => ({ id: nanoid() }));
3382
-
3383
- const indexToInsert = entities.findIndex((e, i) => {
3384
- return getIdOrCodeOrIndex(e, i) === rowId;
3385
- });
3386
- const insertIndex = toTheLeft ? indexToInsert : indexToInsert + 1;
3387
- const insertIndexToUse = appendToEnd ? entities.length : insertIndex;
3388
3092
  let { newEnts, validationErrors } = this.formatAndValidateEntities(
3389
3093
  newEntities,
3390
3094
  {
@@ -3412,11 +3116,10 @@ class DataTable extends React.Component {
3412
3116
  history,
3413
3117
  contextMenu,
3414
3118
  isCopyable,
3415
- allowFormulas,
3416
3119
  isCellEditable,
3417
3120
  entities = [],
3418
3121
  reduxFormSelectedCells = {}
3419
- } = this.props;
3122
+ } = computePresets(this.props);
3420
3123
  let selectedRecords;
3421
3124
  if (isCellEditable) {
3422
3125
  const rowIds = {};
@@ -3443,44 +3146,43 @@ class DataTable extends React.Component {
3443
3146
  e.target.querySelector(".tg-cell-wrapper") ||
3444
3147
  e.target.closest(".tg-cell-wrapper");
3445
3148
  if (cellWrapper) {
3446
- copyMenuItems.push(opts => (
3149
+ copyMenuItems.push(
3447
3150
  <MenuItem
3448
3151
  key="copyCell"
3449
3152
  onClick={() => {
3450
3153
  //TODOCOPY: we need to make sure that the cell copy is being used by the row copy.. right now we have 2 different things going on
3451
3154
  //do we need to be able to copy hidden cells? It seems like it should just copy what's on the page..?
3452
- this.handleCopySelectedCells(e, opts);
3155
+ const specificColumn = cellWrapper.getAttribute("data-test");
3156
+ this.handleCopyRows([cellWrapper.closest(".rt-tr")], {
3157
+ specificColumn,
3158
+ onFinishMsg: "Cell copied"
3159
+ });
3160
+ const [text, jsonText] = this.getCellCopyText(cellWrapper);
3161
+ this.handleCopyHelper(text, jsonText);
3453
3162
  }}
3454
- text={`Cell${
3455
- Object.keys(reduxFormSelectedCells).length > 1 ? "s" : ""
3456
- }`}
3163
+ text="Cell"
3457
3164
  />
3458
- ));
3165
+ );
3459
3166
 
3460
- copyMenuItems.push(opts => (
3167
+ copyMenuItems.push(
3461
3168
  <MenuItem
3462
3169
  key="copyColumn"
3463
3170
  onClick={() => {
3464
- this.handleCopyColumn({ e, cellWrapper, opts });
3171
+ this.handleCopyColumn(e, cellWrapper);
3465
3172
  }}
3466
- text={selectedRecords.length > 1 ? "Single Column" : "Column"}
3173
+ text="Column"
3467
3174
  />
3468
- ));
3175
+ );
3469
3176
  if (selectedRecords.length > 1) {
3470
- copyMenuItems.push(opts => (
3177
+ copyMenuItems.push(
3471
3178
  <MenuItem
3472
3179
  key="copyColumnSelected"
3473
3180
  onClick={() => {
3474
- this.handleCopyColumn({
3475
- e,
3476
- cellWrapper,
3477
- selectedRecords,
3478
- opts
3479
- });
3181
+ this.handleCopyColumn(e, cellWrapper, selectedRecords);
3480
3182
  }}
3481
- text="Selected Columns"
3183
+ text="Column (Selected)"
3482
3184
  />
3483
- ));
3185
+ );
3484
3186
  }
3485
3187
  }
3486
3188
  if (selectedRecords.length === 0 || selectedRecords.length === 1) {
@@ -3490,48 +3192,38 @@ class DataTable extends React.Component {
3490
3192
  e.target.closest(".tg-cell-wrapper") ||
3491
3193
  e.target.closest(".rt-td");
3492
3194
  const row = cell.closest(".rt-tr");
3493
- copyMenuItems.push(opts => (
3195
+ copyMenuItems.push(
3494
3196
  <MenuItem
3495
3197
  key="copySelectedRows"
3496
3198
  onClick={() => {
3497
- this.handleCopyRows([row], opts);
3199
+ this.handleCopyRows([row]);
3498
3200
  // loop through each cell in the row
3499
3201
  }}
3500
3202
  text="Row"
3501
3203
  />
3502
- ));
3204
+ );
3503
3205
  } else if (selectedRecords.length > 1) {
3504
- copyMenuItems.push(opts => (
3206
+ copyMenuItems.push(
3505
3207
  <MenuItem
3506
3208
  key="copySelectedRows"
3507
3209
  onClick={() => {
3508
- this.handleCopySelectedRows(selectedRecords, e, opts);
3210
+ this.handleCopySelectedRows(selectedRecords, e);
3509
3211
  // loop through each cell in the row
3510
3212
  }}
3511
3213
  text="Rows"
3512
3214
  />
3513
- ));
3215
+ );
3514
3216
  }
3515
- copyMenuItems.push(opts => (
3217
+ copyMenuItems.push(
3516
3218
  <MenuItem
3517
3219
  key="copyFullTableRows"
3518
3220
  onClick={() => {
3519
- this.handleCopyTable(e, opts);
3221
+ this.handleCopyTable(e);
3520
3222
  // loop through each cell in the row
3521
3223
  }}
3522
3224
  text="Table"
3523
3225
  />
3524
- ));
3525
- copyMenuItems.push(opts => (
3526
- <MenuItem
3527
- key="copyFullTableRowsNoHeader"
3528
- onClick={() => {
3529
- this.handleCopyTable(e, { ...opts, noHeader: true });
3530
- // loop through each cell in the row
3531
- }}
3532
- text="Table Without Header"
3533
- />
3534
- ));
3226
+ );
3535
3227
  }
3536
3228
  const selectedRowIds = Object.keys(reduxFormSelectedCells).map(cellId => {
3537
3229
  const [rowId] = cellId.split(":");
@@ -3543,39 +3235,11 @@ class DataTable extends React.Component {
3543
3235
  {itemsToRender}
3544
3236
  {copyMenuItems.length && (
3545
3237
  <MenuItem icon="clipboard" key="copyOpts" text="Copy">
3546
- {copyMenuItems.map(f => f())}
3238
+ {copyMenuItems}
3547
3239
  </MenuItem>
3548
3240
  )}
3549
- {copyMenuItems.length && allowFormulas && (
3550
- <MenuItem
3551
- data-tip="This will copy the underlying formula (if there are any) instead of the evaluated value"
3552
- icon="clipboard"
3553
- key="copyOptsFormulas"
3554
- text="Copy Formula"
3555
- >
3556
- {copyMenuItems.map(f => f({ isFormulaCopy: true }))}
3557
- </MenuItem>
3558
- )}
3559
- <Divider></Divider>
3560
3241
  {isCellEditable && (
3561
3242
  <>
3562
- <MenuItem
3563
- icon="add-column-left"
3564
- text="Add Column Left"
3565
- key="addColumnLeft"
3566
- onClick={() => {
3567
- this.insertColumns({ toTheLeft: true });
3568
- }}
3569
- ></MenuItem>
3570
- <MenuItem
3571
- icon="add-column-right"
3572
- text="Add Column Right"
3573
- key="addColumnRight"
3574
- onClick={() => {
3575
- this.insertColumns({});
3576
- }}
3577
- ></MenuItem>
3578
- <Divider></Divider>
3579
3243
  <MenuItem
3580
3244
  icon="add-row-top"
3581
3245
  text="Add Row Above"
@@ -3594,15 +3258,14 @@ class DataTable extends React.Component {
3594
3258
  ></MenuItem>
3595
3259
  <MenuItem
3596
3260
  icon="remove"
3597
- text={`Remove Row${uniq(selectedRowIds).length > 1 ? "s" : ""}`}
3261
+ text={`Remove Row${selectedRowIds.length > 1 ? "s" : ""}`}
3598
3262
  key="removeRow"
3599
3263
  onClick={() => {
3600
3264
  const {
3601
3265
  entities = [],
3602
3266
  reduxFormCellValidation,
3603
- reduxFormSelectedCells = {},
3604
- allowFormulas
3605
- } = this.props;
3267
+ reduxFormSelectedCells = {}
3268
+ } = computePresets(this.props);
3606
3269
  const selectedRowIds = Object.keys(reduxFormSelectedCells).map(
3607
3270
  cellId => {
3608
3271
  const [rowId] = cellId.split(":");
@@ -3610,33 +3273,16 @@ class DataTable extends React.Component {
3610
3273
  }
3611
3274
  );
3612
3275
  this.updateEntitiesHelper(entities, entities => {
3613
- const deleteIndices = uniq(
3614
- selectedRowIds
3615
- .map(
3616
- id =>
3617
- entities.findIndex(
3618
- (e, i) => getIdOrCodeOrIndex(e, i) === id
3619
- ) + 1
3620
- )
3621
- .sort((a, b) => a - b)
3276
+ const ents = entities.filter(
3277
+ (e, i) => !selectedRowIds.includes(getIdOrCodeOrIndex(e, i))
3622
3278
  );
3623
- allowFormulas &&
3624
- updateEntityFormulasToInsertDelete({
3625
- entities,
3626
- deleteIndices
3627
- });
3628
-
3629
- deleteIndices.reverse().forEach(indexToRemove => {
3630
- entities.splice(indexToRemove - 1, 1);
3631
- });
3632
- this.buildDepGraph(entities);
3633
3279
  this.updateValidation(
3634
- entities,
3280
+ ents,
3635
3281
  omitBy(reduxFormCellValidation, (v, cellId) =>
3636
3282
  selectedRowIds.includes(cellId.split(":")[0])
3637
3283
  )
3638
3284
  );
3639
- // return ents;
3285
+ return ents;
3640
3286
  });
3641
3287
  this.refocusTable();
3642
3288
  }}
@@ -3648,7 +3294,7 @@ class DataTable extends React.Component {
3648
3294
  ContextMenu.show(menu, { left: e.clientX, top: e.clientY });
3649
3295
  };
3650
3296
 
3651
- renderColumnHeader = (column, index) => {
3297
+ renderColumnHeader = column => {
3652
3298
  const {
3653
3299
  addFilters,
3654
3300
  setOrder,
@@ -3663,9 +3309,8 @@ class DataTable extends React.Component {
3663
3309
  compact,
3664
3310
  isCellEditable,
3665
3311
  extraCompact,
3666
- entities,
3667
- allowFormulas
3668
- } = this.props;
3312
+ entities
3313
+ } = computePresets(this.props);
3669
3314
  const {
3670
3315
  displayName,
3671
3316
  description,
@@ -3805,15 +3450,7 @@ class DataTable extends React.Component {
3805
3450
  }
3806
3451
 
3807
3452
  const columnTitleTextified = getTextFromEl(columnTitle);
3808
- let inner = renderTitleInner ? renderTitleInner : columnTitle;
3809
- const getLetterifiedColumnTitle = () => {
3810
- const letter = getColLetFromIndex(index);
3811
- if (inner?.toUpperCase() === letter) {
3812
- inner = letter;
3813
- return null;
3814
- }
3815
- return <div>{getColLetFromIndex(index)}:</div>;
3816
- };
3453
+
3817
3454
  return (
3818
3455
  <div
3819
3456
  {...(description && {
@@ -3821,7 +3458,6 @@ class DataTable extends React.Component {
3821
3458
  <strong>${columnTitle}:</strong> <br>
3822
3459
  ${description} ${isUnique ? "<br>Must be unique" : ""}</div>`
3823
3460
  })}
3824
- data-column={column.path}
3825
3461
  data-test={columnTitleTextified}
3826
3462
  data-path={path}
3827
3463
  data-copy-text={columnTitleTextified}
@@ -3836,7 +3472,6 @@ class DataTable extends React.Component {
3836
3472
  {columnTitleTextified && !noTitle && (
3837
3473
  <React.Fragment>
3838
3474
  {maybeCheckbox}
3839
- {allowFormulas && getLetterifiedColumnTitle()}
3840
3475
  <span
3841
3476
  title={columnTitleTextified}
3842
3477
  className={classNames({
@@ -3848,7 +3483,7 @@ class DataTable extends React.Component {
3848
3483
  display: "inline-block"
3849
3484
  }}
3850
3485
  >
3851
- {inner}{" "}
3486
+ {renderTitleInner ? renderTitleInner : columnTitle}{" "}
3852
3487
  </span>
3853
3488
  </React.Fragment>
3854
3489
  )}
@@ -4144,7 +3779,6 @@ function endsWithNumber(str) {
4144
3779
  }
4145
3780
 
4146
3781
  function getNumberStrAtEnd(str) {
4147
- if (typeof str !== "string") str = str.toString();
4148
3782
  if (endsWithNumber(str)) {
4149
3783
  return str.match(/[0-9]+$/)[0];
4150
3784
  }
@@ -4179,13 +3813,7 @@ const formatPasteData = ({ schema, newVal, path }) => {
4179
3813
  newVal = undefined;
4180
3814
  }
4181
3815
  } else {
4182
- newVal = Object.hasOwn(newVal, "__strVal")
4183
- ? newVal.__strVal?.formula
4184
- ? newVal.__strVal.formula
4185
- : newVal.__strVal
4186
- : isEmpty(newVal)
4187
- ? undefined
4188
- : newVal;
3816
+ newVal = Object.hasOwn(newVal, "__strVal") ? newVal.__strVal : newVal;
4189
3817
  }
4190
3818
  return newVal;
4191
3819
  };
@@ -4209,61 +3837,3 @@ export function removeCleanRows(reduxFormEntities, reduxFormCellValidation) {
4209
3837
  });
4210
3838
  return { entsToUse, validationToUse };
4211
3839
  }
4212
-
4213
- const updateEntityFormulasToInsertDelete = ({
4214
- entities,
4215
- deleteIndices,
4216
- insertIndex,
4217
- numEnts = 1
4218
- }) => {
4219
- const isInsert = !deleteIndices;
4220
- entities.forEach(e => {
4221
- Object.values(e).forEach(v => {
4222
- if (v?.formula) {
4223
- // update the formula to shift the row numbers up or down as needed
4224
- v.formula = v.formula.replace(/([A-Z]+[0-9]+)/gi, match => {
4225
- const letter = match.replace(/[0-9]+/gi, "");
4226
- // update the match number
4227
- const num = Number(match.replace(/[A-Z]+/gi, ""));
4228
- if (isInsert) {
4229
- if (num > insertIndex) {
4230
- // if the insert index is above the match number then we need to add 1 to the row number
4231
- const newNum = num + numEnts;
4232
- return `${letter}${newNum}`;
4233
- }
4234
- } else {
4235
- let newNum = num;
4236
- deleteIndices.forEach(i => {
4237
- if (num > i) {
4238
- newNum = num - 1;
4239
- }
4240
- });
4241
- return `${letter}${newNum}`;
4242
- }
4243
- return match;
4244
- });
4245
- v.formula = v.formula.replace(/([0-9]+:[0-9]+)/gi, match => {
4246
- const [num1, num2] = match.split(":");
4247
- if (num1 === num2) {
4248
- const num = Number(num1);
4249
- if (isInsert) {
4250
- if (num > insertIndex) {
4251
- const newNum = num + numEnts;
4252
- return `${newNum}:${newNum}`;
4253
- }
4254
- } else {
4255
- let newNum = num;
4256
- deleteIndices.forEach(i => {
4257
- if (num > i) {
4258
- newNum = num - 1;
4259
- }
4260
- });
4261
- return `${newNum}:${newNum}`;
4262
- }
4263
- }
4264
- return match;
4265
- });
4266
- }
4267
- });
4268
- });
4269
- };