fuse-importer 0.14.1 → 0.17.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.
Files changed (39) hide show
  1. package/lib/esm/Importer/ImporterContextProvider.d.ts +7 -6
  2. package/lib/esm/Importer/ImporterContextProvider.js +19 -17
  3. package/lib/esm/Importer/Matcher/EnumFieldsMatchers/EnumFieldMatcher/index.js +2 -1
  4. package/lib/esm/Importer/Matcher/EnumFieldsMatchers/EnumFieldMatcher/tableColumns.js +6 -5
  5. package/lib/esm/Importer/Matcher/HeaderMatcher/index.js +2 -1
  6. package/lib/esm/Importer/Matcher/HeaderMatcher/tableColumns.d.ts +0 -5
  7. package/lib/esm/Importer/Matcher/HeaderMatcher/tableColumns.js +7 -14
  8. package/lib/esm/Importer/Matcher/common/index.d.ts +4 -0
  9. package/lib/esm/Importer/Matcher/common/index.js +32 -0
  10. package/lib/esm/Importer/Review/index.js +31 -21
  11. package/lib/esm/Importer/SpreadsheetReviewContextProvider.js +2 -2
  12. package/lib/esm/Importer/Stepper.js +5 -4
  13. package/lib/esm/Importer/TrialModeBanner.js +1 -1
  14. package/lib/esm/Importer/common/Spreadsheet/SpreadsheetContextProvider.d.ts +4 -4
  15. package/lib/esm/Importer/common/Spreadsheet/SpreadsheetContextProvider.js +21 -24
  16. package/lib/esm/Importer/common/Spreadsheet/common/fields/SpeadsheetAutocomplete.js +5 -4
  17. package/lib/esm/Importer/common/Spreadsheet/common/fields/SpreadsheetInput.d.ts +12 -0
  18. package/lib/esm/Importer/common/Spreadsheet/common/fields/{SpreadsheetTextInput.js → SpreadsheetInput.js} +15 -4
  19. package/lib/esm/Importer/common/Spreadsheet/common/index.js +2 -2
  20. package/lib/esm/Importer/common/Spreadsheet/index.d.ts +3 -3
  21. package/lib/esm/Importer/common/Spreadsheet/index.js +26 -24
  22. package/lib/esm/Importer/common/utils.d.ts +3 -2
  23. package/lib/esm/Importer/common/utils.js +21 -4
  24. package/lib/esm/Importer/index.d.ts +4 -5
  25. package/lib/esm/Importer/index.js +6 -6
  26. package/lib/esm/common/TooltipProvider.js +8 -0
  27. package/lib/esm/common/index.d.ts +0 -1
  28. package/lib/esm/common/index.js +7 -9
  29. package/lib/esm/common/inputs/Autocomplete.d.ts +3 -2
  30. package/lib/esm/common/inputs/Autocomplete.js +19 -10
  31. package/lib/esm/common/inputs/TextInput.d.ts +1 -0
  32. package/lib/esm/common/inputs/TextInput.js +2 -2
  33. package/lib/esm/index.d.ts +4 -3
  34. package/lib/esm/index.js +17 -9
  35. package/lib/esm/styled/utils.d.ts +2 -0
  36. package/lib/esm/types.d.ts +16 -4
  37. package/lib/main.js +1 -1
  38. package/package.json +3 -3
  39. package/lib/esm/Importer/common/Spreadsheet/common/fields/SpreadsheetTextInput.d.ts +0 -13
@@ -1,8 +1,8 @@
1
1
  import Fuse from "fuse.js";
2
2
  import React from "react";
3
- import { EnvironmentType, OnValidateBatch, OnValidateRecord } from "../types";
3
+ import { ImporterOptions, OnValidateBatch, OnValidateRecord } from "../types";
4
4
  import { FuseApi } from "./FuseApi";
5
- export declare const options: Fuse.IFuseOptions<string>;
5
+ export declare const fusejsOptions: Fuse.IFuseOptions<string>;
6
6
  export declare type HeaderMatchings = {
7
7
  [templateHeaderLabel: string]: string;
8
8
  };
@@ -39,21 +39,22 @@ declare type State = {
39
39
  matcherSubstep: number;
40
40
  setMatcherSubstep: React.Dispatch<number>;
41
41
  uploadedDataEnumFieldValues: UploadedDataEnumFieldValues;
42
- templateId: string;
42
+ templateSlug: string;
43
43
  apiToken: string;
44
44
  inTrialMode: boolean;
45
45
  onClose: () => void;
46
46
  fuseApi: FuseApi;
47
+ importerOptions: ImporterOptions;
47
48
  };
48
49
  declare type Props = {
49
- templateId: string;
50
+ templateSlug: string;
50
51
  apiToken: string;
51
- environment?: EnvironmentType;
52
+ options: ImporterOptions;
52
53
  onClose: () => void;
53
54
  children: JSX.Element;
54
55
  onValidateRecord?: OnValidateRecord;
55
56
  onValidateBatch?: OnValidateBatch;
56
57
  };
57
- export declare const ImporterContextProvider: ({ templateId, environment, apiToken, children, onClose, onValidateBatch, onValidateRecord, }: Props) => JSX.Element;
58
+ export declare const ImporterContextProvider: ({ templateSlug, apiToken, children, options, onClose, onValidateBatch, onValidateRecord, }: Props) => JSX.Element;
58
59
  export declare const useImporterContext: () => State;
59
60
  export {};
@@ -48,25 +48,26 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
48
48
  import { jsx as _jsx } from "react/jsx-runtime";
49
49
  import Fuse from "fuse.js";
50
50
  import { createContext, useContext, useEffect, useState } from "react";
51
- import { isEnumField } from "./common/utils";
51
+ import { FieldTypes, } from "../types";
52
+ import { getColumnType } from "./common/utils";
52
53
  import { FuseApi } from "./FuseApi";
53
- export var options = {
54
+ export var fusejsOptions = {
54
55
  includeScore: true,
55
56
  threshold: 0.35,
56
57
  };
57
58
  var ImporterContext = createContext({});
58
59
  export var ImporterContextProvider = function (_a) {
59
- var templateId = _a.templateId, _b = _a.environment, environment = _b === void 0 ? "local" : _b, apiToken = _a.apiToken, children = _a.children, onClose = _a.onClose, onValidateBatch = _a.onValidateBatch, onValidateRecord = _a.onValidateRecord;
60
- var _c = useState(0), currentStepIndex = _c[0], setCurrentStepIndex = _c[1];
61
- var _d = useState(0), matcherSubstep = _d[0], setMatcherSubstep = _d[1];
62
- var _e = useState(null), templateError = _e[0], setTemplateError = _e[1];
63
- var _f = useState(null), templateHeaders = _f[0], setTemplateHeaders = _f[1];
64
- var _g = useState(null), uploadedData = _g[0], setUploadedData = _g[1];
65
- var _h = useState(null), templateHeaderMatchings = _h[0], setTemplateHeaderMatchings = _h[1];
66
- var _j = useState(null), enumFieldValueMatchings = _j[0], setEnumFieldValueMatchings = _j[1];
67
- var _k = useState(null), uploadedDataEnumFieldValues = _k[0], setUploadedDataEnumFieldValues = _k[1];
68
- var _l = useState(false), inTrialMode = _l[0], setInTrialMode = _l[1];
69
- var fuseApi = new FuseApi(environment, apiToken);
60
+ var templateSlug = _a.templateSlug, apiToken = _a.apiToken, children = _a.children, options = _a.options, onClose = _a.onClose, onValidateBatch = _a.onValidateBatch, onValidateRecord = _a.onValidateRecord;
61
+ var _b = useState(0), currentStepIndex = _b[0], setCurrentStepIndex = _b[1];
62
+ var _c = useState(0), matcherSubstep = _c[0], setMatcherSubstep = _c[1];
63
+ var _d = useState(null), templateError = _d[0], setTemplateError = _d[1];
64
+ var _e = useState(null), templateHeaders = _e[0], setTemplateHeaders = _e[1];
65
+ var _f = useState(null), uploadedData = _f[0], setUploadedData = _f[1];
66
+ var _g = useState(null), templateHeaderMatchings = _g[0], setTemplateHeaderMatchings = _g[1];
67
+ var _h = useState(null), enumFieldValueMatchings = _h[0], setEnumFieldValueMatchings = _h[1];
68
+ var _j = useState(null), uploadedDataEnumFieldValues = _j[0], setUploadedDataEnumFieldValues = _j[1];
69
+ var _k = useState(false), inTrialMode = _k[0], setInTrialMode = _k[1];
70
+ var fuseApi = new FuseApi(options.env, apiToken);
70
71
  var uploadedDataHeaders = uploadedData &&
71
72
  uploadedData[0].map(function (ud) { return (typeof ud === "number" ? ud.toString() : ud); });
72
73
  useEffect(function () {
@@ -75,7 +76,7 @@ export var ImporterContextProvider = function (_a) {
75
76
  var _uploadedDataEnumFieldValues = {};
76
77
  var templateLabels = Object.keys(templateHeaderMatchings);
77
78
  var enumFieldsLabels = templateLabels.filter(function (templateLabel) {
78
- return isEnumField({ templateLabel: templateLabel, templateHeaders: templateHeaders });
79
+ return getColumnType({ templateLabel: templateLabel, templateHeaders: templateHeaders }) === FieldTypes.enum;
79
80
  });
80
81
  enumFieldsLabels.forEach(function (templateLabel) {
81
82
  var uploadedDataHeader = templateHeaderMatchings[templateLabel];
@@ -101,7 +102,7 @@ export var ImporterContextProvider = function (_a) {
101
102
  switch (_c.label) {
102
103
  case 0:
103
104
  _c.trys.push([0, 2, , 3]);
104
- return [4 /*yield*/, fuseApi.get("/api/v1/importer/templates/".concat(templateId))];
105
+ return [4 /*yield*/, fuseApi.get("/api/v1/importer/templates/".concat(templateSlug))];
105
106
  case 1:
106
107
  data = (_c.sent()).data;
107
108
  setTemplateHeaders(data.columns);
@@ -128,7 +129,7 @@ export var ImporterContextProvider = function (_a) {
128
129
  };
129
130
  var setHeadersFromDataset = function () {
130
131
  var _templateHeaderMatchings = {};
131
- var fuse = new Fuse(uploadedDataHeaders, options);
132
+ var fuse = new Fuse(uploadedDataHeaders, fusejsOptions);
132
133
  templateHeaders.forEach(function (templateHeader, _index) {
133
134
  var _a;
134
135
  var fuseResults = fuse.search(templateHeader.label);
@@ -145,6 +146,7 @@ export var ImporterContextProvider = function (_a) {
145
146
  setEnumFieldValueMatchings: setEnumFieldValueMatchings,
146
147
  templateHeaderMatchings: templateHeaderMatchings,
147
148
  uploadedDataEnumFieldValues: uploadedDataEnumFieldValues,
149
+ importerOptions: options,
148
150
  setTemplateHeaderMatchings: setTemplateHeaderMatchings,
149
151
  resetImport: resetImport,
150
152
  uploadedData: uploadedData,
@@ -155,7 +157,7 @@ export var ImporterContextProvider = function (_a) {
155
157
  matcherSubstep: matcherSubstep,
156
158
  setMatcherSubstep: setMatcherSubstep,
157
159
  apiToken: apiToken,
158
- templateId: templateId,
160
+ templateSlug: templateSlug,
159
161
  inTrialMode: inTrialMode,
160
162
  onClose: onClose,
161
163
  fuseApi: fuseApi,
@@ -20,6 +20,7 @@ import { EnumFieldMatcherContextProvider } from "../EnumFieldMatcherContext";
20
20
  import { tableColumns } from "./tableColumns";
21
21
  import { defaultTableHeaderHeightPx } from "../../../../common/Table/TableView/common";
22
22
  import { getTableHeight } from "../../../common";
23
+ import { MAX_VISIBLE_ROWS } from "../../common";
23
24
  export var EnumFieldMatcher = function (_a) {
24
25
  var _b;
25
26
  var templateHeaderLabel = _a.templateHeaderLabel;
@@ -47,7 +48,7 @@ export var EnumFieldMatcher = function (_a) {
47
48
  headerHeight: defaultTableHeaderHeightPx,
48
49
  rowHeight: tableRowHeight,
49
50
  dataCount: data.length,
50
- maxVisibleRows: 5,
51
+ maxVisibleRows: MAX_VISIBLE_ROWS,
51
52
  });
52
53
  return (_jsxs(Div, { children: [_jsx(Div, __assign({ h5: true, mb: 16 }, { children: "Values for the '".concat(templateHeaderLabel).concat(isRequired ? "*" : "", "' Column") }), void 0), _jsx(Div, __assign({ mb: 40 }, { children: _jsx(EnumFieldMatcherContextProvider, __assign({ templateHeaderLabel: templateHeaderLabel }, { children: _jsx(TableView, { h: tableHeight, rowHeight: tableRowHeight, data: sortedData, columns: tableColumns, bg: colors.white }, void 0) }), void 0) }), void 0)] }, void 0));
53
54
  };
@@ -9,13 +9,12 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
12
+ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
13
13
  import { Autocomplete } from "../../../../common/inputs/Autocomplete";
14
14
  import { Div } from "../../../../styled/utils";
15
15
  import { useImporterContext } from "../../../ImporterContextProvider";
16
- import { greenCheckIcon, warningIcon } from "../../common/icons";
16
+ import { matchedIndicatorUI, unmatchedIndicatorUI } from "../../common";
17
17
  import { MatcherStatus } from "../../common/types";
18
- import { StatusColumn } from "../../HeaderMatcher/tableColumns";
19
18
  import { useEnumFieldMatcherContext } from "../EnumFieldMatcherContext";
20
19
  export var tableColumns = [
21
20
  {
@@ -40,7 +39,7 @@ export var tableColumns = [
40
39
  newEnumFieldValueMatchings[templateHeaderLabel][uploadedDataValue] = selected;
41
40
  setEnumFieldValueMatchings(newEnumFieldValueMatchings);
42
41
  };
43
- return (_jsx(Div, __assign({ w100: true }, { children: _jsx(Autocomplete, { placeholder: "Select option...", onChange: onChange, value: uploadedDataValueMatching, options: valueOptions.map(function (vo) { return ({
42
+ return (_jsx(Div, __assign({ w100: true }, { children: _jsx(Autocomplete, { w: "90%", placeholder: "Select option...", onChange: onChange, value: uploadedDataValueMatching, options: valueOptions.map(function (vo) { return ({
44
43
  value: vo,
45
44
  label: vo,
46
45
  }); }) }, void 0) }), void 0));
@@ -51,7 +50,9 @@ export var tableColumns = [
51
50
  width: 1,
52
51
  Content: function (_a) {
53
52
  var status = _a.status;
54
- return (_jsxs(StatusColumn, __assign({ matched: status, justifyCenter: true, body2: true, dflex: true, alignCenter: true }, { children: [status === MatcherStatus.matched ? greenCheckIcon : warningIcon, _jsx(Div, __assign({ ml: 6 }, { children: status }), void 0)] }), void 0));
53
+ return (_jsx(_Fragment, { children: status === MatcherStatus.matched
54
+ ? matchedIndicatorUI
55
+ : unmatchedIndicatorUI }, void 0));
55
56
  },
56
57
  },
57
58
  ];
@@ -21,6 +21,7 @@ import { colors } from "../../../styled/theme";
21
21
  import { Div } from "../../../styled/utils";
22
22
  import { contentWidth, getTableHeight } from "../../common/index";
23
23
  import { useImporterContext } from "../../ImporterContextProvider";
24
+ import { MAX_VISIBLE_ROWS } from "../common";
24
25
  import { MatcherStatus } from "../common/types";
25
26
  import { tableColumns } from "./tableColumns";
26
27
  var CardContainer = styled(Div)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n flex-direction: row;\n > div {\n margin: 16px;\n }\n"], ["\n flex-direction: row;\n > div {\n margin: 16px;\n }\n"])));
@@ -50,7 +51,7 @@ var HeaderMatcher = function () {
50
51
  headerHeight: defaultTableHeaderHeightPx,
51
52
  rowHeight: tableRowHeight,
52
53
  dataCount: data.length,
53
- maxVisibleRows: 5,
54
+ maxVisibleRows: MAX_VISIBLE_ROWS,
54
55
  });
55
56
  var headerMatcher = (_jsx(Div, { children: _jsxs(Div, __assign({ flexColumn: true, centered: true }, { children: [_jsx(Div, __assign({ h2: true, mb: 16 }, { children: "Match Your Columns with Ours" }), void 0), _jsx(Div, __assign({ body1: true, mb: 24, textAlignCenter: true }, { children: "We were able to match ".concat(numberOfMatchedHeaders, " of ").concat(templateHeaders.length, " columns correctly!") }), void 0), _jsx(CardContainer, __assign({ dflex: true, centered: true, alignStart: true }, { children: _jsx(Div, __assign({ w: contentWidth }, { children: _jsx(TableView, { h: tableHeight, data: sortedData, rowHeight: tableRowHeight, columns: tableColumns, bg: colors.white }, void 0) }), void 0) }), void 0)] }), void 0) }, void 0));
56
57
  return _jsx(_Fragment, { children: headerMatcher }, void 0);
@@ -1,8 +1,4 @@
1
1
  /// <reference types="react" />
2
- declare type StatusColumnProps = {
3
- matched: boolean;
4
- };
5
- export declare const StatusColumn: import("styled-components").StyledComponent<"div", import("styled-components").DefaultTheme, import("../../../styled/utils").CSSProps & StatusColumnProps, never>;
6
2
  export declare const tableColumns: ({
7
3
  header: string;
8
4
  width: number;
@@ -17,4 +13,3 @@ export declare const tableColumns: ({
17
13
  status: any;
18
14
  }) => JSX.Element;
19
15
  })[];
20
- export {};
@@ -1,7 +1,3 @@
1
- var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
2
- if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
3
- return cooked;
4
- };
5
1
  var __assign = (this && this.__assign) || function () {
6
2
  __assign = Object.assign || function(t) {
7
3
  for (var s, i = 1, n = arguments.length; i < n; i++) {
@@ -13,16 +9,12 @@ var __assign = (this && this.__assign) || function () {
13
9
  };
14
10
  return __assign.apply(this, arguments);
15
11
  };
16
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
17
- import styled, { css } from "styled-components";
12
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
18
13
  import { Autocomplete } from "../../../common/inputs/Autocomplete";
19
14
  import { Div } from "../../../styled/utils";
20
15
  import { useImporterContext } from "../../ImporterContextProvider";
21
- import { greenCheckIcon, warningIcon } from "../common/icons";
16
+ import { matchedIndicatorUI, unmatchedIndicatorUI } from "../common/index";
22
17
  import { MatcherStatus } from "../common/types";
23
- export var StatusColumn = styled(Div)(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n background-color: ", ";\n padding: 8px 6px;\n border-radius: 5px;\n ", "\n"], ["\n background-color: ", ";\n padding: 8px 6px;\n border-radius: 5px;\n ", "\n"])), function (p) { return p.theme.colors.orange50; }, function (props) {
24
- return props.matched && css(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n background-color: ", ";\n "], ["\n background-color: ", ";\n "])), function (props) { return props.theme.colors.green50; });
25
- });
26
18
  export var tableColumns = [
27
19
  {
28
20
  header: "Your Columns",
@@ -35,7 +27,7 @@ export var tableColumns = [
35
27
  newTemplateHeaderMatchings[ourColumns] = selected;
36
28
  setTemplateHeaderMatchings(newTemplateHeaderMatchings);
37
29
  };
38
- return (_jsx(Autocomplete, { mr: 10, onChange: onChange, value: yourColumns, options: uploadedDataHeaders.map(function (h) { return ({
30
+ return (_jsx(Autocomplete, { w: "92%", onChange: onChange, value: yourColumns, options: uploadedDataHeaders.map(function (h) { return ({
39
31
  value: h,
40
32
  label: h,
41
33
  }); }) }, void 0));
@@ -49,7 +41,7 @@ export var tableColumns = [
49
41
  var ourColumns = _a.ourColumns;
50
42
  var templateHeaders = useImporterContext().templateHeaders;
51
43
  var isRequired = (_b = templateHeaders.find(function (th) { return th.label === ourColumns; })) === null || _b === void 0 ? void 0 : _b.required;
52
- return (_jsxs(Div, __assign({ body1: true }, { children: [ourColumns, isRequired ? "*" : "", " "] }), void 0));
44
+ return (_jsxs(Div, __assign({ body1: true }, { children: [ourColumns, isRequired ? "*" : ""] }), void 0));
53
45
  },
54
46
  },
55
47
  {
@@ -57,8 +49,9 @@ export var tableColumns = [
57
49
  width: 1,
58
50
  Content: function (_a) {
59
51
  var status = _a.status;
60
- return (_jsxs(StatusColumn, __assign({ matched: status, alignCenter: true, body2: true, dflex: true }, { children: [status === MatcherStatus.matched ? greenCheckIcon : warningIcon, _jsx(Div, __assign({ ml: 6 }, { children: status }), void 0)] }), void 0));
52
+ return (_jsx(_Fragment, { children: status === MatcherStatus.matched
53
+ ? matchedIndicatorUI
54
+ : unmatchedIndicatorUI }, void 0));
61
55
  },
62
56
  },
63
57
  ];
64
- var templateObject_1, templateObject_2;
@@ -0,0 +1,4 @@
1
+ /// <reference types="react" />
2
+ export declare const MAX_VISIBLE_ROWS = 5;
3
+ export declare const matchedIndicatorUI: JSX.Element;
4
+ export declare const unmatchedIndicatorUI: JSX.Element;
@@ -0,0 +1,32 @@
1
+ var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
2
+ if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
3
+ return cooked;
4
+ };
5
+ var __assign = (this && this.__assign) || function () {
6
+ __assign = Object.assign || function(t) {
7
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
8
+ s = arguments[i];
9
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
10
+ t[p] = s[p];
11
+ }
12
+ return t;
13
+ };
14
+ return __assign.apply(this, arguments);
15
+ };
16
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
17
+ import styled, { css } from "styled-components";
18
+ import { colors, Div } from "../../../styled";
19
+ export var MAX_VISIBLE_ROWS = 5;
20
+ var successIcon = (_jsx("svg", __assign({ width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, { children: _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M6 11.5C9.03757 11.5 11.5 9.03757 11.5 6C11.5 2.96243 9.03757 0.5 6 0.5C2.96243 0.5 0.5 2.96243 0.5 6C0.5 9.03757 2.96243 11.5 6 11.5ZM4.94194 5.53291C4.69786 5.28883 4.30214 5.28883 4.05806 5.53291C3.81398 5.77699 3.81398 6.17272 4.05806 6.4168L5.11872 7.47746C5.3628 7.72153 5.75852 7.72153 6.0026 7.47746L8.12392 5.35614C8.368 5.11206 8.368 4.71633 8.12392 4.47225C7.87984 4.22817 7.48412 4.22817 7.24004 4.47225L5.56066 6.15163L4.94194 5.53291Z", fill: colors.green300 }, void 0) }), void 0));
21
+ var warningIcon = (_jsx("svg", __assign({ width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, { children: _jsx("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M6 11.5C9.03757 11.5 11.5 9.03757 11.5 6C11.5 2.96243 9.03757 0.5 6 0.5C2.96243 0.5 0.5 2.96243 0.5 6C0.5 9.03757 2.96243 11.5 6 11.5ZM6 2.875C6.34518 2.875 6.625 3.15482 6.625 3.5V6C6.625 6.34518 6.34518 6.625 6 6.625C5.65482 6.625 5.375 6.34518 5.375 6V3.5C5.375 3.15482 5.65482 2.875 6 2.875ZM6 7.375C6.34518 7.375 6.625 7.65482 6.625 8V8.25C6.625 8.59518 6.34518 8.875 6 8.875C5.65482 8.875 5.375 8.59518 5.375 8.25V8C5.375 7.65482 5.65482 7.375 6 7.375Z", fill: colors.orange500 }, void 0) }), void 0));
22
+ var Wrapper = styled(Div)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n padding: 2px 7px;\n ", ";\n"], ["\n padding: 2px 7px;\n ", ";\n"])), function (p) {
23
+ var c = p.theme.css;
24
+ return [c.label3, c.alignCenter, c.selectNone];
25
+ });
26
+ var UnmatchedIndicator = styled(Wrapper)(function (_a) {
27
+ var _b = _a.theme, colors = _b.colors, c = _b.css;
28
+ return css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n border: 1px solid ", ";\n box-sizing: border-box;\n border-radius: 24px;\n "], ["\n border: 1px solid ", ";\n box-sizing: border-box;\n border-radius: 24px;\n "])), function (p) { return p.theme.colors.warning01; });
29
+ });
30
+ export var matchedIndicatorUI = (_jsxs(Wrapper, { children: [_jsx(Div, __assign({ centered: true }, { children: successIcon }), void 0), _jsx(Div, __assign({ ml: 8 }, { children: "MATCHED" }), void 0)] }, void 0));
31
+ export var unmatchedIndicatorUI = (_jsxs(UnmatchedIndicator, { children: [_jsx(Div, __assign({ centered: true }, { children: warningIcon }), void 0), _jsx(Div, __assign({ ml: 8 }, { children: "UNMATCHED" }), void 0)] }, void 0));
32
+ var templateObject_1, templateObject_2;
@@ -14,12 +14,20 @@ import { useMemo } from "react";
14
14
  import { Div } from "../../styled/utils";
15
15
  import { FieldTypes } from "../../types";
16
16
  import { Spreadsheet } from "../common/Spreadsheet";
17
- import { getSpreadsheetRowWidth, isEnumField } from "../common/utils";
18
- import { useImporterContext, } from "../ImporterContextProvider";
17
+ import { getColumnType, getSpreadsheetRowWidth } from "../common/utils";
18
+ import { useImporterContext } from "../ImporterContextProvider";
19
19
  import { useSpreadsheetReviewContext } from "../SpreadsheetReviewContextProvider";
20
20
  import { AppResponseModal } from "./AppResponseModal";
21
- var useInitialData = function (_a) {
22
- var uploadedData = _a.uploadedData, templateHeaderMatchings = _a.templateHeaderMatchings, enumFieldValueMatchings = _a.enumFieldValueMatchings, uploadedDataHeaders = _a.uploadedDataHeaders, templateHeaders = _a.templateHeaders;
21
+ var valueIsTrue = function (value) {
22
+ var _value = value.toLowerCase();
23
+ return ["true", "yes", "1", "y", "on", "t"].includes(_value);
24
+ };
25
+ var valueIsInteger = function (value) { return /^-?[0-9]+$/.test(value + ""); };
26
+ var valueIsNumber = function (value) {
27
+ return /^-?[0-9]+(?:\.[0-9]+)?$/.test(value + "");
28
+ };
29
+ var useInitialData = function () {
30
+ var _a = useImporterContext(), templateHeaderMatchings = _a.templateHeaderMatchings, enumFieldValueMatchings = _a.enumFieldValueMatchings, templateHeaders = _a.templateHeaders, uploadedDataHeaders = _a.uploadedDataHeaders, uploadedData = _a.uploadedData;
23
31
  return useMemo(function () {
24
32
  var templateHeaderLabelsWithMatchings = Object.keys(templateHeaderMatchings).filter(function (thl) { return !!templateHeaderMatchings[thl]; });
25
33
  var getUploadedDataRowIndex = function (templateHeaderLabel) {
@@ -35,13 +43,18 @@ var useInitialData = function (_a) {
35
43
  templateHeaderLabelsWithMatchings.forEach(function (templateLabel) {
36
44
  var key = getTemplateHeaderKey(templateLabel);
37
45
  var value = row[getUploadedDataRowIndex(templateLabel)];
38
- if (isEnumField({ templateLabel: templateLabel, templateHeaders: templateHeaders })) {
39
- var templateOption = enumFieldValueMatchings[templateLabel][value];
40
- record[key] = templateOption || value;
41
- }
42
- else {
43
- record[key] = value;
44
- }
46
+ record[key] = value;
47
+ if (value === undefined)
48
+ return;
49
+ var columnType = getColumnType({ templateLabel: templateLabel, templateHeaders: templateHeaders });
50
+ if (columnType === FieldTypes.enum)
51
+ record[key] = enumFieldValueMatchings[templateLabel][value];
52
+ if (columnType === FieldTypes.boolean)
53
+ record[key] = valueIsTrue(value);
54
+ if (columnType === FieldTypes.float)
55
+ record[key] = valueIsNumber(value) ? parseFloat(value) : undefined;
56
+ if (columnType === FieldTypes.integer)
57
+ record[key] = valueIsInteger(value) ? parseInt(value) : undefined;
45
58
  });
46
59
  return record;
47
60
  };
@@ -55,15 +68,9 @@ var useInitialData = function (_a) {
55
68
  ]);
56
69
  };
57
70
  var Review = function () {
58
- var _a = useImporterContext(), templateHeaderMatchings = _a.templateHeaderMatchings, enumFieldValueMatchings = _a.enumFieldValueMatchings, templateHeaders = _a.templateHeaders, uploadedDataHeaders = _a.uploadedDataHeaders, uploadedData = _a.uploadedData, onValidateRecord = _a.onValidateRecord, onValidateBatch = _a.onValidateBatch;
59
- var _b = useSpreadsheetReviewContext(), submittedData = _b.submittedData, appResponse = _b.appResponse, setReviewedData = _b.setReviewedData;
60
- var initialData = useInitialData({
61
- uploadedData: uploadedData,
62
- uploadedDataHeaders: uploadedDataHeaders,
63
- templateHeaderMatchings: templateHeaderMatchings,
64
- enumFieldValueMatchings: enumFieldValueMatchings,
65
- templateHeaders: templateHeaders,
66
- });
71
+ var _a = useImporterContext(), templateHeaders = _a.templateHeaders, onValidateRecord = _a.onValidateRecord, onValidateBatch = _a.onValidateBatch, _b = _a.importerOptions, batchValidationDelayMs = _b.batchValidationDelayMs, batchValidationSize = _b.batchValidationSize;
72
+ var initialData = useInitialData();
73
+ var _c = useSpreadsheetReviewContext(), submittedData = _c.submittedData, appResponse = _c.appResponse, setReviewedData = _c.setReviewedData;
67
74
  var fields = templateHeaders.map(function (templateHeader) { return ({
68
75
  label: templateHeader.label,
69
76
  name: templateHeader.internal_key,
@@ -71,7 +78,10 @@ var Review = function () {
71
78
  isRequired: templateHeader.required,
72
79
  options: templateHeader.values,
73
80
  }); });
74
- var spreadsheetUI = useMemo(function () { return (_jsx(Div, { children: _jsx(Spreadsheet, __assign({ rowWidth: getSpreadsheetRowWidth(fields, 6) }, {
81
+ var spreadsheetUI = useMemo(function () { return (_jsx(Div, { children: _jsx(Spreadsheet, __assign({ rowWidth: getSpreadsheetRowWidth(fields, 6), options: {
82
+ batchValidationDelayMs: batchValidationDelayMs,
83
+ batchValidationSize: batchValidationSize || initialData.length,
84
+ } }, {
75
85
  submittedData: submittedData,
76
86
  appResponse: appResponse,
77
87
  setReviewedData: setReviewedData,
@@ -57,7 +57,7 @@ export var SpreadsheetReviewContextProvider = function (_a) {
57
57
  var _c = useState(null), reviewedData = _c[0], setReviewedData = _c[1];
58
58
  var _d = useState(null), submittedData = _d[0], setSubmittedData = _d[1];
59
59
  var _e = useState(null), appResponse = _e[0], setAppResponse = _e[1];
60
- var _f = useImporterContext(), templateId = _f.templateId, fuseApi = _f.fuseApi;
60
+ var _f = useImporterContext(), templateSlug = _f.templateSlug, fuseApi = _f.fuseApi;
61
61
  var getImportWasSuccessful = function (response) {
62
62
  return !response.errors || !Object.keys(response.errors).length;
63
63
  };
@@ -69,7 +69,7 @@ export var SpreadsheetReviewContextProvider = function (_a) {
69
69
  trackImportedRowsCount = function (rowCount) { return __awaiter(void 0, void 0, void 0, function () {
70
70
  return __generator(this, function (_a) {
71
71
  switch (_a.label) {
72
- case 0: return [4 /*yield*/, fuseApi.post("/api/v1/importer/templates/".concat(templateId, "/imports"), {
72
+ case 0: return [4 /*yield*/, fuseApi.post("/api/v1/importer/templates/".concat(templateSlug, "/imports"), {
73
73
  row_count: rowCount,
74
74
  })];
75
75
  case 1:
@@ -18,7 +18,7 @@ import { Button } from "../common/buttons";
18
18
  import { whiteCheckIcon, closeIconCondensed, ChevronRightIcon, } from "../common/icons";
19
19
  import { useState } from "react";
20
20
  import styled, { css } from "styled-components";
21
- import { options, useImporterContext, } from "./ImporterContextProvider";
21
+ import { useImporterContext, } from "./ImporterContextProvider";
22
22
  import { colors } from "../styled/theme/colorPalette";
23
23
  import { Div } from "../styled/utils";
24
24
  import { Modal } from "../common/Modal";
@@ -26,6 +26,7 @@ import { useSpreadsheetReviewContext } from "./SpreadsheetReviewContextProvider"
26
26
  import { ColumnType } from "./Matcher/common/types";
27
27
  import Fuse from "fuse.js";
28
28
  import { contentWidth } from "./common";
29
+ import { fusejsOptions } from "./ImporterContextProvider";
29
30
  var StepIndexWrapper = styled(Div)(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n height: 22px;\n width: 22px;\n color: ", ";\n border-radius: 50%;\n background-color: none;\n border: 1px solid ", ";\n\n ", ";\n"], ["\n height: 22px;\n width: 22px;\n color: ", ";\n border-radius: 50%;\n background-color: none;\n border: 1px solid ", ";\n\n ", ";\n"])), function (p) { return p.theme.colors.gray400; }, function (p) { return p.theme.colors.gray400; }, function (p) {
30
31
  return p.isSelected && css(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n height: 32px;\n width: 32px;\n border: solid 1px ", ";\n color: ", ";\n background-color: ", ";\n "], ["\n height: 32px;\n width: 32px;\n border: solid 1px ", ";\n color: ", ";\n background-color: ", ";\n "])), function (p) { return p.theme.colors.blue500; }, function (p) { return p.theme.colors.white; }, function (p) { return p.theme.colors.blue500; });
31
32
  });
@@ -47,7 +48,7 @@ var getEnumFieldValueMatchingsInitialValue = function (_a) {
47
48
  uploadedDataEnumFieldValues[templateLabel].forEach(function (uploadedValue, _index) {
48
49
  var _a, _b;
49
50
  var templateOptions = (_a = templateHeaders.find(function (th) { return th.label === templateLabel; })) === null || _a === void 0 ? void 0 : _a.values;
50
- var fuse = new Fuse(templateOptions, options);
51
+ var fuse = new Fuse(templateOptions, fusejsOptions);
51
52
  var fuseResults = fuse.search(uploadedValue);
52
53
  var previousRes = __assign({}, (res[templateLabel] || {}));
53
54
  res[templateLabel] = previousRes;
@@ -118,7 +119,7 @@ var Stepper = function (_a) {
118
119
  setStep();
119
120
  setIsUnmatchedHeadersModalOpen(false);
120
121
  };
121
- var unmatchedHeadersModalUI = (_jsx(Modal, __assign({ isOpen: isUnmatchedHeadersModalOpen, onClose: function () { return setIsUnmatchedHeadersModalOpen(false); } }, { children: _jsxs(Div, __assign({ p: "17px 20px" }, { children: [_jsx(Div, __assign({ textAlignCenter: true, mb: 24, mt: 5 }, { children: errorIcon }), void 0), _jsx(Div, __assign({ textAlignCenter: true, h3: true, mb: 8 }, { children: "Unmatched Headers" }), void 0), _jsxs(Div, __assign({ maxw: 395, textAlignCenter: true, body1: true, mb: 40 }, { children: ["There are ", unmatchedHeadersCount, " unmatched column headers. You will have to fill these out manually if you proceed."] }), void 0), _jsxs(Div, __assign({ dflex: true, centered: true }, { children: [_jsx(Button, __assign({ variant: "secondary", onClick: function () { return setIsUnmatchedHeadersModalOpen(false); }, w: 160, mr: 16 }, { children: "Assign Headers" }), void 0), _jsx(Button, __assign({ variant: "primary", w: 68, onClick: skipStep }, { children: "Skip" }), void 0)] }), void 0)] }), void 0) }), void 0));
122
+ var unmatchedHeadersModalUI = (_jsx(Modal, __assign({ isOpen: isUnmatchedHeadersModalOpen, onClose: function () { return setIsUnmatchedHeadersModalOpen(false); } }, { children: _jsxs(Div, __assign({ p: "17px 20px" }, { children: [_jsx(Div, __assign({ textAlignCenter: true, mb: 24, mt: 5 }, { children: errorIcon }), void 0), _jsx(Div, __assign({ textAlignCenter: true, h5: true }, { children: "Unmatched Column Headers" }), void 0), _jsxs(Div, __assign({ w: 448, mt: 12, textAlignCenter: true, body1: true }, { children: [unmatchedHeadersCount === 1 ? "There is " : "There are ", unmatchedHeadersCount, " unmatched column headers. You will have to fill these out manually if you proceed."] }), void 0), _jsxs(Div, __assign({ dflex: true, centered: true, mt: 40 }, { children: [_jsx(Button, __assign({ variant: "secondary", onClick: function () { return setIsUnmatchedHeadersModalOpen(false); }, w: 160, mr: 16 }, { children: "Assign Headers" }), void 0), _jsx(Button, __assign({ w: 83, variant: "primary", onClick: skipStep }, { children: "Skip" }), void 0)] }), void 0)] }), void 0) }), void 0));
122
123
  var isMatchStep = currentStepIndex === 1;
123
124
  var isReviewStep = currentStepIndex === 2;
124
125
  var leftButtonUI = (_jsx(Div, __assign({ w: 100 }, { children: currentStepIndex > 0 && !appResponse && (_jsx(Button, __assign({ variant: "secondary", onClick: goBack }, { children: "Go back" }), void 0)) }), void 0));
@@ -139,5 +140,5 @@ var submitSvg = (_jsxs("svg", __assign({ width: 64, height: 64, fill: "none", xm
139
140
  } }, void 0), _jsx("rect", { x: 38.727, y: 44.871, width: 17.915, height: 35.878, rx: 2, transform: "rotate(131.582 38.727 44.87)", fill: "url(#b)", style: {
140
141
  mixBlendMode: "darken",
141
142
  } }, void 0), _jsxs("defs", { children: [_jsxs("linearGradient", __assign({ id: "a", x1: 18.672, y1: 47.198, x2: 37.603, y2: 58.473, gradientUnits: "userSpaceOnUse" }, { children: [_jsx("stop", { stopColor: "#D0A617" }, void 0), _jsx("stop", { offset: 1, stopColor: "#FEE18F" }, void 0)] }), void 0), _jsxs("linearGradient", __assign({ id: "b", x1: 47.684, y1: 44.871, x2: 36.123, y2: 89.527, gradientUnits: "userSpaceOnUse" }, { children: [_jsx("stop", { stopColor: "#6BEEFF" }, void 0), _jsx("stop", { offset: 1, stopColor: "#08CABE" }, void 0)] }), void 0)] }, void 0)] }), void 0));
142
- var errorIcon = (_jsxs("svg", __assign({ width: "64", height: "64", viewBox: "0 0 64 64", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, { children: [_jsx("circle", { cx: "32.0003", cy: "32", r: "29.3333", stroke: "#CF4520", strokeWidth: "5" }, void 0), _jsx("path", { d: "M32 18.6667V32", stroke: "#CF4520", strokeWidth: "5", strokeLinecap: "round", strokeLinejoin: "round" }, void 0), _jsx("path", { d: "M32 42.6667V44", stroke: "#CF4520", strokeWidth: "5", strokeLinecap: "round", strokeLinejoin: "round" }, void 0)] }), void 0));
143
+ var errorIcon = (_jsxs("svg", __assign({ width: "68", height: "68", viewBox: "0 0 68 68", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, { children: [_jsxs("g", __assign({ clipPath: "url(#clip0_1052_34495)" }, { children: [_jsx("rect", { width: "68", height: "68", fill: "white" }, void 0), _jsx("g", __assign({ style: { mixBlendMode: "multiply" } }, { children: _jsx("path", { d: "M28.5668 8.05854C29.6943 6.10577 32.5129 6.10576 33.6403 8.05854L59.1466 52.2368C60.274 54.1895 58.8648 56.6305 56.6099 56.6305H5.59726C3.34239 56.6305 1.93309 54.1895 3.06053 52.2368L28.5668 8.05854Z", fill: "url(#paint0_linear_1052_34495)" }, void 0) }), void 0), _jsx("g", __assign({ style: { mixBlendMode: "multiply" } }, { children: _jsx("path", { d: "M34.4375 9.68867C35.5649 7.73589 38.3835 7.73589 39.511 9.68867L65.816 55.2503C66.9434 57.2031 65.5341 59.6441 63.2793 59.6441H10.6692C8.41432 59.6441 7.00502 57.2031 8.13246 55.2503L34.4375 9.68867Z", fill: "url(#paint1_linear_1052_34495)" }, void 0) }), void 0), _jsx("rect", { x: "29.0371", y: "21.2632", width: "6.43183", height: "21.3972", rx: "2.92916", fill: "#FFFDF8" }, void 0), _jsx("rect", { x: "29.0371", y: "44.7898", width: "6.43183", height: "5.61436", rx: "2.80718", fill: "#FFFDF8" }, void 0)] }), void 0), _jsxs("defs", { children: [_jsxs("linearGradient", __assign({ id: "paint0_linear_1052_34495", x1: "10.0099", y1: "28.8136", x2: "30.2646", y2: "54.4823", gradientUnits: "userSpaceOnUse" }, { children: [_jsx("stop", { stopColor: "#FD5C39" }, void 0), _jsx("stop", { offset: "1", stopColor: "#FFB869" }, void 0)] }), void 0), _jsxs("linearGradient", __assign({ id: "paint1_linear_1052_34495", x1: "18.8007", y1: "74.0811", x2: "85.2567", y2: "33.8684", gradientUnits: "userSpaceOnUse" }, { children: [_jsx("stop", { stopColor: "#E7C551" }, void 0), _jsx("stop", { offset: "1", stopColor: "#FEE18F" }, void 0)] }), void 0), _jsx("clipPath", __assign({ id: "clip0_1052_34495" }, { children: _jsx("rect", { width: "68", height: "68", fill: "white" }, void 0) }), void 0)] }, void 0)] }), void 0));
143
144
  var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6;
@@ -16,7 +16,7 @@ import { Div, Span } from "../styled/utils";
16
16
  import { useImporterContext } from "./ImporterContextProvider";
17
17
  export var TrialModeBanner = function () {
18
18
  var inTrialMode = useImporterContext().inTrialMode;
19
- return (_jsx(_Fragment, { children: inTrialMode && (_jsxs(Div, __assign({ bg: theme.colors.orange100, h: 80, dflex: true, alignCenter: true, justifyCenter: true }, { children: [_jsx(Div, __assign({ ml: 33, mr: 8 }, { children: exclamationPointIcon }), void 0), _jsx(Span, __assign({ mr: 16 }, { children: "You're currently in Test mode. Subscribe to a plan to deploy to your website." }), void 0), _jsx(Button, __assign({ w: 120, br: 8, variant: "secondary", onClick: function () {
19
+ return (_jsx(_Fragment, { children: inTrialMode && (_jsxs(Div, __assign({ bg: theme.colors.orange100, h: 80, dflex: true, alignCenter: true, justifyCenter: true }, { children: [_jsx(Div, __assign({ ml: 33, mr: 8 }, { children: exclamationPointIcon }), void 0), _jsx(Span, __assign({ mr: 16 }, { children: "You're currently in Trial mode. Subscribe to a plan to deploy to your website." }), void 0), _jsx(Button, __assign({ w: 120, br: 8, variant: "secondary", onClick: function () {
20
20
  window.location.href = "".concat(process.env.REACT_APP_API_BASE_URL, "/account/billing");
21
21
  } }, { children: "Select plan" }), void 0)] }), void 0)) }, void 0));
22
22
  };
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
- import { AppResponse } from "../../..";
2
+ import { AppResponse, SpreadsheetOptions } from "../../..";
3
3
  import { BatchValidationErrors, Field, OnValidateBatch, OnValidateRecord, Record } from "../../../types";
4
- export declare const getBatchErrors: (records: any, onValidateRecord: any) => Promise<any>;
4
+ export declare const getBatchErrors: (records: Record[], onValidateRecord: OnValidateRecord) => Promise<BatchValidationErrors>;
5
5
  declare type State = {
6
6
  rowWidth?: number;
7
7
  data: Record[];
@@ -33,13 +33,13 @@ declare type Props = {
33
33
  appResponse?: AppResponse;
34
34
  onValidateRecord: OnValidateRecord;
35
35
  onValidateBatch?: OnValidateBatch;
36
- validationBatchSize?: number;
37
36
  children: JSX.Element;
38
37
  fields: Field[];
38
+ options: SpreadsheetOptions;
39
39
  highlightFirstRow: boolean;
40
40
  submittedData?: Record[];
41
41
  setReviewedData?: React.Dispatch<React.SetStateAction<Record[]>>;
42
42
  };
43
- export declare const SpreadsheetContextProvider: ({ initialData, rowWidth, onValidateRecord, onValidateBatch, appResponse, fields, isReadOnly, validationBatchSize, highlightFirstRow, submittedData, setReviewedData, children, }: Props) => JSX.Element;
43
+ export declare const SpreadsheetContextProvider: ({ initialData, rowWidth, onValidateRecord, onValidateBatch, appResponse, fields, options, isReadOnly, highlightFirstRow, submittedData, setReviewedData, children, }: Props) => JSX.Element;
44
44
  export declare const useSpreadsheetContext: () => State;
45
45
  export {};
@@ -56,45 +56,38 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
56
56
  };
57
57
  import { jsx as _jsx } from "react/jsx-runtime";
58
58
  import { createContext, useContext, useEffect, useState } from "react";
59
+ import { formatBatchErrors } from "../../..";
59
60
  import { getRecordErrors, getRenderedRecordWithErrors, recordIsEmpty, } from "./common";
60
61
  var MINIMUM_ROW_COUNT = 20;
61
- // time in ms
62
- var batchValidationIdleTime = 500;
63
62
  var getRowId = function (id) { return "r".concat(id); };
64
63
  export var getBatchErrors = function (records, onValidateRecord) { return __awaiter(void 0, void 0, void 0, function () {
65
- var getRecordError, errors;
64
+ var batchErrors;
66
65
  return __generator(this, function (_a) {
67
66
  switch (_a.label) {
68
- case 0:
69
- getRecordError = function (record) { return __awaiter(void 0, void 0, void 0, function () {
67
+ case 0: return [4 /*yield*/, Promise.all(records.map(function (record) { return __awaiter(void 0, void 0, void 0, function () {
70
68
  var _a;
71
69
  return __generator(this, function (_b) {
72
70
  switch (_b.label) {
73
71
  case 0:
74
72
  _a = {
75
- id: record._meta.id
73
+ rowId: record._meta.id
76
74
  };
77
75
  return [4 /*yield*/, onValidateRecord(record)];
78
- case 1: return [2 /*return*/, (_a.error = _b.sent(),
76
+ case 1: return [2 /*return*/, (_a.errors = _b.sent(),
79
77
  _a)];
80
78
  }
81
79
  });
82
- }); };
83
- return [4 /*yield*/, Promise.all(records.map(function (r) { return getRecordError(r); }))];
80
+ }); }))];
84
81
  case 1:
85
- errors = _a.sent();
86
- return [2 /*return*/, errors.reduce(function (prevState, curr) {
87
- var newState = __assign({}, prevState);
88
- newState[curr.id] = curr.error;
89
- return newState;
90
- }, {})];
82
+ batchErrors = _a.sent();
83
+ return [2 /*return*/, formatBatchErrors(batchErrors)];
91
84
  }
92
85
  });
93
86
  }); };
94
87
  var SpreadsheetContext = createContext({});
95
88
  var sleep = function (n) { return new Promise(function (resolve) { return setTimeout(resolve, n); }); };
96
89
  export var SpreadsheetContextProvider = function (_a) {
97
- var initialData = _a.initialData, _b = _a.rowWidth, rowWidth = _b === void 0 ? 1 : _b, _c = _a.onValidateRecord, onValidateRecord = _c === void 0 ? null : _c, _d = _a.onValidateBatch, onValidateBatch = _d === void 0 ? null : _d, appResponse = _a.appResponse, fields = _a.fields, isReadOnly = _a.isReadOnly, validationBatchSize = _a.validationBatchSize, highlightFirstRow = _a.highlightFirstRow, submittedData = _a.submittedData, setReviewedData = _a.setReviewedData, children = _a.children;
90
+ var initialData = _a.initialData, _b = _a.rowWidth, rowWidth = _b === void 0 ? 1 : _b, _c = _a.onValidateRecord, onValidateRecord = _c === void 0 ? null : _c, _d = _a.onValidateBatch, onValidateBatch = _d === void 0 ? null : _d, appResponse = _a.appResponse, fields = _a.fields, options = _a.options, isReadOnly = _a.isReadOnly, highlightFirstRow = _a.highlightFirstRow, submittedData = _a.submittedData, setReviewedData = _a.setReviewedData, children = _a.children;
98
91
  var _e = useState(initialData.map(function (d, i) { return (__assign(__assign({}, d), { _meta: { id: getRowId(i), rowIndex: i } })); })), data = _e[0], setData = _e[1];
99
92
  var _f = useState(false), isLoading = _f[0], setIsLoading = _f[1];
100
93
  var _g = useState(null), sortByFieldErrors = _g[0], setSortByFieldErrors = _g[1];
@@ -109,8 +102,9 @@ export var SpreadsheetContextProvider = function (_a) {
109
102
  }), columnErrorCounts = _l.columnErrorCounts, totalErrors = _l.totalErrors, isValidationComplete = _l.isValidationComplete;
110
103
  useEffect(function () {
111
104
  var init = function () { return __awaiter(void 0, void 0, void 0, function () {
112
- var addEmtpyRows, validateInBatches;
105
+ var batchValidationDelayMs, batchValidationSize, addEmtpyRows, validateInBatches;
113
106
  return __generator(this, function (_a) {
107
+ batchValidationDelayMs = options.batchValidationDelayMs, batchValidationSize = options.batchValidationSize;
114
108
  addEmtpyRows = function () {
115
109
  var newData = __spreadArray([], data, true);
116
110
  var emptyRecord = fields.reduce(function (obj, f) {
@@ -128,16 +122,18 @@ export var SpreadsheetContextProvider = function (_a) {
128
122
  if (data.length < MINIMUM_ROW_COUNT)
129
123
  addEmtpyRows();
130
124
  validateInBatches = function () { return __awaiter(void 0, void 0, void 0, function () {
131
- var validationErrors, batchSize, idx, batch, errors;
125
+ var validationErrors, batchSize, batchCount, batchIdx, idx, batch, errors, validationPercentage;
132
126
  return __generator(this, function (_a) {
133
127
  switch (_a.label) {
134
128
  case 0:
135
129
  validationErrors = {};
136
- batchSize = Math.min(validationBatchSize, data.length) || data.length;
137
- idx = 0;
130
+ batchSize = Math.min(Math.floor(batchValidationSize), data.length) || data.length;
131
+ batchCount = Math.ceil(data.length / batchSize);
132
+ batchIdx = 0;
138
133
  _a.label = 1;
139
134
  case 1:
140
- if (!(idx < data.length)) return [3 /*break*/, 5];
135
+ if (!(batchIdx < batchCount)) return [3 /*break*/, 5];
136
+ idx = batchIdx * batchSize;
141
137
  batch = data.slice(idx, idx + batchSize);
142
138
  return [4 /*yield*/, (onValidateBatch
143
139
  ? onValidateBatch(batch)
@@ -146,15 +142,16 @@ export var SpreadsheetContextProvider = function (_a) {
146
142
  errors = _a.sent();
147
143
  validationErrors = __assign(__assign({}, validationErrors), errors);
148
144
  // unblocks main thread for rendering ui
149
- return [4 /*yield*/, sleep(batchValidationIdleTime)];
145
+ return [4 /*yield*/, sleep(batchValidationDelayMs)];
150
146
  case 3:
151
147
  // unblocks main thread for rendering ui
152
148
  _a.sent();
153
- setBatchValidationPercentage(Math.floor(((idx + batchSize) / data.length) * 100));
149
+ validationPercentage = (Math.min(idx + batchSize, data.length) / data.length) * 100;
150
+ setBatchValidationPercentage(Math.floor(validationPercentage));
154
151
  setBatchValidationErrors(validationErrors);
155
152
  _a.label = 4;
156
153
  case 4:
157
- idx += batchSize;
154
+ batchIdx++;
158
155
  return [3 /*break*/, 1];
159
156
  case 5: return [2 /*return*/];
160
157
  }