synapse-react-client 4.0.18 → 4.0.19
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/dist/SWC.index.d.ts +2 -0
- package/dist/SWC.index.d.ts.map +1 -1
- package/dist/SWC.index.js +3 -1
- package/dist/SWC.index.js.map +1 -1
- package/dist/components/DataExplorer/DataExplorer.css +1 -0
- package/dist/components/DataExplorer/DataExplorer.d.ts +13 -0
- package/dist/components/DataExplorer/DataExplorer.d.ts.map +1 -0
- package/dist/components/DataExplorer/DataExplorer.js +119 -0
- package/dist/components/DataExplorer/DataExplorer.js.map +1 -0
- package/dist/components/DataExplorer/DataExplorer.module.js +22 -0
- package/dist/components/DataExplorer/DataExplorer.module.js.map +1 -0
- package/dist/components/DataExplorer/DataExplorer.module.scss +156 -0
- package/dist/components/DataGrid/columns/AutocompleteColumn.d.ts.map +1 -1
- package/dist/components/DataGrid/columns/AutocompleteColumn.js +106 -102
- package/dist/components/DataGrid/columns/AutocompleteColumn.js.map +1 -1
- package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.d.ts.map +1 -1
- package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.js +97 -89
- package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.js.map +1 -1
- package/dist/components/DataGrid/columns/useGridAutocompleteState.d.ts +19 -8
- package/dist/components/DataGrid/columns/useGridAutocompleteState.d.ts.map +1 -1
- package/dist/components/DataGrid/columns/useGridAutocompleteState.js +64 -43
- package/dist/components/DataGrid/columns/useGridAutocompleteState.js.map +1 -1
- package/dist/components/DataGrid/components/UploadCsvToGridDialog.d.ts.map +1 -1
- package/dist/components/DataGrid/components/UploadCsvToGridDialog.js +9 -9
- package/dist/components/DataGrid/components/UploadCsvToGridDialog.js.map +1 -1
- package/dist/components/DataGrid/hooks/useGetSchemaForGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/hooks/useGetSchemaForGrid.js +8 -1
- package/dist/components/DataGrid/hooks/useGetSchemaForGrid.js.map +1 -1
- package/dist/components/QueryVisualizationWrapper/QueryVisualizationWrapper.d.ts.map +1 -1
- package/dist/components/QueryVisualizationWrapper/QueryVisualizationWrapper.js +67 -65
- package/dist/components/QueryVisualizationWrapper/QueryVisualizationWrapper.js.map +1 -1
- package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.d.ts +1 -1
- package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.d.ts.map +1 -1
- package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.js +1 -0
- package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.js.map +1 -1
- package/dist/components/SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav.d.ts +1 -1
- package/dist/components/SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav.d.ts.map +1 -1
- package/dist/components/SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav.js +1 -0
- package/dist/components/SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav.js.map +1 -1
- package/dist/components/StandaloneQueryWrapper/StandaloneQueryWrapper.d.ts +1 -1
- package/dist/components/StandaloneQueryWrapper/StandaloneQueryWrapper.d.ts.map +1 -1
- package/dist/components/StandaloneQueryWrapper/StandaloneQueryWrapper.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/ColumnModelForm.js +9 -9
- package/dist/components/TableColumnSchemaEditor/ColumnModelFormFields/MultiValueField.js +4 -4
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaForm.js +25 -25
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaForm.js.map +1 -1
- package/dist/components/table/CsvPreview/CreateTableFromCsvDialog.d.ts +18 -0
- package/dist/components/table/CsvPreview/CreateTableFromCsvDialog.d.ts.map +1 -0
- package/dist/components/table/CsvPreview/CreateTableFromCsvDialog.js +116 -0
- package/dist/components/table/CsvPreview/CreateTableFromCsvDialog.js.map +1 -0
- package/dist/components/table/CsvPreview/CsvPreviewDialog.d.ts +5 -5
- package/dist/components/table/CsvPreview/CsvPreviewDialog.d.ts.map +1 -1
- package/dist/components/table/CsvPreview/CsvPreviewDialog.js +27 -76
- package/dist/components/table/CsvPreview/CsvPreviewDialog.js.map +1 -1
- package/dist/components/table/CsvPreview/CsvPreviewWithOptions.d.ts +19 -0
- package/dist/components/table/CsvPreview/CsvPreviewWithOptions.d.ts.map +1 -0
- package/dist/components/table/CsvPreview/CsvPreviewWithOptions.js +41 -0
- package/dist/components/table/CsvPreview/CsvPreviewWithOptions.js.map +1 -0
- package/dist/components/table/CsvPreview/CsvUploadPreviewContent.d.ts +12 -0
- package/dist/components/table/CsvPreview/CsvUploadPreviewContent.d.ts.map +1 -0
- package/dist/components/table/CsvPreview/CsvUploadPreviewContent.js +25 -0
- package/dist/components/table/CsvPreview/CsvUploadPreviewContent.js.map +1 -0
- package/dist/components/table/CsvPreview/UpdateTableWithCsvDialog.d.ts +18 -0
- package/dist/components/table/CsvPreview/UpdateTableWithCsvDialog.d.ts.map +1 -0
- package/dist/components/table/CsvPreview/UpdateTableWithCsvDialog.js +55 -0
- package/dist/components/table/CsvPreview/UpdateTableWithCsvDialog.js.map +1 -0
- package/dist/components/table/CsvPreview/useCreateTableFromCsv.d.ts +19 -0
- package/dist/components/table/CsvPreview/useCreateTableFromCsv.d.ts.map +1 -0
- package/dist/components/table/CsvPreview/useCreateTableFromCsv.js +35 -0
- package/dist/components/table/CsvPreview/useCreateTableFromCsv.js.map +1 -0
- package/dist/components/table/CsvPreview/useCsvUploadPreview.d.ts +22 -0
- package/dist/components/table/CsvPreview/useCsvUploadPreview.d.ts.map +1 -0
- package/dist/components/table/CsvPreview/useCsvUploadPreview.js +32 -0
- package/dist/components/table/CsvPreview/useCsvUploadPreview.js.map +1 -0
- package/dist/components/table/CsvPreview/useUploadCsvToExistingTable.d.ts +14 -0
- package/dist/components/table/CsvPreview/useUploadCsvToExistingTable.d.ts.map +1 -0
- package/dist/components/table/CsvPreview/useUploadCsvToExistingTable.js +23 -0
- package/dist/components/table/CsvPreview/useUploadCsvToExistingTable.js.map +1 -0
- package/dist/features/entity/metadata-task/components/CreateOrUpdateCurationTaskDialog.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/components/CreateOrUpdateCurationTaskDialog.js +67 -67
- package/dist/features/entity/metadata-task/components/CreateOrUpdateCurationTaskDialog.js.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksPage.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksPage.js +37 -34
- package/dist/features/entity/metadata-task/components/MetadataTasksPage.js.map +1 -1
- package/dist/features/entity/metadata-task/utils/constants.d.ts +6 -3
- package/dist/features/entity/metadata-task/utils/constants.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/utils/constants.js +2 -2
- package/dist/features/entity/metadata-task/utils/constants.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/featureflag/FeatureFlags.d.ts +2 -1
- package/dist/utils/featureflag/FeatureFlags.d.ts.map +1 -1
- package/dist/utils/featureflag/FeatureFlags.js +1 -1
- package/dist/utils/featureflag/FeatureFlags.js.map +1 -1
- package/package.json +4 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { formatDate as e } from "../../../utils/functions/DateFormatter.js";
|
|
2
|
-
import
|
|
3
|
-
import n from "
|
|
2
|
+
import t from "../../JSONArrayEditor/JSONArrayEditorModal.js";
|
|
3
|
+
import { getJsonSchemaItemDefinitionForColumnType as n } from "../TableColumnSchemaEditorUtils.js";
|
|
4
4
|
import { useMemo as r, useState as i } from "react";
|
|
5
5
|
import { TextField as a } from "@mui/material";
|
|
6
6
|
import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
@@ -8,8 +8,8 @@ import { ColumnTypeEnum as l } from "@sage-bionetworks/synapse-types";
|
|
|
8
8
|
import u from "dayjs";
|
|
9
9
|
//#region src/components/TableColumnSchemaEditor/ColumnModelFormFields/MultiValueField.tsx
|
|
10
10
|
function d(d) {
|
|
11
|
-
let { columnType: f, onChange: p, value: m = [], TextFieldProps: h } = d, [g, _] = i(!1), v = r(() =>
|
|
12
|
-
return /* @__PURE__ */ c(o, { children: [/* @__PURE__ */ s(
|
|
11
|
+
let { columnType: f, onChange: p, value: m = [], TextFieldProps: h } = d, [g, _] = i(!1), v = r(() => n(f), [f]), y = r(() => m == null ? "" : f === l.DATE_LIST ? m.map((t) => e(u(t))).join(", ") : m.join(", "), [m, f]);
|
|
12
|
+
return /* @__PURE__ */ c(o, { children: [/* @__PURE__ */ s(t, {
|
|
13
13
|
arrayItemDefinition: v,
|
|
14
14
|
value: m ?? void 0,
|
|
15
15
|
isShowingModal: g,
|
|
@@ -6,12 +6,12 @@ import i from "../../assets/icons/AddToList.js";
|
|
|
6
6
|
import { useGetAnnotationColumnModels as a, useGetDefaultColumnModels as o } from "../../synapse-queries/table/useColumnModel.js";
|
|
7
7
|
import { findMatchingColumnModel as s, getAllowedColumnTypes as c, transformColumnModelsToFormData as l } from "./TableColumnSchemaEditorUtils.js";
|
|
8
8
|
import { tableColumnSchemaFormDataAtom as u } from "./TableColumnSchemaFormReducer.js";
|
|
9
|
-
import d from "./
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
12
|
-
import m from "./
|
|
13
|
-
import { forwardRef as h, useCallback as g, useEffect as
|
|
14
|
-
import { groupBy as
|
|
9
|
+
import d from "./ColumnModelForm.js";
|
|
10
|
+
import f from "./ImportTableColumnsButton.js";
|
|
11
|
+
import { TableColumnSchemaFormActions as p } from "./TableColumnSchemaFormActions.js";
|
|
12
|
+
import { validateColumnModelFormData as m } from "./Validators/ColumnModelValidator.js";
|
|
13
|
+
import { forwardRef as h, useCallback as g, useEffect as ee, useImperativeHandle as _, useMemo as v, useState as y } from "react";
|
|
14
|
+
import { groupBy as b, isEqual as x, noop as S, omit as C, times as te } from "lodash-es";
|
|
15
15
|
import { Box as w, Button as T, styled as E } from "@mui/material";
|
|
16
16
|
import { Fragment as D, jsx as O, jsxs as k } from "react/jsx-runtime";
|
|
17
17
|
import { ColumnTypeEnum as A, VIEW_CONCRETE_TYPE_VALUES as ne } from "@sage-bionetworks/synapse-types";
|
|
@@ -36,25 +36,25 @@ var R = "18px 18px 1.75fr 1.75fr 0.75fr 1fr 1.25fr 1.25fr 1fr 1.25fr", z = /* @_
|
|
|
36
36
|
borderBottomLeftRadius: "5px"
|
|
37
37
|
}) }), V = E(w, { label: "ColumnHeader" })({ fontWeight: 700 }), H = "Add All Annotations";
|
|
38
38
|
function U(i, s) {
|
|
39
|
-
let { initialData:
|
|
39
|
+
let { initialData: d, entityType: h, viewScope: x, onSubmit: E = S, isSubmitting: D = !1, originalColumnModels: A } = i, j = M(v(() => re((e) => e(u).length), [])), I = N(u), [z, B] = y(null), H = L(g((e) => e(u), [])), U = t(h), W = ne.includes(U), G = W, K = W, { data: q, isLoading: J } = o(x?.viewEntityType, x?.viewTypeMask, {
|
|
40
40
|
enabled: K,
|
|
41
41
|
staleTime: Infinity
|
|
42
42
|
}), Y = a({
|
|
43
|
-
viewScope:
|
|
43
|
+
viewScope: x,
|
|
44
44
|
includeDerivedAnnotations: !0,
|
|
45
45
|
concreteType: "org.sagebionetworks.repo.model.table.ViewColumnModelRequest"
|
|
46
46
|
}, { enabled: G }), { data: X, isLoading: Z } = Y;
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
ee(() => {
|
|
48
|
+
d && !J && I({
|
|
49
49
|
type: "setValue",
|
|
50
|
-
value: l(
|
|
50
|
+
value: l(d, q ?? [])
|
|
51
51
|
});
|
|
52
52
|
}, [J]);
|
|
53
53
|
let Q = g(() => {
|
|
54
|
-
let e =
|
|
54
|
+
let e = m(H());
|
|
55
55
|
return e.success ? B(null) : B(e.error), e;
|
|
56
56
|
}, [H]);
|
|
57
|
-
|
|
57
|
+
_(s, () => ({
|
|
58
58
|
submit() {
|
|
59
59
|
let e = Q();
|
|
60
60
|
e.success && E(e.data);
|
|
@@ -70,7 +70,7 @@ function U(i, s) {
|
|
|
70
70
|
}), [E, Q]);
|
|
71
71
|
let $ = g((t) => {
|
|
72
72
|
let n = H(), r = t.filter((e) => c(W, !1).includes(e.columnType) ? !n.find((t) => t.name === e.name) : !1);
|
|
73
|
-
r = r.map((e) =>
|
|
73
|
+
r = r.map((e) => C(e, ["id"])), r.length > 0 ? (I({
|
|
74
74
|
type: "setValue",
|
|
75
75
|
value: [...n, ...l(r, q)]
|
|
76
76
|
}), e(`${r.length} ${F("column", r.length)} added to schema.`, "success")) : e("No columns added. All columns to add are present in the column schema.", "info");
|
|
@@ -83,12 +83,12 @@ function U(i, s) {
|
|
|
83
83
|
q && $(q);
|
|
84
84
|
}, [q, $]), oe = g(() => {
|
|
85
85
|
X && $(X);
|
|
86
|
-
}, [X, $]), se =
|
|
86
|
+
}, [X, $]), se = v(() => z ? b(z.errors, (e) => e.path[0]) : {}, [z]);
|
|
87
87
|
return /* @__PURE__ */ k(w, {
|
|
88
88
|
component: "form",
|
|
89
89
|
sx: { py: 2.5 },
|
|
90
90
|
children: [
|
|
91
|
-
/* @__PURE__ */ O(
|
|
91
|
+
/* @__PURE__ */ O(p, {
|
|
92
92
|
disabled: D,
|
|
93
93
|
annotationColumnModelsQuery: Y
|
|
94
94
|
}),
|
|
@@ -164,7 +164,7 @@ function U(i, s) {
|
|
|
164
164
|
},
|
|
165
165
|
children: "Add All Annotations"
|
|
166
166
|
}),
|
|
167
|
-
/* @__PURE__ */ O(
|
|
167
|
+
/* @__PURE__ */ O(f, {
|
|
168
168
|
onAddColumns: (e) => {
|
|
169
169
|
$(e);
|
|
170
170
|
},
|
|
@@ -176,20 +176,20 @@ function U(i, s) {
|
|
|
176
176
|
});
|
|
177
177
|
}
|
|
178
178
|
function ie(e) {
|
|
179
|
-
let { columnModelIndex: t, entityType: n, disabled: r, columnModelValidationErrors: a = null, annotationColumnModels: o, originalColumnModels: c } = e, l = N(u),
|
|
180
|
-
if (!
|
|
181
|
-
let g =
|
|
179
|
+
let { columnModelIndex: t, entityType: n, disabled: r, columnModelValidationErrors: a = null, annotationColumnModels: o, originalColumnModels: c } = e, l = N(u), f = M(v(() => I(u, (e) => e[t], x), [t])), p = c ? s(c, f) : void 0, m = o ? s(o, f) : void 0, h = v(() => a ? b(a.filter((e) => e.path[0] === t && e.path[1] == "jsonSubColumns"), (e) => e.path[2]) : {}, [t, a]);
|
|
180
|
+
if (!f) return /* @__PURE__ */ O(D, {});
|
|
181
|
+
let g = f.isOriginallyDefaultColumn;
|
|
182
182
|
return /* @__PURE__ */ k(D, { children: [
|
|
183
|
-
/* @__PURE__ */ O(
|
|
183
|
+
/* @__PURE__ */ O(d, {
|
|
184
184
|
entityType: n,
|
|
185
185
|
columnModelIndex: t,
|
|
186
186
|
isDefaultColumn: g,
|
|
187
187
|
disabled: r,
|
|
188
188
|
validationErrors: a,
|
|
189
|
-
defaultAnnotationModel:
|
|
190
|
-
originalColumnModel:
|
|
189
|
+
defaultAnnotationModel: m,
|
|
190
|
+
originalColumnModel: p
|
|
191
191
|
}),
|
|
192
|
-
|
|
192
|
+
f.columnType === A.JSON && f.jsonSubColumns && f.jsonSubColumns.map((e, i) => /* @__PURE__ */ O(d, {
|
|
193
193
|
entityType: n,
|
|
194
194
|
columnModelIndex: t,
|
|
195
195
|
jsonSubColumnIndex: i,
|
|
@@ -197,7 +197,7 @@ function ie(e) {
|
|
|
197
197
|
disabled: r,
|
|
198
198
|
validationErrors: h[i]
|
|
199
199
|
}, i)),
|
|
200
|
-
|
|
200
|
+
f.columnType === A.JSON && /* @__PURE__ */ k(D, { children: [/* @__PURE__ */ O(w, {
|
|
201
201
|
sx: { gridColumn: "1 / span 2" },
|
|
202
202
|
children: B
|
|
203
203
|
}), /* @__PURE__ */ O(w, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableColumnSchemaForm.js","names":[],"sources":["../../../src/components/TableColumnSchemaEditor/TableColumnSchemaForm.tsx"],"sourcesContent":["import AddToList from '@/assets/icons/AddToList'\nimport {\n useGetAnnotationColumnModels,\n useGetDefaultColumnModels,\n} from '@/synapse-queries/table/useColumnModel'\nimport {\n convertToConcreteEntityType,\n entityTypeToFriendlyName,\n} from '@/utils/functions/EntityTypeUtils'\nimport { AddCircleTwoTone } from '@mui/icons-material'\nimport { Box, Button, styled } from '@mui/material'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport {\n ColumnModel,\n ColumnTypeEnum,\n VIEW_CONCRETE_TYPE_VALUES,\n ViewScope,\n} from '@sage-bionetworks/synapse-types'\nimport { atom, Provider, useAtomValue, useSetAtom } from 'jotai'\nimport { selectAtom, useAtomCallback } from 'jotai/utils'\nimport { groupBy, isEqual, noop, omit, times } from 'lodash-es'\nimport pluralize from 'pluralize'\nimport {\n ForwardedRef,\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useState,\n} from 'react'\nimport { SetOptional } from 'type-fest'\nimport { ZodError, ZodIssue } from 'zod'\nimport { SynapseSpinner } from '../LoadingScreen/LoadingScreen'\nimport { displayToast } from '../ToastMessage'\nimport ColumnModelForm from './ColumnModelForm'\nimport ImportTableColumnsButton from './ImportTableColumnsButton'\nimport {\n findMatchingColumnModel,\n getAllowedColumnTypes,\n transformColumnModelsToFormData,\n} from './TableColumnSchemaEditorUtils'\nimport { TableColumnSchemaFormActions } from './TableColumnSchemaFormActions'\nimport { tableColumnSchemaFormDataAtom } from './TableColumnSchemaFormReducer'\nimport { validateColumnModelFormData } from './Validators/ColumnModelValidator'\n\nconst COLUMN_SCHEMA_FORM_GRID_TEMPLATE_COLUMNS =\n '18px 18px 1.75fr 1.75fr 0.75fr 1fr 1.25fr 1.25fr 1fr 1.25fr'\nconst GRID_CONTAINER_Y_MARGIN_PX = 6\nexport const HIERARCHY_VERTICAL_LINE_COMPONENT = (\n <Box\n sx={{\n width: '1px',\n height: `calc(100% + 2 * ${GRID_CONTAINER_Y_MARGIN_PX}px)`,\n backgroundColor: 'grey.400',\n marginLeft: '8px',\n }}\n />\n)\nexport const HIERARCHY_END_COMPONENT = (\n <Box\n sx={theme => ({\n width: '50%',\n height: '60%',\n borderLeft: `1px solid ${theme.palette.grey[400]}`,\n borderBottom: `1px solid ${theme.palette.grey[400]}`,\n marginLeft: '8px',\n marginBottom: 'auto',\n marginRight: '0',\n borderBottomLeftRadius: '5px',\n })}\n />\n)\n\nexport type SubmitHandle = {\n // Allow the parent component to trigger a submit of the form, so this may be embedded in an arbitrary modal.\n submit: () => void\n // Imperative handle to get the data out of the form for SWC compatibility\n getEditedColumnModels: () => SetOptional<ColumnModel, 'id'>[]\n // Used to check if all form data is valid. Returns the current validity state\n validate: () => boolean\n}\n\ntype TableColumnSchemaFormProps = {\n /* The type of the Table, which determines various schema restrictions and form functionality */\n entityType: EntityType\n /* If this is an entity view, the ViewScope can be used to determine the default column models and fetch annotation column models */\n viewScope?: ViewScope\n initialData?: SetOptional<ColumnModel, 'id'>[]\n onSubmit?: (newColumnModels: SetOptional<ColumnModel, 'id'>[]) => void\n isSubmitting?: boolean\n /** The original/current column models that are applied to the table, if they exist. */\n originalColumnModels?: ColumnModel[]\n}\n\nconst ColumnHeader = styled(Box, {\n label: 'ColumnHeader',\n})({\n fontWeight: 700,\n})\n\nexport const ADD_ALL_ANNOTATIONS_BUTTON_TEXT = 'Add All Annotations'\n\nfunction TableColumnSchemaFormInternal(\n props: TableColumnSchemaFormProps,\n ref: ForwardedRef<SubmitHandle>,\n) {\n const {\n initialData,\n entityType,\n viewScope,\n onSubmit = noop,\n isSubmitting = false,\n originalColumnModels,\n } = props\n\n const numColumnModels = useAtomValue(\n useMemo(() => atom(get => get(tableColumnSchemaFormDataAtom).length), []),\n )\n\n const dispatch = useSetAtom(tableColumnSchemaFormDataAtom)\n const [validationErrors, setValidationErrors] = useState<ZodError | null>(\n null,\n )\n\n // useAtomCallback will let us imperatively read the form data, instead of tracking it in state and triggering a full re-render of the form when any data changes\n const readFormData = useAtomCallback(\n useCallback(get => {\n return get(tableColumnSchemaFormDataAtom)\n }, []),\n )\n const concreteTableType = convertToConcreteEntityType(entityType)\n const isView = VIEW_CONCRETE_TYPE_VALUES.includes(\n concreteTableType as (typeof VIEW_CONCRETE_TYPE_VALUES)[number],\n )\n const hasAnnotationColumnModels = isView,\n hasDefaultColumnModels = isView\n\n const { data: defaultColumnModels, isLoading: isLoadingDefaultColumns } =\n useGetDefaultColumnModels(\n viewScope?.viewEntityType!,\n viewScope?.viewTypeMask,\n {\n enabled: hasDefaultColumnModels,\n staleTime: Infinity, // The default column models will never change\n },\n )\n\n const annotationColumnModelsQuery = useGetAnnotationColumnModels(\n {\n viewScope: viewScope!,\n includeDerivedAnnotations: true,\n concreteType:\n 'org.sagebionetworks.repo.model.table.ViewColumnModelRequest',\n },\n {\n enabled: hasAnnotationColumnModels,\n },\n )\n\n const {\n data: annotationColumnModels,\n isLoading: isLoadingAnnotationColumns,\n } = annotationColumnModelsQuery\n\n /**\n * Set the initialData in the form state atom on mount, if it exists and we have no data.\n */\n useEffect(() => {\n if (initialData && !isLoadingDefaultColumns) {\n dispatch({\n type: 'setValue',\n value: transformColumnModelsToFormData(\n initialData,\n defaultColumnModels ?? [],\n ),\n })\n }\n // Don't re-run if initial data changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isLoadingDefaultColumns])\n\n const validateInternal = useCallback(() => {\n const result = validateColumnModelFormData(readFormData())\n if (result.success) {\n setValidationErrors(null)\n } else {\n setValidationErrors(result.error)\n }\n return result\n }, [readFormData])\n\n useImperativeHandle(ref, () => {\n return {\n submit() {\n const result = validateInternal()\n if (result.success) {\n onSubmit(result.data)\n }\n },\n getEditedColumnModels() {\n const result = validateInternal()\n if (!result.success) {\n throw new Error('Column models were not valid')\n }\n return result.data\n },\n validate() {\n const result = validateInternal()\n return result.success\n },\n }\n }, [onSubmit, validateInternal])\n\n // Generic function to add a set of columns to the schema (e.g. default columns, annotation columns)\n const addColumnSet = useCallback(\n (newColumns: SetOptional<ColumnModel, 'id'>[]) => {\n const currentFormData = readFormData()\n let columnsToAdd = newColumns.filter(\n (cm: SetOptional<ColumnModel, 'id'>) => {\n // Don't add columns that cannot be added (for example, Views cannot have JSON columns)\n if (\n !getAllowedColumnTypes(isView, false).includes(\n cm.columnType as ColumnTypeEnum,\n )\n ) {\n return false\n }\n // Only add columns that are not already present\n // Use the name column to match because the ID may vary, e.g. if the facetType was changed\n return !currentFormData.find(fd => fd.name === cm.name)\n },\n )\n // Remove the ID column so TableColumnSchemaUtils.createTableUpdateTransactionRequest recognizes these as new columns\n // createTableUpdateTransactionRequest uses the existing column ID to track column updates in the table, so any new columns should have no ID\n // The user can also modify these columns before submitting them, so the ID may not be accurate when we end up submitting them\n columnsToAdd = columnsToAdd.map(cm => omit(cm, ['id']))\n if (columnsToAdd.length > 0) {\n dispatch({\n type: 'setValue',\n value: [\n ...currentFormData,\n ...transformColumnModelsToFormData(\n columnsToAdd,\n defaultColumnModels,\n ),\n ],\n })\n displayToast(\n `${columnsToAdd.length} ${pluralize(\n 'column',\n columnsToAdd.length,\n )} added to schema.`,\n 'success',\n )\n } else {\n displayToast(\n 'No columns added. All columns to add are present in the column schema.',\n 'info',\n )\n }\n },\n [defaultColumnModels, dispatch, isView, readFormData],\n )\n\n const addDefaultColumns = useCallback(() => {\n if (defaultColumnModels) {\n addColumnSet(defaultColumnModels)\n }\n }, [defaultColumnModels, addColumnSet])\n\n const addAnnotationColumns = useCallback(() => {\n if (annotationColumnModels) {\n addColumnSet(annotationColumnModels)\n }\n }, [annotationColumnModels, addColumnSet])\n\n // Put the errors into a map of columnModelIndex -> errors\n const errorsByColumnModel = useMemo(() => {\n if (validationErrors) {\n return groupBy(validationErrors.errors, e => e.path[0])\n }\n return {}\n }, [validationErrors])\n\n return (\n <Box\n component={'form'}\n sx={{\n py: 2.5,\n }}\n >\n <TableColumnSchemaFormActions\n disabled={isSubmitting}\n annotationColumnModelsQuery={annotationColumnModelsQuery}\n />\n <Box\n sx={{\n display: 'grid',\n gap: '8px',\n gridTemplateColumns: COLUMN_SCHEMA_FORM_GRID_TEMPLATE_COLUMNS,\n py: 2.5,\n }}\n >\n <ColumnHeader>{/* Checkbox */}</ColumnHeader>\n <ColumnHeader sx={{ gridColumn: '2 / span 2' }}>\n Column Name\n </ColumnHeader>\n <ColumnHeader>Column Type</ColumnHeader>\n <ColumnHeader>Size</ColumnHeader>\n <ColumnHeader>Max List Length</ColumnHeader>\n <ColumnHeader>Default Value</ColumnHeader>\n <ColumnHeader>Restrict Values</ColumnHeader>\n <ColumnHeader>Facet</ColumnHeader>\n <ColumnHeader>Sort Facet Values</ColumnHeader>\n <Box\n sx={{\n gridColumn: '1 / span 11',\n backgroundColor: 'grey.300',\n height: '2px',\n }}\n />\n {times(numColumnModels, index => {\n return (\n <TableColumnSchemaFormRow\n entityType={entityType}\n columnModelIndex={index}\n disabled={isSubmitting}\n key={index}\n columnModelValidationErrors={errorsByColumnModel[index]}\n annotationColumnModels={annotationColumnModels}\n originalColumnModels={originalColumnModels}\n />\n )\n })}\n </Box>\n <Box\n sx={{\n display: 'flex',\n gap: 1,\n }}\n >\n <Button\n variant={'outlined'}\n onClick={() => {\n dispatch({ type: 'appendColumn' })\n }}\n startIcon={<AddCircleTwoTone />}\n disabled={isSubmitting}\n >\n Add Column\n </Button>\n\n {hasDefaultColumnModels && (\n <Button\n variant={'outlined'}\n startIcon={\n isLoadingDefaultColumns ? (\n <SynapseSpinner />\n ) : (\n <AddCircleTwoTone />\n )\n }\n onClick={() => {\n addDefaultColumns()\n }}\n disabled={isLoadingDefaultColumns || isSubmitting}\n >\n Add Default {entityTypeToFriendlyName(entityType)} Columns\n </Button>\n )}\n\n {hasAnnotationColumnModels && (\n <Button\n variant={'outlined'}\n startIcon={\n isLoadingAnnotationColumns ? (\n <SynapseSpinner />\n ) : (\n <AddCircleTwoTone />\n )\n }\n disabled={isLoadingAnnotationColumns || isSubmitting}\n onClick={() => {\n addAnnotationColumns()\n }}\n >\n {ADD_ALL_ANNOTATIONS_BUTTON_TEXT}\n </Button>\n )}\n <ImportTableColumnsButton\n onAddColumns={cms => {\n addColumnSet(cms)\n }}\n disabled={isSubmitting}\n />\n </Box>\n </Box>\n )\n}\n\ntype TableColumnSchemaFormRowProps = {\n entityType: EntityType\n columnModelIndex: number\n disabled: boolean\n columnModelValidationErrors: ZodIssue[] | null\n annotationColumnModels?: ColumnModel[]\n originalColumnModels?: ColumnModel[]\n}\n\nfunction TableColumnSchemaFormRow(props: TableColumnSchemaFormRowProps) {\n const {\n columnModelIndex,\n entityType,\n disabled,\n columnModelValidationErrors = null,\n annotationColumnModels,\n originalColumnModels,\n } = props\n const dispatch = useSetAtom(tableColumnSchemaFormDataAtom)\n const columnModel = useAtomValue(\n useMemo(\n () =>\n selectAtom(\n tableColumnSchemaFormDataAtom,\n formData => formData[columnModelIndex],\n isEqual,\n ),\n [columnModelIndex],\n ),\n )\n\n // Find the original column model that matches the current column model by name and type, so we can tell the user what fields have changed\n const originalColumnModel = originalColumnModels\n ? findMatchingColumnModel(originalColumnModels, columnModel)\n : undefined\n\n // Find the closest match between passed column model and current column model with name and type\n const defaultAnnotationModel = annotationColumnModels\n ? findMatchingColumnModel(annotationColumnModels, columnModel)\n : undefined\n\n // Organize the JSON Subcolumn errors into a map of subcolumn index to errors\n const errorsForSubcolumns = useMemo(() => {\n if (columnModelValidationErrors) {\n const errorsForAllSubcolumns = columnModelValidationErrors.filter(e => {\n return e.path[0] === columnModelIndex && e.path[1] == 'jsonSubColumns'\n })\n return groupBy(errorsForAllSubcolumns, e => e.path[2])\n }\n return {}\n }, [columnModelIndex, columnModelValidationErrors])\n\n if (!columnModel) {\n return <></>\n }\n const isDefaultColumn = columnModel.isOriginallyDefaultColumn\n\n return (\n <>\n <ColumnModelForm\n entityType={entityType}\n columnModelIndex={columnModelIndex}\n isDefaultColumn={isDefaultColumn}\n disabled={disabled}\n validationErrors={columnModelValidationErrors}\n defaultAnnotationModel={defaultAnnotationModel}\n originalColumnModel={originalColumnModel}\n />\n {columnModel.columnType === ColumnTypeEnum.JSON &&\n columnModel.jsonSubColumns &&\n columnModel.jsonSubColumns.map((subColumnFacet, index) => (\n <ColumnModelForm\n key={index}\n entityType={entityType}\n columnModelIndex={columnModelIndex}\n jsonSubColumnIndex={index}\n isDefaultColumn={isDefaultColumn}\n disabled={disabled}\n validationErrors={errorsForSubcolumns[index]}\n />\n ))}\n {columnModel.columnType === ColumnTypeEnum.JSON && (\n <>\n <Box\n sx={{\n gridColumn: '1 / span 2',\n }}\n >\n {HIERARCHY_END_COMPONENT}\n </Box>\n <Box\n sx={{\n gridColumn: '3 / span 5',\n }}\n >\n <Button\n startIcon={<AddToList />}\n variant={'text'}\n disabled={disabled}\n onClick={() =>\n dispatch({ type: 'appendJsonSubColumn', columnModelIndex })\n }\n >\n Add sub-column\n </Button>\n </Box>\n </>\n )}\n </>\n )\n}\n\nconst TableColumnSchemaFormInternalWithForwardRef = forwardRef<\n SubmitHandle,\n TableColumnSchemaFormProps\n>(TableColumnSchemaFormInternal)\n\nconst TableColumnSchemaFormWrapped = forwardRef<\n SubmitHandle,\n TableColumnSchemaFormProps\n>(function TableColumnSchemaForm(props: TableColumnSchemaFormProps, ref) {\n // Wrap the form in a Jotai provider so that the internal atoms are scoped to just this component instance\n // Use forwardRef to ensure that the ref can be passed along\n return (\n <Provider>\n <TableColumnSchemaFormInternalWithForwardRef {...props} ref={ref} />\n </Provider>\n )\n})\n\nexport default TableColumnSchemaFormWrapped\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TableColumnSchemaForm.js","names":[],"sources":["../../../src/components/TableColumnSchemaEditor/TableColumnSchemaForm.tsx"],"sourcesContent":["import AddToList from '@/assets/icons/AddToList'\nimport {\n useGetAnnotationColumnModels,\n useGetDefaultColumnModels,\n} from '@/synapse-queries/table/useColumnModel'\nimport {\n convertToConcreteEntityType,\n entityTypeToFriendlyName,\n} from '@/utils/functions/EntityTypeUtils'\nimport { AddCircleTwoTone } from '@mui/icons-material'\nimport { Box, Button, styled } from '@mui/material'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport {\n ColumnModel,\n ColumnTypeEnum,\n VIEW_CONCRETE_TYPE_VALUES,\n ViewScope,\n} from '@sage-bionetworks/synapse-types'\nimport { atom, Provider, useAtomValue, useSetAtom } from 'jotai'\nimport { selectAtom, useAtomCallback } from 'jotai/utils'\nimport { groupBy, isEqual, noop, omit, times } from 'lodash-es'\nimport pluralize from 'pluralize'\nimport {\n ForwardedRef,\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useState,\n} from 'react'\nimport { SetOptional } from 'type-fest'\nimport { ZodError, ZodIssue } from 'zod'\nimport { SynapseSpinner } from '../LoadingScreen/LoadingScreen'\nimport { displayToast } from '../ToastMessage'\nimport ColumnModelForm from './ColumnModelForm'\nimport ImportTableColumnsButton from './ImportTableColumnsButton'\nimport {\n findMatchingColumnModel,\n getAllowedColumnTypes,\n transformColumnModelsToFormData,\n} from './TableColumnSchemaEditorUtils'\nimport { TableColumnSchemaFormActions } from './TableColumnSchemaFormActions'\nimport { tableColumnSchemaFormDataAtom } from './TableColumnSchemaFormReducer'\nimport { validateColumnModelFormData } from './Validators/ColumnModelValidator'\n\nconst COLUMN_SCHEMA_FORM_GRID_TEMPLATE_COLUMNS =\n '18px 18px 1.75fr 1.75fr 0.75fr 1fr 1.25fr 1.25fr 1fr 1.25fr'\nconst GRID_CONTAINER_Y_MARGIN_PX = 6\nexport const HIERARCHY_VERTICAL_LINE_COMPONENT = (\n <Box\n sx={{\n width: '1px',\n height: `calc(100% + 2 * ${GRID_CONTAINER_Y_MARGIN_PX}px)`,\n backgroundColor: 'grey.400',\n marginLeft: '8px',\n }}\n />\n)\nexport const HIERARCHY_END_COMPONENT = (\n <Box\n sx={theme => ({\n width: '50%',\n height: '60%',\n borderLeft: `1px solid ${theme.palette.grey[400]}`,\n borderBottom: `1px solid ${theme.palette.grey[400]}`,\n marginLeft: '8px',\n marginBottom: 'auto',\n marginRight: '0',\n borderBottomLeftRadius: '5px',\n })}\n />\n)\n\nexport type SubmitHandle = {\n // Allow the parent component to trigger a submit of the form, so this may be embedded in an arbitrary modal.\n submit: () => void\n // Imperative handle to get the data out of the form for SWC compatibility\n getEditedColumnModels: () => SetOptional<ColumnModel, 'id'>[]\n // Used to check if all form data is valid. Returns the current validity state\n validate: () => boolean\n}\n\ntype TableColumnSchemaFormProps = {\n /* The type of the Table, which determines various schema restrictions and form functionality */\n entityType: EntityType\n /* If this is an entity view, the ViewScope can be used to determine the default column models and fetch annotation column models */\n viewScope?: ViewScope\n initialData?: SetOptional<ColumnModel, 'id'>[]\n onSubmit?: (newColumnModels: SetOptional<ColumnModel, 'id'>[]) => void\n isSubmitting?: boolean\n /** The original/current column models that are applied to the table, if they exist. */\n originalColumnModels?: ColumnModel[]\n}\n\nconst ColumnHeader = styled(Box, {\n label: 'ColumnHeader',\n})({\n fontWeight: 700,\n})\n\nexport const ADD_ALL_ANNOTATIONS_BUTTON_TEXT = 'Add All Annotations'\n\nfunction TableColumnSchemaFormInternal(\n props: TableColumnSchemaFormProps,\n ref: ForwardedRef<SubmitHandle>,\n) {\n const {\n initialData,\n entityType,\n viewScope,\n onSubmit = noop,\n isSubmitting = false,\n originalColumnModels,\n } = props\n\n const numColumnModels = useAtomValue(\n useMemo(() => atom(get => get(tableColumnSchemaFormDataAtom).length), []),\n )\n\n const dispatch = useSetAtom(tableColumnSchemaFormDataAtom)\n const [validationErrors, setValidationErrors] = useState<ZodError | null>(\n null,\n )\n\n // useAtomCallback will let us imperatively read the form data, instead of tracking it in state and triggering a full re-render of the form when any data changes\n const readFormData = useAtomCallback(\n useCallback(get => {\n return get(tableColumnSchemaFormDataAtom)\n }, []),\n )\n const concreteTableType = convertToConcreteEntityType(entityType)\n const isView = VIEW_CONCRETE_TYPE_VALUES.includes(\n concreteTableType as (typeof VIEW_CONCRETE_TYPE_VALUES)[number],\n )\n const hasAnnotationColumnModels = isView,\n hasDefaultColumnModels = isView\n\n const { data: defaultColumnModels, isLoading: isLoadingDefaultColumns } =\n useGetDefaultColumnModels(\n viewScope?.viewEntityType!,\n viewScope?.viewTypeMask,\n {\n enabled: hasDefaultColumnModels,\n staleTime: Infinity, // The default column models will never change\n },\n )\n\n const annotationColumnModelsQuery = useGetAnnotationColumnModels(\n {\n viewScope: viewScope!,\n includeDerivedAnnotations: true,\n concreteType:\n 'org.sagebionetworks.repo.model.table.ViewColumnModelRequest',\n },\n {\n enabled: hasAnnotationColumnModels,\n },\n )\n\n const {\n data: annotationColumnModels,\n isLoading: isLoadingAnnotationColumns,\n } = annotationColumnModelsQuery\n\n /**\n * Set the initialData in the form state atom on mount, if it exists and we have no data.\n */\n useEffect(() => {\n if (initialData && !isLoadingDefaultColumns) {\n dispatch({\n type: 'setValue',\n value: transformColumnModelsToFormData(\n initialData,\n defaultColumnModels ?? [],\n ),\n })\n }\n // Don't re-run if initial data changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isLoadingDefaultColumns])\n\n const validateInternal = useCallback(() => {\n const result = validateColumnModelFormData(readFormData())\n if (result.success) {\n setValidationErrors(null)\n } else {\n setValidationErrors(result.error)\n }\n return result\n }, [readFormData])\n\n useImperativeHandle(ref, () => {\n return {\n submit() {\n const result = validateInternal()\n if (result.success) {\n onSubmit(result.data)\n }\n },\n getEditedColumnModels() {\n const result = validateInternal()\n if (!result.success) {\n throw new Error('Column models were not valid')\n }\n return result.data\n },\n validate() {\n const result = validateInternal()\n return result.success\n },\n }\n }, [onSubmit, validateInternal])\n\n // Generic function to add a set of columns to the schema (e.g. default columns, annotation columns)\n const addColumnSet = useCallback(\n (newColumns: SetOptional<ColumnModel, 'id'>[]) => {\n const currentFormData = readFormData()\n let columnsToAdd = newColumns.filter(\n (cm: SetOptional<ColumnModel, 'id'>) => {\n // Don't add columns that cannot be added (for example, Views cannot have JSON columns)\n if (\n !getAllowedColumnTypes(isView, false).includes(\n cm.columnType as ColumnTypeEnum,\n )\n ) {\n return false\n }\n // Only add columns that are not already present\n // Use the name column to match because the ID may vary, e.g. if the facetType was changed\n return !currentFormData.find(fd => fd.name === cm.name)\n },\n )\n // Remove the ID column so TableColumnSchemaUtils.createTableUpdateTransactionRequest recognizes these as new columns\n // createTableUpdateTransactionRequest uses the existing column ID to track column updates in the table, so any new columns should have no ID\n // The user can also modify these columns before submitting them, so the ID may not be accurate when we end up submitting them\n columnsToAdd = columnsToAdd.map(cm => omit(cm, ['id']))\n if (columnsToAdd.length > 0) {\n dispatch({\n type: 'setValue',\n value: [\n ...currentFormData,\n ...transformColumnModelsToFormData(\n columnsToAdd,\n defaultColumnModels,\n ),\n ],\n })\n displayToast(\n `${columnsToAdd.length} ${pluralize(\n 'column',\n columnsToAdd.length,\n )} added to schema.`,\n 'success',\n )\n } else {\n displayToast(\n 'No columns added. All columns to add are present in the column schema.',\n 'info',\n )\n }\n },\n [defaultColumnModels, dispatch, isView, readFormData],\n )\n\n const addDefaultColumns = useCallback(() => {\n if (defaultColumnModels) {\n addColumnSet(defaultColumnModels)\n }\n }, [defaultColumnModels, addColumnSet])\n\n const addAnnotationColumns = useCallback(() => {\n if (annotationColumnModels) {\n addColumnSet(annotationColumnModels)\n }\n }, [annotationColumnModels, addColumnSet])\n\n // Put the errors into a map of columnModelIndex -> errors\n const errorsByColumnModel = useMemo(() => {\n if (validationErrors) {\n return groupBy(validationErrors.errors, e => e.path[0])\n }\n return {}\n }, [validationErrors])\n\n return (\n <Box\n component={'form'}\n sx={{\n py: 2.5,\n }}\n >\n <TableColumnSchemaFormActions\n disabled={isSubmitting}\n annotationColumnModelsQuery={annotationColumnModelsQuery}\n />\n <Box\n sx={{\n display: 'grid',\n gap: '8px',\n gridTemplateColumns: COLUMN_SCHEMA_FORM_GRID_TEMPLATE_COLUMNS,\n py: 2.5,\n }}\n >\n <ColumnHeader>{/* Checkbox */}</ColumnHeader>\n <ColumnHeader sx={{ gridColumn: '2 / span 2' }}>\n Column Name\n </ColumnHeader>\n <ColumnHeader>Column Type</ColumnHeader>\n <ColumnHeader>Size</ColumnHeader>\n <ColumnHeader>Max List Length</ColumnHeader>\n <ColumnHeader>Default Value</ColumnHeader>\n <ColumnHeader>Restrict Values</ColumnHeader>\n <ColumnHeader>Facet</ColumnHeader>\n <ColumnHeader>Sort Facet Values</ColumnHeader>\n <Box\n sx={{\n gridColumn: '1 / span 11',\n backgroundColor: 'grey.300',\n height: '2px',\n }}\n />\n {times(numColumnModels, index => {\n return (\n <TableColumnSchemaFormRow\n entityType={entityType}\n columnModelIndex={index}\n disabled={isSubmitting}\n key={index}\n columnModelValidationErrors={errorsByColumnModel[index]}\n annotationColumnModels={annotationColumnModels}\n originalColumnModels={originalColumnModels}\n />\n )\n })}\n </Box>\n <Box\n sx={{\n display: 'flex',\n gap: 1,\n }}\n >\n <Button\n variant={'outlined'}\n onClick={() => {\n dispatch({ type: 'appendColumn' })\n }}\n startIcon={<AddCircleTwoTone />}\n disabled={isSubmitting}\n >\n Add Column\n </Button>\n\n {hasDefaultColumnModels && (\n <Button\n variant={'outlined'}\n startIcon={\n isLoadingDefaultColumns ? (\n <SynapseSpinner />\n ) : (\n <AddCircleTwoTone />\n )\n }\n onClick={() => {\n addDefaultColumns()\n }}\n disabled={isLoadingDefaultColumns || isSubmitting}\n >\n Add Default {entityTypeToFriendlyName(entityType)} Columns\n </Button>\n )}\n\n {hasAnnotationColumnModels && (\n <Button\n variant={'outlined'}\n startIcon={\n isLoadingAnnotationColumns ? (\n <SynapseSpinner />\n ) : (\n <AddCircleTwoTone />\n )\n }\n disabled={isLoadingAnnotationColumns || isSubmitting}\n onClick={() => {\n addAnnotationColumns()\n }}\n >\n {ADD_ALL_ANNOTATIONS_BUTTON_TEXT}\n </Button>\n )}\n <ImportTableColumnsButton\n onAddColumns={cms => {\n addColumnSet(cms)\n }}\n disabled={isSubmitting}\n />\n </Box>\n </Box>\n )\n}\n\ntype TableColumnSchemaFormRowProps = {\n entityType: EntityType\n columnModelIndex: number\n disabled: boolean\n columnModelValidationErrors: ZodIssue[] | null\n annotationColumnModels?: ColumnModel[]\n originalColumnModels?: ColumnModel[]\n}\n\nfunction TableColumnSchemaFormRow(props: TableColumnSchemaFormRowProps) {\n const {\n columnModelIndex,\n entityType,\n disabled,\n columnModelValidationErrors = null,\n annotationColumnModels,\n originalColumnModels,\n } = props\n const dispatch = useSetAtom(tableColumnSchemaFormDataAtom)\n const columnModel = useAtomValue(\n useMemo(\n () =>\n selectAtom(\n tableColumnSchemaFormDataAtom,\n formData => formData[columnModelIndex],\n isEqual,\n ),\n [columnModelIndex],\n ),\n )\n\n // Find the original column model that matches the current column model by name and type, so we can tell the user what fields have changed\n const originalColumnModel = originalColumnModels\n ? findMatchingColumnModel(originalColumnModels, columnModel)\n : undefined\n\n // Find the closest match between passed column model and current column model with name and type\n const defaultAnnotationModel = annotationColumnModels\n ? findMatchingColumnModel(annotationColumnModels, columnModel)\n : undefined\n\n // Organize the JSON Subcolumn errors into a map of subcolumn index to errors\n const errorsForSubcolumns = useMemo(() => {\n if (columnModelValidationErrors) {\n const errorsForAllSubcolumns = columnModelValidationErrors.filter(e => {\n return e.path[0] === columnModelIndex && e.path[1] == 'jsonSubColumns'\n })\n return groupBy(errorsForAllSubcolumns, e => e.path[2])\n }\n return {}\n }, [columnModelIndex, columnModelValidationErrors])\n\n if (!columnModel) {\n return <></>\n }\n const isDefaultColumn = columnModel.isOriginallyDefaultColumn\n\n return (\n <>\n <ColumnModelForm\n entityType={entityType}\n columnModelIndex={columnModelIndex}\n isDefaultColumn={isDefaultColumn}\n disabled={disabled}\n validationErrors={columnModelValidationErrors}\n defaultAnnotationModel={defaultAnnotationModel}\n originalColumnModel={originalColumnModel}\n />\n {columnModel.columnType === ColumnTypeEnum.JSON &&\n columnModel.jsonSubColumns &&\n columnModel.jsonSubColumns.map((subColumnFacet, index) => (\n <ColumnModelForm\n key={index}\n entityType={entityType}\n columnModelIndex={columnModelIndex}\n jsonSubColumnIndex={index}\n isDefaultColumn={isDefaultColumn}\n disabled={disabled}\n validationErrors={errorsForSubcolumns[index]}\n />\n ))}\n {columnModel.columnType === ColumnTypeEnum.JSON && (\n <>\n <Box\n sx={{\n gridColumn: '1 / span 2',\n }}\n >\n {HIERARCHY_END_COMPONENT}\n </Box>\n <Box\n sx={{\n gridColumn: '3 / span 5',\n }}\n >\n <Button\n startIcon={<AddToList />}\n variant={'text'}\n disabled={disabled}\n onClick={() =>\n dispatch({ type: 'appendJsonSubColumn', columnModelIndex })\n }\n >\n Add sub-column\n </Button>\n </Box>\n </>\n )}\n </>\n )\n}\n\nconst TableColumnSchemaFormInternalWithForwardRef = forwardRef<\n SubmitHandle,\n TableColumnSchemaFormProps\n>(TableColumnSchemaFormInternal)\n\nconst TableColumnSchemaFormWrapped = forwardRef<\n SubmitHandle,\n TableColumnSchemaFormProps\n>(function TableColumnSchemaForm(props: TableColumnSchemaFormProps, ref) {\n // Wrap the form in a Jotai provider so that the internal atoms are scoped to just this component instance\n // Use forwardRef to ensure that the ref can be passed along\n return (\n <Provider>\n <TableColumnSchemaFormInternalWithForwardRef {...props} ref={ref} />\n </Provider>\n )\n})\n\nexport default TableColumnSchemaFormWrapped\n"],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type CreateTableFromCsvDialogProps = {
|
|
2
|
+
/** Whether the dialog is open */
|
|
3
|
+
open: boolean;
|
|
4
|
+
/** Callback when the dialog is closed */
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
/** Destination project/folder to upload to */
|
|
7
|
+
parentId: string;
|
|
8
|
+
/** Invoked after all backend operations successfully complete */
|
|
9
|
+
onSuccess?: () => void;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* A multi-step modal wizard used to create a Synapse Table entity from an uploaded CSV file.
|
|
13
|
+
* It manages two primary phases:
|
|
14
|
+
* 1. CSV Upload & Preview: Displays data preview and infers suggested column models.
|
|
15
|
+
* 2. Table Configuration: Sets table name and allows schema customization.
|
|
16
|
+
*/
|
|
17
|
+
export default function CreateTableFromCsvDialog(props: CreateTableFromCsvDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
//# sourceMappingURL=CreateTableFromCsvDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateTableFromCsvDialog.d.ts","sourceRoot":"","sources":["../../../../src/components/table/CsvPreview/CreateTableFromCsvDialog.tsx"],"names":[],"mappings":"AAwBA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,iCAAiC;IACjC,IAAI,EAAE,OAAO,CAAA;IACb,yCAAyC;IACzC,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAA;IAChB,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB,CAAA;AAOD;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,wBAAwB,CAC9C,KAAK,EAAE,6BAA6B,2CAyJrC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { displayToast as e } from "../../ToastMessage/ToastMessage.js";
|
|
2
|
+
import { DialogBase as t } from "../../DialogBase.js";
|
|
3
|
+
import n, { CsvUploadPreviewStep as r } from "./useCsvUploadPreview.js";
|
|
4
|
+
import i from "./CsvUploadPreviewContent.js";
|
|
5
|
+
import a from "./useCreateTableFromCsv.js";
|
|
6
|
+
import o from "../../TableColumnSchemaEditor/TableColumnSchemaForm.js";
|
|
7
|
+
import { useCallback as s, useRef as c, useState as l } from "react";
|
|
8
|
+
import { isUndefined as u, omitBy as d } from "lodash-es";
|
|
9
|
+
import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
10
|
+
import { EntityType as h } from "@sage-bionetworks/synapse-client";
|
|
11
|
+
import g from "@mui/material/Typography";
|
|
12
|
+
import _ from "@mui/material/TextField";
|
|
13
|
+
import v from "@mui/material/Stack";
|
|
14
|
+
import y from "@mui/material/Button";
|
|
15
|
+
import b from "@mui/icons-material/ExpandMore";
|
|
16
|
+
import x from "@mui/material/Accordion";
|
|
17
|
+
import S from "@mui/material/AccordionDetails";
|
|
18
|
+
import C from "@mui/material/AccordionSummary";
|
|
19
|
+
//#region src/components/table/CsvPreview/CreateTableFromCsvDialog.tsx
|
|
20
|
+
var w = /* @__PURE__ */ function(e) {
|
|
21
|
+
return e[e.CSV_UPLOAD_PREVIEW = 0] = "CSV_UPLOAD_PREVIEW", e[e.TABLE_NAME = 1] = "TABLE_NAME", e;
|
|
22
|
+
}(w || {});
|
|
23
|
+
function T(T) {
|
|
24
|
+
let { open: E, onClose: D, parentId: O, onSuccess: k } = T, A = n(), [j, M] = l(w.CSV_UPLOAD_PREVIEW), [N, P] = l(""), [F, I] = l([]), L = c(null), { mutate: R, isPending: z } = a({
|
|
25
|
+
onSuccess() {
|
|
26
|
+
k?.();
|
|
27
|
+
},
|
|
28
|
+
onError(t) {
|
|
29
|
+
e(t.message, "danger");
|
|
30
|
+
}
|
|
31
|
+
}), B = s((e = []) => {
|
|
32
|
+
R({
|
|
33
|
+
parentId: O,
|
|
34
|
+
tableName: N,
|
|
35
|
+
columnModels: e,
|
|
36
|
+
csvTableDescriptor: A.csvTableDescriptor,
|
|
37
|
+
fileHandleId: A.uploadedFileHandleId
|
|
38
|
+
});
|
|
39
|
+
}, [
|
|
40
|
+
R,
|
|
41
|
+
O,
|
|
42
|
+
N,
|
|
43
|
+
A.csvTableDescriptor,
|
|
44
|
+
A.uploadedFileHandleId
|
|
45
|
+
]), V = s((e) => {
|
|
46
|
+
B(e);
|
|
47
|
+
}, [B]), H = s(() => {
|
|
48
|
+
let e = A.csvPreviewData?.suggestedColumns;
|
|
49
|
+
e && (I(e.map((e) => d(e, u))), M(w.TABLE_NAME));
|
|
50
|
+
}, [A.csvPreviewData, M]), U = /* @__PURE__ */ m(v, {
|
|
51
|
+
spacing: 2,
|
|
52
|
+
children: [
|
|
53
|
+
/* @__PURE__ */ p(_, {
|
|
54
|
+
required: !0,
|
|
55
|
+
label: "Table Name",
|
|
56
|
+
value: N,
|
|
57
|
+
onChange: (e) => P(e.target.value),
|
|
58
|
+
fullWidth: !0
|
|
59
|
+
}),
|
|
60
|
+
/* @__PURE__ */ p(g, {
|
|
61
|
+
variant: "body1",
|
|
62
|
+
children: "Use the schema options button to make changes to the columns of the table. Use the create button to finish building the table."
|
|
63
|
+
}),
|
|
64
|
+
/* @__PURE__ */ m(x, { children: [/* @__PURE__ */ p(C, {
|
|
65
|
+
expandIcon: /* @__PURE__ */ p(b, {}),
|
|
66
|
+
children: /* @__PURE__ */ p(g, {
|
|
67
|
+
variant: "headline3",
|
|
68
|
+
children: "Schema Options"
|
|
69
|
+
})
|
|
70
|
+
}), /* @__PURE__ */ p(S, { children: /* @__PURE__ */ p(o, {
|
|
71
|
+
initialData: F,
|
|
72
|
+
entityType: h.table,
|
|
73
|
+
ref: L,
|
|
74
|
+
onSubmit: V
|
|
75
|
+
}) })] })
|
|
76
|
+
]
|
|
77
|
+
});
|
|
78
|
+
return /* @__PURE__ */ p(t, {
|
|
79
|
+
maxWidth: "lg",
|
|
80
|
+
title: "Upload CSV",
|
|
81
|
+
onCancel: D,
|
|
82
|
+
open: E,
|
|
83
|
+
content: /* @__PURE__ */ m(f, { children: [j === w.CSV_UPLOAD_PREVIEW && /* @__PURE__ */ p(i, { workflow: A }), j === w.TABLE_NAME && U] }),
|
|
84
|
+
actions: /* @__PURE__ */ m(f, { children: [
|
|
85
|
+
/* @__PURE__ */ p(y, {
|
|
86
|
+
variant: "outlined",
|
|
87
|
+
disabled: A.isLoadingPreview,
|
|
88
|
+
onClick: () => {
|
|
89
|
+
D();
|
|
90
|
+
},
|
|
91
|
+
children: "Cancel"
|
|
92
|
+
}),
|
|
93
|
+
j === w.CSV_UPLOAD_PREVIEW && A.step === r.COLUMN_PREVIEW && /* @__PURE__ */ p(y, {
|
|
94
|
+
disabled: A.isLoadingPreview,
|
|
95
|
+
variant: "contained",
|
|
96
|
+
onClick: H,
|
|
97
|
+
children: "Next"
|
|
98
|
+
}),
|
|
99
|
+
j === w.TABLE_NAME && /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(y, {
|
|
100
|
+
variant: "outlined",
|
|
101
|
+
onClick: () => M(w.CSV_UPLOAD_PREVIEW),
|
|
102
|
+
children: "Back"
|
|
103
|
+
}), /* @__PURE__ */ p(y, {
|
|
104
|
+
variant: "contained",
|
|
105
|
+
onClick: () => L.current?.submit(),
|
|
106
|
+
loading: z,
|
|
107
|
+
disabled: !N,
|
|
108
|
+
children: "Create"
|
|
109
|
+
})] })
|
|
110
|
+
] })
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
export { T as default };
|
|
115
|
+
|
|
116
|
+
//# sourceMappingURL=CreateTableFromCsvDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateTableFromCsvDialog.js","names":[],"sources":["../../../../src/components/table/CsvPreview/CreateTableFromCsvDialog.tsx"],"sourcesContent":["import TableColumnSchemaForm, {\n SubmitHandle,\n} from '@/components/TableColumnSchemaEditor/TableColumnSchemaForm'\nimport { DialogBase } from '@/components/DialogBase'\nimport { displayToast } from '@/components/ToastMessage/ToastMessage'\nimport useCsvUploadPreview, {\n CsvUploadPreviewStep,\n} from '@/components/table/CsvPreview/useCsvUploadPreview'\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore'\nimport Accordion from '@mui/material/Accordion'\nimport AccordionDetails from '@mui/material/AccordionDetails'\nimport AccordionSummary from '@mui/material/AccordionSummary'\nimport Button from '@mui/material/Button'\nimport Stack from '@mui/material/Stack'\nimport TextField from '@mui/material/TextField'\nimport Typography from '@mui/material/Typography'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport { isUndefined, omitBy } from 'lodash-es'\nimport { useCallback, useRef, useState } from 'react'\nimport { SetOptional } from 'type-fest'\nimport { ColumnModel as SynapseTypesColumnModel } from '@sage-bionetworks/synapse-types'\nimport useCreateTableFromCsv from './useCreateTableFromCsv'\nimport CsvUploadPreviewContent from './CsvUploadPreviewContent'\n\nexport type CreateTableFromCsvDialogProps = {\n /** Whether the dialog is open */\n open: boolean\n /** Callback when the dialog is closed */\n onClose: () => void\n /** Destination project/folder to upload to */\n parentId: string\n /** Invoked after all backend operations successfully complete */\n onSuccess?: () => void\n}\n\nenum CreateTableFromCsvStep {\n CSV_UPLOAD_PREVIEW = 0,\n TABLE_NAME = 1,\n}\n\n/**\n * A multi-step modal wizard used to create a Synapse Table entity from an uploaded CSV file.\n * It manages two primary phases:\n * 1. CSV Upload & Preview: Displays data preview and infers suggested column models.\n * 2. Table Configuration: Sets table name and allows schema customization.\n */\nexport default function CreateTableFromCsvDialog(\n props: CreateTableFromCsvDialogProps,\n) {\n const { open, onClose, parentId, onSuccess } = props\n const csvUploadPreviewWorkflow = useCsvUploadPreview()\n const [step, setStep] = useState(CreateTableFromCsvStep.CSV_UPLOAD_PREVIEW)\n const [tableName, setTableName] = useState('')\n const [columnModels, setColumnModels] = useState<\n SetOptional<SynapseTypesColumnModel, 'id'>[]\n >([])\n const columnSchemaFormRef = useRef<SubmitHandle>(null)\n\n const { mutate: createTableFromCsv, isPending: isUploading } =\n useCreateTableFromCsv({\n onSuccess() {\n onSuccess?.()\n },\n onError(error) {\n displayToast(error.message, 'danger')\n },\n })\n\n const handleFinish = useCallback(\n (columnModelsParam: SetOptional<SynapseTypesColumnModel, 'id'>[] = []) => {\n createTableFromCsv({\n parentId,\n tableName,\n columnModels: columnModelsParam,\n csvTableDescriptor: csvUploadPreviewWorkflow.csvTableDescriptor,\n fileHandleId: csvUploadPreviewWorkflow.uploadedFileHandleId!,\n })\n },\n [\n createTableFromCsv,\n parentId,\n tableName,\n csvUploadPreviewWorkflow.csvTableDescriptor,\n csvUploadPreviewWorkflow.uploadedFileHandleId,\n ],\n )\n\n const onColumnSchemaSubmit = useCallback(\n (editedColumnModels: SetOptional<SynapseTypesColumnModel, 'id'>[]) => {\n void handleFinish(editedColumnModels)\n },\n [handleFinish],\n )\n\n const handlePreviewConfirm = useCallback(() => {\n const suggestedColumns =\n csvUploadPreviewWorkflow.csvPreviewData?.suggestedColumns\n if (!suggestedColumns) {\n return\n }\n\n // create new table; initialize schema editor with suggestions and proceed to naming.\n setColumnModels(\n suggestedColumns.map(cm => omitBy(cm, isUndefined)) as SetOptional<\n SynapseTypesColumnModel,\n 'id'\n >[],\n )\n setStep(CreateTableFromCsvStep.TABLE_NAME)\n }, [csvUploadPreviewWorkflow.csvPreviewData, setStep])\n\n const tableNameStepContent = (\n <Stack spacing={2}>\n <TextField\n required\n label={'Table Name'}\n value={tableName}\n onChange={e => setTableName(e.target.value)}\n fullWidth\n />\n <Typography variant={'body1'}>\n Use the schema options button to make changes to the columns of the\n table. Use the create button to finish building the table.\n </Typography>\n <Accordion>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <Typography variant={'headline3'}>Schema Options</Typography>\n </AccordionSummary>\n <AccordionDetails>\n <TableColumnSchemaForm\n initialData={columnModels}\n entityType={EntityType.table}\n ref={columnSchemaFormRef}\n onSubmit={onColumnSchemaSubmit}\n />\n </AccordionDetails>\n </Accordion>\n </Stack>\n )\n\n return (\n <DialogBase\n maxWidth={'lg'}\n title={'Upload CSV'}\n onCancel={onClose}\n open={open}\n content={\n <>\n {step === CreateTableFromCsvStep.CSV_UPLOAD_PREVIEW && (\n <CsvUploadPreviewContent workflow={csvUploadPreviewWorkflow} />\n )}\n {step === CreateTableFromCsvStep.TABLE_NAME && tableNameStepContent}\n </>\n }\n actions={\n <>\n <Button\n variant={'outlined'}\n disabled={csvUploadPreviewWorkflow.isLoadingPreview}\n onClick={() => {\n onClose()\n }}\n >\n Cancel\n </Button>\n {step === CreateTableFromCsvStep.CSV_UPLOAD_PREVIEW &&\n csvUploadPreviewWorkflow.step ===\n CsvUploadPreviewStep.COLUMN_PREVIEW && (\n <Button\n disabled={csvUploadPreviewWorkflow.isLoadingPreview}\n variant={'contained'}\n onClick={handlePreviewConfirm}\n >\n Next\n </Button>\n )}\n {step === CreateTableFromCsvStep.TABLE_NAME && (\n <>\n <Button\n variant={'outlined'}\n onClick={() =>\n setStep(CreateTableFromCsvStep.CSV_UPLOAD_PREVIEW)\n }\n >\n Back\n </Button>\n <Button\n variant={'contained'}\n onClick={() => columnSchemaFormRef.current?.submit()}\n loading={isUploading}\n disabled={!tableName}\n >\n Create\n </Button>\n </>\n )}\n </>\n }\n />\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmCA,IAAK,IAAL,yBAAA,GAAA;QACE,EAAA,EAAA,qBAAqB,KAAA,sBACrB,EAAA,EAAA,aAAa,KAAA;EAFV,KAAA,EAAA,CAGJ;AAQD,SAAwB,EACtB,GACA;CACA,IAAM,EAAE,SAAM,YAAS,aAAU,iBAAc,GACzC,IAA2B,GAAqB,EAChD,CAAC,GAAM,KAAW,EAAS,EAAuB,mBAAmB,EACrE,CAAC,GAAW,KAAgB,EAAS,GAAG,EACxC,CAAC,GAAc,KAAmB,EAEtC,EAAE,CAAC,EACC,IAAsB,EAAqB,KAAK,EAEhD,EAAE,QAAQ,GAAoB,WAAW,MAC7C,EAAsB;EACpB,YAAY;AACV,QAAa;;EAEf,QAAQ,GAAO;AACb,KAAa,EAAM,SAAS,SAAS;;EAExC,CAAC,EAEE,IAAe,GAClB,IAAkE,EAAE,KAAK;AACxE,IAAmB;GACjB;GACA;GACA,cAAc;GACd,oBAAoB,EAAyB;GAC7C,cAAc,EAAyB;GACxC,CAAC;IAEJ;EACE;EACA;EACA;EACA,EAAyB;EACzB,EAAyB;EAC1B,CACF,EAEK,IAAuB,GAC1B,MAAqE;AAC/D,IAAa,EAAmB;IAEvC,CAAC,EAAa,CACf,EAEK,IAAuB,QAAkB;EAC7C,IAAM,IACJ,EAAyB,gBAAgB;AACtC,QAKL,EACE,EAAiB,KAAI,MAAM,EAAO,GAAI,EAAY,CAAC,CAIpD,EACD,EAAQ,EAAuB,WAAW;IACzC,CAAC,EAAyB,gBAAgB,EAAQ,CAAC,EAEhD,IACJ,kBAAC,GAAD;EAAO,SAAS;YAAhB;GACE,kBAAC,GAAD;IACE,UAAA;IACA,OAAO;IACP,OAAO;IACP,WAAU,MAAK,EAAa,EAAE,OAAO,MAAM;IAC3C,WAAA;IACA,CAAA;GACF,kBAAC,GAAD;IAAY,SAAS;cAAS;IAGjB,CAAA;GACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD;IAAkB,YAAY,kBAAC,GAAD,EAAkB,CAAA;cAC9C,kBAAC,GAAD;KAAY,SAAS;eAAa;KAA2B,CAAA;IAC5C,CAAA,EACnB,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IACE,aAAa;IACb,YAAY,EAAW;IACvB,KAAK;IACL,UAAU;IACV,CAAA,EACe,CAAA,CACT,EAAA,CAAA;GACN;;AAGV,QACE,kBAAC,GAAD;EACE,UAAU;EACV,OAAO;EACP,UAAU;EACJ;EACN,SACE,kBAAA,GAAA,EAAA,UAAA,CACG,MAAS,EAAuB,sBAC/B,kBAAC,GAAD,EAAyB,UAAU,GAA4B,CAAA,EAEhE,MAAS,EAAuB,cAAc,EAC9C,EAAA,CAAA;EAEL,SACE,kBAAA,GAAA,EAAA,UAAA;GACE,kBAAC,GAAD;IACE,SAAS;IACT,UAAU,EAAyB;IACnC,eAAe;AACb,QAAS;;cAEZ;IAEQ,CAAA;GACR,MAAS,EAAuB,sBAC/B,EAAyB,SACvB,EAAqB,kBACrB,kBAAC,GAAD;IACE,UAAU,EAAyB;IACnC,SAAS;IACT,SAAS;cACV;IAEQ,CAAA;GAEZ,MAAS,EAAuB,cAC/B,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;IACE,SAAS;IACT,eACE,EAAQ,EAAuB,mBAAmB;cAErD;IAEQ,CAAA,EACT,kBAAC,GAAD;IACE,SAAS;IACT,eAAe,EAAoB,SAAS,QAAQ;IACpD,SAAS;IACT,UAAU,CAAC;cACZ;IAEQ,CAAA,CACR,EAAA,CAAA;GAEJ,EAAA,CAAA;EAEL,CAAA"}
|
|
@@ -4,15 +4,15 @@ export type CsvPreviewDialogProps = {
|
|
|
4
4
|
open: boolean;
|
|
5
5
|
/** Callback when the dialog is closed */
|
|
6
6
|
onClose: () => void;
|
|
7
|
-
/** Callback when the user confirms the column models
|
|
8
|
-
* @param dataFileHandleId - The file handle ID of the uploaded CSV
|
|
9
|
-
* @param columnModels - The confirmed column models
|
|
10
|
-
* */
|
|
11
|
-
onConfirm: (dataFileHandleId: string, columnModels: ColumnModel[], csvTableDescriptor: CsvTableDescriptor) => void;
|
|
12
7
|
/** Whether the confirm action is pending */
|
|
13
8
|
confirmIsPending?: boolean;
|
|
14
9
|
/** An optional error message to display */
|
|
15
10
|
errorMessage?: string;
|
|
11
|
+
/** Callback when the user confirms the column models
|
|
12
|
+
* @param dataFileHandleId - The file handle ID of the uploaded CSV
|
|
13
|
+
* @param columnModels - The confirmed column models
|
|
14
|
+
*/
|
|
15
|
+
onConfirm: (dataFileHandleId: string, columnModels: ColumnModel[], csvTableDescriptor: CsvTableDescriptor) => void;
|
|
16
16
|
};
|
|
17
17
|
export default function CsvPreviewDialog(props: CsvPreviewDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
18
18
|
//# sourceMappingURL=CsvPreviewDialog.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CsvPreviewDialog.d.ts","sourceRoot":"","sources":["../../../../src/components/table/CsvPreview/CsvPreviewDialog.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CsvPreviewDialog.d.ts","sourceRoot":"","sources":["../../../../src/components/table/CsvPreview/CsvPreviewDialog.tsx"],"names":[],"mappings":"AAOA,OAAO,EACL,WAAW,EACX,kBAAkB,EACnB,MAAM,kCAAkC,CAAA;AAGzC,MAAM,MAAM,qBAAqB,GAAG;IAClC,iCAAiC;IACjC,IAAI,EAAE,OAAO,CAAA;IACb,yCAAyC;IACzC,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,SAAS,EAAE,CACT,gBAAgB,EAAE,MAAM,EACxB,YAAY,EAAE,WAAW,EAAE,EAC3B,kBAAkB,EAAE,kBAAkB,KACnC,IAAI,CAAA;CACV,CAAA;AAED,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,2CAgEpE"}
|
|
@@ -1,94 +1,45 @@
|
|
|
1
1
|
import { ErrorBanner as e } from "../../error/ErrorBanner.js";
|
|
2
2
|
import { DialogBase as t } from "../../DialogBase.js";
|
|
3
3
|
import "../../index.js";
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import { RefreshTwoTone as d } from "@mui/icons-material";
|
|
10
|
-
import f from "@mui/material/Typography";
|
|
11
|
-
import p from "@mui/material/Stack";
|
|
12
|
-
import m from "@mui/material/Button";
|
|
13
|
-
import h from "@mui/icons-material/ExpandMore";
|
|
14
|
-
import g from "@mui/material/Accordion";
|
|
15
|
-
import _ from "@mui/material/AccordionDetails";
|
|
16
|
-
import v from "@mui/material/AccordionSummary";
|
|
4
|
+
import n, { CsvUploadPreviewStep as r } from "./useCsvUploadPreview.js";
|
|
5
|
+
import i from "./CsvUploadPreviewContent.js";
|
|
6
|
+
import { useCallback as a } from "react";
|
|
7
|
+
import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
8
|
+
import l from "@mui/material/Button";
|
|
17
9
|
//#region src/components/table/CsvPreview/CsvPreviewDialog.tsx
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
F(e), D(y.COLUMN_PREVIEW);
|
|
30
|
-
}, []), L = o(null), R = o(null), z = /* @__PURE__ */ l(n, {
|
|
31
|
-
ref: L,
|
|
32
|
-
allowMultipleUpload: !1,
|
|
33
|
-
onFileUploadComplete: (e) => {
|
|
34
|
-
I(e);
|
|
35
|
-
},
|
|
36
|
-
disableDragAndDrop: !0
|
|
37
|
-
}), B = /* @__PURE__ */ u(p, {
|
|
38
|
-
spacing: 2,
|
|
39
|
-
children: [P && /* @__PURE__ */ l(r, {
|
|
40
|
-
fileHandleId: P,
|
|
41
|
-
csvTableDescriptor: O,
|
|
42
|
-
onCsvPreviewDataChange: j,
|
|
43
|
-
onIsLoadingChange: N
|
|
44
|
-
}), /* @__PURE__ */ u(g, { children: [/* @__PURE__ */ l(v, {
|
|
45
|
-
expandIcon: /* @__PURE__ */ l(h, {}),
|
|
46
|
-
children: /* @__PURE__ */ l(f, {
|
|
47
|
-
variant: "headline3",
|
|
48
|
-
children: "Show Options"
|
|
49
|
-
})
|
|
50
|
-
}), /* @__PURE__ */ u(_, { children: [/* @__PURE__ */ l(i, {
|
|
51
|
-
defaultValue: O,
|
|
52
|
-
ref: R
|
|
53
|
-
}), /* @__PURE__ */ l(m, {
|
|
54
|
-
variant: "outlined",
|
|
55
|
-
startIcon: /* @__PURE__ */ l(d, {}),
|
|
56
|
-
sx: { mt: 2 },
|
|
57
|
-
onClick: () => {
|
|
58
|
-
R.current && k(R.current.getFormData());
|
|
59
|
-
},
|
|
60
|
-
children: "Refresh Preview"
|
|
61
|
-
})] })] })]
|
|
62
|
-
});
|
|
63
|
-
return /* @__PURE__ */ l(t, {
|
|
10
|
+
function u(u) {
|
|
11
|
+
let { open: d, onClose: f, onConfirm: p, confirmIsPending: m, errorMessage: h } = u, g = n(), _ = a(() => {
|
|
12
|
+
let e = g.csvPreviewData?.suggestedColumns;
|
|
13
|
+
e && g.uploadedFileHandleId != null && p(g.uploadedFileHandleId, e, g.csvTableDescriptor);
|
|
14
|
+
}, [
|
|
15
|
+
g.csvPreviewData,
|
|
16
|
+
g.uploadedFileHandleId,
|
|
17
|
+
g.csvTableDescriptor,
|
|
18
|
+
p
|
|
19
|
+
]);
|
|
20
|
+
return /* @__PURE__ */ s(t, {
|
|
64
21
|
maxWidth: "lg",
|
|
65
22
|
title: "Upload CSV",
|
|
66
|
-
onCancel:
|
|
67
|
-
open:
|
|
68
|
-
content: /* @__PURE__ */
|
|
69
|
-
|
|
70
|
-
E === y.COLUMN_PREVIEW && B,
|
|
71
|
-
T && /* @__PURE__ */ l(e, { error: T })
|
|
72
|
-
] }),
|
|
73
|
-
actions: /* @__PURE__ */ u(c, { children: [/* @__PURE__ */ l(m, {
|
|
23
|
+
onCancel: f,
|
|
24
|
+
open: d,
|
|
25
|
+
content: /* @__PURE__ */ c(o, { children: [/* @__PURE__ */ s(i, { workflow: g }), h && /* @__PURE__ */ s(e, { error: h })] }),
|
|
26
|
+
actions: /* @__PURE__ */ c(o, { children: [/* @__PURE__ */ s(l, {
|
|
74
27
|
variant: "outlined",
|
|
75
|
-
disabled:
|
|
28
|
+
disabled: g.isLoadingPreview,
|
|
76
29
|
onClick: () => {
|
|
77
|
-
|
|
30
|
+
f();
|
|
78
31
|
},
|
|
79
32
|
children: "Cancel"
|
|
80
|
-
}),
|
|
81
|
-
disabled:
|
|
33
|
+
}), g.step === r.COLUMN_PREVIEW && /* @__PURE__ */ s(l, {
|
|
34
|
+
disabled: g.isLoadingPreview,
|
|
82
35
|
variant: "contained",
|
|
83
|
-
onClick:
|
|
84
|
-
|
|
85
|
-
},
|
|
86
|
-
loading: w,
|
|
36
|
+
onClick: _,
|
|
37
|
+
loading: m,
|
|
87
38
|
children: "Confirm"
|
|
88
39
|
})] })
|
|
89
40
|
});
|
|
90
41
|
}
|
|
91
42
|
//#endregion
|
|
92
|
-
export {
|
|
43
|
+
export { u as default };
|
|
93
44
|
|
|
94
45
|
//# sourceMappingURL=CsvPreviewDialog.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CsvPreviewDialog.js","names":[],"sources":["../../../../src/components/table/CsvPreview/CsvPreviewDialog.tsx"],"sourcesContent":["import { DialogBase } from '@/components/DialogBase'\nimport {
|
|
1
|
+
{"version":3,"file":"CsvPreviewDialog.js","names":[],"sources":["../../../../src/components/table/CsvPreview/CsvPreviewDialog.tsx"],"sourcesContent":["import { DialogBase } from '@/components/DialogBase'\nimport { ErrorBanner } from '@/components/index'\nimport CsvUploadPreviewContent from '@/components/table/CsvPreview/CsvUploadPreviewContent'\nimport useCsvUploadPreview, {\n CsvUploadPreviewStep,\n} from '@/components/table/CsvPreview/useCsvUploadPreview'\nimport Button from '@mui/material/Button'\nimport {\n ColumnModel,\n CsvTableDescriptor,\n} from '@sage-bionetworks/synapse-client'\nimport { useCallback } from 'react'\n\nexport type CsvPreviewDialogProps = {\n /** Whether the dialog is open */\n open: boolean\n /** Callback when the dialog is closed */\n onClose: () => void\n /** Whether the confirm action is pending */\n confirmIsPending?: boolean\n /** An optional error message to display */\n errorMessage?: string\n /** Callback when the user confirms the column models\n * @param dataFileHandleId - The file handle ID of the uploaded CSV\n * @param columnModels - The confirmed column models\n */\n onConfirm: (\n dataFileHandleId: string,\n columnModels: ColumnModel[],\n csvTableDescriptor: CsvTableDescriptor,\n ) => void\n}\n\nexport default function CsvPreviewDialog(props: CsvPreviewDialogProps) {\n const { open, onClose, onConfirm, confirmIsPending, errorMessage } = props\n\n const csvUploadPreviewWorkflow = useCsvUploadPreview()\n\n const handlePreviewConfirm = useCallback(() => {\n const suggestedColumns =\n csvUploadPreviewWorkflow.csvPreviewData?.suggestedColumns\n if (!suggestedColumns) {\n return\n }\n\n if (csvUploadPreviewWorkflow.uploadedFileHandleId != null) {\n onConfirm(\n csvUploadPreviewWorkflow.uploadedFileHandleId,\n suggestedColumns,\n csvUploadPreviewWorkflow.csvTableDescriptor,\n )\n }\n }, [\n csvUploadPreviewWorkflow.csvPreviewData,\n csvUploadPreviewWorkflow.uploadedFileHandleId,\n csvUploadPreviewWorkflow.csvTableDescriptor,\n onConfirm,\n ])\n\n return (\n <DialogBase\n maxWidth={'lg'}\n title={'Upload CSV'}\n onCancel={onClose}\n open={open}\n content={\n <>\n <CsvUploadPreviewContent workflow={csvUploadPreviewWorkflow} />\n {errorMessage && <ErrorBanner error={errorMessage} />}\n </>\n }\n actions={\n <>\n <Button\n variant={'outlined'}\n disabled={csvUploadPreviewWorkflow.isLoadingPreview}\n onClick={() => {\n onClose()\n }}\n >\n Cancel\n </Button>\n {csvUploadPreviewWorkflow.step ===\n CsvUploadPreviewStep.COLUMN_PREVIEW && (\n <Button\n disabled={csvUploadPreviewWorkflow.isLoadingPreview}\n variant={'contained'}\n onClick={handlePreviewConfirm}\n loading={confirmIsPending}\n >\n Confirm\n </Button>\n )}\n </>\n }\n />\n )\n}\n"],"mappings":";;;;;;;;;AAiCA,SAAwB,EAAiB,GAA8B;CACrE,IAAM,EAAE,SAAM,YAAS,cAAW,qBAAkB,oBAAiB,GAE/D,IAA2B,GAAqB,EAEhD,IAAuB,QAAkB;EAC7C,IAAM,IACJ,EAAyB,gBAAgB;AACtC,OAID,EAAyB,wBAAwB,QACnD,EACE,EAAyB,sBACzB,GACA,EAAyB,mBAC1B;IAEF;EACD,EAAyB;EACzB,EAAyB;EACzB,EAAyB;EACzB;EACD,CAAC;AAEF,QACE,kBAAC,GAAD;EACE,UAAU;EACV,OAAO;EACP,UAAU;EACJ;EACN,SACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAyB,UAAU,GAA4B,CAAA,EAC9D,KAAgB,kBAAC,GAAD,EAAa,OAAO,GAAgB,CAAA,CACpD,EAAA,CAAA;EAEL,SACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;GACE,SAAS;GACT,UAAU,EAAyB;GACnC,eAAe;AACb,OAAS;;aAEZ;GAEQ,CAAA,EACR,EAAyB,SACxB,EAAqB,kBACrB,kBAAC,GAAD;GACE,UAAU,EAAyB;GACnC,SAAS;GACT,SAAS;GACT,SAAS;aACV;GAEQ,CAAA,CAEV,EAAA,CAAA;EAEL,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CsvTableDescriptor, UploadToTablePreviewResult } from '@sage-bionetworks/synapse-client';
|
|
2
|
+
export type CsvPreviewWithOptionsProps = {
|
|
3
|
+
/** File handle ID of the uploaded CSV, or null if not yet uploaded */
|
|
4
|
+
fileHandleId: string | null;
|
|
5
|
+
/** Current CSV parsing configuration */
|
|
6
|
+
csvTableDescriptor: CsvTableDescriptor;
|
|
7
|
+
/** Called when the user clicks "Refresh Preview" with the form's current values */
|
|
8
|
+
onCsvTableDescriptorChange: (descriptor: CsvTableDescriptor) => void;
|
|
9
|
+
/** Called when the CSV preview data is fetched */
|
|
10
|
+
onCsvPreviewDataChange?: (data: UploadToTablePreviewResult) => void;
|
|
11
|
+
/** Called when the preview load state changes */
|
|
12
|
+
onIsLoadingChange?: (isLoading: boolean) => void;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Displays a CSV preview table with expandable parsing options.
|
|
16
|
+
* For upload/preview flows, prefer useCsvUploadPreview with CsvUploadPreviewContent.
|
|
17
|
+
*/
|
|
18
|
+
export default function CsvPreviewWithOptions({ fileHandleId, csvTableDescriptor, onCsvTableDescriptorChange, onCsvPreviewDataChange, onIsLoadingChange, }: CsvPreviewWithOptionsProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
//# sourceMappingURL=CsvPreviewWithOptions.d.ts.map
|