Skip to content

Commit e7dbf9d

Browse files
authored
feat(ObjectSummary): add button to refresh tree (#1559)
1 parent 4cb2d7f commit e7dbf9d

File tree

9 files changed

+134
-64
lines changed

9 files changed

+134
-64
lines changed

src/containers/Tenant/ObjectSummary/ObjectSummary.scss

+4-2
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,16 @@
2727
visibility: hidden;
2828
}
2929

30-
&__action-button {
30+
&__actions {
3131
position: absolute;
3232
top: 19px; // centered relative to the heading
3333
right: 5px; // centered relative to the collapsed panel
3434

3535
background-color: var(--g-color-base-background);
36+
}
37+
&__button {
3638
&_hidden {
37-
visibility: hidden;
39+
display: none;
3840
}
3941
}
4042

src/containers/Tenant/ObjectSummary/ObjectSummary.tsx

+40-33
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ import {isIndexTableType, isTableType} from '../utils/schema';
4040

4141
import {ObjectTree} from './ObjectTree';
4242
import {SchemaActions} from './SchemaActions';
43+
import {RefreshTreeButton} from './SchemaTree/RefreshTreeButton';
44+
import {TreeKeyProvider} from './UpdateTreeContext';
4345
import i18n from './i18n';
4446
import {b} from './shared';
4547
import {isDomain, transformPath} from './transformPath';
@@ -83,6 +85,7 @@ export function ObjectSummary({
8385
undefined,
8486
getTenantCommonInfoState,
8587
);
88+
8689
const {summaryTab = TENANT_SUMMARY_TABS_IDS.overview} = useTypedSelector(
8790
(state) => state.tenant,
8891
);
@@ -419,43 +422,47 @@ export function ObjectSummary({
419422

420423
const renderContent = () => {
421424
return (
422-
<div className={b()}>
423-
<div className={b({hidden: isCollapsed})}>
424-
<SplitPane
425-
direction="vertical"
426-
defaultSizePaneKey={DEFAULT_SIZE_TENANT_SUMMARY_KEY}
427-
onSplitStartDragAdditional={onSplitStartDragAdditional}
428-
triggerCollapse={commonInfoVisibilityState.triggerCollapse}
429-
triggerExpand={commonInfoVisibilityState.triggerExpand}
430-
minSize={[200, 52]}
431-
collapsedSizes={[100, 0]}
432-
>
433-
<ObjectTree tenantName={tenantName} path={path} />
434-
<div className={b('info')}>
435-
<div className={b('sticky-top')}>
436-
<div className={b('info-header')}>
437-
<div className={b('info-title')}>
438-
{renderEntityTypeBadge()}
439-
<div className={b('path-name')}>{relativePath}</div>
440-
</div>
441-
<div className={b('info-controls')}>
442-
{renderCommonInfoControls()}
425+
<TreeKeyProvider>
426+
<div className={b()}>
427+
<div className={b({hidden: isCollapsed})}>
428+
<SplitPane
429+
direction="vertical"
430+
defaultSizePaneKey={DEFAULT_SIZE_TENANT_SUMMARY_KEY}
431+
onSplitStartDragAdditional={onSplitStartDragAdditional}
432+
triggerCollapse={commonInfoVisibilityState.triggerCollapse}
433+
triggerExpand={commonInfoVisibilityState.triggerExpand}
434+
minSize={[200, 52]}
435+
collapsedSizes={[100, 0]}
436+
>
437+
<ObjectTree tenantName={tenantName} path={path} />
438+
<div className={b('info')}>
439+
<div className={b('sticky-top')}>
440+
<div className={b('info-header')}>
441+
<div className={b('info-title')}>
442+
{renderEntityTypeBadge()}
443+
<div className={b('path-name')}>{relativePath}</div>
444+
</div>
445+
<div className={b('info-controls')}>
446+
{renderCommonInfoControls()}
447+
</div>
443448
</div>
449+
{renderTabs()}
444450
</div>
445-
{renderTabs()}
451+
<div className={b('overview-wrapper')}>{renderTabContent()}</div>
446452
</div>
447-
<div className={b('overview-wrapper')}>{renderTabContent()}</div>
448-
</div>
449-
</SplitPane>
453+
</SplitPane>
454+
</div>
455+
<Flex className={b('actions')} gap={0.5}>
456+
{!isCollapsed && <RefreshTreeButton />}
457+
<PaneVisibilityToggleButtons
458+
onCollapse={onCollapseSummary}
459+
onExpand={onExpandSummary}
460+
isCollapsed={isCollapsed}
461+
initialDirection="left"
462+
/>
463+
</Flex>
450464
</div>
451-
<PaneVisibilityToggleButtons
452-
onCollapse={onCollapseSummary}
453-
onExpand={onExpandSummary}
454-
isCollapsed={isCollapsed}
455-
initialDirection="left"
456-
className={b('action-button')}
457-
/>
458-
</div>
465+
</TreeKeyProvider>
459466
);
460467
};
461468

src/containers/Tenant/ObjectSummary/ObjectTree.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import {StringParam, useQueryParam} from 'use-query-params';
22

33
import {Loader} from '../../../components/Loader';
44
import {useGetSchemaQuery} from '../../../store/reducers/schema/schema';
5-
import {SchemaTree} from '../Schema/SchemaTree/SchemaTree';
65

6+
import {SchemaTree} from './SchemaTree/SchemaTree';
77
import i18n from './i18n';
88
import {b} from './shared';
99

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {ArrowRotateRight} from '@gravity-ui/icons';
2+
import {ActionTooltip, Button, Icon} from '@gravity-ui/uikit';
3+
import {nanoid} from '@reduxjs/toolkit';
4+
5+
import {useDispatchTreeKey} from '../UpdateTreeContext';
6+
7+
export function RefreshTreeButton() {
8+
const updateTreeKey = useDispatchTreeKey();
9+
return (
10+
<ActionTooltip title="Refresh">
11+
<Button
12+
view="flat-secondary"
13+
onClick={() => {
14+
updateTreeKey(nanoid());
15+
}}
16+
>
17+
<Icon data={ArrowRotateRight} />
18+
</Button>
19+
</ActionTooltip>
20+
);
21+
}

src/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx renamed to src/containers/Tenant/ObjectSummary/SchemaTree/SchemaTree.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {getSchemaControls} from '../../utils/controls';
1717
import {isChildlessPathType, mapPathTypeToNavigationTreeType} from '../../utils/schema';
1818
import {getActions} from '../../utils/schemaActions';
1919
import {CreateDirectoryDialog} from '../CreateDirectoryDialog/CreateDirectoryDialog';
20+
import {useDispatchTreeKey, useTreeKey} from '../UpdateTreeContext';
2021

2122
interface SchemaTreeProps {
2223
rootPath: string;
@@ -52,7 +53,8 @@ export function SchemaTree(props: SchemaTreeProps) {
5253
const [querySettings, setQueryExecutionSettings] = useQueryExecutionSettings();
5354
const [createDirectoryOpen, setCreateDirectoryOpen] = React.useState(false);
5455
const [parentPath, setParentPath] = React.useState('');
55-
const [schemaTreeKey, setSchemaTreeKey] = React.useState('');
56+
const setSchemaTreeKey = useDispatchTreeKey();
57+
const schemaTreeKey = useTreeKey();
5658

5759
const fetchPath = async (path: string) => {
5860
let schemaData: TEvDescribeSchemeResult | undefined;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React from 'react';
2+
3+
const TreeKeyContext = React.createContext<string | undefined>(undefined);
4+
const TreeKeyDispatchContext = React.createContext<React.Dispatch<string> | undefined>(undefined);
5+
6+
interface TreeKeyProviderProps {
7+
children: React.ReactNode;
8+
}
9+
10+
export function TreeKeyProvider({children}: TreeKeyProviderProps) {
11+
const [key, setKey] = React.useState<string>('');
12+
13+
return (
14+
<TreeKeyContext.Provider value={key}>
15+
<TreeKeyDispatchContext.Provider value={setKey}>
16+
{children}
17+
</TreeKeyDispatchContext.Provider>
18+
</TreeKeyContext.Provider>
19+
);
20+
}
21+
22+
export function useTreeKey() {
23+
const key = React.useContext(TreeKeyContext);
24+
if (key === undefined) {
25+
throw new Error('useTreeKey must be used within a TreeKeyProvider');
26+
}
27+
return key;
28+
}
29+
export function useDispatchTreeKey() {
30+
const updateKey = React.useContext(TreeKeyDispatchContext);
31+
if (updateKey === undefined) {
32+
throw new Error('useDispatchTreeKey must be used within a TreeKeyProvider');
33+
}
34+
return updateKey;
35+
}

src/containers/Tenant/utils/paneVisibilityToggleHelpers.tsx

+30-27
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22

33
import {ChevronsUp} from '@gravity-ui/icons';
4-
import {Button, Icon} from '@gravity-ui/uikit';
4+
import {ActionTooltip, Button, Icon} from '@gravity-ui/uikit';
55

66
import {cn} from '../../../utils/cn';
77

@@ -84,32 +84,35 @@ export function PaneVisibilityToggleButtons({
8484
}: ToggleButtonProps) {
8585
return (
8686
<React.Fragment>
87-
<Button
88-
view="flat-secondary"
89-
onClick={onCollapse}
90-
className={b(
91-
{
92-
hidden: isCollapsed,
93-
},
94-
className,
95-
)}
96-
title="Collapse"
97-
>
98-
<Icon data={ChevronsUp} className={b({[initialDirection]: true})} />
99-
</Button>
100-
<Button
101-
view="flat-secondary"
102-
onClick={onExpand}
103-
className={b(
104-
{
105-
hidden: !isCollapsed,
106-
},
107-
className,
108-
)}
109-
title="Expand"
110-
>
111-
<Icon data={ChevronsUp} className={b({[initialDirection]: true}, 'rotate')} />
112-
</Button>
87+
<ActionTooltip title="Collapse">
88+
<Button
89+
view="flat-secondary"
90+
onClick={onCollapse}
91+
className={b(
92+
{
93+
hidden: isCollapsed,
94+
},
95+
className,
96+
)}
97+
>
98+
<Icon data={ChevronsUp} className={b({[initialDirection]: true})} />
99+
</Button>
100+
</ActionTooltip>
101+
102+
<ActionTooltip title="Expand">
103+
<Button
104+
view="flat-secondary"
105+
onClick={onExpand}
106+
className={b(
107+
{
108+
hidden: !isCollapsed,
109+
},
110+
className,
111+
)}
112+
>
113+
<Icon data={ChevronsUp} className={b({[initialDirection]: true}, 'rotate')} />
114+
</Button>
115+
</ActionTooltip>
113116
</React.Fragment>
114117
);
115118
}

0 commit comments

Comments
 (0)