ydb-embedded-ui 4.12.0 → 4.14.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.
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);