diff --git a/e2e/tests/plugin-datagrid.spec.ts b/e2e/tests/plugin-datagrid.spec.ts new file mode 100644 index 000000000..1ce2d21f0 --- /dev/null +++ b/e2e/tests/plugin-datagrid.spec.ts @@ -0,0 +1,116 @@ +import { expect, test } from '@playwright/test' + +test.describe.configure({ mode: 'serial' }) + +const ADD_ROW_LABEL = 'Add data row' +const CLEAR_TABLE_LABEL = 'Clear table content' +const DEFAULT_EXAMPLE_PAGE = + 'http://localhost:3000/view/?documentId=dmss://DemoDataSource/$Default' +const DEFAULT_EXAMPLE_CONTENT_AREA = 'enabled:dmss://DemoDataSource/$Default' +const NUMERIC_EXAMPLE_PAGE = + 'http://localhost:3000/view/?documentId=dmss://DemoDataSource/$Numeric' +const NUMERIC_EXAMPLE_CONTENT_AREA = 'enabled:dmss://DemoDataSource/$Numeric' + +test('Unknown dimensions', async ({ page }) => { + await page.goto(DEFAULT_EXAMPLE_PAGE) + const contentArea = page.getByTestId(DEFAULT_EXAMPLE_CONTENT_AREA) + const table = contentArea.getByRole('table') + + await expect(contentArea.getByLabel(ADD_ROW_LABEL)).toBeVisible() + await expect(table.getByRole('textbox').first()).toHaveValue('Dodge') + await table.getByRole('textbox').first().fill('Not Dodge') + await expect(table.getByRole('textbox').first()).toHaveValue('Not Dodge') +}) + +test('Set dimensions', async ({ page }) => { + await page.goto(DEFAULT_EXAMPLE_PAGE) + await page + .getByRole('button', { name: 'Set dimensions', exact: true }) + .click() + const contentArea = page.getByTestId(DEFAULT_EXAMPLE_CONTENT_AREA) + const table = contentArea.getByRole('table') + + await expect(contentArea.getByLabel(ADD_ROW_LABEL)).toBeHidden() + await expect(table.getByRole('textbox').nth(16)).toHaveValue('Ford') +}) + +test('Vertical (Set dimensions)', async ({ page }) => { + await page.goto(DEFAULT_EXAMPLE_PAGE) + await page + .getByRole('button', { name: 'Vertical (Set dimensions)', exact: true }) + .click() + const contentArea = page.getByTestId(DEFAULT_EXAMPLE_CONTENT_AREA) + const table = contentArea.getByRole('table') + + await expect(contentArea.getByLabel(ADD_ROW_LABEL)).toBeHidden() + await expect(table.getByRole('textbox').nth(4)).toHaveValue('Ford') + await expect(table.getByRole('textbox').nth(15)).toHaveValue( + '1D3MX48D48B28FPJU' + ) +}) + +test('Vertical (Unknown dimensions)', async ({ page }) => { + await page.goto(DEFAULT_EXAMPLE_PAGE) + await page + .getByRole('button', { name: 'Vertical (Unknown dimensions)', exact: true }) + .click() + const contentArea = page.getByTestId(DEFAULT_EXAMPLE_CONTENT_AREA) + const table = contentArea.getByRole('table') + + await expect(contentArea.getByLabel(ADD_ROW_LABEL)).toBeVisible() + await expect(table.getByRole('textbox').nth(4)).toHaveValue('Ford') + await expect(table.getByRole('textbox').nth(10)).toHaveValue( + 'Extended Cab Pickup' + ) +}) + +test('Custom labels', async ({ page }) => { + await page.goto(DEFAULT_EXAMPLE_PAGE) + await page.getByRole('button', { name: 'Custom labels', exact: true }).click() + const contentArea = page.getByTestId(DEFAULT_EXAMPLE_CONTENT_AREA) + const table = contentArea.getByRole('table') + + await expect(contentArea.getByLabel(ADD_ROW_LABEL)).toBeHidden() + await expect(table.getByText('John')).toBeVisible() + await expect(table.getByText('Manufacturer')).toBeVisible() +}) + +test('Hidden labels', async ({ page }) => { + await page.goto(DEFAULT_EXAMPLE_PAGE) + await page.getByRole('button', { name: 'Hidden labels', exact: true }).click() + const contentArea = page.getByTestId(DEFAULT_EXAMPLE_CONTENT_AREA) + const table = contentArea.getByRole('table') + + await expect(table.getByText('A', { exact: true })).toBeHidden() + await expect(table.getByText('2', { exact: true })).toBeHidden() +}) + +test('No-edit columns and rows', async ({ page }) => { + await page.goto(DEFAULT_EXAMPLE_PAGE) + await page + .getByRole('button', { name: 'No-edit columns and rows', exact: true }) + .click() + const contentArea = page.getByTestId(DEFAULT_EXAMPLE_CONTENT_AREA) + await expect(contentArea.getByLabel(ADD_ROW_LABEL)).toBeHidden() +}) + +test('Non-editable', async ({ page }) => { + await page.goto(DEFAULT_EXAMPLE_PAGE) + await page.getByRole('button', { name: 'Non-editable', exact: true }).click() + const contentArea = page.getByTestId(DEFAULT_EXAMPLE_CONTENT_AREA) + const table = contentArea.getByRole('table') + await expect(contentArea.getByLabel(ADD_ROW_LABEL)).toBeHidden() + await expect(contentArea.getByLabel(CLEAR_TABLE_LABEL)).toBeHidden() + await expect(table.getByRole('textbox').first()).toHaveValue('Dodge') + await expect(table.getByRole('textbox').first()).toHaveAttribute('readonly') +}) + +test('Integer is number input in data grid', async ({ page }) => { + await page.goto(NUMERIC_EXAMPLE_PAGE) + const contentArea = page.getByTestId(NUMERIC_EXAMPLE_CONTENT_AREA) + await expect(contentArea).toBeVisible() + const table = contentArea.getByRole('table') + await expect(table).toBeVisible() + await expect(table.locator('input').first()).toHaveValue('1000') + await expect(table.locator('input').first()).toHaveAttribute('type', 'number') +}) diff --git a/example/app/data/DemoDataSource/plugins/data_grid/numeric/blueprints/Numeric.blueprint.json b/example/app/data/DemoDataSource/plugins/data_grid/numeric/blueprints/Numeric.blueprint.json new file mode 100644 index 000000000..aea14ba71 --- /dev/null +++ b/example/app/data/DemoDataSource/plugins/data_grid/numeric/blueprints/Numeric.blueprint.json @@ -0,0 +1,22 @@ +{ + "name": "Numeric", + "type": "CORE:Blueprint", + "attributes": [ + { + "name": "type", + "type": "dmss://system/SIMOS/BlueprintAttribute", + "attributeType": "string" + }, + { + "name": "name", + "type": "dmss://system/SIMOS/BlueprintAttribute", + "attributeType": "string" + }, + { + "name": "data", + "type": "CORE:BlueprintAttribute", + "attributeType": "integer", + "dimensions": "*,*" + } + ] +} diff --git a/example/app/data/DemoDataSource/plugins/data_grid/numeric/numeric.entity.json b/example/app/data/DemoDataSource/plugins/data_grid/numeric/numeric.entity.json new file mode 100644 index 000000000..c17946553 --- /dev/null +++ b/example/app/data/DemoDataSource/plugins/data_grid/numeric/numeric.entity.json @@ -0,0 +1,11 @@ +{ + "_id": "Numeric", + "name": "Numeric", + "type": "./blueprints/Numeric", + "data": [ + [1000, 2000, 4000, 8000], + [1000, 2000, 3000, 5000], + [1000, 2000, 3000, 4000], + [999, 888, 666, 555] + ] +} diff --git a/example/app/data/DemoDataSource/recipes/plugins/data_grid/numeric/numeric.recipe.json b/example/app/data/DemoDataSource/recipes/plugins/data_grid/numeric/numeric.recipe.json new file mode 100644 index 000000000..02f54bb0f --- /dev/null +++ b/example/app/data/DemoDataSource/recipes/plugins/data_grid/numeric/numeric.recipe.json @@ -0,0 +1,32 @@ +{ + "type": "CORE:RecipeLink", + "_blueprintPath_": "/plugins/data_grid/numeric/blueprints/Numeric", + "initialUiRecipe": { + "name": "ViewSelector", + "type": "CORE:UiRecipe", + "config": { + "type": "PLUGINS:dm-core-plugins/view_selector/ViewSelectorConfig", + "items": [ + { + "type": "PLUGINS:dm-core-plugins/view_selector/ViewSelectorItem", + "label": "Numeric", + "viewConfig": { + "type": "CORE:InlineRecipeViewConfig", + "recipe": { + "name": "Numeric", + "type": "CORE:UiRecipe", + "description": "Single multidimensional primitive", + "config": { + "type": "PLUGINS:dm-core-plugins/data_grid/DataGridPluginConfig", + "fieldNames": ["data"] + }, + "plugin": "@development-framework/dm-core-plugins/data_grid" + }, + "scope": "self" + } + } + ] + }, + "plugin": "@development-framework/dm-core-plugins/view_selector/tabs" + } +} diff --git a/packages/dm-core-plugins/blueprints/data_grid/DataGridPluginConfig.json b/packages/dm-core-plugins/blueprints/data_grid/DataGridPluginConfig.json index 20a2b9028..f0e0aeaee 100644 --- a/packages/dm-core-plugins/blueprints/data_grid/DataGridPluginConfig.json +++ b/packages/dm-core-plugins/blueprints/data_grid/DataGridPluginConfig.json @@ -52,7 +52,7 @@ { "name": "columnLabels", "type": "CORE:BlueprintAttribute", - "description": "Define column labels or use predefined columns. Predefined values are ABC, ZYX, 123 and you can select those by using the spread operator ['...ABC']. You can also merge the two like this: ['custom field', 'custom field2', '...ABC']", + "description": "Define column labels or use predefined columns. Predefined values are ABC, ZYX, 123 and you can select those by using the spread operator ['...ABC'].", "attributeType": "string", "default": ["...ABC"], "dimensions": "*", @@ -72,17 +72,10 @@ "default": true, "optional": true }, - { - "name": "movableRows", - "type": "CORE:BlueprintAttribute", - "attributeType": "boolean", - "default": true, - "optional": true - }, { "name": "rowLabels", "type": "CORE:BlueprintAttribute", - "description": "Define row labels or use predefined rows. Predefined values are ABC, ZYX, 123and you can select those by using the spread operator ['...ABC']. You can also merge the two like this: ['custom field', 'custom field2', '...ABC']", + "description": "Define row labels or use predefined rows. Predefined values are ABC, ZYX, 123and you can select those by using the spread operator ['...ABC'].", "attributeType": "string", "default": ["...123"], "dimensions": "*", diff --git a/packages/dm-core-plugins/src/data-grid/DataCell/DataCell.tsx b/packages/dm-core-plugins/src/data-grid/DataCell/DataCell.tsx index e9807f056..d4f7f6f80 100644 --- a/packages/dm-core-plugins/src/data-grid/DataCell/DataCell.tsx +++ b/packages/dm-core-plugins/src/data-grid/DataCell/DataCell.tsx @@ -27,6 +27,13 @@ export function DataCell(props: DataCellProps) { ? '-' : Number.parseFloat(value) } + if (attributeType === 'integer') { + return value === '' + ? undefined + : value === '-' + ? '-' + : Number.parseInt(value, 10) + } if (attributeType === 'boolean') { return checked } @@ -62,7 +69,11 @@ export function DataCell(props: DataCellProps) { onChange={(event) => updateValue(event, rowIndex, cellIndex)} attributeType={attributeType} readOnly={!config.editable} - type={attributeType === 'number' ? 'number' : 'text'} + type={ + attributeType === 'number' || attributeType === 'integer' + ? 'number' + : 'text' + } /> )} diff --git a/packages/dm-core-plugins/src/data-grid/DataGrid.tsx b/packages/dm-core-plugins/src/data-grid/DataGrid.tsx index 6103b6dce..38baa214e 100644 --- a/packages/dm-core-plugins/src/data-grid/DataGrid.tsx +++ b/packages/dm-core-plugins/src/data-grid/DataGrid.tsx @@ -1,5 +1,5 @@ import { EdsProvider, Typography } from '@equinor/eds-core-react' -import { useCallback, useEffect, useMemo, useState } from 'react' +import { useMemo, useState } from 'react' import { Stack } from '../common' import { DataCell } from './DataCell/DataCell' import { DataGridActions } from './DataGridActions/DataGridActions' @@ -15,74 +15,57 @@ import { import * as utils from './utils' export function DataGrid(props: DataGridProps) { - const { - data, - attributeType, - dimensions, - setData, - config: userConfig, - isDirty = false, - } = props + const { data, attributeType, dimensions, setData, config: userConfig } = props const config: DataGridConfig = { ...defaultConfig, ...userConfig } - const [columnLabels, setColumnLabels] = useState([]) - const [rowLabels, setRowLabels] = useState([]) const [selectedRow, setSelectedRow] = useState(undefined) const [selectedColumn, setSelectedColumn] = useState( undefined ) const [paginationPage, setPaginationPage] = useState(0) const [rowsPerPage, setRowsPerPage] = useState(props.initialRowsPerPage || 25) - const dataGridId: string = useMemo(() => crypto.randomUUID(), []) - const fillValue = utils.getFillValue(attributeType) - const paginatedRows = data.slice( - paginationPage * rowsPerPage, - paginationPage * rowsPerPage + rowsPerPage - ) - const functionality: TFunctionalityChecks = utils.getFunctionalityVariables( - config, - dimensions + const paginatedRows = useMemo( + () => + data.slice( + paginationPage * rowsPerPage, + paginationPage * rowsPerPage + rowsPerPage + ), + [paginationPage, rowsPerPage, data] ) - - const updateColumnLabels = useCallback( - (length: number) => { - const updatedLabels = utils.createLabels(config.columnLabels, length) - setColumnLabels(updatedLabels) - }, - [config] + const functionality: TFunctionalityChecks = useMemo( + () => utils.getFunctionalityVariables(config, dimensions), + [config, dimensions] ) + const columns = functionality.isMultiDimensional ? data[0] : [0] - const updateRowLabels = useCallback( - (length: number) => { - const updatedLabels = utils.createLabels(config.rowLabels, length) - setRowLabels(updatedLabels) - }, - [config] - ) - - useEffect(() => { - // use isDirty to see if data has been reset from the outside, meaning we have to rerender mount function - if (!isDirty) { - const columnsLength = functionality.isMultiDimensional - ? functionality.columnDimensions === '*' - ? data.length > 0 - ? data[0].length - : 0 - : Number.parseInt(functionality.columnDimensions, 10) - : ['1'] - updateColumnLabels(columnsLength) - updateRowLabels(data?.length) - } - }, [isDirty]) + const [ + columnLabels, + useIndexForColumnLabels, + rowLabels, + useIndexForRowLabels, + ] = useMemo(() => { + const [createdColumnLabels, useIndexForColumnLabels] = utils.createLabels( + config.columnLabels + ) + const [createdRowLabels, useIndexForRowLabels] = utils.createLabels( + config.rowLabels + ) + return [ + createdColumnLabels, + useIndexForColumnLabels, + createdRowLabels, + useIndexForRowLabels, + ] + }, [config.columnLabels, config.rowLabels]) function addRow(newIndex?: number) { + const fillValue = utils.getFillValue(attributeType) const newRow = - columnLabels.length > 1 - ? Array.from({ length: columnLabels.length }).fill(fillValue) + typeof data[0] !== 'string' + ? Array.from({ length: columns.length }).fill(fillValue) : fillValue const dataCopy = [...data] dataCopy.splice(newIndex || data.length, 0, newRow) - updateRowLabels(data.length + 1) setData(dataCopy) } @@ -96,7 +79,8 @@ export function DataGrid(props: DataGridProps) { } function clearTable() { - setData([]) + const fill = utils.getFillValue(attributeType) + setData(functionality.isMultiDimensional ? [[fill]] : [fill]) setSelectedRow(undefined) setSelectedColumn(undefined) setPaginationPage(0) @@ -119,7 +103,6 @@ export function DataGrid(props: DataGridProps) { return item }) setData(updatedData) - updateColumnLabels(columnLabels.length + 1) setSelectedColumn(newIndex) } @@ -128,7 +111,6 @@ export function DataGrid(props: DataGridProps) { item.splice(index, 1) return item }) - updateColumnLabels(columnLabels.length - 1) setData(updatedData) setSelectedColumn(undefined) } @@ -144,15 +126,19 @@ export function DataGrid(props: DataGridProps) { {config.showColumns && ( - {config.showRows && #} - {columnLabels.map((column, index) => ( + {config.showRows && } + {columns?.map((_: string, index: number) => ( void - updateColumnLabels: (length: number) => void - updateRowLabels: (length: number) => void clearTable: () => void } @@ -66,21 +68,49 @@ export function DataGridActions(props: DataGridActionsProps) { const [menuButtonAnchor, setMenuButtonAnchor] = useState(null) + function createLabels(type: 'columns' | 'rows') { + let dataLength = type === 'rows' ? data?.length : 1 + if (type === 'columns' && functionality.isMultiDimensional) { + dataLength = data[0]?.length + } + const labelConfig = + type === 'columns' ? config.columnLabels : config.rowLabels + const labels = type === 'columns' ? columnLabels : rowLabels + const labelsToCopy = labelConfig.includes(PredefinedLabel.NUMERIC) + ? Array.from({ length: dataLength }, (_, i) => `${i + 1}`) + : labels.slice(0, dataLength) + return labelsToCopy + } + function mapData(separator: string) { let dataCopy = window.structuredClone(data) - const columnLabelsCopy = [...columnLabels] - if (includeRowLabels) { - dataCopy.map((item, index) => item.unshift(rowLabels[index])) + + if (includeColumnLabels || includeRowLabels) { + const columnLabels = createLabels('columns') + const rowLabels = createLabels('rows') + if (functionality.isMultiDimensional) { + if (includeColumnLabels) { + dataCopy.unshift(columnLabels) // add column labels + } + if (includeRowLabels) { + if (includeColumnLabels) rowLabels.unshift('') // add an empty labels if column labels are also included + dataCopy.map((data, index) => data.unshift(rowLabels[index])) // add row labels + } + } else { + if (includeColumnLabels) dataCopy.unshift(columnLabels) + if (includeRowLabels) { + if (includeColumnLabels) rowLabels.unshift('') // add an empty labels if column labels are also included + // add row labels before data primitive + dataCopy = dataCopy.map( + (data, index) => `${rowLabels[index]}${separator} ${data}` + ) + } + } } + if (functionality.isMultiDimensional) { dataCopy = dataCopy?.map((line: any[]) => line.join(separator)) } - if (includeColumnLabels) { - if (includeRowLabels) { - columnLabelsCopy.unshift('') - } - dataCopy.unshift(columnLabelsCopy?.join(separator)) - } return dataCopy.join('\n') } @@ -107,7 +137,7 @@ export function DataGridActions(props: DataGridActionsProps) { return ( - {functionality.addButtonIsEnabled && ( + {functionality.addButtonIsEnabled && functionality.rowsAreEditable && ( {functionality.rowsAreEditable && ( - + )} - {functionality.isSortEnabled && ( + {functionality.isSortRowsEnabled && ( <> moveRow('up')} disabled={selectedRow === 0} > moveRow('down')} disabled={selectedRow === props.data?.length - 1} > @@ -146,6 +181,7 @@ export function DataGridActions(props: DataGridActionsProps) { )} setIsMenuOpen(true)} @@ -156,7 +192,10 @@ export function DataGridActions(props: DataGridActionsProps) { {functionality.rowsAreEditable && functionality.addButtonIsEnabled && ( - + @@ -183,8 +222,6 @@ export function DataGridActions(props: DataGridActionsProps) { dimensions={props.dimensions} open={isImportDialogOpen} setData={props.setData} - updateColumnLabels={props.updateColumnLabels} - updateRowLabels={props.updateRowLabels} /> (false) const [errors, setErrors] = useState([]) const [successfullyPasted, setSuccessfullyPasted] = useState(false) @@ -56,10 +49,6 @@ export function DataGridImportDialog(props: DataGridImportDialogProps) { ? [...data, ...parsedData] : parsedData - if (isMultiDimensional) { - updateColumnLabels(updatedData[0].length) - } - updateRowLabels(updatedData.length) setData(updatedData) setIsLoading(false) setSuccessfullyPasted(true) @@ -69,7 +58,10 @@ export function DataGridImportDialog(props: DataGridImportDialogProps) { event.preventDefault() setIsLoading(true) const value = event.clipboardData.getData('text') - const parsedValue = value?.split('\n').map((t: string) => t.split('\t')) + const parsedValue = value + ?.replace('\r', '') + .split('\n') + .map((t: string) => t.split('\t')) handleUpload(parsedValue) } @@ -81,7 +73,8 @@ export function DataGridImportDialog(props: DataGridImportDialogProps) { const text = readerEvent.target?.result const separators = new RegExp(/;|\t/) const parsedValue = String(text) - ?.split('\n') + ?.replace('\r', '') + .split('\n') .map((t: string) => t.split(separators)) handleUpload(parsedValue) } diff --git a/packages/dm-core-plugins/src/data-grid/DataGridActions/DataGridImportDialog/types.ts b/packages/dm-core-plugins/src/data-grid/DataGridActions/DataGridImportDialog/types.ts index 8761c7964..159176fc0 100644 --- a/packages/dm-core-plugins/src/data-grid/DataGridActions/DataGridImportDialog/types.ts +++ b/packages/dm-core-plugins/src/data-grid/DataGridActions/DataGridImportDialog/types.ts @@ -5,6 +5,4 @@ export type DataGridImportDialogProps = { closeModal: () => void open: boolean setData: (data: any[]) => void - updateColumnLabels: (length: number) => void - updateRowLabels: (length: number) => void } diff --git a/packages/dm-core-plugins/src/data-grid/DataGridPlugin.tsx b/packages/dm-core-plugins/src/data-grid/DataGridPlugin.tsx index 28b5df766..7081f6dcb 100644 --- a/packages/dm-core-plugins/src/data-grid/DataGridPlugin.tsx +++ b/packages/dm-core-plugins/src/data-grid/DataGridPlugin.tsx @@ -8,11 +8,16 @@ import { } from '@development-framework/dm-core' import { Button, Icon, Tooltip } from '@equinor/eds-core-react' import { undo } from '@equinor/eds-icons' -import { useEffect, useState } from 'react' +import { useMemo, useState } from 'react' +import { toast } from 'react-toastify' import { Stack } from '../common' import { DataGrid } from './DataGrid' import { type DataGridConfig, defaultConfig } from './types' -import { getFunctionalityVariables, reverseData } from './utils' +import { + getCalculatedDimensions, + parseDataBeforeSave, + reverseData, +} from './utils' export function DataGridPlugin(props: IUIPlugin) { const { idReference, config: userConfig, type, onChange } = props @@ -24,28 +29,21 @@ export function DataGridPlugin(props: IUIPlugin) { const [isDirty, setIsDirty] = useState(false) const { blueprint } = useBlueprint(type) const { document, isLoading } = useDocument(idReference, 1) - const { fieldNames, rowsPerPage } = config + const { fieldNames } = config const multiplePrimitives = fieldNames?.length > 1 - const attribute = blueprint?.attributes?.find( - (atts: TAttribute) => atts.name === fieldNames[0] + const attribute: TAttribute = useMemo( + () => + blueprint?.attributes?.find( + (attr: TAttribute) => attr.name === fieldNames[0] + ), + [blueprint, fieldNames] + ) + const dimensions = useMemo( + () => getCalculatedDimensions(config, attribute), + [config, attribute] ) - function getColumnsLength(data: any[]) { - const dimensions = multiplePrimitives - ? `*,${fieldNames.length}` - : attribute?.dimensions - const functionality = getFunctionalityVariables(config, dimensions) - const columnLength = functionality.isMultiDimensional - ? functionality.columnDimensions === '*' - ? data.length > 0 - ? data[0].length - : 0 - : Number.parseInt(functionality.columnDimensions, 10) - : 1 - return columnLength - } - - useEffect(() => { + useMemo(() => { if (isLoading || !document) return let modifiedData = document?.[fieldNames[0]] || [] if (multiplePrimitives) { @@ -54,7 +52,7 @@ export function DataGridPlugin(props: IUIPlugin) { modifiedData = mergedData } if (config.printDirection === 'vertical') { - modifiedData = reverseData(modifiedData, getColumnsLength(modifiedData)) + modifiedData = reverseData(modifiedData, dimensions) } setData(modifiedData) setInitialData(window.structuredClone(modifiedData)) @@ -65,39 +63,21 @@ export function DataGridPlugin(props: IUIPlugin) { setIsDirty(true) } - function revertChanges() { - setData(window.structuredClone(initialData)) - setIsDirty(false) - } - - function parseDataBeforeSave() { - let modifiedData = data - if (config.printDirection === 'vertical') { - modifiedData = reverseData(data || [], getColumnsLength(data || [])) - } - let dataToSave = { [fieldNames[0]]: modifiedData } - if (multiplePrimitives && data?.length) { - dataToSave = Object.fromEntries( - (modifiedData || []).map((value, index) => [fieldNames[index], value]) - ) - } - return dataToSave - } - function updateForm() { - if (onChange) onChange(parseDataBeforeSave()) + if (onChange) onChange(parseDataBeforeSave(data, config, dimensions)) setIsDirty(false) } async function saveDocument() { setLoading(true) try { - const dataToSave = parseDataBeforeSave() + const dataToSave = parseDataBeforeSave(data, config, dimensions) const payload = { ...document, ...dataToSave } await dmssAPI.documentUpdate({ idAddress: idReference, data: JSON.stringify(payload), }) + toast.success('Updated document!') setInitialData(window.structuredClone(data)) setIsDirty(false) } catch (error) { @@ -109,30 +89,16 @@ export function DataGridPlugin(props: IUIPlugin) { } } - function getDimensions() { - if (multiplePrimitives) { - return config.printDirection === 'vertical' - ? `${fieldNames.length},*` - : `*,${fieldNames.length}` - } - if (config.printDirection === 'vertical') { - const reversed = attribute?.dimensions.split('').reverse().join('') - return reversed - } - return attribute?.dimensions - } - return !data ? null : (