Files
cloudbeaver/webapp/packages/plugin-data-viewer/src/DataViewerTabService.ts
T
Alexey 4550a71298 Refactor CB-3819 resources (#2031)
* CB-3819 refactor: split resources to modules

* CB-3819 refactor: move resource API to separate package

* CB-3819 refactor: move resource API to separate package

* CB-3819 refactor: split to submodules

* CB-3819 chore: update ts configuration

* CB-3819 refactor: move administration top bar to separate plugin

* CB-3819 feat: update tests

* CB-3819 chore: add pre scripts

* CB-3819 fix: prebuild tests-runner

* chore: restore cache for jest-tests github action

* chore: update configs

* chore: add frontend build action

* chore: rename build frontend github action

* chore: include test dependencies

* fix: default product build script

* chore: update github action

* chore: rename validation github action

* chore: update typescript cache key

* chore: update naming for github actions

* chore: run tests on ubuntu

* CB-3819 fix: pre build tasks

* CB-3819 fix: ignore order

* CB-3819 fix: remove prettier from gql sdk
2023-10-05 23:36:54 +03:00

128 lines
4.6 KiB
TypeScript

/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2023 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 { ConnectionInfoResource, ConnectionsManagerService, IConnectionExecutorData } from '@cloudbeaver/core-connections';
import { injectable } from '@cloudbeaver/core-di';
import { NotificationService } from '@cloudbeaver/core-events';
import { ExecutorInterrupter, IExecutionContextProvider } from '@cloudbeaver/core-executor';
import { INodeNavigationData, NavNodeManagerService } from '@cloudbeaver/core-navigation-tree';
import { resourceKeyList } from '@cloudbeaver/core-resource';
import { ITab, NavigationTabsService } from '@cloudbeaver/plugin-navigation-tabs';
import { DBObjectPageService, IObjectViewerTabState, isObjectViewerTab, ObjectPage, ObjectViewerTabService } from '@cloudbeaver/plugin-object-viewer';
import { DataViewerPanel } from './DataViewerPage/DataViewerPanel';
import { DataViewerTab } from './DataViewerPage/DataViewerTab';
import { DataViewerTableService } from './DataViewerTableService';
import type { IDataViewerPageState } from './IDataViewerPageState';
@injectable()
export class DataViewerTabService {
readonly page: ObjectPage<IDataViewerPageState>;
constructor(
private readonly navNodeManagerService: NavNodeManagerService,
private readonly dataViewerTableService: DataViewerTableService,
private readonly objectViewerTabService: ObjectViewerTabService,
private readonly dbObjectPageService: DBObjectPageService,
private readonly notificationService: NotificationService,
private readonly connectionsManagerService: ConnectionsManagerService,
private readonly navigationTabsService: NavigationTabsService,
private readonly connectionInfoResource: ConnectionInfoResource,
) {
this.page = this.dbObjectPageService.register({
key: 'data_viewer_data',
priority: 2,
order: 2,
getTabComponent: () => DataViewerTab,
getPanelComponent: () => DataViewerPanel,
onRestore: this.handleTabRestore.bind(this),
canClose: this.handleTabCanClose.bind(this),
onClose: this.handleTabClose.bind(this),
});
}
register() {
this.connectionsManagerService.onDisconnect.addHandler(this.disconnectHandler.bind(this));
}
registerTabHandler(): void {
this.navNodeManagerService.navigator.addHandler(this.navigationHandler.bind(this));
}
private async disconnectHandler(data: IConnectionExecutorData, contexts: IExecutionContextProvider<IConnectionExecutorData>) {
const connectionsKey = resourceKeyList(data.connections);
if (data.state === 'before') {
const tabs = Array.from(
this.navigationTabsService.findTabs(
isObjectViewerTab(tab => {
if (!tab.handlerState.connectionKey) {
return false;
}
return this.connectionInfoResource.isIntersect(connectionsKey, tab.handlerState.connectionKey);
}),
),
);
for (const tab of tabs) {
const canDisconnect = await this.handleTabCanClose(tab);
if (!canDisconnect) {
ExecutorInterrupter.interrupt(contexts);
return;
}
}
}
}
private async navigationHandler(data: INodeNavigationData, contexts: IExecutionContextProvider<INodeNavigationData>) {
try {
const { nodeInfo, tabInfo, initTab, trySwitchPage } = contexts.getContext(this.objectViewerTabService.objectViewerTabContext);
const node = await this.navNodeManagerService.loadNode(nodeInfo);
if (!this.navNodeManagerService.isNodeHasData(node)) {
return;
}
await initTab();
if (tabInfo.isNewlyCreated) {
trySwitchPage(this.page);
}
} catch (exception: any) {
this.notificationService.logException(exception, 'Data Viewer Error', 'Error in Data Viewer while processing action with database node');
}
}
private async handleTabRestore(tab: ITab<IObjectViewerTabState>) {
return true;
}
private async handleTabCanClose(tab: ITab<IObjectViewerTabState>): Promise<boolean> {
const model = this.dataViewerTableService.get(tab.handlerState.tableId || '');
if (model) {
let canClose = false;
try {
await model.requestDataAction(() => {
canClose = true;
});
} catch {}
return canClose;
}
return true;
}
private handleTabClose(tab: ITab<IObjectViewerTabState>) {
if (tab.handlerState.tableId) {
this.dataViewerTableService.removeTableModel(tab.handlerState.tableId);
}
}
}