ydb-embedded-ui 4.21.0 → 4.22.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/components/NodeHostWrapper/NodeHostWrapper.scss +2 -1
  3. package/dist/components/QueryResultTable/QueryResultTable.tsx +7 -3
  4. package/dist/components/VirtualTable/TableChunk.tsx +2 -1
  5. package/dist/components/VirtualTable/VirtualTable.tsx +1 -1
  6. package/dist/containers/Node/Node.tsx +9 -17
  7. package/dist/containers/Node/NodeStructure/NodeStructure.tsx +8 -30
  8. package/dist/containers/Node/NodeStructure/Pdisk.tsx +32 -18
  9. package/dist/containers/Node/i18n/en.json +4 -0
  10. package/dist/containers/Node/i18n/index.ts +11 -0
  11. package/dist/containers/Node/i18n/ru.json +4 -0
  12. package/dist/containers/Nodes/Nodes.tsx +5 -10
  13. package/dist/containers/Nodes/getNodesColumns.tsx +57 -13
  14. package/dist/containers/Tablets/Tablets.tsx +3 -8
  15. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +0 -1
  16. package/dist/containers/Tenant/Diagnostics/Network/Network.js +5 -10
  17. package/dist/containers/Tenant/Diagnostics/Network/utils.ts +6 -0
  18. package/dist/containers/Tenant/Query/ExecuteResult/ExecuteResult.scss +13 -5
  19. package/dist/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx +72 -18
  20. package/dist/containers/Tenant/Query/ExplainResult/ExplainResult.js +2 -1
  21. package/dist/containers/Tenant/Query/ExplainResult/utils.ts +6 -0
  22. package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +11 -24
  23. package/dist/containers/Tenant/Query/utils/getPreparedResult.ts +4 -5
  24. package/dist/containers/UserSettings/i18n/en.json +5 -2
  25. package/dist/containers/UserSettings/i18n/ru.json +5 -2
  26. package/dist/containers/UserSettings/settings.ts +12 -6
  27. package/dist/store/reducers/executeQuery.ts +4 -3
  28. package/dist/store/reducers/nodes/nodes.ts +2 -2
  29. package/dist/store/reducers/nodes/types.ts +12 -1
  30. package/dist/store/reducers/nodes/utils.ts +6 -0
  31. package/dist/store/reducers/settings/settings.ts +5 -3
  32. package/dist/types/api/netInfo.ts +1 -1
  33. package/dist/types/api/nodes.ts +24 -0
  34. package/dist/types/api/query.ts +23 -8
  35. package/dist/types/store/query.ts +6 -0
  36. package/dist/utils/constants.ts +3 -0
  37. package/dist/utils/developerUI/__test__/developerUI.test.ts +50 -0
  38. package/dist/utils/developerUI/developerUI.ts +42 -0
  39. package/dist/utils/diagnostics.ts +1 -0
  40. package/dist/utils/query.ts +68 -13
  41. package/package.json +1 -1
  42. package/dist/utils/index.js +0 -9
  43. /package/dist/{components/VirtualTable/utils.ts → utils/index.ts} +0 -0
@@ -0,0 +1,6 @@
1
+ import type {TNetNodePeerInfo} from '../../../../types/api/netInfo';
2
+
3
+ // determine how many nodes have status Connected "true"
4
+ export const getConnectedNodesCount = (peers: TNetNodePeerInfo[] | undefined) => {
5
+ return peers?.reduce((acc, item) => (item.Connected ? acc + 1 : acc), 0);
6
+ };
@@ -13,11 +13,19 @@
13
13
  & .data-table__table-wrapper {
14
14
  padding-bottom: 0;
15
15
  }
16
- &_fullscreen {
17
- width: 100%;
18
- margin-top: 10px;
19
- padding: 0 10px 10px;
20
- }
16
+ }
17
+
18
+ &__result-fullscreen-wrapper {
19
+ display: flex;
20
+ flex-direction: column;
21
+
22
+ width: 100%;
23
+ margin-top: 10px;
24
+ padding: 0 10px 10px;
25
+ }
26
+
27
+ &__result-tabs {
28
+ padding-left: 10px;
21
29
  }
22
30
 
23
31
  &__error {
@@ -1,26 +1,30 @@
1
- import React, {type ReactNode, useEffect, useState} from 'react';
1
+ import React, {useEffect, useState} from 'react';
2
2
  import {useDispatch} from 'react-redux';
3
3
  import cn from 'bem-cn-lite';
4
4
  import JSONTree from 'react-json-inspector';
5
5
 
6
- import {RadioButton} from '@gravity-ui/uikit';
6
+ import {RadioButton, Tabs} from '@gravity-ui/uikit';
7
7
 
8
8
  import CopyToClipboard from '../../../../components/CopyToClipboard/CopyToClipboard';
9
9
  import Divider from '../../../../components/Divider/Divider';
10
10
  import EnableFullscreenButton from '../../../../components/EnableFullscreenButton/EnableFullscreenButton';
11
11
  import Fullscreen from '../../../../components/Fullscreen/Fullscreen';
12
12
  import {QueryExecutionStatus} from '../../../../components/QueryExecutionStatus';
13
+ import {QueryResultTable} from '../../../../components/QueryResultTable/QueryResultTable';
13
14
 
14
15
  import type {ValueOf} from '../../../../types/common';
15
16
  import type {IQueryResult, QueryErrorResponse} from '../../../../types/store/query';
17
+ import type {ColumnType, KeyValueRow} from '../../../../types/api/query';
16
18
  import {disableFullscreen} from '../../../../store/reducers/fullscreen';
17
19
  import {prepareQueryError} from '../../../../utils/query';
18
20
  import {useTypedSelector} from '../../../../utils/hooks';
21
+ import {getArray} from '../../../../utils';
19
22
 
20
23
  import {PaneVisibilityToggleButtons} from '../../utils/paneVisibilityToggleHelpers';
21
24
 
22
25
  import {ResultIssues} from '../Issues/Issues';
23
26
  import {QueryDuration} from '../QueryDuration/QueryDuration';
27
+ import {getPreparedResult} from '../utils/getPreparedResult';
24
28
 
25
29
  import './ExecuteResult.scss';
26
30
 
@@ -39,30 +43,35 @@ const resultOptions = [
39
43
  ];
40
44
 
41
45
  interface ExecuteResultProps {
42
- textResults: string;
43
- result: ReactNode;
46
+ data: IQueryResult | undefined;
44
47
  stats: IQueryResult['stats'] | undefined;
45
48
  error: string | QueryErrorResponse | undefined;
46
- copyDisabled?: boolean;
47
49
  isResultsCollapsed?: boolean;
48
50
  onCollapseResults: VoidFunction;
49
51
  onExpandResults: VoidFunction;
50
52
  }
51
53
 
52
54
  export function ExecuteResult({
53
- textResults,
54
- result,
55
+ data,
55
56
  stats,
56
57
  error,
57
- copyDisabled,
58
58
  isResultsCollapsed,
59
59
  onCollapseResults,
60
60
  onExpandResults,
61
61
  }: ExecuteResultProps) {
62
+ const [selectedResultSet, setSelectedResultSet] = useState(0);
62
63
  const [activeSection, setActiveSection] = useState<SectionID>(resultOptionsIds.result);
64
+
63
65
  const isFullscreen = useTypedSelector((state) => state.fullscreen);
64
66
  const dispatch = useDispatch();
65
67
 
68
+ const resultsSetsCount = data?.resultSets?.length;
69
+ const isMulti = resultsSetsCount && resultsSetsCount > 0;
70
+ const currentResult = isMulti ? data?.resultSets?.[selectedResultSet].result : data?.result;
71
+ const currentColumns = isMulti ? data?.resultSets?.[selectedResultSet].columns : data?.columns;
72
+ const textResults = getPreparedResult(currentResult);
73
+ const copyDisabled = !textResults.length;
74
+
66
75
  useEffect(() => {
67
76
  return () => {
68
77
  dispatch(disableFullscreen());
@@ -73,6 +82,37 @@ export function ExecuteResult({
73
82
  setActiveSection(value as SectionID);
74
83
  };
75
84
 
85
+ const renderResultTable = (
86
+ result: KeyValueRow[] | undefined,
87
+ columns: ColumnType[] | undefined,
88
+ ) => {
89
+ return <QueryResultTable data={result} columns={columns} settings={{sortable: false}} />;
90
+ };
91
+
92
+ const renderContent = () => {
93
+ return (
94
+ <>
95
+ {isMulti && resultsSetsCount > 1 && (
96
+ <div>
97
+ <Tabs
98
+ className={b('result-tabs')}
99
+ size="l"
100
+ items={getArray(resultsSetsCount).map((item) => ({
101
+ id: String(item),
102
+ title: `Result #${item + 1}`,
103
+ }))}
104
+ activeTab={String(selectedResultSet)}
105
+ onSelectTab={(tabId) => setSelectedResultSet(Number(tabId))}
106
+ />
107
+ </div>
108
+ )}
109
+ <div className={b('result')}>
110
+ {renderResultTable(currentResult, currentColumns)}
111
+ </div>
112
+ </>
113
+ );
114
+ };
115
+
76
116
  const renderClipboardButton = () => {
77
117
  return (
78
118
  <CopyToClipboard
@@ -108,12 +148,14 @@ export function ExecuteResult({
108
148
  };
109
149
 
110
150
  const renderResult = () => {
151
+ const content = renderContent();
152
+
111
153
  return (
112
154
  <React.Fragment>
113
- {result}
155
+ {content}
114
156
  {isFullscreen && (
115
157
  <Fullscreen>
116
- <div className={b('result', {fullscreen: true})}>{result}</div>
158
+ <div className={b('result-fullscreen-wrapper')}>{content}</div>
117
159
  </Fullscreen>
118
160
  )}
119
161
  </React.Fragment>
@@ -126,13 +168,15 @@ export function ExecuteResult({
126
168
  }
127
169
 
128
170
  if (typeof error === 'object' && error.data?.issues && Array.isArray(error.data.issues)) {
171
+ const content = <ResultIssues data={error.data} />;
172
+
129
173
  return (
130
174
  <React.Fragment>
131
- <ResultIssues data={error.data} />
175
+ {content}
132
176
  {isFullscreen && (
133
177
  <Fullscreen>
134
- <div className={b('result', {fullscreen: true})}>
135
- <ResultIssues data={error.data} />
178
+ <div className={b('result-fullscreen-wrapper', b('result'))}>
179
+ {content}
136
180
  </div>
137
181
  </Fullscreen>
138
182
  )}
@@ -145,6 +189,19 @@ export function ExecuteResult({
145
189
  return <div className={b('error')}>{parsedError}</div>;
146
190
  };
147
191
 
192
+ const renderResultSection = () => {
193
+ if (activeSection === resultOptionsIds.result && !error) {
194
+ return renderResult();
195
+ }
196
+
197
+ return (
198
+ <div className={b('result')}>
199
+ {activeSection === resultOptionsIds.stats && !error && renderStats()}
200
+ {renderIssues()}
201
+ </div>
202
+ );
203
+ };
204
+
148
205
  return (
149
206
  <React.Fragment>
150
207
  <div className={b('controls')}>
@@ -174,11 +231,8 @@ export function ExecuteResult({
174
231
  />
175
232
  </div>
176
233
  </div>
177
- <div className={b('result')}>
178
- {activeSection === resultOptionsIds.result && !error && renderResult()}
179
- {activeSection === resultOptionsIds.stats && !error && renderStats()}
180
- {renderIssues()}
181
- </div>
234
+
235
+ {renderResultSection()}
182
236
  </React.Fragment>
183
237
  );
184
238
  }
@@ -16,11 +16,12 @@ import {QueryExecutionStatus} from '../../../../components/QueryExecutionStatus'
16
16
  import {explainVersions} from '../../../../store/reducers/explainQuery';
17
17
  import {disableFullscreen} from '../../../../store/reducers/fullscreen';
18
18
 
19
- import {renderExplainNode} from '../../../../utils';
20
19
  import {LANGUAGE_S_EXPRESSION_ID} from '../../../../utils/monaco';
21
20
 
22
21
  import {PaneVisibilityToggleButtons} from '../../utils/paneVisibilityToggleHelpers';
23
22
 
23
+ import {renderExplainNode} from './utils';
24
+
24
25
  import './ExplainResult.scss';
25
26
 
26
27
  const b = cn('ydb-query-explain-result');
@@ -0,0 +1,6 @@
1
+ import type {GraphNode} from '@gravity-ui/paranoid';
2
+
3
+ export const renderExplainNode = (node: GraphNode): string => {
4
+ const parts = node.name.split('|');
5
+ return parts.length > 1 ? parts[1] : node.name;
6
+ };
@@ -6,7 +6,6 @@ import _ from 'lodash';
6
6
  import MonacoEditor from 'react-monaco-editor';
7
7
 
8
8
  import SplitPane from '../../../../components/SplitPane';
9
- import {QueryResultTable} from '../../../../components/QueryResultTable';
10
9
 
11
10
  import {
12
11
  sendExecuteQuery,
@@ -26,6 +25,7 @@ import {
26
25
  SAVED_QUERIES_KEY,
27
26
  ENABLE_ADDITIONAL_QUERY_MODES,
28
27
  LAST_USED_QUERY_ACTION_KEY,
28
+ QUERY_USE_MULTI_SCHEMA_KEY,
29
29
  } from '../../../../utils/constants';
30
30
  import {useSetting, useQueryModes} from '../../../../utils/hooks';
31
31
  import {QUERY_ACTIONS, QUERY_MODES, isNewQueryMode} from '../../../../utils/query';
@@ -40,14 +40,8 @@ import {ExecuteResult} from '../ExecuteResult/ExecuteResult';
40
40
  import {ExplainResult} from '../ExplainResult/ExplainResult';
41
41
  import {QueryEditorControls} from '../QueryEditorControls/QueryEditorControls';
42
42
 
43
- import {getPreparedResult} from '../utils/getPreparedResult';
44
-
45
43
  import './QueryEditor.scss';
46
44
 
47
- const TABLE_SETTINGS = {
48
- sortable: false,
49
- };
50
-
51
45
  const EDITOR_OPTIONS = {
52
46
  automaticLayout: true,
53
47
  selectOnLineNumbers: true,
@@ -92,6 +86,7 @@ function QueryEditor(props) {
92
86
  const [isResultLoaded, setIsResultLoaded] = useState(false);
93
87
  const [queryMode, setQueryMode] = useQueryModes();
94
88
  const [enableAdditionalQueryModes] = useSetting(ENABLE_ADDITIONAL_QUERY_MODES);
89
+ const [useMultiSchema] = useSetting(QUERY_USE_MULTI_SCHEMA_KEY);
95
90
  const [lastUsedQueryAction, setLastUsedQueryAction] = useSetting(LAST_USED_QUERY_ACTION_KEY);
96
91
 
97
92
  useEffect(() => {
@@ -256,9 +251,16 @@ function QueryEditor(props) {
256
251
  setShowPreview,
257
252
  } = props;
258
253
 
254
+ const schema = useMultiSchema ? 'multi' : 'modern';
255
+
259
256
  setLastUsedQueryAction(QUERY_ACTIONS.execute);
260
257
  setResultType(RESULT_TYPES.EXECUTE);
261
- sendExecuteQuery({query: input, database: path, mode});
258
+ sendExecuteQuery({
259
+ query: input,
260
+ database: path,
261
+ mode,
262
+ schema,
263
+ });
262
264
  setIsResultLoaded(true);
263
265
  setShowPreview(false);
264
266
 
@@ -314,26 +316,11 @@ function QueryEditor(props) {
314
316
  executeQuery: {data, error, stats},
315
317
  } = props;
316
318
 
317
- let content;
318
- if (data) {
319
- content = (
320
- <QueryResultTable
321
- data={data.result}
322
- columns={data.columns}
323
- settings={TABLE_SETTINGS}
324
- />
325
- );
326
- }
327
- const textResults = getPreparedResult(data);
328
- const disabled = !textResults.length || resultType !== RESULT_TYPES.EXECUTE;
329
-
330
319
  return data || error ? (
331
320
  <ExecuteResult
332
- result={content}
321
+ data={data}
333
322
  stats={stats}
334
323
  error={error}
335
- textResults={textResults}
336
- copyDisabled={disabled}
337
324
  isResultsCollapsed={resultVisibilityState.collapsed}
338
325
  onExpandResults={onExpandResultHandler}
339
326
  onCollapseResults={onCollapseResultHandler}
@@ -1,16 +1,15 @@
1
1
  import type {KeyValueRow} from '../../../../types/api/query';
2
- import type {IQueryResult} from '../../../../types/store/query';
3
2
 
4
- export const getPreparedResult = (data: IQueryResult) => {
3
+ export const getPreparedResult = (data: KeyValueRow[] | undefined) => {
5
4
  const columnDivider = '\t';
6
5
  const rowDivider = '\n';
7
6
 
8
- if (!data?.result?.length) {
7
+ if (!data?.length) {
9
8
  return '';
10
9
  }
11
10
 
12
- const columnHeaders = Object.keys(data.result[0]);
13
- const rows = Array<string[] | KeyValueRow[]>(columnHeaders).concat(data.result);
11
+ const columnHeaders = Object.keys(data[0]);
12
+ const rows = Array<string[] | KeyValueRow[]>(columnHeaders).concat(data);
14
13
 
15
14
  return rows
16
15
  .map((item) => {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "page.general": "General",
3
- "section.general": "General",
3
+ "section.appearance": "Appearance",
4
4
 
5
5
  "page.experiments": "Experiments",
6
6
  "section.experiments": "Experiments",
@@ -17,7 +17,7 @@
17
17
  "settings.invertedDisks.title": "Inverted disks space indicators",
18
18
 
19
19
  "settings.useNodesEndpoint.title": "Break the Nodes tab in Diagnostics",
20
- "settings.useNodesEndpoint.popover": "Use /viewer/json/nodes endpoint for Nodes Tab in diagnostics. It returns incorrect data on versions before 23-1",
20
+ "settings.useNodesEndpoint.popover": "Use /viewer/json/nodes endpoint for Nodes Tab in diagnostics. It could return incorrect data on some versions",
21
21
 
22
22
  "settings.useBackendParamsForTables.title": "Use virtual table for cluster Nodes tab",
23
23
  "settings.useBackendParamsForTables.popover": "Use table with data load on scroll. It will increase performance, but could work unstable",
@@ -25,6 +25,9 @@
25
25
  "settings.enableAdditionalQueryModes.title": "Enable additional query modes",
26
26
  "settings.enableAdditionalQueryModes.popover": "Adds 'Data', 'YQL - QueryService' and 'PostgreSQL' modes. May not work on some versions",
27
27
 
28
+ "settings.queryUseMultiSchema.title": "Allow queries with multiple result sets",
29
+ "settings.queryUseMultiSchema.popover": "Use 'multi' schema for queries that enables queries with multiple result sets. Returns nothing on versions 23-3 and older",
30
+
28
31
  "settings.tenantDiagnostics.title": "Display metrics cards for database diagnostics",
29
32
  "settings.tenantDiagnostics.popover": "Adds indicators of database resources usage. Incomplete data may be displayed for some databases"
30
33
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "page.general": "Общие",
3
- "section.general": "Общие",
3
+ "section.appearance": "Внешний вид",
4
4
 
5
5
  "page.experiments": "Эксперименты",
6
6
  "section.experiments": "Эксперименты",
@@ -17,7 +17,7 @@
17
17
  "settings.invertedDisks.title": "Инвертированные индикаторы места на дисках",
18
18
 
19
19
  "settings.useNodesEndpoint.title": "Сломать вкладку Nodes в диагностике",
20
- "settings.useNodesEndpoint.popover": "Использовать эндпоинт /viewer/json/nodes для вкладки Nodes в диагностике. Может возвращать некорректные данные на версиях до 23-1",
20
+ "settings.useNodesEndpoint.popover": "Использовать эндпоинт /viewer/json/nodes для вкладки Nodes в диагностике. Может возвращать некорректные данные на некоторых версиях",
21
21
 
22
22
  "settings.useBackendParamsForTables.title": "Использовать виртуализированную таблицу для вкладки Nodes кластера",
23
23
  "settings.useBackendParamsForTables.popover": "Использовать таблицу с загрузкой данных по скроллу. Это улучшит производительность, но может работать нестабильно",
@@ -25,6 +25,9 @@
25
25
  "settings.enableAdditionalQueryModes.title": "Включить дополнительные режимы выполнения запросов",
26
26
  "settings.enableAdditionalQueryModes.popover": "Добавляет режимы 'Data', 'YQL - QueryService' и 'PostgreSQL'. Может работать некорректно на некоторых версиях",
27
27
 
28
+ "settings.queryUseMultiSchema.title": "Разрешить запросы с несколькими результатами",
29
+ "settings.queryUseMultiSchema.popover": "Использовать для запросов схему 'multi', которая позволяет выполнять запросы с несколькими результатами. На версиях 23-3 и старше результат не возвращается вообще",
30
+
28
31
  "settings.tenantDiagnostics.title": "Показывать карточки с метриками в диагностике базы данных",
29
32
  "settings.tenantDiagnostics.popover": "Добавляет индикаторы использования ресурсов базы данных. Для некоторых баз могут отображаться неполные данные"
30
33
  }
@@ -11,6 +11,7 @@ import {
11
11
  THEME_KEY,
12
12
  USE_BACKEND_PARAMS_FOR_TABLES_KEY,
13
13
  USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
14
+ QUERY_USE_MULTI_SCHEMA_KEY,
14
15
  } from '../../utils/constants';
15
16
  import {Lang, defaultLang} from '../../utils/i18n';
16
17
 
@@ -95,25 +96,30 @@ export const enableQueryModesForExplainSetting: SettingProps = {
95
96
  title: i18n('settings.enableAdditionalQueryModes.title'),
96
97
  helpPopoverContent: i18n('settings.enableAdditionalQueryModes.popover'),
97
98
  };
99
+ export const queryUseMultiSchemaSetting: SettingProps = {
100
+ settingKey: QUERY_USE_MULTI_SCHEMA_KEY,
101
+ title: i18n('settings.queryUseMultiSchema.title'),
102
+ helpPopoverContent: i18n('settings.queryUseMultiSchema.popover'),
103
+ };
98
104
  export const enableNewTenantDiagnosticsDesign: SettingProps = {
99
105
  settingKey: DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS,
100
106
  title: i18n('settings.tenantDiagnostics.title'),
101
107
  helpPopoverContent: i18n('settings.tenantDiagnostics.popover'),
102
108
  };
103
109
 
104
- export const generalSection: SettingsSection = {
105
- id: 'generalSection',
106
- title: i18n('section.general'),
107
- settings: [themeSetting],
110
+ export const appearanceSection: SettingsSection = {
111
+ id: 'appearanceSection',
112
+ title: i18n('section.appearance'),
113
+ settings: [themeSetting, invertedDisksSetting],
108
114
  };
109
115
  export const experimentsSection: SettingsSection = {
110
116
  id: 'experimentsSection',
111
117
  title: i18n('section.experiments'),
112
118
  settings: [
113
- invertedDisksSetting,
114
119
  useNodesEndpointSetting,
115
120
  useBackendParamsForTables,
116
121
  enableQueryModesForExplainSetting,
122
+ queryUseMultiSchemaSetting,
117
123
  enableNewTenantDiagnosticsDesign,
118
124
  ],
119
125
  };
@@ -122,7 +128,7 @@ export const generalPage: SettingsPage = {
122
128
  id: 'generalPage',
123
129
  title: i18n('page.general'),
124
130
  icon: {data: favoriteFilledIcon, height: 14, width: 14},
125
- sections: [generalSection],
131
+ sections: [appearanceSection],
126
132
  };
127
133
  export const experimentsPage: SettingsPage = {
128
134
  id: 'experimentsPage',
@@ -1,6 +1,6 @@
1
1
  import type {Reducer} from 'redux';
2
2
 
3
- import type {ExecuteActions} from '../../types/api/query';
3
+ import type {ExecuteActions, Schemas} from '../../types/api/query';
4
4
  import type {
5
5
  ExecuteQueryAction,
6
6
  ExecuteQueryState,
@@ -154,9 +154,10 @@ const executeQuery: Reducer<ExecuteQueryState, ExecuteQueryAction> = (
154
154
 
155
155
  interface SendQueryParams extends QueryRequestParams {
156
156
  mode?: QueryMode;
157
+ schema?: Schemas;
157
158
  }
158
159
 
159
- export const sendExecuteQuery = ({query, database, mode}: SendQueryParams) => {
160
+ export const sendExecuteQuery = ({query, database, mode, schema = 'modern'}: SendQueryParams) => {
160
161
  let action: ExecuteActions = 'execute';
161
162
  let syntax: QuerySyntax = QUERY_SYNTAX.yql;
162
163
 
@@ -169,7 +170,7 @@ export const sendExecuteQuery = ({query, database, mode}: SendQueryParams) => {
169
170
 
170
171
  return createApiRequest({
171
172
  request: window.api.sendQuery({
172
- schema: 'modern',
173
+ schema,
173
174
  query,
174
175
  database,
175
176
  action,
@@ -99,9 +99,9 @@ const nodes: Reducer<NodesState, NodesAction> = (state = initialState, action) =
99
99
  };
100
100
  const concurrentId = 'getNodes';
101
101
 
102
- export function getNodes({type = 'any', ...params}: NodesApiRequestParams) {
102
+ export function getNodes({type = 'any', storage = false, ...params}: NodesApiRequestParams) {
103
103
  return createApiRequest({
104
- request: window.api.getNodes({type, ...params}, {concurrentId}),
104
+ request: window.api.getNodes({type, storage, ...params}, {concurrentId}),
105
105
  actions: FETCH_NODES,
106
106
  dataHandler: prepareNodesData,
107
107
  });
@@ -30,15 +30,25 @@ export interface NodesPreparedEntity {
30
30
  DataCenter?: string;
31
31
  Rack?: string;
32
32
  Version?: string;
33
+ TenantName?: string;
34
+
33
35
  StartTime?: string;
34
36
  Uptime: string;
37
+ DisconnectTime?: string;
38
+
35
39
  MemoryUsed?: string;
40
+ MemoryUsedInAlloc?: string;
36
41
  MemoryLimit?: string;
42
+
43
+ SharedCacheUsed?: string;
44
+ SharedCacheLimit?: string | number;
45
+
37
46
  PoolStats?: TPoolStats[];
38
47
  LoadAverage?: number[];
39
48
  Tablets?: TFullTabletStateInfo[] | TComputeTabletStateInfo[];
40
- TenantName?: string;
41
49
  Endpoints?: TEndpoint[];
50
+
51
+ TotalSessions?: number;
42
52
  }
43
53
 
44
54
  export interface NodesState {
@@ -70,6 +80,7 @@ export interface NodesGeneralRequestParams extends NodesSortParams {
70
80
  }
71
81
 
72
82
  export interface NodesApiRequestParams extends NodesGeneralRequestParams {
83
+ path?: string;
73
84
  tenant?: string;
74
85
  type?: NodeType;
75
86
  visibleEntities?: VisibleEntities; // "with" param
@@ -50,12 +50,18 @@ export const prepareNodesData = (data: TNodesInfo): NodesHandledResponse => {
50
50
  const rawNodes = data.Nodes || [];
51
51
 
52
52
  const preparedNodes = rawNodes.map((node) => {
53
+ // 0 limit means that limit is not set, so it should be undefined
54
+ const sharedCacheLimit = Number(node.SystemState.SharedCacheStats?.LimitBytes) || undefined;
55
+
53
56
  return {
54
57
  ...node.SystemState,
55
58
  Tablets: node.Tablets,
56
59
  NodeId: node.NodeId,
57
60
  Uptime: calcUptime(node.SystemState?.StartTime),
58
61
  TenantName: node.SystemState?.Tenants?.[0],
62
+
63
+ SharedCacheUsed: node.SystemState.SharedCacheStats?.UsedBytes,
64
+ SharedCacheLimit: sharedCacheLimit,
59
65
  };
60
66
  });
61
67
 
@@ -16,6 +16,7 @@ import {
16
16
  USE_BACKEND_PARAMS_FOR_TABLES_KEY,
17
17
  LANGUAGE_KEY,
18
18
  DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS,
19
+ QUERY_USE_MULTI_SCHEMA_KEY,
19
20
  } from '../../../utils/constants';
20
21
  import '../../../services/api';
21
22
  import {parseJson} from '../../../utils/utils';
@@ -50,15 +51,16 @@ export const initialState = {
50
51
  [INVERTED_DISKS_KEY]: readSavedSettingsValue(INVERTED_DISKS_KEY, 'false'),
51
52
  [USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY]: readSavedSettingsValue(
52
53
  USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
53
- 'true',
54
+ 'false',
54
55
  ),
55
56
  [ENABLE_ADDITIONAL_QUERY_MODES]: readSavedSettingsValue(
56
57
  ENABLE_ADDITIONAL_QUERY_MODES,
57
- 'false',
58
+ 'true',
58
59
  ),
60
+ [QUERY_USE_MULTI_SCHEMA_KEY]: readSavedSettingsValue(QUERY_USE_MULTI_SCHEMA_KEY, 'false'),
59
61
  [DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS]: readSavedSettingsValue(
60
62
  DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS,
61
- 'false',
63
+ 'true',
62
64
  ),
63
65
  [SAVED_QUERIES_KEY]: readSavedSettingsValue(SAVED_QUERIES_KEY, '[]'),
64
66
  [TENANT_INITIAL_PAGE_KEY]: readSavedSettingsValue(
@@ -27,7 +27,7 @@ interface TNetNodeInfo {
27
27
  Port: number;
28
28
  }
29
29
 
30
- interface TNetNodePeerInfo {
30
+ export interface TNetNodePeerInfo {
31
31
  NodeId: number;
32
32
  PeerName: string;
33
33
  Connected: boolean;
@@ -26,6 +26,9 @@ export interface TNodeInfo {
26
26
  Tablets?: TTabletStateInfo[];
27
27
  }
28
28
 
29
+ /**
30
+ * source: https://github.com/ydb-platform/ydb/blob/main/ydb/core/protos/node_whiteboard.proto
31
+ */
29
32
  export interface TSystemStateInfo {
30
33
  /** uint64 */
31
34
  StartTime?: string;
@@ -62,6 +65,20 @@ export interface TSystemStateInfo {
62
65
  /** double */
63
66
  MaxDiskUsage?: number;
64
67
  Location?: TNodeLocation;
68
+
69
+ /**
70
+ * int64
71
+ *
72
+ * a positive value means the peer is ahead in time; a negative value means it's behind
73
+ */
74
+ MaxClockSkewWithPeerUs?: string;
75
+ MaxClockSkewPeerId?: number;
76
+
77
+ /** uint64 */
78
+ DisconnectTime?: string;
79
+
80
+ SharedCacheStats?: TNodeSharedCache;
81
+ TotalSessions?: number;
65
82
  }
66
83
 
67
84
  export interface TPoolStats {
@@ -97,6 +114,13 @@ interface TNodeLocation {
97
114
  Unit?: string;
98
115
  }
99
116
 
117
+ interface TNodeSharedCache {
118
+ /** uint64 */
119
+ UsedBytes: string;
120
+ /** uint64 */
121
+ LimitBytes: string;
122
+ }
123
+
100
124
  enum EConfigState {
101
125
  'Consistent' = 'Consistent',
102
126
  'Outdated' = 'Outdated',