@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.
- package/index.cjs.js +180 -108
- package/index.es.js +180 -108
- package/package.json +1 -1
- package/src/DataTable/dataTableEnhancer.js +9 -0
- package/src/DataTable/index.js +134 -64
package/src/DataTable/index.js
CHANGED
|
@@ -427,13 +427,14 @@ class DataTable extends React.Component {
|
|
|
427
427
|
};
|
|
428
428
|
formatAndValidateTableInitial = () => {
|
|
429
429
|
const {
|
|
430
|
-
_origEntities
|
|
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
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
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
|
-
|
|
626
|
-
|
|
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((
|
|
688
|
-
if (
|
|
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:
|
|
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
|
|
816
|
-
return [
|
|
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
|
|
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
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
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,
|
|
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, {
|
|
897
|
+
getRowCopyText = (rowEl, { specificColumn } = {}) => {
|
|
867
898
|
//takes in a row element
|
|
868
899
|
if (!rowEl) return;
|
|
869
|
-
|
|
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 (
|
|
906
|
+
if (specificColumn) return []; //strip it
|
|
873
907
|
return; //just leave it blank
|
|
874
908
|
}
|
|
875
|
-
if (
|
|
909
|
+
if (
|
|
910
|
+
specificColumn &&
|
|
911
|
+
cellChild.getAttribute("data-test") !== specificColumn
|
|
912
|
+
) {
|
|
876
913
|
return [];
|
|
877
914
|
}
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
915
|
+
const [t, j] = this.getCellCopyText(cellChild);
|
|
916
|
+
textContent.push(t);
|
|
917
|
+
jsonText.push(j);
|
|
918
|
+
});
|
|
881
919
|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
e.preventDefault();
|
|
920
|
+
return [flatMap(textContent).join("\t"), jsonText];
|
|
921
|
+
};
|
|
885
922
|
|
|
886
|
-
|
|
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
|
-
|
|
904
|
-
|
|
905
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
994
|
-
|
|
995
|
-
|
|
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
|
|
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.
|
|
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
|
+
};
|