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.
- package/CHANGELOG.md +18 -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/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/Storage.js +12 -19
- 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 +4 -8
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +7 -7
- package/dist/containers/Tenants/Tenants.js +1 -1
- package/dist/containers/UserSettings/UserSettings.tsx +4 -3
- package/dist/routes.ts +1 -1
- package/dist/store/reducers/{heatmap.js → heatmap.ts} +33 -18
- package/dist/store/reducers/settings.js +12 -2
- package/dist/types/api/compute.ts +1 -1
- package/dist/types/api/schema.ts +16 -3
- package/dist/types/store/heatmap.ts +51 -0
- package/dist/utils/constants.ts +1 -37
- package/dist/utils/getNodesColumns.js +7 -2
- package/dist/utils/tablet.ts +53 -0
- package/package.json +2 -1
- 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
|
@@ -161,7 +161,8 @@ export const HeatmapCanvas = (props) => {
|
|
|
161
161
|
|
|
162
162
|
HeatmapCanvas.propTypes = {
|
|
163
163
|
tablets: PropTypes.array,
|
|
164
|
-
parentRef: PropTypes.
|
|
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
|
|
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
|
|
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
|
-
|
|
234
|
+
const entityName = storageType === StorageTypes.groups ? 'Groups' : 'Nodes';
|
|
234
235
|
const count = storageType === StorageTypes.groups ? groupsCount : nodesCount;
|
|
235
236
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
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
|
}
|
|
@@ -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
|
+
};
|
|
@@ -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-
|
|
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 @@
|
|
|
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 {
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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
|
|
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={
|
|
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
|
-
|
|
175
|
-
<div>
|
|
176
|
-
|
|
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
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
|
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 '
|
|
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
|
-
|
|
8
|
+
|
|
8
9
|
import {INVERTED_DISKS_KEY, THEME_KEY} from '../../utils/constants';
|
|
9
|
-
|
|
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 {
|
|
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
|
|
25
|
+
const heatmap: Reducer<IHeatmapState, IHeatmapAction> = (state = initialState, action) => {
|
|
16
26
|
switch (action.type) {
|
|
17
|
-
case
|
|
27
|
+
case FETCH_HEATMAP.REQUEST: {
|
|
18
28
|
return {
|
|
19
29
|
...state,
|
|
20
30
|
loading: true,
|
|
21
31
|
};
|
|
22
32
|
}
|
|
23
|
-
case
|
|
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
|
|
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:
|
|
57
|
-
dataHandler: ([tabletsData =
|
|
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
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
|
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;
|