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.
Files changed (124) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +2 -0
  3. package/dist/components/DateRange/DateRange.scss +11 -0
  4. package/dist/{containers/Tenant/Diagnostics/TopShards → components}/DateRange/DateRange.tsx +7 -7
  5. package/dist/{containers/Tenant/Diagnostics/TopShards → components}/DateRange/index.ts +0 -0
  6. package/dist/components/EntitiesCount/EntitiesCount.tsx +34 -0
  7. package/dist/components/EntitiesCount/i18n/en.json +3 -0
  8. package/dist/components/{AsideNavigation/Settings → EntitiesCount}/i18n/index.ts +2 -2
  9. package/dist/components/EntitiesCount/i18n/ru.json +3 -0
  10. package/dist/components/EntitiesCount/index.ts +1 -0
  11. package/dist/components/Fullscreen/Fullscreen.scss +7 -5
  12. package/dist/components/Illustration/Illustration.tsx +4 -11
  13. package/dist/components/InfoViewer/InfoViewer.scss +2 -0
  14. package/dist/components/TabletsOverall/TabletsOverall.tsx +4 -4
  15. package/dist/components/TabletsStatistic/TabletsStatistic.tsx +56 -0
  16. package/dist/components/TabletsStatistic/index.ts +1 -0
  17. package/dist/containers/App/App.scss +4 -12
  18. package/dist/containers/AsideNavigation/AsideNavigation.scss +0 -18
  19. package/dist/containers/AsideNavigation/AsideNavigation.tsx +95 -33
  20. package/dist/containers/Heatmap/Heatmap.scss +0 -7
  21. package/dist/containers/Heatmap/Heatmap.tsx +203 -0
  22. package/dist/containers/Heatmap/HeatmapCanvas/HeatmapCanvas.js +2 -1
  23. package/dist/containers/Heatmap/index.ts +1 -0
  24. package/dist/containers/Node/Node.tsx +1 -1
  25. package/dist/containers/Storage/DiskStateProgressBar/DiskStateProgressBar.tsx +1 -1
  26. package/dist/containers/Storage/Storage.js +12 -19
  27. package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +16 -0
  28. package/dist/containers/Tablets/Tablets.scss +0 -5
  29. package/dist/containers/Tablets/Tablets.tsx +172 -0
  30. package/dist/containers/Tablets/i18n/en.json +6 -0
  31. package/dist/{components/AsideNavigation → containers/Tablets}/i18n/index.ts +1 -1
  32. package/dist/containers/Tablets/i18n/ru.json +6 -0
  33. package/dist/containers/Tablets/index.ts +1 -0
  34. package/dist/containers/TabletsFilters/TabletsFilters.js +4 -8
  35. package/dist/containers/TabletsFilters/TabletsFilters.scss +6 -2
  36. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +8 -13
  37. package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.ts +7 -7
  38. package/dist/containers/Tenant/Diagnostics/{TopShards/TopShards.scss → OverloadedShards/OverloadedShards.scss} +1 -1
  39. package/dist/containers/Tenant/Diagnostics/{TopShards/TopShards.tsx → OverloadedShards/OverloadedShards.tsx} +10 -11
  40. package/dist/containers/Tenant/Diagnostics/{TopShards → OverloadedShards}/i18n/en.json +0 -0
  41. package/dist/containers/Tenant/Diagnostics/OverloadedShards/i18n/index.ts +11 -0
  42. package/dist/containers/Tenant/Diagnostics/{TopShards → OverloadedShards}/i18n/ru.json +0 -0
  43. package/dist/containers/Tenant/Diagnostics/OverloadedShards/index.ts +1 -0
  44. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +7 -7
  45. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.scss +16 -19
  46. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +202 -0
  47. package/dist/containers/Tenant/Diagnostics/TopQueries/i18n/en.json +4 -0
  48. package/dist/containers/Tenant/Diagnostics/{TopShards → TopQueries}/i18n/index.ts +1 -1
  49. package/dist/containers/Tenant/Diagnostics/TopQueries/i18n/ru.json +4 -0
  50. package/dist/containers/Tenant/Diagnostics/TopQueries/index.ts +1 -0
  51. package/dist/containers/Tenants/Tenants.js +1 -1
  52. package/dist/containers/UserSettings/UserSettings.tsx +5 -4
  53. package/dist/routes.ts +1 -1
  54. package/dist/services/api.d.ts +7 -0
  55. package/dist/store/reducers/describe.ts +4 -1
  56. package/dist/store/reducers/executeTopQueries.ts +170 -0
  57. package/dist/store/reducers/{heatmap.js → heatmap.ts} +33 -18
  58. package/dist/store/reducers/settings.js +13 -3
  59. package/dist/store/reducers/shardsWorkload.ts +9 -9
  60. package/dist/store/reducers/storage.js +2 -0
  61. package/dist/store/reducers/{tablets.js → tablets.ts} +30 -17
  62. package/dist/store/state-url-mapping.js +10 -2
  63. package/dist/types/api/compute.ts +52 -0
  64. package/dist/types/api/consumer.ts +257 -0
  65. package/dist/types/api/enums.ts +2 -2
  66. package/dist/types/api/nodes.ts +5 -2
  67. package/dist/types/api/pdisk.ts +3 -0
  68. package/dist/types/api/schema.ts +17 -3
  69. package/dist/types/api/storage.ts +31 -28
  70. package/dist/types/api/tablet.ts +18 -2
  71. package/dist/types/api/tenant.ts +4 -1
  72. package/dist/types/api/topic.ts +157 -0
  73. package/dist/types/api/vdisk.ts +3 -0
  74. package/dist/types/store/executeTopQueries.ts +29 -0
  75. package/dist/types/store/heatmap.ts +51 -0
  76. package/dist/types/store/schema.ts +3 -3
  77. package/dist/types/store/shardsWorkload.ts +3 -3
  78. package/dist/types/store/tablets.ts +42 -0
  79. package/dist/utils/constants.ts +1 -37
  80. package/dist/utils/getNodesColumns.js +14 -2
  81. package/dist/utils/tablet.ts +53 -0
  82. package/package.json +4 -3
  83. package/dist/components/AsideNavigation/AsideHeader.scss +0 -147
  84. package/dist/components/AsideNavigation/AsideHeader.tsx +0 -389
  85. package/dist/components/AsideNavigation/AsideHeaderFooterItem/AsideHeaderFooterItem.scss +0 -82
  86. package/dist/components/AsideNavigation/AsideHeaderFooterItem/AsideHeaderFooterItem.tsx +0 -138
  87. package/dist/components/AsideNavigation/AsideHeaderFooterSlot/AsideHeaderFooterSlot.tsx +0 -33
  88. package/dist/components/AsideNavigation/AsideHeaderFooterSlot/SlotsContext.tsx +0 -49
  89. package/dist/components/AsideNavigation/AsideHeaderTooltip/AsideHeaderTooltip.scss +0 -16
  90. package/dist/components/AsideNavigation/AsideHeaderTooltip/AsideHeaderTooltip.tsx +0 -37
  91. package/dist/components/AsideNavigation/CompositeBar/CompositeBar.scss +0 -108
  92. package/dist/components/AsideNavigation/CompositeBar/CompositeBar.tsx +0 -282
  93. package/dist/components/AsideNavigation/Content/Content.tsx +0 -35
  94. package/dist/components/AsideNavigation/Drawer/Drawer.scss +0 -76
  95. package/dist/components/AsideNavigation/Drawer/Drawer.tsx +0 -134
  96. package/dist/components/AsideNavigation/Drawer/index.ts +0 -1
  97. package/dist/components/AsideNavigation/Logo/Logo.scss +0 -43
  98. package/dist/components/AsideNavigation/Logo/Logo.tsx +0 -82
  99. package/dist/components/AsideNavigation/Settings/README.md +0 -92
  100. package/dist/components/AsideNavigation/Settings/Settings.scss +0 -128
  101. package/dist/components/AsideNavigation/Settings/Settings.tsx +0 -270
  102. package/dist/components/AsideNavigation/Settings/SettingsMenu/SettingsMenu.scss +0 -78
  103. package/dist/components/AsideNavigation/Settings/SettingsMenu/SettingsMenu.tsx +0 -141
  104. package/dist/components/AsideNavigation/Settings/SettingsSearch/SettingsSearch.tsx +0 -57
  105. package/dist/components/AsideNavigation/Settings/collect-settings.ts +0 -156
  106. package/dist/components/AsideNavigation/Settings/filter-settings.ts +0 -38
  107. package/dist/components/AsideNavigation/Settings/helpers.ts +0 -39
  108. package/dist/components/AsideNavigation/Settings/i18n/en.json +0 -5
  109. package/dist/components/AsideNavigation/Settings/i18n/ru.json +0 -5
  110. package/dist/components/AsideNavigation/Settings/index.ts +0 -1
  111. package/dist/components/AsideNavigation/constants.ts +0 -28
  112. package/dist/components/AsideNavigation/helpers.ts +0 -34
  113. package/dist/components/AsideNavigation/i18n/en.json +0 -4
  114. package/dist/components/AsideNavigation/i18n/ru.json +0 -4
  115. package/dist/components/AsideNavigation/icons.ts +0 -32
  116. package/dist/components/AsideNavigation/types.ts +0 -23
  117. package/dist/components/TabletsStatistic/TabletsStatistic.js +0 -58
  118. package/dist/containers/Heatmap/Heatmap.js +0 -244
  119. package/dist/containers/Tablets/Tablets.js +0 -228
  120. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.js +0 -188
  121. package/dist/containers/Tenant/Diagnostics/TopShards/DateRange/DateRange.scss +0 -13
  122. package/dist/containers/Tenant/Diagnostics/TopShards/index.ts +0 -1
  123. package/dist/store/reducers/executeTopQueries.js +0 -66
  124. 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.\
@@ -0,0 +1,11 @@
1
+ .date-range {
2
+ &__input {
3
+ min-width: 190px;
4
+ padding: 5px 8px;
5
+
6
+ color: var(--yc-color-text-primary);
7
+ border: 1px solid var(--yc-color-line-generic);
8
+ border-radius: var(--yc-border-radius-m);
9
+ background: transparent;
10
+ }
11
+ }
@@ -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('top-shards');
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('date-range', className)}>
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('date-range-input')}
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('date-range-input')}
71
+ className={b('input')}
72
72
  />
73
73
  </div>
74
74
  );
@@ -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
+ };
@@ -0,0 +1,3 @@
1
+ {
2
+ "of": "of"
3
+ }
@@ -1,9 +1,9 @@
1
- import {i18n, Lang} from '../../../../utils/i18n';
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 = 'nv-settings';
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,3 @@
1
+ {
2
+ "of": "из"
3
+ }
@@ -0,0 +1 @@
1
+ export * from './EntitiesCount';
@@ -1,16 +1,17 @@
1
1
  .kv-fullscreen {
2
- position: fixed;
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
- left: var(--nv-aside-header-size);
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
- <img
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
+ };
@@ -54,6 +54,8 @@
54
54
  &__value {
55
55
  display: flex;
56
56
 
57
+ min-width: 120px;
58
+
57
59
  word-break: break-all;
58
60
  }
59
61
 
@@ -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: string}[];
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.toLowerCase();
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
- .nv-aside-header__pane-container {
50
+ .ycn-aside-header__pane-container {
51
51
  height: 100%;
52
52
  }
53
53
 
54
- .nv-aside-header__content {
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
- //@ts-ignore
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 iconDate = ydbUser?.login ? userChecked : userSecret;
81
+ const iconData = ydbUser?.login ? userChecked : userSecret;
81
82
  return (
82
- <AsideHeaderFooterItem
83
- isCurrent={isUserDropdownVisible}
84
- slot={SlotName.User}
85
- renderCustomIcon={() => <Icon data={iconDate} size={22} className={b('user-icon')} />}
86
- text={ydbUser?.login ?? 'Account'}
87
- isCompact={isCompact}
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
- logoText="YDB"
188
- logoIcon={ydbLogoIcon}
189
- onLogoIconClick={() => history.push('/')}
214
+ logo={{
215
+ text: 'YDB',
216
+ icon: ydbLogoIcon,
217
+ onClick: () => history.push('/'),
218
+ }}
190
219
  menuItems={menuItems}
191
- settings={<UserSettings />}
192
- initIsCompact
220
+ compact={props.compact}
221
+ onChangeCompact={setIsCompact}
193
222
  className={b()}
194
223
  renderContent={() => props.children}
195
- renderFooter={({isCompact, asideRef}) => (
224
+ renderFooter={({compact, asideRef}) => (
196
225
  <React.Fragment>
197
- <AsideHeaderFooterItem
198
- slot={SlotName.Support}
199
- iconSize={24}
200
- text="Documentation"
201
- isCompact={isCompact}
202
- onClick={() => {
203
- window.open('http://ydb.tech/docs', '_blank', 'noreferrer');
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={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);
@@ -6,13 +6,6 @@
6
6
  height: 100%;
7
7
  @include flex-container();
8
8
 
9
- &__loader {
10
- display: flex;
11
- flex: 1 1 auto;
12
- justify-content: center;
13
- align-items: center;
14
- }
15
-
16
9
  &__limits {
17
10
  display: flex;
18
11
  align-items: center;