ydb-embedded-ui 3.2.0 → 3.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/components/EntitiesCount/EntitiesCount.tsx +34 -0
  3. package/dist/components/EntitiesCount/i18n/en.json +3 -0
  4. package/dist/components/{AsideNavigation/Settings → EntitiesCount}/i18n/index.ts +2 -2
  5. package/dist/components/EntitiesCount/i18n/ru.json +3 -0
  6. package/dist/components/EntitiesCount/index.ts +1 -0
  7. package/dist/components/Fullscreen/Fullscreen.scss +7 -5
  8. package/dist/components/TabletsOverall/TabletsOverall.tsx +4 -4
  9. package/dist/components/TabletsStatistic/TabletsStatistic.tsx +56 -0
  10. package/dist/components/TabletsStatistic/index.ts +1 -0
  11. package/dist/containers/App/App.scss +4 -12
  12. package/dist/containers/AsideNavigation/AsideNavigation.scss +0 -18
  13. package/dist/containers/AsideNavigation/AsideNavigation.tsx +95 -33
  14. package/dist/containers/Heatmap/Heatmap.scss +0 -7
  15. package/dist/containers/Heatmap/Heatmap.tsx +203 -0
  16. package/dist/containers/Heatmap/HeatmapCanvas/HeatmapCanvas.js +2 -1
  17. package/dist/containers/Heatmap/index.ts +1 -0
  18. package/dist/containers/Node/Node.tsx +1 -1
  19. package/dist/containers/Storage/Storage.js +12 -19
  20. package/dist/containers/Tablets/Tablets.scss +0 -5
  21. package/dist/containers/Tablets/Tablets.tsx +172 -0
  22. package/dist/containers/Tablets/i18n/en.json +6 -0
  23. package/dist/{components/AsideNavigation → containers/Tablets}/i18n/index.ts +1 -1
  24. package/dist/containers/Tablets/i18n/ru.json +6 -0
  25. package/dist/containers/Tablets/index.ts +1 -0
  26. package/dist/containers/TabletsFilters/TabletsFilters.js +4 -8
  27. package/dist/containers/TabletsFilters/TabletsFilters.scss +6 -2
  28. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +4 -8
  29. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +7 -7
  30. package/dist/containers/Tenants/Tenants.js +1 -1
  31. package/dist/containers/UserSettings/UserSettings.tsx +4 -3
  32. package/dist/routes.ts +1 -1
  33. package/dist/store/reducers/{heatmap.js → heatmap.ts} +33 -18
  34. package/dist/store/reducers/settings.js +12 -2
  35. package/dist/types/api/compute.ts +1 -1
  36. package/dist/types/api/schema.ts +16 -3
  37. package/dist/types/store/heatmap.ts +51 -0
  38. package/dist/utils/constants.ts +1 -37
  39. package/dist/utils/getNodesColumns.js +7 -2
  40. package/dist/utils/tablet.ts +53 -0
  41. package/package.json +2 -1
  42. package/dist/components/AsideNavigation/AsideHeader.scss +0 -147
  43. package/dist/components/AsideNavigation/AsideHeader.tsx +0 -389
  44. package/dist/components/AsideNavigation/AsideHeaderFooterItem/AsideHeaderFooterItem.scss +0 -82
  45. package/dist/components/AsideNavigation/AsideHeaderFooterItem/AsideHeaderFooterItem.tsx +0 -138
  46. package/dist/components/AsideNavigation/AsideHeaderFooterSlot/AsideHeaderFooterSlot.tsx +0 -33
  47. package/dist/components/AsideNavigation/AsideHeaderFooterSlot/SlotsContext.tsx +0 -49
  48. package/dist/components/AsideNavigation/AsideHeaderTooltip/AsideHeaderTooltip.scss +0 -16
  49. package/dist/components/AsideNavigation/AsideHeaderTooltip/AsideHeaderTooltip.tsx +0 -37
  50. package/dist/components/AsideNavigation/CompositeBar/CompositeBar.scss +0 -108
  51. package/dist/components/AsideNavigation/CompositeBar/CompositeBar.tsx +0 -282
  52. package/dist/components/AsideNavigation/Content/Content.tsx +0 -35
  53. package/dist/components/AsideNavigation/Drawer/Drawer.scss +0 -76
  54. package/dist/components/AsideNavigation/Drawer/Drawer.tsx +0 -134
  55. package/dist/components/AsideNavigation/Drawer/index.ts +0 -1
  56. package/dist/components/AsideNavigation/Logo/Logo.scss +0 -43
  57. package/dist/components/AsideNavigation/Logo/Logo.tsx +0 -82
  58. package/dist/components/AsideNavigation/Settings/README.md +0 -92
  59. package/dist/components/AsideNavigation/Settings/Settings.scss +0 -128
  60. package/dist/components/AsideNavigation/Settings/Settings.tsx +0 -270
  61. package/dist/components/AsideNavigation/Settings/SettingsMenu/SettingsMenu.scss +0 -78
  62. package/dist/components/AsideNavigation/Settings/SettingsMenu/SettingsMenu.tsx +0 -141
  63. package/dist/components/AsideNavigation/Settings/SettingsSearch/SettingsSearch.tsx +0 -57
  64. package/dist/components/AsideNavigation/Settings/collect-settings.ts +0 -156
  65. package/dist/components/AsideNavigation/Settings/filter-settings.ts +0 -38
  66. package/dist/components/AsideNavigation/Settings/helpers.ts +0 -39
  67. package/dist/components/AsideNavigation/Settings/i18n/en.json +0 -5
  68. package/dist/components/AsideNavigation/Settings/i18n/ru.json +0 -5
  69. package/dist/components/AsideNavigation/Settings/index.ts +0 -1
  70. package/dist/components/AsideNavigation/constants.ts +0 -28
  71. package/dist/components/AsideNavigation/helpers.ts +0 -34
  72. package/dist/components/AsideNavigation/i18n/en.json +0 -4
  73. package/dist/components/AsideNavigation/i18n/ru.json +0 -4
  74. package/dist/components/AsideNavigation/icons.ts +0 -32
  75. package/dist/components/AsideNavigation/types.ts +0 -23
  76. package/dist/components/TabletsStatistic/TabletsStatistic.js +0 -58
  77. package/dist/containers/Heatmap/Heatmap.js +0 -244
  78. package/dist/containers/Tablets/Tablets.js +0 -228
@@ -161,7 +161,8 @@ export const HeatmapCanvas = (props) => {
161
161
 
162
162
  HeatmapCanvas.propTypes = {
163
163
  tablets: PropTypes.array,
164
- parentRef: PropTypes.node,
164
+ parentRef: PropTypes.object,
165
165
  showTooltip: PropTypes.func,
166
166
  hideTooltip: PropTypes.func,
167
+ currentMetric: PropTypes.string,
167
168
  };
@@ -0,0 +1 @@
1
+ export * from './Heatmap';
@@ -8,7 +8,7 @@ import {Tabs} from '@gravity-ui/uikit';
8
8
  import {Link} from 'react-router-dom';
9
9
 
10
10
  import {TABLETS, STORAGE, NODE_PAGES, OVERVIEW, STRUCTURE} from './NodePages';
11
- import Tablets from '../Tablets/Tablets';
11
+ import {Tablets} from '../Tablets';
12
12
  import Storage from '../Storage/Storage';
13
13
  import NodeOverview from './NodeOverview/NodeOverview';
14
14
  import NodeStructure from './NodeStructure/NodeStructure';
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
3
3
  import {connect} from 'react-redux';
4
4
  import cn from 'bem-cn-lite';
5
5
  import DataTable from '@yandex-cloud/react-data-table';
6
- import {RadioButton, Label} from '@gravity-ui/uikit';
6
+ import {RadioButton} from '@gravity-ui/uikit';
7
7
 
8
8
  import {Search} from '../../components/Search';
9
9
  import {UsageFilter} from './UsageFilter';
@@ -12,6 +12,7 @@ import {NodesUptimeFilterValues} from '../../utils/nodes';
12
12
  import {TableSkeleton} from '../../components/TableSkeleton/TableSkeleton';
13
13
  import {UptimeFilter} from '../../components/UptimeFIlter';
14
14
  import {AccessDenied} from '../../components/Errors/403';
15
+ import {EntitiesCount} from '../../components/EntitiesCount';
15
16
 
16
17
  import {
17
18
  getStorageInfo,
@@ -230,22 +231,17 @@ class Storage extends React.Component {
230
231
  const {storageType, groupsCount, nodesCount, flatListStorageEntities, loading, wasLoaded} =
231
232
  this.props;
232
233
 
233
- let label = `${storageType === StorageTypes.groups ? 'Groups' : 'Nodes'}: `;
234
+ const entityName = storageType === StorageTypes.groups ? 'Groups' : 'Nodes';
234
235
  const count = storageType === StorageTypes.groups ? groupsCount : nodesCount;
235
236
 
236
- if (loading && !wasLoaded) {
237
- label += '...';
238
- return label;
239
- }
240
-
241
- // count.total can be missing in old versions
242
- if (flatListStorageEntities.length === Number(count.total) || !count.total) {
243
- label += flatListStorageEntities.length;
244
- } else {
245
- label += `${flatListStorageEntities.length} of ${count.total}`;
246
- }
247
-
248
- return label;
237
+ return (
238
+ <EntitiesCount
239
+ label={entityName}
240
+ loading={loading && !wasLoaded}
241
+ total={count.total}
242
+ current={flatListStorageEntities.length}
243
+ />
244
+ );
249
245
  }
250
246
 
251
247
  renderControls() {
@@ -307,10 +303,7 @@ class Storage extends React.Component {
307
303
  disabled={usageFilterOptions.length === 0}
308
304
  />
309
305
  )}
310
-
311
- <Label theme="info" size="m">
312
- {this.renderEntitiesCount()}
313
- </Label>
306
+ {this.renderEntitiesCount()}
314
307
  </div>
315
308
  );
316
309
  }
@@ -37,9 +37,4 @@
37
37
  line-height: 18px;
38
38
  text-align: center;
39
39
  }
40
-
41
- &__loader-wrapper {
42
- display: flex;
43
- justify-content: center;
44
- }
45
40
  }
@@ -0,0 +1,172 @@
1
+ import {useCallback, useEffect, useMemo, useState} from 'react';
2
+ import {useDispatch} from 'react-redux';
3
+ import cn from 'bem-cn-lite';
4
+ import ReactList from 'react-list';
5
+
6
+ import {Select} from '@gravity-ui/uikit';
7
+
8
+ import Tablet from '../../components/Tablet/Tablet';
9
+ import TabletsOverall from '../../components/TabletsOverall/TabletsOverall';
10
+ import {Loader} from '../../components/Loader';
11
+
12
+ import {useAutofetcher, useTypedSelector} from '../../utils/hooks';
13
+ import {ETabletState, EType, TTabletStateInfo} from '../../types/api/tablet';
14
+
15
+ import {showTooltip, hideTooltip} from '../../store/reducers/tooltip';
16
+ import {
17
+ getTabletsInfo,
18
+ clearWasLoadingFlag,
19
+ setStateFilter,
20
+ setTypeFilter,
21
+ } from '../../store/reducers/tablets';
22
+
23
+ import './Tablets.scss';
24
+
25
+ import i18n from './i18n';
26
+
27
+ const b = cn('tablets');
28
+
29
+ interface TabletsProps {
30
+ path?: string;
31
+ nodeId?: string | number;
32
+ className?: string;
33
+ }
34
+
35
+ export const Tablets = ({path, nodeId, className}: TabletsProps) => {
36
+ const dispatch = useDispatch();
37
+
38
+ const {
39
+ data = {},
40
+ wasLoaded,
41
+ loading,
42
+ error,
43
+ stateFilter,
44
+ typeFilter,
45
+ } = useTypedSelector((state) => state.tablets);
46
+ const {autorefresh} = useTypedSelector((state) => state.schema);
47
+
48
+ const tablets = useMemo(() => data?.TabletStateInfo || [], [data]);
49
+
50
+ const fetchData = useCallback(
51
+ (isBackground) => {
52
+ if (!isBackground) {
53
+ dispatch(clearWasLoadingFlag());
54
+ }
55
+ if (nodeId) {
56
+ dispatch(getTabletsInfo({nodes: [String(nodeId)]}));
57
+ } else if (path) {
58
+ dispatch(getTabletsInfo({path}));
59
+ }
60
+ },
61
+ [path, nodeId, dispatch],
62
+ );
63
+
64
+ useAutofetcher(fetchData, [fetchData], autorefresh);
65
+
66
+ const [tabletsToRender, setTabletsToRender] = useState<TTabletStateInfo[]>([]);
67
+
68
+ useEffect(() => {
69
+ let filteredTablets = tablets;
70
+
71
+ if (typeFilter.length > 0) {
72
+ filteredTablets = filteredTablets.filter((tablet) =>
73
+ typeFilter.some((filter) => tablet.Type === filter),
74
+ );
75
+ }
76
+ if (stateFilter.length > 0) {
77
+ filteredTablets = filteredTablets.filter((tablet) =>
78
+ stateFilter.some((filter) => tablet.State === filter),
79
+ );
80
+ }
81
+ setTabletsToRender(filteredTablets);
82
+ }, [tablets, stateFilter, typeFilter]);
83
+
84
+ const handleStateFilterChange = (value: string[]) => {
85
+ dispatch(setStateFilter(value as ETabletState[]));
86
+ };
87
+
88
+ const handleTypeFilterChange = (value: string[]) => {
89
+ dispatch(setTypeFilter(value as EType[]));
90
+ };
91
+
92
+ const onShowTooltip = (...args: Parameters<typeof showTooltip>) => {
93
+ dispatch(showTooltip(...args));
94
+ };
95
+
96
+ const onHideTooltip = () => {
97
+ dispatch(hideTooltip());
98
+ };
99
+
100
+ const renderTablet = (tabletIndex: number) => {
101
+ return (
102
+ <Tablet
103
+ onMouseLeave={onHideTooltip}
104
+ onMouseEnter={onShowTooltip}
105
+ tablet={tabletsToRender[tabletIndex]}
106
+ key={tabletIndex}
107
+ className={b('tablet')}
108
+ />
109
+ );
110
+ };
111
+
112
+ const renderContent = () => {
113
+ const states = Array.from(new Set(tablets.map((tablet) => tablet.State)))
114
+ .filter((state): state is ETabletState => state !== undefined)
115
+ .map((item) => ({
116
+ value: item,
117
+ content: item,
118
+ }));
119
+ const types = Array.from(new Set(tablets.map((tablet) => tablet.Type)))
120
+ .filter((type): type is EType => type !== undefined)
121
+ .map((item) => ({
122
+ value: item,
123
+ content: item,
124
+ }));
125
+
126
+ return (
127
+ <div className={b(null, className)}>
128
+ <div className={b('header')}>
129
+ <Select
130
+ className={b('filter-control')}
131
+ multiple
132
+ placeholder={i18n('controls.allItems')}
133
+ label={`${i18n('controls.state')}:`}
134
+ options={states}
135
+ value={stateFilter}
136
+ onUpdate={handleStateFilterChange}
137
+ />
138
+ <Select
139
+ className={b('filter-control')}
140
+ multiple
141
+ placeholder={i18n('controls.allItems')}
142
+ label={`${i18n('controls.type')}:`}
143
+ options={types}
144
+ value={typeFilter}
145
+ onUpdate={handleTypeFilterChange}
146
+ />
147
+ <TabletsOverall tablets={tablets} />
148
+ </div>
149
+
150
+ <div className={b('items')}>
151
+ <ReactList
152
+ itemRenderer={renderTablet}
153
+ length={tabletsToRender.length}
154
+ type="uniform"
155
+ />
156
+ </div>
157
+ </div>
158
+ );
159
+ };
160
+
161
+ if (loading && !wasLoaded) {
162
+ return <Loader />;
163
+ } else if (error) {
164
+ return <div className="error">{error.statusText}</div>;
165
+ } else {
166
+ return tablets.length > 0 ? (
167
+ renderContent()
168
+ ) : (
169
+ <div className="error">{i18n('noTabletsData')}</div>
170
+ );
171
+ }
172
+ };
@@ -0,0 +1,6 @@
1
+ {
2
+ "controls.type": "Type",
3
+ "controls.state": "State",
4
+ "controls.allItems": "All items",
5
+ "noTabletsData": "No tablets data"
6
+ }
@@ -3,7 +3,7 @@ import {i18n, Lang} from '../../../utils/i18n';
3
3
  import en from './en.json';
4
4
  import ru from './ru.json';
5
5
 
6
- const COMPONENT = 'ydb-embedded-ui';
6
+ const COMPONENT = 'ydb-tablets';
7
7
 
8
8
  i18n.registerKeyset(Lang.En, COMPONENT, en);
9
9
  i18n.registerKeyset(Lang.Ru, COMPONENT, ru);
@@ -0,0 +1,6 @@
1
+ {
2
+ "controls.type": "Тип",
3
+ "controls.state": "Состояние",
4
+ "controls.allItems": "Все",
5
+ "noTabletsData": "Нет информации о таблетках"
6
+ }
@@ -0,0 +1 @@
1
+ export * from './Tablets';
@@ -11,7 +11,7 @@ import ReactList from 'react-list';
11
11
  import Tablet from '../../components/Tablet/Tablet';
12
12
  import {AccessDenied} from '../../components/Errors/403';
13
13
 
14
- import {TABLET_COLOR_TO_STATES, TABLETS_STATES} from '../../utils/constants';
14
+ import {tabletColorToTabletState, tabletStates} from '../../utils/tablet';
15
15
  import {showTooltip, hideTooltip} from '../../store/reducers/tooltip';
16
16
  import {
17
17
  getTabletsInfo,
@@ -61,7 +61,7 @@ class TabletsFilters extends React.Component {
61
61
  };
62
62
 
63
63
  static getStateFiltersFromColor = (color) => {
64
- return TABLET_COLOR_TO_STATES[color] || [color];
64
+ return tabletColorToTabletState[color] || [color];
65
65
  };
66
66
 
67
67
  static CONTROL_WIDTH = 220;
@@ -159,7 +159,7 @@ class TabletsFilters extends React.Component {
159
159
  const {nodeFilter, tenantPath} = this.state;
160
160
  const {tablets, filteredTablets, nodes, stateFilter, typeFilter, error} = this.props;
161
161
 
162
- const states = TABLETS_STATES.map((item) => ({value: item, content: item}));
162
+ const states = tabletStates.map((item) => ({value: item, content: item}));
163
163
  const types = Array.from(new Set(...[_.map(tablets, (tblt) => tblt.Type)])).map((item) => ({
164
164
  value: item,
165
165
  content: item,
@@ -243,8 +243,6 @@ const Filters = ({
243
243
  <Select
244
244
  multiple
245
245
  label="Node ID"
246
- showApply
247
- showItemMeta
248
246
  width={TabletsFilters.CONTROL_WIDTH}
249
247
  popupWidth={TabletsFilters.POPUP_WIDTH}
250
248
  placeholder="All"
@@ -255,7 +253,7 @@ const Filters = ({
255
253
  return (
256
254
  <div className={b('node')}>
257
255
  <div>{option.content}</div>
258
- <div className={b('node-meta')}>{option.meta}</div>
256
+ <div className={b('node-meta')} title={option.meta}>{option.meta}</div>
259
257
  </div>
260
258
  );
261
259
  }}
@@ -267,7 +265,6 @@ const Filters = ({
267
265
  <Select
268
266
  multiple
269
267
  label="multiple"
270
- showApply
271
268
  width={TabletsFilters.CONTROL_WIDTH}
272
269
  placeholder="All"
273
270
  options={states}
@@ -280,7 +277,6 @@ const Filters = ({
280
277
  <Select
281
278
  multiple
282
279
  label="Types"
283
- showApply
284
280
  width={TabletsFilters.CONTROL_WIDTH}
285
281
  placeholder="All"
286
282
  options={types}
@@ -6,14 +6,18 @@
6
6
  @include flex-container();
7
7
 
8
8
  &__node {
9
- display: flex;
10
- flex-direction: column;
9
+ overflow: hidden;
11
10
 
12
11
  font-size: var(--yc-text-body-1-font-size);
13
12
  line-height: var(--yc-text-body-1-line-height);
14
13
  }
15
14
 
16
15
  &__node-meta {
16
+ overflow: hidden;
17
+
18
+ white-space: nowrap;
19
+ text-overflow: ellipsis;
20
+
17
21
  color: var(--yc-color-text-secondary);
18
22
  }
19
23
 
@@ -22,11 +22,11 @@ import Describe from './Describe/Describe';
22
22
  //@ts-ignore
23
23
  import HotKeys from './HotKeys/HotKeys';
24
24
  //@ts-ignore
25
- import Heatmap from '../../Heatmap/Heatmap';
25
+ import {Heatmap} from '../../Heatmap';
26
26
  //@ts-ignore
27
27
  import Compute from './Compute/Compute';
28
28
  //@ts-ignore
29
- import Tablets from '../../Tablets/Tablets';
29
+ import {Tablets} from '../../Tablets';
30
30
  import {Consumers} from './Consumers';
31
31
 
32
32
  import routes, {createHref} from '../../../routes';
@@ -50,11 +50,7 @@ const b = cn('kv-tenant-diagnostics');
50
50
 
51
51
  function Diagnostics(props: DiagnosticsProps) {
52
52
  const dispatch = useDispatch();
53
- const {
54
- currentSchemaPath,
55
- currentSchema: currentItem = {},
56
- autorefresh,
57
- } = useSelector((state: any) => state.schema);
53
+ const {currentSchemaPath, autorefresh} = useSelector((state: any) => state.schema);
58
54
  const {diagnosticsTab = GeneralPagesIds.overview, wasLoaded} = useSelector(
59
55
  (state: any) => state.tenant,
60
56
  );
@@ -156,7 +152,7 @@ function Diagnostics(props: DiagnosticsProps) {
156
152
  return <HotKeys type={type} />;
157
153
  }
158
154
  case GeneralPagesIds.graph: {
159
- return <Heatmap path={currentItem.Path} />;
155
+ return <Heatmap path={currentSchemaPath} />;
160
156
  }
161
157
  case GeneralPagesIds.consumers: {
162
158
  return <Consumers path={currentSchemaPath} type={type} />;
@@ -171,18 +171,18 @@ class TenantOverview extends React.Component {
171
171
  ))}
172
172
  </div>
173
173
  <div className={b('common-info')}>
174
- {PoolStats ? (
175
- <div>
176
- <div className={b('section-title')}>Pools</div>
174
+ <div>
175
+ <div className={b('section-title')}>Pools</div>
176
+ {PoolStats ? (
177
177
  <div className={b('section', {pools: true})}>
178
178
  {PoolStats.map((pool, poolIndex) => (
179
179
  <PoolUsage key={poolIndex} data={pool} />
180
180
  ))}
181
181
  </div>
182
- </div>
183
- ) : (
184
- <div className="error">no pools data</div>
185
- )}
182
+ ) : (
183
+ <div className="error">no pools data</div>
184
+ )}
185
+ </div>
186
186
  <InfoViewer
187
187
  title="Metrics"
188
188
  className={b('section', {metrics: true})}
@@ -9,7 +9,7 @@ import {Loader, TextInput, Button} from '@gravity-ui/uikit';
9
9
 
10
10
  import EntityStatus from '../../components/EntityStatus/EntityStatus';
11
11
  import PoolsGraph from '../../components/PoolsGraph/PoolsGraph';
12
- import TabletsStatistic from '../../components/TabletsStatistic/TabletsStatistic';
12
+ import {TabletsStatistic} from '../../components/TabletsStatistic';
13
13
  import {ProblemFilter} from '../../components/ProblemFilter';
14
14
  import {Illustration} from '../../components/Illustration';
15
15
  import {AutoFetcher} from '../../utils/autofetcher';
@@ -1,12 +1,13 @@
1
1
  import {connect} from 'react-redux';
2
2
 
3
3
  import {RadioButton, Switch} from '@gravity-ui/uikit';
4
- import {Settings} from '../../components/AsideNavigation/Settings';
4
+ import {Settings} from '@gravity-ui/navigation';
5
+
5
6
  import favoriteFilledIcon from '../../assets/icons/star.svg';
6
7
  import flaskIcon from '../../assets/icons/flask.svg';
7
- //@ts-ignore
8
+
8
9
  import {INVERTED_DISKS_KEY, THEME_KEY} from '../../utils/constants';
9
- //@ts-ignore
10
+
10
11
  import {setSettingValue} from '../../store/reducers/settings';
11
12
 
12
13
  enum Theme {
package/dist/routes.ts CHANGED
@@ -28,7 +28,7 @@ export const CLUSTER_PAGES = {
28
28
  export function createHref(
29
29
  route: string,
30
30
  params?: object,
31
- query: Record<string | number, string | number> = {},
31
+ query: Record<string | number, string | number | string[] | number[] | undefined> = {},
32
32
  ) {
33
33
  let extendedQuery = query;
34
34
 
@@ -1,7 +1,17 @@
1
- import {createRequestActionTypes, createApiRequest} from '../utils';
1
+ import type {Reducer} from 'redux';
2
+
2
3
  import '../../services/api';
4
+ import type {
5
+ IHeatmapAction,
6
+ IHeatmapApiRequestParams,
7
+ IHeatmapState,
8
+ IHeatmapTabletData,
9
+ } from '../../types/store/heatmap';
10
+
11
+ import {createRequestActionTypes, createApiRequest} from '../utils';
12
+
13
+ export const FETCH_HEATMAP = createRequestActionTypes('heatmap', 'FETCH_HEATMAP');
3
14
 
4
- const FETCH_TABLETS = createRequestActionTypes('heatmap', 'FETCH_TABLETS');
5
15
  const SET_HEATMAP_OPTIONS = 'heatmap/SET_HEATMAP_OPTIONS';
6
16
 
7
17
  export const initialState = {
@@ -12,15 +22,15 @@ export const initialState = {
12
22
  heatmap: false,
13
23
  };
14
24
 
15
- const tablets = function z(state = initialState, action) {
25
+ const heatmap: Reducer<IHeatmapState, IHeatmapAction> = (state = initialState, action) => {
16
26
  switch (action.type) {
17
- case FETCH_TABLETS.REQUEST: {
27
+ case FETCH_HEATMAP.REQUEST: {
18
28
  return {
19
29
  ...state,
20
30
  loading: true,
21
31
  };
22
32
  }
23
- case FETCH_TABLETS.SUCCESS: {
33
+ case FETCH_HEATMAP.SUCCESS: {
24
34
  return {
25
35
  ...state,
26
36
  ...action.data,
@@ -29,7 +39,7 @@ const tablets = function z(state = initialState, action) {
29
39
  error: undefined,
30
40
  };
31
41
  }
32
- case FETCH_TABLETS.FAILURE: {
42
+ case FETCH_HEATMAP.FAILURE: {
33
43
  return {
34
44
  ...state,
35
45
  error: action.error,
@@ -47,16 +57,16 @@ const tablets = function z(state = initialState, action) {
47
57
  }
48
58
  };
49
59
 
50
- export function getTabletsInfo({nodes, path}) {
60
+ export function getTabletsInfo({nodes, path}: IHeatmapApiRequestParams) {
51
61
  return createApiRequest({
52
62
  request: Promise.all([
53
63
  window.api.getTabletsInfo({nodes, path}),
54
64
  window.api.getHeatmapData({path}),
55
65
  ]),
56
- actions: FETCH_TABLETS,
57
- dataHandler: ([tabletsData = [], describe = {}]) => {
66
+ actions: FETCH_HEATMAP,
67
+ dataHandler: ([tabletsData = {}, describe = {}]) => {
58
68
  const {TabletStateInfo: tablets = []} = tabletsData;
59
- const TabletsMap = new Map();
69
+ const TabletsMap: Map<string, IHeatmapTabletData> = new Map();
60
70
  const {PathDescription = {}} = describe;
61
71
  const {
62
72
  TablePartitions = [],
@@ -65,7 +75,9 @@ export function getTabletsInfo({nodes, path}) {
65
75
  } = PathDescription;
66
76
 
67
77
  tablets.forEach((item) => {
68
- TabletsMap.set(item.TabletId, item);
78
+ if (item.TabletId) {
79
+ TabletsMap.set(item.TabletId, item);
80
+ }
69
81
  });
70
82
 
71
83
  TablePartitions.forEach((item, index) => {
@@ -74,15 +86,18 @@ export function getTabletsInfo({nodes, path}) {
74
86
  TablePartitionStats[index],
75
87
  TablePartitionMetrics[index],
76
88
  );
77
- TabletsMap.set(item.DatashardId, {
78
- ...TabletsMap.get(item.DatashardId),
79
- metrics,
80
- });
89
+ if (item.DatashardId) {
90
+ TabletsMap.set(item.DatashardId, {
91
+ ...TabletsMap.get(item.DatashardId),
92
+ metrics,
93
+ });
94
+ }
81
95
  });
82
96
 
83
97
  const preparedTablets = Array.from(TabletsMap.values());
84
98
  const selectMetrics =
85
99
  preparedTablets[0] &&
100
+ preparedTablets[0].metrics &&
86
101
  Object.keys(preparedTablets[0].metrics).map((item) => {
87
102
  return {
88
103
  value: item,
@@ -95,11 +110,11 @@ export function getTabletsInfo({nodes, path}) {
95
110
  });
96
111
  }
97
112
 
98
- export function setHeatmapOptions(options) {
113
+ export function setHeatmapOptions(options: Partial<IHeatmapState>) {
99
114
  return {
100
115
  type: SET_HEATMAP_OPTIONS,
101
116
  data: options,
102
- };
117
+ } as const;
103
118
  }
104
119
 
105
- export default tablets;
120
+ export default heatmap;
@@ -1,11 +1,11 @@
1
1
  import {
2
- defaultUserSettings,
3
2
  ALL,
4
3
  SAVED_QUERIES_KEY,
5
4
  THEME_KEY,
6
5
  TENANT_INITIAL_TAB_KEY,
7
6
  QUERY_INITIAL_RUN_ACTION_KEY,
8
7
  INVERTED_DISKS_KEY,
8
+ ASIDE_HEADER_COMPACT_KEY,
9
9
  } from '../../utils/constants';
10
10
  import '../../services/api';
11
11
  import {getValueFromLS} from '../../utils/utils';
@@ -24,16 +24,26 @@ export function readSavedSettingsValue(key, defaultValue) {
24
24
  return savedValue ?? defaultValue;
25
25
  }
26
26
 
27
+ // navigation managed its compact state internally before, and its approach is not compatible with settings
28
+ // try reading the old localStorage entry to use it as a default value, for backward compatibility
29
+ // assume it is safe to remove this code block if it is at least a few months old
30
+ // there a two of these, search for a similar comment
31
+ let legacyAsideNavCompactState = '';
32
+ try {
33
+ legacyAsideNavCompactState = String(JSON.parse(getValueFromLS('nvAsideHeader')).isCompact);
34
+ localStorage.removeItem('nvAsideHeader');
35
+ } catch {}
36
+
27
37
  export const initialState = {
28
38
  problemFilter: ALL,
29
39
  userSettings: {
30
- ...defaultUserSettings,
31
40
  ...userSettings,
32
41
  [THEME_KEY]: readSavedSettingsValue(THEME_KEY, 'light'),
33
42
  [INVERTED_DISKS_KEY]: readSavedSettingsValue(INVERTED_DISKS_KEY, 'false'),
34
43
  [SAVED_QUERIES_KEY]: readSavedSettingsValue(SAVED_QUERIES_KEY, '[]'),
35
44
  [TENANT_INITIAL_TAB_KEY]: readSavedSettingsValue(TENANT_INITIAL_TAB_KEY),
36
45
  [QUERY_INITIAL_RUN_ACTION_KEY]: readSavedSettingsValue(QUERY_INITIAL_RUN_ACTION_KEY),
46
+ [ASIDE_HEADER_COMPACT_KEY]: readSavedSettingsValue(ASIDE_HEADER_COMPACT_KEY, legacyAsideNavCompactState || 'true'),
37
47
  },
38
48
  systemSettings,
39
49
  };
@@ -45,7 +45,7 @@ interface TComputeNodeInfo {
45
45
 
46
46
  // Tablets in compute nodes
47
47
  // Types for tabletInfo and tablets inside nodes and storage endpoints are in tablet.ts
48
- interface TTabletStateInfo {
48
+ export interface TTabletStateInfo {
49
49
  Type: string;
50
50
  State: EFlag;
51
51
  Count: number;