ydb-embedded-ui 4.12.0 → 4.14.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +29 -0
- package/dist/components/InfoViewer/formatters/common.ts +4 -2
- package/dist/components/InfoViewer/i18n/en.json +4 -0
- package/dist/components/InfoViewer/i18n/index.ts +11 -0
- package/dist/components/InfoViewer/i18n/ru.json +4 -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/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/Tablet/Tablet.tsx +9 -3
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +5 -2
- package/dist/containers/Tenant/Info/ExternalDataSource/ExternalDataSource.scss +5 -0
- package/dist/containers/Tenant/Info/ExternalDataSource/ExternalDataSource.tsx +81 -0
- package/dist/containers/Tenant/Info/ExternalTable/ExternalTable.scss +5 -0
- package/dist/containers/Tenant/Info/ExternalTable/ExternalTable.tsx +103 -0
- package/dist/containers/Tenant/Info/i18n/en.json +8 -0
- package/dist/containers/Tenant/Info/i18n/index.ts +11 -0
- package/dist/containers/Tenant/Info/i18n/ru.json +8 -0
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.scss +4 -4
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +10 -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/QueryEditor/QueryEditor.js +4 -6
- 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 +12 -2
- package/dist/containers/Tenant/i18n/en.json +12 -2
- package/dist/containers/Tenant/i18n/ru.json +11 -1
- package/dist/containers/Tenant/utils/schemaActions.ts +76 -28
- 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/index.js +7 -3
- package/dist/services/api.ts +24 -12
- package/dist/store/reducers/header/types.ts +2 -0
- 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/styles/constants.scss +3 -0
- package/dist/types/api/compute.ts +0 -12
- package/dist/types/api/nodes.ts +0 -12
- package/dist/utils/constants.ts +3 -0
- package/dist/utils/filters.ts +23 -0
- package/dist/utils/hooks/i18n/en.json +3 -0
- package/dist/utils/hooks/i18n/index.ts +11 -0
- package/dist/utils/hooks/i18n/ru.json +3 -0
- package/dist/utils/hooks/index.ts +4 -0
- package/dist/utils/hooks/useNodesRequestParams.ts +46 -0
- package/dist/utils/hooks/useQueryModes.ts +34 -0
- package/dist/utils/hooks/useTableSort.ts +37 -0
- package/dist/utils/nodes.ts +25 -0
- package/dist/utils/query.ts +5 -1
- package/package.json +2 -2
@@ -0,0 +1,69 @@
|
|
1
|
+
import {Dispatch} from 'react';
|
2
|
+
|
3
|
+
import {NavigationTreeNodeType, NavigationTreeProps} from 'ydb-ui-components';
|
4
|
+
import {Button} from '@gravity-ui/uikit';
|
5
|
+
|
6
|
+
import {setShowPreview} from '../../../store/reducers/schema/schema';
|
7
|
+
import {setQueryTab, setTenantPage} from '../../../store/reducers/tenant/tenant';
|
8
|
+
import {TENANT_PAGES_IDS, TENANT_QUERY_TABS_ID} from '../../../store/reducers/tenant/constants';
|
9
|
+
import {IconWrapper} from '../../../components/Icon';
|
10
|
+
|
11
|
+
import i18n from '../i18n';
|
12
|
+
|
13
|
+
interface ControlsAdditionalEffects {
|
14
|
+
setActivePath: (path: string) => void;
|
15
|
+
}
|
16
|
+
|
17
|
+
const bindActions = (
|
18
|
+
path: string,
|
19
|
+
dispatch: Dispatch<any>,
|
20
|
+
additionalEffects: ControlsAdditionalEffects,
|
21
|
+
) => {
|
22
|
+
const {setActivePath} = additionalEffects;
|
23
|
+
|
24
|
+
return {
|
25
|
+
openPreview: () => {
|
26
|
+
dispatch(setShowPreview(true));
|
27
|
+
dispatch(setTenantPage(TENANT_PAGES_IDS.query));
|
28
|
+
dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
|
29
|
+
setActivePath(path);
|
30
|
+
},
|
31
|
+
};
|
32
|
+
};
|
33
|
+
|
34
|
+
type Controls = ReturnType<Required<NavigationTreeProps>['renderAdditionalNodeElements']>;
|
35
|
+
|
36
|
+
export const getControls =
|
37
|
+
(dispatch: Dispatch<any>, additionalEffects: ControlsAdditionalEffects) =>
|
38
|
+
(path: string, type: NavigationTreeNodeType) => {
|
39
|
+
const options = bindActions(path, dispatch, additionalEffects);
|
40
|
+
const openPreview = (
|
41
|
+
<Button
|
42
|
+
view="flat-secondary"
|
43
|
+
onClick={options.openPreview}
|
44
|
+
title={i18n('actions.openPreview')}
|
45
|
+
size="s"
|
46
|
+
>
|
47
|
+
<IconWrapper name="tablePreview" />
|
48
|
+
</Button>
|
49
|
+
);
|
50
|
+
|
51
|
+
const nodeTypeToControls: Record<NavigationTreeNodeType, Controls> = {
|
52
|
+
database: undefined,
|
53
|
+
directory: undefined,
|
54
|
+
|
55
|
+
table: openPreview,
|
56
|
+
column_table: openPreview,
|
57
|
+
|
58
|
+
index_table: undefined,
|
59
|
+
topic: undefined,
|
60
|
+
stream: undefined,
|
61
|
+
|
62
|
+
index: undefined,
|
63
|
+
|
64
|
+
external_table: openPreview,
|
65
|
+
external_data_source: undefined,
|
66
|
+
};
|
67
|
+
|
68
|
+
return nodeTypeToControls[type];
|
69
|
+
};
|
@@ -15,6 +15,9 @@
|
|
15
15
|
"settings.useNodesEndpoint.title": "Break the Nodes tab in Diagnostics",
|
16
16
|
"settings.useNodesEndpoint.popover": "Use /viewer/json/nodes endpoint for Nodes Tab in diagnostics. It returns incorrect data on versions before 23-1",
|
17
17
|
|
18
|
+
"settings.useBackendParamsForTables.title": "Offload tables filters and sorting to backend",
|
19
|
+
"settings.useBackendParamsForTables.popover": "Filter and sort Nodes table with request params. May increase performance, but could causes additional fetches and longer loading time on older versions",
|
20
|
+
|
18
21
|
"settings.enableAdditionalQueryModes.title": "Enable additional query modes",
|
19
22
|
"settings.enableAdditionalQueryModes.popover": "Adds 'Data' and 'YQL - QueryService' modes. May not work on some versions"
|
20
23
|
}
|
@@ -15,6 +15,9 @@
|
|
15
15
|
"settings.useNodesEndpoint.title": "Сломать вкладку Nodes в диагностике",
|
16
16
|
"settings.useNodesEndpoint.popover": "Использовать эндпоинт /viewer/json/nodes для вкладки Nodes в диагностике. Может возвращать некорректные данные на версиях до 23-1",
|
17
17
|
|
18
|
+
"settings.useBackendParamsForTables.title": "Перенести фильтры и сортировку таблиц на бэкенд",
|
19
|
+
"settings.useBackendParamsForTables.popover": "Добавляет фильтрацию и сортировку таблицы Nodes с использованием параметров запроса. Может улушить производительность, но на старых версиях может привести к дополнительным запросам и большему времени ожидания загрузки",
|
20
|
+
|
18
21
|
"settings.enableAdditionalQueryModes.title": "Включить дополнительные режимы выполнения запросов",
|
19
22
|
"settings.enableAdditionalQueryModes.popover": "Добавляет режимы 'Data' и 'YQL - QueryService'. Может работать некорректно на некоторых версиях"
|
20
23
|
}
|
@@ -7,6 +7,7 @@ import {
|
|
7
7
|
ENABLE_ADDITIONAL_QUERY_MODES,
|
8
8
|
INVERTED_DISKS_KEY,
|
9
9
|
THEME_KEY,
|
10
|
+
USE_BACKEND_PARAMS_FOR_TABLES_KEY,
|
10
11
|
USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
|
11
12
|
} from '../../utils/constants';
|
12
13
|
|
@@ -58,6 +59,11 @@ export const useNodesEndpointSetting: SettingProps = {
|
|
58
59
|
title: i18n('settings.useNodesEndpoint.title'),
|
59
60
|
helpPopoverContent: i18n('settings.useNodesEndpoint.popover'),
|
60
61
|
};
|
62
|
+
export const useBackendParamsForTables: SettingProps = {
|
63
|
+
settingKey: USE_BACKEND_PARAMS_FOR_TABLES_KEY,
|
64
|
+
title: i18n('settings.useBackendParamsForTables.title'),
|
65
|
+
helpPopoverContent: i18n('settings.useBackendParamsForTables.popover'),
|
66
|
+
};
|
61
67
|
export const enableQueryModesForExplainSetting: SettingProps = {
|
62
68
|
settingKey: ENABLE_ADDITIONAL_QUERY_MODES,
|
63
69
|
title: i18n('settings.enableAdditionalQueryModes.title'),
|
@@ -72,7 +78,12 @@ export const generalSection: SettingsSection = {
|
|
72
78
|
export const experimentsSection: SettingsSection = {
|
73
79
|
id: 'experimentsSection',
|
74
80
|
title: i18n('section.experiments'),
|
75
|
-
settings: [
|
81
|
+
settings: [
|
82
|
+
invertedDisksSetting,
|
83
|
+
useNodesEndpointSetting,
|
84
|
+
useBackendParamsForTables,
|
85
|
+
enableQueryModesForExplainSetting,
|
86
|
+
],
|
76
87
|
};
|
77
88
|
|
78
89
|
export const generalPage: SettingsPage = {
|
package/dist/index.js
CHANGED
@@ -1,13 +1,17 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import ReactDOM from 'react-dom';
|
3
|
-
import './index.css';
|
4
|
-
import App from './containers/App/App';
|
5
3
|
import {Provider} from 'react-redux';
|
4
|
+
|
5
|
+
import '@gravity-ui/uikit/styles/styles.scss';
|
6
|
+
|
7
|
+
import App from './containers/App/App';
|
6
8
|
import configureStore from './store';
|
7
9
|
import reportWebVitals from './reportWebVitals';
|
8
|
-
import '@gravity-ui/uikit/styles/styles.scss';
|
9
10
|
import HistoryContext from './contexts/HistoryContext';
|
10
11
|
|
12
|
+
import './styles/constants.scss';
|
13
|
+
import './index.css';
|
14
|
+
|
11
15
|
const {store, history} = configureStore();
|
12
16
|
window.store = store;
|
13
17
|
|
package/dist/services/api.ts
CHANGED
@@ -32,6 +32,7 @@ import type {ComputeApiRequestParams, NodesApiRequestParams} from '../store/redu
|
|
32
32
|
import type {StorageApiRequestParams} from '../store/reducers/storage/types';
|
33
33
|
|
34
34
|
import {backend as BACKEND} from '../store';
|
35
|
+
import {prepareSortValue} from '../utils/filters';
|
35
36
|
|
36
37
|
const config = {withCredentials: !window.custom_backend};
|
37
38
|
|
@@ -82,24 +83,35 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
82
83
|
});
|
83
84
|
}
|
84
85
|
getNodes(
|
85
|
-
{
|
86
|
+
{
|
87
|
+
visibleEntities,
|
88
|
+
type = 'any',
|
89
|
+
tablets = true,
|
90
|
+
sortOrder,
|
91
|
+
sortValue,
|
92
|
+
...params
|
93
|
+
}: NodesApiRequestParams,
|
86
94
|
{concurrentId}: AxiosOptions = {},
|
87
95
|
) {
|
96
|
+
const sort = prepareSortValue(sortValue, sortOrder);
|
97
|
+
|
88
98
|
return this.get<TNodesInfo>(
|
89
99
|
this.getPath('/viewer/json/nodes?enums=true'),
|
90
|
-
{
|
91
|
-
|
92
|
-
type,
|
93
|
-
tablets,
|
94
|
-
...params,
|
95
|
-
},
|
96
|
-
{
|
97
|
-
concurrentId,
|
98
|
-
},
|
100
|
+
{with: visibleEntities, type, tablets, sort, ...params},
|
101
|
+
{concurrentId},
|
99
102
|
);
|
100
103
|
}
|
101
|
-
getCompute(
|
102
|
-
|
104
|
+
getCompute(
|
105
|
+
{sortOrder, sortValue, ...params}: ComputeApiRequestParams,
|
106
|
+
{concurrentId}: AxiosOptions = {},
|
107
|
+
) {
|
108
|
+
const sort = prepareSortValue(sortValue, sortOrder);
|
109
|
+
|
110
|
+
return this.get<TComputeInfo>(
|
111
|
+
this.getPath('/viewer/json/compute?enums=true'),
|
112
|
+
{sort, ...params},
|
113
|
+
{concurrentId},
|
114
|
+
);
|
103
115
|
}
|
104
116
|
getStorageInfo(
|
105
117
|
{tenant, visibleEntities, nodeId}: StorageApiRequestParams,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import type {ClusterTab} from '../../../containers/Cluster/utils';
|
2
|
+
import type {EType} from '../../../types/api/tablet';
|
2
3
|
|
3
4
|
import {setHeaderBreadcrumbs} from './header';
|
4
5
|
|
@@ -23,6 +24,7 @@ export interface TabletsBreadcrumbsOptions extends TenantBreadcrumbsOptions {
|
|
23
24
|
|
24
25
|
export interface TabletBreadcrumbsOptions extends TabletsBreadcrumbsOptions {
|
25
26
|
tabletId?: string;
|
27
|
+
tabletType?: EType;
|
26
28
|
}
|
27
29
|
|
28
30
|
export type BreadcrumbsOptions =
|
@@ -10,6 +10,7 @@ import type {
|
|
10
10
|
ComputeApiRequestParams,
|
11
11
|
NodesAction,
|
12
12
|
NodesApiRequestParams,
|
13
|
+
NodesSortParams,
|
13
14
|
NodesState,
|
14
15
|
} from './types';
|
15
16
|
import {prepareComputeNodesData, prepareNodesData} from './utils';
|
@@ -20,6 +21,7 @@ const RESET_NODES_STATE = 'nodes/RESET_NODES_STATE';
|
|
20
21
|
const SET_NODES_UPTIME_FILTER = 'nodes/SET_NODES_UPTIME_FILTER';
|
21
22
|
const SET_DATA_WAS_NOT_LOADED = 'nodes/SET_DATA_WAS_NOT_LOADED';
|
22
23
|
const SET_SEARCH_VALUE = 'nodes/SET_SEARCH_VALUE';
|
24
|
+
const SET_SORT = 'nodes/SET_SORT';
|
23
25
|
|
24
26
|
const initialState = {
|
25
27
|
loading: false,
|
@@ -47,6 +49,10 @@ const nodes: Reducer<NodesState, NodesAction> = (state = initialState, action) =
|
|
47
49
|
};
|
48
50
|
}
|
49
51
|
case FETCH_NODES.FAILURE: {
|
52
|
+
if (action.error?.isCancelled) {
|
53
|
+
return state;
|
54
|
+
}
|
55
|
+
|
50
56
|
return {
|
51
57
|
...state,
|
52
58
|
error: action.error,
|
@@ -74,7 +80,13 @@ const nodes: Reducer<NodesState, NodesAction> = (state = initialState, action) =
|
|
74
80
|
searchValue: action.data,
|
75
81
|
};
|
76
82
|
}
|
77
|
-
|
83
|
+
case SET_SORT: {
|
84
|
+
return {
|
85
|
+
...state,
|
86
|
+
sortValue: action.data.sortValue,
|
87
|
+
sortOrder: action.data.sortOrder,
|
88
|
+
};
|
89
|
+
}
|
78
90
|
case SET_DATA_WAS_NOT_LOADED: {
|
79
91
|
return {
|
80
92
|
...state,
|
@@ -85,13 +97,11 @@ const nodes: Reducer<NodesState, NodesAction> = (state = initialState, action) =
|
|
85
97
|
return state;
|
86
98
|
}
|
87
99
|
};
|
100
|
+
const concurrentId = 'getNodes';
|
88
101
|
|
89
102
|
export function getNodes({type = 'any', ...params}: NodesApiRequestParams) {
|
90
103
|
return createApiRequest({
|
91
|
-
request: window.api.getNodes({
|
92
|
-
type,
|
93
|
-
...params,
|
94
|
-
}),
|
104
|
+
request: window.api.getNodes({type, ...params}, {concurrentId}),
|
95
105
|
actions: FETCH_NODES,
|
96
106
|
dataHandler: prepareNodesData,
|
97
107
|
});
|
@@ -99,7 +109,7 @@ export function getNodes({type = 'any', ...params}: NodesApiRequestParams) {
|
|
99
109
|
|
100
110
|
export function getComputeNodes({version = EVersion.v2, ...params}: ComputeApiRequestParams) {
|
101
111
|
return createApiRequest({
|
102
|
-
request: window.api.getCompute({version, ...params}),
|
112
|
+
request: window.api.getCompute({version, ...params}, {concurrentId}),
|
103
113
|
actions: FETCH_NODES,
|
104
114
|
dataHandler: prepareComputeNodesData,
|
105
115
|
});
|
@@ -130,4 +140,11 @@ export const setSearchValue = (value: string) => {
|
|
130
140
|
} as const;
|
131
141
|
};
|
132
142
|
|
143
|
+
export const setSort = (sortParams: NodesSortParams) => {
|
144
|
+
return {
|
145
|
+
type: SET_SORT,
|
146
|
+
data: sortParams,
|
147
|
+
} as const;
|
148
|
+
};
|
149
|
+
|
133
150
|
export default nodes;
|
@@ -1,10 +1,10 @@
|
|
1
1
|
import {Selector, createSelector} from 'reselect';
|
2
|
-
import {escapeRegExp} from 'lodash';
|
3
2
|
|
4
3
|
import {EFlag} from '../../../types/api/enums';
|
5
4
|
import {calcUptimeInSeconds} from '../../../utils';
|
6
5
|
import {HOUR_IN_SECONDS} from '../../../utils/constants';
|
7
6
|
import {NodesUptimeFilterValues} from '../../../utils/nodes';
|
7
|
+
import {prepareSearchValue} from '../../../utils/filters';
|
8
8
|
|
9
9
|
import type {ProblemFilterValue} from '../settings/types';
|
10
10
|
import type {NodesPreparedEntity, NodesStateSlice} from './types';
|
@@ -41,7 +41,7 @@ const filterNodesBySearchValue = (nodesList: NodesPreparedEntity[] = [], searchV
|
|
41
41
|
if (!searchValue) {
|
42
42
|
return nodesList;
|
43
43
|
}
|
44
|
-
const re =
|
44
|
+
const re = prepareSearchValue(searchValue);
|
45
45
|
|
46
46
|
return nodesList.filter((node) => {
|
47
47
|
return node.Host ? re.test(node.Host) || re.test(String(node.NodeId)) : true;
|
@@ -1,3 +1,5 @@
|
|
1
|
+
import type {OrderType} from '@gravity-ui/react-data-table';
|
2
|
+
|
1
3
|
import type {IResponseError} from '../../../types/api/error';
|
2
4
|
import type {TEndpoint, TPoolStats} from '../../../types/api/nodes';
|
3
5
|
import type {
|
@@ -9,13 +11,14 @@ import type {EFlag} from '../../../types/api/enums';
|
|
9
11
|
import type {ApiRequestAction} from '../../utils';
|
10
12
|
import type {VisibleEntities} from '../storage/types';
|
11
13
|
|
12
|
-
import {NodesUptimeFilterValues} from '../../../utils/nodes';
|
14
|
+
import type {NodesSortValue, NodesUptimeFilterValues} from '../../../utils/nodes';
|
13
15
|
import {
|
14
16
|
FETCH_NODES,
|
15
17
|
resetNodesState,
|
16
18
|
setDataWasNotLoaded,
|
17
19
|
setNodesUptimeFilter,
|
18
20
|
setSearchValue,
|
21
|
+
setSort,
|
19
22
|
} from './nodes';
|
20
23
|
|
21
24
|
// Since nodes from different endpoints can have different types,
|
@@ -42,6 +45,8 @@ export interface NodesState {
|
|
42
45
|
wasLoaded: boolean;
|
43
46
|
nodesUptimeFilter: NodesUptimeFilterValues;
|
44
47
|
searchValue: string;
|
48
|
+
sortValue?: NodesSortValue;
|
49
|
+
sortOrder?: OrderType;
|
45
50
|
data?: NodesPreparedEntity[];
|
46
51
|
totalNodes?: number;
|
47
52
|
error?: IResponseError;
|
@@ -49,17 +54,21 @@ export interface NodesState {
|
|
49
54
|
|
50
55
|
export type NodeType = 'static' | 'dynamic' | 'any';
|
51
56
|
|
52
|
-
interface
|
57
|
+
export interface NodesSortParams {
|
58
|
+
sortOrder?: OrderType;
|
59
|
+
sortValue?: NodesSortValue;
|
60
|
+
}
|
61
|
+
|
62
|
+
export interface NodesGeneralRequestParams extends NodesSortParams {
|
53
63
|
filter?: string; // NodeId or Host
|
54
64
|
uptime?: number; // return nodes with less uptime in seconds
|
55
65
|
problems_only?: boolean; // return nodes with SystemState !== EFlag.Green
|
56
|
-
sort?: string; // Sort by one of ESort params (may differ for /nodes and /compute)
|
57
66
|
|
58
67
|
offser?: number;
|
59
68
|
limit?: number;
|
60
69
|
}
|
61
70
|
|
62
|
-
export interface NodesApiRequestParams extends
|
71
|
+
export interface NodesApiRequestParams extends NodesGeneralRequestParams {
|
63
72
|
tenant?: string;
|
64
73
|
type?: NodeType;
|
65
74
|
visibleEntities?: VisibleEntities; // "with" param
|
@@ -67,7 +76,7 @@ export interface NodesApiRequestParams extends RequestParams {
|
|
67
76
|
tablets?: boolean;
|
68
77
|
}
|
69
78
|
|
70
|
-
export interface ComputeApiRequestParams extends
|
79
|
+
export interface ComputeApiRequestParams extends NodesGeneralRequestParams {
|
71
80
|
path: string;
|
72
81
|
version?: EVersion; // only v2 works with filters
|
73
82
|
}
|
@@ -90,6 +99,7 @@ export type NodesAction =
|
|
90
99
|
| ReturnType<typeof setDataWasNotLoaded>
|
91
100
|
| ReturnType<typeof setNodesUptimeFilter>
|
92
101
|
| ReturnType<typeof setSearchValue>
|
102
|
+
| ReturnType<typeof setSort>
|
93
103
|
| ReturnType<typeof resetNodesState>
|
94
104
|
);
|
95
105
|
|
@@ -13,6 +13,7 @@ import {
|
|
13
13
|
ENABLE_ADDITIONAL_QUERY_MODES,
|
14
14
|
CLUSTER_INFO_HIDDEN_KEY,
|
15
15
|
LAST_USED_QUERY_ACTION_KEY,
|
16
|
+
USE_BACKEND_PARAMS_FOR_TABLES_KEY,
|
16
17
|
} from '../../../utils/constants';
|
17
18
|
import '../../../services/api';
|
18
19
|
import {getValueFromLS, parseJson} from '../../../utils/utils';
|
@@ -76,6 +77,10 @@ export const initialState = {
|
|
76
77
|
[ASIDE_HEADER_COMPACT_KEY]: readSavedSettingsValue(ASIDE_HEADER_COMPACT_KEY, 'true'),
|
77
78
|
[PARTITIONS_HIDDEN_COLUMNS_KEY]: readSavedSettingsValue(PARTITIONS_HIDDEN_COLUMNS_KEY),
|
78
79
|
[CLUSTER_INFO_HIDDEN_KEY]: readSavedSettingsValue(CLUSTER_INFO_HIDDEN_KEY, 'true'),
|
80
|
+
[USE_BACKEND_PARAMS_FOR_TABLES_KEY]: readSavedSettingsValue(
|
81
|
+
USE_BACKEND_PARAMS_FOR_TABLES_KEY,
|
82
|
+
'false',
|
83
|
+
),
|
79
84
|
},
|
80
85
|
systemSettings,
|
81
86
|
};
|
@@ -65,15 +65,3 @@ export enum EVersion {
|
|
65
65
|
v1 = 'v1',
|
66
66
|
v2 = 'v2', // only this versions works with sorting
|
67
67
|
}
|
68
|
-
|
69
|
-
export enum ESort {
|
70
|
-
NodeId = 'NodeId',
|
71
|
-
Host = 'Host',
|
72
|
-
DC = 'DC',
|
73
|
-
Rack = 'Rack',
|
74
|
-
Version = 'Version',
|
75
|
-
Uptime = 'Uptime',
|
76
|
-
Memory = 'Memory',
|
77
|
-
CPU = 'CPU',
|
78
|
-
LoadAverage = 'LoadAverage',
|
79
|
-
}
|
package/dist/types/api/nodes.ts
CHANGED
@@ -101,15 +101,3 @@ enum EConfigState {
|
|
101
101
|
'Consistent' = 'Consistent',
|
102
102
|
'Outdated' = 'Outdated',
|
103
103
|
}
|
104
|
-
|
105
|
-
export enum ESort {
|
106
|
-
NodeId = 'NodeId',
|
107
|
-
Host = 'Host',
|
108
|
-
DC = 'DC',
|
109
|
-
Rack = 'Rack',
|
110
|
-
Version = 'Version',
|
111
|
-
Uptime = 'Uptime',
|
112
|
-
Memory = 'Memory',
|
113
|
-
CPU = 'CPU',
|
114
|
-
LoadAverage = 'LoadAverage',
|
115
|
-
}
|
package/dist/utils/constants.ts
CHANGED
@@ -119,3 +119,6 @@ export const CLUSTER_INFO_HIDDEN_KEY = 'clusterInfoHidden';
|
|
119
119
|
|
120
120
|
// Remain "tab" in key name for backward compatibility
|
121
121
|
export const TENANT_INITIAL_PAGE_KEY = 'saved_tenant_initial_tab';
|
122
|
+
|
123
|
+
// Send filters and sort params to backend for Nodes and Storage tables
|
124
|
+
export const USE_BACKEND_PARAMS_FOR_TABLES_KEY = 'useBackendParamsForTables';
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import {escapeRegExp} from 'lodash';
|
2
|
+
|
3
|
+
import type {OrderType} from '@gravity-ui/react-data-table';
|
4
|
+
import {DESCENDING} from '@gravity-ui/react-data-table/build/esm/lib/constants';
|
5
|
+
|
6
|
+
export const prepareSortValue = (
|
7
|
+
sortValue: string | undefined,
|
8
|
+
sortOrder: OrderType = DESCENDING,
|
9
|
+
) => {
|
10
|
+
if (!sortValue) {
|
11
|
+
return '';
|
12
|
+
}
|
13
|
+
|
14
|
+
if (sortOrder === DESCENDING) {
|
15
|
+
return '-' + sortValue;
|
16
|
+
}
|
17
|
+
|
18
|
+
return sortValue;
|
19
|
+
};
|
20
|
+
|
21
|
+
export const prepareSearchValue = (searchValue = '') => {
|
22
|
+
return new RegExp(escapeRegExp(searchValue), 'i');
|
23
|
+
};
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import {i18n, Lang} from '../../../utils/i18n';
|
2
|
+
|
3
|
+
import en from './en.json';
|
4
|
+
import ru from './ru.json';
|
5
|
+
|
6
|
+
const COMPONENT = 'ydb-hooks';
|
7
|
+
|
8
|
+
i18n.registerKeyset(Lang.En, COMPONENT, en);
|
9
|
+
i18n.registerKeyset(Lang.Ru, COMPONENT, ru);
|
10
|
+
|
11
|
+
export default i18n.keyset(COMPONENT);
|
@@ -0,0 +1,46 @@
|
|
1
|
+
import {useMemo} from 'react';
|
2
|
+
|
3
|
+
import type {NodesGeneralRequestParams} from '../../store/reducers/nodes/types';
|
4
|
+
import type {ProblemFilterValue} from '../../store/reducers/settings/types';
|
5
|
+
import {ProblemFilterValues} from '../../store/reducers/settings/settings';
|
6
|
+
|
7
|
+
import {HOUR_IN_SECONDS, USE_BACKEND_PARAMS_FOR_TABLES_KEY} from '../constants';
|
8
|
+
import {NodesUptimeFilterValues} from '../nodes';
|
9
|
+
import {useSetting} from './useSetting';
|
10
|
+
|
11
|
+
interface NodesRawRequestParams
|
12
|
+
extends Omit<NodesGeneralRequestParams, 'problems_only' | 'uptime'> {
|
13
|
+
problemFilter?: ProblemFilterValue;
|
14
|
+
nodesUptimeFilter?: NodesUptimeFilterValues;
|
15
|
+
}
|
16
|
+
|
17
|
+
export const useNodesRequestParams = ({
|
18
|
+
filter,
|
19
|
+
problemFilter,
|
20
|
+
nodesUptimeFilter,
|
21
|
+
sortOrder,
|
22
|
+
sortValue,
|
23
|
+
}: NodesRawRequestParams) => {
|
24
|
+
const [useBackendParamsForTables] = useSetting<boolean>(USE_BACKEND_PARAMS_FOR_TABLES_KEY);
|
25
|
+
|
26
|
+
// If backend params are enabled, update params value to use them in fetch request
|
27
|
+
// Otherwise no params will be updated, no hooks that depend on requestParams will be triggered
|
28
|
+
return useMemo(() => {
|
29
|
+
if (useBackendParamsForTables) {
|
30
|
+
const problemsOnly = problemFilter === ProblemFilterValues.PROBLEMS;
|
31
|
+
const uptime =
|
32
|
+
nodesUptimeFilter === NodesUptimeFilterValues.SmallUptime
|
33
|
+
? HOUR_IN_SECONDS
|
34
|
+
: undefined;
|
35
|
+
|
36
|
+
return {
|
37
|
+
filter,
|
38
|
+
problems_only: problemsOnly,
|
39
|
+
uptime,
|
40
|
+
sortOrder,
|
41
|
+
sortValue,
|
42
|
+
};
|
43
|
+
}
|
44
|
+
return undefined;
|
45
|
+
}, [useBackendParamsForTables, filter, problemFilter, nodesUptimeFilter, sortOrder, sortValue]);
|
46
|
+
};
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import type {QueryMode} from '../../types/store/query';
|
2
|
+
import {ENABLE_ADDITIONAL_QUERY_MODES, QUERY_INITIAL_MODE_KEY} from '../constants';
|
3
|
+
import {isNewQueryMode} from '../query';
|
4
|
+
import createToast from '../createToast';
|
5
|
+
import {useSetting} from './useSetting';
|
6
|
+
import i18n from './i18n';
|
7
|
+
|
8
|
+
export type SetQueryModeIfAvailable = (
|
9
|
+
value: QueryMode,
|
10
|
+
errorMessage?: string | undefined,
|
11
|
+
) => boolean;
|
12
|
+
|
13
|
+
export const useQueryModes = (): [QueryMode, SetQueryModeIfAvailable] => {
|
14
|
+
const [queryMode, setQueryMode] = useSetting<QueryMode>(QUERY_INITIAL_MODE_KEY);
|
15
|
+
const [enableAdditionalQueryModes] = useSetting<boolean>(ENABLE_ADDITIONAL_QUERY_MODES);
|
16
|
+
|
17
|
+
const setQueryModeIfAvailable: SetQueryModeIfAvailable = (value, errorMessage) => {
|
18
|
+
if (isNewQueryMode(value) && !enableAdditionalQueryModes) {
|
19
|
+
createToast({
|
20
|
+
name: 'QueryModeCannotBeSet',
|
21
|
+
title: errorMessage ?? i18n('useQueryModes.queryModeCannotBeSet', {mode: value}),
|
22
|
+
type: 'error',
|
23
|
+
});
|
24
|
+
|
25
|
+
return false;
|
26
|
+
} else {
|
27
|
+
setQueryMode(value);
|
28
|
+
|
29
|
+
return true;
|
30
|
+
}
|
31
|
+
};
|
32
|
+
|
33
|
+
return [queryMode, setQueryModeIfAvailable];
|
34
|
+
};
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import {useMemo} from 'react';
|
2
|
+
|
3
|
+
import {OrderType, SortOrder} from '@gravity-ui/react-data-table';
|
4
|
+
import {DESCENDING} from '@gravity-ui/react-data-table/build/esm/lib/constants';
|
5
|
+
|
6
|
+
interface SortParams {
|
7
|
+
sortValue: string | undefined;
|
8
|
+
sortOrder: OrderType | undefined;
|
9
|
+
}
|
10
|
+
|
11
|
+
type HandleSort = (rawValue: SortOrder | SortOrder[] | undefined) => void;
|
12
|
+
|
13
|
+
export const useTableSort = (
|
14
|
+
{sortValue, sortOrder = DESCENDING}: SortParams,
|
15
|
+
onSort: (params: SortParams) => void,
|
16
|
+
): [SortOrder | undefined, HandleSort] => {
|
17
|
+
const sort: SortOrder | undefined = useMemo(() => {
|
18
|
+
if (!sortValue) {
|
19
|
+
return undefined;
|
20
|
+
}
|
21
|
+
|
22
|
+
return {
|
23
|
+
columnId: sortValue,
|
24
|
+
order: sortOrder,
|
25
|
+
};
|
26
|
+
}, [sortValue, sortOrder]);
|
27
|
+
|
28
|
+
const handleSort: HandleSort = (rawValue) => {
|
29
|
+
const value = Array.isArray(rawValue) ? rawValue[0] : rawValue;
|
30
|
+
onSort({
|
31
|
+
sortValue: value?.columnId,
|
32
|
+
sortOrder: value?.order,
|
33
|
+
});
|
34
|
+
};
|
35
|
+
|
36
|
+
return [sort, handleSort];
|
37
|
+
};
|
package/dist/utils/nodes.ts
CHANGED
@@ -2,6 +2,7 @@ import type {TSystemStateInfo} from '../types/api/nodes';
|
|
2
2
|
import type {TNodeInfo} from '../types/api/nodesList';
|
3
3
|
import type {NodesPreparedEntity} from '../store/reducers/nodes/types';
|
4
4
|
import type {NodesMap} from '../types/store/nodesList';
|
5
|
+
import type {ValueOf} from '../types/common';
|
5
6
|
import {EFlag} from '../types/api/enums';
|
6
7
|
|
7
8
|
export enum NodesUptimeFilterValues {
|
@@ -31,3 +32,27 @@ export const prepareNodesMap = (nodesList?: TNodeInfo[]) => {
|
|
31
32
|
return nodesMap;
|
32
33
|
}, new Map());
|
33
34
|
};
|
35
|
+
|
36
|
+
/**
|
37
|
+
* Values to sort /compute v2 and /nodes responses
|
38
|
+
*
|
39
|
+
* For actual values go to:\
|
40
|
+
* /nodes: https://github.com/ydb-platform/ydb/blob/main/ydb/core/viewer/json_nodes.h\
|
41
|
+
* /compute: https://github.com/ydb-platform/ydb/blob/main/ydb/core/viewer/json_compute.h
|
42
|
+
*/
|
43
|
+
export const NODES_SORT_VALUES = {
|
44
|
+
NodeId: 'NodeId',
|
45
|
+
Host: 'Host',
|
46
|
+
DC: 'DC',
|
47
|
+
Rack: 'Rack',
|
48
|
+
Version: 'Version',
|
49
|
+
Uptime: 'Uptime',
|
50
|
+
Memory: 'Memory',
|
51
|
+
CPU: 'CPU',
|
52
|
+
LoadAverage: 'LoadAverage',
|
53
|
+
} as const;
|
54
|
+
|
55
|
+
export type NodesSortValue = ValueOf<typeof NODES_SORT_VALUES>;
|
56
|
+
|
57
|
+
export const isSortableNodesProperty = (value: string): value is NodesSortValue =>
|
58
|
+
Object.values(NODES_SORT_VALUES).includes(value as NodesSortValue);
|