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.
Files changed (61) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/components/InfoViewer/formatters/common.ts +4 -2
  3. package/dist/components/InfoViewer/i18n/en.json +4 -0
  4. package/dist/components/InfoViewer/i18n/index.ts +11 -0
  5. package/dist/components/InfoViewer/i18n/ru.json +4 -0
  6. package/dist/components/Tablet/Tablet.scss +1 -16
  7. package/dist/components/Tablet/Tablet.tsx +5 -5
  8. package/dist/components/TabletIcon/TabletIcon.scss +17 -0
  9. package/dist/components/TabletIcon/TabletIcon.tsx +18 -0
  10. package/dist/containers/Header/Header.scss +2 -0
  11. package/dist/containers/Header/Header.tsx +2 -7
  12. package/dist/containers/Header/{breadcrumbs.ts → breadcrumbs.tsx} +19 -8
  13. package/dist/containers/Nodes/Nodes.tsx +53 -16
  14. package/dist/containers/Nodes/getNodesColumns.tsx +31 -13
  15. package/dist/containers/Tablet/Tablet.tsx +9 -3
  16. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +5 -2
  17. package/dist/containers/Tenant/Info/ExternalDataSource/ExternalDataSource.scss +5 -0
  18. package/dist/containers/Tenant/Info/ExternalDataSource/ExternalDataSource.tsx +81 -0
  19. package/dist/containers/Tenant/Info/ExternalTable/ExternalTable.scss +5 -0
  20. package/dist/containers/Tenant/Info/ExternalTable/ExternalTable.tsx +103 -0
  21. package/dist/containers/Tenant/Info/i18n/en.json +8 -0
  22. package/dist/containers/Tenant/Info/i18n/index.ts +11 -0
  23. package/dist/containers/Tenant/Info/i18n/ru.json +8 -0
  24. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.scss +4 -4
  25. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +10 -3
  26. package/dist/containers/Tenant/Query/QueryDuration/QueryDuration.scss +8 -0
  27. package/dist/containers/Tenant/Query/QueryDuration/QueryDuration.tsx +13 -1
  28. package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +4 -6
  29. package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.scss +3 -1
  30. package/dist/containers/Tenant/Query/i18n/en.json +6 -4
  31. package/dist/containers/Tenant/Query/i18n/ru.json +6 -4
  32. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +12 -2
  33. package/dist/containers/Tenant/i18n/en.json +12 -2
  34. package/dist/containers/Tenant/i18n/ru.json +11 -1
  35. package/dist/containers/Tenant/utils/schemaActions.ts +76 -28
  36. package/dist/containers/Tenant/utils/schemaControls.tsx +69 -0
  37. package/dist/containers/UserSettings/i18n/en.json +3 -0
  38. package/dist/containers/UserSettings/i18n/ru.json +3 -0
  39. package/dist/containers/UserSettings/settings.ts +12 -1
  40. package/dist/index.js +7 -3
  41. package/dist/services/api.ts +24 -12
  42. package/dist/store/reducers/header/types.ts +2 -0
  43. package/dist/store/reducers/nodes/nodes.ts +23 -6
  44. package/dist/store/reducers/nodes/selectors.ts +2 -2
  45. package/dist/store/reducers/nodes/types.ts +15 -5
  46. package/dist/store/reducers/settings/settings.ts +5 -0
  47. package/dist/styles/constants.scss +3 -0
  48. package/dist/types/api/compute.ts +0 -12
  49. package/dist/types/api/nodes.ts +0 -12
  50. package/dist/utils/constants.ts +3 -0
  51. package/dist/utils/filters.ts +23 -0
  52. package/dist/utils/hooks/i18n/en.json +3 -0
  53. package/dist/utils/hooks/i18n/index.ts +11 -0
  54. package/dist/utils/hooks/i18n/ru.json +3 -0
  55. package/dist/utils/hooks/index.ts +4 -0
  56. package/dist/utils/hooks/useNodesRequestParams.ts +46 -0
  57. package/dist/utils/hooks/useQueryModes.ts +34 -0
  58. package/dist/utils/hooks/useTableSort.ts +37 -0
  59. package/dist/utils/nodes.ts +25 -0
  60. package/dist/utils/query.ts +5 -1
  61. 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: [invertedDisksSetting, useNodesEndpointSetting, enableQueryModesForExplainSetting],
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
 
@@ -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
- {visibleEntities, type = 'any', tablets = true, ...params}: NodesApiRequestParams,
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
- with: visibleEntities,
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(params: ComputeApiRequestParams) {
102
- return this.get<TComputeInfo>(this.getPath('/viewer/json/compute?enums=true'), params);
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 = new RegExp(escapeRegExp(searchValue), 'i');
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 RequestParams {
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 RequestParams {
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 RequestParams {
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
  };
@@ -0,0 +1,3 @@
1
+ :root {
2
+ --tenant-object-info-max-value-width: 300px;
3
+ }
@@ -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
- }
@@ -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
- }
@@ -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,3 @@
1
+ {
2
+ "useQueryModes.queryModeCannotBeSet": "Query mode \"{{mode}}\" cannot be set. You need to turn in additional query modes in settings to enable it"
3
+ }
@@ -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,3 @@
1
+ {
2
+ "useQueryModes.queryModeCannotBeSet": "Режим выполнения запроса \"{{mode}}\" недоступен. Вам необходимо включить дополнительные режимы выполнения запросов в настройках"
3
+ }
@@ -1,3 +1,7 @@
1
1
  export * from './useAutofetcher';
2
2
  export * from './useTypedSelector';
3
3
  export * from './useSetting';
4
+ export * from './useQueryModes';
5
+ export * from './useTableSort';
6
+
7
+ export * from './useNodesRequestParams';
@@ -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
+ };
@@ -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);