diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/NavigationTreeBootstrap.ts b/webapp/packages/plugin-navigation-tree/src/NavigationTree/NavigationTreeBootstrap.ts index 21ec05be2d..c3a522688e 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/NavigationTreeBootstrap.ts +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/NavigationTreeBootstrap.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2025 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -10,17 +10,19 @@ import { Bootstrap, injectable } from '@cloudbeaver/core-di'; import { LeftBarPanelService } from '@cloudbeaver/core-ui'; import { NavigationTreeSettingsService } from '../NavigationTreeSettingsService.js'; +import { TreeSettingsMenuService } from '../TreeNew/TreeSettingsMenuService.js'; import { TreeToolbarMenuService } from '../TreeNew/TreeToolbarMenuService.js'; import { ElementsTreeToolsMenuService } from './ElementsTree/ElementsTreeTools/ElementsTreeToolsMenuService.js'; const NavigationTreePanel = importLazyComponent(() => import('./NavigationTreePanel.js').then(m => m.NavigationTreePanel)); -@injectable(() => [NavigationTreeSettingsService, ElementsTreeToolsMenuService, TreeToolbarMenuService, LeftBarPanelService]) +@injectable(() => [NavigationTreeSettingsService, ElementsTreeToolsMenuService, TreeToolbarMenuService, TreeSettingsMenuService, LeftBarPanelService]) export class NavigationTreeBootstrap extends Bootstrap { constructor( private readonly navigationTreeSettingsService: NavigationTreeSettingsService, private readonly elementsTreeToolsMenuService: ElementsTreeToolsMenuService, private readonly treeToolbarMenuService: TreeToolbarMenuService, + private readonly treeSettingsMenuService: TreeSettingsMenuService, private readonly leftBarPanelService: LeftBarPanelService, ) { super(); @@ -29,6 +31,7 @@ export class NavigationTreeBootstrap extends Bootstrap { override register(): void { this.elementsTreeToolsMenuService.register(); this.treeToolbarMenuService.register(); + this.treeSettingsMenuService.register(); this.leftBarPanelService.tabsContainer.add({ key: 'navigation-tree-tab', order: 0, diff --git a/webapp/packages/plugin-navigation-tree/src/TreeNew/DATA_CONTEXT_TREE.ts b/webapp/packages/plugin-navigation-tree/src/TreeNew/DATA_CONTEXT_TREE.ts index ebde4963d7..5c156cc8ef 100644 --- a/webapp/packages/plugin-navigation-tree/src/TreeNew/DATA_CONTEXT_TREE.ts +++ b/webapp/packages/plugin-navigation-tree/src/TreeNew/DATA_CONTEXT_TREE.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2025 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -8,11 +8,13 @@ import { createDataContext } from '@cloudbeaver/core-data-context'; import type { ITreeData } from './ITreeData.js'; -import type { ITreeFilter } from './useTreeFilter.js'; +import type { ITreeFilter, ITreeFilterState } from './useTreeFilter.js'; +import type { ITreeSettings } from './useTreeSettings.js'; -export type ITreeToolbarFilter = ITreeFilter & { filterPlaceholder?: string }; +export type ITreeToolbarFilter = ITreeFilter & ITreeFilterState & { filterPlaceholder?: string }; export type TreeRefreshHandler = () => Promise; export const DATA_CONTEXT_TREE_DATA = createDataContext('tree-new-data'); export const DATA_CONTEXT_TREE_FILTER = createDataContext('tree-new-filter'); export const DATA_CONTEXT_TREE_REFRESH = createDataContext('tree-new-refresh'); +export const DATA_CONTEXT_TREE_SETTINGS = createDataContext('tree-new-settings'); diff --git a/webapp/packages/plugin-navigation-tree/src/TreeNew/MENU_TREE_SETTINGS.ts b/webapp/packages/plugin-navigation-tree/src/TreeNew/MENU_TREE_SETTINGS.ts new file mode 100644 index 0000000000..3296b09749 --- /dev/null +++ b/webapp/packages/plugin-navigation-tree/src/TreeNew/MENU_TREE_SETTINGS.ts @@ -0,0 +1,13 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2026 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 { createMenu } from '@cloudbeaver/core-view'; + +export const MENU_TREE_SETTINGS = createMenu('tree-settings', { + label: 'plugin_navigation_tree_settings_menu_title', + icon: '/icons/settings_cog_sm.svg', +}); diff --git a/webapp/packages/plugin-navigation-tree/src/TreeNew/TreeSettingsMenuService.ts b/webapp/packages/plugin-navigation-tree/src/TreeNew/TreeSettingsMenuService.ts new file mode 100644 index 0000000000..c90e1f5920 --- /dev/null +++ b/webapp/packages/plugin-navigation-tree/src/TreeNew/TreeSettingsMenuService.ts @@ -0,0 +1,82 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2026 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 type { IDataContextProvider } from '@cloudbeaver/core-data-context'; +import { injectable } from '@cloudbeaver/core-di'; +import { ActionService, type IAction, MenuService } from '@cloudbeaver/core-view'; + +import { DATA_CONTEXT_TREE_SETTINGS } from './DATA_CONTEXT_TREE.js'; +import { MENU_TREE_SETTINGS } from './MENU_TREE_SETTINGS.js'; +import { ACTION_TREE_SAVE_STATE } from './actions/ACTION_TREE_SAVE_STATE.js'; +import { ACTION_TREE_SHOW_DESCRIPTIONS } from './actions/ACTION_TREE_SHOW_DESCRIPTIONS.js'; +import { ACTION_TREE_SHOW_FILTER } from './actions/ACTION_TREE_SHOW_FILTER.js'; +import { TREE_SETTINGS_FILTER_ENABLED } from './useTreeFilter.js'; + +export const TREE_SETTINGS_SHOW_DESCRIPTIONS = 'tree.showDescriptions'; +export const TREE_SETTINGS_SAVE_STATE = 'tree.saveState'; + +@injectable(() => [ActionService, MenuService]) +export class TreeSettingsMenuService { + constructor( + private readonly actionService: ActionService, + private readonly menuService: MenuService, + ) { } + + register(): void { + this.actionService.addHandler({ + id: 'tree-settings-handler', + menus: [MENU_TREE_SETTINGS], + actions: [ACTION_TREE_SHOW_FILTER, ACTION_TREE_SHOW_DESCRIPTIONS, ACTION_TREE_SAVE_STATE], + contexts: [DATA_CONTEXT_TREE_SETTINGS], + isActionApplicable(context: IDataContextProvider): boolean { + const settings = context.get(DATA_CONTEXT_TREE_SETTINGS); + return settings !== undefined; + }, + isChecked(context: IDataContextProvider, action: IAction): boolean { + const settings = context.get(DATA_CONTEXT_TREE_SETTINGS); + + if (!settings) { + return false; + } + + if (action === ACTION_TREE_SHOW_FILTER) { + return settings.get(TREE_SETTINGS_FILTER_ENABLED) ?? false; + } + + if (action === ACTION_TREE_SHOW_DESCRIPTIONS) { + return settings.get(TREE_SETTINGS_SHOW_DESCRIPTIONS) ?? false; + } + + if (action === ACTION_TREE_SAVE_STATE) { + return settings.get(TREE_SETTINGS_SAVE_STATE) ?? false; + } + + return false; + }, + handler(context: IDataContextProvider, action: IAction): void { + const settings = context.get(DATA_CONTEXT_TREE_SETTINGS); + + if (!settings) { + return; + } + + if (action === ACTION_TREE_SHOW_FILTER) { + settings.set(TREE_SETTINGS_FILTER_ENABLED, !(settings.get(TREE_SETTINGS_FILTER_ENABLED) ?? false)); + } else if (action === ACTION_TREE_SHOW_DESCRIPTIONS) { + settings.set(TREE_SETTINGS_SHOW_DESCRIPTIONS, !(settings.get(TREE_SETTINGS_SHOW_DESCRIPTIONS) ?? false)); + } else if (action === ACTION_TREE_SAVE_STATE) { + settings.set(TREE_SETTINGS_SAVE_STATE, !(settings.get(TREE_SETTINGS_SAVE_STATE) ?? false)); + } + }, + }); + + this.menuService.addCreator({ + menus: [MENU_TREE_SETTINGS], + getItems: (context, items) => [...items, ACTION_TREE_SHOW_FILTER, ACTION_TREE_SHOW_DESCRIPTIONS, ACTION_TREE_SAVE_STATE], + }); + } +} diff --git a/webapp/packages/plugin-navigation-tree/src/TreeNew/TreeToolbar.tsx b/webapp/packages/plugin-navigation-tree/src/TreeNew/TreeToolbar.tsx index 089ab8b4fe..d42b51efe2 100644 --- a/webapp/packages/plugin-navigation-tree/src/TreeNew/TreeToolbar.tsx +++ b/webapp/packages/plugin-navigation-tree/src/TreeNew/TreeToolbar.tsx @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2025 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -8,22 +8,37 @@ import React, { use } from 'react'; import { observer } from 'mobx-react-lite'; -import { DATA_CONTEXT_TREE_DATA, DATA_CONTEXT_TREE_FILTER, DATA_CONTEXT_TREE_REFRESH, type ITreeToolbarFilter } from './DATA_CONTEXT_TREE.js'; +import { + DATA_CONTEXT_TREE_DATA, + DATA_CONTEXT_TREE_FILTER, + DATA_CONTEXT_TREE_REFRESH, + DATA_CONTEXT_TREE_SETTINGS, + type ITreeToolbarFilter, +} from './DATA_CONTEXT_TREE.js'; +import type { ITreeSettings } from './useTreeSettings.js'; import { clsx } from '@dbeaver/ui-kit'; import { useCaptureViewContext } from '@cloudbeaver/core-view'; import { TreeDataContext } from './contexts/TreeDataContext.js'; export interface TreeToolbarProps { + settings?: ITreeSettings; filter?: ITreeToolbarFilter; onRefresh?: () => Promise | void; className?: string; } -export const TreeToolbar = observer>(function TreeToolbar({ className, children, filter, onRefresh }) { +export const TreeToolbar = observer>(function TreeToolbar({ + className, + children, + settings, + filter, + onRefresh, +}) { const data = use(TreeDataContext); useCaptureViewContext((context, id) => { context.set(DATA_CONTEXT_TREE_DATA, data, id); + context.set(DATA_CONTEXT_TREE_SETTINGS, settings, id); context.set(DATA_CONTEXT_TREE_FILTER, filter, id); context.set(DATA_CONTEXT_TREE_REFRESH, onRefresh, id); }); diff --git a/webapp/packages/plugin-navigation-tree/src/TreeNew/TreeToolbarFilter.tsx b/webapp/packages/plugin-navigation-tree/src/TreeNew/TreeToolbarFilter.tsx index 6a53cd4009..0d2b05e320 100644 --- a/webapp/packages/plugin-navigation-tree/src/TreeNew/TreeToolbarFilter.tsx +++ b/webapp/packages/plugin-navigation-tree/src/TreeNew/TreeToolbarFilter.tsx @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2025 DBeaver Corp and others + * Copyright (C) 2020-2026 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,7 +20,7 @@ export const TreeToolbarFilter = observer(function TreeToolbarFilter() { const context = useDataContext(viewContext); const filter = context.get(DATA_CONTEXT_TREE_FILTER); - if (!filter) { + if (!filter?.enabled) { return null; } diff --git a/webapp/packages/plugin-navigation-tree/src/TreeNew/TreeToolbarMenuService.ts b/webapp/packages/plugin-navigation-tree/src/TreeNew/TreeToolbarMenuService.ts index e60b1ac7d8..5bad47f76c 100644 --- a/webapp/packages/plugin-navigation-tree/src/TreeNew/TreeToolbarMenuService.ts +++ b/webapp/packages/plugin-navigation-tree/src/TreeNew/TreeToolbarMenuService.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2025 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -10,6 +10,7 @@ import { injectable } from '@cloudbeaver/core-di'; import { ACTION_COLLAPSE_ALL, ActionService, type IAction, MenuService } from '@cloudbeaver/core-view'; import { DATA_CONTEXT_TREE_DATA, DATA_CONTEXT_TREE_REFRESH } from './DATA_CONTEXT_TREE.js'; +import { MENU_TREE_SETTINGS } from './MENU_TREE_SETTINGS.js'; import { MENU_TREE_TOOLBAR } from './MENU_TREE_TOOLBAR.js'; import { ACTION_TREE_REFRESH } from './actions/ACTION_TREE_REFRESH.js'; @@ -51,7 +52,7 @@ export class TreeToolbarMenuService { this.menuService.addCreator({ menus: [MENU_TREE_TOOLBAR], - getItems: (_, items) => [...items, ACTION_TREE_REFRESH, ACTION_COLLAPSE_ALL], + getItems: (_, items) => [...items, MENU_TREE_SETTINGS, ACTION_TREE_REFRESH, ACTION_COLLAPSE_ALL], }); } diff --git a/webapp/packages/plugin-navigation-tree/src/TreeNew/actions/ACTION_TREE_SAVE_STATE.ts b/webapp/packages/plugin-navigation-tree/src/TreeNew/actions/ACTION_TREE_SAVE_STATE.ts new file mode 100644 index 0000000000..d8402e3ca1 --- /dev/null +++ b/webapp/packages/plugin-navigation-tree/src/TreeNew/actions/ACTION_TREE_SAVE_STATE.ts @@ -0,0 +1,14 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2026 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_TREE_SAVE_STATE = createAction('tree-save-state', { + label: 'plugin_navigation_tree_settings_save_state', + type: 'checkbox', +}); diff --git a/webapp/packages/plugin-navigation-tree/src/TreeNew/actions/ACTION_TREE_SHOW_DESCRIPTIONS.ts b/webapp/packages/plugin-navigation-tree/src/TreeNew/actions/ACTION_TREE_SHOW_DESCRIPTIONS.ts new file mode 100644 index 0000000000..8fba75e0b6 --- /dev/null +++ b/webapp/packages/plugin-navigation-tree/src/TreeNew/actions/ACTION_TREE_SHOW_DESCRIPTIONS.ts @@ -0,0 +1,14 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2026 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_TREE_SHOW_DESCRIPTIONS = createAction('tree-show-descriptions', { + label: 'plugin_navigation_tree_settings_show_descriptions', + type: 'checkbox', +}); diff --git a/webapp/packages/plugin-navigation-tree/src/TreeNew/actions/ACTION_TREE_SHOW_FILTER.ts b/webapp/packages/plugin-navigation-tree/src/TreeNew/actions/ACTION_TREE_SHOW_FILTER.ts new file mode 100644 index 0000000000..77ad2b6291 --- /dev/null +++ b/webapp/packages/plugin-navigation-tree/src/TreeNew/actions/ACTION_TREE_SHOW_FILTER.ts @@ -0,0 +1,14 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2026 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_TREE_SHOW_FILTER = createAction('tree-show-filter', { + label: 'plugin_navigation_tree_settings_show_filter', + type: 'checkbox', +}); diff --git a/webapp/packages/plugin-navigation-tree/src/TreeNew/useTreeFilter.ts b/webapp/packages/plugin-navigation-tree/src/TreeNew/useTreeFilter.ts index 88e238fb12..7d6cc69fb2 100644 --- a/webapp/packages/plugin-navigation-tree/src/TreeNew/useTreeFilter.ts +++ b/webapp/packages/plugin-navigation-tree/src/TreeNew/useTreeFilter.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2025 DBeaver Corp and others + * Copyright (C) 2020-2026 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,6 +12,7 @@ import { useObjectRef, useObservableRef } from '@cloudbeaver/core-blocks'; import type { TreeDataTransformer } from './DataTransformers/TreeDataTransformer.js'; import type { ITreeData } from './ITreeData.js'; import type { INodeState } from './INodeState.js'; +import type { ITreeSettings } from './useTreeSettings.js'; export interface ITreeFilterOptions { isNodeMatched?: (nodeId: string, filter: string, isMatched: boolean) => boolean; @@ -25,7 +26,22 @@ export interface ITreeFilter { setFilter(filter: string): void; } -export function useTreeFilter(options: ITreeFilterOptions = {}): Readonly { +export interface ITreeFilterState { + enabled: boolean; +} + +export type ITreeFilterWithState = Readonly; + +export const TREE_SETTINGS_FILTER_ENABLED = 'tree.filter.enabled'; + +interface ITreeFilterStateObject extends ITreeFilter, ITreeFilterState { + settings?: ITreeSettings; +} + +export function useTreeFilter( + options: ITreeFilterOptions = {}, + settings?: ITreeSettings, +): ITreeFilterWithState { options = useObjectRef(options); const matchCache = new Map(); @@ -57,9 +73,13 @@ export function useTreeFilter(options: ITreeFilterOptions = {}): Readonly( + return useObservableRef( () => ({ + settings, filter: '', + get enabled() { + return this.settings?.get(TREE_SETTINGS_FILTER_ENABLED) ?? false; + }, isNodeMatched(treeData: ITreeData, nodeId: string): boolean { const filter = this.filter.trim(); if (!filter) { @@ -75,6 +95,10 @@ export function useTreeFilter(options: ITreeFilterOptions = {}): Readonly 0; }, transformer(treeData: ITreeData, nodeId: string, children: string[]): string[] { + if (!this.enabled) { + return children; + } + const filter = this.filter.trim(); if (!filter) { return children; @@ -93,6 +117,10 @@ export function useTreeFilter(options: ITreeFilterOptions = {}): Readonly this.isNodeMatched(treeData, child)); }, stateTransformer(treeData: ITreeData, nodeId: string, state: INodeState): INodeState { + if (!this.enabled) { + return state; + } + const filter = this.filter.trim(); if (!filter) { return state; @@ -110,9 +138,10 @@ export function useTreeFilter(options: ITreeFilterOptions = {}): Readonly(key: string): T | undefined; + set(key: string, value: T): void; + delete(key: string): void; + clear(): void; + replace(entries: Record): void; +} + +export interface ITreeSettingsOptions { + initialSettings?: Record; + onChange?(entities: ReadonlyMap): void; +} + +export function useTreeSettings(options: ITreeSettingsOptions = {}): ITreeSettings { + const { initialSettings = {}, onChange } = options; + + return useObservableRef( + () => ({ + settings: observable.map(initialSettings), + get(key: string): T | undefined { + return this.settings.get(key) as T | undefined; + }, + set(key: string, value: T): void { + this.settings.set(key, value); + onChange?.(this.settings); + }, + delete(key: string): void { + this.settings.delete(key); + onChange?.(this.settings); + }, + clear(): void { + this.settings.clear(); + onChange?.(this.settings); + }, + replace(entries: Record): void { + this.settings.replace(entries); + }, + }), + { + settings: observable.ref, + set: action.bound, + delete: action.bound, + clear: action.bound, + replace: action.bound, + }, + false, + ); +} \ No newline at end of file diff --git a/webapp/packages/plugin-navigation-tree/src/TreeNew/useUserTreeSettings.ts b/webapp/packages/plugin-navigation-tree/src/TreeNew/useUserTreeSettings.ts new file mode 100644 index 0000000000..b523ba36c0 --- /dev/null +++ b/webapp/packages/plugin-navigation-tree/src/TreeNew/useUserTreeSettings.ts @@ -0,0 +1,59 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2026 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 { useEffect, useRef } from 'react'; + +import { useUserData } from '@cloudbeaver/core-blocks'; + +import { type ITreeSettings, useTreeSettings } from './useTreeSettings.js'; + +function validateRecord(data: unknown): boolean { + return typeof data === 'object' && data !== null && !Array.isArray(data); +} + +export function useUserTreeSettings(settingsId: string): ITreeSettings { + const persistedSettingsRef = useRef | null>(null); + const treeSettingsRef = useRef(null); + + const persistedSettings = useUserData>( + settingsId, + () => ({}), + data => { + treeSettingsRef.current?.replace(data); + }, + validateRecord, + ); + + const treeSettings = useTreeSettings({ + initialSettings: persistedSettings, + onChange(newSettings) { + const current = persistedSettingsRef.current; + + if (!current) { + return; + } + + for (const key of Object.keys(current)) { + if (!newSettings.has(key)) { + delete current[key]; + } + } + + for (const [key, value] of newSettings) { + current[key] = value; + } + }, + }); + + useEffect(() => { + persistedSettingsRef.current = persistedSettings; + treeSettingsRef.current = treeSettings; + }); + + return treeSettings; +} diff --git a/webapp/packages/plugin-navigation-tree/src/index.ts b/webapp/packages/plugin-navigation-tree/src/index.ts index 2e7d9b4c78..8f0aa6ead4 100644 --- a/webapp/packages/plugin-navigation-tree/src/index.ts +++ b/webapp/packages/plugin-navigation-tree/src/index.ts @@ -54,6 +54,8 @@ export * from './TreeNew/NodeControlLazy.js'; export * from './TreeNew/useTreeData.js'; export * from './TreeNew/ITreeData.js'; export * from './TreeNew/useTreeFilter.js'; +export * from './TreeNew/useTreeSettings.js'; +export * from './TreeNew/useUserTreeSettings.js'; export * from './TreeNew/useTreeSelection.js'; export * from './TreeNew/useTreeClickSelection.js'; export * from './TreeNew/ITreeSelection.js'; @@ -65,7 +67,12 @@ export * from './TreeNew/TreeToolbarMenuLazy.js'; export * from './TreeNew/TreeToolbarMenuService.js'; export * from './TreeNew/DATA_CONTEXT_TREE.js'; export * from './TreeNew/MENU_TREE_TOOLBAR.js'; +export * from './TreeNew/MENU_TREE_SETTINGS.js'; export * from './TreeNew/actions/ACTION_TREE_REFRESH.js'; +export * from './TreeNew/actions/ACTION_TREE_SHOW_FILTER.js'; +export * from './TreeNew/actions/ACTION_TREE_SHOW_DESCRIPTIONS.js'; +export * from './TreeNew/actions/ACTION_TREE_SAVE_STATE.js'; +export * from './TreeNew/TreeSettingsMenuService.js'; export * from './NavigationTree/getNavigationTreeUserSettingsId.js'; export * from './NodesManager/NavNodeView/IFolderTransform.js'; diff --git a/webapp/packages/plugin-navigation-tree/src/locales/en.ts b/webapp/packages/plugin-navigation-tree/src/locales/en.ts index 97890e0f63..c1a2b325ab 100644 --- a/webapp/packages/plugin-navigation-tree/src/locales/en.ts +++ b/webapp/packages/plugin-navigation-tree/src/locales/en.ts @@ -35,4 +35,8 @@ export default [ ['plugin_navigation_tree_settings_disable', 'Disable'], ['plugin_navigation_tree_settings_disable_description', 'Disable navigation tree for all users'], ['plugin_navigation_tree_toolbar_menu_title', 'Tree Toolbar'], + ['plugin_navigation_tree_settings_menu_title', 'Tree settings'], + ['plugin_navigation_tree_settings_show_filter', 'Show filter'], + ['plugin_navigation_tree_settings_show_descriptions', 'Show descriptions'], + ['plugin_navigation_tree_settings_save_state', 'Save tree state'], ]; diff --git a/webapp/packages/plugin-navigation-tree/src/locales/fr.ts b/webapp/packages/plugin-navigation-tree/src/locales/fr.ts index c51d85c01d..7d26886027 100644 --- a/webapp/packages/plugin-navigation-tree/src/locales/fr.ts +++ b/webapp/packages/plugin-navigation-tree/src/locales/fr.ts @@ -36,4 +36,5 @@ export default [ ['plugin_navigation_tree_settings_disable', 'Désactiver'], ['plugin_navigation_tree_settings_disable_description', 'Désactiver l’arborescence de navigation pour tous les utilisateurs'], ['plugin_navigation_tree_toolbar_menu_title', "Barre d'outils de l'arborescence"], + ['plugin_navigation_tree_settings_menu_title', "Paramètres de l'arborescence"], ]; diff --git a/webapp/packages/plugin-navigation-tree/src/locales/it.ts b/webapp/packages/plugin-navigation-tree/src/locales/it.ts index 979e190857..c4bdbeec41 100644 --- a/webapp/packages/plugin-navigation-tree/src/locales/it.ts +++ b/webapp/packages/plugin-navigation-tree/src/locales/it.ts @@ -32,4 +32,5 @@ export default [ ['plugin_navigation_tree_settings_disable', 'Disabilita'], ['plugin_navigation_tree_settings_disable_description', "Disabilita l'albero di navigazione per tutti gli utenti"], ['plugin_navigation_tree_toolbar_menu_title', "Barra degli strumenti dell'albero"], + ['plugin_navigation_tree_settings_menu_title', "Impostazioni dell'albero"], ]; diff --git a/webapp/packages/plugin-navigation-tree/src/locales/ru.ts b/webapp/packages/plugin-navigation-tree/src/locales/ru.ts index 77334229e4..6d703bf690 100644 --- a/webapp/packages/plugin-navigation-tree/src/locales/ru.ts +++ b/webapp/packages/plugin-navigation-tree/src/locales/ru.ts @@ -38,4 +38,8 @@ export default [ ['plugin_navigation_tree_settings_disable', 'Отключить'], ['plugin_navigation_tree_settings_disable_description', 'Отключить дерево навигации для всех пользователей'], ['plugin_navigation_tree_toolbar_menu_title', 'Панель инструментов дерева'], + ['plugin_navigation_tree_settings_menu_title', 'Настройки дерева'], + ['plugin_navigation_tree_settings_show_filter', 'Показывать фильтр'], + ['plugin_navigation_tree_settings_show_descriptions', 'Показывать описания'], + ['plugin_navigation_tree_settings_save_state', 'Сохранять состояние дерева'], ]; diff --git a/webapp/packages/plugin-navigation-tree/src/locales/vi.ts b/webapp/packages/plugin-navigation-tree/src/locales/vi.ts index 8c08521d3d..1828af1f64 100644 --- a/webapp/packages/plugin-navigation-tree/src/locales/vi.ts +++ b/webapp/packages/plugin-navigation-tree/src/locales/vi.ts @@ -35,4 +35,5 @@ export default [ ['plugin_navigation_tree_settings_disable', 'Tắt'], ['plugin_navigation_tree_settings_disable_description', 'Tắt cây điều hướng cho tất cả người dùng'], ['plugin_navigation_tree_toolbar_menu_title', 'Menu Thanh công cụ Cây'], + ['plugin_navigation_tree_settings_menu_title', 'Cài đặt Cây'], ]; diff --git a/webapp/packages/plugin-navigation-tree/src/locales/zh.ts b/webapp/packages/plugin-navigation-tree/src/locales/zh.ts index da5ab80586..3e59a5793c 100644 --- a/webapp/packages/plugin-navigation-tree/src/locales/zh.ts +++ b/webapp/packages/plugin-navigation-tree/src/locales/zh.ts @@ -34,4 +34,5 @@ export default [ ['plugin_navigation_tree_settings_disable', 'Disable'], ['plugin_navigation_tree_settings_disable_description', 'Disable navigation tree for all users'], ['plugin_navigation_tree_toolbar_menu_title', '树工具栏菜单'], + ['plugin_navigation_tree_settings_menu_title', '树设置'], ]; diff --git a/webapp/packages/plugin-navigation-tree/src/module.ts b/webapp/packages/plugin-navigation-tree/src/module.ts index 5f900f2f8e..4456e1d96e 100644 --- a/webapp/packages/plugin-navigation-tree/src/module.ts +++ b/webapp/packages/plugin-navigation-tree/src/module.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2025 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ import { ElementsTreeSettingsService } from './NavigationTree/ElementsTree/Eleme import { ElementsTreeToolsMenuService } from './NavigationTree/ElementsTree/ElementsTreeTools/ElementsTreeToolsMenuService.js'; import { ElementsTreeService } from './NavigationTree/ElementsTree/ElementsTreeService.js'; import { TreeToolbarMenuService } from './TreeNew/TreeToolbarMenuService.js'; +import { TreeSettingsMenuService } from './TreeNew/TreeSettingsMenuService.js'; import { LocaleService } from './LocaleService.js'; export default ModuleRegistry.add({ @@ -37,6 +38,7 @@ export default ModuleRegistry.add({ .addSingleton(ElementsTreeSettingsService) .addSingleton(ElementsTreeToolsMenuService) .addSingleton(TreeToolbarMenuService) + .addSingleton(TreeSettingsMenuService) .addSingleton(ElementsTreeService); }, });