From eaeb493d6b695451d59c458cd5d9247e0c1adaf0 Mon Sep 17 00:00:00 2001 From: sergeyteleshev Date: Thu, 26 Jun 2025 13:05:29 +0200 Subject: [PATCH] [CB-6221] Add a Clear button to the Output log #4410 (#3547) * dbeaver/pro#4410 adds clear button for output logs * pr fixes * pr fixes * lint fix * removes logs only for specific context --------- Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com> --- .../src/Resource/CachedResource.ts | 6 ++-- .../ACTION_SQL_EDITOR_CLEAR_OUTPUT_LOGS.ts | 14 +++++++++ .../OutputLogs/OutputLogsPanel.tsx | 22 +++++++------- .../OutputLogs/OutputLogsResource.ts | 13 +++++++-- .../OutputLogs/OutputLogsService.ts | 29 ++++++++++++++----- .../OutputLogs/OutputMenuBootstrap.ts | 13 ++++++--- .../OutputLogs/useOutputLogsPanelState.ts | 20 +++++++++---- 7 files changed, 84 insertions(+), 33 deletions(-) create mode 100644 webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/ACTION_SQL_EDITOR_CLEAR_OUTPUT_LOGS.ts diff --git a/webapp/packages/core-resource/src/Resource/CachedResource.ts b/webapp/packages/core-resource/src/Resource/CachedResource.ts index b6b6949bbe..dd0dfb159f 100644 --- a/webapp/packages/core-resource/src/Resource/CachedResource.ts +++ b/webapp/packages/core-resource/src/Resource/CachedResource.ts @@ -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. @@ -625,7 +625,7 @@ export abstract class CachedResource< context?: TInclude, ): Promise {} - protected abstract loader(param: ResourceKey, include: ReadonlyArray | undefined, refresh: boolean): Promise; + protected abstract loader(param: ResourceKey, include: ReadonlyArray | undefined, refresh: boolean): TData | Promise; /** * Implements same behavior as {@link CachedResource.load} and {@link CachedResource.refresh} for custom loaders. @@ -784,7 +784,7 @@ export abstract class CachedResource< this.markOutdatedSync(key); } }, - success: async () => { + success: () => { if (loaded) { this.dataUpdate(key); } diff --git a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/ACTION_SQL_EDITOR_CLEAR_OUTPUT_LOGS.ts b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/ACTION_SQL_EDITOR_CLEAR_OUTPUT_LOGS.ts new file mode 100644 index 0000000000..80df6498c3 --- /dev/null +++ b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/ACTION_SQL_EDITOR_CLEAR_OUTPUT_LOGS.ts @@ -0,0 +1,14 @@ +/* + * CloudBeaver - Cloud Database Manager + * 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. + */ +import { createAction } from '@cloudbeaver/core-view'; + +export const ACTION_SQL_EDITOR_CLEAR_OUTPUT_LOGS = createAction('action_sql_editor_clear_output_logs', { + label: 'ui_clear', + icon: 'erase', + tooltip: 'ui_clear', +}); diff --git a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/OutputLogsPanel.tsx b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/OutputLogsPanel.tsx index 0ab7fa37d4..baee5dc2a4 100644 --- a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/OutputLogsPanel.tsx +++ b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/OutputLogsPanel.tsx @@ -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. @@ -31,17 +31,15 @@ export const OutputLogsPanel = observer(function SqlOutputLogsPanel({ sql return ( - {data && ( - - - - )} + + + ); }); diff --git a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/OutputLogsResource.ts b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/OutputLogsResource.ts index 7a4110329b..f2059088b7 100644 --- a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/OutputLogsResource.ts +++ b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/OutputLogsResource.ts @@ -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. @@ -58,7 +58,16 @@ export class OutputLogsResource extends CachedDataResource { this.setData(updatedData); } - protected async loader(): Promise { + override clear(): void { + super.clear(); + this.useTracker.use(undefined); + } + + deleteLogsByContextId(contextId: string): void { + this.setData(this.data.filter(log => log.contextId !== contextId)); + } + + protected loader(): IOutputLog[] { return this.data; } } diff --git a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/OutputLogsService.ts b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/OutputLogsService.ts index 7993b1f157..7bee694241 100644 --- a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/OutputLogsService.ts +++ b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/OutputLogsService.ts @@ -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,7 +12,7 @@ import type { ISqlEditorTabState } from '../../ISqlEditorTabState.js'; import { SqlDataSourceService } from '../../SqlDataSource/SqlDataSourceService.js'; import { OUTPUT_LOG_TYPES } from './IOutputLogTypes.js'; import { OUTPUT_LOGS_TAB_ID } from './OUTPUT_LOGS_TAB_ID.js'; -import type { IOutputLog } from './OutputLogsResource.js'; +import { type IOutputLog, OutputLogsResource } from './OutputLogsResource.js'; const OUTPUT_LOGS_KEY = 'output_logs'; @@ -22,13 +22,17 @@ interface ISettings { @injectable() export class OutputLogsService { - get settings() { + get settings(): ISettings { return this.userDataService.getUserData(OUTPUT_LOGS_KEY, getOutputLogsDefaultSettings); } - constructor(private readonly sqlDataSourceService: SqlDataSourceService, private readonly userDataService: UserDataService) {} + constructor( + private readonly sqlDataSourceService: SqlDataSourceService, + private readonly userDataService: UserDataService, + private readonly outputLogsResource: OutputLogsResource, + ) {} - async showOutputLogs(editorState: ISqlEditorTabState): Promise { + showOutputLogs(editorState: ISqlEditorTabState): void { this.createOutputLogsTab(editorState); editorState.currentTabId = OUTPUT_LOGS_TAB_ID; } @@ -39,7 +43,7 @@ export class OutputLogsService { } } - toggleWrapMode() { + toggleWrapMode(): void { this.settings.wrapMode = !this.settings.wrapMode; } @@ -61,11 +65,22 @@ export class OutputLogsService { state.tabs.push({ ...tab }); } - getOutputLogs(events: IOutputLog[], editorState: ISqlEditorTabState) { + getOutputLogs(events: IOutputLog[], editorState: ISqlEditorTabState): IOutputLog[] { const dataSource = this.sqlDataSourceService.get(editorState.editorId); return events.filter(event => event.contextId === dataSource?.executionContext?.id); } + + clearOutputLogs(state: ISqlEditorTabState): void { + const dataSource = this.sqlDataSourceService.get(state.editorId); + const contextId = dataSource?.executionContext?.id; + + if (!contextId) { + return; + } + + this.outputLogsResource.deleteLogsByContextId(contextId); + } } function getOutputLogsDefaultSettings(): ISettings { diff --git a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/OutputMenuBootstrap.ts b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/OutputMenuBootstrap.ts index ef6f12e140..00cb9b4c16 100644 --- a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/OutputMenuBootstrap.ts +++ b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/OutputMenuBootstrap.ts @@ -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. @@ -20,6 +20,7 @@ import { OUTPUT_LOGS_FILTER_MENU } from './OUTPUT_LOGS_FILTER_MENU.js'; import { OUTPUT_LOGS_MENU } from './OUTPUT_LOGS_MENU.js'; import { OUTPUT_LOGS_SETTINGS_MENU } from './OUTPUT_LOGS_SETTINGS_MENU.js'; import { OutputLogsService } from './OutputLogsService.js'; +import { ACTION_SQL_EDITOR_CLEAR_OUTPUT_LOGS } from './ACTION_SQL_EDITOR_CLEAR_OUTPUT_LOGS.js'; @injectable() export class OutputMenuBootstrap extends Bootstrap { @@ -37,7 +38,7 @@ export class OutputMenuBootstrap extends Bootstrap { this.menuService.addCreator({ menus: [OUTPUT_LOGS_MENU], getItems(context, items) { - return [...items, OUTPUT_LOGS_FILTER_MENU, OUTPUT_LOGS_SETTINGS_MENU]; + return [...items, ACTION_SQL_EDITOR_CLEAR_OUTPUT_LOGS, OUTPUT_LOGS_FILTER_MENU, OUTPUT_LOGS_SETTINGS_MENU]; }, }); @@ -118,7 +119,7 @@ export class OutputMenuBootstrap extends Bootstrap { private registerOutputLogsAction() { this.actionService.addHandler({ id: 'output-logs-handler', - actions: [ACTION_SHOW_OUTPUT_LOGS], + actions: [ACTION_SHOW_OUTPUT_LOGS, ACTION_SQL_EDITOR_CLEAR_OUTPUT_LOGS], contexts: [DATA_CONTEXT_SQL_EDITOR_STATE], isActionApplicable: (context): boolean => { const state = context.get(DATA_CONTEXT_SQL_EDITOR_STATE)!; @@ -130,12 +131,16 @@ export class OutputMenuBootstrap extends Bootstrap { return !!isQuery && !!isExecutable; }, - handler: async (context, action) => { + handler: (context, action) => { const state = context.get(DATA_CONTEXT_SQL_EDITOR_STATE)!; if (action === ACTION_SHOW_OUTPUT_LOGS) { this.outputLogsService.showOutputLogs(state); } + + if (action === ACTION_SQL_EDITOR_CLEAR_OUTPUT_LOGS) { + this.outputLogsService.clearOutputLogs(state); + } }, }); diff --git a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/useOutputLogsPanelState.ts b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/useOutputLogsPanelState.ts index 5329a669b7..b0330f9324 100644 --- a/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/useOutputLogsPanelState.ts +++ b/webapp/packages/plugin-sql-editor/src/SqlResultTabs/OutputLogs/useOutputLogsPanelState.ts @@ -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. @@ -15,26 +15,31 @@ import type { IOutputLog } from './OutputLogsResource.js'; export interface SqlOutputLogsPanelState { searchValue: string; + outputLogs: IOutputLog[]; + sqlEditorTabState: ISqlEditorTabState; setSearchValue: (value: string) => void; logMessages: WsOutputLogInfo['message'][]; readonly resultValue: string; readonly filteredLogs: WsOutputLogInfo[]; } -export const useOutputLogsPanelState = (outputLogs: IOutputLog[], sqlEditorTabState: ISqlEditorTabState) => + +export const useOutputLogsPanelState = (outputLogs: IOutputLog[], sqlEditorTabState: ISqlEditorTabState): SqlOutputLogsPanelState => useObservableRef( () => ({ + outputLogs, + sqlEditorTabState, searchValue: '', setSearchValue(value: string) { this.searchValue = value; }, get filteredLogs() { - const selectedLogTypes = sqlEditorTabState.outputLogsTab?.selectedLogTypes; + const selectedLogTypes = this.sqlEditorTabState.outputLogsTab?.selectedLogTypes; if (!selectedLogTypes?.length) { return []; } - return outputLogs.filter(log => { + return this.outputLogs.filter(log => { if (log.severity && !selectedLogTypes.includes(log.severity)) { return false; } @@ -65,10 +70,15 @@ export const useOutputLogsPanelState = (outputLogs: IOutputLog[], sqlEditorTabSt }, }), { + outputLogs: observable.ref, + sqlEditorTabState: observable.ref, searchValue: observable.ref, setSearchValue: action.bound, filteredLogs: computed, resultValue: computed, }, - false, + { + outputLogs, + sqlEditorTabState, + }, );