Skip to content

Commit d123263

Browse files
feat(Header): add manage DB dropdown (#2680)
1 parent fae206e commit d123263

File tree

7 files changed

+99
-17
lines changed

7 files changed

+99
-17
lines changed

src/containers/Clusters/Clusters.scss

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,6 @@
8080
color: var(--g-color-text-secondary);
8181
}
8282

83-
&__remove-cluster {
84-
color: var(--ydb-color-status-red);
85-
}
86-
8783
&__progress {
8884
--g-progress-filled-background-color: var(--ydb-color-status-green);
8985
}

src/containers/Clusters/columns.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ function getTitleColumn({isEditClusterAvailable, isDeleteClusterAvailable}: Clus
7979
action: () => {
8080
onDeleteCluster({clusterData: row});
8181
},
82-
className: b('remove-cluster'),
82+
theme: 'danger',
8383
});
8484
}
8585

src/containers/Header/Header.tsx

Lines changed: 90 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,41 @@
11
import React from 'react';
22

3-
import {ArrowUpRightFromSquare, CirclePlus, PlugConnection} from '@gravity-ui/icons';
4-
import {Breadcrumbs, Button, Divider, Flex, Icon} from '@gravity-ui/uikit';
5-
import {useLocation} from 'react-router-dom';
3+
import {
4+
ArrowUpRightFromSquare,
5+
ChevronDown,
6+
CirclePlus,
7+
Pencil,
8+
PlugConnection,
9+
TrashBin,
10+
} from '@gravity-ui/icons';
11+
import type {DropdownMenuItem, DropdownMenuProps} from '@gravity-ui/uikit';
12+
import {Breadcrumbs, Button, Divider, DropdownMenu, Flex, Icon} from '@gravity-ui/uikit';
13+
import {skipToken} from '@reduxjs/toolkit/query';
14+
import {useHistory, useLocation} from 'react-router-dom';
615

716
import {getConnectToDBDialog} from '../../components/ConnectToDB/ConnectToDBDialog';
817
import {InternalLink} from '../../components/InternalLink';
9-
import {useAddClusterFeatureAvailable} from '../../store/reducers/capabilities/hooks';
18+
import {
19+
useAddClusterFeatureAvailable,
20+
useDeleteDatabaseFeatureAvailable,
21+
useEditDatabaseFeatureAvailable,
22+
} from '../../store/reducers/capabilities/hooks';
1023
import {useClusterBaseInfo} from '../../store/reducers/cluster/cluster';
24+
import {tenantApi} from '../../store/reducers/tenant/tenant';
1125
import {uiFactory} from '../../uiFactory/uiFactory';
1226
import {cn} from '../../utils/cn';
1327
import {DEVELOPER_UI_TITLE} from '../../utils/constants';
1428
import {createDeveloperUIInternalPageHref} from '../../utils/developerUI/developerUI';
1529
import {useTypedSelector} from '../../utils/hooks';
16-
import {useDatabaseFromQuery} from '../../utils/hooks/useDatabaseFromQuery';
30+
import {
31+
useClusterNameFromQuery,
32+
useDatabaseFromQuery,
33+
} from '../../utils/hooks/useDatabaseFromQuery';
1734
import {
1835
useIsUserAllowedToMakeChanges,
1936
useIsViewerUser,
2037
} from '../../utils/hooks/useIsUserAllowedToMakeChanges';
38+
import {getClusterPath} from '../Cluster/utils';
2139

2240
import {getBreadcrumbs} from './breadcrumbs';
2341
import {headerKeyset} from './i18n';
@@ -35,13 +53,29 @@ function Header() {
3553
const {title: clusterTitle} = useClusterBaseInfo();
3654

3755
const database = useDatabaseFromQuery();
56+
const clusterName = useClusterNameFromQuery();
57+
3858
const location = useLocation();
59+
const history = useHistory();
60+
3961
const isDatabasePage = location.pathname === '/tenant';
4062
const isClustersPage = location.pathname === '/clusters';
4163

4264
const isAddClusterAvailable =
4365
useAddClusterFeatureAvailable() && uiFactory.onAddCluster !== undefined;
4466

67+
const isEditDBAvailable = useEditDatabaseFeatureAvailable() && uiFactory.onEditDB !== undefined;
68+
const isDeleteDBAvailable =
69+
useDeleteDatabaseFeatureAvailable() && uiFactory.onDeleteDB !== undefined;
70+
71+
const shouldRequestTenantData =
72+
database && isDatabasePage && (isEditDBAvailable || isDeleteDBAvailable);
73+
74+
const params = shouldRequestTenantData ? {path: database, clusterName} : skipToken;
75+
76+
const {currentData: databaseData, isLoading: isDatabaseDataLoading} =
77+
tenantApi.useGetTenantInfoQuery(params);
78+
4579
const breadcrumbItems = React.useMemo(() => {
4680
let options = {
4781
...pageBreadcrumbsOptions,
@@ -82,6 +116,57 @@ function Header() {
82116
{headerKeyset('connect')}
83117
</Button>,
84118
);
119+
120+
const menuItems: DropdownMenuItem[] = [];
121+
122+
const {onEditDB, onDeleteDB} = uiFactory;
123+
124+
const isEnoughData = clusterName && databaseData;
125+
126+
if (isEditDBAvailable && onEditDB && isEnoughData) {
127+
menuItems.push({
128+
text: headerKeyset('action_edit-db'),
129+
iconStart: <Pencil />,
130+
action: () => {
131+
onEditDB({clusterName, databaseData});
132+
},
133+
});
134+
}
135+
if (isDeleteDBAvailable && onDeleteDB && isEnoughData) {
136+
menuItems.push({
137+
text: headerKeyset('action_delete-db'),
138+
iconStart: <TrashBin />,
139+
action: () => {
140+
onDeleteDB({clusterName, databaseData}).then((isDeleted) => {
141+
if (isDeleted) {
142+
const path = getClusterPath('tenants');
143+
history.push(path);
144+
}
145+
});
146+
},
147+
theme: 'danger',
148+
});
149+
}
150+
151+
if (menuItems.length) {
152+
const renderSwitcher: DropdownMenuProps<unknown>['renderSwitcher'] = (props) => {
153+
return (
154+
<Button {...props} loading={isDatabaseDataLoading} view="flat" size="m">
155+
{headerKeyset('action_manage')}
156+
<Icon data={ChevronDown} />
157+
</Button>
158+
);
159+
};
160+
161+
elements.push(
162+
<DropdownMenu
163+
items={menuItems}
164+
renderSwitcher={renderSwitcher}
165+
menuProps={{size: 'l'}}
166+
popupProps={{placement: 'bottom-end'}}
167+
/>,
168+
);
169+
}
85170
}
86171

87172
if (!isClustersPage && isUserAllowedToMakeChanges) {

src/containers/Header/i18n/en.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,9 @@
99
"breadcrumbs.storageGroup": "Storage Group",
1010

1111
"connect": "Connect",
12-
"add-cluster": "Add Cluster"
12+
"add-cluster": "Add Cluster",
13+
14+
"action_edit-db": "Edit database",
15+
"action_delete-db": "Delete database",
16+
"action_manage": "Manage"
1317
}

src/containers/Tenants/Tenants.scss

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,4 @@
6565

6666
margin: 0 0 0 auto;
6767
}
68-
69-
&__remove-db {
70-
color: var(--ydb-color-status-red);
71-
}
7268
}

src/containers/Tenants/Tenants.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ function getDBActionsColumn({
374374
databaseData: row,
375375
});
376376
},
377-
className: b('remove-db'),
377+
theme: 'danger',
378378
});
379379
}
380380

src/store/reducers/tenant/tenant.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {TTenantInfo} from '../../../types/api/tenant';
66
import {TENANT_INITIAL_PAGE_KEY} from '../../../utils/constants';
77
import {useClusterNameFromQuery} from '../../../utils/hooks/useDatabaseFromQuery';
88
import {api} from '../api';
9+
import {prepareTenants} from '../tenants/utils';
910

1011
import {TENANT_DIAGNOSTICS_TABS_IDS, TENANT_METRICS_TABS_IDS} from './constants';
1112
import {tenantPageSchema} from './types';
@@ -74,7 +75,7 @@ export const tenantApi = api.injectEndpoints({
7475
} else {
7576
tenantData = await window.api.viewer.getTenantInfo({path}, {signal});
7677
}
77-
const databases = tenantData.TenantInfo || [];
78+
const databases = prepareTenants(tenantData.TenantInfo || []);
7879
// previous meta versions do not support filtering databases by name
7980
const data =
8081
databases.find((tenant) => tenant.Name === path) ?? databases[0] ?? null;

0 commit comments

Comments
 (0)