From 7afbc8ec028722b3f01d0f696754566fd3925b6e Mon Sep 17 00:00:00 2001 From: Naumov Alexey Date: Mon, 5 Apr 2021 14:05:33 +0300 Subject: [PATCH] fix(plugin-data-spreadsheet-new): CB-743 don't copy null values to clipboard --- .../DataGrid/CellRenderer/CellRenderer.tsx | 8 +++- .../src/DataGrid/DataGridTable.tsx | 3 +- .../src/DataGrid/useGridSelectedCellsCopy.ts | 40 +++++++++++-------- .../src/styles/themes/_base-react-grid.scss | 8 +++- 4 files changed, 38 insertions(+), 21 deletions(-) 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 5778bceec0..1c3a726840 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 @@ -30,7 +30,13 @@ export const CellRenderer: React.FC> = observer(function const { rowIdx, column } = props; if (selectionContext?.isSelected(rowIdx, column.idx)) { - classes.push('rdg-cell-custom-selected'); + const columnIndex = tableDataContext?.getDataColumnIndexFromKey(column.key) ?? null; + + if (columnIndex !== null && editor?.getCell(rowIdx, columnIndex) === null) { + classes.push('rdg-cell-custom-null-selected'); + } else { + classes.push('rdg-cell-custom-selected'); + } } if (editingContext?.isEditing({ idx: column.idx, rowIdx })) { 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 95488c2ed6..5b74accbd6 100644 --- a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridTable.tsx +++ b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridTable.tsx @@ -51,7 +51,6 @@ export const DataGridTable: React.FC = observer(function DataGridTable({ const [columnResize] = useState(() => new Executor()); const selectionAction = model.source.getAction(resultIndex, ResultSetSelectAction); - const modelResultData = model.getResult(resultIndex); const tableData = useTableData(model, resultIndex); @@ -78,7 +77,7 @@ export const DataGridTable: React.FC = observer(function DataGridTable({ }, }); - const { onKeydownHandler } = useGridSelectedCellsCopy(modelResultData, gridSelectionContext); + const { onKeydownHandler } = useGridSelectedCellsCopy(model, resultIndex, gridSelectionContext); const { onMouseDownHandler, onMouseMoveHandler } = useGridDragging({ onDragStart: startPosition => { dataGridRef.current?.selectCell({ idx: startPosition.colIdx, rowIdx: startPosition.rowIdx }); diff --git a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/useGridSelectedCellsCopy.ts b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/useGridSelectedCellsCopy.ts index 4314ed4c6d..217007e541 100644 --- a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/useGridSelectedCellsCopy.ts +++ b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/useGridSelectedCellsCopy.ts @@ -9,9 +9,8 @@ import { useCallback } from 'react'; import { useObjectRef } from '@cloudbeaver/core-blocks'; -import type { SqlResultSet } from '@cloudbeaver/core-sdk'; import { copyToClipboard } from '@cloudbeaver/core-utils'; -import type { IDatabaseDataResult } from '@cloudbeaver/plugin-data-viewer'; +import { IDatabaseDataModel, IDatabaseResultSet, ResultSetFormatAction } from '@cloudbeaver/plugin-data-viewer'; import type { IDataGridSelectionContext } from './DataGridSelection/DataGridSelectionContext'; @@ -19,11 +18,12 @@ const EVENT_KEY_CODE = { C: 'KeyC', }; -function copyGridSelectedDataToClipboard(modelData: SqlResultSet, selectedCells: Map) { - if (!modelData.rows) { - return; - } - +function copyGridSelectedDataToClipboard( + model: IDatabaseDataModel, + resultIndex: number, + selectedCells: Map +) { + const format = model.source.getAction(resultIndex, ResultSetFormatAction); const orderedSelectedCells: Map = new Map([...selectedCells].sort((a, b) => a[0] - b[0])); const selectedColumns: Set = new Set(); @@ -34,7 +34,7 @@ function copyGridSelectedDataToClipboard(modelData: SqlResultSet, selectedCells: } } - const columns = [...selectedColumns].sort(); + const columns = [...selectedColumns].sort((a, b) => a - b); let data = ''; for (const [rowIdx, colIndexes] of orderedSelectedCells) { @@ -44,8 +44,12 @@ function copyGridSelectedDataToClipboard(modelData: SqlResultSet, selectedCells: } if (colIndexes.includes(column)) { - const value = modelData.rows?.[rowIdx][column]; - data += value; + const cell = model.source.getEditor(resultIndex).getCell(rowIdx, column); + const cellValue = format.get(cell); + if (cellValue === null) { + continue; + } + data += cellValue; } } data += '\r\n'; @@ -58,17 +62,19 @@ function copyGridSelectedDataToClipboard(modelData: SqlResultSet, selectedCells: type IKeyboardEvent = React.KeyboardEvent & KeyboardEvent; export function useGridSelectedCellsCopy( - modelResultData: IDatabaseDataResult | null, + model: IDatabaseDataModel, + resultIndex: number, selectionContext: IDataGridSelectionContext ) { - const props = useObjectRef({ modelResultData, selectionContext }); - const onKeydownHandler = useCallback((event: IKeyboardEvent) => { - if (!props.modelResultData) { - return; - } + const props = useObjectRef({ model, resultIndex, selectionContext }); + const onKeydownHandler = useCallback((event: IKeyboardEvent) => { if ((event.ctrlKey || event.metaKey) && event.code === EVENT_KEY_CODE.C) { - copyGridSelectedDataToClipboard(props.modelResultData.data, props.selectionContext.selectedCells); + copyGridSelectedDataToClipboard( + props.model, + props.resultIndex, + props.selectionContext.selectedCells + ); } }, []); diff --git a/webapp/packages/plugin-data-spreadsheet-new/src/styles/themes/_base-react-grid.scss b/webapp/packages/plugin-data-spreadsheet-new/src/styles/themes/_base-react-grid.scss index 52afbbd717..56491db925 100644 --- a/webapp/packages/plugin-data-spreadsheet-new/src/styles/themes/_base-react-grid.scss +++ b/webapp/packages/plugin-data-spreadsheet-new/src/styles/themes/_base-react-grid.scss @@ -16,9 +16,14 @@ $edited-color: #ff99006b; .rdg-cell-custom-selected:not(.rdg-cell-custom-editing) { background-color: rgba(0, 145, 234, 0.3); } + .rdg-cell-custom-null-selected:not(.rdg-cell-custom-editing) { + background-color: rgba(0, 145, 234, 0.1); + } + .rdg-cell-selected { box-shadow: inset 0 0 0 1px #0091ea; } + .rdg-cell-custom-editing { box-shadow: none; } @@ -56,7 +61,8 @@ $edited-color: #ff99006b; @include mdc-theme-prop(background-color, surface, false); } - .rdg-cell-custom-selected { + .rdg-cell-custom-selected, + .rdg-cell-custom-null-selected { background-color: rgba(150, 150, 150, 0.3); box-shadow: none; }