mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
Merge pull request #411 from dbeaver/feat/boolean-toggle
This commit is contained in:
+5
-2
@@ -17,6 +17,7 @@ import { ResultSetFormatAction } from '@cloudbeaver/plugin-data-viewer';
|
||||
import { EditingContext } from '../../Editing/EditingContext';
|
||||
import { DataGridContext } from '../DataGridContext';
|
||||
import { DataGridSelectionContext } from '../DataGridSelection/DataGridSelectionContext';
|
||||
import { isBooleanFormatterAvailable } from '../Formatters/CellFormatters/isBooleanFormatterAvailable';
|
||||
import { TableDataContext } from '../TableDataContext';
|
||||
import { CellContext, ICellContext } from './CellContext';
|
||||
|
||||
@@ -79,7 +80,9 @@ export const CellRenderer: React.FC<CellRendererProps<any>> = observer(function
|
||||
}, [column, rowIdx, selectionContext, dataGridContext]);
|
||||
|
||||
const handleDoubleClick = useCallback(() => {
|
||||
if (!column.editable || resultColumn?.dataKind?.toLowerCase() === 'boolean') {
|
||||
if (!column.editable || (
|
||||
resultColumn && isBooleanFormatterAvailable(editor?.getCell(rowIdx, Number(column.key)), resultColumn)
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
const format = dataGridContext?.model.source.getAction(dataGridContext.resultIndex, ResultSetFormatAction);
|
||||
@@ -96,7 +99,7 @@ export const CellRenderer: React.FC<CellRendererProps<any>> = observer(function
|
||||
}
|
||||
|
||||
editingContext?.edit({ idx: column.idx, rowIdx });
|
||||
}, [column, rowIdx, props.row]);
|
||||
}, [column, rowIdx, props.row, editor, resultColumn]);
|
||||
|
||||
const row = editor?.get(rowIdx) || props.row;
|
||||
|
||||
|
||||
+4
-1
@@ -9,6 +9,7 @@
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
import { ResultSetDataAction, ResultSetFormatAction } from '@cloudbeaver/plugin-data-viewer';
|
||||
|
||||
import { isBooleanFormatterAvailable } from '../Formatters/CellFormatters/isBooleanFormatterAvailable';
|
||||
import { DataGridContextMenuService } from './DataGridContextMenuService';
|
||||
|
||||
@injectable()
|
||||
@@ -50,13 +51,15 @@ export class DataGridContextMenuCellEditingService {
|
||||
},
|
||||
isHidden(context) {
|
||||
const data = context.data.model.source.getAction(context.data.resultIndex, ResultSetDataAction);
|
||||
const editor = context.data.model.source.getEditor(context.data.resultIndex);
|
||||
const cellValue = editor.getCell(context.data.row, context.data.column);
|
||||
const column = data.getColumn(context.data.column);
|
||||
|
||||
if (!column) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return column.dataKind?.toLowerCase() === 'boolean';
|
||||
return isBooleanFormatterAvailable(cellValue, column);
|
||||
},
|
||||
order: 0,
|
||||
title: 'data_grid_table_editing_open_inline_editor',
|
||||
|
||||
+14
-4
@@ -6,28 +6,38 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { useContext } from 'react';
|
||||
import { useContext, useRef } from 'react';
|
||||
import type { FormatterProps } from 'react-data-grid';
|
||||
|
||||
import { ResultSetFormatAction } from '@cloudbeaver/plugin-data-viewer';
|
||||
|
||||
import { EditingContext } from '../../Editing/EditingContext';
|
||||
import { DataGridContext } from '../DataGridContext';
|
||||
import { TableDataContext } from '../TableDataContext';
|
||||
import { BooleanFormatter } from './CellFormatters/BooleanFormatter';
|
||||
import { isBooleanFormatterAvailable } from './CellFormatters/isBooleanFormatterAvailable';
|
||||
import { TextFormatter } from './CellFormatters/TextFormatter';
|
||||
|
||||
export const CellFormatterFactory: React.FC<FormatterProps> = function CellFormatterFactory(props) {
|
||||
const formatterRef = useRef<React.FC<FormatterProps> | null>(null);
|
||||
const context = useContext(DataGridContext);
|
||||
const tableDataContext = useContext(TableDataContext);
|
||||
const formatter = context?.model.source.getAction(context.resultIndex, ResultSetFormatAction);
|
||||
const editingContext = useContext(EditingContext);
|
||||
const isEditing = editingContext?.isEditing({ idx: props.column.idx, rowIdx: props.rowIdx });
|
||||
|
||||
const resultColumn = tableDataContext?.getColumnInfo(props.column.key);
|
||||
const rawValue = formatter?.get(props.row[props.column.key]) ?? props.row[props.column.key];
|
||||
|
||||
let Formatter: React.FC<FormatterProps> = TextFormatter;
|
||||
if (!isEditing || formatterRef === null) {
|
||||
formatterRef.current = TextFormatter;
|
||||
|
||||
if (resultColumn?.dataKind?.toLowerCase() === 'boolean' && (typeof rawValue === 'boolean' || formatter?.isNull(rawValue))) {
|
||||
Formatter = BooleanFormatter;
|
||||
if (resultColumn && isBooleanFormatterAvailable(rawValue, resultColumn)) {
|
||||
formatterRef.current = BooleanFormatter;
|
||||
}
|
||||
}
|
||||
|
||||
const Formatter = formatterRef.current!;
|
||||
|
||||
return <Formatter {...props} />;
|
||||
};
|
||||
|
||||
+6
-5
@@ -42,8 +42,9 @@ export const BooleanFormatter: React.FC<FormatterProps> = observer(function Bool
|
||||
const formatter = context?.model.source.getAction(context.resultIndex, ResultSetFormatAction);
|
||||
const resultColumn = tableDataContext?.getColumnInfo(column.key);
|
||||
const rawValue = formatter?.get(row[column.key]) ?? row[column.key];
|
||||
const stringifiedValue = formatter?.toDisplayString(rawValue) ?? String(rawValue);
|
||||
const value = rawValue === null ? stringifiedValue : `[${rawValue ? 'v' : ' '}]`;
|
||||
const value = typeof rawValue === 'string' ? rawValue.toLowerCase() === 'true' : rawValue;
|
||||
const stringifiedValue = formatter?.toDisplayString(value) ?? String(value);
|
||||
const valueRepresentation = value === null ? stringifiedValue : `[${value ? 'v' : ' '}]`;
|
||||
const classes = getClasses(rawValue);
|
||||
|
||||
const getNextValue = useCallback((prev: boolean | null) => {
|
||||
@@ -60,10 +61,10 @@ export const BooleanFormatter: React.FC<FormatterProps> = observer(function Bool
|
||||
as='span'
|
||||
title={stringifiedValue}
|
||||
onClick={() => context?.model.source.getEditor(context.resultIndex)
|
||||
.setCell(rowIdx, Number(column.key), getNextValue(rawValue))}
|
||||
{...use({ boolean: rawValue !== null })}
|
||||
.setCell(rowIdx, Number(column.key), getNextValue(value))}
|
||||
{...use({ boolean: value !== null })}
|
||||
>
|
||||
{value}
|
||||
{valueRepresentation}
|
||||
</boolean-formatter>
|
||||
);
|
||||
});
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import type { SqlResultColumn } from '@cloudbeaver/core-sdk';
|
||||
import type { IResultSetValue } from '@cloudbeaver/plugin-data-viewer';
|
||||
|
||||
export function isBooleanFormatterAvailable(cellValue: IResultSetValue, column: SqlResultColumn): boolean {
|
||||
return column?.dataKind?.toLowerCase() === 'boolean'
|
||||
&& (
|
||||
typeof cellValue === 'boolean'
|
||||
|| cellValue === null
|
||||
|| (typeof cellValue === 'string' && ['false', 'true'].includes(cellValue.toLowerCase()))
|
||||
);
|
||||
}
|
||||
@@ -299,6 +299,10 @@ export class DatabaseDataEditor<TResult extends IDatabaseDataResult> implements
|
||||
return String(valueA) === String(valueB);
|
||||
}
|
||||
|
||||
if (typeof valueA === 'boolean' || typeof valueB === 'boolean') {
|
||||
return String(valueA).toLowerCase() === String(valueB).toLowerCase();
|
||||
}
|
||||
|
||||
if (isResultSetContentValue(valueA) && isResultSetContentValue(valueB)) {
|
||||
if ('text' in valueA && 'text' in valueB) {
|
||||
return valueA.text === valueB.text;
|
||||
|
||||
+1
-4
@@ -17,7 +17,6 @@ import { CodeEditorLoader } from '@cloudbeaver/plugin-codemirror';
|
||||
|
||||
import type { IResultSetElementKey } from '../../DatabaseDataModel/Actions/ResultSet/IResultSetElementKey';
|
||||
import { isResultSetContentValue } from '../../DatabaseDataModel/Actions/ResultSet/isResultSetContentValue';
|
||||
import { ResultSetDataAction } from '../../DatabaseDataModel/Actions/ResultSet/ResultSetDataAction';
|
||||
import { ResultSetFormatAction } from '../../DatabaseDataModel/Actions/ResultSet/ResultSetFormatAction';
|
||||
import { ResultSetSelectAction } from '../../DatabaseDataModel/Actions/ResultSet/ResultSetSelectAction';
|
||||
import type { IDatabaseResultSet } from '../../DatabaseDataModel/IDatabaseResultSet';
|
||||
@@ -93,7 +92,6 @@ export const TextValuePresentation: TabContainerPanelComponent<IDataValuePanelPr
|
||||
|
||||
const result = model.getResult(resultIndex);
|
||||
const selection = model.source.getAction(resultIndex, ResultSetSelectAction);
|
||||
const data = model.source.getAction(resultIndex, ResultSetDataAction);
|
||||
|
||||
const selectedCells = selection.getSelectedElements();
|
||||
const focusCell = selection.getFocusedElement();
|
||||
@@ -113,8 +111,7 @@ export const TextValuePresentation: TabContainerPanelComponent<IDataValuePanelPr
|
||||
.getCell(firstSelectedCell.row, firstSelectedCell.column);
|
||||
|
||||
stringValue = format.getText(value) ?? '';
|
||||
readonly = format.isReadOnly(firstSelectedCell)
|
||||
|| data.getColumn(firstSelectedCell.column)?.dataKind?.toLowerCase() === 'boolean';
|
||||
readonly = format.isReadOnly(firstSelectedCell);
|
||||
|
||||
if (isResultSetContentValue(value)) {
|
||||
if (value.contentType) {
|
||||
|
||||
Reference in New Issue
Block a user