dbeaver/pro#5215 track close event on layout close (#3472)

* dbeaver/pro#5215 track close event on layout close

* dbeaver/pro#5215 support old close behaviour

* dbeaver/pro#5215 add event data check to user form

* dbeaver/pro#5215 change naming

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
This commit is contained in:
alex
2025-05-27 00:39:06 +08:00
committed by GitHub
co-authored by Evgenia
parent 0a7d9e6a25
commit 005adb10ce
6 changed files with 44 additions and 33 deletions
@@ -1,6 +1,6 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
* Copyright (C) 2020-2025 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
@@ -9,11 +9,11 @@ import { action, makeObservable, observable } from 'mobx';
import { Executor, type IExecutor } from '@cloudbeaver/core-executor';
import type { OptionsPanelService } from './OptionsPanelService.js';
import type { OptionsPanelCloseEventData, OptionsPanelService } from './OptionsPanelService.js';
export abstract class BaseOptionsPanelService<T> {
itemId: T | null;
readonly onClose: IExecutor;
readonly onClose: IExecutor<OptionsPanelCloseEventData>;
constructor(
protected readonly optionsPanelService: OptionsPanelService,
@@ -26,6 +26,12 @@ export abstract class BaseOptionsPanelService<T> {
this.close = this.close.bind(this);
this.open = this.open.bind(this);
this.onClose.addHandler(data => {
if (data === 'after') {
this.itemId = null;
}
});
makeObservable(this, {
itemId: observable.ref,
open: action,
@@ -52,10 +58,6 @@ export abstract class BaseOptionsPanelService<T> {
return;
}
const result = await this.optionsPanelService.close();
if (result) {
this.itemId = null;
}
await this.optionsPanelService.close();
}
}
@@ -1,6 +1,6 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
* Copyright (C) 2020-2025 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@ import { Executor, ExecutorInterrupter, type IExecutionContext, type IExecutor,
import { NavigationService } from './NavigationService.js';
export type OptionsPanelCloseEventData = 'before' | 'after';
@injectable()
export class OptionsPanelService {
active: boolean;
readonly closeTask: IExecutor;
readonly closeTask: IExecutor<OptionsPanelCloseEventData>;
panelComponent: (() => React.FC) | null;
private basePanelComponent: (() => React.FC) | null;
@@ -55,12 +57,12 @@ export class OptionsPanelService {
return true;
}
async close(context?: IExecutionContext<void>): Promise<boolean> {
async close(context?: IExecutionContext<any>): Promise<boolean> {
if (this.panelComponent === null) {
return true;
}
const contexts = await this.closeTask.execute(undefined, context);
const contexts = await this.closeTask.execute('before', context);
const interrupted = contexts.getContext(ExecutorInterrupter.interruptContext);
@@ -68,9 +70,12 @@ export class OptionsPanelService {
return false;
}
await this.closeTask.execute('after', context);
this.panelComponent = null;
this.basePanelComponent = null;
this.active = false;
return true;
}
@@ -1,6 +1,6 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
* Copyright (C) 2020-2025 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
@@ -36,8 +36,8 @@ export const UserEdit = observer<TableItemExpandProps<string>>(function UserEdit
useExecutor({
executor: usersTableOptionsPanelService.onClose,
handlers: [
async function closeHandler(_, contexts) {
if (state.isChanged) {
async function closeHandler(event, contexts) {
if (state.isChanged && event === 'before') {
const result = await commonDialogService.open(ConfirmationDialog, {
title: 'core_blocks_confirmation_dialog_title',
message: 'ui_save_reminder',
@@ -15,7 +15,7 @@ import { CommonDialogService, DialogueStateResult } from '@cloudbeaver/core-dial
import { NotificationService } from '@cloudbeaver/core-events';
import { ExecutorInterrupter, type IExecutorHandler } from '@cloudbeaver/core-executor';
import type { AdminConnectionSearchInfo } from '@cloudbeaver/core-sdk';
import { OptionsPanelService } from '@cloudbeaver/core-ui';
import { OptionsPanelService, type OptionsPanelCloseEventData } from '@cloudbeaver/core-ui';
import { ConnectionFormService, ConnectionFormState, getConnectionFormOptionsPart } from '@cloudbeaver/plugin-connections';
const SearchDatabase = importLazyComponent(() => import('./SearchDatabase.js').then(module => module.SearchDatabase));
@@ -92,16 +92,18 @@ export class ConnectionSearchService {
}
}
private readonly closeHandler: IExecutorHandler<void> = async (data, contexts) => {
const isDialogClosed = await this.showUnsavedChangesDialog();
private readonly closeHandler: IExecutorHandler<OptionsPanelCloseEventData> = async (data, contexts) => {
if (data === 'before') {
const isDialogClosed = await this.showUnsavedChangesDialog();
if (!isDialogClosed) {
ExecutorInterrupter.interrupt(contexts);
return;
if (!isDialogClosed) {
ExecutorInterrupter.interrupt(contexts);
return;
}
this.clearFormState();
this.close();
}
this.clearFormState();
this.close();
};
private get optionsPart() {
@@ -17,7 +17,7 @@ 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 { FormMode, OptionsPanelService, type OptionsPanelCloseEventData } from '@cloudbeaver/core-ui';
import { AuthenticationService } from '@cloudbeaver/plugin-authentication';
import { ConnectionFormState } from '../ConnectionForm/ConnectionFormState.js';
@@ -148,15 +148,17 @@ export class PublicConnectionFormService {
}
};
private readonly closeHandler: IExecutorHandler<any> = async (data, contexts) => {
const confirmed = await this.showUnsavedChangesDialog();
private readonly closeHandler: IExecutorHandler<OptionsPanelCloseEventData> = async (data, contexts) => {
if (data === 'before') {
const confirmed = await this.showUnsavedChangesDialog();
if (!confirmed) {
ExecutorInterrupter.interrupt(contexts);
return;
if (!confirmed) {
ExecutorInterrupter.interrupt(contexts);
return;
}
this.clearFormState();
}
this.clearFormState();
};
private async showUnsavedChangesDialog(): Promise<boolean> {
@@ -33,7 +33,7 @@ export class UserProfileOptionsPanelService {
this.onOpen = new SyncExecutor();
this.onClose = new Executor();
this.optionsPanelService.closeTask.next(this.onClose, undefined, () => this.optionsPanelService.isOpen(panelGetter));
this.optionsPanelService.closeTask.next(this.onClose, undefined, data => data === 'before' && this.optionsPanelService.isOpen(panelGetter));
this.userInfoResource.onDataUpdate.addHandler(this.userUpdateHandler.bind(this));
makeObservable(this, {