@teselagen/ui 0.4.14 → 0.4.15
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/AdvancedOptions.d.ts +1 -1
- package/AssignDefaultsModeContext.d.ts +1 -1
- package/AsyncValidateFieldSpinner/index.d.ts +1 -1
- package/BlueprintError/index.d.ts +1 -1
- package/BounceLoader/index.d.ts +1 -1
- package/CollapsibleCard/index.d.ts +1 -1
- package/DNALoader/index.d.ts +1 -1
- package/DataTable/CellDragHandle.d.ts +1 -1
- package/DataTable/ColumnFilterMenu.d.ts +14 -0
- package/DataTable/DisabledLoadingComponent.d.ts +1 -1
- package/DataTable/DisplayOptions.d.ts +2 -2
- package/DataTable/DropdownCell.d.ts +8 -0
- package/DataTable/EditabelCell.d.ts +10 -0
- package/DataTable/FilterAndSortMenu.d.ts +2 -2
- package/DataTable/SearchBar.d.ts +1 -1
- package/DataTable/SortableColumns.d.ts +2 -2
- package/DataTable/TableFormTrackerContext.d.ts +1 -1
- package/DataTable/defaultProps.d.ts +1 -1
- package/DataTable/index.d.ts +0 -5
- package/DataTable/utils/computePresets.d.ts +1 -1
- package/DataTable/utils/formatPasteData.d.ts +5 -0
- package/DataTable/utils/getAllRows.d.ts +1 -0
- package/DataTable/utils/getCellCopyText.d.ts +1 -0
- package/DataTable/utils/getCellInfo.d.ts +17 -0
- package/DataTable/utils/getFieldPathToField.d.ts +1 -0
- package/DataTable/utils/getIdOrCodeOrIndex.d.ts +1 -2
- package/DataTable/utils/getLastSelectedEntity.d.ts +1 -0
- package/DataTable/utils/getNewEntToSelect.d.ts +6 -0
- package/DataTable/utils/getRowCopyText.d.ts +3 -0
- package/DataTable/utils/handleCopyColumn.d.ts +1 -0
- package/DataTable/utils/handleCopyHelper.d.ts +1 -0
- package/DataTable/utils/handleCopyRows.d.ts +5 -0
- package/DataTable/utils/index.d.ts +21 -0
- package/DataTable/utils/isBottomRightCornerOfRectangle.d.ts +8 -0
- package/DataTable/utils/isEntityClean.d.ts +1 -0
- package/DataTable/utils/removeCleanRows.d.ts +4 -0
- package/DataTable/utils/rowClick.d.ts +10 -2
- package/DataTable/utils/utils.d.ts +5 -0
- package/DataTable/viewColumn.d.ts +2 -2
- package/DialogFooter/index.d.ts +1 -1
- package/DropdownButton.d.ts +1 -1
- package/FillWindow.d.ts +1 -1
- package/FormComponents/LoadingDots.d.ts +1 -1
- package/FormComponents/Uploader.d.ts +29 -1
- package/FormComponents/index.d.ts +34 -34
- package/FormComponents/itemUpload.d.ts +1 -1
- package/HotkeysDialog/index.d.ts +1 -1
- package/InfoHelper/index.d.ts +1 -1
- package/IntentText/index.d.ts +1 -1
- package/MatchHeaders.d.ts +1 -1
- package/MenuBar/index.d.ts +4 -4
- package/PromptUnsavedChanges/index.d.ts +1 -1
- package/README.md +18 -0
- package/ResizableDraggableDialog/index.d.ts +2 -2
- package/ScrollToTop/index.d.ts +1 -1
- package/SimpleStepViz.d.ts +1 -1
- package/Tag.d.ts +1 -1
- package/TagSelect/index.d.ts +1 -1
- package/TgSelect/index.d.ts +2 -2
- package/TgSuggest/index.d.ts +3 -3
- package/Timeline/TimelineEvent.d.ts +1 -1
- package/Timeline/index.d.ts +2 -2
- package/UploadCsvWizard.d.ts +1 -1
- package/customIcons.d.ts +19 -19
- package/enhancers/withField.d.ts +1 -1
- package/enhancers/withFields.d.ts +1 -1
- package/enhancers/withLocalStorage.d.ts +1 -1
- package/index.cjs.js +14026 -12765
- package/index.d.ts +60 -60
- package/index.es.js +13844 -12583
- package/package.json +7 -4
- package/showConfirmationDialog/index.d.ts +2 -2
- package/src/DataTable/CellDragHandle.js +6 -7
- package/src/DataTable/ColumnFilterMenu.js +60 -0
- package/src/DataTable/DropdownCell.js +61 -0
- package/src/DataTable/EditabelCell.js +55 -0
- package/src/DataTable/PagingTool.js +1 -1
- package/src/DataTable/SortableColumns.js +53 -18
- package/src/DataTable/dataTableEnhancer.js +1 -1
- package/src/DataTable/index.js +385 -759
- package/src/DataTable/utils/formatPasteData.js +16 -0
- package/src/DataTable/utils/getAllRows.js +11 -0
- package/src/DataTable/utils/getCellCopyText.js +7 -0
- package/src/DataTable/utils/getCellInfo.js +36 -0
- package/src/DataTable/utils/getFieldPathToField.js +7 -0
- package/src/DataTable/utils/getIdOrCodeOrIndex.js +1 -1
- package/src/DataTable/utils/getLastSelectedEntity.js +11 -0
- package/src/DataTable/utils/getNewEntToSelect.js +25 -0
- package/src/DataTable/utils/getRowCopyText.js +28 -0
- package/src/DataTable/utils/handleCopyColumn.js +21 -0
- package/src/DataTable/utils/handleCopyHelper.js +15 -0
- package/src/DataTable/utils/handleCopyRows.js +23 -0
- package/src/DataTable/utils/index.js +51 -0
- package/src/DataTable/utils/isBottomRightCornerOfRectangle.js +20 -0
- package/src/DataTable/utils/isEntityClean.js +15 -0
- package/src/DataTable/utils/removeCleanRows.js +22 -0
- package/src/DataTable/utils/rowClick.js +7 -4
- package/src/DataTable/utils/selection.js +1 -1
- package/src/DataTable/utils/utils.js +37 -0
- package/src/DataTable/validateTableWideErrors.js +1 -1
- package/src/FillWindow.js +2 -3
- package/src/FormComponents/Uploader.js +400 -400
- package/src/FormComponents/tryToMatchSchemas.js +0 -6
- package/src/UploadCsvWizard.js +312 -371
- package/src/index.js +3 -3
- package/src/showDialogOnDocBody.js +5 -9
- package/src/useDialog.js +7 -4
- package/src/utils/renderOnDoc.js +8 -5
- package/style.css +7 -7
- package/useDialog.d.ts +2 -2
- package/utils/adHoc.d.ts +1 -1
- package/utils/commandControls.d.ts +5 -5
- package/utils/hotkeyUtils.d.ts +1 -1
- package/utils/menuUtils.d.ts +7 -7
- package/utils/renderOnDoc.d.ts +1 -1
- package/utils/tagUtils.d.ts +1 -1
- package/utils/tgFormValues.d.ts +1 -1
- package/utils/withStore.d.ts +1 -1
- package/wrapDialog.d.ts +1 -1
package/src/UploadCsvWizard.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useRef, useState } from "react";
|
|
1
|
+
import React, { useRef, useState, useEffect } from "react";
|
|
2
2
|
import { reduxForm, change, formValueSelector, destroy } from "redux-form";
|
|
3
3
|
import { Callout, Icon, Intent, Tab, Tabs } from "@blueprintjs/core";
|
|
4
4
|
import immer from "immer";
|
|
@@ -12,10 +12,11 @@ import { tgFormValueSelector } from "./utils/tgFormValues";
|
|
|
12
12
|
import { some } from "lodash-es";
|
|
13
13
|
import { times } from "lodash-es";
|
|
14
14
|
import DialogFooter from "./DialogFooter";
|
|
15
|
-
import DataTable
|
|
15
|
+
import DataTable from "./DataTable";
|
|
16
|
+
import { removeCleanRows } from "./DataTable/utils";
|
|
16
17
|
import wrapDialog from "./wrapDialog";
|
|
17
18
|
import { omit } from "lodash-es";
|
|
18
|
-
import {
|
|
19
|
+
import { useDispatch, useSelector } from "react-redux";
|
|
19
20
|
import { MatchHeaders } from "./MatchHeaders";
|
|
20
21
|
import { isEmpty } from "lodash-es";
|
|
21
22
|
import { addSpecialPropToAsyncErrs } from "./FormComponents/tryToMatchSchemas";
|
|
@@ -35,64 +36,62 @@ const UploadCsvWizardDialog = compose(
|
|
|
35
36
|
reduxForm({
|
|
36
37
|
form: "UploadCsvWizardDialog"
|
|
37
38
|
}),
|
|
38
|
-
connect(
|
|
39
|
-
(state, props) => {
|
|
40
|
-
if (props.filesWIssues.length > 0) {
|
|
41
|
-
const reduxFormEntitiesArray = [];
|
|
42
|
-
const finishedFiles = props.filesWIssues.map((f, i) => {
|
|
43
|
-
const { reduxFormEntities, reduxFormCellValidation } =
|
|
44
|
-
formValueSelector(`editableCellTable-${i}`)(
|
|
45
|
-
state,
|
|
46
|
-
"reduxFormEntities",
|
|
47
|
-
"reduxFormCellValidation"
|
|
48
|
-
);
|
|
49
|
-
reduxFormEntitiesArray.push(reduxFormEntities);
|
|
50
|
-
const { entsToUse, validationToUse } = removeCleanRows(
|
|
51
|
-
reduxFormEntities,
|
|
52
|
-
reduxFormCellValidation
|
|
53
|
-
);
|
|
54
|
-
return (
|
|
55
|
-
entsToUse &&
|
|
56
|
-
entsToUse.length &&
|
|
57
|
-
!some(validationToUse, v => v) &&
|
|
58
|
-
entsToUse
|
|
59
|
-
);
|
|
60
|
-
});
|
|
61
|
-
return {
|
|
62
|
-
reduxFormEntitiesArray,
|
|
63
|
-
finishedFiles
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
{ changeForm: change, destroyForms: destroy }
|
|
68
|
-
),
|
|
69
39
|
observer
|
|
70
40
|
)(function UploadCsvWizardDialogOuter({
|
|
71
|
-
validateAgainstSchema,
|
|
72
|
-
reduxFormEntitiesArray,
|
|
73
|
-
filesWIssues: _filesWIssues,
|
|
74
|
-
finishedFiles,
|
|
75
|
-
onUploadWizardFinish,
|
|
76
|
-
doAllFilesHaveSameHeaders,
|
|
77
|
-
destroyForms,
|
|
78
41
|
csvValidationIssue,
|
|
42
|
+
doAllFilesHaveSameHeaders,
|
|
43
|
+
filesWIssues: _filesWIssues,
|
|
44
|
+
flippedMatchedHeaders,
|
|
79
45
|
ignoredHeadersMsg,
|
|
80
|
-
searchResults,
|
|
81
46
|
matchedHeaders,
|
|
47
|
+
onUploadWizardFinish,
|
|
48
|
+
searchResults,
|
|
82
49
|
userSchema,
|
|
83
|
-
|
|
84
|
-
changeForm
|
|
50
|
+
validateAgainstSchema
|
|
85
51
|
}) {
|
|
52
|
+
const dispatch = useDispatch();
|
|
86
53
|
// will unmount state hook
|
|
87
|
-
|
|
54
|
+
useEffect(() => {
|
|
88
55
|
return () => {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
56
|
+
dispatch(
|
|
57
|
+
destroy(
|
|
58
|
+
"editableCellTable",
|
|
59
|
+
...times(_filesWIssues.length, i => `editableCellTable-${i}`)
|
|
60
|
+
)
|
|
92
61
|
);
|
|
93
62
|
};
|
|
94
|
-
|
|
95
|
-
|
|
63
|
+
}, [_filesWIssues.length, dispatch]);
|
|
64
|
+
|
|
65
|
+
const changeForm = (...args) => dispatch(change(...args));
|
|
66
|
+
const { reduxFormEntitiesArray, finishedFiles } = useSelector(state => {
|
|
67
|
+
if (_filesWIssues.length > 0) {
|
|
68
|
+
const reduxFormEntitiesArray = [];
|
|
69
|
+
const finishedFiles = _filesWIssues.map((f, i) => {
|
|
70
|
+
const { reduxFormEntities, reduxFormCellValidation } =
|
|
71
|
+
formValueSelector(`editableCellTable-${i}`)(
|
|
72
|
+
state,
|
|
73
|
+
"reduxFormEntities",
|
|
74
|
+
"reduxFormCellValidation"
|
|
75
|
+
);
|
|
76
|
+
reduxFormEntitiesArray.push(reduxFormEntities);
|
|
77
|
+
const { entsToUse, validationToUse } = removeCleanRows(
|
|
78
|
+
reduxFormEntities,
|
|
79
|
+
reduxFormCellValidation
|
|
80
|
+
);
|
|
81
|
+
return (
|
|
82
|
+
entsToUse &&
|
|
83
|
+
entsToUse.length &&
|
|
84
|
+
!some(validationToUse, v => v) &&
|
|
85
|
+
entsToUse
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
return {
|
|
89
|
+
reduxFormEntitiesArray,
|
|
90
|
+
finishedFiles
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
96
95
|
const [hasSubmittedOuter, setSubmittedOuter] = useState();
|
|
97
96
|
const [steps, setSteps] = useState(getInitialSteps(true));
|
|
98
97
|
|
|
@@ -118,7 +117,6 @@ const UploadCsvWizardDialog = compose(
|
|
|
118
117
|
>
|
|
119
118
|
{filesWIssues.map((f, i) => {
|
|
120
119
|
const isGood = finishedFiles[i];
|
|
121
|
-
|
|
122
120
|
const isThisTheLastBadFile = finishedFiles.every((ff, j) => {
|
|
123
121
|
if (i === j) {
|
|
124
122
|
return true;
|
|
@@ -135,108 +133,98 @@ const UploadCsvWizardDialog = compose(
|
|
|
135
133
|
<Icon
|
|
136
134
|
intent={isGood ? "success" : "warning"}
|
|
137
135
|
icon={isGood ? "tick-circle" : "warning-sign"}
|
|
138
|
-
|
|
136
|
+
/>{" "}
|
|
139
137
|
{f.file.name}
|
|
140
138
|
</div>
|
|
141
139
|
}
|
|
142
140
|
panel={
|
|
143
141
|
<UploadCsvWizardDialogInner
|
|
144
|
-
{
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
142
|
+
isThisTheLastBadFile={isThisTheLastBadFile}
|
|
143
|
+
onBackClick={
|
|
144
|
+
doAllFilesHaveSameHeaders &&
|
|
145
|
+
(() => {
|
|
146
|
+
setSubmittedOuter(false);
|
|
147
|
+
setSteps(getInitialSteps(true));
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
onMultiFileUploadSubmit={async () => {
|
|
151
|
+
let nextUnfinishedFile;
|
|
152
|
+
//find the next unfinished file
|
|
153
|
+
for (
|
|
154
|
+
let j = (i + 1) % finishedFiles.length;
|
|
155
|
+
j < finishedFiles.length;
|
|
156
|
+
j++
|
|
157
|
+
) {
|
|
158
|
+
if (j === i) {
|
|
159
|
+
break;
|
|
160
|
+
} else if (!finishedFiles[j]) {
|
|
161
|
+
nextUnfinishedFile = j;
|
|
162
|
+
break;
|
|
163
|
+
} else if (j === finishedFiles.length - 1) {
|
|
164
|
+
j = -1;
|
|
168
165
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
166
|
+
}
|
|
167
|
+
if (nextUnfinishedFile !== undefined) {
|
|
168
|
+
//do async validation here if needed
|
|
169
|
+
const currentEnts = reduxFormEntitiesArray[focusedTab];
|
|
170
|
+
if (
|
|
171
|
+
await asyncValidateHelper(
|
|
172
|
+
validateAgainstSchema,
|
|
173
|
+
currentEnts,
|
|
174
|
+
changeForm,
|
|
175
|
+
`editableCellTable-${focusedTab}`
|
|
176
|
+
)
|
|
177
|
+
)
|
|
178
|
+
return;
|
|
179
|
+
setFocusedTab(nextUnfinishedFile);
|
|
180
|
+
} else {
|
|
181
|
+
//do async validation here if needed
|
|
182
|
+
for (const [i, ents] of finishedFiles.entries()) {
|
|
176
183
|
if (
|
|
177
184
|
await asyncValidateHelper(
|
|
178
185
|
validateAgainstSchema,
|
|
179
|
-
|
|
186
|
+
ents,
|
|
180
187
|
changeForm,
|
|
181
|
-
`editableCellTable-${
|
|
188
|
+
`editableCellTable-${i}`
|
|
182
189
|
)
|
|
183
190
|
)
|
|
184
191
|
return;
|
|
185
|
-
|
|
186
|
-
setFocusedTab(nextUnfinishedFile);
|
|
187
|
-
} else {
|
|
188
|
-
//do async validation here if needed
|
|
189
|
-
|
|
190
|
-
for (const [i, ents] of finishedFiles.entries()) {
|
|
191
|
-
if (
|
|
192
|
-
await asyncValidateHelper(
|
|
193
|
-
validateAgainstSchema,
|
|
194
|
-
ents,
|
|
195
|
-
changeForm,
|
|
196
|
-
`editableCellTable-${i}`
|
|
197
|
-
)
|
|
198
|
-
)
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
//we are done
|
|
203
|
-
onUploadWizardFinish({
|
|
204
|
-
res: finishedFiles.map(ents => {
|
|
205
|
-
return maybeStripIdFromEntities(
|
|
206
|
-
ents,
|
|
207
|
-
f.validateAgainstSchema
|
|
208
|
-
);
|
|
209
|
-
})
|
|
210
|
-
});
|
|
211
192
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
ignoredHeadersMsg,
|
|
223
|
-
searchResults,
|
|
224
|
-
matchedHeaders,
|
|
225
|
-
userSchema,
|
|
226
|
-
flippedMatchedHeaders,
|
|
227
|
-
// reduxFormEntities,
|
|
228
|
-
changeForm,
|
|
229
|
-
fileIndex: i,
|
|
230
|
-
form: `correctCSVHeadersForm-${i}`,
|
|
231
|
-
datatableFormName: `editableCellTable-${i}`,
|
|
232
|
-
...f,
|
|
233
|
-
...(doAllFilesHaveSameHeaders && {
|
|
234
|
-
csvValidationIssue: false
|
|
235
|
-
})
|
|
193
|
+
//we are done
|
|
194
|
+
onUploadWizardFinish({
|
|
195
|
+
res: finishedFiles.map(ents => {
|
|
196
|
+
return maybeStripIdFromEntities(
|
|
197
|
+
ents,
|
|
198
|
+
f.validateAgainstSchema
|
|
199
|
+
);
|
|
200
|
+
})
|
|
201
|
+
});
|
|
202
|
+
}
|
|
236
203
|
}}
|
|
204
|
+
validateAgainstSchema={validateAgainstSchema}
|
|
205
|
+
reduxFormEntitiesArray={reduxFormEntitiesArray}
|
|
206
|
+
filesWIssues={filesWIssues}
|
|
207
|
+
finishedFiles={finishedFiles}
|
|
208
|
+
onUploadWizardFinish={onUploadWizardFinish}
|
|
209
|
+
doAllFilesHaveSameHeaders={doAllFilesHaveSameHeaders}
|
|
210
|
+
setFilesWIssues={setFilesWIssues}
|
|
211
|
+
csvValidationIssue={csvValidationIssue}
|
|
212
|
+
ignoredHeadersMsg={ignoredHeadersMsg}
|
|
213
|
+
searchResults={searchResults}
|
|
214
|
+
matchedHeader={matchedHeaders}
|
|
215
|
+
userSchema={userSchema}
|
|
216
|
+
flippedMatchedHeaders={flippedMatchedHeaders}
|
|
217
|
+
changeForm={changeForm}
|
|
218
|
+
fileIndex={i}
|
|
219
|
+
form={`correctCSVHeadersForm-${i}`}
|
|
220
|
+
datatableFormName={`editableCellTable-${i}`}
|
|
221
|
+
{...f}
|
|
222
|
+
{...(doAllFilesHaveSameHeaders && {
|
|
223
|
+
csvValidationIssue: false
|
|
224
|
+
})}
|
|
237
225
|
/>
|
|
238
226
|
}
|
|
239
|
-
|
|
227
|
+
/>
|
|
240
228
|
);
|
|
241
229
|
})}
|
|
242
230
|
</Tabs>
|
|
@@ -248,34 +236,27 @@ const UploadCsvWizardDialog = compose(
|
|
|
248
236
|
comp = (
|
|
249
237
|
<>
|
|
250
238
|
{doAllFilesHaveSameHeaders && (
|
|
251
|
-
<SimpleStepViz
|
|
252
|
-
style={{ marginTop: 8 }}
|
|
253
|
-
steps={steps}
|
|
254
|
-
></SimpleStepViz>
|
|
239
|
+
<SimpleStepViz style={{ marginTop: 8 }} steps={steps} />
|
|
255
240
|
)}
|
|
256
241
|
|
|
257
242
|
{!hasSubmittedOuter && (
|
|
258
243
|
<MatchHeaders
|
|
259
|
-
{
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
filesWIssues,
|
|
276
|
-
fileIndex: 0,
|
|
277
|
-
...filesWIssues[0]
|
|
278
|
-
}}
|
|
244
|
+
doAllFilesHaveSameHeaders={doAllFilesHaveSameHeaders}
|
|
245
|
+
datatableFormNames={filesWIssues.map((f, i) => {
|
|
246
|
+
return `editableCellTable-${i}`;
|
|
247
|
+
})}
|
|
248
|
+
reduxFormEntitiesArray={reduxFormEntitiesArray}
|
|
249
|
+
csvValidationIssue={csvValidationIssue}
|
|
250
|
+
ignoredHeadersMsg={ignoredHeadersMsg}
|
|
251
|
+
searchResults={searchResults}
|
|
252
|
+
matchedHeaders={matchedHeaders}
|
|
253
|
+
userSchema={userSchema}
|
|
254
|
+
flippedMatchedHeaders={flippedMatchedHeaders}
|
|
255
|
+
changeForm={changeForm}
|
|
256
|
+
setFilesWIssues={setFilesWIssues}
|
|
257
|
+
filesWIssues={filesWIssues}
|
|
258
|
+
fileIndex={0}
|
|
259
|
+
{...filesWIssues[0]}
|
|
279
260
|
/>
|
|
280
261
|
)}
|
|
281
262
|
{hasSubmittedOuter && tabs}
|
|
@@ -287,230 +268,200 @@ const UploadCsvWizardDialog = compose(
|
|
|
287
268
|
setSteps(getInitialSteps(false));
|
|
288
269
|
}}
|
|
289
270
|
text="Review and Edit Data"
|
|
290
|
-
|
|
271
|
+
/>
|
|
291
272
|
)}
|
|
292
273
|
</>
|
|
293
274
|
);
|
|
294
275
|
}
|
|
295
|
-
return
|
|
296
|
-
<div
|
|
297
|
-
style={{
|
|
298
|
-
padding: 10
|
|
299
|
-
}}
|
|
300
|
-
>
|
|
301
|
-
{comp}
|
|
302
|
-
</div>
|
|
303
|
-
);
|
|
276
|
+
return <div style={{ padding: 10 }}>{comp}</div>;
|
|
304
277
|
} else {
|
|
305
278
|
return (
|
|
306
279
|
<UploadCsvWizardDialogInner
|
|
307
280
|
form="correctCSVHeadersForm"
|
|
308
|
-
{
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
flippedMatchedHeaders,
|
|
322
|
-
// reduxFormEntities,
|
|
323
|
-
// datatableFormNames
|
|
324
|
-
fileIndex: 0,
|
|
325
|
-
...filesWIssues[0]
|
|
326
|
-
}}
|
|
281
|
+
validateAgainstSchema={validateAgainstSchema}
|
|
282
|
+
userSchema={userSchema}
|
|
283
|
+
searchResults={searchResults}
|
|
284
|
+
onUploadWizardFinish={onUploadWizardFinish}
|
|
285
|
+
csvValidationIssue={csvValidationIssue}
|
|
286
|
+
ignoredHeadersMsg={ignoredHeadersMsg}
|
|
287
|
+
matchedHeaders={matchedHeaders}
|
|
288
|
+
changeForm={changeForm}
|
|
289
|
+
setFilesWIssues={setFilesWIssues}
|
|
290
|
+
filesWIssues={filesWIssues}
|
|
291
|
+
flippedMatchedHeaders={flippedMatchedHeaders}
|
|
292
|
+
fileIndex={0}
|
|
293
|
+
{...filesWIssues[0]}
|
|
327
294
|
/>
|
|
328
295
|
);
|
|
329
296
|
}
|
|
330
297
|
});
|
|
331
298
|
|
|
332
|
-
const UploadCsvWizardDialogInner =
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
changeForm,
|
|
356
|
-
setFilesWIssues,
|
|
357
|
-
doAllFilesHaveSameHeaders,
|
|
358
|
-
filesWIssues,
|
|
359
|
-
datatableFormName = "editableCellTable",
|
|
360
|
-
onMultiFileUploadSubmit,
|
|
361
|
-
isThisTheLastBadFile,
|
|
362
|
-
submitting
|
|
363
|
-
}) {
|
|
364
|
-
const [hasSubmitted, setSubmitted] = useState(!csvValidationIssue);
|
|
365
|
-
const [steps, setSteps] = useState(getInitialSteps(csvValidationIssue));
|
|
299
|
+
const UploadCsvWizardDialogInner = reduxForm()(
|
|
300
|
+
function UploadCsvWizardDialogInner({
|
|
301
|
+
validateAgainstSchema,
|
|
302
|
+
userSchema,
|
|
303
|
+
searchResults,
|
|
304
|
+
onUploadWizardFinish,
|
|
305
|
+
csvValidationIssue,
|
|
306
|
+
ignoredHeadersMsg,
|
|
307
|
+
matchedHeaders,
|
|
308
|
+
handleSubmit,
|
|
309
|
+
fileIndex,
|
|
310
|
+
onBackClick,
|
|
311
|
+
changeForm,
|
|
312
|
+
setFilesWIssues,
|
|
313
|
+
doAllFilesHaveSameHeaders,
|
|
314
|
+
filesWIssues,
|
|
315
|
+
datatableFormName = "editableCellTable",
|
|
316
|
+
onMultiFileUploadSubmit,
|
|
317
|
+
isThisTheLastBadFile,
|
|
318
|
+
submitting
|
|
319
|
+
}) {
|
|
320
|
+
const [hasSubmitted, setSubmitted] = useState(!csvValidationIssue);
|
|
321
|
+
const [steps, setSteps] = useState(getInitialSteps(csvValidationIssue));
|
|
366
322
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
showDoesDataLookCorrectMsg: true,
|
|
374
|
-
initialEntities: reduxFormEntities || null,
|
|
375
|
-
matchedHeaders,
|
|
376
|
-
validateAgainstSchema,
|
|
377
|
-
userSchema
|
|
378
|
-
}}
|
|
379
|
-
></PreviewCsvData>
|
|
323
|
+
const { reduxFormEntities, reduxFormCellValidation } = useSelector(state =>
|
|
324
|
+
formValueSelector(datatableFormName)(
|
|
325
|
+
state,
|
|
326
|
+
"reduxFormEntities",
|
|
327
|
+
"reduxFormCellValidation"
|
|
328
|
+
)
|
|
380
329
|
);
|
|
381
|
-
|
|
382
|
-
inner
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
matchedHeaders
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
330
|
+
|
|
331
|
+
let inner;
|
|
332
|
+
if (hasSubmitted) {
|
|
333
|
+
inner = (
|
|
334
|
+
<PreviewCsvData
|
|
335
|
+
datatableFormName={datatableFormName}
|
|
336
|
+
showDoesDataLookCorrectMsg
|
|
337
|
+
initialEntities={reduxFormEntities || null}
|
|
338
|
+
matchedHeaders={matchedHeaders}
|
|
339
|
+
validateAgainstSchema={validateAgainstSchema}
|
|
340
|
+
userSchema={userSchema}
|
|
341
|
+
/>
|
|
342
|
+
);
|
|
343
|
+
} else {
|
|
344
|
+
inner = (
|
|
345
|
+
<MatchHeaders
|
|
346
|
+
onMultiFileUploadSubmit={onMultiFileUploadSubmit}
|
|
347
|
+
csvValidationIssue={csvValidationIssue}
|
|
348
|
+
ignoredHeadersMsg={ignoredHeadersMsg}
|
|
349
|
+
searchResults={searchResults}
|
|
350
|
+
matchedHeaders={matchedHeaders}
|
|
351
|
+
userSchema={userSchema}
|
|
352
|
+
reduxFormEntitiesArray={[reduxFormEntities]}
|
|
353
|
+
changeForm={changeForm}
|
|
354
|
+
datatableFormName={datatableFormName}
|
|
355
|
+
setFilesWIssues={setFilesWIssues}
|
|
356
|
+
filesWIssues={filesWIssues}
|
|
357
|
+
fileIndex={fileIndex}
|
|
358
|
+
/>
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
const { entsToUse, validationToUse } = removeCleanRows(
|
|
362
|
+
reduxFormEntities,
|
|
363
|
+
reduxFormCellValidation
|
|
399
364
|
);
|
|
400
|
-
}
|
|
401
|
-
const { entsToUse, validationToUse } = removeCleanRows(
|
|
402
|
-
reduxFormEntities,
|
|
403
|
-
reduxFormCellValidation
|
|
404
|
-
);
|
|
405
365
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
onBackClick
|
|
435
|
-
|
|
366
|
+
return (
|
|
367
|
+
<div>
|
|
368
|
+
{!doAllFilesHaveSameHeaders && (
|
|
369
|
+
<SimpleStepViz style={{ marginTop: 8 }} steps={steps} />
|
|
370
|
+
)}
|
|
371
|
+
<div className="bp3-dialog-body">{inner}</div>
|
|
372
|
+
<DialogFooter
|
|
373
|
+
text={
|
|
374
|
+
!hasSubmitted
|
|
375
|
+
? "Review and Edit Data"
|
|
376
|
+
: onMultiFileUploadSubmit
|
|
377
|
+
? isThisTheLastBadFile
|
|
378
|
+
? "Finalize Files"
|
|
379
|
+
: "Next File"
|
|
380
|
+
: "Add File"
|
|
381
|
+
}
|
|
382
|
+
submitting={submitting}
|
|
383
|
+
disabled={
|
|
384
|
+
hasSubmitted &&
|
|
385
|
+
(!entsToUse?.length || some(validationToUse, v => v))
|
|
386
|
+
}
|
|
387
|
+
intent={
|
|
388
|
+
hasSubmitted && onMultiFileUploadSubmit && isThisTheLastBadFile
|
|
389
|
+
? Intent.SUCCESS
|
|
390
|
+
: Intent.PRIMARY
|
|
391
|
+
}
|
|
392
|
+
noCancel={onMultiFileUploadSubmit}
|
|
393
|
+
{...(hasSubmitted && {
|
|
394
|
+
onBackClick:
|
|
395
|
+
onBackClick ||
|
|
396
|
+
(() => {
|
|
397
|
+
setSteps(
|
|
398
|
+
immer(steps, draft => {
|
|
399
|
+
draft[0].active = true;
|
|
400
|
+
draft[0].completed = false;
|
|
401
|
+
draft[1].active = false;
|
|
402
|
+
})
|
|
403
|
+
);
|
|
404
|
+
setSubmitted(false);
|
|
405
|
+
})
|
|
406
|
+
})}
|
|
407
|
+
onClick={handleSubmit(async function () {
|
|
408
|
+
if (!hasSubmitted) {
|
|
409
|
+
//step 1 submit
|
|
436
410
|
setSteps(
|
|
437
411
|
immer(steps, draft => {
|
|
438
|
-
draft[0].active =
|
|
439
|
-
draft[0].completed =
|
|
440
|
-
draft[1].active =
|
|
412
|
+
draft[0].active = false;
|
|
413
|
+
draft[0].completed = true;
|
|
414
|
+
draft[1].active = true;
|
|
441
415
|
})
|
|
442
416
|
);
|
|
443
|
-
setSubmitted(
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
})
|
|
455
|
-
);
|
|
456
|
-
setSubmitted(true);
|
|
457
|
-
} else {
|
|
458
|
-
if (!onMultiFileUploadSubmit) {
|
|
459
|
-
//do async validation here if needed
|
|
460
|
-
if (
|
|
461
|
-
await asyncValidateHelper(
|
|
462
|
-
validateAgainstSchema,
|
|
463
|
-
entsToUse,
|
|
464
|
-
changeForm,
|
|
465
|
-
`editableCellTable`
|
|
417
|
+
setSubmitted(true);
|
|
418
|
+
} else {
|
|
419
|
+
if (!onMultiFileUploadSubmit) {
|
|
420
|
+
//do async validation here if needed
|
|
421
|
+
if (
|
|
422
|
+
await asyncValidateHelper(
|
|
423
|
+
validateAgainstSchema,
|
|
424
|
+
entsToUse,
|
|
425
|
+
changeForm,
|
|
426
|
+
`editableCellTable`
|
|
427
|
+
)
|
|
466
428
|
)
|
|
467
|
-
|
|
468
|
-
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
//step 2 submit
|
|
432
|
+
const payload = maybeStripIdFromEntities(
|
|
433
|
+
entsToUse,
|
|
434
|
+
validateAgainstSchema
|
|
435
|
+
);
|
|
436
|
+
return onMultiFileUploadSubmit
|
|
437
|
+
? await onMultiFileUploadSubmit()
|
|
438
|
+
: onUploadWizardFinish({ res: [payload] });
|
|
469
439
|
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
: onUploadWizardFinish({ res: [payload] });
|
|
478
|
-
}
|
|
479
|
-
})}
|
|
480
|
-
style={{ alignSelf: "end" }}
|
|
481
|
-
></DialogFooter>
|
|
482
|
-
</div>
|
|
483
|
-
);
|
|
484
|
-
});
|
|
440
|
+
})}
|
|
441
|
+
style={{ alignSelf: "end" }}
|
|
442
|
+
/>
|
|
443
|
+
</div>
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
);
|
|
485
447
|
|
|
486
448
|
export default UploadCsvWizardDialog;
|
|
487
449
|
|
|
488
450
|
const exampleData = { userData: times(5).map(() => ({ _isClean: true })) };
|
|
489
|
-
|
|
451
|
+
|
|
452
|
+
export const PreviewCsvData = observer(props => {
|
|
490
453
|
const {
|
|
491
454
|
matchedHeaders,
|
|
492
455
|
isEditingExistingFile,
|
|
493
456
|
showDoesDataLookCorrectMsg,
|
|
494
457
|
headerMessage,
|
|
495
458
|
datatableFormName,
|
|
496
|
-
// onlyShowRowsWErrors,
|
|
497
459
|
validateAgainstSchema,
|
|
498
460
|
userSchema = exampleData,
|
|
499
461
|
initialEntities
|
|
500
462
|
} = props;
|
|
501
463
|
const rerenderKey = useRef(0);
|
|
502
464
|
rerenderKey.current = rerenderKey.current + 1;
|
|
503
|
-
// const useExampleData = userSchema === exampleData;
|
|
504
|
-
// const [loading, setLoading] = useState(true);
|
|
505
|
-
// useEffect(() => {
|
|
506
|
-
// // simulate layout change outside of React lifecycle
|
|
507
|
-
// setTimeout(() => {
|
|
508
|
-
// setLoading(false);
|
|
509
|
-
// }, 400);
|
|
510
|
-
// }, []);
|
|
511
|
-
|
|
512
|
-
// const [val, forceUpdate] = useForceUpdate();
|
|
513
|
-
|
|
514
465
|
const data =
|
|
515
466
|
userSchema.userData &&
|
|
516
467
|
userSchema.userData.length &&
|
|
@@ -575,7 +526,7 @@ export const PreviewCsvData = observer(function (props) {
|
|
|
575
526
|
<validateAgainstSchema.HeaderComp
|
|
576
527
|
{...props}
|
|
577
528
|
// {...{ forceUpdate }}
|
|
578
|
-
|
|
529
|
+
/>
|
|
579
530
|
)}
|
|
580
531
|
</div>
|
|
581
532
|
<DataTable
|
|
@@ -591,7 +542,7 @@ export const PreviewCsvData = observer(function (props) {
|
|
|
591
542
|
initialEntities={(initialEntities ? initialEntities : data) || []}
|
|
592
543
|
entities={(initialEntities ? initialEntities : data) || []}
|
|
593
544
|
schema={validateAgainstSchema}
|
|
594
|
-
|
|
545
|
+
/>
|
|
595
546
|
</div>
|
|
596
547
|
);
|
|
597
548
|
});
|
|
@@ -608,14 +559,12 @@ export const SimpleInsertDataDialog = compose(
|
|
|
608
559
|
"reduxFormEntities",
|
|
609
560
|
"reduxFormCellValidation"
|
|
610
561
|
),
|
|
611
|
-
connect(undefined, { changeForm: change }),
|
|
612
562
|
observer
|
|
613
563
|
)(function SimpleInsertDataDialog({
|
|
614
564
|
onSimpleInsertDialogFinish,
|
|
615
565
|
reduxFormEntities,
|
|
616
566
|
reduxFormCellValidation,
|
|
617
567
|
validateAgainstSchema,
|
|
618
|
-
changeForm,
|
|
619
568
|
submitting,
|
|
620
569
|
isEditingExistingFile,
|
|
621
570
|
matchedHeaders,
|
|
@@ -625,11 +574,14 @@ export const SimpleInsertDataDialog = compose(
|
|
|
625
574
|
userSchema,
|
|
626
575
|
initialEntities
|
|
627
576
|
}) {
|
|
577
|
+
const dispatch = useDispatch();
|
|
628
578
|
const { entsToUse, validationToUse } = removeCleanRows(
|
|
629
579
|
reduxFormEntities,
|
|
630
580
|
reduxFormCellValidation
|
|
631
581
|
);
|
|
632
582
|
|
|
583
|
+
const changeForm = (...args) => dispatch(change(...args));
|
|
584
|
+
|
|
633
585
|
return (
|
|
634
586
|
<>
|
|
635
587
|
<div className="bp3-dialog-body">
|
|
@@ -642,20 +594,17 @@ export const SimpleInsertDataDialog = compose(
|
|
|
642
594
|
label="File Name:"
|
|
643
595
|
defaultValue={"manual_data_entry"}
|
|
644
596
|
name="fileName"
|
|
645
|
-
|
|
597
|
+
/>
|
|
646
598
|
<PreviewCsvData
|
|
647
|
-
{
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
datatableFormName: "simpleInsertEditableTable"
|
|
657
|
-
}}
|
|
658
|
-
></PreviewCsvData>
|
|
599
|
+
matchedHeaders={matchedHeaders}
|
|
600
|
+
isEditingExistingFile={isEditingExistingFile}
|
|
601
|
+
showDoesDataLookCorrectMsg={showDoesDataLookCorrectMsg}
|
|
602
|
+
headerMessage={headerMessage}
|
|
603
|
+
validateAgainstSchema={validateAgainstSchema}
|
|
604
|
+
userSchema={userSchema}
|
|
605
|
+
initialEntities={initialEntities}
|
|
606
|
+
datatableFormName={"simpleInsertEditableTable"}
|
|
607
|
+
/>
|
|
659
608
|
</div>
|
|
660
609
|
<DialogFooter
|
|
661
610
|
submitting={submitting}
|
|
@@ -681,7 +630,7 @@ export const SimpleInsertDataDialog = compose(
|
|
|
681
630
|
})}
|
|
682
631
|
disabled={!entsToUse?.length || some(validationToUse, e => e)}
|
|
683
632
|
text={isEditingExistingFile ? "Edit Data" : "Add File"}
|
|
684
|
-
|
|
633
|
+
/>
|
|
685
634
|
</>
|
|
686
635
|
);
|
|
687
636
|
});
|
|
@@ -715,11 +664,3 @@ function maybeStripIdFromEntities(ents, validateAgainstSchema) {
|
|
|
715
664
|
}
|
|
716
665
|
return toRet?.map(e => omit(e, ["_isClean"]));
|
|
717
666
|
}
|
|
718
|
-
|
|
719
|
-
//create your forceUpdate hook
|
|
720
|
-
// function useForceUpdate() {
|
|
721
|
-
// const [val, setValue] = useState(0); // integer state
|
|
722
|
-
// return [val, () => setValue(value => value + 1)]; // update state to force render
|
|
723
|
-
// // A function that increment 👆🏻 the previous state like here
|
|
724
|
-
// // is better than directly setting `setValue(value + 1)`
|
|
725
|
-
// }
|