mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-13 07:47:05 +08:00
fix(plugin-data-viewer): CB-1232 disabled state for edit actions
This commit is contained in:
@@ -14,7 +14,7 @@ import styled from 'reshadow';
|
||||
|
||||
import { Executor } from '@cloudbeaver/core-executor';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
import { DatabaseDataSelectActionsData, IDatabaseResultSet, IDataPresentationProps, IResultSetEditActionData, IResultSetElementKey, IResultSetPartialKey, ResultSetDataKeysUtils, ResultSetSelectAction } from '@cloudbeaver/plugin-data-viewer';
|
||||
import { DatabaseDataSelectActionsData, DatabaseEditChangeType, IDatabaseResultSet, IDataPresentationProps, IResultSetEditActionData, IResultSetElementKey, IResultSetPartialKey, ResultSetDataKeysUtils, ResultSetSelectAction } from '@cloudbeaver/plugin-data-viewer';
|
||||
|
||||
import { CellPosition, EditingContext } from '../Editing/EditingContext';
|
||||
import { useEditing } from '../Editing/useEditing';
|
||||
@@ -109,12 +109,19 @@ export const DataGridTable = observer<IDataPresentationProps<any, IDatabaseResul
|
||||
useEffect(() => {
|
||||
function syncEditor(data: IResultSetEditActionData) {
|
||||
const editor = tableData.editor;
|
||||
if (data.resultId !== editor.result.id || !data.value) {
|
||||
if (
|
||||
data.resultId !== editor.result.id
|
||||
|| !data.value
|
||||
|| data.value.length === 0
|
||||
|| data.type === DatabaseEditChangeType.delete
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const idx = tableData.getColumnIndexFromColumnKey(data.value.key.column);
|
||||
const rowIdx = tableData.getRowIndexFromKey(data.value.key.row);
|
||||
const key = data.value[data.value.length - 1].key;
|
||||
|
||||
const idx = tableData.getColumnIndexFromColumnKey(key.column);
|
||||
const rowIdx = tableData.getRowIndexFromKey(key.row);
|
||||
|
||||
if (data.revert) {
|
||||
editingContext.closeEditor({
|
||||
@@ -123,7 +130,7 @@ export const DataGridTable = observer<IDataPresentationProps<any, IDatabaseResul
|
||||
});
|
||||
}
|
||||
|
||||
if (selectionAction.isFocused(data.value.key)) {
|
||||
if (selectionAction.isFocused(key)) {
|
||||
const rowTop = rowIdx * rowHeight;
|
||||
const gridDiv = dataGridDivRef.current;
|
||||
dataGridRef.current?.scrollToColumn(idx);
|
||||
|
||||
+2
-2
@@ -40,8 +40,8 @@ export abstract class DatabaseEditAction<TKey, TValue, TResult extends IDatabase
|
||||
abstract get(key: TKey): TValue | undefined;
|
||||
abstract set(key: TKey, value: TValue): void;
|
||||
abstract add(key?: TKey): void;
|
||||
abstract delete(key: TKey): void;
|
||||
abstract delete(...key: TKey[]): void;
|
||||
abstract applyUpdate(result: TResult): void;
|
||||
abstract revert(key: TKey): void;
|
||||
abstract revert(...key: TKey[]): void;
|
||||
abstract clear(): void;
|
||||
}
|
||||
|
||||
+3
-3
@@ -78,11 +78,11 @@ export class DocumentEditAction
|
||||
type: DatabaseEditChangeType.update,
|
||||
revert: false,
|
||||
resultId: this.result.id,
|
||||
value: {
|
||||
value: [{
|
||||
key: key,
|
||||
prevValue,
|
||||
value,
|
||||
},
|
||||
}],
|
||||
});
|
||||
|
||||
this.removeUnchanged(key);
|
||||
@@ -137,7 +137,7 @@ export class DocumentEditAction
|
||||
this.action.execute({
|
||||
revert: true,
|
||||
resultId: this.result.id,
|
||||
value: { key: key },
|
||||
value: [{ key: key }],
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ export interface IDatabaseDataEditActionData<TKey, TValue> {
|
||||
revert: boolean;
|
||||
type?: DatabaseEditChangeType;
|
||||
resultId: string;
|
||||
value?: IDatabaseDataEditActionValue<TKey, TValue>;
|
||||
value?: Array<IDatabaseDataEditActionValue<TKey, TValue>>;
|
||||
}
|
||||
|
||||
export interface IDatabaseDataEditAction<TKey, TValue, TResult extends IDatabaseDataResult>
|
||||
|
||||
+48
-16
@@ -15,7 +15,7 @@ import type { IDatabaseDataSource } from '../../IDatabaseDataSource';
|
||||
import type { IDatabaseResultSet } from '../../IDatabaseResultSet';
|
||||
import { databaseDataAction } from '../DatabaseDataActionDecorator';
|
||||
import { DatabaseEditAction } from '../DatabaseEditAction';
|
||||
import { DatabaseEditChangeType, IDatabaseDataEditActionData } from '../IDatabaseDataEditAction';
|
||||
import { DatabaseEditChangeType, IDatabaseDataEditActionData, IDatabaseDataEditActionValue } from '../IDatabaseDataEditAction';
|
||||
import type { IResultSetColumnKey, IResultSetElementKey, IResultSetRowKey } from './IResultSetDataKey';
|
||||
import { isResultSetContentValue } from './isResultSetContentValue';
|
||||
import { ResultSetDataAction } from './ResultSetDataAction';
|
||||
@@ -156,11 +156,11 @@ export class ResultSetEditAction
|
||||
resultId: this.result.id,
|
||||
type: update.type,
|
||||
revert: false,
|
||||
value: {
|
||||
value: [{
|
||||
key,
|
||||
prevValue,
|
||||
value,
|
||||
},
|
||||
}],
|
||||
});
|
||||
|
||||
this.removeEmptyUpdate(update);
|
||||
@@ -199,18 +199,50 @@ export class ResultSetEditAction
|
||||
resultId: this.result.id,
|
||||
type: update.type,
|
||||
revert: false,
|
||||
value: {
|
||||
value: [{
|
||||
key: { column, row },
|
||||
},
|
||||
}],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
delete(key: IResultSetElementKey): void {
|
||||
this.deleteRow(key.row, key.column);
|
||||
delete(...keys: IResultSetElementKey[]): void {
|
||||
const reverted: Array<IDatabaseDataEditActionValue<IResultSetElementKey, IResultSetValue>> = [];
|
||||
const deleted: Array<IDatabaseDataEditActionValue<IResultSetElementKey, IResultSetValue>> = [];
|
||||
|
||||
for (const key of keys) {
|
||||
const serializedKey = ResultSetDataKeysUtils.serialize(key.row);
|
||||
const update = this.editorData.get(serializedKey);
|
||||
|
||||
if (update?.type === DatabaseEditChangeType.add) {
|
||||
reverted.push({ key });
|
||||
this.editorData.delete(serializedKey);
|
||||
} else {
|
||||
this.deleteRow(key.row, key.column, true);
|
||||
deleted.push({ key });
|
||||
}
|
||||
}
|
||||
|
||||
if (reverted.length > 0) {
|
||||
this.action.execute({
|
||||
resultId: this.result.id,
|
||||
type: DatabaseEditChangeType.add,
|
||||
revert: true,
|
||||
value: reverted,
|
||||
});
|
||||
}
|
||||
|
||||
if (deleted.length > 0) {
|
||||
this.action.execute({
|
||||
resultId: this.result.id,
|
||||
type: DatabaseEditChangeType.delete,
|
||||
revert: false,
|
||||
value: deleted,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
deleteRow(key: IResultSetRowKey, column?: IResultSetColumnKey): void {
|
||||
deleteRow(key: IResultSetRowKey, column?: IResultSetColumnKey, silent?: boolean): void {
|
||||
const serializedKey = ResultSetDataKeysUtils.serialize(key);
|
||||
const update = this.editorData.get(serializedKey);
|
||||
|
||||
@@ -225,24 +257,24 @@ export class ResultSetEditAction
|
||||
if (update?.type !== DatabaseEditChangeType.add) {
|
||||
const [update, created] = this.getOrCreateUpdate(key, DatabaseEditChangeType.delete);
|
||||
|
||||
if (created) {
|
||||
if (created && !silent) {
|
||||
this.action.execute({
|
||||
resultId: this.result.id,
|
||||
type: update.type,
|
||||
revert: false,
|
||||
value: {
|
||||
value: [{
|
||||
key: { column, row: key },
|
||||
},
|
||||
}],
|
||||
});
|
||||
}
|
||||
} else {
|
||||
} else if (!silent) {
|
||||
this.action.execute({
|
||||
resultId: this.result.id,
|
||||
type: update.type,
|
||||
revert: true,
|
||||
value: {
|
||||
value: [{
|
||||
key: { column, row: key },
|
||||
},
|
||||
}],
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -318,11 +350,11 @@ export class ResultSetEditAction
|
||||
resultId: this.result.id,
|
||||
type: update.type,
|
||||
revert: true,
|
||||
value: {
|
||||
value: [{
|
||||
key,
|
||||
prevValue,
|
||||
value,
|
||||
},
|
||||
}],
|
||||
});
|
||||
|
||||
this.removeEmptyUpdate(update);
|
||||
|
||||
+12
-16
@@ -6,7 +6,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { computed, IReactionDisposer, makeObservable, observable, observe, toJS } from 'mobx';
|
||||
import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
|
||||
|
||||
import { Executor, IExecutor } from '@cloudbeaver/core-executor';
|
||||
import { ResultDataFormat } from '@cloudbeaver/core-sdk';
|
||||
@@ -37,7 +37,7 @@ export class ResultSetSelectAction extends DatabaseSelectAction<any, IDatabaseRe
|
||||
private focusedElement: IResultSetElementKey | null;
|
||||
private view: ResultSetViewAction;
|
||||
private edit: ResultSetEditAction;
|
||||
private validationDisposer: () => void;
|
||||
private validationDisposer: IReactionDisposer;
|
||||
|
||||
constructor(source: IDatabaseDataSource<any, IDatabaseResultSet>, result: IDatabaseResultSet) {
|
||||
super(source, result);
|
||||
@@ -51,16 +51,12 @@ export class ResultSetSelectAction extends DatabaseSelectAction<any, IDatabaseRe
|
||||
selectedElements: observable,
|
||||
focusedElement: observable.ref,
|
||||
elements: computed,
|
||||
set: action,
|
||||
focus: action,
|
||||
clear: action,
|
||||
});
|
||||
|
||||
this.validationDisposer = observe(this.view, 'rowKeys', change => {
|
||||
const previous = change.oldValue as IResultSetRowKey[] | undefined;
|
||||
const current = change.newValue as IResultSetRowKey[];
|
||||
|
||||
if (!previous) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.validationDisposer = reaction(() => this.view.rowKeys, (current, previous) => {
|
||||
if (this.focusedElement) {
|
||||
const focus = this.focusedElement;
|
||||
const focusIndex = previous.findIndex(key => ResultSetDataKeysUtils.isEqual(key, focus.row));
|
||||
@@ -274,22 +270,22 @@ export class ResultSetSelectAction extends DatabaseSelectAction<any, IDatabaseRe
|
||||
if (data.value) {
|
||||
if (data.revert) {
|
||||
// this.focus({ ...data.value.key, row: this.view.getShift(data.value.key.row) });
|
||||
} else {
|
||||
this.focus(data.value.key);
|
||||
} else if (data.value.length > 0) {
|
||||
this.focus(data.value[data.value.length - 1].key);
|
||||
}
|
||||
this.clear();
|
||||
}
|
||||
break;
|
||||
|
||||
case DatabaseEditChangeType.delete:
|
||||
if (data.value) {
|
||||
this.focus(data.value.key);
|
||||
if (data.value && data.value.length > 0) {
|
||||
this.focus(data.value[data.value.length - 1].key);
|
||||
this.clear();
|
||||
}
|
||||
break;
|
||||
case DatabaseEditChangeType.update:
|
||||
if (data.value) {
|
||||
this.focus(data.value.key);
|
||||
if (data.value && data.value.length > 0) {
|
||||
this.focus(data.value[data.value.length - 1].key);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { computed, extendObservable, IComputedValue, makeObservable, observe } from 'mobx';
|
||||
import { computed, makeObservable } from 'mobx';
|
||||
|
||||
import { DataTypeLogicalOperation, ResultDataFormat, SqlResultColumn } from '@cloudbeaver/core-sdk';
|
||||
|
||||
|
||||
+38
-28
@@ -44,23 +44,23 @@ export class TableFooterMenuService {
|
||||
return context.contextType === TableFooterMenuService.nodeContextType;
|
||||
},
|
||||
isHidden(context) {
|
||||
if (context.data.model.isReadonly()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const editor = context.data.model.source.getActionImplementation(
|
||||
context.data.resultIndex,
|
||||
DatabaseEditAction
|
||||
);
|
||||
|
||||
return (
|
||||
context.data.model.isReadonly()
|
||||
|| context.data.model.isDisabled(context.data.resultIndex)
|
||||
|| !editor?.hasFeature('add')
|
||||
);
|
||||
return !editor?.hasFeature('add');
|
||||
},
|
||||
isDisabled(context) {
|
||||
if (context.data.model.isLoading()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return (
|
||||
context.data.model.isLoading()
|
||||
|| context.data.model.isDisabled(context.data.resultIndex)
|
||||
|| !context.data.model.source.hasResult(context.data.resultIndex)
|
||||
);
|
||||
},
|
||||
onClick(context) {
|
||||
const editor = context.data.model.source.getActionImplementation(
|
||||
@@ -89,19 +89,23 @@ export class TableFooterMenuService {
|
||||
return context.contextType === TableFooterMenuService.nodeContextType;
|
||||
},
|
||||
isHidden(context) {
|
||||
if (context.data.model.isReadonly()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const editor = context.data.model.source.getActionImplementation(
|
||||
context.data.resultIndex,
|
||||
DatabaseEditAction
|
||||
);
|
||||
|
||||
return (
|
||||
context.data.model.isReadonly()
|
||||
|| context.data.model.isDisabled(context.data.resultIndex)
|
||||
|| !editor?.hasFeature('delete')
|
||||
);
|
||||
return !editor?.hasFeature('delete');
|
||||
},
|
||||
isDisabled(context) {
|
||||
if (context.data.model.isLoading()) {
|
||||
if (
|
||||
context.data.model.isLoading()
|
||||
|| context.data.model.isDisabled(context.data.resultIndex)
|
||||
|| !context.data.model.source.hasResult(context.data.resultIndex)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -130,9 +134,7 @@ export class TableFooterMenuService {
|
||||
|
||||
const selectedElements = getActiveElements(context.data.model, context.data.resultIndex);
|
||||
|
||||
for (const key of selectedElements) {
|
||||
editor?.delete(key);
|
||||
}
|
||||
editor?.delete(...selectedElements);
|
||||
},
|
||||
});
|
||||
this.registerMenuItem({
|
||||
@@ -144,10 +146,7 @@ export class TableFooterMenuService {
|
||||
return context.contextType === TableFooterMenuService.nodeContextType;
|
||||
},
|
||||
isHidden(context) {
|
||||
if (
|
||||
context.data.model.isReadonly()
|
||||
|| context.data.model.isDisabled(context.data.resultIndex)
|
||||
) {
|
||||
if (context.data.model.isReadonly()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -159,6 +158,14 @@ export class TableFooterMenuService {
|
||||
return !editor;
|
||||
},
|
||||
isDisabled(context) {
|
||||
if (
|
||||
context.data.model.isLoading()
|
||||
|| context.data.model.isDisabled(context.data.resultIndex)
|
||||
|| !context.data.model.source.hasResult(context.data.resultIndex)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const editor = context.data.model.source.getActionImplementation(
|
||||
context.data.resultIndex,
|
||||
DatabaseEditAction
|
||||
@@ -167,8 +174,7 @@ export class TableFooterMenuService {
|
||||
const selectedElements = getActiveElements(context.data.model, context.data.resultIndex);
|
||||
|
||||
return (
|
||||
context.data.model.isLoading()
|
||||
|| !editor
|
||||
!editor
|
||||
|| selectedElements.length === 0
|
||||
|| !selectedElements.some(key => {
|
||||
const state = editor.getElementState(key);
|
||||
@@ -189,9 +195,7 @@ export class TableFooterMenuService {
|
||||
|
||||
const selectedElements = getActiveElements(context.data.model, context.data.resultIndex);
|
||||
|
||||
for (const element of selectedElements) {
|
||||
editor?.revert(element);
|
||||
}
|
||||
editor?.revert(...selectedElements);
|
||||
},
|
||||
});
|
||||
this.registerMenuItem({
|
||||
@@ -202,6 +206,9 @@ export class TableFooterMenuService {
|
||||
isPresent(context) {
|
||||
return context.contextType === TableFooterMenuService.nodeContextType;
|
||||
},
|
||||
isHidden(context) {
|
||||
return context.data.model.isReadonly();
|
||||
},
|
||||
isDisabled(context) {
|
||||
if (
|
||||
context.data.model.isLoading()
|
||||
@@ -230,6 +237,9 @@ export class TableFooterMenuService {
|
||||
isPresent(context) {
|
||||
return context.contextType === TableFooterMenuService.nodeContextType;
|
||||
},
|
||||
isHidden(context) {
|
||||
return context.data.model.isReadonly();
|
||||
},
|
||||
isDisabled(context) {
|
||||
if (
|
||||
context.data.model.isLoading()
|
||||
|
||||
Reference in New Issue
Block a user