@teselagen/ui 0.3.41 → 0.3.42

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.
@@ -427,13 +427,14 @@ class DataTable extends React.Component {
427
427
  };
428
428
  formatAndValidateTableInitial = () => {
429
429
  const {
430
- _origEntities: entities,
430
+ _origEntities,
431
+ entities,
431
432
  initialEntities,
432
433
  change,
433
434
  reduxFormCellValidation
434
435
  } = this.props;
435
436
  const { newEnts, validationErrors } = this.formatAndValidateEntities(
436
- initialEntities || entities
437
+ initialEntities || entities || _origEntities
437
438
  );
438
439
  change("reduxFormEntities", newEnts);
439
440
  const toKeep = {};
@@ -616,17 +617,39 @@ class DataTable extends React.Component {
616
617
  } else if (e.clipboardData && e.clipboardData.getData) {
617
618
  toPaste = e.clipboardData.getData("text/plain");
618
619
  }
619
- if (toPaste.includes(",")) {
620
- //try papaparsing it out as a csv if it contains commas
621
- try {
622
- const { data, errors } = papaparse.parse(toPaste, {
623
- header: false
620
+ const jsonToPaste = e.clipboardData.getData("application/json");
621
+ try {
622
+ const pastedJson = [];
623
+ JSON.parse(jsonToPaste).forEach(row => {
624
+ const newRow = [];
625
+ Object.values(row).forEach(cell => {
626
+ const cellVal = JSON.parse(cell);
627
+ newRow.push(cellVal);
624
628
  });
625
- if (data?.length && !errors?.length) {
626
- pasteData = data;
629
+ pastedJson.push(newRow);
630
+ });
631
+ pasteData = pastedJson;
632
+ // try to remove the header row if it exists
633
+ if (
634
+ pasteData[0] &&
635
+ pasteData[0][0] &&
636
+ pasteData[0][0].__isHeaderCell
637
+ ) {
638
+ pasteData = pasteData.slice(1);
639
+ }
640
+ } catch (e) {
641
+ if (toPaste.includes(",")) {
642
+ //try papaparsing it out as a csv if it contains commas
643
+ try {
644
+ const { data, errors } = papaparse.parse(toPaste, {
645
+ header: false
646
+ });
647
+ if (data?.length && !errors?.length) {
648
+ pasteData = data;
649
+ }
650
+ } catch (error) {
651
+ console.error(`error p982qhgpf9qh`, error);
627
652
  }
628
- } catch (error) {
629
- console.error(`error p982qhgpf9qh`, error);
630
653
  }
631
654
  }
632
655
  pasteData = pasteData.length ? pasteData : defaultParsePaste(toPaste);
@@ -643,13 +666,14 @@ class DataTable extends React.Component {
643
666
  const entityIdToEntity = getEntityIdToEntity(entities);
644
667
  Object.keys(reduxFormSelectedCells).forEach(cellId => {
645
668
  const [rowId, path] = cellId.split(":");
669
+
646
670
  const entity = entityIdToEntity[rowId].e;
647
671
  delete entity._isClean;
648
672
  const { error } = editCellHelper({
649
673
  entity,
650
674
  path,
651
675
  schema,
652
- newVal
676
+ newVal: formatPasteData({ newVal, path, schema })
653
677
  });
654
678
  if (error) {
655
679
  newCellValidate[cellId] = error;
@@ -684,8 +708,8 @@ class DataTable extends React.Component {
684
708
  const indexToPath = invert(pathToIndex);
685
709
  const startCellIndex = pathToIndex[primaryCellPath];
686
710
  pasteData.forEach((row, i) => {
687
- row.forEach((cell, j) => {
688
- if (cell) {
711
+ row.forEach((newVal, j) => {
712
+ if (newVal) {
689
713
  const cellIndexToChange = startCellIndex + j;
690
714
  const entity = entitiesToManipulate[i];
691
715
  if (entity) {
@@ -696,7 +720,11 @@ class DataTable extends React.Component {
696
720
  entity,
697
721
  path,
698
722
  schema,
699
- newVal: cell
723
+ newVal: formatPasteData({
724
+ newVal,
725
+ path,
726
+ schema
727
+ })
700
728
  });
701
729
  const cellId = `${getIdOrCodeOrIndex(entity)}:${path}`;
702
730
  if (!newSelectedCells[cellId]) {
@@ -812,18 +840,12 @@ class DataTable extends React.Component {
812
840
  const text = cellWrapper && cellWrapper.getAttribute("data-copy-text");
813
841
  const jsonText = cellWrapper && cellWrapper.getAttribute("data-copy-json");
814
842
 
815
- const toRet = text || cellWrapper.textContent || "";
816
- return [toRet, jsonText];
843
+ const textContent = text || cellWrapper.textContent || "";
844
+ return [textContent, jsonText];
817
845
  };
818
846
 
819
- handleCopyRow = rowEl => {
820
- //takes in a row element
821
- const text = this.getRowCopyText(rowEl);
822
- if (!text) return window.toastr.warning("No text to copy");
823
- this.handleCopyHelper(text, undefined, "Row Copied");
824
- };
825
847
  handleCopyColumn = (e, cellWrapper, selectedRecords) => {
826
- const cellType = cellWrapper.getAttribute("data-test");
848
+ const specificColumn = cellWrapper.getAttribute("data-test");
827
849
  let rowElsToCopy = getAllRows(e);
828
850
  if (!rowElsToCopy) return;
829
851
  if (selectedRecords) {
@@ -834,14 +856,23 @@ class DataTable extends React.Component {
834
856
  });
835
857
  }
836
858
  if (!rowElsToCopy) return;
837
- const textToCopy = map(rowElsToCopy, rowEl =>
838
- this.getRowCopyText(rowEl, { cellType })
839
- )
840
- .filter(text => text)
841
- .join("\n");
859
+ this.handleCopyRows(rowElsToCopy, {
860
+ specificColumn,
861
+ onFinishMsg: "Column Copied"
862
+ });
863
+ };
864
+ handleCopyRows = (rowElsToCopy, { specificColumn, onFinishMsg } = {}) => {
865
+ let textToCopy = [];
866
+ const jsonToCopy = [];
867
+ forEach(rowElsToCopy, rowEl => {
868
+ const [t, j] = this.getRowCopyText(rowEl, { specificColumn });
869
+ textToCopy.push(t);
870
+ jsonToCopy.push(j);
871
+ });
872
+ textToCopy = textToCopy.filter(text => text).join("\n");
842
873
  if (!textToCopy) return window.toastr.warning("No text to copy");
843
874
 
844
- this.handleCopyHelper(textToCopy, undefined, "Column copied");
875
+ this.handleCopyHelper(textToCopy, jsonToCopy, onFinishMsg || "Row Copied");
845
876
  };
846
877
  updateEntitiesHelper = (ents, fn) => {
847
878
  const { change, reduxFormEntitiesUndoRedoStack = { currentVersion: 0 } } =
@@ -863,36 +894,41 @@ class DataTable extends React.Component {
863
894
  });
864
895
  };
865
896
 
866
- getRowCopyText = (rowEl, { cellType } = {}) => {
897
+ getRowCopyText = (rowEl, { specificColumn } = {}) => {
867
898
  //takes in a row element
868
899
  if (!rowEl) return;
869
- return flatMap(rowEl.children, cellEl => {
900
+ const textContent = [];
901
+ const jsonText = [];
902
+
903
+ forEach(rowEl.children, cellEl => {
870
904
  const cellChild = cellEl.querySelector(`[data-copy-text]`);
871
905
  if (!cellChild) {
872
- if (cellType) return []; //strip it
906
+ if (specificColumn) return []; //strip it
873
907
  return; //just leave it blank
874
908
  }
875
- if (cellType && cellChild.getAttribute("data-test") !== cellType) {
909
+ if (
910
+ specificColumn &&
911
+ cellChild.getAttribute("data-test") !== specificColumn
912
+ ) {
876
913
  return [];
877
914
  }
878
- return this.getCellCopyText(cellChild);
879
- }).join("\t");
880
- };
915
+ const [t, j] = this.getCellCopyText(cellChild);
916
+ textContent.push(t);
917
+ jsonText.push(j);
918
+ });
881
919
 
882
- handleCopyHelper = (stringToCopy, objToCopy, message) => {
883
- const copyHandler = e => {
884
- e.preventDefault();
920
+ return [flatMap(textContent).join("\t"), jsonText];
921
+ };
885
922
 
886
- e.clipboardData.setData("application/json", JSON.stringify(objToCopy));
887
- e.clipboardData.setData("text/plain", stringToCopy);
888
- };
889
- document.addEventListener("copy", copyHandler);
923
+ handleCopyHelper = (stringToCopy, jsonToCopy, message) => {
890
924
  !window.Cypress &&
891
925
  copy(stringToCopy, {
926
+ onCopy: clipboardData => {
927
+ clipboardData.setData("application/json", JSON.stringify(jsonToCopy));
928
+ },
892
929
  // keep this so that pasting into spreadsheets works.
893
930
  format: "text/plain"
894
931
  });
895
- document.removeEventListener("copy", copyHandler);
896
932
  window.toastr.success(message);
897
933
  };
898
934
 
@@ -900,13 +936,9 @@ class DataTable extends React.Component {
900
936
  try {
901
937
  const allRowEls = getAllRows(e);
902
938
  if (!allRowEls) return;
903
- //get row elements and call this.handleCopyRow for each
904
- const textToCopy = map(allRowEls, rowEl => this.getRowCopyText(rowEl))
905
- .filter(text => text)
906
- .join("\n");
907
- if (!textToCopy) return window.toastr.warning("No text to copy");
908
-
909
- this.handleCopyHelper(textToCopy, undefined, "Table copied");
939
+ this.handleCopyRows(allRowEls, {
940
+ onFinishMsg: "Table Copied"
941
+ });
910
942
  } catch (error) {
911
943
  console.error(`error:`, error);
912
944
  window.toastr.error("Error copying rows.");
@@ -946,6 +978,7 @@ class DataTable extends React.Component {
946
978
  if (firstRowIndex === undefined) return;
947
979
  const allRows = getAllRows(e);
948
980
  let fullCellText = "";
981
+ const fullJson = [];
949
982
  times(selectionGrid.length, i => {
950
983
  const row = selectionGrid[i];
951
984
  if (fullCellText) {
@@ -954,20 +987,24 @@ class DataTable extends React.Component {
954
987
  if (!row) {
955
988
  return;
956
989
  } else {
990
+ const jsonRow = [];
957
991
  // ignore header
958
- const rowCopyText = this.getRowCopyText(allRows[i + 1]).split("\t");
992
+ let [rowCopyText, json] = this.getRowCopyText(allRows[i + 1]);
993
+ rowCopyText = rowCopyText.split("\t");
959
994
  times(row.length, i => {
960
995
  const cell = row[i];
961
996
  if (cell) {
962
997
  fullCellText += rowCopyText[i];
998
+ jsonRow.push(json[i]);
963
999
  }
964
1000
  if (i !== row.length - 1 && i >= firstCellIndex) fullCellText += "\t";
965
1001
  });
1002
+ fullJson.push(jsonRow);
966
1003
  }
967
1004
  });
968
1005
  if (!fullCellText) return window.toastr.warning("No text to copy");
969
1006
 
970
- this.handleCopyHelper(fullCellText, undefined, "Selected cells copied");
1007
+ this.handleCopyHelper(fullCellText, fullJson, "Selected cells copied");
971
1008
  };
972
1009
 
973
1010
  handleCopySelectedRows = (selectedRecords, e) => {
@@ -990,13 +1027,9 @@ class DataTable extends React.Component {
990
1027
  if (!allRowEls) return;
991
1028
  const rowEls = rowNumbersToCopy.map(i => allRowEls[i]);
992
1029
 
993
- //get row elements and call this.handleCopyRow for each const rowEls = this.getRowEls(rowNumbersToCopy)
994
- const textToCopy = map(rowEls, rowEl => this.getRowCopyText(rowEl))
995
- .filter(text => text)
996
- .join("\n");
997
- if (!textToCopy) return window.toastr.warning("No text to copy");
998
-
999
- this.handleCopyHelper(textToCopy, undefined, "Selected rows copied");
1030
+ this.handleCopyRows(rowEls, {
1031
+ onFinishMsg: "Selected rows copied"
1032
+ });
1000
1033
  } catch (error) {
1001
1034
  console.error(`error:`, error);
1002
1035
  window.toastr.error("Error copying rows.");
@@ -2489,6 +2522,7 @@ class DataTable extends React.Component {
2489
2522
  const dataTest = {
2490
2523
  "data-test": "tgCell_" + column.path
2491
2524
  };
2525
+ const fullValue = row.original?.[row.column.path];
2492
2526
  if (isCellEditable && isBool) {
2493
2527
  val = (
2494
2528
  <Checkbox
@@ -2510,9 +2544,11 @@ class DataTable extends React.Component {
2510
2544
  if (reduxFormEditingCell === cellId) {
2511
2545
  if (column.type === "genericSelect") {
2512
2546
  const GenericSelectComp = column.GenericSelectComp;
2547
+
2513
2548
  return (
2514
2549
  <GenericSelectComp
2515
2550
  rowId={rowId}
2551
+ fullValue={fullValue}
2516
2552
  initialValue={text}
2517
2553
  {...dataTest}
2518
2554
  finishEdit={(newVal, doNotStopEditing) => {
@@ -2568,7 +2604,7 @@ class DataTable extends React.Component {
2568
2604
  // return getIdOrCodeOrIndex(e, i) === rowId2;
2569
2605
  // });
2570
2606
  // }
2571
-
2607
+ // if ()
2572
2608
  const {
2573
2609
  isRect,
2574
2610
  selectionGrid,
@@ -2577,6 +2613,7 @@ class DataTable extends React.Component {
2577
2613
  entityMap,
2578
2614
  pathToIndex
2579
2615
  } = this.isSelectionARectangle();
2616
+ // const __isHeaderCell =
2580
2617
  return (
2581
2618
  <>
2582
2619
  <div
@@ -2589,6 +2626,15 @@ class DataTable extends React.Component {
2589
2626
  {...dataTest}
2590
2627
  className="tg-cell-wrapper"
2591
2628
  data-copy-text={text}
2629
+ data-copy-json={JSON.stringify(
2630
+ //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
2631
+ column.type === "genericSelect"
2632
+ ? {
2633
+ __strVal: fullValue,
2634
+ __genSelCol: column.path
2635
+ }
2636
+ : { __strVal: text }
2637
+ )}
2592
2638
  title={title || undefined}
2593
2639
  >
2594
2640
  {val}
@@ -2992,8 +3038,13 @@ class DataTable extends React.Component {
2992
3038
  onClick={() => {
2993
3039
  //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
2994
3040
  //do we need to be able to copy hidden cells? It seems like it should just copy what's on the page..?
3041
+ const specificColumn = cellWrapper.getAttribute("data-test");
3042
+ this.handleCopyRows([cellWrapper.closest(".rt-tr")], {
3043
+ specificColumn,
3044
+ onFinishMsg: "Cell copied"
3045
+ });
2995
3046
  const [text, jsonText] = this.getCellCopyText(cellWrapper);
2996
- this.handleCopyHelper(text, jsonText, "Cell copied");
3047
+ this.handleCopyHelper(text, jsonText);
2997
3048
  }}
2998
3049
  text="Cell"
2999
3050
  />
@@ -3031,7 +3082,7 @@ class DataTable extends React.Component {
3031
3082
  <MenuItem
3032
3083
  key="copySelectedRows"
3033
3084
  onClick={() => {
3034
- this.handleCopyRow(row);
3085
+ this.handleCopyRows([row]);
3035
3086
  // loop through each cell in the row
3036
3087
  }}
3037
3088
  text="Row"
@@ -3296,6 +3347,10 @@ class DataTable extends React.Component {
3296
3347
  data-test={columnTitleTextified}
3297
3348
  data-path={path}
3298
3349
  data-copy-text={columnTitleTextified}
3350
+ data-copy-json={JSON.stringify({
3351
+ __strVal: columnTitleTextified,
3352
+ __isHeaderCell: true
3353
+ })}
3299
3354
  className={classNames("tg-react-table-column-header", {
3300
3355
  "sort-active": sortUp || sortDown
3301
3356
  })}
@@ -3633,3 +3688,18 @@ export function isEntityClean(e) {
3633
3688
  });
3634
3689
  return isClean;
3635
3690
  }
3691
+
3692
+ const formatPasteData = ({ schema, newVal, path }) => {
3693
+ const pathToField = getFieldPathToField(schema);
3694
+ const column = pathToField[path];
3695
+ if (column.type === "genericSelect") {
3696
+ if (newVal?.__genSelCol === path) {
3697
+ newVal = newVal.__strVal;
3698
+ } else {
3699
+ newVal = undefined;
3700
+ }
3701
+ } else {
3702
+ newVal = Object.hasOwn(newVal, "__strVal") ? newVal.__strVal : newVal;
3703
+ }
3704
+ return newVal;
3705
+ };