ydb-embedded-ui 22.5.0 → 22.6.0
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/dist/components/AutoRefreshControl/StickyAutoRefreshControl.d.ts +2 -0
- package/dist/components/AutoRefreshControl/StickyAutoRefreshControl.js +9 -0
- package/dist/components/AutoRefreshControl/StickyAutoRefreshControl.js.map +1 -0
- package/dist/components/AutoRefreshControl/StickyAutoRefreshControl.scss +18 -0
- package/dist/components/HideUnavailableNodesSwitch/HideUnavailableNodesSwitch.d.ts +3 -0
- package/dist/components/HideUnavailableNodesSwitch/HideUnavailableNodesSwitch.js +12 -0
- package/dist/components/HideUnavailableNodesSwitch/HideUnavailableNodesSwitch.js.map +1 -0
- package/dist/components/HideUnavailableNodesSwitch/i18n/en.json +3 -0
- package/dist/components/HideUnavailableNodesSwitch/i18n/index.d.ts +2 -0
- package/dist/components/HideUnavailableNodesSwitch/i18n/index.js +6 -0
- package/dist/components/HideUnavailableNodesSwitch/i18n/index.js.map +1 -0
- package/dist/components/HideUnavailableNodesSwitch/i18n/ru.json +3 -0
- package/dist/components/PageMeta/PageMeta.d.ts +0 -2
- package/dist/components/PageMeta/PageMeta.js +1 -6
- package/dist/components/PageMeta/PageMeta.js.map +1 -1
- package/dist/containers/Node/Node.js +4 -3
- package/dist/containers/Node/Node.js.map +1 -1
- package/dist/containers/Node/Node.scss +14 -2
- package/dist/containers/Nodes/NodesControls/NodesControls.js +2 -1
- package/dist/containers/Nodes/NodesControls/NodesControls.js.map +1 -1
- package/dist/containers/Nodes/NodesTable.js +4 -0
- package/dist/containers/Nodes/NodesTable.js.map +1 -1
- package/dist/containers/Nodes/PaginatedNodes/GroupedNodesComponent.js +3 -0
- package/dist/containers/Nodes/PaginatedNodes/GroupedNodesComponent.js.map +1 -1
- package/dist/containers/Nodes/PaginatedNodes/NodesComponent.js +9 -1
- package/dist/containers/Nodes/PaginatedNodes/NodesComponent.js.map +1 -1
- package/dist/containers/Nodes/getNodes.js +2 -1
- package/dist/containers/Nodes/getNodes.js.map +1 -1
- package/dist/containers/PDiskPage/PDiskPage.js +5 -14
- package/dist/containers/PDiskPage/PDiskPage.js.map +1 -1
- package/dist/containers/PDiskPage/PDiskPage.scss +11 -4
- package/dist/containers/PDiskPage/i18n/en.json +0 -1
- package/dist/containers/PDiskPage/i18n/index.d.ts +1 -1
- package/dist/containers/Storage/PaginatedStorageNodes/GroupedStorageNodesComponent.js +3 -0
- package/dist/containers/Storage/PaginatedStorageNodes/GroupedStorageNodesComponent.js.map +1 -1
- package/dist/containers/Storage/PaginatedStorageNodes/StorageNodesComponent.js +8 -1
- package/dist/containers/Storage/PaginatedStorageNodes/StorageNodesComponent.js.map +1 -1
- package/dist/containers/Storage/PaginatedStorageNodes/StorageNodesControls.js +2 -1
- package/dist/containers/Storage/PaginatedStorageNodes/StorageNodesControls.js.map +1 -1
- package/dist/containers/Storage/PaginatedStorageNodesTable/PaginatedStorageNodesTable.js +4 -0
- package/dist/containers/Storage/PaginatedStorageNodesTable/PaginatedStorageNodesTable.js.map +1 -1
- package/dist/containers/Storage/PaginatedStorageNodesTable/getNodes.js +2 -1
- package/dist/containers/Storage/PaginatedStorageNodesTable/getNodes.js.map +1 -1
- package/dist/containers/Storage/Storage.scss +4 -0
- package/dist/containers/StorageGroupPage/StorageGroupPage.js +4 -15
- package/dist/containers/StorageGroupPage/StorageGroupPage.js.map +1 -1
- package/dist/containers/StorageGroupPage/StorageGroupPage.scss +14 -9
- package/dist/containers/StorageGroupPage/i18n/en.json +0 -1
- package/dist/containers/StorageGroupPage/i18n/index.d.ts +1 -1
- package/dist/containers/Tablet/Tablet.js +3 -2
- package/dist/containers/Tablet/Tablet.js.map +1 -1
- package/dist/containers/Tablet/Tablet.scss +15 -1
- package/dist/containers/VDiskPage/VDiskPage.js +5 -14
- package/dist/containers/VDiskPage/VDiskPage.js.map +1 -1
- package/dist/containers/VDiskPage/VDiskPage.scss +23 -4
- package/dist/containers/VDiskPage/i18n/en.json +0 -1
- package/dist/containers/VDiskPage/i18n/index.d.ts +1 -1
- package/dist/store/reducers/capabilities/hooks.d.ts +1 -0
- package/dist/store/reducers/capabilities/hooks.js +3 -0
- package/dist/store/reducers/capabilities/hooks.js.map +1 -1
- package/dist/store/reducers/nodes/types.d.ts +1 -0
- package/dist/store/reducers/storage/types.d.ts +1 -0
- package/dist/types/api/capabilities.d.ts +1 -1
- package/dist/types/api/nodes.d.ts +2 -0
- package/dist/utils/hooks/useHideUnavailableNodes.d.ts +5 -0
- package/dist/utils/hooks/useHideUnavailableNodes.js +21 -0
- package/dist/utils/hooks/useHideUnavailableNodes.js.map +1 -0
- package/package.json +1 -1
- package/src/components/AutoRefreshControl/StickyAutoRefreshControl.scss +18 -0
- package/src/components/AutoRefreshControl/StickyAutoRefreshControl.tsx +15 -0
- package/src/components/HideUnavailableNodesSwitch/HideUnavailableNodesSwitch.tsx +24 -0
- package/src/components/HideUnavailableNodesSwitch/i18n/en.json +3 -0
- package/src/components/HideUnavailableNodesSwitch/i18n/index.ts +7 -0
- package/src/components/HideUnavailableNodesSwitch/i18n/ru.json +3 -0
- package/src/components/PageMeta/PageMeta.tsx +0 -18
- package/src/containers/Node/Node.scss +14 -2
- package/src/containers/Node/Node.tsx +6 -6
- package/src/containers/Nodes/NodesControls/NodesControls.tsx +2 -0
- package/src/containers/Nodes/NodesTable.tsx +4 -0
- package/src/containers/Nodes/PaginatedNodes/GroupedNodesComponent.tsx +3 -0
- package/src/containers/Nodes/PaginatedNodes/NodesComponent.tsx +9 -1
- package/src/containers/Nodes/getNodes.ts +2 -0
- package/src/containers/PDiskPage/PDiskPage.scss +11 -4
- package/src/containers/PDiskPage/PDiskPage.tsx +4 -30
- package/src/containers/PDiskPage/i18n/en.json +0 -1
- package/src/containers/Storage/PaginatedStorageNodes/GroupedStorageNodesComponent.tsx +3 -0
- package/src/containers/Storage/PaginatedStorageNodes/StorageNodesComponent.tsx +8 -1
- package/src/containers/Storage/PaginatedStorageNodes/StorageNodesControls.tsx +2 -0
- package/src/containers/Storage/PaginatedStorageNodesTable/PaginatedStorageNodesTable.tsx +4 -0
- package/src/containers/Storage/PaginatedStorageNodesTable/getNodes.ts +2 -0
- package/src/containers/Storage/Storage.scss +4 -0
- package/src/containers/StorageGroupPage/StorageGroupPage.scss +14 -9
- package/src/containers/StorageGroupPage/StorageGroupPage.tsx +3 -32
- package/src/containers/StorageGroupPage/i18n/en.json +0 -1
- package/src/containers/Tablet/Tablet.scss +15 -1
- package/src/containers/Tablet/Tablet.tsx +21 -15
- package/src/containers/VDiskPage/VDiskPage.scss +23 -4
- package/src/containers/VDiskPage/VDiskPage.tsx +4 -31
- package/src/containers/VDiskPage/i18n/en.json +0 -1
- package/src/store/reducers/capabilities/hooks.ts +4 -0
- package/src/store/reducers/nodes/types.ts +1 -0
- package/src/store/reducers/storage/types.ts +1 -0
- package/src/types/api/capabilities.ts +1 -0
- package/src/types/api/nodes.ts +2 -0
- package/src/utils/hooks/useHideUnavailableNodes.ts +33 -0
|
@@ -7,6 +7,7 @@ import {NODES_COLUMNS_TO_DATA_FIELDS} from '../../../components/nodesColumns/con
|
|
|
7
7
|
import {storageApi} from '../../../store/reducers/storage/storage';
|
|
8
8
|
import type {NodesGroupByField, NodesRequiredField} from '../../../types/api/nodes';
|
|
9
9
|
import {useAutoRefreshInterval} from '../../../utils/hooks';
|
|
10
|
+
import {useHideUnavailableNodes} from '../../../utils/hooks/useHideUnavailableNodes';
|
|
10
11
|
import {NodesUptimeFilterValues} from '../../../utils/nodes';
|
|
11
12
|
import {renderPaginatedTableErrorMessage} from '../../../utils/renderPaginatedTableErrorMessage';
|
|
12
13
|
import {getRequiredDataFields} from '../../../utils/tableUtils/getRequiredDataFields';
|
|
@@ -105,6 +106,7 @@ export function GroupedStorageNodesComponent({
|
|
|
105
106
|
scrollContainerRef,
|
|
106
107
|
}: PaginatedStorageProps) {
|
|
107
108
|
const [autoRefreshInterval] = useAutoRefreshInterval();
|
|
109
|
+
const {hideUnavailable} = useHideUnavailableNodes();
|
|
108
110
|
|
|
109
111
|
const {nodesSearchValue, storageNodesGroupByParam, handleShowAllNodes} =
|
|
110
112
|
useStorageQueryParams();
|
|
@@ -131,6 +133,7 @@ export function GroupedStorageNodesComponent({
|
|
|
131
133
|
const {currentData, isFetching, error} = storageApi.useGetStorageNodesInfoQuery(
|
|
132
134
|
{
|
|
133
135
|
database,
|
|
136
|
+
alive: hideUnavailable || undefined,
|
|
134
137
|
with: 'all',
|
|
135
138
|
filter: nodesSearchValue.trim(),
|
|
136
139
|
node_id: nodeId,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {PaginatedTableWithLayout} from '../../../components/PaginatedTable/PaginatedTableWithLayout';
|
|
2
2
|
import {TableColumnSetup} from '../../../components/TableColumnSetup/TableColumnSetup';
|
|
3
3
|
import {useViewerNodesHandlerHasGrouping} from '../../../store/reducers/capabilities/hooks';
|
|
4
|
+
import {useHideUnavailableNodes} from '../../../utils/hooks/useHideUnavailableNodes';
|
|
4
5
|
import {renderPaginatedTableErrorMessage} from '../../../utils/renderPaginatedTableErrorMessage';
|
|
5
6
|
import type {PaginatedStorageProps} from '../PaginatedStorage';
|
|
6
7
|
import {PaginatedStorageNodesTable} from '../PaginatedStorageNodesTable/PaginatedStorageNodesTable';
|
|
@@ -22,6 +23,7 @@ export function StorageNodesComponent({
|
|
|
22
23
|
useStorageQueryParams();
|
|
23
24
|
|
|
24
25
|
const viewerNodesHandlerHasGrouping = useViewerNodesHandlerHasGrouping();
|
|
26
|
+
const {hideUnavailable} = useHideUnavailableNodes();
|
|
25
27
|
|
|
26
28
|
const expertMode = useIsStorageExpertMode();
|
|
27
29
|
const {handleDataFetched, columnsSettings, rowHeight} = useStorageColumnsSettings({
|
|
@@ -69,7 +71,12 @@ export function StorageNodesComponent({
|
|
|
69
71
|
}
|
|
70
72
|
tableWrapperProps={{
|
|
71
73
|
scrollContainerRef,
|
|
72
|
-
scrollDependencies: [
|
|
74
|
+
scrollDependencies: [
|
|
75
|
+
nodesSearchValue,
|
|
76
|
+
visibleEntities,
|
|
77
|
+
nodesUptimeFilter,
|
|
78
|
+
hideUnavailable,
|
|
79
|
+
],
|
|
73
80
|
}}
|
|
74
81
|
/>
|
|
75
82
|
);
|
|
@@ -4,6 +4,7 @@ import {ChartTreemap} from '@gravity-ui/icons';
|
|
|
4
4
|
import {Button, Flex, Icon, Select, Text} from '@gravity-ui/uikit';
|
|
5
5
|
|
|
6
6
|
import {EntitiesCount} from '../../../components/EntitiesCount/EntitiesCount';
|
|
7
|
+
import {HideUnavailableNodesSwitch} from '../../../components/HideUnavailableNodesSwitch/HideUnavailableNodesSwitch';
|
|
7
8
|
import {usePaginatedTableState} from '../../../components/PaginatedTable/PaginatedTableContext';
|
|
8
9
|
import {Search} from '../../../components/Search/Search';
|
|
9
10
|
import {UptimeFilter} from '../../../components/UptimeFIlter';
|
|
@@ -127,6 +128,7 @@ export function StorageNodesControls({
|
|
|
127
128
|
{i18n('controls_expert-mode')}
|
|
128
129
|
</Button>
|
|
129
130
|
) : null}
|
|
131
|
+
<HideUnavailableNodesSwitch className={b('hide-unavailable')} />
|
|
130
132
|
</Flex>
|
|
131
133
|
{canUseStorageExpertMode && isStorageExpertMode ? (
|
|
132
134
|
<StorageNodesExpertModePanel />
|
|
@@ -14,6 +14,7 @@ import {VISIBLE_ENTITIES} from '../../../store/reducers/storage/constants';
|
|
|
14
14
|
import type {PreparedStorageNode, VisibleEntities} from '../../../store/reducers/storage/types';
|
|
15
15
|
import type {NodesGroupByField} from '../../../types/api/nodes';
|
|
16
16
|
import {cn} from '../../../utils/cn';
|
|
17
|
+
import {useHideUnavailableNodes} from '../../../utils/hooks/useHideUnavailableNodes';
|
|
17
18
|
import {NodesUptimeFilterValues, isUnavailableNode} from '../../../utils/nodes';
|
|
18
19
|
import {STORAGE_NODES_DEFAULT_ROW_HEIGHT} from '../PaginatedStorageNodes/nodeExpertModeLayout';
|
|
19
20
|
|
|
@@ -69,9 +70,11 @@ export const PaginatedStorageNodesTable = ({
|
|
|
69
70
|
onDataFetched,
|
|
70
71
|
}: PaginatedStorageNodesTableProps) => {
|
|
71
72
|
const history = useHistory();
|
|
73
|
+
const {hideUnavailable} = useHideUnavailableNodes();
|
|
72
74
|
const tableFilters = React.useMemo(() => {
|
|
73
75
|
return {
|
|
74
76
|
searchValue,
|
|
77
|
+
hideUnavailable,
|
|
75
78
|
visibleEntities,
|
|
76
79
|
nodesUptimeFilter,
|
|
77
80
|
database,
|
|
@@ -81,6 +84,7 @@ export const PaginatedStorageNodesTable = ({
|
|
|
81
84
|
filterGroupBy,
|
|
82
85
|
};
|
|
83
86
|
}, [
|
|
87
|
+
hideUnavailable,
|
|
84
88
|
searchValue,
|
|
85
89
|
visibleEntities,
|
|
86
90
|
nodesUptimeFilter,
|
|
@@ -29,6 +29,7 @@ export const getStorageNodes: FetchData<
|
|
|
29
29
|
} = params;
|
|
30
30
|
const {
|
|
31
31
|
searchValue,
|
|
32
|
+
hideUnavailable,
|
|
32
33
|
nodesUptimeFilter,
|
|
33
34
|
visibleEntities,
|
|
34
35
|
database,
|
|
@@ -51,6 +52,7 @@ export const getStorageNodes: FetchData<
|
|
|
51
52
|
offset,
|
|
52
53
|
sort,
|
|
53
54
|
filter: searchValue?.trim(),
|
|
55
|
+
alive: hideUnavailable || undefined,
|
|
54
56
|
uptime: getUptimeParamValue(nodesUptimeFilter),
|
|
55
57
|
with: visibleEntities,
|
|
56
58
|
database,
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
@use '../../styles/mixins.scss';
|
|
2
|
+
|
|
1
3
|
.ydb-storage-group-page {
|
|
4
|
+
--sticky-tabs-height: 40px;
|
|
5
|
+
--data-table-start: var(--sticky-tabs-height);
|
|
2
6
|
position: relative;
|
|
3
7
|
|
|
4
8
|
overflow: auto;
|
|
@@ -15,16 +19,12 @@
|
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
&__summary {
|
|
18
|
-
margin-top: var(--g-spacing-4);
|
|
19
22
|
margin-bottom: var(--g-spacing-6);
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
&__meta {
|
|
23
|
-
margin-bottom: var(--g-spacing-4);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
25
|
&__title {
|
|
27
26
|
margin-bottom: var(--g-spacing-4);
|
|
27
|
+
padding-right: 125px;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
&__title-content {
|
|
@@ -33,11 +33,16 @@
|
|
|
33
33
|
min-width: 0;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
&__refresh-control {
|
|
37
|
-
flex-shrink: 0;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
36
|
&__storage-title {
|
|
37
|
+
z-index: 3;
|
|
38
|
+
|
|
39
|
+
display: flex;
|
|
40
|
+
align-items: center;
|
|
41
|
+
|
|
42
|
+
height: var(--sticky-tabs-height);
|
|
41
43
|
margin: 0;
|
|
44
|
+
padding-right: 125px;
|
|
45
|
+
|
|
46
|
+
@include mixins.sticky-top();
|
|
42
47
|
}
|
|
43
48
|
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {Button, Flex, Icon, Text} from '@gravity-ui/uikit';
|
|
3
|
+
import {Flex, Text} from '@gravity-ui/uikit';
|
|
5
4
|
import {skipToken} from '@reduxjs/toolkit/query';
|
|
6
5
|
import {Helmet} from 'react-helmet-async';
|
|
7
|
-
import {useHistory} from 'react-router-dom';
|
|
8
6
|
import {StringParam, useQueryParams} from 'use-query-params';
|
|
9
7
|
|
|
10
|
-
import {
|
|
8
|
+
import {StickyAutoRefreshControl} from '../../components/AutoRefreshControl/StickyAutoRefreshControl';
|
|
11
9
|
import {CopyableValue} from '../../components/CopyableValue/CopyableValue';
|
|
12
10
|
import {ResponseError} from '../../components/Errors/ResponseError';
|
|
13
11
|
import {InfoViewerSkeleton} from '../../components/InfoViewerSkeleton/InfoViewerSkeleton';
|
|
@@ -32,13 +30,10 @@ const storageGroupPageCn = cn('ydb-storage-group-page');
|
|
|
32
30
|
|
|
33
31
|
export function StorageGroupPage() {
|
|
34
32
|
const dispatch = useTypedDispatch();
|
|
35
|
-
const history = useHistory();
|
|
36
33
|
const database = useDatabaseFromQuery();
|
|
37
34
|
const containerRef = React.useRef<HTMLDivElement>(null);
|
|
38
35
|
|
|
39
36
|
const [{groupId}] = useQueryParams({groupId: StringParam});
|
|
40
|
-
const showBackButton = Boolean(groupId) && history.length > 1;
|
|
41
|
-
const showRefreshInTitle = Boolean(groupId) && !showBackButton;
|
|
42
37
|
|
|
43
38
|
const [autoRefreshInterval] = useAutoRefreshInterval();
|
|
44
39
|
const capabilitiesLoaded = useCapabilitiesLoaded();
|
|
@@ -75,27 +70,6 @@ export function StorageGroupPage() {
|
|
|
75
70
|
);
|
|
76
71
|
};
|
|
77
72
|
|
|
78
|
-
const renderPageMeta = () => {
|
|
79
|
-
if (!showBackButton) {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return (
|
|
84
|
-
<Flex
|
|
85
|
-
className={storageGroupPageCn('meta')}
|
|
86
|
-
alignItems="center"
|
|
87
|
-
justifyContent="space-between"
|
|
88
|
-
gap={2}
|
|
89
|
-
>
|
|
90
|
-
<Button view="outlined" onClick={() => history.goBack()}>
|
|
91
|
-
<Icon data={ArrowLeft} />
|
|
92
|
-
{storageGroupPageKeyset('action_back')}
|
|
93
|
-
</Button>
|
|
94
|
-
<AutoRefreshControl className={storageGroupPageCn('refresh-control')} />
|
|
95
|
-
</Flex>
|
|
96
|
-
);
|
|
97
|
-
};
|
|
98
|
-
|
|
99
73
|
const renderPageTitle = () => {
|
|
100
74
|
return (
|
|
101
75
|
<Flex
|
|
@@ -122,9 +96,6 @@ export function StorageGroupPage() {
|
|
|
122
96
|
</CopyableValue>
|
|
123
97
|
<StorageGroupStateLabel state={state} />
|
|
124
98
|
</Flex>
|
|
125
|
-
{showRefreshInTitle && (
|
|
126
|
-
<AutoRefreshControl className={storageGroupPageCn('refresh-control')} />
|
|
127
|
-
)}
|
|
128
99
|
</Flex>
|
|
129
100
|
);
|
|
130
101
|
};
|
|
@@ -167,8 +138,8 @@ export function StorageGroupPage() {
|
|
|
167
138
|
return (
|
|
168
139
|
<div className={storageGroupPageCn(null)} ref={containerRef}>
|
|
169
140
|
{renderHelmet()}
|
|
141
|
+
{groupId ? <StickyAutoRefreshControl /> : null}
|
|
170
142
|
<div className={storageGroupPageCn('summary')}>
|
|
171
|
-
{renderPageMeta()}
|
|
172
143
|
{renderPageTitle()}
|
|
173
144
|
{renderError()}
|
|
174
145
|
{renderInfo()}
|
|
@@ -2,10 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
.ydb-tablet-page {
|
|
4
4
|
$_: &;
|
|
5
|
+
position: relative;
|
|
6
|
+
|
|
7
|
+
overflow: auto;
|
|
8
|
+
|
|
5
9
|
height: 100%;
|
|
6
|
-
padding: 20px;
|
|
10
|
+
padding: 0 20px 20px;
|
|
7
11
|
@include mixins.body-2-typography();
|
|
8
12
|
|
|
13
|
+
&__content {
|
|
14
|
+
// The sticky refresh wrapper already supplies the initial 20px page inset.
|
|
15
|
+
min-height: calc(100% - 20px);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
&__meta {
|
|
19
|
+
min-height: 28px;
|
|
20
|
+
padding-right: 121px;
|
|
21
|
+
}
|
|
22
|
+
|
|
9
23
|
&__placeholder {
|
|
10
24
|
display: flex;
|
|
11
25
|
flex: 1 1 auto;
|
|
@@ -7,12 +7,13 @@ import {useParams} from 'react-router-dom';
|
|
|
7
7
|
import {useQueryParams} from 'use-query-params';
|
|
8
8
|
import {z} from 'zod';
|
|
9
9
|
|
|
10
|
+
import {StickyAutoRefreshControl} from '../../components/AutoRefreshControl/StickyAutoRefreshControl';
|
|
10
11
|
import {EmptyStateWrapper} from '../../components/EmptyState';
|
|
11
12
|
import {EntityPageTitle} from '../../components/EntityPageTitle/EntityPageTitle';
|
|
12
13
|
import {ResponseError} from '../../components/Errors/ResponseError';
|
|
13
14
|
import {InternalLink} from '../../components/InternalLink';
|
|
14
15
|
import {LoaderWrapper} from '../../components/LoaderWrapper/LoaderWrapper';
|
|
15
|
-
import {
|
|
16
|
+
import {PageMeta} from '../../components/PageMeta/PageMeta';
|
|
16
17
|
import {tabletPageQueryParams, useTabletPagePath} from '../../routes';
|
|
17
18
|
import {useTabletDevUiSecurePath} from '../../store/reducers/capabilities/hooks';
|
|
18
19
|
import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
|
|
@@ -106,25 +107,30 @@ export function Tablet() {
|
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
return (
|
|
109
|
-
<
|
|
110
|
+
<div className={b()}>
|
|
110
111
|
<Helmet>
|
|
111
112
|
<title>{`${id} — ${i18n('tablet.header')} — ${
|
|
112
113
|
databaseFullPath || queryClusterName || CLUSTER_DEFAULT_TITLE
|
|
113
114
|
}`}</title>
|
|
114
115
|
</Helmet>
|
|
115
|
-
<
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
116
|
+
<StickyAutoRefreshControl />
|
|
117
|
+
<Flex gap={5} direction="column" className={b('content')}>
|
|
118
|
+
<Flex alignItems="center" className={b('meta')}>
|
|
119
|
+
<PageMeta items={metaItems} />
|
|
120
|
+
</Flex>
|
|
121
|
+
<LoaderWrapper loading={loading} size="l">
|
|
122
|
+
{error ? <ResponseError error={error} /> : null}
|
|
123
|
+
{currentData ? (
|
|
124
|
+
<TabletContent
|
|
125
|
+
id={id}
|
|
126
|
+
tablet={tablet}
|
|
127
|
+
history={history}
|
|
128
|
+
database={database || databaseFullPath}
|
|
129
|
+
/>
|
|
130
|
+
) : null}
|
|
131
|
+
</LoaderWrapper>
|
|
132
|
+
</Flex>
|
|
133
|
+
</div>
|
|
128
134
|
);
|
|
129
135
|
}
|
|
130
136
|
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
@use '../../styles/mixins.scss';
|
|
2
|
+
|
|
1
3
|
.ydb-vdisk-page {
|
|
4
|
+
--sticky-tabs-height: 40px;
|
|
5
|
+
--data-table-start: var(--sticky-tabs-height);
|
|
2
6
|
--g-definition-list-item-gap: var(--g-spacing-3);
|
|
3
7
|
position: relative;
|
|
4
8
|
|
|
@@ -6,9 +10,8 @@
|
|
|
6
10
|
overflow-anchor: none;
|
|
7
11
|
|
|
8
12
|
height: 100%;
|
|
9
|
-
padding:
|
|
13
|
+
padding: 0 20px;
|
|
10
14
|
|
|
11
|
-
&__meta,
|
|
12
15
|
&__title,
|
|
13
16
|
&__controls,
|
|
14
17
|
&__storage-details,
|
|
@@ -36,8 +39,8 @@
|
|
|
36
39
|
min-width: 0;
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
&
|
|
40
|
-
|
|
42
|
+
&__title {
|
|
43
|
+
padding-right: 125px;
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
&__controls {
|
|
@@ -53,5 +56,21 @@
|
|
|
53
56
|
|
|
54
57
|
&__tablets-content {
|
|
55
58
|
margin-top: var(--g-spacing-4);
|
|
59
|
+
|
|
60
|
+
.data-table__sticky_moving {
|
|
61
|
+
// Override the table's inline sticky offset.
|
|
62
|
+
top: var(--sticky-tabs-height) !important;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
&__tabs {
|
|
67
|
+
z-index: 3;
|
|
68
|
+
|
|
69
|
+
height: var(--sticky-tabs-height);
|
|
70
|
+
margin-bottom: 0;
|
|
71
|
+
padding-right: 125px;
|
|
72
|
+
|
|
73
|
+
@include mixins.sticky-top();
|
|
74
|
+
@include mixins.tabs-wrapper-styles();
|
|
56
75
|
}
|
|
57
76
|
}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import {Wrench} from '@gravity-ui/icons';
|
|
4
|
+
import {Flex, Tab, TabList, TabProvider, Text} from '@gravity-ui/uikit';
|
|
5
5
|
import {skipToken} from '@reduxjs/toolkit/query';
|
|
6
6
|
import {isNil} from 'lodash';
|
|
7
7
|
import {Helmet} from 'react-helmet-async';
|
|
8
|
-
import {useHistory} from 'react-router-dom';
|
|
9
8
|
|
|
10
|
-
import {
|
|
9
|
+
import {StickyAutoRefreshControl} from '../../components/AutoRefreshControl/StickyAutoRefreshControl';
|
|
11
10
|
import {CopyableValue} from '../../components/CopyableValue/CopyableValue';
|
|
12
11
|
import {DiskTypeLabel} from '../../components/DiskStatus/DiskStatus';
|
|
13
12
|
import {ResponseError} from '../../components/Errors/ResponseError';
|
|
@@ -48,8 +47,6 @@ const vDiskPageCn = cn('ydb-vdisk-page');
|
|
|
48
47
|
|
|
49
48
|
export function VDiskPage() {
|
|
50
49
|
const dispatch = useTypedDispatch();
|
|
51
|
-
const history = useHistory();
|
|
52
|
-
const showBackButton = history.length > 1;
|
|
53
50
|
const getVDiskPagePath = useVDiskPagePath();
|
|
54
51
|
|
|
55
52
|
const containerRef = React.useRef<HTMLDivElement>(null);
|
|
@@ -114,27 +111,6 @@ export function VDiskPage() {
|
|
|
114
111
|
);
|
|
115
112
|
};
|
|
116
113
|
|
|
117
|
-
const renderPageMeta = () => {
|
|
118
|
-
if (!showBackButton) {
|
|
119
|
-
return null;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return (
|
|
123
|
-
<Flex
|
|
124
|
-
className={vDiskPageCn('meta')}
|
|
125
|
-
alignItems="center"
|
|
126
|
-
justifyContent="space-between"
|
|
127
|
-
gap={1}
|
|
128
|
-
>
|
|
129
|
-
<Button size="m" view="outlined" onClick={() => history.goBack()}>
|
|
130
|
-
<Icon data={ArrowLeft} size={16} />
|
|
131
|
-
{vDiskPageKeyset('action_back')}
|
|
132
|
-
</Button>
|
|
133
|
-
<AutoRefreshControl className={vDiskPageCn('refresh-control')} />
|
|
134
|
-
</Flex>
|
|
135
|
-
);
|
|
136
|
-
};
|
|
137
|
-
|
|
138
114
|
const renderTitleMeta = () => {
|
|
139
115
|
return (
|
|
140
116
|
<Flex gap={2} wrap="wrap" alignItems="center">
|
|
@@ -182,9 +158,6 @@ export function VDiskPage() {
|
|
|
182
158
|
</CopyableValue>
|
|
183
159
|
</Flex>
|
|
184
160
|
</Flex>
|
|
185
|
-
{!showBackButton && (
|
|
186
|
-
<AutoRefreshControl className={vDiskPageCn('refresh-control')} />
|
|
187
|
-
)}
|
|
188
161
|
</Flex>
|
|
189
162
|
);
|
|
190
163
|
};
|
|
@@ -334,7 +307,7 @@ export function VDiskPage() {
|
|
|
334
307
|
return (
|
|
335
308
|
<div className={vDiskPageCn(null)} ref={containerRef}>
|
|
336
309
|
{renderHelmet()}
|
|
337
|
-
|
|
310
|
+
<StickyAutoRefreshControl />
|
|
338
311
|
{renderPageTitle()}
|
|
339
312
|
{renderControls()}
|
|
340
313
|
{renderContent()}
|
|
@@ -106,6 +106,10 @@ export const useStorageGroupsHandlerHasGrouping = () => {
|
|
|
106
106
|
return useGetFeatureVersion('/storage/groups') > 4;
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
+
export const useViewerNodesAliveFilterAvailable = () => {
|
|
110
|
+
return useGetFeatureVersion('/viewer/nodes/alive') >= 1;
|
|
111
|
+
};
|
|
112
|
+
|
|
109
113
|
export const useViewerNodesHandlerHasGrouping = () => {
|
|
110
114
|
return useGetFeatureVersion('/viewer/nodes') > 6;
|
|
111
115
|
};
|
package/src/types/api/nodes.ts
CHANGED
|
@@ -363,6 +363,8 @@ export interface NodesRequestParams {
|
|
|
363
363
|
uptime?: number;
|
|
364
364
|
/** return nodes with SystemState !== EFlag.Green */
|
|
365
365
|
problems_only?: boolean;
|
|
366
|
+
/** exclude disconnected nodes; requires /viewer/nodes/alive capability */
|
|
367
|
+
alive?: boolean;
|
|
366
368
|
/** filter nodes by id or host */
|
|
367
369
|
filter?: string;
|
|
368
370
|
filter_peer_role?: NodesPeerRole; // v14
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {BooleanParam, useQueryParam} from 'use-query-params';
|
|
4
|
+
import {z} from 'zod';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
useCapabilitiesLoaded,
|
|
8
|
+
useViewerNodesAliveFilterAvailable,
|
|
9
|
+
} from '../../store/reducers/capabilities/hooks';
|
|
10
|
+
|
|
11
|
+
const hideUnavailableSchema = z.boolean().catch(false);
|
|
12
|
+
|
|
13
|
+
export function useHideUnavailableNodes() {
|
|
14
|
+
const [value, setValue] = useQueryParam('hideUnavailable', BooleanParam);
|
|
15
|
+
const available = useViewerNodesAliveFilterAvailable();
|
|
16
|
+
const capabilitiesLoaded = useCapabilitiesLoaded();
|
|
17
|
+
const hideUnavailable = available && hideUnavailableSchema.parse(value);
|
|
18
|
+
|
|
19
|
+
React.useEffect(() => {
|
|
20
|
+
if (capabilitiesLoaded && !available && value !== undefined) {
|
|
21
|
+
setValue(undefined, 'replaceIn');
|
|
22
|
+
}
|
|
23
|
+
}, [available, capabilitiesLoaded, setValue, value]);
|
|
24
|
+
|
|
25
|
+
const handleHideUnavailableChange = React.useCallback(
|
|
26
|
+
(checked: boolean) => {
|
|
27
|
+
setValue(checked || undefined, 'replaceIn');
|
|
28
|
+
},
|
|
29
|
+
[setValue],
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
return {available, hideUnavailable, handleHideUnavailableChange};
|
|
33
|
+
}
|