fix(plugin-data-viewer): CB-1232 disabled state for edit actions

This commit is contained in:
Wroud
2021-09-06 10:59:12 +03:00
parent 31e3488110
commit 7bc9b7ba19
8 changed files with 117 additions and 72 deletions
@@ -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);
@@ -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;
}
@@ -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 }],
});
}
@@ -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>
@@ -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);
@@ -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;
}
@@ -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';
@@ -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()