CB-5867 show objects description (#3170)

* CB-5867 show objects description

* CB-5867 add description only to the connection tree

---------

Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
This commit is contained in:
alex
2025-01-10 20:43:17 +03:00
committed by GitHub
co-authored by Daria Marutkina
parent 5f87ef177f
commit 06f8b448ca
16 changed files with 131 additions and 4 deletions
@@ -0,0 +1,11 @@
/*
* 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.
*/
.description {
composes: theme-typography--caption from global;
color: var(--theme-text-hint-on-light);
}
@@ -0,0 +1,26 @@
/*
* 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 { observer } from 'mobx-react-lite';
import { s } from '../../s.js';
import { useS } from '../../useS.js';
import classes from './TreeNodeDescription.module.css';
interface Props extends React.HTMLAttributes<HTMLSpanElement> {
className?: string;
}
export const TreeNodeDescription: React.FC<Props> = observer(function TreeNodeDescription({ className, children, ...rest }) {
const styles = useS(classes);
return (
<span className={s(styles, { description: true }, className)} {...rest}>
{children}
</span>
);
});
+1
View File
@@ -131,6 +131,7 @@ export * from './Tree/TreeNode/TreeNodeControl.js';
export * from './Tree/TreeNode/TreeNodeExpand.js';
export * from './Tree/TreeNode/TreeNodeIcon.js';
export * from './Tree/TreeNode/TreeNodeName.js';
export * from './Tree/TreeNode/TreeNodeDescription.js';
export * from './Tree/TreeNode/TreeNodeNested.js';
export * from './Tree/TreeNode/TreeNodeNestedMessage.js';
export * from './Tree/TreeNode/TreeNodeSelect.js';
@@ -2,6 +2,7 @@ fragment NavNodeInfo on NavigatorNodeInfo {
id
name
plainName
description
hasChildren
nodeType
icon
@@ -0,0 +1,42 @@
/*
* 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 { observer } from 'mobx-react-lite';
import { type PlaceholderComponent, type PlaceholderElement, Switch, useTranslate } from '@cloudbeaver/core-blocks';
import type { IElementsTreeSettingsProps } from './ElementsTreeSettingsService.js';
export const ObjectsDescriptionSettingsForm: PlaceholderComponent<IElementsTreeSettingsProps> = observer(function ObjectsDescriptionSettingsForm({
tree: { root, settings },
}) {
const translate = useTranslate();
if (!settings) {
return null;
}
return (
<Switch
id={`${root}.objectsDescription`}
name="objectsDescription"
state={settings}
disabled={!settings.configurable}
title={translate('app_navigationTree_settings_filter_objects_description')}
mod={['primary', 'dense']}
small
>
{translate('app_navigationTree_settings_filter_objects_description')}
</Switch>
);
});
export const ObjectsDescriptionSettingsPlaceholderElement: PlaceholderElement<IElementsTreeSettingsProps> = {
id: 'settings-objects-description',
component: ObjectsDescriptionSettingsForm,
order: 2,
};
@@ -17,6 +17,7 @@ export function createElementsTreeSettings(defaults?: Partial<IElementsTreeSetti
showFolderExplorerPath: true,
configurable: true,
projects: true,
objectsDescription: true,
...defaults,
};
}
@@ -31,6 +32,7 @@ export function validateElementsTreeSettings(data: any): boolean {
typeof data.foldersTree === 'boolean' &&
typeof data.showFolderExplorerPath === 'boolean' &&
typeof data.configurable === 'boolean' &&
typeof data.projects === 'boolean'
typeof data.projects === 'boolean' &&
typeof data.objectsDescription === 'boolean'
);
}
@@ -8,6 +8,7 @@
export interface INavTreeNodeInfo {
name: string;
description?: string;
tooltip?: string;
icon?: string;
}
@@ -15,6 +15,7 @@ import {
s,
TreeNodeContext,
TreeNodeControl,
TreeNodeDescription,
TreeNodeIcon,
TreeNodeName,
useMouseContextMenu,
@@ -26,6 +27,7 @@ import { useService } from '@cloudbeaver/core-di';
import { EventContext, EventStopPropagationFlag } from '@cloudbeaver/core-events';
import { getNodePlainName, type INodeActions, NavNodeInfoResource, NavTreeResource } from '@cloudbeaver/core-navigation-tree';
import { ElementsTreeContext } from '../../ElementsTreeContext.js';
import type { NavTreeControlComponent } from '../../NavigationNodeComponent.js';
import { TreeNodeMenuLoader } from '../TreeNodeMenu/TreeNodeMenuLoader.js';
import { DATA_ATTRIBUTE_NODE_EDITING } from './DATA_ATTRIBUTE_NODE_EDITING.js';
@@ -52,6 +54,7 @@ export const NavigationNodeControl: NavTreeControlComponent = observer(
const styles = useS(style);
const mouseContextMenu = useMouseContextMenu();
const treeNodeContext = useContext(TreeNodeContext);
const elementsTreeContext = useContext(ElementsTreeContext);
const navNodeInfoResource = useService(NavNodeInfoResource);
const navTreeResource = useService(NavTreeResource);
const error = getComputed(() => !!navNodeInfoResource.getException(node.id) || !!navTreeResource.getException(node.id));
@@ -110,6 +113,7 @@ export const NavigationNodeControl: NavTreeControlComponent = observer(
let icon = nodeInfo.icon;
const name = nodeInfo.name;
const description = nodeInfo.description;
const title = nodeInfo.tooltip;
if (error) {
@@ -145,7 +149,12 @@ export const NavigationNodeControl: NavTreeControlComponent = observer(
{editing ? (
<NavigationNodeEditorLoader name={getNodePlainName(node)} disabled={saving} onSave={editingState.save} onClose={editingState.cancel} />
) : (
<div className={s(styles, { nameBox: true })}>{name}</div>
<div className={s(styles, { nameBox: true })}>
{name}
{elementsTreeContext?.tree.settings?.objectsDescription && description && (
<TreeNodeDescription>{` - ${description}`}</TreeNodeDescription>
)}
</div>
)}
</Loader>
</TreeNodeName>
@@ -0,0 +1,25 @@
/*
* 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 type { NavNodeInfoResource } from '@cloudbeaver/core-navigation-tree';
import type { IElementsTreeCustomNodeInfo } from './useElementsTree.js';
export function transformDescriptionNodeInfo(navNodeInfoResource: NavNodeInfoResource): IElementsTreeCustomNodeInfo {
return function transformDescriptionNodeInfo(nodeId, info) {
const node = navNodeInfoResource.get(nodeId);
if (node?.description && !node.folder) {
return {
...info,
description: node.description,
};
}
return info;
};
}
@@ -77,6 +77,7 @@ export interface IElementsTreeSettings {
showFolderExplorerPath: boolean;
configurable: boolean;
projects: boolean;
objectsDescription: boolean;
}
export interface IElementsTreeOptions {
@@ -24,6 +24,8 @@ import {
createElementsTreeSettings,
validateElementsTreeSettings,
} from './ElementsTree/ElementsTreeTools/NavigationTreeSettings/createElementsTreeSettings.js';
import { ObjectsDescriptionSettingsPlaceholderElement } from './ElementsTree/ElementsTreeTools/NavigationTreeSettings/ObjectsDescriptionSettingsForm.js';
import { transformDescriptionNodeInfo } from './ElementsTree/transformDescriptionNodeInfo.js';
import { transformFilteredNodeInfo } from './ElementsTree/transformFilteredNodeInfo.js';
import type { IElementsTreeSettings } from './ElementsTree/useElementsTree.js';
import elementsTreeToolsStyles from './ElementsTreeTools.module.css';
@@ -77,12 +79,13 @@ export const NavigationTree = observer(function NavigationTree() {
[navNodeInfoResource, projectsService, projectsNavNodeService],
);
const transformFilteredNode = useMemo(() => transformFilteredNodeInfo(navNodeInfoResource), [navNodeInfoResource]);
const transformDescriptionNode = useMemo(() => transformDescriptionNodeInfo(navNodeInfoResource), [navNodeInfoResource]);
const projectFilter = useMemo(
() => navigationTreeProjectFilter(projectsNavNodeService, projectsService, navNodeInfoResource, navTreeResource),
[projectsNavNodeService, projectsService, navNodeInfoResource, navTreeResource],
);
const settingsElements = useMemo(() => [ProjectsSettingsPlaceholderElement], []);
const settingsElements = useMemo(() => [ProjectsSettingsPlaceholderElement, ObjectsDescriptionSettingsPlaceholderElement], []);
return (
<SContext registry={registry}>
@@ -93,7 +96,7 @@ export const NavigationTree = observer(function NavigationTree() {
filters={[duplicateFilter, connectionGroupFilter, projectFilter]}
renderers={[projectsRendererRenderer, navigationTreeConnectionGroupRenderer, connectionRenderer]}
navNodeFilterCompare={navigationTreeProjectSearchCompare}
nodeInfoTransformers={[transformFilteredNode]}
nodeInfoTransformers={[transformFilteredNode, transformDescriptionNode]}
expandStateGetters={[projectsExpandStateGetter]}
settingsElements={settingsElements}
className={s(styles, { elementsTree: true })}
@@ -12,6 +12,7 @@ export default [
['app_navigationTree_limited', 'Elements are limited to {arg:limit} items'],
['app_navigationTree_action_link_with_editor', 'Link with editor'],
['app_navigationTree_action_collapse_all', 'Collapse all'],
['app_navigationTree_settings_filter_objects_description', 'Show objects description'],
['app_navigationTree_settings_filter_title', 'Filter'],
['app_navigationTree_settings_filter_description', 'Show filtering field'],
['app_navigationTree_settings_filter_all_title', 'Show collapsed'],
@@ -12,6 +12,7 @@ export default [
['app_navigationTree_limited', 'Les éléments sont limités à {arg:limit} éléments'],
['app_navigationTree_link_with_editor', "Lier avec l'éditeur"],
['app_navigationTree_action_collapse_all', 'Tout réduire'],
['app_navigationTree_settings_filter_objects_description', 'Show objects description'],
['app_navigationTree_settings_filter_title', 'Filtrer'],
['app_navigationTree_settings_filter_description', 'Affiche les éléments filtrés dans les dossiers réduits'],
['app_navigationTree_settings_filter_all_title', 'Tout filtrer'],
@@ -12,6 +12,7 @@ export default [
['app_navigationTree_limited', 'Elements are limited to {arg:limit} items'],
['app_navigationTree_action_link_with_editor', 'Link with editor'],
['app_navigationTree_action_collapse_all', 'Collapse all'],
['app_navigationTree_settings_filter_objects_description', 'Show objects description'],
['app_navigationTree_settings_filter_title', 'Filter'],
['app_navigationTree_settings_filter_description', 'Show filtering field'],
['app_navigationTree_settings_filter_all_title', 'Show collapsed'],
@@ -13,6 +13,7 @@ export default [
['app_navigationTree_action_link_with_editor', 'Синхронизовать с редактором'],
['app_navigationTree_action_collapse_all', 'Свернуть все элементы'],
['app_navigationTree_settings_filter_objects_description', 'Показывать описание объектов'],
['app_navigationTree_settings_filter_title', 'Фильтр'],
['app_navigationTree_settings_filter_description', 'Показывать фильтр'],
@@ -11,6 +11,7 @@ export default [
['app_navigationTree_limited', '元素数量限制为 {arg:limit} '],
['app_navigationTree_action_link_with_editor', '连接至编辑器'],
['app_navigationTree_action_collapse_all', '收起全部'],
['app_navigationTree_settings_filter_objects_description', 'Show objects description'],
['app_navigationTree_settings_filter_title', '过滤器'],
['app_navigationTree_settings_filter_description', '查看过滤字段'],
['app_navigationTree_settings_filter_all_title', '查看收缩项'],