mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-24 23:05:29 +08:00
211 lines
7.3 KiB
TypeScript
211 lines
7.3 KiB
TypeScript
/*
|
|
* CloudBeaver - Cloud Database Manager
|
|
* Copyright (C) 2020-2024 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 { action, makeObservable, observable } from 'mobx';
|
|
|
|
import { UserInfoResource } from '@cloudbeaver/core-authentication';
|
|
import { ConfirmationDialog, importLazyComponent } from '@cloudbeaver/core-blocks';
|
|
import { ConnectionInfoResource, ConnectionsManagerService, createConnectionParam, type IConnectionInfoParams } from '@cloudbeaver/core-connections';
|
|
import { injectable, IServiceProvider } from '@cloudbeaver/core-di';
|
|
import { CommonDialogService, DialogueStateResult } from '@cloudbeaver/core-dialogs';
|
|
import { NotificationService } from '@cloudbeaver/core-events';
|
|
import { executorHandlerFilter, ExecutorInterrupter, type IExecutorHandler } from '@cloudbeaver/core-executor';
|
|
import type { ResourceKey, ResourceKeySimple } from '@cloudbeaver/core-resource';
|
|
import type { ConnectionConfig } from '@cloudbeaver/core-sdk';
|
|
import { FormMode, OptionsPanelService } from '@cloudbeaver/core-ui';
|
|
import { AuthenticationService } from '@cloudbeaver/plugin-authentication';
|
|
|
|
import { ConnectionFormState } from '../ConnectionForm/ConnectionFormState.js';
|
|
import { ConnectionFormService } from '../ConnectionForm/ConnectionFormService.js';
|
|
|
|
const PublicConnectionForm = importLazyComponent(() => import('./PublicConnectionForm.js').then(m => m.PublicConnectionForm));
|
|
|
|
const formGetter = () => PublicConnectionForm;
|
|
|
|
@injectable()
|
|
export class PublicConnectionFormService {
|
|
formState: ConnectionFormState | null;
|
|
|
|
constructor(
|
|
private readonly commonDialogService: CommonDialogService,
|
|
private readonly notificationService: NotificationService,
|
|
private readonly optionsPanelService: OptionsPanelService,
|
|
private readonly serviceProvider: IServiceProvider,
|
|
private readonly connectionFormService: ConnectionFormService,
|
|
private readonly connectionInfoResource: ConnectionInfoResource,
|
|
private readonly connectionsManagerService: ConnectionsManagerService,
|
|
private readonly userInfoResource: UserInfoResource,
|
|
private readonly authenticationService: AuthenticationService,
|
|
) {
|
|
this.formState = null;
|
|
this.optionsPanelService.closeTask.addHandler(this.closeHandler);
|
|
this.connectionInfoResource.onDataUpdate.addPostHandler(this.closeRemoved);
|
|
this.connectionInfoResource.onItemDelete.addPostHandler(this.closeDeleted);
|
|
|
|
this.authenticationService.onLogin.addHandler(
|
|
executorHandlerFilter(
|
|
() => !!this.formState && this.optionsPanelService.isOpen(formGetter),
|
|
async (event, context) => {
|
|
if (event === 'before' && this.userInfoResource.isAnonymous()) {
|
|
const confirmed = await this.showUnsavedChangesDialog();
|
|
|
|
if (!confirmed) {
|
|
ExecutorInterrupter.interrupt(context);
|
|
}
|
|
}
|
|
},
|
|
),
|
|
);
|
|
|
|
makeObservable(this, {
|
|
formState: observable.shallow,
|
|
change: action,
|
|
open: action,
|
|
close: action,
|
|
});
|
|
}
|
|
|
|
change(projectId: string, config: ConnectionConfig, availableDrivers?: string[]): void {
|
|
if (this.formState) {
|
|
// this.formState.dispose();
|
|
this.clearFormState();
|
|
}
|
|
|
|
if (!this.formState) {
|
|
this.formState = new ConnectionFormState(this.serviceProvider, this.connectionFormService, {
|
|
projectId,
|
|
availableDrivers: availableDrivers ?? [],
|
|
config,
|
|
submitType: 'submit',
|
|
type: 'public',
|
|
});
|
|
}
|
|
|
|
this.formState.setMode(config.connectionId ? FormMode.Edit : FormMode.Create);
|
|
}
|
|
|
|
async open(projectId: string, config: ConnectionConfig, availableDrivers?: string[]): Promise<boolean> {
|
|
const state = await this.optionsPanelService.open(formGetter);
|
|
|
|
if (state) {
|
|
this.change(projectId, config, availableDrivers);
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
async close(saved?: boolean): Promise<boolean> {
|
|
if (!this.formState) {
|
|
return true;
|
|
}
|
|
|
|
if (saved) {
|
|
this.clearFormState();
|
|
}
|
|
|
|
const state = await this.optionsPanelService.close();
|
|
|
|
if (state) {
|
|
this.clearFormState();
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
async save(): Promise<void> {
|
|
const key =
|
|
this.formState && this.formState.state.config.connectionId && this.formState.state.projectId !== null
|
|
? createConnectionParam(this.formState.state.projectId, this.formState.state.config.connectionId)
|
|
: null;
|
|
|
|
await this.close(true);
|
|
|
|
if (key && this.connectionInfoResource.isConnected(key)) {
|
|
this.tryReconnect(key);
|
|
}
|
|
}
|
|
|
|
private readonly closeRemoved: IExecutorHandler<ResourceKey<IConnectionInfoParams>> = (data, contexts) => {
|
|
if (!this.formState || !this.formState.state.config.connectionId || this.formState.state.projectId === null) {
|
|
return;
|
|
}
|
|
|
|
if (!this.connectionInfoResource.has(createConnectionParam(this.formState.state.projectId, this.formState.state.config.connectionId))) {
|
|
this.close(true);
|
|
}
|
|
};
|
|
|
|
private readonly closeDeleted: IExecutorHandler<ResourceKeySimple<IConnectionInfoParams>> = (data, contexts) => {
|
|
if (!this.formState || !this.formState.state.config.connectionId || this.formState.state.projectId === null) {
|
|
return;
|
|
}
|
|
|
|
if (
|
|
this.connectionInfoResource.isIntersect(data, createConnectionParam(this.formState.state.projectId, this.formState.state.config.connectionId))
|
|
) {
|
|
this.close(true);
|
|
}
|
|
};
|
|
|
|
private readonly closeHandler: IExecutorHandler<any> = async (data, contexts) => {
|
|
const confirmed = await this.showUnsavedChangesDialog();
|
|
|
|
if (!confirmed) {
|
|
ExecutorInterrupter.interrupt(contexts);
|
|
}
|
|
};
|
|
|
|
private async showUnsavedChangesDialog(): Promise<boolean> {
|
|
if (
|
|
!this.formState ||
|
|
!this.optionsPanelService.isOpen(formGetter) ||
|
|
(this.formState.state.config.connectionId &&
|
|
this.formState.state.projectId !== null &&
|
|
!this.connectionInfoResource.has(createConnectionParam(this.formState.state.projectId, this.formState.state.config.connectionId)))
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
if (!this.formState.isChanged) {
|
|
return true;
|
|
}
|
|
|
|
const result = await this.commonDialogService.open(ConfirmationDialog, {
|
|
title: 'plugin_connections_connection_edit_cancel_title',
|
|
message: 'plugin_connections_connection_edit_cancel_message',
|
|
confirmActionText: 'ui_processing_ok',
|
|
});
|
|
|
|
return result !== DialogueStateResult.Rejected;
|
|
}
|
|
|
|
private async tryReconnect(connectionKey: IConnectionInfoParams) {
|
|
const result = await this.commonDialogService.open(ConfirmationDialog, {
|
|
title: 'plugin_connections_connection_edit_reconnect_title',
|
|
message: 'plugin_connections_connection_edit_reconnect_message',
|
|
confirmActionText: 'ui_reconnect',
|
|
});
|
|
|
|
if (result === DialogueStateResult.Rejected) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await this.connectionsManagerService.closeConnectionAsync(connectionKey);
|
|
await this.connectionsManagerService.requireConnection(connectionKey);
|
|
} catch (exception: any) {
|
|
this.notificationService.logException(exception, 'plugin_connections_connection_edit_reconnect_failed');
|
|
}
|
|
}
|
|
|
|
private clearFormState() {
|
|
// TODO dispose the form once we have this API
|
|
// this.formState?.dispose();
|
|
this.formState = null;
|
|
}
|
|
}
|