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