diff --git a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/CellRenderer/CellRenderer.tsx b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/CellRenderer/CellRenderer.tsx index eb5537ec68..f81238bc49 100644 --- a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/CellRenderer/CellRenderer.tsx +++ b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/CellRenderer/CellRenderer.tsx @@ -103,7 +103,10 @@ export const CellRenderer = observer): boolean { - if (!cellContext.cell) { + if ( + !cellContext.cell || + (!dataGridContext.model.hasElementIdentifier(tableDataContext.view.resultIndex) && cellContext.editionState !== DatabaseEditChangeType.add) + ) { return false; } diff --git a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridContextMenu/DataGridContextMenuCellEditingService.ts b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridContextMenu/DataGridContextMenuCellEditingService.ts index a4d7a03f5b..a056c6c35d 100644 --- a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridContextMenu/DataGridContextMenuCellEditingService.ts +++ b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridContextMenu/DataGridContextMenuCellEditingService.ts @@ -86,9 +86,11 @@ export class DataGridContextMenuCellEditingService { const isComplex = format.isBinary(key) || format.isGeometry(key); const isTruncated = content.isTextTruncated(key); const selectedElements = select?.getSelectedElements() || []; + // we can't edit table cells if table doesn't have row identifier, but we can edit new created rows before insert (CB-6063) + const canEdit = model.hasElementIdentifier(resultIndex) || editor.getElementState(key) === DatabaseEditChangeType.add; if (action === ACTION_EDIT) { - if (!column || cellValue === undefined || format.isReadOnly(key) || isComplex || isTruncated) { + if (!column || cellValue === undefined || format.isReadOnly(key) || isComplex || isTruncated || !canEdit) { return false; } @@ -96,7 +98,7 @@ export class DataGridContextMenuCellEditingService { } if (action === ACTION_DATA_GRID_EDITING_SET_TO_NULL) { - return cellValue !== undefined && !format.isReadOnly(key) && !view.getColumn(key.column)?.required && !format.isNull(key); + return cellValue !== undefined && !format.isReadOnly(key) && !view.getColumn(key.column)?.required && !format.isNull(key) && canEdit; } if (action === ACTION_DATA_GRID_EDITING_ADD_ROW || action === ACTION_DATA_GRID_EDITING_DUPLICATE_ROW) { @@ -104,11 +106,11 @@ export class DataGridContextMenuCellEditingService { } if (action === ACTION_DATA_GRID_EDITING_DELETE_ROW) { - return !format.isReadOnly(key) && editor.getElementState(key) !== DatabaseEditChangeType.delete; + return !format.isReadOnly(key) && canEdit && editor.getElementState(key) !== DatabaseEditChangeType.delete; } if (action === ACTION_DATA_GRID_EDITING_DELETE_SELECTED_ROW) { - if (model.isReadonly(resultIndex) || !editor.hasFeature('delete')) { + if (model.isReadonly(resultIndex) || !canEdit || !editor.hasFeature('delete')) { return false; } diff --git a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridTable.tsx b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridTable.tsx index da7b068bdb..919a256102 100644 --- a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridTable.tsx +++ b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridTable.tsx @@ -222,12 +222,14 @@ export const DataGridTable = observer(function DataGridT function handleKeyDown(event: React.KeyboardEvent) { gridSelectedCellCopy.onKeydownHandler(event); + const cell = selectionAction.getFocusedElement(); + // we can't edit table cells if table doesn't have row identifier, but we can edit new created rows before insert (CB-6063) + const canEdit = model.hasElementIdentifier(resultIndex) || !!(cell && tableData.editor.getElementState(cell) === DatabaseEditChangeType.add); - if (EventContext.has(event, EventStopPropagationFlag) || tableData.isReadOnly() || model.isReadonly(resultIndex)) { + if (EventContext.has(event, EventStopPropagationFlag) || !canEdit || tableData.isReadOnly() || model.isReadonly(resultIndex)) { return; } - const cell = selectionAction.getFocusedElement(); const activeElements = selectionAction.getActiveElements(); const activeRows = selectionAction.getActiveRows(); diff --git a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/TableColumnHeader/TableIndexColumnHeader.tsx b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/TableColumnHeader/TableIndexColumnHeader.tsx index d6ef14007c..0d016feb71 100644 --- a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/TableColumnHeader/TableIndexColumnHeader.tsx +++ b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/TableColumnHeader/TableIndexColumnHeader.tsx @@ -27,7 +27,12 @@ export const TableIndexColumnHeader = observer>(funct throw new Error('Contexts required'); } - const readonly = getComputed(() => tableDataContext.isReadOnly() || dataGridContext.model.isReadonly(dataGridContext.resultIndex)); + const readonly = getComputed( + () => + tableDataContext.isReadOnly() || + dataGridContext.model.isReadonly(dataGridContext.resultIndex) || + !dataGridContext.model.hasElementIdentifier(dataGridContext.resultIndex), + ); function handleClick(event: React.MouseEvent) { selectionContext.selectTable(); diff --git a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/DatabaseDataModel.ts b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/DatabaseDataModel.ts index eadfee8830..1b101f2cf8 100644 --- a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/DatabaseDataModel.ts +++ b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/DatabaseDataModel.ts @@ -59,6 +59,10 @@ export class DatabaseDataModel = I return this.source.isReadonly(resultIndex); } + hasElementIdentifier(resultIndex: number): boolean { + return this.source.hasElementIdentifier(resultIndex); + } + isDataAvailable(offset: number, count: number): boolean { return this.source.isDataAvailable(offset, count); } diff --git a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/DatabaseDataSource.ts b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/DatabaseDataSource.ts index aed18b399f..5490880853 100644 --- a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/DatabaseDataSource.ts +++ b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/DatabaseDataSource.ts @@ -206,6 +206,10 @@ export abstract class DatabaseDataSource 1 || this.disabled; } diff --git a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/IDatabaseDataModel.ts b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/IDatabaseDataModel.ts index 5557d1b31a..1ecb50bb1e 100644 --- a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/IDatabaseDataModel.ts +++ b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/IDatabaseDataModel.ts @@ -31,6 +31,7 @@ export interface IDatabaseDataModel this; isReadonly: (resultIndex: number) => boolean; + hasElementIdentifier: (resultIndex: number) => boolean; isDisabled: (resultIndex?: number) => boolean; isLoading: () => boolean; isDataAvailable: (offset: number, count: number) => boolean; diff --git a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/IDatabaseDataSource.ts b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/IDatabaseDataSource.ts index a8705f3605..cbd4fc739c 100644 --- a/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/IDatabaseDataSource.ts +++ b/webapp/packages/plugin-data-viewer/src/DatabaseDataModel/IDatabaseDataSource.ts @@ -71,6 +71,7 @@ export interface IDatabaseDataSource boolean; isLoadable: () => boolean; isReadonly: (resultIndex: number) => boolean; + hasElementIdentifier: (resultIndex: number) => boolean; isDataAvailable: (offset: number, count: number) => boolean; isLoading: () => boolean; isDisabled: (resultIndex?: number) => boolean; diff --git a/webapp/packages/plugin-data-viewer/src/ResultSet/ResultSetDataSource.ts b/webapp/packages/plugin-data-viewer/src/ResultSet/ResultSetDataSource.ts index 3aa856dbf2..4a70da9867 100644 --- a/webapp/packages/plugin-data-viewer/src/ResultSet/ResultSetDataSource.ts +++ b/webapp/packages/plugin-data-viewer/src/ResultSet/ResultSetDataSource.ts @@ -39,7 +39,7 @@ export abstract class ResultSetDataSource exten } override isReadonly(resultIndex: number): boolean { - return super.isReadonly(resultIndex) || !this.executionContext?.context || this.getResult(resultIndex)?.data?.hasRowIdentifier === false; + return super.isReadonly(resultIndex) || !this.executionContext?.context; } override async cancel(): Promise { diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TableFooterMenu/TableFooterMenuService.ts b/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TableFooterMenu/TableFooterMenuService.ts index d2820b630b..1a4fb798dd 100644 --- a/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TableFooterMenu/TableFooterMenuService.ts +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TableFooterMenu/TableFooterMenuService.ts @@ -101,13 +101,16 @@ export class TableFooterMenuService { } case ACTION_DELETE: { const editor = model.source.getActionImplementation(resultIndex, DatabaseEditAction); + const selectedElements = getActiveElements(model, resultIndex); - if (!editor) { + // we can't edit table cells if table doesn't have row identifier, but we can edit new created rows before insert (CB-6063) + const canEdit = + model.hasElementIdentifier(resultIndex) || selectedElements.every(key => editor?.getElementState(key) === DatabaseEditChangeType.add); + + if (!editor || !canEdit) { return true; } - const selectedElements = getActiveElements(model, resultIndex); - return selectedElements.length === 0 || !selectedElements.some(key => editor.getElementState(key) !== DatabaseEditChangeType.delete); } case ACTION_REVERT: { diff --git a/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/BooleanValue/BooleanValuePresentation.tsx b/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/BooleanValue/BooleanValuePresentation.tsx index eeba7b5a7b..17f70f82d6 100644 --- a/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/BooleanValue/BooleanValuePresentation.tsx +++ b/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/BooleanValue/BooleanValuePresentation.tsx @@ -51,7 +51,11 @@ export const BooleanValuePresentation: TabContainerPanelComponent diff --git a/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/TextValue/isTextValueReadonly.ts b/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/TextValue/isTextValueReadonly.ts index a927689d4a..b1ad216ad1 100644 --- a/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/TextValue/isTextValueReadonly.ts +++ b/webapp/packages/plugin-data-viewer/src/ValuePanelPresentation/TextValue/isTextValueReadonly.ts @@ -30,6 +30,7 @@ export function isTextValueReadonly({ contentAction, formatAction, model, result formatAction.isGeometry(cell) || contentAction.isTextTruncated(cell) || model.isReadonly(resultIndex) || - model.isDisabled(resultIndex) + model.isDisabled(resultIndex) || + !model.hasElementIdentifier(resultIndex) ); } diff --git a/webapp/packages/plugin-sql-generator/src/GeneratorMenuBootstrap.ts b/webapp/packages/plugin-sql-generator/src/GeneratorMenuBootstrap.ts index d2f1031429..d2d1e3482f 100644 --- a/webapp/packages/plugin-sql-generator/src/GeneratorMenuBootstrap.ts +++ b/webapp/packages/plugin-sql-generator/src/GeneratorMenuBootstrap.ts @@ -43,6 +43,7 @@ export class GeneratorMenuBootstrap extends Bootstrap { const presentation = context.get(DATA_CONTEXT_DV_PRESENTATION); return ( !model.isReadonly(resultIndex) && + model.hasElementIdentifier(resultIndex) && model.source.getResult(resultIndex)?.dataFormat === ResultDataFormat.Resultset && !presentation?.readonly && (!presentation || presentation.type === DataViewerPresentationType.Data)