ydb-embedded-ui 3.4.5 → 4.0.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 (56) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/components/InfoViewer/formatters/table.ts +6 -0
  3. package/dist/components/TruncatedQuery/TruncatedQuery.js +1 -1
  4. package/dist/components/TruncatedQuery/TruncatedQuery.scss +7 -3
  5. package/dist/containers/Node/{NodePages.js → NodePages.ts} +1 -1
  6. package/dist/containers/Tablet/TabletControls/TabletControls.tsx +2 -2
  7. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +11 -43
  8. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/TableInfo.tsx +19 -17
  9. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.ts +192 -37
  10. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.scss +20 -14
  11. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +49 -12
  12. package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +37 -18
  13. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +3 -3
  14. package/dist/containers/Tenant/QueryEditor/QueryDuration/QueryDuration.scss +8 -0
  15. package/dist/containers/Tenant/QueryEditor/QueryDuration/QueryDuration.tsx +21 -0
  16. package/dist/containers/Tenant/QueryEditor/QueryEditor.js +58 -82
  17. package/dist/containers/Tenant/QueryEditor/QueryEditor.scss +0 -33
  18. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/OldQueryEditorControls.tsx +83 -0
  19. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/QueryEditorControls.scss +57 -0
  20. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/QueryEditorControls.tsx +84 -0
  21. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/shared.ts +23 -0
  22. package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.js +12 -23
  23. package/dist/containers/Tenant/QueryEditor/QueryResult/QueryResult.js +4 -6
  24. package/dist/containers/Tenant/QueryEditor/i18n/en.json +3 -0
  25. package/dist/containers/Tenant/QueryEditor/i18n/index.ts +11 -0
  26. package/dist/containers/Tenant/QueryEditor/i18n/ru.json +3 -0
  27. package/dist/containers/UserSettings/UserSettings.tsx +30 -1
  28. package/dist/routes.ts +1 -1
  29. package/dist/services/api.d.ts +4 -3
  30. package/dist/services/api.js +5 -5
  31. package/dist/store/reducers/{executeQuery.js → executeQuery.ts} +48 -43
  32. package/dist/store/reducers/executeTopQueries.ts +5 -1
  33. package/dist/store/reducers/{explainQuery.js → explainQuery.ts} +44 -59
  34. package/dist/store/reducers/{olapStats.js → olapStats.ts} +8 -18
  35. package/dist/store/reducers/settings.js +19 -4
  36. package/dist/store/reducers/storage.js +5 -7
  37. package/dist/types/api/error.ts +14 -0
  38. package/dist/types/api/query.ts +227 -115
  39. package/dist/types/api/schema.ts +523 -3
  40. package/dist/types/common.ts +1 -0
  41. package/dist/types/store/executeQuery.ts +38 -0
  42. package/dist/types/store/explainQuery.ts +38 -0
  43. package/dist/types/store/olapStats.ts +14 -0
  44. package/dist/types/store/query.ts +23 -3
  45. package/dist/utils/constants.ts +2 -1
  46. package/dist/utils/error.ts +25 -0
  47. package/dist/utils/index.js +0 -49
  48. package/dist/utils/prepareQueryExplain.ts +7 -24
  49. package/dist/utils/query.test.ts +148 -213
  50. package/dist/utils/query.ts +68 -90
  51. package/dist/utils/timeParsers/formatDuration.ts +30 -12
  52. package/dist/utils/timeParsers/i18n/en.json +9 -5
  53. package/dist/utils/timeParsers/i18n/ru.json +9 -5
  54. package/dist/utils/timeParsers/parsers.ts +9 -0
  55. package/dist/utils/utils.js +1 -2
  56. package/package.json +1 -1
@@ -1,5 +1,7 @@
1
1
  import {useCallback, useEffect, useRef, useState} from 'react';
2
2
  import {useDispatch} from 'react-redux';
3
+ import {useHistory, useLocation} from 'react-router';
4
+ import qs from 'qs';
3
5
  import cn from 'bem-cn-lite';
4
6
 
5
7
  import DataTable, {Column, Settings} from '@gravity-ui/react-data-table';
@@ -21,13 +23,14 @@ import type {EPathType} from '../../../../types/api/schema';
21
23
  import type {ITopQueriesFilters} from '../../../../types/store/executeTopQueries';
22
24
  import type {IQueryResult} from '../../../../types/store/query';
23
25
 
24
- import {formatDateTime} from '../../../../utils';
26
+ import {formatDateTime, formatNumber} from '../../../../utils';
25
27
  import {DEFAULT_TABLE_SETTINGS, HOUR_IN_SECONDS} from '../../../../utils/constants';
26
28
  import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
27
29
  import {prepareQueryError} from '../../../../utils/query';
30
+ import routes, {createHref} from '../../../../routes';
28
31
 
29
32
  import {isColumnEntityType} from '../../utils/schema';
30
- import {TenantGeneralTabsIds} from '../../TenantPages';
33
+ import {TenantGeneralTabsIds, TenantTabsGroups} from '../../TenantPages';
31
34
 
32
35
  import i18n from './i18n';
33
36
  import './TopQueries.scss';
@@ -43,19 +46,41 @@ const MAX_QUERY_HEIGHT = 10;
43
46
  const COLUMNS: Column<KeyValueRow>[] = [
44
47
  {
45
48
  name: 'CPUTimeUs',
46
- width: 140,
47
- sortAccessor: (row) => Number(row['CPUTimeUs']),
49
+ sortAccessor: (row) => Number(row.CPUTimeUs),
50
+ align: DataTable.RIGHT,
48
51
  },
49
52
  {
50
53
  name: 'QueryText',
51
54
  width: 500,
52
55
  sortable: false,
53
- render: ({value}) => <TruncatedQuery value={value} maxQueryHeight={MAX_QUERY_HEIGHT} />,
56
+ render: ({row}) => (
57
+ <div className={b('query')}>
58
+ <TruncatedQuery value={row.QueryText} maxQueryHeight={MAX_QUERY_HEIGHT} />
59
+ </div>
60
+ ),
61
+ },
62
+ {
63
+ name: 'EndTime',
64
+ render: ({row}) => formatDateTime(new Date(row.EndTime as string).getTime()),
65
+ align: DataTable.RIGHT,
66
+ },
67
+ {
68
+ name: 'ReadRows',
69
+ render: ({row}) => formatNumber(row.ReadRows),
70
+ sortAccessor: (row) => Number(row.ReadRows),
71
+ align: DataTable.RIGHT,
72
+ },
73
+ {
74
+ name: 'ReadBytes',
75
+ render: ({row}) => formatNumber(row.ReadBytes),
76
+ sortAccessor: (row) => Number(row.ReadBytes),
77
+ align: DataTable.RIGHT,
54
78
  },
55
79
  {
56
- name: 'IntervalEnd',
57
- width: 140,
58
- render: ({value}) => formatDateTime(new Date(value as string).getTime()),
80
+ name: 'UserSID',
81
+ render: ({row}) => <div className={b('user-sid')}>{row.UserSID || '–'}</div>,
82
+ sortAccessor: (row) => String(row.UserSID),
83
+ align: DataTable.LEFT,
59
84
  },
60
85
  ];
61
86
 
@@ -65,8 +90,10 @@ interface TopQueriesProps {
65
90
  type?: EPathType;
66
91
  }
67
92
 
68
- export const TopQueries = ({path, type, changeSchemaTab}: TopQueriesProps) => {
93
+ export const TopQueries = ({path, type}: TopQueriesProps) => {
69
94
  const dispatch = useDispatch();
95
+ const location = useLocation();
96
+ const history = useHistory();
70
97
 
71
98
  const {autorefresh} = useTypedSelector((state) => state.schema);
72
99
 
@@ -144,9 +171,19 @@ export const TopQueries = ({path, type, changeSchemaTab}: TopQueriesProps) => {
144
171
  const {QueryText: input} = row;
145
172
 
146
173
  dispatch(changeUserInput({input}));
147
- changeSchemaTab(TenantGeneralTabsIds.query);
174
+
175
+ const queryParams = qs.parse(location.search, {
176
+ ignoreQueryPrefix: true,
177
+ });
178
+
179
+ const queryPath = createHref(routes.tenant, undefined, {
180
+ ...queryParams,
181
+ [TenantTabsGroups.general]: TenantGeneralTabsIds.query,
182
+ });
183
+
184
+ history.push(queryPath);
148
185
  },
149
- [changeSchemaTab, dispatch],
186
+ [dispatch, history, location],
150
187
  );
151
188
 
152
189
  const handleTextSearchUpdate = (text: string) => {
@@ -179,7 +216,7 @@ export const TopQueries = ({path, type, changeSchemaTab}: TopQueriesProps) => {
179
216
  }
180
217
 
181
218
  return (
182
- <div className={b('result')}>
219
+ <div className={b('table')}>
183
220
  <DataTable
184
221
  columns={COLUMNS}
185
222
  data={data}
@@ -20,6 +20,7 @@ import {setCurrentSchemaPath, getSchema} from '../../../../store/reducers/schema
20
20
  import {EShardsWorkloadMode, IShardsWorkloadFilters} from '../../../../types/store/shardsWorkload';
21
21
 
22
22
  import type {EPathType} from '../../../../types/api/schema';
23
+ import type {CellValue, KeyValueRow} from '../../../../types/api/query';
23
24
 
24
25
  import {formatDateTime, formatNumber} from '../../../../utils';
25
26
  import {DEFAULT_TABLE_SETTINGS, HOUR_IN_SECONDS} from '../../../../utils/constants';
@@ -57,10 +58,17 @@ const tableColumnsNames = {
57
58
  IntervalEnd: 'IntervalEnd',
58
59
  };
59
60
 
60
- function prepareCPUWorkloadValue(value: string) {
61
+ function prepareCPUWorkloadValue(value: string | number) {
61
62
  return `${(Number(value) * 100).toFixed(2)}%`;
62
63
  }
63
64
 
65
+ function prepareDateTimeValue(value: CellValue) {
66
+ if (!value) {
67
+ return '–';
68
+ }
69
+ return formatDateTime(new Date(value).getTime());
70
+ }
71
+
64
72
  function stringToDataTableSortOrder(value: string): SortOrder[] | undefined {
65
73
  return value
66
74
  ? value.split(',').map((columnId) => ({
@@ -190,16 +198,17 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
190
198
  };
191
199
  };
192
200
 
193
- const columns: Column<any>[] = [
201
+ const columns: Column<KeyValueRow>[] = [
194
202
  {
195
203
  name: tableColumnsNames.Path,
196
- render: ({value: relativeNodePath}) => {
204
+ render: ({row}) => {
205
+ // row.Path - relative schema path
197
206
  return (
198
207
  <span
199
- onClick={onSchemaClick(tenantPath + relativeNodePath)}
208
+ onClick={onSchemaClick(tenantPath + row.Path)}
200
209
  className={bLink({view: 'normal'})}
201
210
  >
202
- {relativeNodePath as string}
211
+ {row.Path}
203
212
  </span>
204
213
  );
205
214
  },
@@ -207,25 +216,28 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
207
216
  },
208
217
  {
209
218
  name: tableColumnsNames.CPUCores,
210
- render: ({value}) => {
211
- return prepareCPUWorkloadValue(value as string);
219
+ render: ({row}) => {
220
+ return prepareCPUWorkloadValue(row.CPUCores || 0);
212
221
  },
213
222
  align: DataTable.RIGHT,
214
223
  },
215
224
  {
216
225
  name: tableColumnsNames.DataSize,
217
226
  header: 'DataSize (B)',
218
- render: ({value}) => {
219
- return formatNumber(value as number);
227
+ render: ({row}) => {
228
+ return formatNumber(row.DataSize);
220
229
  },
221
230
  align: DataTable.RIGHT,
222
231
  },
223
232
  {
224
233
  name: tableColumnsNames.TabletId,
225
- render: ({value}) => {
234
+ render: ({row}) => {
235
+ if (!row.TabletId) {
236
+ return '–';
237
+ }
226
238
  return (
227
- <InternalLink to={createHref(routes.tablet, {id: value})}>
228
- {value as string}
239
+ <InternalLink to={createHref(routes.tablet, {id: row.TabletId})}>
240
+ {row.TabletId}
229
241
  </InternalLink>
230
242
  );
231
243
  },
@@ -233,10 +245,13 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
233
245
  },
234
246
  {
235
247
  name: tableColumnsNames.NodeId,
236
- render: ({value: nodeId}) => {
248
+ render: ({row}) => {
249
+ if (!row.NodeId) {
250
+ return '–';
251
+ }
237
252
  return (
238
- <InternalLink to={getDefaultNodePath(nodeId as string)}>
239
- {nodeId as string}
253
+ <InternalLink to={getDefaultNodePath(row.NodeId)}>
254
+ {row.NodeId}
240
255
  </InternalLink>
241
256
  );
242
257
  },
@@ -245,7 +260,7 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
245
260
  },
246
261
  {
247
262
  name: tableColumnsNames.InFlightTxCount,
248
- render: ({value}) => formatNumber(value as number),
263
+ render: ({row}) => formatNumber(row.InFlightTxCount),
249
264
  align: DataTable.RIGHT,
250
265
  sortable: false,
251
266
  },
@@ -255,12 +270,16 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
255
270
  // after NodeId
256
271
  columns.splice(5, 0, {
257
272
  name: tableColumnsNames.PeakTime,
258
- render: ({value}) => formatDateTime(new Date(value as string).valueOf()),
273
+ render: ({row}) => {
274
+ return prepareDateTimeValue(row.PeakTime);
275
+ },
259
276
  sortable: false,
260
277
  });
261
278
  columns.push({
262
279
  name: tableColumnsNames.IntervalEnd,
263
- render: ({value}) => formatDateTime(new Date(value as string).getTime()),
280
+ render: ({row}) => {
281
+ return prepareDateTimeValue(row.IntervalEnd);
282
+ },
264
283
  });
265
284
  }
266
285
 
@@ -2,8 +2,9 @@ import React, {useRef, useState} from 'react';
2
2
  import cn from 'bem-cn-lite';
3
3
  import _ from 'lodash';
4
4
  import {Button, Popup} from '@gravity-ui/uikit';
5
+
5
6
  import TruncatedQuery from '../../../../components/TruncatedQuery/TruncatedQuery';
6
- import {useSelector} from 'react-redux';
7
+ import {useTypedSelector} from '../../../../utils/hooks';
7
8
 
8
9
  import './QueriesHistory.scss';
9
10
 
@@ -17,8 +18,7 @@ interface QueriesHistoryProps {
17
18
 
18
19
  function QueriesHistory(props: QueriesHistoryProps) {
19
20
  const [isHistoryVisible, setIsHistoryVisible] = useState(false);
20
- const history: string[] =
21
- useSelector((state: any) => state.executeQuery.history?.queries) ?? [];
21
+ const history = useTypedSelector((state) => state.executeQuery.history.queries) ?? [];
22
22
  const anchor = useRef(null);
23
23
 
24
24
  const onShowHistoryClick = () => {
@@ -0,0 +1,8 @@
1
+ .ydb-query-duration {
2
+ display: flex;
3
+ align-items: center;
4
+
5
+ margin-left: 10px;
6
+
7
+ color: var(--yc-color-text-complementary);
8
+ }
@@ -0,0 +1,21 @@
1
+ import block from 'bem-cn-lite';
2
+
3
+ import {formatDurationToShortTimeFormat, parseUsToMs} from '../../../../utils/timeParsers';
4
+
5
+ import './QueryDuration.scss';
6
+
7
+ interface QueryDurationProps {
8
+ duration?: string;
9
+ }
10
+
11
+ const b = block('ydb-query-duration');
12
+
13
+ export const QueryDuration = ({duration}: QueryDurationProps) => {
14
+ if (!duration) {
15
+ return null;
16
+ }
17
+
18
+ const parsedDuration = formatDurationToShortTimeFormat(parseUsToMs(duration), 1);
19
+
20
+ return <span className={b()}>{parsedDuration}</span>;
21
+ };
@@ -4,41 +4,36 @@ import {connect} from 'react-redux';
4
4
  import cn from 'bem-cn-lite';
5
5
  import _ from 'lodash';
6
6
  import MonacoEditor from 'react-monaco-editor';
7
- import {Button, DropdownMenu} from '@gravity-ui/uikit';
8
7
 
9
8
  import SplitPane from '../../../components/SplitPane';
10
9
  import {QueryResultTable} from '../../../components/QueryResultTable';
11
10
 
12
- import SaveQuery from './SaveQuery/SaveQuery';
13
11
  import SavedQueries from './SavedQueries/SavedQueries';
14
- import {Icon} from '../../../components/Icon';
15
12
  import QueryResult from './QueryResult/QueryResult';
16
13
  import QueryExplain from './QueryExplain/QueryExplain';
14
+ import {QueryEditorControls} from './QueryEditorControls/QueryEditorControls';
15
+ import {OldQueryEditorControls} from './QueryEditorControls/OldQueryEditorControls';
17
16
 
18
17
  import {
19
- sendQuery,
18
+ sendExecuteQuery,
20
19
  changeUserInput,
21
20
  saveQueryToHistory,
22
21
  goToPreviousQuery,
23
22
  goToNextQuery,
24
- selectRunAction,
25
- RUN_ACTIONS_VALUES,
26
23
  MONACO_HOT_KEY_ACTIONS,
27
24
  setMonacoHotKey,
28
25
  } from '../../../store/reducers/executeQuery';
29
26
  import {getExplainQuery, getExplainQueryAst} from '../../../store/reducers/explainQuery';
30
- import {getSettingValue, setSettingValue} from '../../../store/reducers/settings';
27
+ import {getParsedSettingValue, setSettingValue} from '../../../store/reducers/settings';
31
28
  import {
32
29
  DEFAULT_IS_QUERY_RESULT_COLLAPSED,
33
30
  DEFAULT_SIZE_RESULT_PANE_KEY,
34
31
  SAVED_QUERIES_KEY,
35
- QUERY_INITIAL_RUN_ACTION_KEY,
32
+ QUERY_INITIAL_MODE_KEY,
33
+ ENABLE_QUERY_MODES_FOR_EXPLAIN,
36
34
  } from '../../../utils/constants';
37
35
 
38
- import {parseJson} from '../../../utils/utils';
39
-
40
36
  import './QueryEditor.scss';
41
- import Divider from '../../../components/Divider/Divider';
42
37
  import QueriesHistory from './QueriesHistory/QueriesHistory';
43
38
  import {
44
39
  PaneVisibilityActionTypes,
@@ -47,11 +42,6 @@ import {
47
42
  import Preview from '../Preview/Preview';
48
43
  import {setShowPreview} from '../../../store/reducers/schema';
49
44
 
50
- export const RUN_ACTIONS = [
51
- {value: RUN_ACTIONS_VALUES.script, content: 'Run Script'},
52
- {value: RUN_ACTIONS_VALUES.scan, content: 'Run Scan'},
53
- ];
54
-
55
45
  const TABLE_SETTINGS = {
56
46
  sortable: false,
57
47
  };
@@ -73,7 +63,7 @@ const RESULT_TYPES = {
73
63
  const b = cn('query-editor');
74
64
 
75
65
  const propTypes = {
76
- sendQuery: PropTypes.func,
66
+ sendExecuteQuery: PropTypes.func,
77
67
  path: PropTypes.string,
78
68
  response: PropTypes.oneOfType([PropTypes.bool, PropTypes.array]),
79
69
  executeQuery: PropTypes.object,
@@ -81,6 +71,7 @@ const propTypes = {
81
71
  setMonacoHotKey: PropTypes.func,
82
72
  theme: PropTypes.string,
83
73
  type: PropTypes.string,
74
+ initialQueryMode: PropTypes.string,
84
75
  };
85
76
 
86
77
  const initialTenantCommonInfoState = {
@@ -92,6 +83,7 @@ function QueryEditor(props) {
92
83
  const [resultType, setResultType] = useState(RESULT_TYPES.EXECUTE);
93
84
 
94
85
  const [isResultLoaded, setIsResultLoaded] = useState(false);
86
+ const [queryMode, setQueryMode] = useState(props.initialQueryMode);
95
87
 
96
88
  const [resultVisibilityState, dispatchResultVisibilityState] = useReducer(
97
89
  paneVisibilityToggleReducerCreator(DEFAULT_IS_QUERY_RESULT_COLLAPSED),
@@ -155,7 +147,7 @@ function QueryEditor(props) {
155
147
  setMonacoHotKey(null);
156
148
  switch (monacoHotKey) {
157
149
  case MONACO_HOT_KEY_ACTIONS.sendQuery: {
158
- return handleSendClick();
150
+ return handleSendExecuteClick(queryMode);
159
151
  }
160
152
  case MONACO_HOT_KEY_ACTIONS.goPrev: {
161
153
  return handlePreviousHistoryClick();
@@ -246,17 +238,17 @@ function QueryEditor(props) {
246
238
  props.changeUserInput({input: newValue});
247
239
  };
248
240
 
249
- const handleSendClick = () => {
241
+ const handleSendExecuteClick = (mode) => {
250
242
  const {
251
243
  path,
252
- executeQuery: {input, history, runAction},
253
- sendQuery,
244
+ executeQuery: {input, history},
245
+ sendExecuteQuery,
254
246
  saveQueryToHistory,
255
247
  setShowPreview,
256
248
  } = props;
257
249
 
258
250
  setResultType(RESULT_TYPES.EXECUTE);
259
- sendQuery({query: input, database: path, action: runAction});
251
+ sendExecuteQuery({query: input, database: path, mode});
260
252
  setIsResultLoaded(true);
261
253
  setShowPreview(false);
262
254
 
@@ -267,15 +259,20 @@ function QueryEditor(props) {
267
259
  dispatchResultVisibilityState(PaneVisibilityActionTypes.triggerExpand);
268
260
  };
269
261
 
270
- const handleGetExplainQueryClick = () => {
262
+ const handleGetExplainQueryClick = (mode) => {
271
263
  const {
272
264
  path,
273
265
  executeQuery: {input},
274
266
  getExplainQuery,
275
267
  setShowPreview,
276
268
  } = props;
269
+
277
270
  setResultType(RESULT_TYPES.EXPLAIN);
278
- getExplainQuery({query: input, database: path});
271
+ getExplainQuery({
272
+ query: input,
273
+ database: path,
274
+ mode: mode,
275
+ });
279
276
  setIsResultLoaded(true);
280
277
  setShowPreview(false);
281
278
  dispatchResultVisibilityState(PaneVisibilityActionTypes.triggerExpand);
@@ -513,64 +510,42 @@ function QueryEditor(props) {
513
510
  setSettingValue(SAVED_QUERIES_KEY, JSON.stringify(newSavedQueries));
514
511
  };
515
512
 
516
- const renderControls = () => {
517
- const {executeQuery, explainQuery, savedQueries, selectRunAction, setSettingValue} = props;
518
- const {runAction} = executeQuery;
519
- const runIsDisabled = !executeQuery.input || executeQuery.loading;
520
- const runText = _.find(RUN_ACTIONS, {value: runAction}).content;
521
-
522
- const menuItems = RUN_ACTIONS.map((action) => {
523
- return {
524
- text: action.content,
525
- action: () => {
526
- selectRunAction(action.value);
527
- setSettingValue(QUERY_INITIAL_RUN_ACTION_KEY, action.value);
528
- },
529
- };
530
- });
513
+ const onUpdateQueryMode = (mode) => {
514
+ setQueryMode(mode);
515
+ props.setSettingValue(QUERY_INITIAL_MODE_KEY, mode);
516
+ };
531
517
 
532
- return (
533
- <div className={b('controls')}>
534
- <div className={b('control-run')}>
535
- <Button
536
- onClick={handleSendClick}
537
- view="action"
538
- pin="round-brick"
539
- disabled={runIsDisabled}
540
- loading={executeQuery.loading}
541
- >
542
- <Icon name="startPlay" viewBox="0 0 16 16" width={16} height={16} />
543
- {runText}
544
- </Button>
545
- <DropdownMenu
546
- items={menuItems}
547
- switcher={
548
- <Button
549
- view="action"
550
- pin="brick-round"
551
- disabled={runIsDisabled}
552
- loading={executeQuery.loading}
553
- className={b('select-query-action')}
554
- >
555
- <Icon name="chevron-down" width={16} height={16} />
556
- </Button>
557
- }
558
- />
559
- </div>
560
- <Button
561
- onClick={handleGetExplainQueryClick}
562
- disabled={!executeQuery.input}
563
- loading={explainQuery.loading}
564
- >
565
- Explain
566
- </Button>
567
- <Divider />
568
- <SaveQuery
518
+ const renderControls = () => {
519
+ const {executeQuery, explainQuery, savedQueries, enableQueryModesForExplain} = props;
520
+
521
+ if (enableQueryModesForExplain) {
522
+ return (
523
+ <QueryEditorControls
524
+ onRunButtonClick={handleSendExecuteClick}
525
+ runIsLoading={executeQuery.loading}
526
+ onExplainButtonClick={handleGetExplainQueryClick}
527
+ explainIsLoading={explainQuery.loading}
528
+ onSaveQueryClick={onSaveQueryHandler}
569
529
  savedQueries={savedQueries}
570
- onSaveQuery={onSaveQueryHandler}
571
- saveButtonDisabled={runIsDisabled}
530
+ disabled={!executeQuery.input}
531
+ onUpdateQueryMode={onUpdateQueryMode}
532
+ queryMode={queryMode}
572
533
  />
573
- </div>
534
+ );
535
+ }
536
+
537
+ return (
538
+ <OldQueryEditorControls
539
+ onRunButtonClick={handleSendExecuteClick}
540
+ runIsLoading={executeQuery.loading}
541
+ onExplainButtonClick={handleGetExplainQueryClick}
542
+ explainIsLoading={explainQuery.loading}
543
+ onSaveQueryClick={onSaveQueryHandler}
544
+ savedQueries={savedQueries}
545
+ disabled={!executeQuery.input}
546
+ onUpdateQueryMode={onUpdateQueryMode}
547
+ queryMode={queryMode}
548
+ />
574
549
  );
575
550
  };
576
551
 
@@ -631,7 +606,9 @@ const mapStateToProps = (state) => {
631
606
  return {
632
607
  executeQuery: state.executeQuery,
633
608
  explainQuery: state.explainQuery,
634
- savedQueries: parseJson(getSettingValue(state, SAVED_QUERIES_KEY)),
609
+ savedQueries: getParsedSettingValue(state, SAVED_QUERIES_KEY),
610
+ initialQueryMode: getParsedSettingValue(state, QUERY_INITIAL_MODE_KEY),
611
+ enableQueryModesForExplain: getParsedSettingValue(state, ENABLE_QUERY_MODES_FOR_EXPLAIN),
635
612
  showPreview: state.schema.showPreview,
636
613
  currentSchema: state.schema.currentSchema,
637
614
  monacoHotKey: state.executeQuery?.monacoHotKey,
@@ -639,7 +616,7 @@ const mapStateToProps = (state) => {
639
616
  };
640
617
 
641
618
  const mapDispatchToProps = {
642
- sendQuery,
619
+ sendExecuteQuery,
643
620
  changeUserInput,
644
621
  saveQueryToHistory,
645
622
  goToPreviousQuery,
@@ -647,7 +624,6 @@ const mapDispatchToProps = {
647
624
  getExplainQuery,
648
625
  getExplainQueryAst,
649
626
  setSettingValue,
650
- selectRunAction,
651
627
  setShowPreview,
652
628
  setMonacoHotKey,
653
629
  };
@@ -54,35 +54,6 @@
54
54
  align-items: center;
55
55
  }
56
56
 
57
- &__controls {
58
- display: flex;
59
- flex: 0 0 40px;
60
- align-items: flex-end;
61
-
62
- min-height: 40px;
63
- padding: 5px 20px;
64
-
65
- border-top: 1px solid var(--yc-color-line-generic);
66
- border-bottom: 1px solid var(--yc-color-line-generic);
67
- background-color: var(--yc-color-base-background);
68
- gap: 12px;
69
- }
70
-
71
- &__control-run {
72
- display: flex;
73
- align-items: center;
74
- .yc-select__option-text {
75
- display: none;
76
- }
77
-
78
- .yc-button__text {
79
- display: flex;
80
- justify-content: center;
81
- align-items: center;
82
- gap: 8px;
83
- }
84
- }
85
-
86
57
  &__history-controls {
87
58
  display: flex;
88
59
  align-items: center;
@@ -93,8 +64,4 @@
93
64
 
94
65
  color: var(--yc-color-text-secondary);
95
66
  }
96
-
97
- &__select-query-action {
98
- margin-left: 2px;
99
- }
100
67
  }