fuse-importer 0.21.0 → 0.23.2

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 (58) hide show
  1. package/README.md +259 -0
  2. package/lib/esm/Importer/ImporterContextProvider.d.ts +31 -4
  3. package/lib/esm/Importer/ImporterContextProvider.js +40 -33
  4. package/lib/esm/Importer/Matcher/index.js +6 -5
  5. package/lib/esm/Importer/PreviewModeBanner.d.ts +2 -0
  6. package/lib/esm/Importer/PreviewModeBanner.js +20 -0
  7. package/lib/esm/Importer/Review/index.js +14 -18
  8. package/lib/esm/Importer/SpreadsheetReviewContextProvider.js +1 -1
  9. package/lib/esm/Importer/Stepper.js +10 -3
  10. package/lib/esm/Importer/Uploader/DragAndDropImporter/ImporterDropzone.js +4 -1
  11. package/lib/esm/Importer/Uploader/HeadersPreview.js +19 -17
  12. package/lib/esm/Importer/common/Spreadsheet/SpreadsheetContextProvider.js +7 -5
  13. package/lib/esm/Importer/common/Spreadsheet/common/FieldHeader.d.ts +7 -0
  14. package/lib/esm/Importer/common/Spreadsheet/common/FieldHeader.js +31 -0
  15. package/lib/esm/Importer/common/Spreadsheet/common/fields/SpeadsheetAutocomplete.d.ts +11 -6
  16. package/lib/esm/Importer/common/Spreadsheet/common/fields/SpeadsheetAutocomplete.js +6 -7
  17. package/lib/esm/Importer/common/Spreadsheet/common/fields/SpreadsheetInput.d.ts +4 -4
  18. package/lib/esm/Importer/common/Spreadsheet/common/fields/SpreadsheetInput.js +4 -5
  19. package/lib/esm/Importer/common/Spreadsheet/common/fields/index.d.ts +6 -5
  20. package/lib/esm/Importer/common/Spreadsheet/common/fields/index.js +14 -6
  21. package/lib/esm/Importer/common/Spreadsheet/common/index.d.ts +3 -0
  22. package/lib/esm/Importer/common/Spreadsheet/common/index.js +53 -9
  23. package/lib/esm/Importer/common/Spreadsheet/index.js +28 -57
  24. package/lib/esm/Importer/common/Spreadsheet/inputs/Boolean.d.ts +3 -0
  25. package/lib/esm/Importer/common/Spreadsheet/inputs/Boolean.js +18 -0
  26. package/lib/esm/Importer/common/Spreadsheet/inputs/EmailInput.d.ts +3 -0
  27. package/lib/esm/Importer/common/Spreadsheet/inputs/EmailInput.js +14 -0
  28. package/lib/esm/Importer/common/Spreadsheet/inputs/EnumInput.d.ts +6 -0
  29. package/lib/esm/Importer/common/Spreadsheet/inputs/EnumInput.js +30 -0
  30. package/lib/esm/Importer/common/Spreadsheet/inputs/FloatInput.d.ts +3 -0
  31. package/lib/esm/Importer/common/Spreadsheet/inputs/FloatInput.js +16 -0
  32. package/lib/esm/Importer/common/Spreadsheet/inputs/IntegerInput.d.ts +3 -0
  33. package/lib/esm/Importer/common/Spreadsheet/inputs/IntegerInput.js +16 -0
  34. package/lib/esm/Importer/common/Spreadsheet/inputs/StringInput.d.ts +3 -0
  35. package/lib/esm/Importer/common/Spreadsheet/inputs/StringInput.js +14 -0
  36. package/lib/esm/Importer/common/Spreadsheet/inputs/index.d.ts +13 -0
  37. package/lib/esm/Importer/common/Spreadsheet/inputs/index.js +20 -0
  38. package/lib/esm/Importer/common/index.d.ts +2 -2
  39. package/lib/esm/Importer/common/index.js +2 -2
  40. package/lib/esm/Importer/index.d.ts +1 -0
  41. package/lib/esm/Importer/index.js +3 -4
  42. package/lib/esm/Importer/theme.d.ts +225 -0
  43. package/lib/esm/Importer/theme.js +18 -0
  44. package/lib/esm/common/buttons.d.ts +15 -5
  45. package/lib/esm/common/buttons.js +13 -11
  46. package/lib/esm/common/index.js +1 -1
  47. package/lib/esm/common/inputs/Autocomplete.d.ts +2 -2
  48. package/lib/esm/common/inputs/TextInput.js +8 -1
  49. package/lib/esm/common/logo.js +1 -1
  50. package/lib/esm/styled/themeType.d.ts +1 -1
  51. package/lib/esm/styled/utils.d.ts +3 -0
  52. package/lib/esm/styled/utils.js +4 -3
  53. package/lib/esm/types.d.ts +7 -2
  54. package/lib/esm/types.js +4 -1
  55. package/lib/main.js +1 -1
  56. package/package.json +2 -2
  57. package/lib/esm/Importer/useCustomImporter.d.ts +0 -4
  58. package/lib/esm/Importer/useCustomImporter.js +0 -81
@@ -30,6 +30,7 @@ import { useImporterContext } from "../ImporterContextProvider";
30
30
  import { FieldTypes } from "../../types";
31
31
  import { Div } from "../../styled/utils";
32
32
  import { getSpreadsheetRowWidth } from "../common/utils";
33
+ import { useMemo } from "react";
33
34
  var HeaderButtonsWrapper = styled(Div)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n > div {\n margin-left: 8px;\n margin-right: 8px;\n }\n"], ["\n > div {\n margin-left: 8px;\n margin-right: 8px;\n }\n"])));
34
35
  var HeaderButtons = function () {
35
36
  var _a = useImporterContext(), setCurrentStepIndex = _a.setCurrentStepIndex, resetImport = _a.resetImport;
@@ -40,13 +41,14 @@ var HeaderButtons = function () {
40
41
  };
41
42
  var HeadersPreview = function () {
42
43
  var uploadedData = useImporterContext().uploadedData;
43
- var formattedData = (function () {
44
+ var formattedData = useMemo(function () {
44
45
  var firstRowLen = 0;
45
- if (uploadedData.length > 0 && Array.isArray(uploadedData[0]))
46
+ if (uploadedData.length > 0 && Array.isArray(uploadedData[0])) {
46
47
  firstRowLen = uploadedData[0].length;
47
- var placeholderHeaders = __spreadArray([], Array(firstRowLen), true).map(function (_, i) {
48
- return String.fromCharCode(65 + i);
49
- });
48
+ }
49
+ var placeholderHeaders = new Array(firstRowLen)
50
+ .fill(null)
51
+ .map(function (_, i) { return String.fromCharCode(65 + i); });
50
52
  var getDataRows = function () {
51
53
  var emptyRows = [];
52
54
  if (uploadedData.length < 20)
@@ -60,18 +62,18 @@ var HeadersPreview = function () {
60
62
  return entry;
61
63
  });
62
64
  };
63
- var dataRows = getDataRows();
64
- return dataRows;
65
- })();
66
- var placeholderFields = Object.keys(formattedData[0]);
67
- var readonlyFields = placeholderFields.map(function (key) {
68
- return {
69
- label: key,
70
- name: key,
71
- type: FieldTypes.string,
72
- isRequired: false,
73
- };
74
- });
65
+ return getDataRows();
66
+ }, [uploadedData]);
67
+ var readonlyFields = useMemo(function () {
68
+ return Object.keys(formattedData[0]).map(function (key) {
69
+ return {
70
+ label: key,
71
+ name: key,
72
+ type: FieldTypes.string,
73
+ isRequired: false,
74
+ };
75
+ });
76
+ }, []);
75
77
  return (_jsx(_Fragment, { children: _jsxs(Div, __assign({ flexColumn: true, centered: true, pt: 40 }, { children: [_jsx(Div, __assign({ h2: true, mb: 16 }, { children: "Verify Your Column Headers" })), _jsx(Div, __assign({ body1: true, mb: 24, textAlignCenter: true }, { children: "File must contain column headers to proceed." })), _jsx(HeaderButtons, {}), _jsx(Div, __assign({ w100: true, centered: true, mb: 36 }, { children: _jsx(Spreadsheet, __assign({ rowWidth: getSpreadsheetRowWidth(readonlyFields, 6), isReadOnly: true, initialData: formattedData }, { fields: readonlyFields }, { highlightFirstRow: true })) }))] })) }));
76
78
  };
77
79
  export default HeadersPreview;
@@ -55,7 +55,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
55
55
  return to.concat(ar || Array.prototype.slice.call(from));
56
56
  };
57
57
  import { jsx as _jsx } from "react/jsx-runtime";
58
- import { createContext, useContext, useEffect, useState } from "react";
58
+ import { createContext, useContext, useEffect, useState, useMemo, } from "react";
59
59
  import { formatBatchErrors } from "../../..";
60
60
  import { getRecordErrors, getRenderedRecordWithErrors, recordIsEmpty, } from "./common";
61
61
  var MINIMUM_ROW_COUNT = 20;
@@ -102,10 +102,10 @@ export var SpreadsheetContextProvider = function (_a) {
102
102
  }), columnErrorCounts = _l.columnErrorCounts, totalErrors = _l.totalErrors, isValidationComplete = _l.isValidationComplete;
103
103
  useEffect(function () {
104
104
  var init = function () { return __awaiter(void 0, void 0, void 0, function () {
105
- var batchValidationDelayMs, batchValidationSize, addEmtpyRows, validateInBatches;
105
+ var batchValidationDelayMs, batchValidationSize, addEmptyRows, validateInBatches;
106
106
  return __generator(this, function (_a) {
107
107
  batchValidationDelayMs = options.batchValidationDelayMs, batchValidationSize = options.batchValidationSize;
108
- addEmtpyRows = function () {
108
+ addEmptyRows = function () {
109
109
  var newData = __spreadArray([], data, true);
110
110
  var emptyRecord = fields.reduce(function (obj, f) {
111
111
  var _a;
@@ -120,7 +120,7 @@ export var SpreadsheetContextProvider = function (_a) {
120
120
  setData(newData);
121
121
  };
122
122
  if (data.length < MINIMUM_ROW_COUNT)
123
- addEmtpyRows();
123
+ addEmptyRows();
124
124
  validateInBatches = function () { return __awaiter(void 0, void 0, void 0, function () {
125
125
  var validationErrors, batchSize, batchCount, batchIdx, idx, batch, errors, validationPercentage;
126
126
  return __generator(this, function (_a) {
@@ -280,7 +280,9 @@ var useValidationState = function (_a) {
280
280
  };
281
281
  updateErrorCounts();
282
282
  }, [data, batchValidationErrors]);
283
- var totalErrors = Object.keys(columnErrorCounts).reduce(function (total, key) { return total + (columnErrorCounts[key] || 0); }, 0);
283
+ var totalErrors = useMemo(function () {
284
+ return Object.keys(columnErrorCounts).reduce(function (total, key) { return total + (columnErrorCounts[key] || 0); }, 0);
285
+ }, []);
284
286
  var isValidationComplete = batchValidationErrors && totalErrors === 0;
285
287
  return { columnErrorCounts: columnErrorCounts, totalErrors: totalErrors, isValidationComplete: isValidationComplete };
286
288
  };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ import { Field } from "../../../../types";
3
+ export declare type FieldHeaderProps = {
4
+ field: Field;
5
+ sortByFieldErrors: (name: string) => void;
6
+ };
7
+ export declare const FieldHeader: React.FC<FieldHeaderProps>;
@@ -0,0 +1,31 @@
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 { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
17
+ import { TooltipProvider } from "../../../../common";
18
+ import { Div } from "../../../../styled/utils";
19
+ import { useSpreadsheetContext } from "../SpreadsheetContextProvider";
20
+ import styled, { css } from "styled-components";
21
+ var ErrorCount = styled(Div)(function (_a) {
22
+ var _b = _a.theme, colors = _b.colors, c = _b.css;
23
+ 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
+ export var FieldHeader = function (_a) {
26
+ var field = _a.field, sortByFieldErrors = _a.sortByFieldErrors;
27
+ var columnErrorCounts = useSpreadsheetContext().columnErrorCounts;
28
+ var fieldErrorCount = columnErrorCounts[field.name];
29
+ return (_jsxs(Div, __assign({ 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({ 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 })) })) })) })))] })));
30
+ };
31
+ var templateObject_1;
@@ -1,7 +1,12 @@
1
- /// <reference types="react" />
2
- export declare const SpreadsheetAutocomplete: ({ name, record, options, isInputDisabled, }: {
3
- name: any;
4
- record: any;
5
- options: any;
1
+ import React from "react";
2
+ import { Option } from "../../../../../common/inputs/Autocomplete";
3
+ import { Record, FieldTypes } from "../../../../../types";
4
+ export declare type AutoCompleteOption = Option;
5
+ export declare type SpreadsheetAutocompleteProps = {
6
+ name: string;
7
+ record: Record;
8
+ options: AutoCompleteOption[];
6
9
  isInputDisabled?: boolean;
7
- }) => JSX.Element;
10
+ fieldType: FieldTypes;
11
+ };
12
+ export declare const SpreadsheetAutocomplete: React.FC<SpreadsheetAutocompleteProps>;
@@ -15,9 +15,9 @@ var __assign = (this && this.__assign) || function () {
15
15
  };
16
16
  import { jsx as _jsx } from "react/jsx-runtime";
17
17
  import styled, { css } from "styled-components";
18
- import { SpreadsheetField, useSpreadsheetField, useValidationError } from ".";
18
+ import { SpreadsheetField, useSpreadsheetField } from ".";
19
19
  import { spreadsheetRowHeightPx } from "..";
20
- import { Autocomplete as AutocompleteBase } from "../../../../../common/inputs/Autocomplete";
20
+ import { Autocomplete as AutocompleteBase, } from "../../../../../common/inputs/Autocomplete";
21
21
  import { SelectMenuDiv, SelectMenuScrollArea, } from "../../../../../common/inputs/SelectMenu";
22
22
  import { HTMLInput, TextInputIcon, } from "../../../../../common/inputs/TextInput";
23
23
  import { useSpreadsheetContext } from "../../SpreadsheetContextProvider";
@@ -26,12 +26,11 @@ var Autocomplete = styled(AutocompleteBase)(templateObject_3 || (templateObject_
26
26
  }, function (p) {
27
27
  return p.hasError && css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n color: ", ";\n "], ["\n color: ", ";\n "])), function (p) { return p.theme.colors.error; });
28
28
  }, TextInputIcon, SelectMenuDiv, SelectMenuScrollArea);
29
- export var SpreadsheetAutocomplete = function (_a) {
30
- var name = _a.name, record = _a.record, options = _a.options, _b = _a.isInputDisabled, isInputDisabled = _b === void 0 ? false : _b;
31
- var validationError = useValidationError(name, record).validationError;
32
- var _c = useSpreadsheetField(name, record), value = _c.value, setValue = _c.setValue;
29
+ export var SpreadsheetAutocomplete = function (props) {
30
+ var name = props.name, record = props.record, options = props.options, fieldType = props.fieldType, _a = props.isInputDisabled, isInputDisabled = _a === void 0 ? false : _a;
31
+ var _b = useSpreadsheetField(name, record, fieldType), value = _b.value, setValue = _b.setValue, validationError = _b.validationError;
33
32
  var setIsScrollingEnabled = useSpreadsheetContext().setIsScrollingEnabled;
34
- return (_jsx(SpreadsheetField, __assign({}, { name: name, record: record }, { children: _jsx(Autocomplete, { placement: "bottom", isInputDisabled: isInputDisabled, hasError: !!validationError, onToggle: function (isOpen) { return setIsScrollingEnabled(!isOpen); }, options: options, value: value, icon: chevronDownIcon, onChange: function (v) { return setValue(v); } }) })));
33
+ return (_jsx(SpreadsheetField, __assign({ validationError: validationError }, { children: _jsx(Autocomplete, { placement: "bottom", isInputDisabled: isInputDisabled, hasError: !!validationError, onToggle: function (isOpen) { return setIsScrollingEnabled(!isOpen); }, options: options, value: value, icon: chevronDownIcon, onChange: function (v) { return setValue(v); } }) })));
35
34
  };
36
35
  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" }) })));
37
36
  var templateObject_1, templateObject_2, templateObject_3;
@@ -1,12 +1,12 @@
1
1
  /// <reference types="react" />
2
2
  import { HTMLInputCSSProps } from "../../../../../styled/utils";
3
- import { Record } from "../../../../../types";
4
- declare type SpreadsheetTextInputArgs = {
3
+ import { FieldTypes, Record } from "../../../../../types";
4
+ export declare type SpreadsheetTextInputArgs = {
5
5
  name: string;
6
6
  record: Record;
7
+ fieldType: FieldTypes;
7
8
  } & HTMLInputCSSProps;
8
- export declare const SpreadsheetInput: ({ name, record, ...props }: SpreadsheetTextInputArgs) => JSX.Element;
9
+ export declare const SpreadsheetInput: ({ name, record, fieldType, ...props }: SpreadsheetTextInputArgs) => JSX.Element;
9
10
  export declare const Input: import("styled-components").StyledComponent<"input", import("styled-components").DefaultTheme, {
10
11
  hasError: boolean;
11
12
  } & import("../../../../../styled/utils").HTMLInputProps & import("../../../../../styled/utils").CSSProps, never>;
12
- export {};
@@ -26,12 +26,11 @@ var __rest = (this && this.__rest) || function (s, e) {
26
26
  };
27
27
  import { jsx as _jsx } from "react/jsx-runtime";
28
28
  import styled, { css } from "styled-components";
29
- import { SpreadsheetField, useSpreadsheetField, useValidationError } from ".";
29
+ import { SpreadsheetField, useSpreadsheetField } from ".";
30
30
  export var SpreadsheetInput = function (_a) {
31
- var name = _a.name, record = _a.record, props = __rest(_a, ["name", "record"]);
32
- var validationError = useValidationError(name, record).validationError;
33
- var _b = useSpreadsheetField(name, record), value = _b.value, setValue = _b.setValue;
34
- return (_jsx(SpreadsheetField, __assign({}, { name: name, record: record }, { children: _jsx(Input, __assign({ hasError: !!validationError, value: value || "", onChange: function (_a) {
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) {
35
34
  var value = _a.target.value;
36
35
  return setValue(value);
37
36
  } }, props)) })));
@@ -1,14 +1,15 @@
1
1
  import React from "react";
2
- import { Record } from "../../../../../types";
2
+ import { FieldTypes, Record } from "../../../../../types";
3
+ export declare const parseValue: (fieldType: FieldTypes, value: any) => any;
3
4
  export declare const useValidationError: (fieldName: string, record: Record) => {
4
5
  validationError: any;
5
6
  };
6
- export declare const useSpreadsheetField: (name: any, record: Record) => {
7
+ export declare const useSpreadsheetField: (name: any, record: Record, fieldType: FieldTypes) => {
7
8
  value: any;
8
9
  setValue: React.Dispatch<any>;
10
+ validationError: any;
9
11
  };
10
- export declare const SpreadsheetField: ({ name, record, children }: {
11
- name: any;
12
- record: any;
12
+ export declare const SpreadsheetField: ({ validationError, children }: {
13
+ validationError: any;
13
14
  children: any;
14
15
  }) => JSX.Element;
@@ -61,11 +61,19 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
61
61
  import { jsx as _jsx } from "react/jsx-runtime";
62
62
  import { useEffect, useRef, useState } from "react";
63
63
  import styled, { css } from "styled-components";
64
- import { getRecordErrors, getRenderedRecordWithErrors } from "..";
64
+ import { getRecordErrors, getRenderedRecordWithErrors, isFloat, isInteger, } from "..";
65
65
  import { TooltipProvider } from "../../../../../common/TooltipProvider";
66
66
  import { Div } from "../../../../../styled/utils";
67
+ import { FieldTypes } from "../../../../../types";
67
68
  import { useSpreadsheetReviewContext } from "../../../../SpreadsheetReviewContextProvider";
68
69
  import { useSpreadsheetContext } from "../../SpreadsheetContextProvider";
70
+ export var parseValue = function (fieldType, value) {
71
+ if (fieldType === FieldTypes.float)
72
+ return isFloat(value) ? parseFloat(value) : value;
73
+ if (fieldType === FieldTypes.integer)
74
+ return isInteger(value) ? parseInt(value) : value;
75
+ return value;
76
+ };
69
77
  export var useValidationError = function (fieldName, record) {
70
78
  var isSubmitting = useSpreadsheetReviewContext().isSubmitting;
71
79
  var _a = useSpreadsheetContext(), fields = _a.fields, submittedData = _a.submittedData, batchValidationErrors = _a.batchValidationErrors;
@@ -81,9 +89,10 @@ export var useValidationError = function (fieldName, record) {
81
89
  }
82
90
  return { validationError: validationError };
83
91
  };
84
- export var useSpreadsheetField = function (name, record) {
92
+ export var useSpreadsheetField = function (name, record, fieldType) {
85
93
  var _a = useSpreadsheetContext(), data = _a.data, setData = _a.setData, onValidateRecord = _a.onValidateRecord;
86
94
  var _b = useState(record[name]), value = _b[0], setValue = _b[1];
95
+ var validationError = useValidationError(name, record).validationError;
87
96
  // used for debouncing validations
88
97
  var timeoutIdRef = useRef(null);
89
98
  // used for getting updated data in setTimeout
@@ -110,7 +119,7 @@ export var useSpreadsheetField = function (name, record) {
110
119
  switch (_f.label) {
111
120
  case 0:
112
121
  newData = __spreadArray([], dataRef.current, true);
113
- newRecord = __assign(__assign({}, recordRef.current), (_d = {}, _d[name] = value, _d));
122
+ newRecord = __assign(__assign({}, recordRef.current), (_d = {}, _d[name] = parseValue(fieldType, value), _d));
114
123
  rowIndex = newData.findIndex(function (r) { return r._meta.id === record._meta.id; });
115
124
  _a = newData;
116
125
  _b = rowIndex;
@@ -128,7 +137,7 @@ export var useSpreadsheetField = function (name, record) {
128
137
  });
129
138
  }); }, 300);
130
139
  }, [value]);
131
- return { value: value, setValue: setValue };
140
+ return { value: value, setValue: setValue, validationError: validationError };
132
141
  };
133
142
  var ContentContainer = styled(Div)(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n height: calc(100% - 1px);\n width: 100%;\n ", ";\n ", "\n ", "\n"], ["\n height: calc(100% - 1px);\n width: 100%;\n ", ";\n ", "\n ", "\n"])), function (p) { return p.theme.css.alignCenter; }, function (p) {
134
143
  return p.hasError && 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.error; }, function (p) { return p.theme.colors.red100; }, function (p) { return p.theme.colors.error; });
@@ -140,9 +149,8 @@ var Wrapper = styled(Div)(function (_a) {
140
149
  return css(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n ", "\n "], ["\n ", "\n "])), isLoading && css(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n pointer-events: none;\n "], ["\n pointer-events: none;\n "]))));
141
150
  });
142
151
  export var SpreadsheetField = function (_a) {
143
- var name = _a.name, record = _a.record, children = _a.children;
152
+ var validationError = _a.validationError, children = _a.children;
144
153
  var _b = useSpreadsheetContext(), isReadOnly = _b.isReadOnly, isLoading = _b.isLoading;
145
- var validationError = useValidationError(name, record).validationError;
146
154
  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 })) })) })) })));
147
155
  };
148
156
  var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5;
@@ -1,6 +1,9 @@
1
1
  import { Field, Record, BatchValidationErrors } from "../../../../types";
2
2
  export declare const spreadsheetRowHeightPx = 40;
3
3
  export declare const spreadsheetHeaderHeightPx = 40;
4
+ export declare const isTrue: (value: string) => boolean;
5
+ export declare const isInteger: (value: string) => boolean;
6
+ export declare const isFloat: (value: string) => boolean;
4
7
  export declare const recordIsEmpty: (record: any, fields: any) => any;
5
8
  export declare const getRenderedRecordWithErrors: ({ record, validationErrors, }: {
6
9
  record: any;
@@ -9,7 +9,9 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
+ var _a;
12
13
  import { FieldTypes, } from "../../../../types";
14
+ import { DateTime } from "luxon";
13
15
  export var spreadsheetRowHeightPx = 40;
14
16
  export var spreadsheetHeaderHeightPx = 40;
15
17
  var isEmpty = function (value) {
@@ -18,6 +20,22 @@ var isEmpty = function (value) {
18
20
  (typeof value === "object" && Object.keys(value).length === 0) ||
19
21
  (typeof value === "string" && value.trim().length === 0));
20
22
  };
23
+ var isEmail = function (value) {
24
+ var emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
25
+ return emailRegex.test(value);
26
+ };
27
+ var isUrl = function (value) {
28
+ var urlRegex = /^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/g;
29
+ return urlRegex.test(value);
30
+ };
31
+ export var isTrue = function (value) {
32
+ var _value = (value || "").toString().toLowerCase();
33
+ return ["true", "yes", "1", "y", "on", "t"].includes(_value);
34
+ };
35
+ export var isInteger = function (value) { return /^-?[0-9]+$/.test(value + ""); };
36
+ export var isFloat = function (value) {
37
+ return /^-?[0-9]+(?:\.[0-9]+)?$/.test(value + "");
38
+ };
21
39
  export var recordIsEmpty = function (record, fields) {
22
40
  return fields.reduce(function (isEmptyRecord, f) { return isEmptyRecord && isEmpty(record[f.name]); }, true);
23
41
  };
@@ -25,24 +43,50 @@ export var getRenderedRecordWithErrors = function (_a) {
25
43
  var record = _a.record, validationErrors = _a.validationErrors;
26
44
  return (__assign(__assign({}, record), { _meta: __assign(__assign({}, (record._meta || {})), { localValidationErrors: validationErrors, wasSeen: true }) }));
27
45
  };
46
+ var validateDatePattern = function (field, fieldValue) {
47
+ var date = DateTime.fromFormat(fieldValue, field.pattern);
48
+ if (!date.isValid) {
49
+ return "".concat(field.label, " must match the pattern ").concat(field.pattern);
50
+ }
51
+ };
52
+ var validations = (_a = {},
53
+ _a[FieldTypes.email] = function (field, fieldValue) {
54
+ if (!isEmail(fieldValue)) {
55
+ return "".concat(field.label, " is not a valid email");
56
+ }
57
+ },
58
+ _a[FieldTypes.url] = function (field, fieldValue) {
59
+ if (!isUrl(fieldValue)) {
60
+ return "".concat(field.label, " is not a valid url");
61
+ }
62
+ },
63
+ _a[FieldTypes.integer] = function (field, fieldValue) {
64
+ if (!isInteger(fieldValue)) {
65
+ return "".concat(field.label, " is not a valid integer");
66
+ }
67
+ },
68
+ _a[FieldTypes.float] = function (field, fieldValue) {
69
+ if (!isFloat(fieldValue)) {
70
+ return "".concat(field.label, " is not a valid float");
71
+ }
72
+ },
73
+ _a[FieldTypes.date] = validateDatePattern,
74
+ _a[FieldTypes.time] = validateDatePattern,
75
+ _a[FieldTypes.datetime] = validateDatePattern,
76
+ _a);
28
77
  export var getRecordErrors = function (_a) {
29
78
  var record = _a.record, fields = _a.fields, batchValidationErrors = _a.batchValidationErrors, submittedData = _a.submittedData;
30
79
  var submittedRecord = submittedData === null || submittedData === void 0 ? void 0 : submittedData.find(function (r) { return r._meta.id === record._meta.id; });
31
- var isEmail = function (value) {
32
- var emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
33
- return emailRegex.test(value);
34
- };
35
80
  var recordHasData = !recordIsEmpty(record, fields);
36
81
  if (recordHasData) {
37
82
  var recordTemplateValidationErrors = fields.reduce(function (errors, field) {
38
83
  var newErrors = __assign({}, errors);
39
84
  var fieldValue = record[field.name];
40
- if (isEmpty(fieldValue)) {
41
- if (field.isRequired)
42
- newErrors[field.name] = "".concat(field.label, " is required");
85
+ if (isEmpty(fieldValue) && field.isRequired) {
86
+ newErrors[field.name] = "".concat(field.label, " is required");
43
87
  }
44
- else if (field.type === FieldTypes.email && !isEmail(fieldValue)) {
45
- newErrors[field.name] = "".concat(field.label, " is not a valid email");
88
+ else if (validations[field.type]) {
89
+ newErrors[field.name] = validations[field.type](field, fieldValue);
46
90
  }
47
91
  return newErrors;
48
92
  }, {});
@@ -49,29 +49,34 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
49
49
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
50
50
  }
51
51
  };
52
+ var __rest = (this && this.__rest) || function (s, e) {
53
+ var t = {};
54
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
55
+ t[p] = s[p];
56
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
57
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
58
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
59
+ t[p[i]] = s[p[i]];
60
+ }
61
+ return t;
62
+ };
52
63
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
53
- import { useEffect, useMemo, useRef, useState } from "react";
54
- import styled, { css } from "styled-components";
64
+ import { useEffect, useMemo, useRef, useState, useCallback, } from "react";
65
+ import styled from "styled-components";
55
66
  import { getTableHeight } from "..";
56
- import { TooltipProvider } from "../../../common";
57
67
  import { TableView as TableViewBase, TableViewCellContainer, TableViewRow, } from "../../../common/Table/TableView";
58
68
  import { colors } from "../../../styled/theme/colorPalette";
59
69
  import { Div } from "../../../styled/utils";
60
- import { FieldTypes, } from "../../../types";
61
70
  import { useSpreadsheetReviewContext } from "../../SpreadsheetReviewContextProvider";
62
71
  import { getUnsubmittedData } from "../utils";
63
72
  import { spreadsheetHeaderHeightPx, spreadsheetRowHeightPx } from "./common";
64
- import { SpreadsheetAutocomplete } from "./common/fields/SpeadsheetAutocomplete";
65
- import { SpreadsheetInput } from "./common/fields/SpreadsheetInput";
73
+ import { FieldHeader } from "./common/FieldHeader";
66
74
  import GlobalStyle from "./GlobalStyle";
67
75
  import { SpreadsheetContextProvider, useSpreadsheetContext, } from "./SpreadsheetContextProvider";
68
76
  import { SpreadsheetRowNumbers } from "./SpreadsheetRowNumbers";
77
+ import { inputTypes } from "./inputs";
69
78
  var SpreadSheetWrapper = styled(Div)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n border: solid 1px ", ";\n border-radius: 8px;\n background: ", ";\n overflow: hidden !important;\n"], ["\n border: solid 1px ", ";\n border-radius: 8px;\n background: ", ";\n overflow: hidden !important;\n"])), function (p) { return p.theme.colors.gray300; }, function (p) { return p.theme.colors.white; });
70
79
  var TableView = styled(TableViewBase)(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n width: 100%;\n border: none;\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n overflow: hidden;\n background-color: ", ";\n ", " {\n border-bottom: none;\n height: 40px;\n }\n ", " {\n padding: 0;\n border-right: 1px solid ", ";\n }\n"], ["\n width: 100%;\n border: none;\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n overflow: hidden;\n background-color: ", ";\n ", " {\n border-bottom: none;\n height: 40px;\n }\n ", " {\n padding: 0;\n border-right: 1px solid ", ";\n }\n"])), function (p) { return p.theme.colors.gray50; }, TableViewRow, TableViewCellContainer, function (p) { return p.theme.colors.gray300; });
71
- var ErrorCount = styled(Div)(function (_a) {
72
- var _b = _a.theme, colors = _b.colors, c = _b.css;
73
- return css(templateObject_3 || (templateObject_3 = __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);
74
- });
75
80
  var Spreadsheet = function (_a) {
76
81
  var isReadOnly = _a.isReadOnly, initialData = _a.initialData, rowWidth = _a.rowWidth, fields = _a.fields, appResponse = _a.appResponse, options = _a.options, _b = _a.onValidateRecord, onValidateRecord = _b === void 0 ? null : _b, submittedData = _a.submittedData, setReviewedData = _a.setReviewedData, _c = _a.onValidateBatch, onValidateBatch = _c === void 0 ? null : _c, _d = _a.highlightFirstRow, highlightFirstRow = _d === void 0 ? false : _d;
77
82
  return (_jsx(SpreadsheetContextProvider, __assign({}, {
@@ -95,10 +100,6 @@ var SpreadSheetWithContext = function () {
95
100
  batchValidationPercentage < 100 &&
96
101
  batchValidationProgressUI })), _jsx(SpreadsheetData, {})] }));
97
102
  };
98
- var booleanOptions = [
99
- { label: "True", value: true },
100
- { label: "False", value: false },
101
- ];
102
103
  var SpreadsheetData = function () {
103
104
  var _a = useSpreadsheetReviewContext(), appResponse = _a.appResponse, isSubmitting = _a.isSubmitting;
104
105
  var _b = useSpreadsheetContext(), fields = _b.fields, data = _b.data, isLoading = _b.isLoading, isReadOnly = _b.isReadOnly, rowWidth = _b.rowWidth, sortByFieldErrors = _b.sortByFieldErrors, setSortByFieldErrors = _b.setSortByFieldErrors, validateRenderedRecords = _b.validateRenderedRecords, setIsLoading = _b.setIsLoading;
@@ -112,7 +113,7 @@ var SpreadsheetData = function () {
112
113
  setSortByFieldErrors(null);
113
114
  }, 10);
114
115
  }, [sortByFieldErrors]);
115
- var onSectionRendered = function (_a) {
116
+ var onSectionRendered = useCallback(function (_a) {
116
117
  var data = _a.data;
117
118
  return __awaiter(void 0, void 0, void 0, function () {
118
119
  return __generator(this, function (_b) {
@@ -128,59 +129,29 @@ var SpreadsheetData = function () {
128
129
  return [2 /*return*/];
129
130
  });
130
131
  });
131
- };
132
+ }, [isSortingTableData]);
132
133
  var columns = useMemo(function () {
133
- return fields.map(function (f) { return ({
134
- Header: function () {
135
- var columnErrorCounts = useSpreadsheetContext().columnErrorCounts;
136
- var fieldErrorCount = columnErrorCounts[f.name];
137
- return (_jsxs(Div, __assign({ p: "0 16px", spaceBetween: true, w100: true, alignCenter: true }, { children: [_jsxs(Div, __assign({ truncateText: true }, { children: [f.label, f.isRequired && "*"] })), fieldErrorCount && (_jsx(TooltipProvider, __assign({ mr: 3, w: 35, tooltip: "Sort by ".concat(f.label, " errors") }, { children: _jsx(ErrorCount, __assign({ onClick: function () { return setSortByFieldErrors(f.name); } }, { children: _jsx(Div, __assign({ centered: true }, { children: _jsx(Div, __assign({ w: 35, textAlignCenter: true, label3: true, truncateText: true }, { children: fieldErrorCount })) })) })) })))] })));
138
- },
134
+ return fields.map(function (field) { return ({
135
+ Header: function () { return (_jsx(FieldHeader, { field: field, sortByFieldErrors: setSortByFieldErrors })); },
139
136
  Content: function (record) {
140
- var props = {
141
- name: f.name,
142
- record: (function () {
143
- var res = __assign({}, record);
144
- delete res.rowIndex;
145
- return res;
146
- })(),
147
- };
148
- switch (f.type) {
149
- case FieldTypes.boolean:
150
- return (_jsx(SpreadsheetAutocomplete, __assign({ isInputDisabled: true }, props, { options: booleanOptions })));
151
- case FieldTypes.enum:
152
- return (_jsx(SpreadsheetAutocomplete, __assign({}, props, { options: f === null || f === void 0 ? void 0 : f.options.map(function (o) { return ({ label: o, value: o }); }) })));
153
- case FieldTypes.integer:
154
- return (_jsx(SpreadsheetInput, __assign({}, props, { type: "number", step: "1", onKeyDown: function (event) {
155
- if (event.key === "." ||
156
- event.key === "," ||
157
- event.key === "e") {
158
- event.preventDefault();
159
- }
160
- } })));
161
- case FieldTypes.float:
162
- return (_jsx(SpreadsheetInput, __assign({}, props, { type: "number", onKeyDown: function (event) {
163
- if (event.key === "e") {
164
- event.preventDefault();
165
- }
166
- } })));
167
- case FieldTypes.string:
168
- return _jsx(SpreadsheetInput, __assign({}, props, { type: "email" }));
169
- case FieldTypes.email:
170
- return _jsx(SpreadsheetInput, __assign({}, props, { type: "text" }));
171
- }
137
+ var Input = inputTypes[field.type];
138
+ var rowIndex = record.rowIndex, recordProp = __rest(record, ["rowIndex"]);
139
+ return (_jsx(Input, { fieldType: field.type, name: field.name, options: field.options, record: recordProp }));
172
140
  },
173
141
  }); });
174
142
  }, [fields]);
175
- var unsubmittedData = getUnsubmittedData(data, appResponse);
143
+ var unsubmittedData = useMemo(function () { return getUnsubmittedData(data, appResponse); }, [
144
+ data,
145
+ appResponse,
146
+ ]);
176
147
  var spreadsheetHeight = getTableHeight({
177
148
  headerHeight: spreadsheetHeaderHeightPx,
178
149
  rowHeight: spreadsheetRowHeightPx,
179
150
  dataCount: unsubmittedData.length,
180
- mininmumTableHeight: 450,
151
+ minimumTableHeight: 450,
181
152
  maxVisibleRows: 12,
182
153
  });
183
154
  return (_jsxs(_Fragment, { children: [_jsx(GlobalStyle, {}), !isSortingTableData && !isSubmitting && (_jsxs(SpreadSheetWrapper, __assign({ h: spreadsheetHeight, dflex: true, w: 1400 }, { children: [_jsx(SpreadsheetRowNumbers, { spreadsheetHasXScroll: rowWidth > 1, scrollTop: scrollTop, height: spreadsheetHeight }), _jsx(TableView, { tableHeadersHeight: spreadsheetHeaderHeightPx, highlightFirstRow: isReadOnly, rowHeight: spreadsheetRowHeightPx, onSectionRendered: onSectionRendered, onTableScroll: function (_scrollTop) { return setScrollTop(_scrollTop); }, h: spreadsheetHeight, rowWidth: rowWidth, data: unsubmittedData, columns: columns, isLoading: isLoading })] })))] }));
184
155
  };
185
156
  export { Spreadsheet };
186
- var templateObject_1, templateObject_2, templateObject_3;
157
+ var templateObject_1, templateObject_2;
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ import { SpreadsheetAutocompleteProps } from "../common/fields/SpeadsheetAutocomplete";
3
+ export declare const BooleanInput: React.FC<SpreadsheetAutocompleteProps>;
@@ -0,0 +1,18 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ import { SpreadsheetAutocomplete, } from "../common/fields/SpeadsheetAutocomplete";
14
+ var booleanOptions = [
15
+ { label: "True", value: true },
16
+ { label: "False", value: false },
17
+ ];
18
+ export var BooleanInput = function (props) { return (_jsx(SpreadsheetAutocomplete, __assign({ isInputDisabled: true }, props, { options: booleanOptions }))); };
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ import { SpreadsheetTextInputArgs } from "../common/fields/SpreadsheetInput";
3
+ export declare const EmailInput: React.FC<SpreadsheetTextInputArgs>;
@@ -0,0 +1,14 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ import { SpreadsheetInput, } from "../common/fields/SpreadsheetInput";
14
+ export var EmailInput = function (props) { return (_jsx(SpreadsheetInput, __assign({}, props, { type: "email" }))); };
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ import { SpreadsheetAutocompleteProps } from "../common/fields/SpeadsheetAutocomplete";
3
+ export declare type EnumInputProps = {
4
+ options: any;
5
+ } & SpreadsheetAutocompleteProps;
6
+ export declare const EnumInput: React.FC<EnumInputProps>;