ydb-embedded-ui 3.1.0 → 3.2.1
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +30 -0
- package/README.md +2 -0
- package/dist/components/DateRange/DateRange.scss +11 -0
- package/dist/{containers/Tenant/Diagnostics/TopShards → components}/DateRange/DateRange.tsx +7 -7
- package/dist/{containers/Tenant/Diagnostics/TopShards → components}/DateRange/index.ts +0 -0
- package/dist/components/EntitiesCount/EntitiesCount.tsx +34 -0
- package/dist/components/EntitiesCount/i18n/en.json +3 -0
- package/dist/components/{AsideNavigation/Settings → EntitiesCount}/i18n/index.ts +2 -2
- package/dist/components/EntitiesCount/i18n/ru.json +3 -0
- package/dist/components/EntitiesCount/index.ts +1 -0
- package/dist/components/Fullscreen/Fullscreen.scss +7 -5
- package/dist/components/Illustration/Illustration.tsx +4 -11
- package/dist/components/InfoViewer/InfoViewer.scss +2 -0
- package/dist/components/TabletsOverall/TabletsOverall.tsx +4 -4
- package/dist/components/TabletsStatistic/TabletsStatistic.tsx +56 -0
- package/dist/components/TabletsStatistic/index.ts +1 -0
- package/dist/containers/App/App.scss +4 -12
- package/dist/containers/AsideNavigation/AsideNavigation.scss +0 -18
- package/dist/containers/AsideNavigation/AsideNavigation.tsx +95 -33
- package/dist/containers/Heatmap/Heatmap.scss +0 -7
- package/dist/containers/Heatmap/Heatmap.tsx +203 -0
- package/dist/containers/Heatmap/HeatmapCanvas/HeatmapCanvas.js +2 -1
- package/dist/containers/Heatmap/index.ts +1 -0
- package/dist/containers/Node/Node.tsx +1 -1
- package/dist/containers/Storage/DiskStateProgressBar/DiskStateProgressBar.tsx +1 -1
- package/dist/containers/Storage/Storage.js +12 -19
- package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +16 -0
- package/dist/containers/Tablets/Tablets.scss +0 -5
- package/dist/containers/Tablets/Tablets.tsx +172 -0
- package/dist/containers/Tablets/i18n/en.json +6 -0
- package/dist/{components/AsideNavigation → containers/Tablets}/i18n/index.ts +1 -1
- package/dist/containers/Tablets/i18n/ru.json +6 -0
- package/dist/containers/Tablets/index.ts +1 -0
- package/dist/containers/TabletsFilters/TabletsFilters.js +4 -8
- package/dist/containers/TabletsFilters/TabletsFilters.scss +6 -2
- package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +8 -13
- package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.ts +7 -7
- package/dist/containers/Tenant/Diagnostics/{TopShards/TopShards.scss → OverloadedShards/OverloadedShards.scss} +1 -1
- package/dist/containers/Tenant/Diagnostics/{TopShards/TopShards.tsx → OverloadedShards/OverloadedShards.tsx} +10 -11
- package/dist/containers/Tenant/Diagnostics/{TopShards → OverloadedShards}/i18n/en.json +0 -0
- package/dist/containers/Tenant/Diagnostics/OverloadedShards/i18n/index.ts +11 -0
- package/dist/containers/Tenant/Diagnostics/{TopShards → OverloadedShards}/i18n/ru.json +0 -0
- package/dist/containers/Tenant/Diagnostics/OverloadedShards/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +7 -7
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.scss +16 -19
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +202 -0
- package/dist/containers/Tenant/Diagnostics/TopQueries/i18n/en.json +4 -0
- package/dist/containers/Tenant/Diagnostics/{TopShards → TopQueries}/i18n/index.ts +1 -1
- package/dist/containers/Tenant/Diagnostics/TopQueries/i18n/ru.json +4 -0
- package/dist/containers/Tenant/Diagnostics/TopQueries/index.ts +1 -0
- package/dist/containers/Tenants/Tenants.js +1 -1
- package/dist/containers/UserSettings/UserSettings.tsx +5 -4
- package/dist/routes.ts +1 -1
- package/dist/services/api.d.ts +7 -0
- package/dist/store/reducers/describe.ts +4 -1
- package/dist/store/reducers/executeTopQueries.ts +170 -0
- package/dist/store/reducers/{heatmap.js → heatmap.ts} +33 -18
- package/dist/store/reducers/settings.js +13 -3
- package/dist/store/reducers/shardsWorkload.ts +9 -9
- package/dist/store/reducers/storage.js +2 -0
- package/dist/store/reducers/{tablets.js → tablets.ts} +30 -17
- package/dist/store/state-url-mapping.js +10 -2
- package/dist/types/api/compute.ts +52 -0
- package/dist/types/api/consumer.ts +257 -0
- package/dist/types/api/enums.ts +2 -2
- package/dist/types/api/nodes.ts +5 -2
- package/dist/types/api/pdisk.ts +3 -0
- package/dist/types/api/schema.ts +17 -3
- package/dist/types/api/storage.ts +31 -28
- package/dist/types/api/tablet.ts +18 -2
- package/dist/types/api/tenant.ts +4 -1
- package/dist/types/api/topic.ts +157 -0
- package/dist/types/api/vdisk.ts +3 -0
- package/dist/types/store/executeTopQueries.ts +29 -0
- package/dist/types/store/heatmap.ts +51 -0
- package/dist/types/store/schema.ts +3 -3
- package/dist/types/store/shardsWorkload.ts +3 -3
- package/dist/types/store/tablets.ts +42 -0
- package/dist/utils/constants.ts +1 -37
- package/dist/utils/getNodesColumns.js +14 -2
- package/dist/utils/tablet.ts +53 -0
- package/package.json +4 -3
- package/dist/components/AsideNavigation/AsideHeader.scss +0 -147
- package/dist/components/AsideNavigation/AsideHeader.tsx +0 -389
- package/dist/components/AsideNavigation/AsideHeaderFooterItem/AsideHeaderFooterItem.scss +0 -82
- package/dist/components/AsideNavigation/AsideHeaderFooterItem/AsideHeaderFooterItem.tsx +0 -138
- package/dist/components/AsideNavigation/AsideHeaderFooterSlot/AsideHeaderFooterSlot.tsx +0 -33
- package/dist/components/AsideNavigation/AsideHeaderFooterSlot/SlotsContext.tsx +0 -49
- package/dist/components/AsideNavigation/AsideHeaderTooltip/AsideHeaderTooltip.scss +0 -16
- package/dist/components/AsideNavigation/AsideHeaderTooltip/AsideHeaderTooltip.tsx +0 -37
- package/dist/components/AsideNavigation/CompositeBar/CompositeBar.scss +0 -108
- package/dist/components/AsideNavigation/CompositeBar/CompositeBar.tsx +0 -282
- package/dist/components/AsideNavigation/Content/Content.tsx +0 -35
- package/dist/components/AsideNavigation/Drawer/Drawer.scss +0 -76
- package/dist/components/AsideNavigation/Drawer/Drawer.tsx +0 -134
- package/dist/components/AsideNavigation/Drawer/index.ts +0 -1
- package/dist/components/AsideNavigation/Logo/Logo.scss +0 -43
- package/dist/components/AsideNavigation/Logo/Logo.tsx +0 -82
- package/dist/components/AsideNavigation/Settings/README.md +0 -92
- package/dist/components/AsideNavigation/Settings/Settings.scss +0 -128
- package/dist/components/AsideNavigation/Settings/Settings.tsx +0 -270
- package/dist/components/AsideNavigation/Settings/SettingsMenu/SettingsMenu.scss +0 -78
- package/dist/components/AsideNavigation/Settings/SettingsMenu/SettingsMenu.tsx +0 -141
- package/dist/components/AsideNavigation/Settings/SettingsSearch/SettingsSearch.tsx +0 -57
- package/dist/components/AsideNavigation/Settings/collect-settings.ts +0 -156
- package/dist/components/AsideNavigation/Settings/filter-settings.ts +0 -38
- package/dist/components/AsideNavigation/Settings/helpers.ts +0 -39
- package/dist/components/AsideNavigation/Settings/i18n/en.json +0 -5
- package/dist/components/AsideNavigation/Settings/i18n/ru.json +0 -5
- package/dist/components/AsideNavigation/Settings/index.ts +0 -1
- package/dist/components/AsideNavigation/constants.ts +0 -28
- package/dist/components/AsideNavigation/helpers.ts +0 -34
- package/dist/components/AsideNavigation/i18n/en.json +0 -4
- package/dist/components/AsideNavigation/i18n/ru.json +0 -4
- package/dist/components/AsideNavigation/icons.ts +0 -32
- package/dist/components/AsideNavigation/types.ts +0 -23
- package/dist/components/TabletsStatistic/TabletsStatistic.js +0 -58
- package/dist/containers/Heatmap/Heatmap.js +0 -244
- package/dist/containers/Tablets/Tablets.js +0 -228
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.js +0 -188
- package/dist/containers/Tenant/Diagnostics/TopShards/DateRange/DateRange.scss +0 -13
- package/dist/containers/Tenant/Diagnostics/TopShards/index.ts +0 -1
- package/dist/store/reducers/executeTopQueries.js +0 -66
- package/dist/types/api/consumers.ts +0 -3
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,35 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [3.2.1](https://github.com/ydb-platform/ydb-embedded-ui/compare/v3.2.0...v3.2.1) (2023-01-12)
|
4
|
+
|
5
|
+
|
6
|
+
### Bug Fixes
|
7
|
+
|
8
|
+
* align standard errors to the left ([cce100c](https://github.com/ydb-platform/ydb-embedded-ui/commit/cce100c5df83243df1fb0bc59d84d0d9b33719e6))
|
9
|
+
* **TabletsFilters:** properly display long data in select options ([ea37d9f](https://github.com/ydb-platform/ydb-embedded-ui/commit/ea37d9fc08245ccdd38a6120dd620f59a528879c))
|
10
|
+
* **TabletsFilters:** replace constants ([ea948ca](https://github.com/ydb-platform/ydb-embedded-ui/commit/ea948ca86276b5521979105b2ab99546da389e80))
|
11
|
+
* **TabletsStatistic:** process different tablets state types ([78798de](https://github.com/ydb-platform/ydb-embedded-ui/commit/78798de984bf4f6133515bb1c440e4fe0d15b07e))
|
12
|
+
* **Tenant:** always display Pools heading ([94baeff](https://github.com/ydb-platform/ydb-embedded-ui/commit/94baeff82f9c2c1aecda7c11c3b090125ba9e4b6))
|
13
|
+
|
14
|
+
## [3.2.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v3.1.0...v3.2.0) (2023-01-09)
|
15
|
+
|
16
|
+
|
17
|
+
### Features
|
18
|
+
|
19
|
+
* **Nodes:** display rack in table ([3b8cdd5](https://github.com/ydb-platform/ydb-embedded-ui/commit/3b8cdd5b472f98132b2faaa9b71b8911750545a6))
|
20
|
+
* **StorageNodes:** display datacenter in table ([4507bfd](https://github.com/ydb-platform/ydb-embedded-ui/commit/4507bfde839b0aafa3722828b7528885c6ac8f84))
|
21
|
+
* **TopQueries:** date range filter ([b9a8e95](https://github.com/ydb-platform/ydb-embedded-ui/commit/b9a8e9504fa68556a724b214ee91b73ec900d37e))
|
22
|
+
* **TopQueries:** filter by query text ([2c8ea97](https://github.com/ydb-platform/ydb-embedded-ui/commit/2c8ea97dd215ea59165cf05315bc5809cf7fafd7))
|
23
|
+
|
24
|
+
|
25
|
+
### Bug Fixes
|
26
|
+
|
27
|
+
* **InfoViewer:** min width for values ([64a4fd4](https://github.com/ydb-platform/ydb-embedded-ui/commit/64a4fd4de16738a9e2fac9cb4fba94eafc938762))
|
28
|
+
* **Nodes:** open external link in new tab ([b7c3ddd](https://github.com/ydb-platform/ydb-embedded-ui/commit/b7c3ddd1e611f2b61466e3eda51f3341f8407588))
|
29
|
+
* **TopQueries:** proper table dynamic render type ([9add6ca](https://github.com/ydb-platform/ydb-embedded-ui/commit/9add6ca9fbfe0475caf1586070a800210320cee6))
|
30
|
+
* **TopShards:** rename to overloaded shards ([d9978bd](https://github.com/ydb-platform/ydb-embedded-ui/commit/d9978bdd84b9a883e4eefcac7f85f856da55d770))
|
31
|
+
* **UserSettings:** treat invertedDisks settings as string ([ad7742a](https://github.com/ydb-platform/ydb-embedded-ui/commit/ad7742a6bf0be59c2b9cbbf947aaa66f79d748be))
|
32
|
+
|
3
33
|
## [3.1.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v3.0.1...v3.1.0) (2022-12-13)
|
4
34
|
|
5
35
|
|
package/README.md
CHANGED
@@ -15,6 +15,8 @@ Local viewer for YDB clusters
|
|
15
15
|
3) Open [http://localhost:3000](http://localhost:3000) to view it in the browser. The page will reload if you make edits.\
|
16
16
|
You will also see any lint errors in the console.
|
17
17
|
|
18
|
+
For API reference, open Swagger UI on http://localhost:8765/viewer/api/.
|
19
|
+
|
18
20
|
### Making a production bundle.
|
19
21
|
|
20
22
|
Base command `npm run build` builds the app for production to the `build` folder.\
|
@@ -1,9 +1,9 @@
|
|
1
|
-
import cn from 'bem-cn-lite';
|
2
1
|
import {ChangeEventHandler} from 'react';
|
2
|
+
import cn from 'bem-cn-lite';
|
3
3
|
|
4
4
|
import './DateRange.scss';
|
5
5
|
|
6
|
-
const b = cn('
|
6
|
+
const b = cn('date-range');
|
7
7
|
|
8
8
|
export interface DateRangeValues {
|
9
9
|
/** ms from epoch */
|
@@ -54,21 +54,21 @@ export const DateRange = ({from, to, className, onChange}: DateRangeProps) => {
|
|
54
54
|
const endISO = toTimezonelessISOString(to);
|
55
55
|
|
56
56
|
return (
|
57
|
-
<div className={b(
|
57
|
+
<div className={b(null, className)}>
|
58
58
|
<input
|
59
59
|
type="datetime-local"
|
60
|
-
value={startISO}
|
60
|
+
value={startISO || ''}
|
61
61
|
max={endISO}
|
62
62
|
onChange={handleFromChange}
|
63
|
-
className={b('
|
63
|
+
className={b('input')}
|
64
64
|
/>
|
65
65
|
—
|
66
66
|
<input
|
67
67
|
type="datetime-local"
|
68
68
|
min={startISO}
|
69
|
-
value={endISO}
|
69
|
+
value={endISO || ''}
|
70
70
|
onChange={handleToChange}
|
71
|
-
className={b('
|
71
|
+
className={b('input')}
|
72
72
|
/>
|
73
73
|
</div>
|
74
74
|
);
|
File without changes
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import {Label} from '@gravity-ui/uikit';
|
2
|
+
import i18n from './i18n';
|
3
|
+
|
4
|
+
interface EntitiesCountProps {
|
5
|
+
current: number | string;
|
6
|
+
total?: number | string;
|
7
|
+
label?: string;
|
8
|
+
loading?: boolean;
|
9
|
+
className?: string;
|
10
|
+
}
|
11
|
+
|
12
|
+
export const EntitiesCount = ({total, current, label, loading, className}: EntitiesCountProps) => {
|
13
|
+
let content = '';
|
14
|
+
|
15
|
+
if (label) {
|
16
|
+
content += `${label}: `;
|
17
|
+
}
|
18
|
+
|
19
|
+
if (loading) {
|
20
|
+
content += '...';
|
21
|
+
} else {
|
22
|
+
content += `${current}`;
|
23
|
+
|
24
|
+
if (total && Number(total) !== Number(current)) {
|
25
|
+
content += ` ${i18n('of')} ${total}`;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
return (
|
30
|
+
<Label theme="info" size="m" className={className}>
|
31
|
+
{content}
|
32
|
+
</Label>
|
33
|
+
);
|
34
|
+
};
|
@@ -1,9 +1,9 @@
|
|
1
|
-
import {i18n, Lang} from '
|
1
|
+
import {i18n, Lang} from '../../../utils/i18n';
|
2
2
|
|
3
3
|
import en from './en.json';
|
4
4
|
import ru from './ru.json';
|
5
5
|
|
6
|
-
const COMPONENT = '
|
6
|
+
const COMPONENT = 'ydb-entities-count';
|
7
7
|
|
8
8
|
i18n.registerKeyset(Lang.En, COMPONENT, en);
|
9
9
|
i18n.registerKeyset(Lang.Ru, COMPONENT, ru);
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './EntitiesCount';
|
@@ -1,16 +1,17 @@
|
|
1
1
|
.kv-fullscreen {
|
2
|
-
|
2
|
+
// should expand to fill the content area, keeping aside navigation visible
|
3
|
+
// counts on .ycn-aside-header__content to have position: relative, it is set in App.scss
|
4
|
+
position: absolute;
|
3
5
|
z-index: 10;
|
4
6
|
top: 0;
|
5
|
-
|
7
|
+
right: 0;
|
8
|
+
bottom: 0;
|
9
|
+
left: 0;
|
6
10
|
|
7
11
|
display: flex;
|
8
12
|
overflow: hidden;
|
9
13
|
flex-grow: 1;
|
10
14
|
|
11
|
-
width: calc(100% - var(--nv-aside-header-size));
|
12
|
-
height: 100%;
|
13
|
-
|
14
15
|
background-color: var(--yc-color-base-background);
|
15
16
|
|
16
17
|
&__close-button {
|
@@ -18,6 +19,7 @@
|
|
18
19
|
z-index: 11;
|
19
20
|
top: 8px;
|
20
21
|
right: 20px;
|
22
|
+
|
21
23
|
.yc-button__text {
|
22
24
|
display: flex;
|
23
25
|
align-items: center;
|
@@ -1,8 +1,8 @@
|
|
1
|
-
import {useEffect, useState} from 'react';
|
1
|
+
import {ImgHTMLAttributes, useEffect, useState} from 'react';
|
2
2
|
import cn from 'bem-cn-lite';
|
3
3
|
import {useThemeValue} from '@gravity-ui/uikit';
|
4
4
|
|
5
|
-
export interface IllustrationProps {
|
5
|
+
export interface IllustrationProps extends ImgHTMLAttributes<HTMLImageElement> {
|
6
6
|
name: string;
|
7
7
|
className?: string;
|
8
8
|
}
|
@@ -38,12 +38,5 @@ export const Illustration = ({name, className, ...props}: IllustrationProps) =>
|
|
38
38
|
}
|
39
39
|
}, [srcGetter]);
|
40
40
|
|
41
|
-
return (
|
42
|
-
|
43
|
-
alt={name}
|
44
|
-
src={src}
|
45
|
-
className={b(null, className)}
|
46
|
-
{...props}
|
47
|
-
/>
|
48
|
-
);
|
49
|
-
}
|
41
|
+
return <img alt={name} src={src} className={b(null, className)} {...props} />;
|
42
|
+
};
|
@@ -25,7 +25,7 @@ const b = cn('kv-tablets-overall');
|
|
25
25
|
type Color = keyof typeof colors;
|
26
26
|
|
27
27
|
interface TabletsOverallProps {
|
28
|
-
tablets: {Overall
|
28
|
+
tablets: {Overall?: string}[];
|
29
29
|
}
|
30
30
|
|
31
31
|
function TabletsOverall({tablets}: TabletsOverallProps) {
|
@@ -48,10 +48,10 @@ function TabletsOverall({tablets}: TabletsOverallProps) {
|
|
48
48
|
|
49
49
|
// determine how many tablets of what color are in "tablets"
|
50
50
|
const statesForOverallProgress: Record<string, number> = tablets.reduce((acc, tablet) => {
|
51
|
-
const color = tablet.Overall
|
52
|
-
if (!acc[color]) {
|
51
|
+
const color = tablet.Overall?.toLowerCase();
|
52
|
+
if (color && !acc[color]) {
|
53
53
|
acc[color] = 1;
|
54
|
-
} else {
|
54
|
+
} else if (color) {
|
55
55
|
acc[color]++;
|
56
56
|
}
|
57
57
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import cn from 'bem-cn-lite';
|
2
|
+
import {Link} from 'react-router-dom';
|
3
|
+
|
4
|
+
import {getTabletLabel} from '../../utils/constants';
|
5
|
+
import {mapTabletStateToColorState} from '../../utils/tablet';
|
6
|
+
import routes, {createHref} from '../../routes';
|
7
|
+
|
8
|
+
import type {TTabletStateInfo as TFullTabletStateInfo} from '../../types/api/tablet';
|
9
|
+
import type {TTabletStateInfo as TComputeTabletStateInfo} from '../../types/api/compute';
|
10
|
+
|
11
|
+
import './TabletsStatistic.scss';
|
12
|
+
|
13
|
+
const b = cn('tablets-statistic');
|
14
|
+
|
15
|
+
type ITablets = TFullTabletStateInfo[] | TComputeTabletStateInfo[];
|
16
|
+
|
17
|
+
const prepareTablets = (tablets: ITablets) => {
|
18
|
+
const res = tablets.map((tablet) => {
|
19
|
+
return {
|
20
|
+
label: getTabletLabel(tablet.Type),
|
21
|
+
type: tablet.Type,
|
22
|
+
count: tablet.Count,
|
23
|
+
state: mapTabletStateToColorState(tablet.State),
|
24
|
+
};
|
25
|
+
});
|
26
|
+
|
27
|
+
return res.sort((x, y) => String(x.label).localeCompare(String(y.label)));
|
28
|
+
};
|
29
|
+
|
30
|
+
interface TabletsStatisticProps {
|
31
|
+
tablets: ITablets;
|
32
|
+
path: string;
|
33
|
+
nodeIds: string[] | number[];
|
34
|
+
}
|
35
|
+
|
36
|
+
export const TabletsStatistic = ({tablets = [], path, nodeIds}: TabletsStatisticProps) => {
|
37
|
+
const renderTabletInfo = (item: ReturnType<typeof prepareTablets>[number], index: number) => {
|
38
|
+
return (
|
39
|
+
<Link
|
40
|
+
to={createHref(routes.tabletsFilters, undefined, {
|
41
|
+
nodeIds,
|
42
|
+
state: item.state,
|
43
|
+
type: item.type,
|
44
|
+
path,
|
45
|
+
})}
|
46
|
+
key={index}
|
47
|
+
className={b('tablet', {state: item.state?.toLowerCase()})}
|
48
|
+
>
|
49
|
+
{item.label}: {item.count}
|
50
|
+
</Link>
|
51
|
+
);
|
52
|
+
};
|
53
|
+
const preparedTablets = prepareTablets(tablets);
|
54
|
+
|
55
|
+
return <div className={b()}>{preparedTablets.map(renderTabletInfo)}</div>;
|
56
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './TabletsStatistic';
|
@@ -47,11 +47,13 @@ body,
|
|
47
47
|
color: var(--yc-color-text-secondary);
|
48
48
|
}
|
49
49
|
|
50
|
-
.
|
50
|
+
.ycn-aside-header__pane-container {
|
51
51
|
height: 100%;
|
52
52
|
}
|
53
53
|
|
54
|
-
.
|
54
|
+
.ycn-aside-header__content {
|
55
|
+
position: relative;
|
56
|
+
|
55
57
|
display: flex;
|
56
58
|
overflow: auto;
|
57
59
|
flex-direction: column;
|
@@ -116,17 +118,7 @@ body,
|
|
116
118
|
}
|
117
119
|
|
118
120
|
.error {
|
119
|
-
display: flex;
|
120
|
-
justify-content: center;
|
121
|
-
align-items: center;
|
122
|
-
|
123
|
-
margin: 2px;
|
124
|
-
padding: 2px;
|
125
|
-
|
126
|
-
text-align: center;
|
127
|
-
|
128
121
|
color: var(--yc-color-text-danger);
|
129
|
-
border-color: var(--yc-color-text-danger);
|
130
122
|
}
|
131
123
|
|
132
124
|
.data-table__row:hover .entity-status__clipboard-button {
|
@@ -23,21 +23,3 @@
|
|
23
23
|
padding: 10px;
|
24
24
|
}
|
25
25
|
}
|
26
|
-
|
27
|
-
.nv-aside-header-footer-item__popup {
|
28
|
-
.nv-user-menu-content__organizations {
|
29
|
-
margin-top: 19px;
|
30
|
-
margin-left: 0;
|
31
|
-
.yc-menu__item {
|
32
|
-
cursor: auto;
|
33
|
-
}
|
34
|
-
}
|
35
|
-
|
36
|
-
.yc-menu__item {
|
37
|
-
//stylelint-disable-next-line declaration-no-important
|
38
|
-
padding-right: 0 !important;
|
39
|
-
&:hover {
|
40
|
-
background-color: unset;
|
41
|
-
}
|
42
|
-
}
|
43
|
-
}
|
@@ -1,16 +1,12 @@
|
|
1
|
-
import React, {useState} from 'react';
|
1
|
+
import React, {useEffect, useState} from 'react';
|
2
|
+
import {connect} from 'react-redux';
|
3
|
+
import {useLocation} from 'react-router';
|
2
4
|
import {useHistory} from 'react-router-dom';
|
3
5
|
import cn from 'bem-cn-lite';
|
4
|
-
import {useLocation} from 'react-router';
|
5
|
-
import {connect} from 'react-redux';
|
6
6
|
|
7
|
-
import {
|
8
|
-
AsideHeader,
|
9
|
-
AsideHeaderFooterItem,
|
10
|
-
AsideHeaderMenuItem,
|
11
|
-
SlotName,
|
12
|
-
} from '../../components/AsideNavigation/AsideHeader';
|
13
7
|
import {Icon, Button} from '@gravity-ui/uikit';
|
8
|
+
import {AsideHeader, MenuItem as AsideHeaderMenuItem, FooterItem} from '@gravity-ui/navigation';
|
9
|
+
|
14
10
|
import signOutIcon from '../../assets/icons/signOut.svg';
|
15
11
|
import signInIcon from '../../assets/icons/signIn.svg';
|
16
12
|
import databaseIcon from '../../assets/icons/server.svg';
|
@@ -20,12 +16,17 @@ import ydbLogoIcon from '../../assets/icons/ydb.svg';
|
|
20
16
|
import databasesIcon from '../../assets/icons/databases.svg';
|
21
17
|
import userSecret from '../../assets/icons/user-secret.svg';
|
22
18
|
import userChecked from '../../assets/icons/user-check.svg';
|
23
|
-
|
19
|
+
import settingsIcon from '../../assets/icons/settings.svg';
|
20
|
+
import supportIcon from '../../assets/icons/support.svg';
|
21
|
+
|
24
22
|
import UserSettings from '../UserSettings/UserSettings';
|
23
|
+
|
25
24
|
import routes, {createHref, CLUSTER_PAGES} from '../../routes';
|
26
25
|
|
27
|
-
//@ts-ignore
|
28
26
|
import {logout, setIsNotAuthenticated} from '../../store/reducers/authentication';
|
27
|
+
import {getSettingValue, setSettingValue} from '../../store/reducers/settings';
|
28
|
+
|
29
|
+
import {ASIDE_HEADER_COMPACT_KEY} from '../../utils/constants';
|
29
30
|
|
30
31
|
import './AsideNavigation.scss';
|
31
32
|
|
@@ -77,17 +78,21 @@ interface YdbUserDropdownProps {
|
|
77
78
|
|
78
79
|
function YdbUserDropdown({isCompact, popupAnchor, ydbUser}: YdbUserDropdownProps) {
|
79
80
|
const [isUserDropdownVisible, setIsUserDropdownVisible] = useState(false);
|
80
|
-
const
|
81
|
+
const iconData = ydbUser?.login ? userChecked : userSecret;
|
81
82
|
return (
|
82
|
-
<
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
83
|
+
<FooterItem
|
84
|
+
compact={isCompact}
|
85
|
+
item={{
|
86
|
+
id: 'user-popup',
|
87
|
+
title: ydbUser?.login ?? 'Account',
|
88
|
+
current: isUserDropdownVisible,
|
89
|
+
icon: iconData,
|
90
|
+
iconSize: 22,
|
91
|
+
onItemClick: () => setIsUserDropdownVisible(true),
|
92
|
+
}}
|
93
|
+
enableTooltip={!isUserDropdownVisible}
|
88
94
|
popupAnchor={popupAnchor}
|
89
95
|
popupVisible={isUserDropdownVisible}
|
90
|
-
onClick={() => setIsUserDropdownVisible(true)}
|
91
96
|
onClosePopup={() => setIsUserDropdownVisible(false)}
|
92
97
|
renderPopupContent={() => (
|
93
98
|
<div className={b('ydb-user-wrapper')}>
|
@@ -105,8 +110,10 @@ function YdbUserDropdown({isCompact, popupAnchor, ydbUser}: YdbUserDropdownProps
|
|
105
110
|
interface AsideNavigationProps {
|
106
111
|
children: React.ReactNode;
|
107
112
|
ydbUser: string;
|
113
|
+
compact: boolean;
|
108
114
|
logout: VoidFunction;
|
109
115
|
setIsNotAuthenticated: VoidFunction;
|
116
|
+
setSettingValue: (name: string, value: string) => void;
|
110
117
|
}
|
111
118
|
|
112
119
|
const items: MenuItem[] = [
|
@@ -150,10 +157,30 @@ const items: MenuItem[] = [
|
|
150
157
|
},
|
151
158
|
];
|
152
159
|
|
160
|
+
enum Panel {
|
161
|
+
UserSettings = 'UserSettings',
|
162
|
+
}
|
163
|
+
|
153
164
|
function AsideNavigation(props: AsideNavigationProps) {
|
154
165
|
const location = useLocation();
|
155
166
|
const history = useHistory();
|
156
167
|
|
168
|
+
const [visiblePanel, setVisiblePanel] = useState<Panel>();
|
169
|
+
|
170
|
+
const setIsCompact = (compact: boolean) => {
|
171
|
+
props.setSettingValue(ASIDE_HEADER_COMPACT_KEY, JSON.stringify(compact));
|
172
|
+
};
|
173
|
+
|
174
|
+
// navigation managed its compact state internally before, and its approach is not compatible with settings
|
175
|
+
// to migrate, save the incoming value again; save only `false` because `true` is the default value
|
176
|
+
// assume it is safe to remove this code block if it is at least a few months old
|
177
|
+
// there a two of these, search for a similar comment
|
178
|
+
useEffect(() => {
|
179
|
+
if (props.compact === false) {
|
180
|
+
setIsCompact(props.compact);
|
181
|
+
}
|
182
|
+
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
183
|
+
|
157
184
|
const menuItems: AsideHeaderMenuItem[] = React.useMemo(() => {
|
158
185
|
const {pathname} = location;
|
159
186
|
const isClusterPage = pathname === '/cluster';
|
@@ -184,28 +211,51 @@ function AsideNavigation(props: AsideNavigationProps) {
|
|
184
211
|
return (
|
185
212
|
<React.Fragment>
|
186
213
|
<AsideHeader
|
187
|
-
|
188
|
-
|
189
|
-
|
214
|
+
logo={{
|
215
|
+
text: 'YDB',
|
216
|
+
icon: ydbLogoIcon,
|
217
|
+
onClick: () => history.push('/'),
|
218
|
+
}}
|
190
219
|
menuItems={menuItems}
|
191
|
-
|
192
|
-
|
220
|
+
compact={props.compact}
|
221
|
+
onChangeCompact={setIsCompact}
|
193
222
|
className={b()}
|
194
223
|
renderContent={() => props.children}
|
195
|
-
renderFooter={({
|
224
|
+
renderFooter={({compact, asideRef}) => (
|
196
225
|
<React.Fragment>
|
197
|
-
<
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
226
|
+
<FooterItem
|
227
|
+
compact={compact}
|
228
|
+
item={{
|
229
|
+
id: 'documentation',
|
230
|
+
title: 'Documentation',
|
231
|
+
icon: supportIcon,
|
232
|
+
iconSize: 24,
|
233
|
+
onItemClick: () => {
|
234
|
+
window.open('https://ydb.tech/docs', '_blank', 'noreferrer');
|
235
|
+
},
|
236
|
+
}}
|
237
|
+
/>
|
238
|
+
|
239
|
+
<FooterItem
|
240
|
+
item={{
|
241
|
+
id: 'user-settings',
|
242
|
+
title: 'Settings',
|
243
|
+
icon: settingsIcon,
|
244
|
+
iconSize: 24,
|
245
|
+
current: visiblePanel === Panel.UserSettings,
|
246
|
+
onItemClick: () => {
|
247
|
+
setVisiblePanel(
|
248
|
+
visiblePanel === Panel.UserSettings
|
249
|
+
? undefined
|
250
|
+
: Panel.UserSettings,
|
251
|
+
);
|
252
|
+
},
|
204
253
|
}}
|
254
|
+
compact={compact}
|
205
255
|
/>
|
206
256
|
|
207
257
|
<YdbUserDropdown
|
208
|
-
isCompact={
|
258
|
+
isCompact={compact}
|
209
259
|
popupAnchor={asideRef}
|
210
260
|
ydbUser={{
|
211
261
|
login: props.ydbUser,
|
@@ -215,6 +265,16 @@ function AsideNavigation(props: AsideNavigationProps) {
|
|
215
265
|
/>
|
216
266
|
</React.Fragment>
|
217
267
|
)}
|
268
|
+
panelItems={[
|
269
|
+
{
|
270
|
+
id: 'user-settings',
|
271
|
+
visible: visiblePanel === Panel.UserSettings,
|
272
|
+
content: <UserSettings />,
|
273
|
+
},
|
274
|
+
]}
|
275
|
+
onClosePanel={() => {
|
276
|
+
setVisiblePanel(undefined);
|
277
|
+
}}
|
218
278
|
/>
|
219
279
|
</React.Fragment>
|
220
280
|
);
|
@@ -225,12 +285,14 @@ const mapStateToProps = (state: any) => {
|
|
225
285
|
|
226
286
|
return {
|
227
287
|
ydbUser,
|
288
|
+
compact: JSON.parse(getSettingValue(state, ASIDE_HEADER_COMPACT_KEY)),
|
228
289
|
};
|
229
290
|
};
|
230
291
|
|
231
292
|
const mapDispatchToProps = {
|
232
293
|
logout,
|
233
294
|
setIsNotAuthenticated,
|
295
|
+
setSettingValue,
|
234
296
|
};
|
235
297
|
|
236
298
|
export default connect(mapStateToProps, mapDispatchToProps)(AsideNavigation);
|