@vuu-ui/vuu-table-extras 4.0.0-alpha.1 → 4.0.0-alpha.3
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/package.json +12 -12
- package/src/calculated-column/CalculatedColumnPanel.js +2 -2
- package/src/column-picker/ColumnModel.js +13 -25
- package/src/column-picker/ColumnPicker.css.js +0 -86
- package/src/column-picker/ColumnPicker.js +12 -180
- package/src/column-picker/useColumnPicker.js +28 -22
- package/src/csv-upload/CsvUpload.js +52 -32
- package/src/csv-upload/parse/csv-constants.js +2 -2
- package/src/csv-upload/parse/csv-errors.js +1 -0
- package/src/csv-upload/parse/csv-schema-validation.js +9 -0
- package/src/csv-upload/useCsvUpload.js +7 -5
- package/src/tabbed-table-config-panel/TabbedTableConfigPanel.js +17 -8
- package/src/tabbed-table-config-panel/useTabbedTableConfigPanel.js +1 -1
- package/types/calculated-column/CalculatedColumnPanel.d.ts +2 -2
- package/types/column-picker/ColumnModel.d.ts +4 -3
- package/types/column-picker/ColumnPicker.d.ts +4 -6
- package/types/column-picker/useColumnPicker.d.ts +7 -10
- package/types/column-settings-panel/useColumnSettings.d.ts +3 -3
- package/types/csv-upload/CsvUpload.d.ts +2 -1
- package/types/csv-upload/data-upload-preview/useDataUploadPreview.d.ts +1 -1
- package/types/csv-upload/index.d.ts +1 -1
- package/types/csv-upload/parse/csv-constants.d.ts +2 -2
- package/types/csv-upload/parse/csv-errors.d.ts +2 -1
- package/types/csv-upload/parse/csv-schema-validation.d.ts +2 -0
- package/types/csv-upload/parse/index.d.ts +1 -1
- package/types/csv-upload/useCsvUpload.d.ts +3 -2
- package/types/index.d.ts +0 -1
- package/types/src/csv-upload/CsvUpload.d.ts +2 -1
- package/types/src/csv-upload/index.d.ts +1 -1
- package/types/src/csv-upload/parse/csv-constants.d.ts +2 -2
- package/types/src/csv-upload/parse/csv-errors.d.ts +2 -1
- package/types/src/csv-upload/parse/csv-schema-validation.d.ts +2 -0
- package/types/src/csv-upload/parse/index.d.ts +1 -1
- package/types/src/csv-upload/useCsvUpload.d.ts +3 -2
- package/types/tabbed-table-config-panel/useTabbedTableConfigPanel.d.ts +4 -3
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "4.0.0-alpha.
|
|
2
|
+
"version": "4.0.0-alpha.3",
|
|
3
3
|
"author": "heswell",
|
|
4
4
|
"main": "./src/index.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
@@ -12,19 +12,19 @@
|
|
|
12
12
|
"lezer-generate:column": "lezer-generator --output ./src/column-expression-input/column-language-parser/generated/column-parser.ts ./src/column-expression-input/column-language-parser/grammar/column.grammar"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@vuu-ui/vuu-filter-types": "4.0.0-alpha.
|
|
16
|
-
"@vuu-ui/vuu-protocol-types": "4.0.0-alpha.
|
|
15
|
+
"@vuu-ui/vuu-filter-types": "4.0.0-alpha.3",
|
|
16
|
+
"@vuu-ui/vuu-protocol-types": "4.0.0-alpha.3"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@vuu-ui/vuu-codemirror": "4.0.0-alpha.
|
|
20
|
-
"@vuu-ui/vuu-data-editing": "4.0.0-alpha.
|
|
21
|
-
"@vuu-ui/vuu-data-react": "4.0.0-alpha.
|
|
22
|
-
"@vuu-ui/vuu-data-types": "4.0.0-alpha.
|
|
23
|
-
"@vuu-ui/vuu-table-types": "4.0.0-alpha.
|
|
24
|
-
"@vuu-ui/vuu-popups": "4.0.0-alpha.
|
|
25
|
-
"@vuu-ui/vuu-table": "4.0.0-alpha.
|
|
26
|
-
"@vuu-ui/vuu-utils": "4.0.0-alpha.
|
|
27
|
-
"@vuu-ui/vuu-ui-controls": "4.0.0-alpha.
|
|
19
|
+
"@vuu-ui/vuu-codemirror": "4.0.0-alpha.3",
|
|
20
|
+
"@vuu-ui/vuu-data-editing": "4.0.0-alpha.3",
|
|
21
|
+
"@vuu-ui/vuu-data-react": "4.0.0-alpha.3",
|
|
22
|
+
"@vuu-ui/vuu-data-types": "4.0.0-alpha.3",
|
|
23
|
+
"@vuu-ui/vuu-table-types": "4.0.0-alpha.3",
|
|
24
|
+
"@vuu-ui/vuu-popups": "4.0.0-alpha.3",
|
|
25
|
+
"@vuu-ui/vuu-table": "4.0.0-alpha.3",
|
|
26
|
+
"@vuu-ui/vuu-utils": "4.0.0-alpha.3",
|
|
27
|
+
"@vuu-ui/vuu-ui-controls": "4.0.0-alpha.3",
|
|
28
28
|
"@lezer/lr": "1.4.2",
|
|
29
29
|
"@salt-ds/core": "1.67.0",
|
|
30
30
|
"@salt-ds/lab": "1.0.0-alpha.99",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Dropdown, FormField, FormFieldLabel, Input, Option } from "@salt-ds/core";
|
|
3
|
-
import { useCalculatedColumnPanel } from "./useCalculatedColumnPanel.js";
|
|
4
|
-
import { useCallback, useRef } from "react";
|
|
5
3
|
import { getCalculatedColumnDetails } from "@vuu-ui/vuu-utils";
|
|
4
|
+
import { useCallback, useRef } from "react";
|
|
6
5
|
import { ColumnExpressionInput, useColumnExpressionSuggestionProvider } from "../column-expression-input/index.js";
|
|
6
|
+
import { useCalculatedColumnPanel } from "./useCalculatedColumnPanel.js";
|
|
7
7
|
const classBase = "vuuCalculatedColumnPanel";
|
|
8
8
|
const CalculatedColumnPanel = ({ column: columnProp, columnModel, onChangeColumn, onChangeServerDataType: onChangeServerDataTypeProp, vuuTable })=>{
|
|
9
9
|
const typeRef = useRef(null);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventEmitter, reorderItems } from "@vuu-ui/vuu-utils";
|
|
1
|
+
import { EventEmitter, getAddedItems, getRemovedItems, itemsOrOrderChanged, reorderItems } from "@vuu-ui/vuu-utils";
|
|
2
2
|
const ColumnChangeSource = {
|
|
3
3
|
ColumnPicker: "column-picker",
|
|
4
4
|
ColumnSettings: "column-settings",
|
|
@@ -15,37 +15,15 @@ const isColumnAdded = (change)=>change?.type === SelectedColumnChangeType.Column
|
|
|
15
15
|
const isColumnRemoved = (change)=>change?.type === SelectedColumnChangeType.ColumnRemoved;
|
|
16
16
|
const isColumnUpdated = (change)=>change?.type === SelectedColumnChangeType.ColumnUpdated;
|
|
17
17
|
const isColumnsReordered = (change)=>change?.type === SelectedColumnChangeType.ColumnsReordered;
|
|
18
|
-
const byColumnName = ({ name: n1, label: l1 = n1 }, { name: n2, label: l2 = n2 })=>l1 > l2 ? 1 : l2 > l1 ? -1 : 0;
|
|
19
|
-
const filterColumns = (columns, pattern)=>{
|
|
20
|
-
if (!pattern) return columns;
|
|
21
|
-
{
|
|
22
|
-
const lowerCasePattern = pattern.toLowerCase();
|
|
23
|
-
return columns.filter(({ name, label = name })=>-1 !== label.toLowerCase().indexOf(lowerCasePattern));
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
18
|
class ColumnModel extends EventEmitter {
|
|
27
19
|
allColumns;
|
|
28
|
-
#searchPattern = "";
|
|
29
20
|
#selectedColumns;
|
|
30
21
|
constructor(allColumns, selectedColumns){
|
|
31
22
|
super(), this.allColumns = allColumns;
|
|
32
23
|
this.#selectedColumns = selectedColumns;
|
|
33
24
|
}
|
|
34
|
-
get availableColumns() {
|
|
35
|
-
return filterColumns(this.allColumns, this.#searchPattern).filter(({ name })=>-1 === this.#selectedColumns.findIndex((c)=>c.name === name)).toSorted(byColumnName);
|
|
36
|
-
}
|
|
37
|
-
set searchPattern(pattern) {
|
|
38
|
-
const searchPattern = pattern;
|
|
39
|
-
if (searchPattern !== this.#searchPattern) {
|
|
40
|
-
this.#searchPattern = searchPattern;
|
|
41
|
-
this.emit("render", {});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
get searchPattern() {
|
|
45
|
-
return this.#searchPattern ?? "";
|
|
46
|
-
}
|
|
47
25
|
get selectedColumns() {
|
|
48
|
-
return
|
|
26
|
+
return this.#selectedColumns;
|
|
49
27
|
}
|
|
50
28
|
setSelectedColumns(selectedColumns, source, changeDescriptor) {
|
|
51
29
|
this.#selectedColumns = selectedColumns;
|
|
@@ -56,6 +34,16 @@ class ColumnModel extends EventEmitter {
|
|
|
56
34
|
if (col) return col;
|
|
57
35
|
throw Error(`[ColumnModel] columns does not contain column ${name}`);
|
|
58
36
|
}
|
|
37
|
+
addRemoveOrReorderSelectedColumns(newSelectedColumns, source) {
|
|
38
|
+
if (!itemsOrOrderChanged(this.#selectedColumns, newSelectedColumns)) throw Error("[ColumnModel] addRemoveOrReorderSelectedColumns no change detected between current and new selected columns");
|
|
39
|
+
const addedColumns = getAddedItems(this.#selectedColumns, newSelectedColumns);
|
|
40
|
+
if (addedColumns.length > 0) if (1 == addedColumns.length) return void this.addItemToSelectedColumns(addedColumns[0].name, source);
|
|
41
|
+
else throw Error("[ColumnModel] addRemoveOrReorderSelectedColumns attempt to add multiple selected columns in a single call");
|
|
42
|
+
const removedColumns = getRemovedItems(this.#selectedColumns, newSelectedColumns);
|
|
43
|
+
if (removedColumns.length > 0) if (1 == removedColumns.length) return void this.removeItemFromSelectedColumns(removedColumns[0].name, source);
|
|
44
|
+
else throw Error("[ColumnModel] addRemoveOrReorderSelectedColumns attempt to remove multiple selected columns in a single call");
|
|
45
|
+
this.reorderSelectedColumns(newSelectedColumns.map(({ name })=>name), source);
|
|
46
|
+
}
|
|
59
47
|
addItemToSelectedColumns(name, source) {
|
|
60
48
|
const column = this.allColumns.find((col)=>col.name === name);
|
|
61
49
|
if (column) {
|
|
@@ -97,7 +85,7 @@ class ColumnModel extends EventEmitter {
|
|
|
97
85
|
}
|
|
98
86
|
addColumn(column, addToSelectedColumns = false) {
|
|
99
87
|
console.log(`[ColumnModel] add column ${JSON.stringify(column)}`);
|
|
100
|
-
if (addToSelectedColumns) console.log("add it to selected
|
|
88
|
+
if (addToSelectedColumns) console.log("add it to selected columns");
|
|
101
89
|
this.allColumns = this.allColumns.concat(column);
|
|
102
90
|
this.#selectedColumns = this.#selectedColumns.concat(column);
|
|
103
91
|
this.notifyListeners(this.#selectedColumns, "column-picker", {
|
|
@@ -1,94 +1,8 @@
|
|
|
1
1
|
const css = `
|
|
2
2
|
.vuuColumnPicker {
|
|
3
|
-
--label-margin-left: 0px;
|
|
4
|
-
--columnpicker-background: var(--vuuColumnPicker-background, var(--salt-container-primary-background));
|
|
5
|
-
background: var(--columnpicker-background);
|
|
6
|
-
gap: var(--salt-spacing-300);
|
|
7
|
-
height: var(--vuuColumnPicker-height, 100%);
|
|
8
|
-
padding: var(--salt-spacing-300) 0;
|
|
9
|
-
flex-direction: column;
|
|
10
|
-
display: flex;
|
|
11
|
-
overflow: hidden;
|
|
12
|
-
container-type: inline-size;
|
|
13
|
-
|
|
14
3
|
&.vuuColumnPicker-withCalculated {
|
|
15
4
|
--label-margin-left: 8px;
|
|
16
5
|
}
|
|
17
|
-
|
|
18
|
-
& .saltListBox {
|
|
19
|
-
background-color: inherit;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
& .saltOption {
|
|
23
|
-
background-color: inherit;
|
|
24
|
-
border-bottom: var(--vuuColumnListItem-border, solid) 1px
|
|
25
|
-
var(--salt-separable-tertiary-borderColor);
|
|
26
|
-
align-items: center;
|
|
27
|
-
gap: var(--salt-spacing-200);
|
|
28
|
-
height: calc(var(--salt-size-base) + var(--salt-spacing-200));
|
|
29
|
-
|
|
30
|
-
& .vuuIcon {
|
|
31
|
-
--vuu-icon-color: var(--salt-content-secondary-foreground);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
& .vuuCalculatedColumnIcon {
|
|
35
|
-
--vuu-icon-color: var(--salt-content-secondary-foreground);
|
|
36
|
-
position: absolute;
|
|
37
|
-
top: 8px;
|
|
38
|
-
left: 32px;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
& .vuuHighlight {
|
|
42
|
-
color: var(--vuu-color-blue-40);
|
|
43
|
-
text-decoration: underline;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
& .vuuColumnPicker-text {
|
|
47
|
-
margin-left: var(--label-margin-left);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
& .vuuColumnPickerListItem-action {
|
|
52
|
-
visibility: hidden;
|
|
53
|
-
margin-left: auto;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
& .saltOption:hover {
|
|
57
|
-
& .vuuColumnPickerListItem-action {
|
|
58
|
-
visibility: visible;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
& .vuuColumnPicker-search {
|
|
63
|
-
--saltInput-paddingLeft: var(--salt-spacing-300);
|
|
64
|
-
padding: var(--salt-spacing-200) var(--salt-spacing-300) 0 var(--salt-spacing-300);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
& .vuuColumnPicker-scrollContainer {
|
|
68
|
-
flex: 1 1 0;
|
|
69
|
-
overflow: auto;
|
|
70
|
-
|
|
71
|
-
& .vuuColumnPicker-sectionHeader {
|
|
72
|
-
background: var(--columnpicker-background);
|
|
73
|
-
height: 32px;
|
|
74
|
-
padding: 0 var(--salt-spacing-300);
|
|
75
|
-
z-index: 1;
|
|
76
|
-
align-items: center;
|
|
77
|
-
display: flex;
|
|
78
|
-
position: sticky;
|
|
79
|
-
top: 0;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
& .vuuColumnPicker-availableHeader {
|
|
83
|
-
top: 32px;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
& .vuuColumnPicker-availableList {
|
|
87
|
-
& .saltOption {
|
|
88
|
-
padding-left: var(--salt-spacing-300);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
6
|
}
|
|
93
7
|
|
|
94
8
|
|
|
@@ -1,204 +1,36 @@
|
|
|
1
|
-
import { jsx
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useComponentCssInjection } from "@salt-ds/styles";
|
|
3
3
|
import { useWindow } from "@salt-ds/window";
|
|
4
|
-
import { DragDropProvider, getColumnLabel, isCalculatedColumn, useSortable } from "@vuu-ui/vuu-utils";
|
|
5
4
|
import clsx from "clsx";
|
|
6
|
-
import { forwardRef
|
|
7
|
-
import { Button, Input, ListBox, Option } from "@salt-ds/core";
|
|
8
|
-
import { applyHighlighting } from "@vuu-ui/vuu-table";
|
|
9
|
-
import { Icon, IconButton } from "@vuu-ui/vuu-ui-controls";
|
|
10
|
-
import { ColumnChangeSource } from "./ColumnModel.js";
|
|
5
|
+
import { forwardRef } from "react";
|
|
11
6
|
import { useColumnPicker } from "./useColumnPicker.js";
|
|
7
|
+
import { ItemPicker } from "@vuu-ui/vuu-ui-controls";
|
|
12
8
|
import ColumnPicker_0 from "./ColumnPicker.css";
|
|
13
9
|
const classBase = "vuuColumnPicker";
|
|
14
10
|
const classBaseListItem = "vuuColumnPickerListItem";
|
|
15
|
-
const searchIcon = /*#__PURE__*/ jsx("span", {
|
|
16
|
-
"data-icon": "search"
|
|
17
|
-
});
|
|
18
11
|
const NO_SELECTION = [];
|
|
19
|
-
const
|
|
20
|
-
const { handleRef: sortableHandleRef, ref: sortableRef } = useSortable({
|
|
21
|
-
id,
|
|
22
|
-
index
|
|
23
|
-
});
|
|
24
|
-
const [handleRef, ref] = useMemo(()=>[
|
|
25
|
-
sortableHandleRef,
|
|
26
|
-
sortableRef
|
|
27
|
-
], [
|
|
28
|
-
sortableHandleRef,
|
|
29
|
-
sortableRef
|
|
30
|
-
]);
|
|
31
|
-
return {
|
|
32
|
-
handleRef,
|
|
33
|
-
ref
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
const SelectedColumnListItem = ({ className: classNameProp, index, column, onRemove, searchPattern = "", ...optionProps })=>{
|
|
37
|
-
const { handleRef, ref } = useSorting(column.name, index);
|
|
38
|
-
const value = getColumnLabel(column);
|
|
39
|
-
const valueWithHighlighting = applyHighlighting(value, searchPattern);
|
|
40
|
-
const handleRemoveButtonClick = useCallback((e)=>{
|
|
41
|
-
e.stopPropagation();
|
|
42
|
-
onRemove?.(e);
|
|
43
|
-
}, [
|
|
44
|
-
onRemove
|
|
45
|
-
]);
|
|
46
|
-
return /*#__PURE__*/ jsxs(Option, {
|
|
47
|
-
...optionProps,
|
|
48
|
-
className: clsx(classNameProp, classBaseListItem),
|
|
49
|
-
"data-name": column.name,
|
|
50
|
-
ref: ref,
|
|
51
|
-
children: [
|
|
52
|
-
/*#__PURE__*/ jsx(IconButton, {
|
|
53
|
-
"data-embedded": true,
|
|
54
|
-
appearance: "transparent",
|
|
55
|
-
icon: "draggable",
|
|
56
|
-
ref: handleRef,
|
|
57
|
-
size: 16
|
|
58
|
-
}),
|
|
59
|
-
isCalculatedColumn(column.name) ? /*#__PURE__*/ jsx(Icon, {
|
|
60
|
-
className: "vuuCalculatedColumnIcon",
|
|
61
|
-
name: "function"
|
|
62
|
-
}) : null,
|
|
63
|
-
/*#__PURE__*/ jsx("span", {
|
|
64
|
-
className: `${classBase}-text`,
|
|
65
|
-
children: valueWithHighlighting
|
|
66
|
-
}),
|
|
67
|
-
/*#__PURE__*/ jsx(IconButton, {
|
|
68
|
-
className: `${classBaseListItem}-action`,
|
|
69
|
-
"data-embedded": true,
|
|
70
|
-
appearance: "transparent",
|
|
71
|
-
icon: "cross",
|
|
72
|
-
onClick: handleRemoveButtonClick,
|
|
73
|
-
size: 16
|
|
74
|
-
})
|
|
75
|
-
]
|
|
76
|
-
});
|
|
77
|
-
};
|
|
78
|
-
const AvailableColumnListItem = ({ className: classNameProp, index, column: item, onAdd, searchPattern = "", ...optionProps })=>{
|
|
79
|
-
const value = getColumnLabel(item);
|
|
80
|
-
const valueWithHighlighting = applyHighlighting(value, searchPattern);
|
|
81
|
-
return /*#__PURE__*/ jsxs(Option, {
|
|
82
|
-
...optionProps,
|
|
83
|
-
className: clsx(classNameProp, classBaseListItem),
|
|
84
|
-
"data-name": item.name,
|
|
85
|
-
children: [
|
|
86
|
-
/*#__PURE__*/ jsx("span", {
|
|
87
|
-
className: `${classBase}-text`,
|
|
88
|
-
children: valueWithHighlighting
|
|
89
|
-
}),
|
|
90
|
-
/*#__PURE__*/ jsx(IconButton, {
|
|
91
|
-
className: `${classBaseListItem}-action`,
|
|
92
|
-
"data-embedded": true,
|
|
93
|
-
appearance: "transparent",
|
|
94
|
-
icon: "plus",
|
|
95
|
-
onClick: onAdd,
|
|
96
|
-
size: 16
|
|
97
|
-
})
|
|
98
|
-
]
|
|
99
|
-
});
|
|
100
|
-
};
|
|
101
|
-
const ColumnPicker_ColumnPicker = /*#__PURE__*/ forwardRef(function({ allowCreateCalculatedColumn, columnModel, className, onClickCreateCalculatedColumn, onSelectionChange, selected = NO_SELECTION, ...htmlAttributes }, forwardedRef) {
|
|
12
|
+
const ColumnPicker_ColumnPicker = /*#__PURE__*/ forwardRef(function({ columnModel, className, onSelectionChange, selected = NO_SELECTION, ...htmlAttributes }, forwardedRef) {
|
|
102
13
|
const targetWindow = useWindow();
|
|
103
14
|
useComponentCssInjection({
|
|
104
15
|
testId: "vuu-column-picker",
|
|
105
16
|
css: ColumnPicker_0,
|
|
106
17
|
window: targetWindow
|
|
107
18
|
});
|
|
108
|
-
const
|
|
109
|
-
setTimeout(()=>{
|
|
110
|
-
el?.querySelector("input")?.focus();
|
|
111
|
-
}, 100);
|
|
112
|
-
}, []);
|
|
113
|
-
const { availableColumns, onAddItemToSelectedList, onChangeSearchInput, onRemoveItemFromSelectedList, searchText, selectedColumns } = useColumnPicker({
|
|
19
|
+
const { allItems, selectedItems, oneOrMoreColumnsIsCalculated, handleSelectedItemsChange } = useColumnPicker({
|
|
114
20
|
columnModel: columnModel
|
|
115
21
|
});
|
|
116
|
-
|
|
117
|
-
const getOptionName = (option)=>{
|
|
118
|
-
if (option) {
|
|
119
|
-
const { name } = option.dataset;
|
|
120
|
-
if (name) return name;
|
|
121
|
-
}
|
|
122
|
-
throw Error("[ColumnPicker] list option has no data-name");
|
|
123
|
-
};
|
|
124
|
-
const handleDragEnd = useCallback(()=>{
|
|
125
|
-
setTimeout(()=>{
|
|
126
|
-
const listItems = listRef.current?.querySelectorAll(".saltOption");
|
|
127
|
-
if (listItems) {
|
|
128
|
-
const orderedColumnNames = Array.from(listItems).map(getOptionName);
|
|
129
|
-
columnModel.reorderSelectedColumns(orderedColumnNames, ColumnChangeSource.ColumnPicker);
|
|
130
|
-
}
|
|
131
|
-
}, 300);
|
|
132
|
-
}, [
|
|
133
|
-
columnModel
|
|
134
|
-
]);
|
|
135
|
-
const oneOrMoreColumnsIsCalculated = selectedColumns.some((column)=>isCalculatedColumn(column.name));
|
|
136
|
-
return /*#__PURE__*/ jsxs("div", {
|
|
22
|
+
return /*#__PURE__*/ jsx(ItemPicker, {
|
|
137
23
|
...htmlAttributes,
|
|
138
24
|
className: clsx(classBase, className, {
|
|
139
25
|
[`${classBase}-withCalculated`]: oneOrMoreColumnsIsCalculated
|
|
140
26
|
}),
|
|
27
|
+
allItems: allItems,
|
|
28
|
+
selectedItems: selectedItems,
|
|
29
|
+
itemTypeName: "column",
|
|
30
|
+
onSelectedItemsChange: handleSelectedItemsChange,
|
|
31
|
+
onSelectionChange: onSelectionChange,
|
|
141
32
|
ref: forwardedRef,
|
|
142
|
-
|
|
143
|
-
/*#__PURE__*/ jsx("form", {
|
|
144
|
-
className: `${classBase}-search`,
|
|
145
|
-
role: "search",
|
|
146
|
-
children: /*#__PURE__*/ jsx(Input, {
|
|
147
|
-
startAdornment: searchIcon,
|
|
148
|
-
placeholder: "Find column",
|
|
149
|
-
ref: searchCallbackRef,
|
|
150
|
-
value: searchText,
|
|
151
|
-
onChange: onChangeSearchInput
|
|
152
|
-
})
|
|
153
|
-
}),
|
|
154
|
-
/*#__PURE__*/ jsxs("div", {
|
|
155
|
-
className: `${classBase}-scrollContainer vuuScrollable`,
|
|
156
|
-
children: [
|
|
157
|
-
/*#__PURE__*/ jsx("div", {
|
|
158
|
-
className: `${classBase}-sectionHeader`,
|
|
159
|
-
children: "Columns in view"
|
|
160
|
-
}),
|
|
161
|
-
/*#__PURE__*/ jsx(DragDropProvider, {
|
|
162
|
-
onDragEnd: handleDragEnd,
|
|
163
|
-
children: /*#__PURE__*/ jsx(ListBox, {
|
|
164
|
-
className: `${classBase}-selectedList`,
|
|
165
|
-
onSelectionChange: onSelectionChange,
|
|
166
|
-
ref: listRef,
|
|
167
|
-
selected: selected,
|
|
168
|
-
children: selectedColumns.map((column, index)=>/*#__PURE__*/ jsx(SelectedColumnListItem, {
|
|
169
|
-
column: column,
|
|
170
|
-
index: index,
|
|
171
|
-
onRemove: onRemoveItemFromSelectedList,
|
|
172
|
-
searchPattern: searchText.toLowerCase(),
|
|
173
|
-
value: column
|
|
174
|
-
}, column.name))
|
|
175
|
-
})
|
|
176
|
-
}),
|
|
177
|
-
/*#__PURE__*/ jsx("div", {
|
|
178
|
-
className: clsx(`${classBase}-sectionHeader`, `${classBase}-availableHeader`),
|
|
179
|
-
children: "Available columns"
|
|
180
|
-
}),
|
|
181
|
-
/*#__PURE__*/ jsx(ListBox, {
|
|
182
|
-
className: `${classBase}-availableList`,
|
|
183
|
-
selected: NO_SELECTION,
|
|
184
|
-
children: availableColumns.map((column, index)=>/*#__PURE__*/ jsx(AvailableColumnListItem, {
|
|
185
|
-
column: column,
|
|
186
|
-
index: index,
|
|
187
|
-
onAdd: onAddItemToSelectedList,
|
|
188
|
-
searchPattern: searchText.toLowerCase(),
|
|
189
|
-
value: column
|
|
190
|
-
}, column.name))
|
|
191
|
-
})
|
|
192
|
-
]
|
|
193
|
-
}),
|
|
194
|
-
allowCreateCalculatedColumn ? /*#__PURE__*/ jsx("div", {
|
|
195
|
-
className: `${classBase}-column-buttons`,
|
|
196
|
-
children: /*#__PURE__*/ jsx(Button, {
|
|
197
|
-
onClick: onClickCreateCalculatedColumn,
|
|
198
|
-
children: "Create calculated column"
|
|
199
|
-
})
|
|
200
|
-
}) : null
|
|
201
|
-
]
|
|
33
|
+
selected: selected
|
|
202
34
|
});
|
|
203
35
|
});
|
|
204
36
|
export { ColumnPicker_ColumnPicker as ColumnPicker, classBaseListItem };
|
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useCallback, useEffect, useState } from "react";
|
|
1
|
+
import { isCalculatedColumn } from "@vuu-ui/vuu-utils";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
3
3
|
import { ColumnChangeSource } from "./ColumnModel.js";
|
|
4
4
|
const SOURCE = ColumnChangeSource.ColumnPicker;
|
|
5
|
-
const columnName = (target)=>{
|
|
6
|
-
const listItem = queryClosest(target, ".saltOption", true);
|
|
7
|
-
const { name } = listItem.dataset;
|
|
8
|
-
if (name) return name;
|
|
9
|
-
throw Error("[useColumnPicker] column name could not be identified, data-name attribute not found");
|
|
10
|
-
};
|
|
11
5
|
const useColumnPicker = ({ columnModel: model })=>{
|
|
12
6
|
const [, forceRender] = useState({});
|
|
13
7
|
useEffect(()=>{
|
|
@@ -18,25 +12,37 @@ const useColumnPicker = ({ columnModel: model })=>{
|
|
|
18
12
|
}, [
|
|
19
13
|
model
|
|
20
14
|
]);
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
15
|
+
const allItems = useMemo(()=>{
|
|
16
|
+
const itemDescriptors = model.allColumns.map((column)=>({
|
|
17
|
+
name: column.name,
|
|
18
|
+
label: column.label,
|
|
19
|
+
icon: isCalculatedColumn(column.name) ? "vuuCalculatedColumnIcon" : void 0
|
|
20
|
+
}));
|
|
21
|
+
return itemDescriptors;
|
|
24
22
|
}, [
|
|
25
|
-
model
|
|
23
|
+
model.allColumns
|
|
26
24
|
]);
|
|
27
|
-
const
|
|
28
|
-
model
|
|
25
|
+
const selectedItems = useMemo(()=>{
|
|
26
|
+
const itemDescriptors = model.selectedColumns.map((column)=>allItems.find((item)=>item.name === column.name));
|
|
27
|
+
return itemDescriptors;
|
|
28
|
+
}, [
|
|
29
|
+
model.selectedColumns,
|
|
30
|
+
allItems
|
|
29
31
|
]);
|
|
30
|
-
const
|
|
31
|
-
model
|
|
32
|
+
const oneOrMoreColumnsIsCalculated = useMemo(()=>model.selectedColumns.some((column)=>isCalculatedColumn(column.name)), [
|
|
33
|
+
model.selectedColumns
|
|
34
|
+
]);
|
|
35
|
+
const handleSelectedItemsChange = useCallback((newSelectedItems)=>{
|
|
36
|
+
const newSelectedColumns = newSelectedItems.map((item)=>model.allColumns.find((column)=>column.name === item.name));
|
|
37
|
+
model.addRemoveOrReorderSelectedColumns(newSelectedColumns, SOURCE);
|
|
38
|
+
}, [
|
|
39
|
+
model.allColumns
|
|
32
40
|
]);
|
|
33
41
|
return {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
searchText: model.searchPattern,
|
|
39
|
-
selectedColumns: model.selectedColumns
|
|
42
|
+
allItems,
|
|
43
|
+
selectedItems,
|
|
44
|
+
oneOrMoreColumnsIsCalculated,
|
|
45
|
+
handleSelectedItemsChange
|
|
40
46
|
};
|
|
41
47
|
};
|
|
42
48
|
export { useColumnPicker };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Button, Dialog, DialogActions, DialogContent, DialogHeader, FileDropZone, FileDropZoneIcon, FileDropZoneTrigger } from "@salt-ds/core";
|
|
2
|
+
import { Button, Dialog, DialogActions, DialogContent, DialogHeader, FileDropZone, FileDropZoneIcon, FileDropZoneTrigger, Text } from "@salt-ds/core";
|
|
3
3
|
import { useComponentCssInjection } from "@salt-ds/styles";
|
|
4
4
|
import { useWindow } from "@salt-ds/window";
|
|
5
5
|
import { useCallback, useState } from "react";
|
|
@@ -18,6 +18,10 @@ const CsvUpload_CsvUpload = (props)=>{
|
|
|
18
18
|
window: targetWindow
|
|
19
19
|
});
|
|
20
20
|
const { canImport, cancelImport, isProcessingFile, isImporting, importData, onDrop, onTriggerChange, schema, validation, error } = useCsvUpload(props);
|
|
21
|
+
const fileErrors = validation?.errors.filter((e)=>e.column in validation.errorMap.fileErrors) ?? [];
|
|
22
|
+
const hasErrors = !!error || validation && validation.errors.length > 0;
|
|
23
|
+
const isUploaded = canImport || isImporting;
|
|
24
|
+
const status = hasErrors ? "error" : isUploaded ? "success" : void 0;
|
|
21
25
|
const handleCancel = useCallback(async ()=>{
|
|
22
26
|
await cancelImport();
|
|
23
27
|
if (!isControlledOpen) setInternalOpen(false);
|
|
@@ -36,38 +40,55 @@ const CsvUpload_CsvUpload = (props)=>{
|
|
|
36
40
|
const content = /*#__PURE__*/ jsxs("div", {
|
|
37
41
|
className: classBase,
|
|
38
42
|
children: [
|
|
39
|
-
/*#__PURE__*/
|
|
43
|
+
/*#__PURE__*/ jsx(FileDropZone, {
|
|
40
44
|
className: `${classBase}-dropZone`,
|
|
41
45
|
disabled: void 0 === schema || isProcessingFile || isImporting,
|
|
42
46
|
onDrop: onDrop,
|
|
43
|
-
status:
|
|
44
|
-
children:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
47
|
+
status: status,
|
|
48
|
+
children: isUploaded ? /*#__PURE__*/ jsxs(Fragment, {
|
|
49
|
+
children: [
|
|
50
|
+
/*#__PURE__*/ jsx(FileDropZoneIcon, {
|
|
51
|
+
status: "success"
|
|
52
|
+
}),
|
|
53
|
+
/*#__PURE__*/ jsx("strong", {
|
|
54
|
+
children: "Upload completed"
|
|
55
|
+
})
|
|
56
|
+
]
|
|
57
|
+
}) : /*#__PURE__*/ jsxs(Fragment, {
|
|
58
|
+
children: [
|
|
59
|
+
/*#__PURE__*/ jsx(FileDropZoneIcon, {
|
|
60
|
+
status: hasErrors ? "error" : void 0
|
|
61
|
+
}),
|
|
62
|
+
validation && validation.errors.length > 0 ? /*#__PURE__*/ jsxs(Fragment, {
|
|
63
|
+
children: [
|
|
64
|
+
/*#__PURE__*/ jsx("div", {
|
|
65
|
+
children: "Your file contains errors"
|
|
66
|
+
}),
|
|
67
|
+
fileErrors.length > 0 && /*#__PURE__*/ jsx("ul", {
|
|
68
|
+
className: `${classBase}-errorList`,
|
|
69
|
+
children: fileErrors.map((error, i)=>/*#__PURE__*/ jsx("li", {
|
|
70
|
+
className: `${classBase}-errorItem`,
|
|
71
|
+
children: error.message
|
|
72
|
+
}, `${error.column}-${error.message}-${i}`))
|
|
73
|
+
}),
|
|
74
|
+
/*#__PURE__*/ jsx("div", {
|
|
75
|
+
children: "Please rectify and reupload"
|
|
76
|
+
})
|
|
77
|
+
]
|
|
78
|
+
}) : /*#__PURE__*/ jsx("div", {
|
|
79
|
+
children: "Drop a file here or"
|
|
80
|
+
}),
|
|
81
|
+
/*#__PURE__*/ jsx(FileDropZoneTrigger, {
|
|
82
|
+
accept: ".csv,text/csv",
|
|
83
|
+
onChange: onTriggerChange,
|
|
84
|
+
children: "BROWSE FILES"
|
|
85
|
+
}),
|
|
86
|
+
/*#__PURE__*/ jsx(Text, {
|
|
87
|
+
children: "Only .csv files"
|
|
88
|
+
}),
|
|
89
|
+
children
|
|
90
|
+
]
|
|
91
|
+
})
|
|
71
92
|
}),
|
|
72
93
|
error && (renderError ? renderError(error) : /*#__PURE__*/ jsxs("div", {
|
|
73
94
|
className: `${classBase}-errors`,
|
|
@@ -81,8 +102,7 @@ const CsvUpload_CsvUpload = (props)=>{
|
|
|
81
102
|
children: error.errors.importError?.message || error.errors.schemaError?.message || error.errors.validationError?.message || "An unexpected error occurred during import."
|
|
82
103
|
})
|
|
83
104
|
]
|
|
84
|
-
}))
|
|
85
|
-
children
|
|
105
|
+
}))
|
|
86
106
|
]
|
|
87
107
|
});
|
|
88
108
|
const actions = /*#__PURE__*/ jsxs(DialogActions, {
|
|
@@ -15,6 +15,7 @@ var csv_errors_CsvValidationErrorEnum = /*#__PURE__*/ function(CsvValidationErro
|
|
|
15
15
|
CsvValidationErrorEnum["MAX_ROWS_EXCEEDED"] = "MAX_ROWS_EXCEEDED";
|
|
16
16
|
CsvValidationErrorEnum["EMPTY_NON_STRING_VALUE"] = "EMPTY_NON_STRING_VALUE";
|
|
17
17
|
CsvValidationErrorEnum["TYPE_MISMATCH"] = "TYPE_MISMATCH";
|
|
18
|
+
CsvValidationErrorEnum["CUSTOM_VALIDATION"] = "CUSTOM_VALIDATION";
|
|
18
19
|
return CsvValidationErrorEnum;
|
|
19
20
|
}({});
|
|
20
21
|
const createCsvErrorState = ()=>({
|
|
@@ -20,6 +20,10 @@ const validateCsvAgainstSchema = (parsed, tableSchema, options)=>{
|
|
|
20
20
|
parsed.rows.forEach((rowValues, rowIndex)=>{
|
|
21
21
|
const rowNum = rowIndex + CSV_FIRST_DATA_ROW_NUMBER;
|
|
22
22
|
const typedRow = {};
|
|
23
|
+
const rawRow = parsed.header.reduce((acc, headerCol, idx)=>{
|
|
24
|
+
acc[headerCol] = rowValues[idx];
|
|
25
|
+
return acc;
|
|
26
|
+
}, {});
|
|
23
27
|
parsed.header.forEach((columnName, columnIndex)=>{
|
|
24
28
|
const rawValue = rowValues[columnIndex];
|
|
25
29
|
const schemaType = schemaColumns.get(columnName);
|
|
@@ -33,6 +37,11 @@ const validateCsvAgainstSchema = (parsed, tableSchema, options)=>{
|
|
|
33
37
|
return;
|
|
34
38
|
}
|
|
35
39
|
if (void 0 === value) return void addCsvRowError(errorState, rowNum, columnName, CsvValidationErrorEnum.TYPE_MISMATCH, `Value '${rawValue}' is not a valid ${toType}`, rawValue);
|
|
40
|
+
const customValidator = options?.validators?.[columnName];
|
|
41
|
+
if (customValidator) {
|
|
42
|
+
const validationResult = customValidator(rawValue, columnName, rawRow);
|
|
43
|
+
if (true !== validationResult) return void addCsvRowError(errorState, rowNum, columnName, CsvValidationErrorEnum.CUSTOM_VALIDATION, "string" == typeof validationResult ? validationResult : `Value '${rawValue}' failed custom validation.`, rawValue);
|
|
44
|
+
}
|
|
36
45
|
typedRow[columnName] = value;
|
|
37
46
|
});
|
|
38
47
|
typedRows.push(typedRow);
|
|
@@ -5,7 +5,7 @@ import { parseCsv } from "./parse/csv-parse.js";
|
|
|
5
5
|
import { validateCsvAgainstSchema } from "./parse/csv-schema-validation.js";
|
|
6
6
|
import { buildRowErrorMessage, createUploadError, hasFileParseErrors, isCsvParseError, mergeValidationWithParseErrors, toErrorMessage } from "./parse/csv-upload-utils.js";
|
|
7
7
|
import { CSV_FIRST_DATA_ROW_NUMBER } from "./parse/csv-constants.js";
|
|
8
|
-
const useCsvUpload = ({ dataSource, importMode = "direct", importSchema, importTable, onImportSessionEnded, onImportSessionStarted, onError, onImported, onPreview, onProcessingStarted, maxRows, parseOptions, rowDefaults })=>{
|
|
8
|
+
const useCsvUpload = ({ dataSource, importMode = "direct", importSchema, importTable, onImportSessionEnded, onImportSessionStarted, onError, onImported, onPreview, onProcessingStarted, maxRows, parseOptions, rowDefaults, validators })=>{
|
|
9
9
|
const { getServerAPI } = useData();
|
|
10
10
|
const [validation, setValidation] = useState();
|
|
11
11
|
const [sessionTable, setSessionTable] = useState();
|
|
@@ -140,7 +140,7 @@ const useCsvUpload = ({ dataSource, importMode = "direct", importSchema, importT
|
|
|
140
140
|
if (rowNum < CSV_FIRST_DATA_ROW_NUMBER) continue;
|
|
141
141
|
const existing = vuuMsgByRow.get(rowNum);
|
|
142
142
|
const columnError = `${column}: ${message}`;
|
|
143
|
-
vuuMsgByRow.set(rowNum, existing ? `${existing}; ${columnError}` : `Row ${rowNum}: ${columnError}`);
|
|
143
|
+
vuuMsgByRow.set(rowNum, existing ? `${existing}; ${columnError}` : `${0 === rowNum ? "Header" : `Row ${rowNum}`}: ${columnError}`);
|
|
144
144
|
}
|
|
145
145
|
const parsedRowCount = mergedValidation.rows.length;
|
|
146
146
|
const unparsedErrorRows = [
|
|
@@ -174,7 +174,7 @@ const useCsvUpload = ({ dataSource, importMode = "direct", importSchema, importT
|
|
|
174
174
|
if (isRpcError(result)) throw Error(result.errorMessage);
|
|
175
175
|
if ("string" == typeof result) throw Error(result);
|
|
176
176
|
} catch (error) {
|
|
177
|
-
rpcErrors.push(`Row ${rowNum}: ${toErrorMessage(error)}`);
|
|
177
|
+
rpcErrors.push(`${0 === rowNum ? "Header" : `Row ${rowNum}`}: ${toErrorMessage(error)}`);
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
if (rpcErrors.length > 0) throw Error(buildRowErrorMessage("Import failed", rpcErrors));
|
|
@@ -240,7 +240,8 @@ const useCsvUpload = ({ dataSource, importMode = "direct", importSchema, importT
|
|
|
240
240
|
return;
|
|
241
241
|
}
|
|
242
242
|
const schemaValidation = validateCsvAgainstSchema(parsedCsv, schema, {
|
|
243
|
-
maxRows
|
|
243
|
+
maxRows,
|
|
244
|
+
validators
|
|
244
245
|
});
|
|
245
246
|
if (Object.keys(schemaValidation.errorMap.fileErrors).length > 0) {
|
|
246
247
|
setValidation(schemaValidation);
|
|
@@ -288,7 +289,8 @@ const useCsvUpload = ({ dataSource, importMode = "direct", importSchema, importT
|
|
|
288
289
|
dataSource.table,
|
|
289
290
|
table,
|
|
290
291
|
endEditSessionAndNotify,
|
|
291
|
-
schema
|
|
292
|
+
schema,
|
|
293
|
+
validators
|
|
292
294
|
]);
|
|
293
295
|
const handleFiles = useCallback(async (files)=>{
|
|
294
296
|
const file = files[0];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Tab, TabBar, TabList, TabPanel, TabTrigger, Tabs } from "@salt-ds/core";
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, Tab, TabBar, TabList, TabPanel, TabTrigger, Tabs } from "@salt-ds/core";
|
|
3
3
|
import { useComponentCssInjection } from "@salt-ds/styles";
|
|
4
4
|
import { useWindow } from "@salt-ds/window";
|
|
5
5
|
import clsx from "clsx";
|
|
@@ -78,12 +78,21 @@ const TabbedTableConfigPanel_TabbedTableConfigPanel = ({ allowCreateCalculatedCo
|
|
|
78
78
|
}),
|
|
79
79
|
/*#__PURE__*/ jsx(TabPanel, {
|
|
80
80
|
value: "table-columns",
|
|
81
|
-
children: /*#__PURE__*/
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
81
|
+
children: /*#__PURE__*/ jsxs(Fragment, {
|
|
82
|
+
children: [
|
|
83
|
+
/*#__PURE__*/ jsx(ColumnPicker, {
|
|
84
|
+
columnModel: columnModel,
|
|
85
|
+
onSelectionChange: handleSelectionChange,
|
|
86
|
+
selected: columns
|
|
87
|
+
}),
|
|
88
|
+
allowCreateCalculatedColumn ? /*#__PURE__*/ jsx("div", {
|
|
89
|
+
className: `${classBase}-column-buttons`,
|
|
90
|
+
children: /*#__PURE__*/ jsx(Button, {
|
|
91
|
+
onClick: onCreateCalculatedColumn,
|
|
92
|
+
children: "Create calculated column"
|
|
93
|
+
})
|
|
94
|
+
}) : null
|
|
95
|
+
]
|
|
87
96
|
})
|
|
88
97
|
}),
|
|
89
98
|
/*#__PURE__*/ jsx(TabPanel, {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useRef } from "react";
|
|
3
2
|
import { useContextPanel } from "@vuu-ui/vuu-ui-controls";
|
|
3
|
+
import { useCallback, useRef } from "react";
|
|
4
4
|
import { TabbedTableConfigPanel } from "./TabbedTableConfigPanel.js";
|
|
5
5
|
const useTabbedTableConfigPanel = ({ allowCreateCalculatedColumn, columnModel, config, onDisplayAttributeChange, vuuTable })=>{
|
|
6
6
|
const showContextPanel = useContextPanel();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { HTMLAttributes } from "react";
|
|
2
|
-
import { ColumnDescriptor } from "@vuu-ui/vuu-table-types";
|
|
3
1
|
import { VuuColumnDataType, VuuTable } from "@vuu-ui/vuu-protocol-types";
|
|
2
|
+
import { ColumnDescriptor } from "@vuu-ui/vuu-table-types";
|
|
3
|
+
import { HTMLAttributes } from "react";
|
|
4
4
|
import { ColumnModel } from "../column-picker/ColumnModel";
|
|
5
5
|
export interface CalculatedColumnPanelProps extends HTMLAttributes<HTMLDivElement> {
|
|
6
6
|
column: ColumnDescriptor;
|
|
@@ -58,12 +58,13 @@ export declare class ColumnModel extends EventEmitter<ColumnEvents> {
|
|
|
58
58
|
* Columns already selected and rendered in Table.
|
|
59
59
|
*/
|
|
60
60
|
selectedColumns: readonly ColumnDescriptor[]);
|
|
61
|
-
get availableColumns(): ColumnDescriptor[];
|
|
62
|
-
set searchPattern(pattern: string);
|
|
63
|
-
get searchPattern(): string;
|
|
64
61
|
get selectedColumns(): readonly ColumnDescriptor[];
|
|
65
62
|
setSelectedColumns(selectedColumns: readonly ColumnDescriptor[], source: ColumnChangeSource, changeDescriptor?: SelectedColumnChangeDescriptor): void;
|
|
66
63
|
getColumn(name: string): ColumnDescriptor;
|
|
64
|
+
/**
|
|
65
|
+
* Introduced for use by ColumnPicker
|
|
66
|
+
*/
|
|
67
|
+
addRemoveOrReorderSelectedColumns(newSelectedColumns: readonly ColumnDescriptor[], source: ColumnChangeSource): void;
|
|
67
68
|
addItemToSelectedColumns(name: string, source: ColumnChangeSource): void;
|
|
68
69
|
removeItemFromSelectedColumns(name: string, source: ColumnChangeSource): void;
|
|
69
70
|
reorderSelectedColumns(orderedColumnNames: string[], source: ColumnChangeSource): void;
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { ColumnPickerHookProps } from "./useColumnPicker";
|
|
1
|
+
import type { ListBoxProps } from "@salt-ds/core";
|
|
2
|
+
import type { ColumnDescriptor } from "@vuu-ui/vuu-table-types";
|
|
3
|
+
import { type HTMLAttributes } from "react";
|
|
4
|
+
import { type ColumnPickerHookProps } from "./useColumnPicker";
|
|
5
5
|
export declare const classBaseListItem = "vuuColumnPickerListItem";
|
|
6
6
|
export interface ColumnPickerProps extends ColumnPickerHookProps, Pick<ListBoxProps<ColumnDescriptor>, "selected" | "onSelectionChange">, HTMLAttributes<HTMLDivElement> {
|
|
7
|
-
allowCreateCalculatedColumn?: boolean;
|
|
8
|
-
onClickCreateCalculatedColumn?: MouseEventHandler<HTMLButtonElement>;
|
|
9
7
|
}
|
|
10
8
|
export declare const ColumnPicker: import("react").ForwardRefExoticComponent<ColumnPickerProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { ColumnModel
|
|
1
|
+
import { TableSelectionModel } from "@vuu-ui/vuu-table-types";
|
|
2
|
+
import { ItemDescriptor } from "@vuu-ui/vuu-ui-controls";
|
|
3
|
+
import { ColumnModel } from "./ColumnModel";
|
|
4
4
|
export type ColumnSelectionModel = Extract<TableSelectionModel, "none" | "single">;
|
|
5
|
-
export type SelectedColumnsChangeHandler = (columns: ColumnDescriptor[], changeType: SelectedColumnChangeType) => void;
|
|
6
5
|
export interface ColumnPickerHookProps {
|
|
7
6
|
columnModel: ColumnModel;
|
|
8
7
|
}
|
|
9
8
|
export declare const useColumnPicker: ({ columnModel: model, }: ColumnPickerHookProps) => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
searchText: string;
|
|
15
|
-
selectedColumns: readonly ColumnDescriptor[];
|
|
9
|
+
allItems: ItemDescriptor[];
|
|
10
|
+
selectedItems: ItemDescriptor[];
|
|
11
|
+
oneOrMoreColumnsIsCalculated: boolean;
|
|
12
|
+
handleSelectedItemsChange: (newSelectedItems: readonly ItemDescriptor[]) => void;
|
|
16
13
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { ColumnDescriptor,
|
|
2
|
-
import {
|
|
1
|
+
import { ColumnDescriptor, ColumnTypeFormatting, TableConfig } from "@vuu-ui/vuu-table-types";
|
|
2
|
+
import { DataValueTypeSimple } from "@vuu-ui/vuu-data-types";
|
|
3
3
|
import { VuuColumnDataType, VuuTable } from "@vuu-ui/vuu-protocol-types";
|
|
4
|
+
import { CellRendererDescriptor, ColumnRenderPropsChangeHandler } from "@vuu-ui/vuu-utils";
|
|
4
5
|
import { FormEventHandler } from "react";
|
|
5
|
-
import { DataValueTypeSimple } from "@vuu-ui/vuu-data-types";
|
|
6
6
|
import { ColumnModel } from "../column-picker/ColumnModel";
|
|
7
7
|
/**
|
|
8
8
|
* Describes the props for a Column Configuration Editor, for which
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import type { RowDefaultDataItemValues, EditSession } from "@vuu-ui/vuu-data-editing";
|
|
3
3
|
import type { CsvParseError, CsvParseOptions } from "./parse/csv-parse";
|
|
4
|
-
import type { CsvValidationStructuredError } from "./parse/csv-schema-validation";
|
|
4
|
+
import type { CsvValidationStructuredError, CsvColumnValidator } from "./parse/csv-schema-validation";
|
|
5
5
|
import type { DataSource, TableSchema } from "@vuu-ui/vuu-data-types";
|
|
6
6
|
import type { VuuTable } from "@vuu-ui/vuu-protocol-types";
|
|
7
7
|
import type { CsvUploadTableData } from "./parse/csv-upload-utils";
|
|
@@ -60,6 +60,7 @@ export interface CsvUploadProps {
|
|
|
60
60
|
parseOptions?: CsvParseOptions;
|
|
61
61
|
importMode?: "direct" | "preview";
|
|
62
62
|
rowDefaults?: RowDefaultDataItemValues;
|
|
63
|
+
validators?: Record<string, CsvColumnValidator>;
|
|
63
64
|
/**
|
|
64
65
|
* Custom renderer for the error panel.
|
|
65
66
|
*/
|
|
@@ -11,7 +11,7 @@ export declare const useDataUploadPreview: ({ dataSource, editSession, onClose,
|
|
|
11
11
|
canSave: boolean;
|
|
12
12
|
hasSelection: boolean;
|
|
13
13
|
onCancel: () => Promise<void>;
|
|
14
|
-
onDelete: () => Promise<
|
|
14
|
+
onDelete: () => Promise<import("@vuu-ui/vuu-protocol-types").RpcResult>;
|
|
15
15
|
onSave: (force?: boolean) => Promise<void>;
|
|
16
16
|
sessionError: string | undefined;
|
|
17
17
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { CsvUpload, type CsvUploadError, type CsvUploadProps, type CsvUploadErrorResult, type CsvUploadErrors, type CsvUploadPhase, type CsvUploadImportedResult, type CsvUploadPreviewResult, type CsvUploadSessionEndReason, type CsvUploadSessionEndResult, type CsvUploadSessionTable, } from "./CsvUpload";
|
|
2
2
|
export { useCsvUpload, type CsvUploadHookProps, type UseCsvUploadReturn, } from "./useCsvUpload";
|
|
3
3
|
export { DataUploadPreview, type DataUploadPreviewProps, } from "./data-upload-preview/DataUploadPreview";
|
|
4
|
-
export { validateCsvAgainstSchema, type CsvValidationOptions, type CsvValidationResult, } from "./parse/csv-schema-validation";
|
|
4
|
+
export { validateCsvAgainstSchema, type CsvColumnValidator, type CsvValidationOptions, type CsvValidationResult, } from "./parse/csv-schema-validation";
|
|
5
5
|
export { parseCsv, type CsvParseOptions, type CsvParseResult, } from "./parse/csv-parse";
|
|
6
6
|
export { CsvValidationErrorEnum, CsvParseErrorEnum, type CsvError, type CsvErrorMap, type CsvStructuredError, type CsvValidationError, type CsvValidationErrorMap, type CsvValidationErrorType, type CsvValidationStructuredError, type CsvParseError, type CsvParseErrorMap, } from "./parse/csv-errors";
|
|
7
7
|
export { CSV_FIRST_DATA_ROW_NUMBER, CSV_HEADER_ROW_NUMBER, } from "./parse/csv-constants";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare const CSV_HEADER_ROW_NUMBER =
|
|
2
|
-
export declare const CSV_FIRST_DATA_ROW_NUMBER =
|
|
1
|
+
export declare const CSV_HEADER_ROW_NUMBER = 0;
|
|
2
|
+
export declare const CSV_FIRST_DATA_ROW_NUMBER = 1;
|
|
3
3
|
export declare const MAX_ROWS_IN_CSV = 10000;
|
|
@@ -12,7 +12,8 @@ export declare enum CsvValidationErrorEnum {
|
|
|
12
12
|
UNKNOWN_COLUMN = "UNKNOWN_COLUMN",
|
|
13
13
|
MAX_ROWS_EXCEEDED = "MAX_ROWS_EXCEEDED",
|
|
14
14
|
EMPTY_NON_STRING_VALUE = "EMPTY_NON_STRING_VALUE",
|
|
15
|
-
TYPE_MISMATCH = "TYPE_MISMATCH"
|
|
15
|
+
TYPE_MISMATCH = "TYPE_MISMATCH",
|
|
16
|
+
CUSTOM_VALIDATION = "CUSTOM_VALIDATION"
|
|
16
17
|
}
|
|
17
18
|
export type CsvErrorMap<TError extends string> = {
|
|
18
19
|
rowErrors: Record<number, Record<string, TError[]>>;
|
|
@@ -3,6 +3,7 @@ import type { VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
|
|
|
3
3
|
import type { CsvValidationError, CsvValidationErrorMap, CsvParseError } from "./csv-errors";
|
|
4
4
|
import type { CsvParseResult } from "./csv-parse";
|
|
5
5
|
export { CsvValidationErrorEnum, type CsvValidationError, type CsvValidationErrorMap, type CsvValidationErrorType, type CsvValidationStructuredError, } from "./csv-errors";
|
|
6
|
+
export type CsvColumnValidator = (value: string, columnName: string, row: Record<string, string>) => boolean | string;
|
|
6
7
|
export type CsvValidationResult = {
|
|
7
8
|
columns: string[];
|
|
8
9
|
errorMap: CsvValidationErrorMap;
|
|
@@ -12,5 +13,6 @@ export type CsvValidationResult = {
|
|
|
12
13
|
};
|
|
13
14
|
export type CsvValidationOptions = {
|
|
14
15
|
maxRows?: number;
|
|
16
|
+
validators?: Record<string, CsvColumnValidator>;
|
|
15
17
|
};
|
|
16
18
|
export declare const validateCsvAgainstSchema: (parsed: CsvParseResult, tableSchema: TableSchema, options?: CsvValidationOptions) => CsvValidationResult;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { CSV_FIRST_DATA_ROW_NUMBER, CSV_HEADER_ROW_NUMBER, } from "./csv-constants";
|
|
2
2
|
export { CsvParseErrorEnum, CsvValidationErrorEnum, type CsvError, type CsvErrorMap, type CsvErrorState, type CsvParseError, type CsvParseErrorMap, type CsvStructuredError, type CsvValidationError, type CsvValidationErrorMap, type CsvValidationErrorType, type CsvValidationStructuredError, addCsvFileError, addCsvRowError, createCsvErrorState, hasCsvErrors, } from "./csv-errors";
|
|
3
3
|
export { parseCsv, type CsvParseOptions, type CsvParseResult, } from "./csv-parse";
|
|
4
|
-
export { validateCsvAgainstSchema, type CsvValidationOptions, type CsvValidationResult, } from "./csv-schema-validation";
|
|
4
|
+
export { validateCsvAgainstSchema, type CsvColumnValidator, type CsvValidationOptions, type CsvValidationResult, } from "./csv-schema-validation";
|
|
5
5
|
export { buildRowErrorMessage, executeBatchRpcCalls, hasFileParseErrors, isCsvParseError, mergeValidationWithParseErrors, normalizeTableData, toErrorMessage, toValidationErrorsFromParseRowErrors, type CsvUploadTableData, type RpcBatchResult, } from "./csv-upload-utils";
|
|
@@ -2,7 +2,7 @@ import type { DataSource, TableSchema } from "@vuu-ui/vuu-data-types";
|
|
|
2
2
|
import { type RowDefaultDataItemValues } from "@vuu-ui/vuu-data-editing";
|
|
3
3
|
import type { VuuTable } from "@vuu-ui/vuu-protocol-types";
|
|
4
4
|
import { type CsvParseOptions } from "./parse/csv-parse";
|
|
5
|
-
import { type CsvValidationResult } from "./parse/csv-schema-validation";
|
|
5
|
+
import { type CsvValidationResult, type CsvColumnValidator } from "./parse/csv-schema-validation";
|
|
6
6
|
import type { CsvUploadErrorResult, CsvUploadImportedResult, CsvUploadPreviewResult, CsvUploadSessionEndResult, CsvUploadSessionTable } from "./CsvUpload";
|
|
7
7
|
export interface CsvUploadHookProps {
|
|
8
8
|
dataSource: DataSource;
|
|
@@ -25,6 +25,7 @@ export interface CsvUploadHookProps {
|
|
|
25
25
|
parseOptions?: CsvParseOptions;
|
|
26
26
|
/** Default column values applied to every addRow call. Pass a stable reference — a new object triggers EditSession recreation. */
|
|
27
27
|
rowDefaults?: RowDefaultDataItemValues;
|
|
28
|
+
validators?: Record<string, CsvColumnValidator>;
|
|
28
29
|
}
|
|
29
30
|
export type UseCsvUploadReturn = {
|
|
30
31
|
canImport: boolean;
|
|
@@ -39,4 +40,4 @@ export type UseCsvUploadReturn = {
|
|
|
39
40
|
validation: CsvValidationResult | undefined;
|
|
40
41
|
error: CsvUploadErrorResult | undefined;
|
|
41
42
|
};
|
|
42
|
-
export declare const useCsvUpload: ({ dataSource, importMode, importSchema, importTable, onImportSessionEnded, onImportSessionStarted, onError, onImported, onPreview, onProcessingStarted, maxRows, parseOptions, rowDefaults, }: CsvUploadHookProps) => UseCsvUploadReturn;
|
|
43
|
+
export declare const useCsvUpload: ({ dataSource, importMode, importSchema, importTable, onImportSessionEnded, onImportSessionStarted, onError, onImported, onPreview, onProcessingStarted, maxRows, parseOptions, rowDefaults, validators, }: CsvUploadHookProps) => UseCsvUploadReturn;
|
package/types/index.d.ts
CHANGED
|
@@ -11,7 +11,6 @@ export { useColumnActions } from "./column-menu/useColumnActions";
|
|
|
11
11
|
export { ColumnChangeSource, ColumnModel, isColumnAdded, isColumnRemoved, isColumnsReordered, SelectedColumnChangeType, type ColumnEvents, type ColumnsChangeHandler, } from "./column-picker/ColumnModel";
|
|
12
12
|
export { ColumnPicker, type ColumnPickerProps, } from "./column-picker/ColumnPicker";
|
|
13
13
|
export { ColumnPickerAction } from "./column-picker/ColumnPickerAction";
|
|
14
|
-
export type { SelectedColumnsChangeHandler } from "./column-picker/useColumnPicker";
|
|
15
14
|
export { useTableColumnPicker } from "./column-picker/useTableColumnPicker";
|
|
16
15
|
export { ColumnSettingsPanel } from "./column-settings-panel/ColumnSettingsPanel";
|
|
17
16
|
export { useColumnSettings } from "./column-settings-panel/useColumnSettings";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import type { RowDefaultDataItemValues, EditSession } from "@vuu-ui/vuu-data-editing";
|
|
3
3
|
import type { CsvParseError, CsvParseOptions } from "./parse/csv-parse";
|
|
4
|
-
import type { CsvValidationStructuredError } from "./parse/csv-schema-validation";
|
|
4
|
+
import type { CsvValidationStructuredError, CsvColumnValidator } from "./parse/csv-schema-validation";
|
|
5
5
|
import type { DataSource, TableSchema } from "@vuu-ui/vuu-data-types";
|
|
6
6
|
import type { VuuTable } from "@vuu-ui/vuu-protocol-types";
|
|
7
7
|
import type { CsvUploadTableData } from "./parse/csv-upload-utils";
|
|
@@ -60,6 +60,7 @@ export interface CsvUploadProps {
|
|
|
60
60
|
parseOptions?: CsvParseOptions;
|
|
61
61
|
importMode?: "direct" | "preview";
|
|
62
62
|
rowDefaults?: RowDefaultDataItemValues;
|
|
63
|
+
validators?: Record<string, CsvColumnValidator>;
|
|
63
64
|
/**
|
|
64
65
|
* Custom renderer for the error panel.
|
|
65
66
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { CsvUpload, type CsvUploadError, type CsvUploadProps, type CsvUploadErrorResult, type CsvUploadErrors, type CsvUploadPhase, type CsvUploadImportedResult, type CsvUploadPreviewResult, type CsvUploadSessionEndReason, type CsvUploadSessionEndResult, type CsvUploadSessionTable, } from "./CsvUpload";
|
|
2
2
|
export { useCsvUpload, type CsvUploadHookProps, type UseCsvUploadReturn, } from "./useCsvUpload";
|
|
3
3
|
export { DataUploadPreview, type DataUploadPreviewProps, } from "./data-upload-preview/DataUploadPreview";
|
|
4
|
-
export { validateCsvAgainstSchema, type CsvValidationOptions, type CsvValidationResult, } from "./parse/csv-schema-validation";
|
|
4
|
+
export { validateCsvAgainstSchema, type CsvColumnValidator, type CsvValidationOptions, type CsvValidationResult, } from "./parse/csv-schema-validation";
|
|
5
5
|
export { parseCsv, type CsvParseOptions, type CsvParseResult, } from "./parse/csv-parse";
|
|
6
6
|
export { CsvValidationErrorEnum, CsvParseErrorEnum, type CsvError, type CsvErrorMap, type CsvStructuredError, type CsvValidationError, type CsvValidationErrorMap, type CsvValidationErrorType, type CsvValidationStructuredError, type CsvParseError, type CsvParseErrorMap, } from "./parse/csv-errors";
|
|
7
7
|
export { CSV_FIRST_DATA_ROW_NUMBER, CSV_HEADER_ROW_NUMBER, } from "./parse/csv-constants";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare const CSV_HEADER_ROW_NUMBER =
|
|
2
|
-
export declare const CSV_FIRST_DATA_ROW_NUMBER =
|
|
1
|
+
export declare const CSV_HEADER_ROW_NUMBER = 0;
|
|
2
|
+
export declare const CSV_FIRST_DATA_ROW_NUMBER = 1;
|
|
3
3
|
export declare const MAX_ROWS_IN_CSV = 10000;
|
|
@@ -12,7 +12,8 @@ export declare enum CsvValidationErrorEnum {
|
|
|
12
12
|
UNKNOWN_COLUMN = "UNKNOWN_COLUMN",
|
|
13
13
|
MAX_ROWS_EXCEEDED = "MAX_ROWS_EXCEEDED",
|
|
14
14
|
EMPTY_NON_STRING_VALUE = "EMPTY_NON_STRING_VALUE",
|
|
15
|
-
TYPE_MISMATCH = "TYPE_MISMATCH"
|
|
15
|
+
TYPE_MISMATCH = "TYPE_MISMATCH",
|
|
16
|
+
CUSTOM_VALIDATION = "CUSTOM_VALIDATION"
|
|
16
17
|
}
|
|
17
18
|
export type CsvErrorMap<TError extends string> = {
|
|
18
19
|
rowErrors: Record<number, Record<string, TError[]>>;
|
|
@@ -3,6 +3,7 @@ import type { VuuRowDataItemType } from "@vuu-ui/vuu-protocol-types";
|
|
|
3
3
|
import type { CsvValidationError, CsvValidationErrorMap, CsvParseError } from "./csv-errors";
|
|
4
4
|
import type { CsvParseResult } from "./csv-parse";
|
|
5
5
|
export { CsvValidationErrorEnum, type CsvValidationError, type CsvValidationErrorMap, type CsvValidationErrorType, type CsvValidationStructuredError, } from "./csv-errors";
|
|
6
|
+
export type CsvColumnValidator = (value: string, columnName: string, row: Record<string, string>) => boolean | string;
|
|
6
7
|
export type CsvValidationResult = {
|
|
7
8
|
columns: string[];
|
|
8
9
|
errorMap: CsvValidationErrorMap;
|
|
@@ -12,5 +13,6 @@ export type CsvValidationResult = {
|
|
|
12
13
|
};
|
|
13
14
|
export type CsvValidationOptions = {
|
|
14
15
|
maxRows?: number;
|
|
16
|
+
validators?: Record<string, CsvColumnValidator>;
|
|
15
17
|
};
|
|
16
18
|
export declare const validateCsvAgainstSchema: (parsed: CsvParseResult, tableSchema: TableSchema, options?: CsvValidationOptions) => CsvValidationResult;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { CSV_FIRST_DATA_ROW_NUMBER, CSV_HEADER_ROW_NUMBER, } from "./csv-constants";
|
|
2
2
|
export { CsvParseErrorEnum, CsvValidationErrorEnum, type CsvError, type CsvErrorMap, type CsvErrorState, type CsvParseError, type CsvParseErrorMap, type CsvStructuredError, type CsvValidationError, type CsvValidationErrorMap, type CsvValidationErrorType, type CsvValidationStructuredError, addCsvFileError, addCsvRowError, createCsvErrorState, hasCsvErrors, } from "./csv-errors";
|
|
3
3
|
export { parseCsv, type CsvParseOptions, type CsvParseResult, } from "./csv-parse";
|
|
4
|
-
export { validateCsvAgainstSchema, type CsvValidationOptions, type CsvValidationResult, } from "./csv-schema-validation";
|
|
4
|
+
export { validateCsvAgainstSchema, type CsvColumnValidator, type CsvValidationOptions, type CsvValidationResult, } from "./csv-schema-validation";
|
|
5
5
|
export { buildRowErrorMessage, executeBatchRpcCalls, hasFileParseErrors, isCsvParseError, mergeValidationWithParseErrors, normalizeTableData, toErrorMessage, toValidationErrorsFromParseRowErrors, type CsvUploadTableData, type RpcBatchResult, } from "./csv-upload-utils";
|
|
@@ -2,7 +2,7 @@ import type { DataSource, TableSchema } from "@vuu-ui/vuu-data-types";
|
|
|
2
2
|
import { type RowDefaultDataItemValues } from "@vuu-ui/vuu-data-editing";
|
|
3
3
|
import type { VuuTable } from "@vuu-ui/vuu-protocol-types";
|
|
4
4
|
import { type CsvParseOptions } from "./parse/csv-parse";
|
|
5
|
-
import { type CsvValidationResult } from "./parse/csv-schema-validation";
|
|
5
|
+
import { type CsvValidationResult, type CsvColumnValidator } from "./parse/csv-schema-validation";
|
|
6
6
|
import type { CsvUploadErrorResult, CsvUploadImportedResult, CsvUploadPreviewResult, CsvUploadSessionEndResult, CsvUploadSessionTable } from "./CsvUpload";
|
|
7
7
|
export interface CsvUploadHookProps {
|
|
8
8
|
dataSource: DataSource;
|
|
@@ -25,6 +25,7 @@ export interface CsvUploadHookProps {
|
|
|
25
25
|
parseOptions?: CsvParseOptions;
|
|
26
26
|
/** Default column values applied to every addRow call. Pass a stable reference — a new object triggers EditSession recreation. */
|
|
27
27
|
rowDefaults?: RowDefaultDataItemValues;
|
|
28
|
+
validators?: Record<string, CsvColumnValidator>;
|
|
28
29
|
}
|
|
29
30
|
export type UseCsvUploadReturn = {
|
|
30
31
|
canImport: boolean;
|
|
@@ -39,4 +40,4 @@ export type UseCsvUploadReturn = {
|
|
|
39
40
|
validation: CsvValidationResult | undefined;
|
|
40
41
|
error: CsvUploadErrorResult | undefined;
|
|
41
42
|
};
|
|
42
|
-
export declare const useCsvUpload: ({ dataSource, importMode, importSchema, importTable, onImportSessionEnded, onImportSessionStarted, onError, onImported, onPreview, onProcessingStarted, maxRows, parseOptions, rowDefaults, }: CsvUploadHookProps) => UseCsvUploadReturn;
|
|
43
|
+
export declare const useCsvUpload: ({ dataSource, importMode, importSchema, importTable, onImportSessionEnded, onImportSessionStarted, onError, onImported, onPreview, onProcessingStarted, maxRows, parseOptions, rowDefaults, validators, }: CsvUploadHookProps) => UseCsvUploadReturn;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { VuuTable } from "@vuu-ui/vuu-protocol-types";
|
|
2
2
|
import { TableProps } from "@vuu-ui/vuu-table";
|
|
3
3
|
import { ColumnPickerProps } from "../column-picker/ColumnPicker";
|
|
4
|
-
import {
|
|
5
|
-
export interface TabbedTableConfigPanelHookProps extends Pick<ColumnPickerProps, "
|
|
4
|
+
import { TableSettingsPanelProps } from "../table-settings-panel/TableSettingsPanel";
|
|
5
|
+
export interface TabbedTableConfigPanelHookProps extends Pick<ColumnPickerProps, "columnModel">, Pick<TableSettingsPanelProps, "onDisplayAttributeChange">, Pick<TableProps, "config"> {
|
|
6
6
|
/**
|
|
7
7
|
* only required for calculated columns
|
|
8
8
|
*/
|
|
9
9
|
vuuTable?: VuuTable;
|
|
10
|
+
allowCreateCalculatedColumn?: boolean;
|
|
10
11
|
}
|
|
11
12
|
export declare const useTabbedTableConfigPanel: ({ allowCreateCalculatedColumn, columnModel, config, onDisplayAttributeChange, vuuTable, }: TabbedTableConfigPanelHookProps) => {
|
|
12
13
|
showTabbedTableConfigPanel: (title?: string) => void;
|