ydb-embedded-ui 3.2.0 → 3.2.2

Sign up to get free protection for your applications and to get access to all the features.
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;