ydb-embedded-ui 4.13.0 → 4.15.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/CHANGELOG.md +25 -0
- package/dist/components/Tablet/Tablet.scss +1 -16
- package/dist/components/Tablet/Tablet.tsx +5 -5
- package/dist/components/TabletIcon/TabletIcon.scss +17 -0
- package/dist/components/TabletIcon/TabletIcon.tsx +18 -0
- package/dist/containers/App/App.js +1 -1
- package/dist/containers/AsideNavigation/AsideNavigation.tsx +1 -1
- package/dist/containers/Authentication/Authentication.tsx +1 -1
- package/dist/containers/Header/Header.scss +2 -0
- package/dist/containers/Header/Header.tsx +2 -7
- package/dist/containers/Header/{breadcrumbs.ts → breadcrumbs.tsx} +19 -8
- package/dist/containers/Nodes/Nodes.tsx +53 -16
- package/dist/containers/Nodes/getNodesColumns.tsx +31 -13
- package/dist/containers/Storage/Storage.tsx +64 -32
- package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +56 -73
- package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +33 -43
- package/dist/containers/Storage/utils/index.ts +3 -3
- package/dist/containers/Tablet/Tablet.tsx +9 -3
- package/dist/containers/Tenant/Query/QueryDuration/QueryDuration.scss +8 -0
- package/dist/containers/Tenant/Query/QueryDuration/QueryDuration.tsx +13 -1
- package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.scss +3 -1
- package/dist/containers/Tenant/Query/i18n/en.json +6 -4
- package/dist/containers/Tenant/Query/i18n/ru.json +6 -4
- package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +4 -0
- package/dist/containers/Tenant/i18n/en.json +3 -0
- package/dist/containers/Tenant/i18n/ru.json +3 -0
- package/dist/containers/Tenant/utils/queryTemplates.ts +89 -0
- package/dist/containers/Tenant/utils/schema.ts +1 -1
- package/dist/containers/Tenant/utils/schemaActions.ts +30 -54
- package/dist/containers/Tenant/utils/schemaControls.tsx +69 -0
- package/dist/containers/UserSettings/i18n/en.json +3 -0
- package/dist/containers/UserSettings/i18n/ru.json +3 -0
- package/dist/containers/UserSettings/settings.ts +12 -1
- package/dist/{reportWebVitals.js → reportWebVitals.ts} +3 -1
- package/dist/services/api.ts +30 -16
- package/dist/store/reducers/{authentication.js → authentication/authentication.ts} +14 -7
- package/dist/store/reducers/authentication/types.ts +15 -0
- package/dist/store/reducers/describe.ts +1 -16
- package/dist/store/reducers/header/types.ts +2 -0
- package/dist/store/reducers/index.ts +1 -1
- package/dist/store/reducers/nodes/nodes.ts +23 -6
- package/dist/store/reducers/nodes/selectors.ts +2 -2
- package/dist/store/reducers/nodes/types.ts +15 -5
- package/dist/store/reducers/settings/settings.ts +5 -0
- package/dist/store/reducers/storage/selectors.ts +50 -150
- package/dist/store/reducers/storage/storage.ts +73 -25
- package/dist/store/reducers/storage/types.ts +49 -17
- package/dist/store/reducers/storage/utils.ts +207 -0
- package/dist/store/utils.ts +1 -1
- package/dist/types/api/compute.ts +0 -12
- package/dist/types/api/error.ts +4 -0
- package/dist/types/api/nodes.ts +0 -12
- package/dist/types/api/storage.ts +32 -4
- package/dist/types/window.d.ts +1 -0
- package/dist/utils/constants.ts +3 -0
- package/dist/utils/filters.ts +23 -0
- package/dist/utils/hooks/index.ts +4 -0
- package/dist/utils/hooks/useNodesRequestParams.ts +46 -0
- package/dist/utils/hooks/useStorageRequestParams.ts +28 -0
- package/dist/utils/hooks/useTableSort.ts +37 -0
- package/dist/utils/nodes.ts +25 -0
- package/dist/utils/storage.ts +31 -3
- package/package.json +2 -6
- package/dist/HOCS/WithSearch/WithSearch.js +0 -26
- package/dist/HOCS/index.js +0 -1
- package/dist/components/Hotkey/Hotkey.js +0 -102
- package/dist/components/Pagination/Pagination.js +0 -63
- package/dist/components/Pagination/Pagination.scss +0 -28
- package/dist/types/store/storage.ts +0 -12
- /package/dist/{index.js → index.tsx} +0 -0
- /package/dist/utils/{monaco.js → monaco.ts} +0 -0
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,30 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [4.15.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.14.0...v4.15.0) (2023-08-17)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* **SchemaTree:** add actions for topic ([#507](https://github.com/ydb-platform/ydb-embedded-ui/issues/507)) ([6700136](https://github.com/ydb-platform/ydb-embedded-ui/commit/670013629cb68425e670969323a2ef466ef7c018))
|
9
|
+
* **Storage:** sort on backend ([#510](https://github.com/ydb-platform/ydb-embedded-ui/issues/510)) ([034a89a](https://github.com/ydb-platform/ydb-embedded-ui/commit/034a89a9844021c5ea3a73c8f6456e35128078c0))
|
10
|
+
* **Storage:** v2 api and backend filters ([#506](https://github.com/ydb-platform/ydb-embedded-ui/issues/506)) ([ce4bf6d](https://github.com/ydb-platform/ydb-embedded-ui/commit/ce4bf6d0ef154b87a7b3a44d56281230b2b5b554))
|
11
|
+
|
12
|
+
## [4.14.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.13.0...v4.14.0) (2023-08-11)
|
13
|
+
|
14
|
+
|
15
|
+
### Features
|
16
|
+
|
17
|
+
* **Nodes:** filter and sort on backend ([#503](https://github.com/ydb-platform/ydb-embedded-ui/issues/503)) ([2e8ab8e](https://github.com/ydb-platform/ydb-embedded-ui/commit/2e8ab8e9965db61ec281f7340b89dd3967b639df))
|
18
|
+
* **Query:** add explanation to query duration ([#501](https://github.com/ydb-platform/ydb-embedded-ui/issues/501)) ([a5f5140](https://github.com/ydb-platform/ydb-embedded-ui/commit/a5f5140a23864147d8495e3c6b94709e5e710a9b))
|
19
|
+
|
20
|
+
|
21
|
+
### Bug Fixes
|
22
|
+
|
23
|
+
* **Header:** add icons for nodes and tablets ([#500](https://github.com/ydb-platform/ydb-embedded-ui/issues/500)) ([862660c](https://github.com/ydb-platform/ydb-embedded-ui/commit/862660c1928c2c2b626e4417cd043f0bd5a65df9))
|
24
|
+
* **Query:** fix query method selector help text ([#504](https://github.com/ydb-platform/ydb-embedded-ui/issues/504)) ([65cdf9e](https://github.com/ydb-platform/ydb-embedded-ui/commit/65cdf9ee93277c193cc1ad036b2cb38d2ae15b71))
|
25
|
+
* **Query:** transfer API calls to a new line ([#499](https://github.com/ydb-platform/ydb-embedded-ui/issues/499)) ([de3d540](https://github.com/ydb-platform/ydb-embedded-ui/commit/de3d5404310f32ba05598bb99a1afb1b65ab45a1))
|
26
|
+
* **SchemaTree:** transfer Show Preview to SchemaTree ([#505](https://github.com/ydb-platform/ydb-embedded-ui/issues/505)) ([46220c4](https://github.com/ydb-platform/ydb-embedded-ui/commit/46220c4b2cd111acf12712b4693744c52aaf7231))
|
27
|
+
|
3
28
|
## [4.13.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.12.0...v4.13.0) (2023-08-04)
|
4
29
|
|
5
30
|
|
@@ -1,17 +1,8 @@
|
|
1
1
|
.tablet {
|
2
|
-
display: flex;
|
3
|
-
justify-content: center;
|
4
|
-
|
5
|
-
width: 23px;
|
6
|
-
height: 18px;
|
7
|
-
|
8
|
-
font-size: 10px;
|
9
2
|
cursor: pointer;
|
10
|
-
text-transform: uppercase;
|
11
3
|
|
12
4
|
color: var(--yc-color-text-complementary);
|
13
|
-
border:
|
14
|
-
border-radius: 4px;
|
5
|
+
border-color: var(--yc-color-base-generic-medium-hover);
|
15
6
|
|
16
7
|
&__wrapper {
|
17
8
|
margin-right: 2px;
|
@@ -25,12 +16,6 @@
|
|
25
16
|
padding: 10px;
|
26
17
|
}
|
27
18
|
|
28
|
-
&__type {
|
29
|
-
line-height: 17px;
|
30
|
-
|
31
|
-
color: var(--yc-color-text-complementary);
|
32
|
-
}
|
33
|
-
|
34
19
|
&_status_gray {
|
35
20
|
background-color: var(--yc-color-text-complementary);
|
36
21
|
}
|
@@ -5,6 +5,7 @@ import {getTabletLabel} from '../../utils/constants';
|
|
5
5
|
import routes, {createHref} from '../../routes';
|
6
6
|
|
7
7
|
import {ContentWithPopup} from '../ContentWithPopup/ContentWithPopup';
|
8
|
+
import {TabletIcon} from '../TabletIcon/TabletIcon';
|
8
9
|
import {InternalLink} from '../InternalLink';
|
9
10
|
import {TabletTooltipContent} from '../TooltipsContent';
|
10
11
|
|
@@ -18,10 +19,11 @@ interface TabletProps {
|
|
18
19
|
}
|
19
20
|
|
20
21
|
export const Tablet = ({tablet = {}, tenantName}: TabletProps) => {
|
21
|
-
const {TabletId: id, NodeId} = tablet;
|
22
|
+
const {TabletId: id, NodeId, Type} = tablet;
|
22
23
|
const status = tablet.Overall?.toLowerCase();
|
23
24
|
|
24
|
-
const tabletPath =
|
25
|
+
const tabletPath =
|
26
|
+
id && createHref(routes.tablet, {id}, {nodeId: NodeId, tenantName, type: Type});
|
25
27
|
|
26
28
|
return (
|
27
29
|
<ContentWithPopup
|
@@ -29,9 +31,7 @@ export const Tablet = ({tablet = {}, tenantName}: TabletProps) => {
|
|
29
31
|
content={<TabletTooltipContent data={tablet} className={b('popup-content')} />}
|
30
32
|
>
|
31
33
|
<InternalLink to={tabletPath}>
|
32
|
-
<
|
33
|
-
<div className={b('type')}>{[getTabletLabel(tablet.Type)]}</div>
|
34
|
-
</div>
|
34
|
+
<TabletIcon className={b({status})} text={getTabletLabel(tablet.Type)} />
|
35
35
|
</InternalLink>
|
36
36
|
</ContentWithPopup>
|
37
37
|
);
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import cn from 'bem-cn-lite';
|
2
|
+
|
3
|
+
import './TabletIcon.scss';
|
4
|
+
|
5
|
+
interface TabletIconProps {
|
6
|
+
text?: string;
|
7
|
+
className?: string;
|
8
|
+
}
|
9
|
+
|
10
|
+
const b = cn('tablet-icon');
|
11
|
+
|
12
|
+
export const TabletIcon = ({text, className}: TabletIconProps) => {
|
13
|
+
return (
|
14
|
+
<div className={b(null, className)}>
|
15
|
+
<div className={b('type')}>{text || 'T'}</div>
|
16
|
+
</div>
|
17
|
+
);
|
18
|
+
};
|
@@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
|
|
5
5
|
import ContentWrapper, {Content} from './Content';
|
6
6
|
import AsideNavigation from '../AsideNavigation/AsideNavigation';
|
7
7
|
|
8
|
-
import {getUser} from '../../store/reducers/authentication';
|
8
|
+
import {getUser} from '../../store/reducers/authentication/authentication';
|
9
9
|
import {registerLanguages} from '../../utils/monaco';
|
10
10
|
|
11
11
|
import './App.scss';
|
@@ -18,7 +18,7 @@ import userChecked from '../../assets/icons/user-check.svg';
|
|
18
18
|
import settingsIcon from '../../assets/icons/settings.svg';
|
19
19
|
import supportIcon from '../../assets/icons/support.svg';
|
20
20
|
|
21
|
-
import {logout} from '../../store/reducers/authentication';
|
21
|
+
import {logout} from '../../store/reducers/authentication/authentication';
|
22
22
|
import {getParsedSettingValue, setSettingValue} from '../../store/reducers/settings/settings';
|
23
23
|
import {TENANT_PAGE, TENANT_PAGES_IDS} from '../../store/reducers/tenant/constants';
|
24
24
|
import routes, {TENANT, createHref, parseQuery} from '../../routes';
|
@@ -5,7 +5,7 @@ import cn from 'bem-cn-lite';
|
|
5
5
|
|
6
6
|
import {Button, TextInput, Icon, Link as ExternalLink} from '@gravity-ui/uikit';
|
7
7
|
|
8
|
-
import {authenticate} from '../../store/reducers/authentication';
|
8
|
+
import {authenticate} from '../../store/reducers/authentication/authentication';
|
9
9
|
import {useTypedSelector} from '../../utils/hooks';
|
10
10
|
|
11
11
|
import ydbLogoIcon from '../../assets/icons/ydb.svg';
|
@@ -3,7 +3,7 @@ import {useHistory, useLocation} from 'react-router';
|
|
3
3
|
import {useDispatch} from 'react-redux';
|
4
4
|
import block from 'bem-cn-lite';
|
5
5
|
|
6
|
-
import {Breadcrumbs
|
6
|
+
import {Breadcrumbs} from '@gravity-ui/uikit';
|
7
7
|
|
8
8
|
import {ExternalLinkWithIcon} from '../../components/ExternalLinkWithIcon/ExternalLinkWithIcon';
|
9
9
|
|
@@ -91,12 +91,7 @@ function Header({mainPage}: HeaderProps) {
|
|
91
91
|
}
|
92
92
|
return (
|
93
93
|
<span className={b('breadcrumb')}>
|
94
|
-
<
|
95
|
-
width={16}
|
96
|
-
height={16}
|
97
|
-
data={icon}
|
98
|
-
className={b('breadcrumb__icon')}
|
99
|
-
/>
|
94
|
+
<div className={b('breadcrumb__icon')}>{icon}</div>
|
100
95
|
{text}
|
101
96
|
</span>
|
102
97
|
);
|
@@ -1,5 +1,9 @@
|
|
1
|
-
import
|
2
|
-
|
1
|
+
import {
|
2
|
+
NodesRight as ClusterIcon,
|
3
|
+
Database as DatabaseIcon,
|
4
|
+
Cpu as ComputeNodeIcon,
|
5
|
+
HardDrive as StorageNodeIcon,
|
6
|
+
} from '@gravity-ui/icons';
|
3
7
|
|
4
8
|
import type {
|
5
9
|
BreadcrumbsOptions,
|
@@ -15,8 +19,9 @@ import {
|
|
15
19
|
TENANT_PAGE,
|
16
20
|
TENANT_PAGES_IDS,
|
17
21
|
} from '../../store/reducers/tenant/constants';
|
22
|
+
import {TabletIcon} from '../../components/TabletIcon/TabletIcon';
|
18
23
|
import routes, {createHref} from '../../routes';
|
19
|
-
import {CLUSTER_DEFAULT_TITLE} from '../../utils/constants';
|
24
|
+
import {CLUSTER_DEFAULT_TITLE, getTabletLabel} from '../../utils/constants';
|
20
25
|
|
21
26
|
import {getClusterPath} from '../Cluster/utils';
|
22
27
|
import {TenantTabsGroups, getTenantPath} from '../Tenant/TenantPages';
|
@@ -29,7 +34,7 @@ const prepareTenantName = (tenantName: string) => {
|
|
29
34
|
export interface RawBreadcrumbItem {
|
30
35
|
text: string;
|
31
36
|
link?: string;
|
32
|
-
icon?:
|
37
|
+
icon?: JSX.Element;
|
33
38
|
}
|
34
39
|
|
35
40
|
const getClusterBreadcrumbs = (
|
@@ -42,7 +47,7 @@ const getClusterBreadcrumbs = (
|
|
42
47
|
{
|
43
48
|
text: clusterName || CLUSTER_DEFAULT_TITLE,
|
44
49
|
link: getClusterPath(clusterTab, query),
|
45
|
-
icon:
|
50
|
+
icon: <ClusterIcon />,
|
46
51
|
},
|
47
52
|
];
|
48
53
|
};
|
@@ -56,7 +61,7 @@ const getTenantBreadcrumbs = (
|
|
56
61
|
const text = tenantName ? prepareTenantName(tenantName) : 'Tenant';
|
57
62
|
const link = tenantName ? getTenantPath({...query, name: tenantName}) : undefined;
|
58
63
|
|
59
|
-
return [...getClusterBreadcrumbs(options, query), {text, link, icon:
|
64
|
+
return [...getClusterBreadcrumbs(options, query), {text, link, icon: <DatabaseIcon />}];
|
60
65
|
};
|
61
66
|
|
62
67
|
const getNodeBreadcrumbs = (options: NodeBreadcrumbsOptions, query = {}): RawBreadcrumbItem[] => {
|
@@ -81,8 +86,13 @@ const getNodeBreadcrumbs = (options: NodeBreadcrumbsOptions, query = {}): RawBre
|
|
81
86
|
|
82
87
|
const text = nodeId ? `Node ${nodeId}` : 'Node';
|
83
88
|
const link = nodeId ? getDefaultNodePath(nodeId, query) : undefined;
|
89
|
+
const icon = isStorageNode ? <StorageNodeIcon /> : <ComputeNodeIcon />;
|
84
90
|
|
85
|
-
breadcrumbs.push({
|
91
|
+
breadcrumbs.push({
|
92
|
+
text,
|
93
|
+
link,
|
94
|
+
icon,
|
95
|
+
});
|
86
96
|
|
87
97
|
return breadcrumbs;
|
88
98
|
};
|
@@ -123,12 +133,13 @@ const getTabletBreadcrubms = (
|
|
123
133
|
options: TabletBreadcrumbsOptions,
|
124
134
|
query = {},
|
125
135
|
): RawBreadcrumbItem[] => {
|
126
|
-
const {tabletId} = options;
|
136
|
+
const {tabletId, tabletType} = options;
|
127
137
|
|
128
138
|
const breadcrumbs = getTabletsBreadcrubms(options, query);
|
129
139
|
|
130
140
|
breadcrumbs.push({
|
131
141
|
text: tabletId || 'Tablet',
|
142
|
+
icon: <TabletIcon text={getTabletLabel(tabletType)} />,
|
132
143
|
});
|
133
144
|
|
134
145
|
return breadcrumbs;
|
@@ -3,9 +3,11 @@ import cn from 'bem-cn-lite';
|
|
3
3
|
import {useDispatch} from 'react-redux';
|
4
4
|
|
5
5
|
import DataTable from '@gravity-ui/react-data-table';
|
6
|
+
import {ASCENDING} from '@gravity-ui/react-data-table/build/esm/lib/constants';
|
6
7
|
|
7
8
|
import type {EPathType} from '../../types/api/schema';
|
8
9
|
import type {ProblemFilterValue} from '../../store/reducers/settings/types';
|
10
|
+
import type {NodesSortParams} from '../../store/reducers/nodes/types';
|
9
11
|
|
10
12
|
import {AccessDenied} from '../../components/Errors/403';
|
11
13
|
import {Illustration} from '../../components/Illustration';
|
@@ -17,7 +19,13 @@ import {TableWithControlsLayout} from '../../components/TableWithControlsLayout/
|
|
17
19
|
import {ResponseError} from '../../components/Errors/ResponseError';
|
18
20
|
|
19
21
|
import {DEFAULT_TABLE_SETTINGS, USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY} from '../../utils/constants';
|
20
|
-
import {
|
22
|
+
import {
|
23
|
+
useAutofetcher,
|
24
|
+
useSetting,
|
25
|
+
useTypedSelector,
|
26
|
+
useNodesRequestParams,
|
27
|
+
useTableSort,
|
28
|
+
} from '../../utils/hooks';
|
21
29
|
import {AdditionalNodesInfo, isUnavailableNode, NodesUptimeFilterValues} from '../../utils/nodes';
|
22
30
|
|
23
31
|
import {
|
@@ -26,6 +34,8 @@ import {
|
|
26
34
|
setSearchValue,
|
27
35
|
resetNodesState,
|
28
36
|
getComputeNodes,
|
37
|
+
setDataWasNotLoaded,
|
38
|
+
setSort,
|
29
39
|
} from '../../store/reducers/nodes/nodes';
|
30
40
|
import {selectFilteredNodes} from '../../store/reducers/nodes/selectors';
|
31
41
|
import {changeFilter, ProblemFilterValues} from '../../store/reducers/settings/settings';
|
@@ -58,8 +68,16 @@ export const Nodes = ({path, type, additionalNodesInfo = {}}: NodesProps) => {
|
|
58
68
|
dispatch(resetNodesState());
|
59
69
|
}, [dispatch, path]);
|
60
70
|
|
61
|
-
const {
|
62
|
-
|
71
|
+
const {
|
72
|
+
wasLoaded,
|
73
|
+
loading,
|
74
|
+
error,
|
75
|
+
nodesUptimeFilter,
|
76
|
+
searchValue,
|
77
|
+
sortOrder = ASCENDING,
|
78
|
+
sortValue = 'NodeId',
|
79
|
+
totalNodes,
|
80
|
+
} = useTypedSelector((state) => state.nodes);
|
63
81
|
const problemFilter = useTypedSelector((state) => state.settings.problemFilter);
|
64
82
|
const {autorefresh} = useTypedSelector((state) => state.schema);
|
65
83
|
|
@@ -67,18 +85,39 @@ export const Nodes = ({path, type, additionalNodesInfo = {}}: NodesProps) => {
|
|
67
85
|
|
68
86
|
const [useNodesEndpoint] = useSetting(USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY);
|
69
87
|
|
70
|
-
const
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
88
|
+
const requestParams = useNodesRequestParams({
|
89
|
+
filter: searchValue,
|
90
|
+
problemFilter,
|
91
|
+
nodesUptimeFilter,
|
92
|
+
sortOrder,
|
93
|
+
sortValue,
|
94
|
+
});
|
95
|
+
|
96
|
+
const fetchNodes = useCallback(
|
97
|
+
(isBackground) => {
|
98
|
+
if (!isBackground) {
|
99
|
+
dispatch(setDataWasNotLoaded());
|
100
|
+
}
|
101
|
+
|
102
|
+
const params = requestParams || {};
|
103
|
+
|
104
|
+
// For not DB entities we always use /compute endpoint instead of /nodes
|
105
|
+
// since /nodes can return data only for tenants
|
106
|
+
if (path && (!useNodesEndpoint || !isDatabaseEntityType(type))) {
|
107
|
+
dispatch(getComputeNodes({path, ...params}));
|
108
|
+
} else {
|
109
|
+
dispatch(getNodes({tenant: path, ...params}));
|
110
|
+
}
|
111
|
+
},
|
112
|
+
[dispatch, path, type, useNodesEndpoint, requestParams],
|
113
|
+
);
|
79
114
|
|
80
115
|
useAutofetcher(fetchNodes, [fetchNodes], isClusterNodes ? true : autorefresh);
|
81
116
|
|
117
|
+
const [sort, handleSort] = useTableSort({sortValue, sortOrder}, (sortParams) =>
|
118
|
+
dispatch(setSort(sortParams as NodesSortParams)),
|
119
|
+
);
|
120
|
+
|
82
121
|
const handleSearchQueryChange = (value: string) => {
|
83
122
|
dispatch(setSearchValue(value));
|
84
123
|
};
|
@@ -132,10 +171,8 @@ export const Nodes = ({path, type, additionalNodesInfo = {}}: NodesProps) => {
|
|
132
171
|
data={nodes || []}
|
133
172
|
columns={columns}
|
134
173
|
settings={DEFAULT_TABLE_SETTINGS}
|
135
|
-
|
136
|
-
|
137
|
-
order: DataTable.ASCENDING,
|
138
|
-
}}
|
174
|
+
sortOrder={sort}
|
175
|
+
onSort={handleSort}
|
139
176
|
emptyDataMessage={i18n('empty.default')}
|
140
177
|
rowClassName={(row) => b('node', {unavailable: isUnavailableNode(row)})}
|
141
178
|
/>
|
@@ -6,26 +6,42 @@ import ProgressViewer from '../../components/ProgressViewer/ProgressViewer';
|
|
6
6
|
import {TabletsStatistic} from '../../components/TabletsStatistic';
|
7
7
|
import {NodeHostWrapper} from '../../components/NodeHostWrapper/NodeHostWrapper';
|
8
8
|
|
9
|
-
import type
|
9
|
+
import {isSortableNodesProperty, type NodeAddress} from '../../utils/nodes';
|
10
10
|
import {formatBytesToGigabyte} from '../../utils/index';
|
11
11
|
|
12
12
|
import type {NodesPreparedEntity} from '../../store/reducers/nodes/types';
|
13
13
|
|
14
|
+
const NODES_COLUMNS_IDS = {
|
15
|
+
NodeId: 'NodeId',
|
16
|
+
Host: 'Host',
|
17
|
+
DC: 'DC',
|
18
|
+
Rack: 'Rack',
|
19
|
+
Version: 'Version',
|
20
|
+
Uptime: 'Uptime',
|
21
|
+
Memory: 'Memory',
|
22
|
+
CPU: 'CPU',
|
23
|
+
LoadAverage: 'LoadAverage',
|
24
|
+
Tablets: 'Tablets',
|
25
|
+
};
|
26
|
+
|
14
27
|
interface GetNodesColumnsProps {
|
15
28
|
tabletsPath?: string;
|
16
29
|
getNodeRef?: (node?: NodeAddress) => string | null;
|
17
30
|
}
|
18
31
|
|
19
|
-
export function getNodesColumns({
|
32
|
+
export function getNodesColumns({
|
33
|
+
tabletsPath,
|
34
|
+
getNodeRef,
|
35
|
+
}: GetNodesColumnsProps): Column<NodesPreparedEntity>[] {
|
20
36
|
const columns: Column<NodesPreparedEntity>[] = [
|
21
37
|
{
|
22
|
-
name:
|
38
|
+
name: NODES_COLUMNS_IDS.NodeId,
|
23
39
|
header: '#',
|
24
40
|
width: '80px',
|
25
41
|
align: DataTable.RIGHT,
|
26
42
|
},
|
27
43
|
{
|
28
|
-
name:
|
44
|
+
name: NODES_COLUMNS_IDS.Host,
|
29
45
|
render: ({row}) => {
|
30
46
|
return <NodeHostWrapper node={row} getNodeRef={getNodeRef} />;
|
31
47
|
},
|
@@ -33,21 +49,21 @@ export function getNodesColumns({tabletsPath, getNodeRef}: GetNodesColumnsProps)
|
|
33
49
|
align: DataTable.LEFT,
|
34
50
|
},
|
35
51
|
{
|
36
|
-
name:
|
52
|
+
name: NODES_COLUMNS_IDS.DC,
|
37
53
|
header: 'DC',
|
38
54
|
align: DataTable.LEFT,
|
39
55
|
render: ({row}) => (row.DataCenter ? row.DataCenter : '—'),
|
40
56
|
width: '60px',
|
41
57
|
},
|
42
58
|
{
|
43
|
-
name:
|
59
|
+
name: NODES_COLUMNS_IDS.Rack,
|
44
60
|
header: 'Rack',
|
45
61
|
align: DataTable.LEFT,
|
46
62
|
render: ({row}) => (row.Rack ? row.Rack : '—'),
|
47
63
|
width: '80px',
|
48
64
|
},
|
49
65
|
{
|
50
|
-
name:
|
66
|
+
name: NODES_COLUMNS_IDS.Version,
|
51
67
|
width: '200px',
|
52
68
|
align: DataTable.LEFT,
|
53
69
|
render: ({row}) => {
|
@@ -55,14 +71,14 @@ export function getNodesColumns({tabletsPath, getNodeRef}: GetNodesColumnsProps)
|
|
55
71
|
},
|
56
72
|
},
|
57
73
|
{
|
58
|
-
name:
|
74
|
+
name: NODES_COLUMNS_IDS.Uptime,
|
59
75
|
header: 'Uptime',
|
60
76
|
sortAccessor: ({StartTime}) => StartTime && -StartTime,
|
61
77
|
align: DataTable.RIGHT,
|
62
78
|
width: '110px',
|
63
79
|
},
|
64
80
|
{
|
65
|
-
name:
|
81
|
+
name: NODES_COLUMNS_IDS.Memory,
|
66
82
|
header: 'Memory',
|
67
83
|
sortAccessor: ({MemoryUsed = 0}) => Number(MemoryUsed),
|
68
84
|
defaultOrder: DataTable.DESCENDING,
|
@@ -77,7 +93,7 @@ export function getNodesColumns({tabletsPath, getNodeRef}: GetNodesColumnsProps)
|
|
77
93
|
width: '120px',
|
78
94
|
},
|
79
95
|
{
|
80
|
-
name:
|
96
|
+
name: NODES_COLUMNS_IDS.CPU,
|
81
97
|
header: 'CPU',
|
82
98
|
sortAccessor: ({PoolStats = []}) =>
|
83
99
|
PoolStats.reduce((acc, item) => {
|
@@ -93,7 +109,7 @@ export function getNodesColumns({tabletsPath, getNodeRef}: GetNodesColumnsProps)
|
|
93
109
|
width: '120px',
|
94
110
|
},
|
95
111
|
{
|
96
|
-
name:
|
112
|
+
name: NODES_COLUMNS_IDS.LoadAverage,
|
97
113
|
header: 'Load average',
|
98
114
|
sortAccessor: ({LoadAverage = []}) =>
|
99
115
|
LoadAverage.slice(0, 1).reduce((acc, item) => acc + item, 0),
|
@@ -112,7 +128,7 @@ export function getNodesColumns({tabletsPath, getNodeRef}: GetNodesColumnsProps)
|
|
112
128
|
width: '140px',
|
113
129
|
},
|
114
130
|
{
|
115
|
-
name:
|
131
|
+
name: NODES_COLUMNS_IDS.Tablets,
|
116
132
|
width: '430px',
|
117
133
|
render: ({row}) => {
|
118
134
|
return row.Tablets ? (
|
@@ -129,5 +145,7 @@ export function getNodesColumns({tabletsPath, getNodeRef}: GetNodesColumnsProps)
|
|
129
145
|
},
|
130
146
|
];
|
131
147
|
|
132
|
-
return columns
|
148
|
+
return columns.map((column) => {
|
149
|
+
return {...column, sortable: isSortableNodesProperty(column.name)};
|
150
|
+
});
|
133
151
|
}
|