fuse-importer 0.24.4 → 0.25.0
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/README.md +14 -5
- package/lib/esm/Importer/ImporterWithContext.js +1 -1
- package/lib/esm/Importer/common/Spreadsheet/SpreadsheetContextProvider.d.ts +2 -0
- package/lib/esm/Importer/common/Spreadsheet/SpreadsheetContextProvider.js +17 -7
- package/lib/esm/Importer/common/Spreadsheet/components/FieldHeader.d.ts +1 -0
- package/lib/esm/Importer/common/Spreadsheet/components/FieldHeader.js +9 -3
- package/lib/esm/Importer/common/Spreadsheet/components/SpreadsheetData.js +7 -2
- package/lib/esm/Importer/common/Spreadsheet/components/fields/SpeadsheetAutocomplete.js +10 -6
- package/lib/esm/Importer/common/Spreadsheet/components/fields/SpreadsheetInput.d.ts +1 -0
- package/lib/esm/Importer/common/Spreadsheet/components/fields/SpreadsheetInput.js +7 -5
- package/lib/esm/Importer/common/Spreadsheet/components/fields/index.d.ts +4 -2
- package/lib/esm/Importer/common/Spreadsheet/components/fields/index.js +12 -9
- package/lib/esm/Importer/common/Spreadsheet/hooks.d.ts +5 -0
- package/lib/esm/Importer/common/Spreadsheet/hooks.js +53 -20
- package/lib/esm/Importer/common/Spreadsheet/validation/index.d.ts +4 -1
- package/lib/esm/Importer/common/Spreadsheet/validation/index.js +39 -15
- package/lib/esm/Importer/common/theme.d.ts +2 -0
- package/lib/esm/Importer/data/index.js +0 -1
- package/lib/esm/styled/theme/colorPalette.d.ts +4 -0
- package/lib/esm/styled/theme/colorPalette.js +2 -0
- package/lib/esm/styled/theme/index.d.ts +2 -0
- package/lib/esm/types.d.ts +6 -2
- package/lib/main.js +5 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -80,7 +80,7 @@ If you don't have an account yet, you can go over the [Registration](https://fus
|
|
|
80
80
|
|
|
81
81
|
## Create Your First Importer
|
|
82
82
|
|
|
83
|
-
If you don’t have
|
|
83
|
+
If you don’t have an Importer yet, you can go over [Create Your First Importer](https://fuse-docs.flatirons.com/getting-started/create-your-first-template?utm_source=npmjs&utm_medium=Create+Your+First+Template&utm_campaign=NPM). Importer represents the fields and validations that your own system accepts, also known as your data schema.
|
|
84
84
|
|
|
85
85
|
## Getting started
|
|
86
86
|
|
|
@@ -180,26 +180,35 @@ importer.onClose = () => {
|
|
|
180
180
|
|
|
181
181
|
#### `onValidateRecord`
|
|
182
182
|
|
|
183
|
-
The `onValidationRecord` hook is called for each row (record) that a customer uploads. It allows you to specify custom frontend validations and display error messages in the importer for the user to fix. When you create
|
|
183
|
+
The `onValidationRecord` hook is called for each row (record) that a customer uploads. It allows you to specify custom frontend validations and display error messages in the importer for the user to fix. When you create an importer, each column contains an `internal key`. These internal keys represent the
|
|
184
184
|
|
|
185
185
|
Return values:
|
|
186
186
|
|
|
187
|
-
- If the record has no errors, we expect you to return an empty object: `return {}
|
|
188
|
-
- If the record has validation errors, you can specify them like
|
|
187
|
+
- If the record has no errors, we expect you to return an empty object: `return {}`.
|
|
188
|
+
- If the record has validation errors, you can specify them like below.
|
|
189
|
+
- If the record has validation warnings, you can specify them like so:
|
|
189
190
|
|
|
190
191
|
```typescript
|
|
191
192
|
importer.onValidateRecord = async (record) => {
|
|
192
193
|
const errors = {};
|
|
194
|
+
const warnings = {};
|
|
193
195
|
|
|
194
196
|
// force emails to include gmail
|
|
195
197
|
if (!record.email?.includes("gmail")) {
|
|
196
198
|
errors["email"] = "Email must be from Gmail";
|
|
197
199
|
}
|
|
198
200
|
|
|
199
|
-
|
|
201
|
+
// email should be from the domain.
|
|
202
|
+
if (!record.email?.includes("@example.com")) {
|
|
203
|
+
warnings["email"] = "Email is outside the domain";
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return { errors: errors, warnings: warnings };
|
|
200
207
|
};
|
|
201
208
|
```
|
|
202
209
|
|
|
210
|
+
`warnings` will still allow you to submit the spreadsheet, unlike `errors`.
|
|
211
|
+
|
|
203
212
|
#### `formatRecord`
|
|
204
213
|
|
|
205
214
|
The `formatRecord` hook can be used to format data automatically on behalf of a user. For example, if you have a field called `first_name` and you know that your system always requires `first_name` to be capitalized, you can use this callback to uppercase all `first_name` records like so:
|
|
@@ -51,7 +51,7 @@ var Content = styled(Div)(function (_a) {
|
|
|
51
51
|
return css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n background-color: ", ";\n padding-bottom: 70px;\n "], ["\n background-color: ", ";\n padding-bottom: 70px;\n "])), colors.backgroundInterface);
|
|
52
52
|
});
|
|
53
53
|
export var ImporterWithContext = function () {
|
|
54
|
-
var _a = useImporterContext(), inTrialMode = _a.inTrialMode, currentStepIndex = _a.currentStepIndex, matcherSubstep = _a.matcherSubstep, theme = _a.theme, logoURL = _a.logoURL, previewFirstTime = _a.previewFirstTime, _b = _a.importerOptions, zIndex = _b.zIndex,
|
|
54
|
+
var _a = useImporterContext(), inTrialMode = _a.inTrialMode, currentStepIndex = _a.currentStepIndex, matcherSubstep = _a.matcherSubstep, theme = _a.theme, logoURL = _a.logoURL, previewFirstTime = _a.previewFirstTime, _b = _a.importerOptions, zIndex = _b.zIndex, previewMode = _b.previewMode;
|
|
55
55
|
var layoutRef = useRef(null);
|
|
56
56
|
var t = useTranslation().t;
|
|
57
57
|
useEffect(function () {
|
|
@@ -13,11 +13,13 @@ type State = {
|
|
|
13
13
|
highlightFirstRow: boolean;
|
|
14
14
|
options: SpreadsheetOptions;
|
|
15
15
|
sortByFieldErrors: string;
|
|
16
|
+
sortByFieldWarnings: string;
|
|
16
17
|
updateRecord: (record: Record) => void;
|
|
17
18
|
setIsLoading: React.Dispatch<React.SetStateAction<boolean>>;
|
|
18
19
|
setSortByFieldErrors: React.Dispatch<React.SetStateAction<string>>;
|
|
19
20
|
selectedRows: number[];
|
|
20
21
|
setSelectedRows: React.Dispatch<React.SetStateAction<number[]>>;
|
|
22
|
+
setSortByFieldWarnings: React.Dispatch<React.SetStateAction<string>>;
|
|
21
23
|
} & ValidationState;
|
|
22
24
|
type Props = {
|
|
23
25
|
initialDataSet: RecordDataSet;
|
|
@@ -30,8 +30,10 @@ export var SpreadsheetContextProvider = function (_a) {
|
|
|
30
30
|
var _c = useState(initialDataSet), dataSet = _c[0], setDataSet = _c[1];
|
|
31
31
|
var _d = useState(false), isLoading = _d[0], setIsLoading = _d[1];
|
|
32
32
|
var _e = useState(null), sortByFieldErrors = _e[0], setSortByFieldErrors = _e[1];
|
|
33
|
+
var _f = useState(null), sortByFieldWarnings = _f[0], setSortByFieldWarnings = _f[1];
|
|
33
34
|
var sortByCurrentErrorsRef = useRef({});
|
|
34
|
-
var
|
|
35
|
+
var sortByCurrentWarningsRef = useRef({});
|
|
36
|
+
var _g = useValidationState({
|
|
35
37
|
dataSet: dataSet,
|
|
36
38
|
initialDataSet: initialDataSet,
|
|
37
39
|
fields: fields,
|
|
@@ -40,22 +42,23 @@ export var SpreadsheetContextProvider = function (_a) {
|
|
|
40
42
|
setDataSet: setDataSet,
|
|
41
43
|
setIsLoading: setIsLoading,
|
|
42
44
|
onValidateRecord: onValidateRecord,
|
|
43
|
-
}), errorsRef =
|
|
45
|
+
}), errorsRef = _g.errorsRef, warningsRef = _g.warningsRef, updateRecordAndRevalidate = _g.updateRecordAndRevalidate, validationState = __rest(_g, ["errorsRef", "warningsRef", "updateRecordAndRevalidate"]);
|
|
44
46
|
// sort data based on errors (errors group on top and not errors group at bottom)
|
|
45
47
|
var data = useMemo(function () {
|
|
46
48
|
var errors = sortByCurrentErrorsRef.current; //Sort errors snapshot
|
|
49
|
+
var warnings = sortByCurrentWarningsRef.current; //Sort warnings snapshot
|
|
47
50
|
var dataSetValues = Object.values(dataSet);
|
|
48
|
-
if (!sortByFieldErrors)
|
|
51
|
+
if (!sortByFieldErrors && !sortByFieldWarnings)
|
|
49
52
|
return dataSetValues;
|
|
50
53
|
return dataSetValues.sort(function (a, b) {
|
|
51
|
-
var aHasErrors = !!get(errors, "".concat(get(a, "_meta.id"), ".").concat(sortByFieldErrors), false);
|
|
52
|
-
var bHasErrors = !!get(errors, "".concat(get(b, "_meta.id"), ".").concat(sortByFieldErrors), false);
|
|
54
|
+
var aHasErrors = !!get(sortByFieldErrors ? errors : warnings, "".concat(get(a, "_meta.id"), ".").concat(sortByFieldErrors || sortByFieldWarnings), false);
|
|
55
|
+
var bHasErrors = !!get(sortByFieldErrors ? errors : warnings, "".concat(get(b, "_meta.id"), ".").concat(sortByFieldErrors || sortByFieldWarnings), false);
|
|
53
56
|
if (aHasErrors === bHasErrors) {
|
|
54
57
|
return a._meta.rowIndex > b._meta.rowIndex ? 1 : -1;
|
|
55
58
|
}
|
|
56
59
|
return bHasErrors ? 1 : -1;
|
|
57
60
|
});
|
|
58
|
-
}, [dataSet, sortByFieldErrors]);
|
|
61
|
+
}, [dataSet, sortByFieldErrors, sortByFieldWarnings]);
|
|
59
62
|
useEffect(function () {
|
|
60
63
|
onDataSetChanged && onDataSetChanged(dataSet);
|
|
61
64
|
}, [dataSet]);
|
|
@@ -69,8 +72,15 @@ export var SpreadsheetContextProvider = function (_a) {
|
|
|
69
72
|
//current errors snapshot for use on sort to keep data sorted without changing with each edit or revalidation.
|
|
70
73
|
sortByCurrentErrorsRef.current = __assign({}, errorsRef.current);
|
|
71
74
|
setSortByFieldErrors(value);
|
|
75
|
+
setSortByFieldWarnings(null);
|
|
72
76
|
}, []);
|
|
73
|
-
var
|
|
77
|
+
var handleSortByFieldWarnings = useCallback(function (value) {
|
|
78
|
+
//current errors snapshot for use on sort to keep data sorted without changing with each edit or revalidation.
|
|
79
|
+
sortByCurrentWarningsRef.current = __assign({}, warningsRef.current);
|
|
80
|
+
setSortByFieldWarnings(value);
|
|
81
|
+
setSortByFieldErrors(null);
|
|
82
|
+
}, []);
|
|
83
|
+
var value = __assign(__assign({ data: data, fields: fields, isLoading: isLoading }, validationState), { isReadOnly: isReadOnly, rowWidth: rowWidth, sortByFieldErrors: sortByFieldErrors, sortByFieldWarnings: sortByFieldWarnings, highlightFirstRow: highlightFirstRow, options: options, setIsLoading: setIsLoading, setSortByFieldErrors: handleSortByFieldErrors, setSortByFieldWarnings: handleSortByFieldWarnings, onValidateRecord: onValidateRecord, updateRecord: updateRecordAndRevalidate, selectedRows: selectedRows, setSelectedRows: setSelectedRows });
|
|
74
84
|
return (_jsx(SpreadsheetContext.Provider, __assign({ value: value }, { children: children })));
|
|
75
85
|
};
|
|
76
86
|
export var useSpreadsheetContext = function () { return useContext(SpreadsheetContext); };
|
|
@@ -14,6 +14,7 @@ var __assign = (this && this.__assign) || function () {
|
|
|
14
14
|
return __assign.apply(this, arguments);
|
|
15
15
|
};
|
|
16
16
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
17
|
+
import { colors } from "../../../../styled/theme/colorPalette";
|
|
17
18
|
import styled, { css } from "styled-components";
|
|
18
19
|
import { TooltipProvider } from "../../../../common";
|
|
19
20
|
import { Div } from "../../../../styled/utils";
|
|
@@ -23,9 +24,14 @@ var ErrorCount = styled(Div)(function (_a) {
|
|
|
23
24
|
return css(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n color: ", ";\n background: ", ";\n border: solid 1px ", ";\n padding: 4px 7px;\n border-radius: 56px;\n min-width: 24px;\n ", ";\n "], ["\n color: ", ";\n background: ", ";\n border: solid 1px ", ";\n padding: 4px 7px;\n border-radius: 56px;\n min-width: 24px;\n ", ";\n "])), colors.error, colors.red100, colors.error, c.centered);
|
|
24
25
|
});
|
|
25
26
|
export var FieldHeader = function (_a) {
|
|
26
|
-
var field = _a.field, sortByFieldErrors = _a.sortByFieldErrors;
|
|
27
|
-
var
|
|
27
|
+
var field = _a.field, sortByFieldErrors = _a.sortByFieldErrors, sortByFieldWarnings = _a.sortByFieldWarnings;
|
|
28
|
+
var _b = useSpreadsheetContext(), columnErrorCounts = _b.columnErrorCounts, columnWarningCounts = _b.columnWarningCounts;
|
|
28
29
|
var fieldErrorCount = columnErrorCounts[field.name];
|
|
29
|
-
|
|
30
|
+
var fieldWarningCount = columnWarningCounts[field.name];
|
|
31
|
+
return (_jsxs(Div, __assign({ "data-test-id": "column-header-".concat(field.name), p: "0 16px", spaceBetween: true, w100: true, alignCenter: true }, { children: [_jsxs(Div, __assign({ truncateText: true }, { children: [field.label, field.isRequired && "*"] })), fieldErrorCount && (_jsx(TooltipProvider, __assign({ mr: 3, w: 35, tooltip: "Sort by ".concat(field.label, " errors") }, { children: _jsx(ErrorCount, __assign({ "data-test-id": "column-errors-count-".concat(field.name), onClick: function () { return sortByFieldErrors(field.name); } }, { children: _jsx(Div, __assign({ centered: true }, { children: _jsx(Div, __assign({ w: 35, textAlignCenter: true, label3: true, truncateText: true }, { children: fieldErrorCount })) })) })) }))), !fieldErrorCount && fieldWarningCount && (_jsx(TooltipProvider, __assign({ mr: 3, w: 35, tooltip: "Sort by ".concat(field.label, " errors") }, { children: _jsx(ErrorCount, __assign({ style: {
|
|
32
|
+
color: colors.orange1200,
|
|
33
|
+
background: colors.orange1100,
|
|
34
|
+
boxShadow: "0px 0px 0px 1px ".concat(colors.orange500, " inset"),
|
|
35
|
+
}, "data-test-id": "column-errors-count-".concat(field.name), onClick: function () { return sortByFieldWarnings(field.name); } }, { children: _jsx(Div, __assign({ centered: true }, { children: _jsx(Div, __assign({ w: 35, textAlignCenter: true, label3: true, truncateText: true }, { children: fieldWarningCount })) })) })) })))] })));
|
|
30
36
|
};
|
|
31
37
|
var templateObject_1;
|
|
@@ -36,7 +36,7 @@ import { SpreadsheetRowCheckboxes } from "./SpreadsheetRowCheckboxes";
|
|
|
36
36
|
import ValidationProgress from "./ValidationProgress";
|
|
37
37
|
var getItemKey = function (record) { return record._meta.id; };
|
|
38
38
|
var SpreadsheetData = function () {
|
|
39
|
-
var _a = useSpreadsheetContext(), fields = _a.fields, data = _a.data, isLoading = _a.isLoading, isReadOnly = _a.isReadOnly, rowWidth = _a.rowWidth, totalErrors = _a.totalErrors, validationPercentage = _a.validationPercentage, setSortByFieldErrors = _a.setSortByFieldErrors, options = _a.options;
|
|
39
|
+
var _a = useSpreadsheetContext(), fields = _a.fields, data = _a.data, isLoading = _a.isLoading, isReadOnly = _a.isReadOnly, rowWidth = _a.rowWidth, totalErrors = _a.totalErrors, validationPercentage = _a.validationPercentage, setSortByFieldErrors = _a.setSortByFieldErrors, options = _a.options, setSortByFieldWarnings = _a.setSortByFieldWarnings;
|
|
40
40
|
var rowNumbersGridRef = useRef();
|
|
41
41
|
var rowCheckboxesGridRef = useRef();
|
|
42
42
|
var sortByErrors = useCallback(function (field) {
|
|
@@ -44,9 +44,14 @@ var SpreadsheetData = function () {
|
|
|
44
44
|
return sortByFieldErrors === field ? null : field;
|
|
45
45
|
});
|
|
46
46
|
}, []);
|
|
47
|
+
var sortByWarnings = useCallback(function (field) {
|
|
48
|
+
return setSortByFieldWarnings(function (sortByFieldWarnings) {
|
|
49
|
+
return sortByFieldWarnings === field ? null : field;
|
|
50
|
+
});
|
|
51
|
+
}, []);
|
|
47
52
|
var columns = useMemo(function () {
|
|
48
53
|
return fields.map(function (field) { return ({
|
|
49
|
-
Header: function () { return (_jsx(FieldHeader, { field: field, sortByFieldErrors: sortByErrors })); },
|
|
54
|
+
Header: function () { return (_jsx(FieldHeader, { field: field, sortByFieldErrors: sortByErrors, sortByFieldWarnings: sortByWarnings })); },
|
|
50
55
|
Content: function (record) {
|
|
51
56
|
var Input = inputTypes[field.type];
|
|
52
57
|
var rowIndex = record.rowIndex, recordProp = __rest(record, ["rowIndex"]);
|
|
@@ -20,15 +20,19 @@ import { Autocomplete as AutocompleteBase, } from "../../../../../common/inputs/
|
|
|
20
20
|
import { SelectMenuDiv, SelectMenuScrollArea, } from "../../../../../common/inputs/SelectMenu";
|
|
21
21
|
import { HTMLInput, TextInputIcon, } from "../../../../../common/inputs/TextInput";
|
|
22
22
|
import { spreadsheetRowHeightPx } from "../../common";
|
|
23
|
-
var Autocomplete = styled(AutocompleteBase)(
|
|
24
|
-
return p.
|
|
23
|
+
var Autocomplete = styled(AutocompleteBase)(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n ", " {\n border: none;\n border-radius: 0;\n margin: 0;\n background: transparent;\n height: ", "px;\n padding: 0 12px;\n\n ", "\n\n ::placeholder {\n ", "\n\n ", "\n\n ::placeholder {\n ", "\n }\n }\n :focus {\n border: none;\n box-shadow: none;\n }\n }\n ", " {\n right: 6px;\n }\n ", " {\n border-radius: 7px;\n }\n ", " {\n padding: 4px;\n }\n"], ["\n ", " {\n border: none;\n border-radius: 0;\n margin: 0;\n background: transparent;\n height: ", "px;\n padding: 0 12px;\n\n ", "\n\n ::placeholder {\n ", "\n\n ", "\n\n ::placeholder {\n ", "\n }\n }\n :focus {\n border: none;\n box-shadow: none;\n }\n }\n ", " {\n right: 6px;\n }\n ", " {\n border-radius: 7px;\n }\n ", " {\n padding: 4px;\n }\n"])), HTMLInput, spreadsheetRowHeightPx - 5, function (p) {
|
|
24
|
+
return p.hasWarning && css(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n color: ", ";\n "], ["\n color: ", ";\n "])), function (p) { return p.theme.colors.orange1200; });
|
|
25
25
|
}, function (p) {
|
|
26
|
-
return p.
|
|
26
|
+
return p.hasWarning && css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n color: ", ";\n "], ["\n color: ", ";\n "])), function (p) { return p.theme.colors.orange1200; });
|
|
27
|
+
}, function (p) {
|
|
28
|
+
return p.hasError && css(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n color: ", ";\n "], ["\n color: ", ";\n "])), function (p) { return p.theme.colors.error; });
|
|
29
|
+
}, function (p) {
|
|
30
|
+
return p.hasError && css(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n color: ", ";\n "], ["\n color: ", ";\n "])), function (p) { return p.theme.colors.error; });
|
|
27
31
|
}, TextInputIcon, SelectMenuDiv, SelectMenuScrollArea);
|
|
28
32
|
export var SpreadsheetAutocomplete = function (props) {
|
|
29
33
|
var name = props.name, record = props.record, options = props.options, fieldType = props.fieldType, _a = props.isInputDisabled, isInputDisabled = _a === void 0 ? false : _a, id = props.id;
|
|
30
|
-
var _b = useSpreadsheetField(name, record, fieldType), value = _b.value, setValue = _b.setValue, validationError = _b.validationError;
|
|
31
|
-
return (_jsx(SpreadsheetField, __assign({ validationError: validationError }, { children: _jsx(Autocomplete, { placement: "bottom", isInputDisabled: isInputDisabled, hasError: !!validationError, options: options, value: value, icon: chevronDownIcon, onChange: function (v) { return setValue(v); }, id: id }) })));
|
|
34
|
+
var _b = useSpreadsheetField(name, record, fieldType), value = _b.value, setValue = _b.setValue, validationError = _b.validationError, validationWarning = _b.validationWarning;
|
|
35
|
+
return (_jsx(SpreadsheetField, __assign({ validationError: validationError, validationWarning: validationWarning }, { children: _jsx(Autocomplete, { placement: "bottom", isInputDisabled: isInputDisabled, hasError: !!validationError, hasWarning: !!validationWarning, options: options, value: value, icon: chevronDownIcon, onChange: function (v) { return setValue(v); }, id: id }) })));
|
|
32
36
|
};
|
|
33
37
|
var chevronDownIcon = (_jsx("svg", __assign({ width: "10", height: "6", viewBox: "0 0 10 6", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, { children: _jsx("path", { d: "M8.46289 1L4.98131 4.48159L1.49972 1", stroke: "black", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })));
|
|
34
|
-
var templateObject_1, templateObject_2, templateObject_3;
|
|
38
|
+
var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5;
|
|
@@ -8,4 +8,5 @@ export type SpreadsheetTextInputArgs = {
|
|
|
8
8
|
export declare const SpreadsheetInput: ({ name, record, fieldType, ...props }: SpreadsheetTextInputArgs) => JSX.Element;
|
|
9
9
|
export declare const Input: import("styled-components").StyledComponent<"input", import("styled-components").DefaultTheme, {
|
|
10
10
|
hasError: boolean;
|
|
11
|
+
hasWarning?: boolean;
|
|
11
12
|
} & import("../../../../../styled/utils").HTMLInputProps & import("../../../../../styled/utils").CSSProps, never>;
|
|
@@ -29,13 +29,15 @@ import styled, { css } from "styled-components";
|
|
|
29
29
|
import { SpreadsheetField, useSpreadsheetField } from ".";
|
|
30
30
|
export var SpreadsheetInput = function (_a) {
|
|
31
31
|
var name = _a.name, record = _a.record, fieldType = _a.fieldType, props = __rest(_a, ["name", "record", "fieldType"]);
|
|
32
|
-
var _b = useSpreadsheetField(name, record, fieldType), value = _b.value, setValue = _b.setValue, validationError = _b.validationError;
|
|
33
|
-
return (_jsx(SpreadsheetField, __assign({ validationError: validationError }, { children: _jsx(Input, __assign({ hasError: !!validationError, value: value || "", onChange: function (_a) {
|
|
32
|
+
var _b = useSpreadsheetField(name, record, fieldType), value = _b.value, setValue = _b.setValue, validationError = _b.validationError, validationWarning = _b.validationWarning;
|
|
33
|
+
return (_jsx(SpreadsheetField, __assign({ validationError: validationError, validationWarning: validationWarning }, { children: _jsx(Input, __assign({ hasError: !!validationError, hasWarning: !!validationWarning, value: value || "", onChange: function (_a) {
|
|
34
34
|
var value = _a.target.value;
|
|
35
35
|
return setValue(value);
|
|
36
36
|
} }, props)) })));
|
|
37
37
|
};
|
|
38
|
-
export var Input = styled.input(
|
|
39
|
-
return p.
|
|
38
|
+
export var Input = styled.input(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n outline: none;\n border: none;\n width: 100%;\n height: calc(100% - 2px);\n background: transparent;\n box-sizing: border-box;\n\n ::-webkit-outer-spin-button,\n ::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n }\n /* Firefox */\n -moz-appearance: textfield;\n\n padding: 0 12px;\n ", ";\n color: ", ";\n ::placeholder {\n color: ", ";\n }\n\n ", "\n\n ", "\n"], ["\n outline: none;\n border: none;\n width: 100%;\n height: calc(100% - 2px);\n background: transparent;\n box-sizing: border-box;\n\n ::-webkit-outer-spin-button,\n ::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n }\n /* Firefox */\n -moz-appearance: textfield;\n\n padding: 0 12px;\n ", ";\n color: ", ";\n ::placeholder {\n color: ", ";\n }\n\n ", "\n\n ", "\n"])), function (props) { return props.theme.css.body1; }, function (props) { return props.theme.colors.gray1000; }, function (props) { return props.theme.colors.placeholder; }, function (p) {
|
|
39
|
+
return p.hasWarning && css(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n color: ", ";\n "], ["\n color: ", ";\n "])), function (p) { return p.theme.colors.orange1200; });
|
|
40
|
+
}, function (p) {
|
|
41
|
+
return p.hasError && css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n color: ", ";\n "], ["\n color: ", ";\n "])), function (p) { return p.theme.colors.error; });
|
|
40
42
|
});
|
|
41
|
-
var templateObject_1, templateObject_2;
|
|
43
|
+
var templateObject_1, templateObject_2, templateObject_3;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { FieldTypes, Record } from "../../../../../types";
|
|
2
|
-
export declare const useSpreadsheetField: (name:
|
|
2
|
+
export declare const useSpreadsheetField: (name: string, record: Record, fieldType: FieldTypes) => {
|
|
3
3
|
value: any;
|
|
4
4
|
setValue: (value: any) => void;
|
|
5
5
|
validationError: any;
|
|
6
|
+
validationWarning: any;
|
|
6
7
|
};
|
|
7
|
-
export declare const SpreadsheetField: ({ validationError, children }: {
|
|
8
|
+
export declare const SpreadsheetField: ({ validationError, validationWarning, children, }: {
|
|
8
9
|
validationError: any;
|
|
10
|
+
validationWarning: any;
|
|
9
11
|
children: any;
|
|
10
12
|
}) => JSX.Element;
|
|
@@ -58,9 +58,10 @@ import { Div } from "../../../../../styled/utils";
|
|
|
58
58
|
import { parseValue } from "../../common";
|
|
59
59
|
import { useSpreadsheetContext } from "../../SpreadsheetContextProvider";
|
|
60
60
|
export var useSpreadsheetField = function (name, record, fieldType) {
|
|
61
|
-
var _a = useSpreadsheetContext(), updateRecord = _a.updateRecord, errors = _a.errors;
|
|
61
|
+
var _a = useSpreadsheetContext(), updateRecord = _a.updateRecord, errors = _a.errors, warnings = _a.warnings;
|
|
62
62
|
var _b = useState(record[name]), value = _b[0], setValue = _b[1];
|
|
63
63
|
var validationError = get(errors, "".concat(record._meta.id, ".").concat(name), null);
|
|
64
|
+
var validationWarning = get(warnings, "".concat(record._meta.id, ".").concat(name), null);
|
|
64
65
|
var updateData = useCallback(debounce(function (value) { return __awaiter(void 0, void 0, void 0, function () {
|
|
65
66
|
var newRecord;
|
|
66
67
|
var _a;
|
|
@@ -74,20 +75,22 @@ export var useSpreadsheetField = function (name, record, fieldType) {
|
|
|
74
75
|
setValue(value);
|
|
75
76
|
updateData(value);
|
|
76
77
|
}, [record, updateData]);
|
|
77
|
-
return { value: value, setValue: updateValue, validationError: validationError };
|
|
78
|
+
return { value: value, setValue: updateValue, validationError: validationError, validationWarning: validationWarning };
|
|
78
79
|
};
|
|
79
|
-
var ContentContainer = styled(Div)(
|
|
80
|
-
return p.
|
|
80
|
+
var ContentContainer = styled(Div)(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n height: calc(100% - 1px);\n width: 100%;\n ", ";\n ", "\n ", "\n ", "\n"], ["\n height: calc(100% - 1px);\n width: 100%;\n ", ";\n ", "\n ", "\n ", "\n"])), function (p) { return p.theme.css.alignCenter; }, function (p) {
|
|
81
|
+
return p.hasWarning && css(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n color: ", ";\n background: ", ";\n /* internal border */\n box-shadow: 0px 0px 0px 1px ", " inset;\n "], ["\n color: ", ";\n background: ", ";\n /* internal border */\n box-shadow: 0px 0px 0px 1px ", " inset;\n "])), function (p) { return p.theme.colors.orange1200; }, function (p) { return p.theme.colors.orange1100; }, function (p) { return p.theme.colors.orange500; });
|
|
81
82
|
}, function (p) {
|
|
82
|
-
return p.
|
|
83
|
+
return p.hasError && css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n color: ", ";\n background: ", ";\n /* internal border */\n box-shadow: 0px 0px 0px 1px ", " inset;\n "], ["\n color: ", ";\n background: ", ";\n /* internal border */\n box-shadow: 0px 0px 0px 1px ", " inset;\n "])), function (p) { return p.theme.colors.error; }, function (p) { return p.theme.colors.red100; }, function (p) { return p.theme.colors.error; });
|
|
84
|
+
}, function (p) {
|
|
85
|
+
return p.isReadOnly && css(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n pointer-events: none;\n "], ["\n pointer-events: none;\n "])));
|
|
83
86
|
});
|
|
84
87
|
var Wrapper = styled(Div)(function (_a) {
|
|
85
88
|
var isLoading = _a.isLoading;
|
|
86
|
-
return css(
|
|
89
|
+
return css(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n ", "\n "], ["\n ", "\n "])), isLoading && css(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n pointer-events: none;\n "], ["\n pointer-events: none;\n "]))));
|
|
87
90
|
});
|
|
88
91
|
export var SpreadsheetField = function (_a) {
|
|
89
|
-
var validationError = _a.validationError, children = _a.children;
|
|
92
|
+
var validationError = _a.validationError, validationWarning = _a.validationWarning, children = _a.children;
|
|
90
93
|
var _b = useSpreadsheetContext(), isReadOnly = _b.isReadOnly, isLoading = _b.isLoading;
|
|
91
|
-
return (_jsx(Wrapper, __assign({ dim: "100%", isLoading: isLoading }, { children: _jsx(TooltipProvider, __assign({ tooltip: validationError }, { children: _jsx(Div, __assign({ dim: "100%" }, { children: _jsx(ContentContainer, __assign({ hasError: !!validationError, isReadOnly: isReadOnly }, { children: children })) })) })) })));
|
|
94
|
+
return (_jsx(Wrapper, __assign({ dim: "100%", isLoading: isLoading }, { children: _jsx(TooltipProvider, __assign({ tooltip: validationError || validationWarning }, { children: _jsx(Div, __assign({ dim: "100%" }, { children: _jsx(ContentContainer, __assign({ hasError: !!validationError, hasWarning: !!validationWarning, isReadOnly: isReadOnly }, { children: children })) })) })) })));
|
|
92
95
|
};
|
|
93
|
-
var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5;
|
|
96
|
+
var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6;
|
|
@@ -16,14 +16,19 @@ export type ValidationState = {
|
|
|
16
16
|
isValidationCompleted: boolean;
|
|
17
17
|
validationPercentage: number;
|
|
18
18
|
errors: BatchValidationErrors;
|
|
19
|
+
warnings: BatchValidationErrors;
|
|
19
20
|
totalErrors: number;
|
|
20
21
|
columnErrorCounts: {
|
|
21
22
|
[column: string]: number;
|
|
22
23
|
};
|
|
24
|
+
columnWarningCounts: {
|
|
25
|
+
[column: string]: number;
|
|
26
|
+
};
|
|
23
27
|
};
|
|
24
28
|
type UseValidationStateReturnValue = ValidationState & {
|
|
25
29
|
updateRecordAndRevalidate: (record: Record) => Promise<void>;
|
|
26
30
|
errorsRef: React.MutableRefObject<BatchValidationErrors>;
|
|
31
|
+
warningsRef: React.MutableRefObject<BatchValidationErrors>;
|
|
27
32
|
};
|
|
28
33
|
export declare const useValidationState: ({ initialDataSet, dataSet, fields, options, isReadOnly, setDataSet, setIsLoading, onValidateRecord, }: UseValidationStateArgs) => UseValidationStateReturnValue;
|
|
29
34
|
export {};
|
|
@@ -50,25 +50,27 @@ import { useCallback, useEffect, useMemo, useRef, useState, } from "react";
|
|
|
50
50
|
import { sleep } from "../../..";
|
|
51
51
|
import { selectValidatorsFor, validateRecord } from "./validation";
|
|
52
52
|
var checkIfHasErrors = function (errors) {
|
|
53
|
-
return Object.keys(errors).length > 0;
|
|
53
|
+
return errors && Object.keys(errors).length > 0;
|
|
54
54
|
};
|
|
55
55
|
export var useValidationState = function (_a) {
|
|
56
56
|
var initialDataSet = _a.initialDataSet, //Initial Data Set, used to run the initial validation
|
|
57
57
|
dataSet = _a.dataSet, //Current Updated Data Set
|
|
58
58
|
fields = _a.fields, options = _a.options, isReadOnly = _a.isReadOnly, setDataSet = _a.setDataSet, setIsLoading = _a.setIsLoading, onValidateRecord = _a.onValidateRecord;
|
|
59
59
|
var _b = useState({}), errors = _b[0], setErrors = _b[1];
|
|
60
|
-
var _c = useState(
|
|
60
|
+
var _c = useState({}), warnings = _c[0], setWarnings = _c[1];
|
|
61
|
+
var _d = useState(0), validationPercentage = _d[0], setValidationPercentage = _d[1];
|
|
61
62
|
var validatorsCache = useMemo(function () { return selectValidatorsFor(fields); }, [fields]);
|
|
62
63
|
var errorsRef = useRef(errors);
|
|
64
|
+
var warningsRef = useRef(warnings);
|
|
63
65
|
//Validate record and update dataSet
|
|
64
66
|
var updateRecordAndRevalidate = useCallback(function (record) { return __awaiter(void 0, void 0, void 0, function () {
|
|
65
|
-
var recordId, newDataSet, data, recordErrors, hasError;
|
|
66
|
-
var
|
|
67
|
-
return __generator(this, function (
|
|
68
|
-
switch (
|
|
67
|
+
var recordId, newDataSet, data, _a, recordErrors, recordWarnings, hasError, hasWarning;
|
|
68
|
+
var _b;
|
|
69
|
+
return __generator(this, function (_c) {
|
|
70
|
+
switch (_c.label) {
|
|
69
71
|
case 0:
|
|
70
72
|
recordId = record._meta.id;
|
|
71
|
-
newDataSet = __assign(__assign({}, dataSet), (
|
|
73
|
+
newDataSet = __assign(__assign({}, dataSet), (_b = {}, _b[recordId] = __assign({}, record), _b));
|
|
72
74
|
data = Object.values(newDataSet);
|
|
73
75
|
return [4 /*yield*/, validateRecord({
|
|
74
76
|
validatorsCache: validatorsCache,
|
|
@@ -78,9 +80,11 @@ export var useValidationState = function (_a) {
|
|
|
78
80
|
record: record,
|
|
79
81
|
})];
|
|
80
82
|
case 1:
|
|
81
|
-
|
|
83
|
+
_a = _c.sent(), recordErrors = _a.errors, recordWarnings = _a.warnings;
|
|
82
84
|
hasError = checkIfHasErrors(recordErrors);
|
|
85
|
+
hasWarning = checkIfHasErrors(recordWarnings);
|
|
83
86
|
newDataSet[recordId]._meta.isInvalid = hasError;
|
|
87
|
+
newDataSet[recordId]._meta.hasWarning = hasWarning;
|
|
84
88
|
newDataSet[recordId]._meta.touched = true;
|
|
85
89
|
setErrors(function (errors) {
|
|
86
90
|
var newErrors = __assign({}, errors);
|
|
@@ -90,6 +94,14 @@ export var useValidationState = function (_a) {
|
|
|
90
94
|
errorsRef.current = newState;
|
|
91
95
|
return newState;
|
|
92
96
|
});
|
|
97
|
+
setWarnings(function (warnings) {
|
|
98
|
+
var newWarnings = __assign({}, warnings);
|
|
99
|
+
var newState = hasWarning
|
|
100
|
+
? set(newWarnings, recordId, recordWarnings)
|
|
101
|
+
: omit(newWarnings, recordId);
|
|
102
|
+
warningsRef.current = newState;
|
|
103
|
+
return newState;
|
|
104
|
+
});
|
|
93
105
|
setDataSet(newDataSet); //Update the dataSet
|
|
94
106
|
return [2 /*return*/];
|
|
95
107
|
}
|
|
@@ -102,18 +114,19 @@ export var useValidationState = function (_a) {
|
|
|
102
114
|
var isCancelled = false;
|
|
103
115
|
setIsLoading(true);
|
|
104
116
|
var initialValidation = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
105
|
-
var errors, initialData, length, _a, batchValidationDelayMs, _b, batchValidationSize, batchSize, batchCount, batchIdx, idx, batch, index, record, recordId, recordErrors, hasError,
|
|
106
|
-
return __generator(this, function (
|
|
107
|
-
switch (
|
|
117
|
+
var errors, warnings, initialData, length, _a, batchValidationDelayMs, _b, batchValidationSize, batchSize, batchCount, batchIdx, idx, batch, index, record, recordId, _c, recordErrors, recordWarnings, hasError, hasWarning, validationPercentage_1;
|
|
118
|
+
return __generator(this, function (_d) {
|
|
119
|
+
switch (_d.label) {
|
|
108
120
|
case 0:
|
|
109
121
|
errors = {};
|
|
122
|
+
warnings = {};
|
|
110
123
|
initialData = Object.values(initialDataSet);
|
|
111
124
|
length = initialData.length;
|
|
112
125
|
_a = options.batchValidationDelayMs, batchValidationDelayMs = _a === void 0 ? 400 : _a, _b = options.batchValidationSize, batchValidationSize = _b === void 0 ? 1000 : _b;
|
|
113
126
|
batchSize = Math.min(Math.floor(batchValidationSize), length) || length;
|
|
114
127
|
batchCount = Math.ceil(length / batchSize);
|
|
115
128
|
batchIdx = 0;
|
|
116
|
-
|
|
129
|
+
_d.label = 1;
|
|
117
130
|
case 1:
|
|
118
131
|
if (!(batchIdx < batchCount)) return [3 /*break*/, 8];
|
|
119
132
|
if (isCancelled)
|
|
@@ -121,7 +134,7 @@ export var useValidationState = function (_a) {
|
|
|
121
134
|
idx = batchIdx * batchSize;
|
|
122
135
|
batch = initialData.slice(idx, idx + batchSize);
|
|
123
136
|
index = 0;
|
|
124
|
-
|
|
137
|
+
_d.label = 2;
|
|
125
138
|
case 2:
|
|
126
139
|
if (!(index < batch.length)) return [3 /*break*/, 5];
|
|
127
140
|
if (isCancelled)
|
|
@@ -136,12 +149,16 @@ export var useValidationState = function (_a) {
|
|
|
136
149
|
validatorsCache: validatorsCache,
|
|
137
150
|
})];
|
|
138
151
|
case 3:
|
|
139
|
-
|
|
152
|
+
_c = _d.sent(), recordErrors = _c.errors, recordWarnings = _c.warnings;
|
|
140
153
|
hasError = checkIfHasErrors(recordErrors);
|
|
154
|
+
hasWarning = checkIfHasErrors(recordWarnings);
|
|
141
155
|
record._meta.isInvalid = hasError;
|
|
156
|
+
record._meta.hasWarning = hasWarning;
|
|
142
157
|
if (hasError)
|
|
143
158
|
errors[recordId] = recordErrors;
|
|
144
|
-
|
|
159
|
+
if (hasWarning)
|
|
160
|
+
warnings[recordId] = recordWarnings;
|
|
161
|
+
_d.label = 4;
|
|
145
162
|
case 4:
|
|
146
163
|
index++;
|
|
147
164
|
return [3 /*break*/, 2];
|
|
@@ -151,11 +168,12 @@ export var useValidationState = function (_a) {
|
|
|
151
168
|
setValidationPercentage(Math.round((validationPercentage_1 + Number.EPSILON) * 10) / 10);
|
|
152
169
|
return [4 /*yield*/, sleep(batchValidationDelayMs)];
|
|
153
170
|
case 6:
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
171
|
+
_d.sent();
|
|
172
|
+
errorsRef.current = errors;
|
|
173
|
+
setErrors(errors);
|
|
174
|
+
warningsRef.current = warnings;
|
|
175
|
+
setWarnings(warnings);
|
|
176
|
+
_d.label = 7;
|
|
159
177
|
case 7:
|
|
160
178
|
batchIdx++;
|
|
161
179
|
return [3 /*break*/, 1];
|
|
@@ -183,6 +201,18 @@ export var useValidationState = function (_a) {
|
|
|
183
201
|
}, errorsByColumns);
|
|
184
202
|
}, {});
|
|
185
203
|
}, [errors]);
|
|
204
|
+
var columnWarningCounts = useMemo(function () {
|
|
205
|
+
return Object.keys(warnings).reduce(function (errorsByColumns, rowId) {
|
|
206
|
+
var recordWarnings = warnings[rowId];
|
|
207
|
+
return Object.keys(recordWarnings).reduce(function (internalErrorsByColumns, fieldKey) {
|
|
208
|
+
var _a;
|
|
209
|
+
var hasError = !!recordWarnings[fieldKey];
|
|
210
|
+
var count = (_a = internalErrorsByColumns[fieldKey]) !== null && _a !== void 0 ? _a : 0;
|
|
211
|
+
internalErrorsByColumns[fieldKey] = hasError ? count + 1 : count;
|
|
212
|
+
return internalErrorsByColumns;
|
|
213
|
+
}, errorsByColumns);
|
|
214
|
+
}, {});
|
|
215
|
+
}, [warnings]);
|
|
186
216
|
var totalErrors = useMemo(function () {
|
|
187
217
|
return Object.keys(columnErrorCounts).reduce(function (count, column) { return count + columnErrorCounts[column]; }, 0);
|
|
188
218
|
}, [columnErrorCounts]);
|
|
@@ -190,12 +220,15 @@ export var useValidationState = function (_a) {
|
|
|
190
220
|
var isValid = isValidationCompleted && totalErrors === 0;
|
|
191
221
|
return {
|
|
192
222
|
errors: errors,
|
|
223
|
+
warnings: warnings,
|
|
193
224
|
totalErrors: totalErrors,
|
|
194
225
|
columnErrorCounts: columnErrorCounts,
|
|
226
|
+
columnWarningCounts: columnWarningCounts,
|
|
195
227
|
validationPercentage: validationPercentage,
|
|
196
228
|
isValidationCompleted: isValidationCompleted,
|
|
197
229
|
isValid: isValid,
|
|
198
230
|
errorsRef: errorsRef,
|
|
231
|
+
warningsRef: warningsRef,
|
|
199
232
|
updateRecordAndRevalidate: updateRecordAndRevalidate,
|
|
200
233
|
};
|
|
201
234
|
};
|
|
@@ -16,5 +16,8 @@ type ValidateRecordArgs = {
|
|
|
16
16
|
data: Record[];
|
|
17
17
|
};
|
|
18
18
|
export declare function selectValidatorsFor(fields: Field[]): SelectedFieldValidators[];
|
|
19
|
-
export declare function validateRecord({ record, fields, data, onValidateRecord, validatorsCache, }: ValidateRecordArgs): Promise<
|
|
19
|
+
export declare function validateRecord({ record, fields, data, onValidateRecord, validatorsCache, }: ValidateRecordArgs): Promise<{
|
|
20
|
+
errors?: ValidationErrors;
|
|
21
|
+
warnings?: ValidationErrors;
|
|
22
|
+
}>;
|
|
20
23
|
export {};
|