mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-13 07:47:05 +08:00
330 lines
10 KiB
TypeScript
330 lines
10 KiB
TypeScript
/*
|
|
* 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 { injectable } from '@cloudbeaver/core-di';
|
|
import {
|
|
ContextMenuService, IMenuContext, IContextMenuItem, IMenuItem
|
|
} from '@cloudbeaver/core-dialogs';
|
|
import { ResultDataFormat } from '@cloudbeaver/core-sdk';
|
|
|
|
import { DatabaseEditAction } from '../../../DatabaseDataModel/Actions/DatabaseEditAction';
|
|
import { DatabaseSelectAction } from '../../../DatabaseDataModel/Actions/DatabaseSelectAction';
|
|
import { DatabaseEditChangeType } from '../../../DatabaseDataModel/Actions/IDatabaseDataEditAction';
|
|
import type { IDatabaseDataModel } from '../../../DatabaseDataModel/IDatabaseDataModel';
|
|
import type { IDatabaseDataResult } from '../../../DatabaseDataModel/IDatabaseDataResult';
|
|
import { ScriptPreviewService } from '../../../ScriptPreview/ScriptPreviewService';
|
|
|
|
export interface ITableFooterMenuContext {
|
|
model: IDatabaseDataModel<any>;
|
|
resultIndex: number;
|
|
}
|
|
|
|
@injectable()
|
|
export class TableFooterMenuService {
|
|
static nodeContextType = 'NodeWithParent';
|
|
private tableFooterMenuToken = 'tableFooterMenu';
|
|
|
|
constructor(
|
|
private contextMenuService: ContextMenuService,
|
|
private scriptPreviewService: ScriptPreviewService,
|
|
) {
|
|
this.contextMenuService.addPanel(this.tableFooterMenuToken);
|
|
|
|
this.registerMenuItem({
|
|
id: 'table_add',
|
|
order: 0.5,
|
|
icon: '/icons/data_add.svg',
|
|
tooltip: 'data_viewer_action_edit_add',
|
|
isPresent(context) {
|
|
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 !editor?.hasFeature('add');
|
|
},
|
|
isDisabled(context) {
|
|
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(
|
|
context.data.resultIndex,
|
|
DatabaseEditAction
|
|
);
|
|
|
|
if (!editor) {
|
|
return;
|
|
}
|
|
|
|
const select = context.data.model.source.getActionImplementation(
|
|
context.data.resultIndex,
|
|
DatabaseSelectAction
|
|
);
|
|
|
|
editor.add(select?.getFocusedElement());
|
|
},
|
|
});
|
|
this.registerMenuItem({
|
|
id: 'table_delete',
|
|
order: 0.6,
|
|
icon: '/icons/data_delete.svg',
|
|
tooltip: 'data_viewer_action_edit_delete',
|
|
isPresent(context) {
|
|
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 !editor?.hasFeature('delete');
|
|
},
|
|
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
|
|
);
|
|
|
|
if (!editor) {
|
|
return true;
|
|
}
|
|
|
|
const selectedElements = getActiveElements(context.data.model, context.data.resultIndex);
|
|
|
|
if (selectedElements.length === 0) {
|
|
return true;
|
|
}
|
|
|
|
return !selectedElements.some(key => editor.getElementState(key) !== DatabaseEditChangeType.delete);
|
|
},
|
|
onClick(context) {
|
|
const editor = context.data.model.source.getActionImplementation(
|
|
context.data.resultIndex,
|
|
DatabaseEditAction
|
|
);
|
|
|
|
const selectedElements = getActiveElements(context.data.model, context.data.resultIndex);
|
|
|
|
editor?.delete(...selectedElements);
|
|
},
|
|
});
|
|
this.registerMenuItem({
|
|
id: 'table_revert',
|
|
order: 0.7,
|
|
icon: '/icons/data_revert.svg',
|
|
tooltip: 'data_viewer_action_edit_revert',
|
|
isPresent(context) {
|
|
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 !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
|
|
);
|
|
|
|
const selectedElements = getActiveElements(context.data.model, context.data.resultIndex);
|
|
|
|
return (
|
|
!editor
|
|
|| selectedElements.length === 0
|
|
|| !selectedElements.some(key => {
|
|
const state = editor.getElementState(key);
|
|
|
|
if (state === DatabaseEditChangeType.add) {
|
|
return editor.isElementEdited(key);
|
|
}
|
|
|
|
return state !== null;
|
|
})
|
|
);
|
|
},
|
|
onClick(context) {
|
|
const editor = context.data.model.source.getActionImplementation(
|
|
context.data.resultIndex,
|
|
DatabaseEditAction
|
|
);
|
|
|
|
const selectedElements = getActiveElements(context.data.model, context.data.resultIndex);
|
|
|
|
editor?.revert(...selectedElements);
|
|
},
|
|
});
|
|
this.registerMenuItem({
|
|
id: 'save ',
|
|
order: 1,
|
|
title: 'ui_processing_save',
|
|
icon: 'table-save',
|
|
isPresent(context) {
|
|
return context.contextType === TableFooterMenuService.nodeContextType;
|
|
},
|
|
isHidden(context) {
|
|
return context.data.model.isReadonly();
|
|
},
|
|
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
|
|
);
|
|
|
|
return !editor?.isEdited();
|
|
},
|
|
onClick: context => context.data.model.source.saveData(),
|
|
});
|
|
|
|
this.registerMenuItem({
|
|
id: 'cancel ',
|
|
order: 2,
|
|
title: 'data_viewer_value_revert',
|
|
tooltip: 'data_viewer_value_revert_title',
|
|
icon: '/icons/data_revert_all.svg',
|
|
isPresent(context) {
|
|
return context.contextType === TableFooterMenuService.nodeContextType;
|
|
},
|
|
isHidden(context) {
|
|
return context.data.model.isReadonly();
|
|
},
|
|
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
|
|
);
|
|
|
|
return !editor?.isEdited();
|
|
},
|
|
onClick: context => {
|
|
const editor = context.data.model.source.getActionImplementation(
|
|
context.data.resultIndex,
|
|
DatabaseEditAction
|
|
);
|
|
editor?.clear();
|
|
},
|
|
});
|
|
|
|
this.registerMenuItem({
|
|
id: 'script',
|
|
order: 3,
|
|
title: 'data_viewer_script_preview',
|
|
tooltip: 'data_viewer_script_preview',
|
|
icon: 'sql-script-preview',
|
|
isPresent(context) {
|
|
return context.contextType === TableFooterMenuService.nodeContextType;
|
|
},
|
|
isHidden(context) {
|
|
return context.data.model.source.getResult(context.data.resultIndex)?.dataFormat !== ResultDataFormat.Resultset;
|
|
},
|
|
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
|
|
);
|
|
return !editor?.isEdited();
|
|
},
|
|
onClick: async context => {
|
|
await this.scriptPreviewService.open(context.data.model, context.data.resultIndex);
|
|
},
|
|
});
|
|
}
|
|
|
|
constructMenuWithContext(model: IDatabaseDataModel<any>, resultIndex: number): IMenuItem[] {
|
|
const context: IMenuContext<ITableFooterMenuContext> = {
|
|
menuId: this.tableFooterMenuToken,
|
|
contextId: model.id,
|
|
contextType: TableFooterMenuService.nodeContextType,
|
|
data: { model, resultIndex },
|
|
};
|
|
return this.contextMenuService.createContextMenu(context, this.tableFooterMenuToken).menuItems;
|
|
}
|
|
|
|
registerMenuItem(options: IContextMenuItem<ITableFooterMenuContext>): void {
|
|
this.contextMenuService.addMenuItem<ITableFooterMenuContext>(this.tableFooterMenuToken, options);
|
|
}
|
|
}
|
|
|
|
function getActiveElements(model: IDatabaseDataModel<any, IDatabaseDataResult>, resultIndex: number): unknown[] {
|
|
const select = model.source.getActionImplementation(
|
|
resultIndex,
|
|
DatabaseSelectAction
|
|
);
|
|
|
|
const selectedElements = select?.getSelectedElements() || [];
|
|
const focus = select?.getFocusedElement();
|
|
|
|
if (selectedElements.length === 0 && focus) {
|
|
selectedElements.push(focus);
|
|
}
|
|
|
|
return selectedElements;
|
|
}
|