@teselagen/ui 0.0.9 → 0.0.12

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.
Files changed (126) hide show
  1. package/README.md +7 -0
  2. package/cypress.config.ts +6 -0
  3. package/index.html +12 -0
  4. package/package.json +2 -2
  5. package/project.json +74 -0
  6. package/src/AdvancedOptions.js +33 -0
  7. package/src/AdvancedOptions.spec.js +24 -0
  8. package/src/AssignDefaultsModeContext.js +21 -0
  9. package/src/AsyncValidateFieldSpinner/index.js +12 -0
  10. package/src/BlueprintError/index.js +14 -0
  11. package/src/BounceLoader/index.js +16 -0
  12. package/src/BounceLoader/style.css +45 -0
  13. package/src/CollapsibleCard/index.js +92 -0
  14. package/src/CollapsibleCard/style.css +21 -0
  15. package/src/DNALoader/index.js +20 -0
  16. package/src/DNALoader/style.css +251 -0
  17. package/src/DataTable/CellDragHandle.js +130 -0
  18. package/src/DataTable/DisabledLoadingComponent.js +15 -0
  19. package/src/DataTable/DisplayOptions.js +218 -0
  20. package/src/DataTable/FilterAndSortMenu.js +397 -0
  21. package/src/DataTable/PagingTool.js +232 -0
  22. package/src/DataTable/SearchBar.js +57 -0
  23. package/src/DataTable/SortableColumns.js +53 -0
  24. package/src/DataTable/TableFormTrackerContext.js +10 -0
  25. package/src/DataTable/dataTableEnhancer.js +291 -0
  26. package/src/DataTable/defaultFormatters.js +32 -0
  27. package/src/DataTable/defaultProps.js +45 -0
  28. package/src/DataTable/defaultValidators.js +40 -0
  29. package/src/DataTable/editCellHelper.js +44 -0
  30. package/src/DataTable/getCellVal.js +20 -0
  31. package/src/DataTable/getVals.js +8 -0
  32. package/src/DataTable/index.js +3537 -0
  33. package/src/DataTable/isTruthy.js +12 -0
  34. package/src/DataTable/isValueEmpty.js +3 -0
  35. package/src/DataTable/style.css +600 -0
  36. package/src/DataTable/utils/computePresets.js +42 -0
  37. package/src/DataTable/utils/convertSchema.js +69 -0
  38. package/src/DataTable/utils/getIdOrCodeOrIndex.js +9 -0
  39. package/src/DataTable/utils/getTableConfigFromStorage.js +5 -0
  40. package/src/DataTable/utils/queryParams.js +1032 -0
  41. package/src/DataTable/utils/rowClick.js +156 -0
  42. package/src/DataTable/utils/selection.js +8 -0
  43. package/src/DataTable/utils/withSelectedEntities.js +65 -0
  44. package/src/DataTable/utils/withTableParams.js +328 -0
  45. package/src/DataTable/validateTableWideErrors.js +135 -0
  46. package/src/DataTable/viewColumn.js +37 -0
  47. package/src/DialogFooter/index.js +79 -0
  48. package/src/DialogFooter/style.css +9 -0
  49. package/src/DropdownButton.js +36 -0
  50. package/src/FillWindow.css +6 -0
  51. package/src/FillWindow.js +69 -0
  52. package/src/FormComponents/Uploader.js +1197 -0
  53. package/src/FormComponents/getNewName.js +31 -0
  54. package/src/FormComponents/index.js +1384 -0
  55. package/src/FormComponents/itemUpload.js +84 -0
  56. package/src/FormComponents/sortify.js +73 -0
  57. package/src/FormComponents/style.css +247 -0
  58. package/src/FormComponents/tryToMatchSchemas.js +222 -0
  59. package/src/FormComponents/utils.js +6 -0
  60. package/src/HotkeysDialog/index.js +79 -0
  61. package/src/HotkeysDialog/style.css +54 -0
  62. package/src/InfoHelper/index.js +83 -0
  63. package/src/InfoHelper/style.css +7 -0
  64. package/src/IntentText/index.js +18 -0
  65. package/src/Loading/index.js +74 -0
  66. package/src/Loading/style.css +4 -0
  67. package/src/MatchHeaders.js +223 -0
  68. package/src/MenuBar/index.js +416 -0
  69. package/src/MenuBar/style.css +45 -0
  70. package/src/PromptUnsavedChanges/index.js +40 -0
  71. package/src/ResizableDraggableDialog/index.js +138 -0
  72. package/src/ResizableDraggableDialog/style.css +42 -0
  73. package/src/ScrollToTop/index.js +72 -0
  74. package/src/SimpleStepViz.js +26 -0
  75. package/src/TgSelect/index.js +465 -0
  76. package/src/TgSelect/style.css +34 -0
  77. package/src/TgSuggest/index.js +121 -0
  78. package/src/Timeline/TimelineEvent.js +31 -0
  79. package/src/Timeline/index.js +22 -0
  80. package/src/Timeline/style.css +29 -0
  81. package/src/UploadCsvWizard.css +4 -0
  82. package/src/UploadCsvWizard.js +731 -0
  83. package/src/autoTooltip.js +89 -0
  84. package/src/constants.js +1 -0
  85. package/src/customIcons.js +361 -0
  86. package/src/enhancers/withDialog/index.js +196 -0
  87. package/src/enhancers/withDialog/tg_modalState.js +46 -0
  88. package/src/enhancers/withField.js +20 -0
  89. package/src/enhancers/withFields.js +11 -0
  90. package/src/enhancers/withLocalStorage.js +11 -0
  91. package/src/index.js +76 -0
  92. package/src/rerenderOnWindowResize.js +27 -0
  93. package/src/showAppSpinner.js +12 -0
  94. package/src/showConfirmationDialog/index.js +116 -0
  95. package/src/showDialogOnDocBody.js +37 -0
  96. package/src/style.css +214 -0
  97. package/src/toastr.js +92 -0
  98. package/src/typeToCommonType.js +6 -0
  99. package/src/useDialog.js +64 -0
  100. package/src/utils/S3Download.js +14 -0
  101. package/src/utils/adHoc.js +10 -0
  102. package/src/utils/basicHandleActionsWithFullState.js +14 -0
  103. package/src/utils/combineReducersWithFullState.js +14 -0
  104. package/src/utils/commandControls.js +83 -0
  105. package/src/utils/commandUtils.js +112 -0
  106. package/src/utils/determineBlackOrWhiteTextColor.js +4 -0
  107. package/src/utils/getDayjsFormatter.js +35 -0
  108. package/src/utils/getTextFromEl.js +28 -0
  109. package/src/utils/handlerHelpers.js +30 -0
  110. package/src/utils/hotkeyUtils.js +129 -0
  111. package/src/utils/menuUtils.js +402 -0
  112. package/src/utils/popoverOverflowModifiers.js +11 -0
  113. package/src/utils/pureNoFunc.js +31 -0
  114. package/src/utils/renderOnDoc.js +29 -0
  115. package/src/utils/showProgressToast.js +22 -0
  116. package/src/utils/tagUtils.js +45 -0
  117. package/src/utils/tgFormValues.js +32 -0
  118. package/src/utils/withSelectTableRecords.js +38 -0
  119. package/src/utils/withStore.js +10 -0
  120. package/src/wrapDialog.js +112 -0
  121. package/tsconfig.json +4 -0
  122. package/vite.config.ts +7 -0
  123. package/index.js +0 -80652
  124. package/index.mjs +0 -80636
  125. package/index.umd.js +0 -80649
  126. package/style.css +0 -10421
@@ -0,0 +1,130 @@
1
+ import { flatMap } from "lodash";
2
+ import { forEach } from "lodash";
3
+ import React, { useRef } from "react";
4
+ import ReactDOM from "react-dom";
5
+
6
+ export function CellDragHandle({
7
+ thisTable,
8
+ onDragEnd,
9
+ cellId,
10
+ isSelectionARectangle
11
+ }) {
12
+ const xStart = useRef(0);
13
+ const timeoutkey = useRef();
14
+ const rowsToSelect = useRef();
15
+ const rectangleCellPaths = useRef();
16
+
17
+ const handleDrag = useRef(e => {
18
+ const table = ReactDOM.findDOMNode(thisTable).querySelector(".rt-table");
19
+ const trs = table.querySelectorAll(`.rt-tr-group.with-row-data`);
20
+ const [rowId, path] = cellId.split(":");
21
+ const selectedTr = table.querySelector(
22
+ `.rt-tr-group.with-row-data[data-test-id="${rowId}"]`
23
+ );
24
+ const selectedIndex = selectedTr.dataset.index;
25
+
26
+ if (selectedTr && trs.length) {
27
+ const selectedY = selectedTr.getBoundingClientRect().y;
28
+ const cursorY = e.clientY;
29
+ clearTimeout(timeoutkey.current);
30
+ // eslint-disable-next-line no-inner-declarations
31
+ function updateScrollIfNecessary() {
32
+ const { y, height } = table.getBoundingClientRect();
33
+ if (cursorY < y) {
34
+ table.scrollBy(0, -5);
35
+ } else if (cursorY > y + height) {
36
+ table.scrollBy(0, 5);
37
+ }
38
+ }
39
+ updateScrollIfNecessary();
40
+ timeoutkey.current = setInterval(() => {
41
+ updateScrollIfNecessary();
42
+ }, 10);
43
+
44
+ const isCursorBelow = cursorY > selectedY;
45
+ rowsToSelect.current = [];
46
+ forEach(trs, (tr, index) => {
47
+ let isSelectedForUpdate;
48
+ const rowId = tr.dataset.testId;
49
+ const changeDashedBorder = (path, on) => {
50
+ tr.querySelector(`[data-test="tgCell_${path}"]`).parentNode.classList[
51
+ on ? "add" : "remove"
52
+ ]("selectedForUpdate");
53
+ };
54
+ if (isCursorBelow ? index > selectedIndex : index < selectedIndex) {
55
+ const { y, height } = tr.getBoundingClientRect();
56
+ if (isCursorBelow ? y < cursorY : y + height > cursorY) {
57
+ rowsToSelect.current.push(rowId);
58
+ isSelectedForUpdate = true;
59
+ //add dashed borders
60
+
61
+ if (rectangleCellPaths.current) {
62
+ rectangleCellPaths.current.forEach(path => {
63
+ changeDashedBorder(path, true);
64
+ });
65
+ } else {
66
+ changeDashedBorder(path, true);
67
+ }
68
+ }
69
+ }
70
+ if (!isSelectedForUpdate) {
71
+ if (rectangleCellPaths.current) {
72
+ rectangleCellPaths.current.forEach(path => {
73
+ changeDashedBorder(path, false);
74
+ });
75
+ } else {
76
+ changeDashedBorder(path, false);
77
+ }
78
+ }
79
+ });
80
+ }
81
+ });
82
+
83
+ const mouseup = useRef(() => {
84
+ clearTimeout(timeoutkey.current);
85
+ const table = ReactDOM.findDOMNode(thisTable);
86
+ const trs = table.querySelectorAll(`.rt-tr-group.with-row-data`);
87
+ const [, path] = cellId.split(":");
88
+ //remove the dashed borders
89
+ forEach(trs, tr => {
90
+ if (rectangleCellPaths.current) {
91
+ rectangleCellPaths.current.forEach(path => {
92
+ const el = tr.querySelector(`[data-test="tgCell_${path}"]`);
93
+ el.parentNode.classList.remove("selectedForUpdate");
94
+ });
95
+ } else {
96
+ const el = tr.querySelector(`[data-test="tgCell_${path}"]`);
97
+ el.parentNode.classList.remove("selectedForUpdate");
98
+ }
99
+ });
100
+ document.removeEventListener("mousemove", handleDrag.current, false);
101
+ document.removeEventListener("mouseup", mouseup.current, false);
102
+ onDragEnd(
103
+ flatMap(rowsToSelect.current, id => {
104
+ if (rectangleCellPaths.current) {
105
+ return rectangleCellPaths.current.map(path => {
106
+ return `${id}:${path}`;
107
+ });
108
+ } else {
109
+ return `${id}:${path}`;
110
+ }
111
+ })
112
+ );
113
+ });
114
+
115
+ return (
116
+ <div
117
+ onMouseDown={e => {
118
+ rowsToSelect.current = [];
119
+ xStart.current = e.clientX;
120
+ const { isRect, selectedPaths } = isSelectionARectangle();
121
+ if (isRect) {
122
+ rectangleCellPaths.current = selectedPaths;
123
+ }
124
+ document.addEventListener("mousemove", handleDrag.current, false);
125
+ document.addEventListener("mouseup", mouseup.current, false);
126
+ }}
127
+ className="cellDragHandle"
128
+ ></div>
129
+ );
130
+ }
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+ import { ReactTableDefaults } from "@teselagen/react-table";
3
+ const { LoadingComponent } = ReactTableDefaults;
4
+
5
+ function DisabledLoadingComponent({ disabled, loading, loadingText }) {
6
+ return (
7
+ <LoadingComponent
8
+ className={disabled ? "disabled" : ""}
9
+ loading={loading}
10
+ loadingText={disabled ? "" : loadingText}
11
+ />
12
+ );
13
+ }
14
+
15
+ export default DisabledLoadingComponent;
@@ -0,0 +1,218 @@
1
+ import React from "react";
2
+ import { map, isEmpty, noop } from "lodash";
3
+ import {
4
+ Button,
5
+ Checkbox,
6
+ Menu,
7
+ MenuItem,
8
+ Classes,
9
+ InputGroup,
10
+ Popover,
11
+ Switch
12
+ } from "@blueprintjs/core";
13
+
14
+ export default class DisplayOptions extends React.Component {
15
+ state = {
16
+ isOpen: false,
17
+ searchTerms: {}
18
+ };
19
+
20
+ openPopover = () => {
21
+ this.setState({
22
+ isOpen: true
23
+ });
24
+ };
25
+
26
+ closePopover = () => {
27
+ this.setState({
28
+ isOpen: false
29
+ });
30
+ };
31
+
32
+ changeTableDensity = e => {
33
+ const { updateTableDisplayDensity = noop } = this.props;
34
+ updateTableDisplayDensity(e.target.value);
35
+ this.closePopover();
36
+ };
37
+
38
+ toggleForcedHidden = e => this.props.setShowForcedHidden(e.target.checked);
39
+
40
+ render() {
41
+ const { isOpen, searchTerms } = this.state;
42
+ const {
43
+ schema,
44
+ updateColumnVisibility = noop,
45
+ resetDefaultVisibility = noop,
46
+ compact,
47
+ extraCompact,
48
+ disabled,
49
+ hasOptionForForcedHidden,
50
+ showForcedHiddenColumns,
51
+ hideDisplayOptionsIcon
52
+ } = this.props;
53
+ if (hideDisplayOptionsIcon) {
54
+ return null; //don't show antyhing!
55
+ }
56
+ const { fields } = schema;
57
+ const fieldGroups = {};
58
+ const mainFields = [];
59
+
60
+ fields.forEach(field => {
61
+ if (field.hideInMenu) return;
62
+ if (!field.fieldGroup) return mainFields.push(field);
63
+ if (!fieldGroups[field.fieldGroup]) fieldGroups[field.fieldGroup] = [];
64
+ fieldGroups[field.fieldGroup].push(field);
65
+ });
66
+
67
+ let numVisible = 0;
68
+
69
+ const getFieldCheckbox = (field, i) => {
70
+ const { displayName, isHidden, isForcedHidden, path } = field;
71
+ if (isForcedHidden) return;
72
+ if (!isHidden) numVisible++;
73
+ return (
74
+ <Checkbox
75
+ key={path || i}
76
+ onChange={() => {
77
+ if (numVisible <= 1 && !isHidden) {
78
+ return window.toastr.warning(
79
+ "We have to display at least one column :)"
80
+ );
81
+ }
82
+ updateColumnVisibility({ shouldShow: isHidden, path });
83
+ }}
84
+ checked={!isHidden}
85
+ label={displayName}
86
+ />
87
+ );
88
+ };
89
+
90
+ let fieldGroupMenu;
91
+ if (!isEmpty(fieldGroups)) {
92
+ fieldGroupMenu = map(fieldGroups, (groupFields, groupName) => {
93
+ const searchTerm = searchTerms[groupName] || "";
94
+ const anyVisible = groupFields.some(
95
+ field => !field.isHidden && !field.isForcedHidden
96
+ );
97
+ const anyNotForcedHidden = groupFields.some(
98
+ field => !field.isForcedHidden
99
+ );
100
+ if (!anyNotForcedHidden) return;
101
+ return (
102
+ <MenuItem key={groupName} text={groupName}>
103
+ <InputGroup
104
+ leftIcon="search"
105
+ value={searchTerm}
106
+ onChange={e => {
107
+ this.setState({
108
+ searchTerms: {
109
+ ...searchTerms,
110
+ [groupName]: e.target.value
111
+ }
112
+ });
113
+ }}
114
+ />
115
+ <Button
116
+ className={Classes.MINIMAL}
117
+ text={(anyVisible ? "Hide" : "Show") + " All"}
118
+ style={{ margin: "10px 0" }}
119
+ onClick={() => {
120
+ updateColumnVisibility({
121
+ shouldShow: !anyVisible,
122
+ paths: groupFields.map(field => field.path)
123
+ });
124
+ }}
125
+ />
126
+ {groupFields
127
+ .filter(
128
+ field =>
129
+ field.displayName
130
+ .toLowerCase()
131
+ .indexOf(searchTerm.toLowerCase()) > -1
132
+ )
133
+ .map(getFieldCheckbox)}
134
+ </MenuItem>
135
+ );
136
+ });
137
+ }
138
+
139
+ return (
140
+ <Popover
141
+ isOpen={isOpen}
142
+ onClose={this.closePopover}
143
+ content={
144
+ <Menu>
145
+ <div style={{ padding: 10, paddingLeft: 20, paddingRight: 20 }}>
146
+ <h5 style={{ marginBottom: 10 }}>Display Density:</h5>
147
+ <div className={Classes.SELECT + " tg-table-display-density"}>
148
+ <select
149
+ onChange={this.changeTableDensity}
150
+ value={
151
+ extraCompact
152
+ ? "extraCompact"
153
+ : compact
154
+ ? "compact"
155
+ : "normal"
156
+ }
157
+ >
158
+ <option className={Classes.POPOVER_DISMISS} value="normal">
159
+ Comfortable
160
+ </option>
161
+ {/* tnr: as you can see we're calling what was "compact" Normal now in response to https://github.com/TeselaGen/lims/issues/4713 */}
162
+ <option className={Classes.POPOVER_DISMISS} value="compact">
163
+ Normal
164
+ </option>
165
+ <option
166
+ className={Classes.POPOVER_DISMISS}
167
+ value="extraCompact"
168
+ >
169
+ Compact
170
+ </option>
171
+ </select>
172
+ </div>
173
+ <h5 style={{ marginBottom: 10, marginTop: 10 }}>
174
+ Displayed Columns:
175
+ </h5>
176
+ <div style={{ maxHeight: 260, overflowY: "auto", padding: 2 }}>
177
+ {mainFields.map(getFieldCheckbox)}
178
+ </div>
179
+ <div>{fieldGroupMenu}</div>
180
+ {hasOptionForForcedHidden && (
181
+ <div style={{ marginTop: 15 }}>
182
+ <Switch
183
+ label="Show Empty Columns"
184
+ checked={showForcedHiddenColumns}
185
+ onChange={this.toggleForcedHidden}
186
+ />
187
+ </div>
188
+ )}
189
+ <div
190
+ style={{
191
+ width: "100%",
192
+ display: "flex",
193
+ justifyContent: "flex-end"
194
+ }}
195
+ >
196
+ <Button
197
+ onClick={resetDefaultVisibility}
198
+ title="Display Options"
199
+ minimal
200
+ >
201
+ Reset
202
+ </Button>
203
+ </div>
204
+ </div>
205
+ </Menu>
206
+ }
207
+ >
208
+ <Button
209
+ className="tg-table-display-options"
210
+ onClick={this.openPopover}
211
+ disabled={disabled}
212
+ minimal
213
+ icon="cog"
214
+ />
215
+ </Popover>
216
+ );
217
+ }
218
+ }