ydb-embedded-ui 4.6.0 → 4.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/assets/icons/versions.svg +3 -0
  3. package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +6 -1
  4. package/dist/components/Tablet/Tablet.tsx +17 -3
  5. package/dist/components/TabletsStatistic/TabletsStatistic.tsx +23 -16
  6. package/dist/containers/App/Content.js +5 -2
  7. package/dist/containers/Cluster/Cluster.tsx +6 -13
  8. package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +3 -3
  9. package/dist/containers/Cluster/{utils.ts → utils.tsx} +11 -0
  10. package/dist/containers/Header/Header.scss +9 -0
  11. package/dist/containers/Header/Header.tsx +70 -14
  12. package/dist/containers/Header/breadcrumbs.ts +146 -0
  13. package/dist/containers/Node/Node.tsx +21 -27
  14. package/dist/containers/Node/NodePages.ts +10 -6
  15. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +11 -3
  16. package/dist/containers/Tablet/Tablet.tsx +35 -27
  17. package/dist/containers/Tablet/TabletInfo/TabletInfo.tsx +2 -2
  18. package/dist/containers/TabletsFilters/TabletsFilters.js +13 -15
  19. package/dist/containers/Tenant/Diagnostics/Consumers/columns/columns.tsx +1 -1
  20. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +5 -1
  21. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +1 -1
  22. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +5 -3
  23. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +1 -1
  24. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +2 -1
  25. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +11 -13
  26. package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +2 -2
  27. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +6 -2
  28. package/dist/containers/Tenant/{QueryEditor/QueryResult/QueryResult.js → Query/ExecuteResult/ExecuteResult.js} +3 -5
  29. package/dist/containers/Tenant/{QueryEditor/QueryResult/QueryResult.scss → Query/ExecuteResult/ExecuteResult.scss} +1 -1
  30. package/dist/containers/Tenant/{QueryEditor/QueryExplain/QueryExplain.js → Query/ExplainResult/ExplainResult.js} +3 -5
  31. package/dist/containers/Tenant/{QueryEditor/QueryExplain/QueryExplain.scss → Query/ExplainResult/ExplainResult.scss} +1 -1
  32. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.scss +20 -0
  33. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.tsx +60 -0
  34. package/dist/containers/Tenant/Query/Query.scss +16 -0
  35. package/dist/containers/Tenant/Query/Query.tsx +73 -0
  36. package/dist/containers/Tenant/{QueryEditor → Query/QueryEditor}/QueryEditor.js +26 -87
  37. package/dist/containers/Tenant/{QueryEditor → Query/QueryEditor}/QueryEditor.scss +7 -23
  38. package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/QueryEditorControls.scss +1 -4
  39. package/dist/containers/Tenant/Query/QueryTabs/QueryTabs.tsx +59 -0
  40. package/dist/containers/Tenant/{QueryEditor → Query}/SaveQuery/SaveQuery.js +5 -5
  41. package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.scss +55 -0
  42. package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.tsx +150 -0
  43. package/dist/containers/Tenant/Query/i18n/en.json +12 -0
  44. package/dist/containers/Tenant/Query/i18n/ru.json +12 -0
  45. package/dist/containers/Tenant/Query/utils/getPreparedResult.ts +30 -0
  46. package/dist/containers/Tenant/Tenant.tsx +2 -18
  47. package/dist/containers/Tenant/TenantPages.tsx +8 -2
  48. package/dist/containers/Tenant/utils/constants.ts +10 -0
  49. package/dist/containers/Tenant/utils/schemaActions.ts +7 -2
  50. package/dist/containers/Tenants/Tenants.js +21 -9
  51. package/dist/routes.ts +10 -1
  52. package/dist/services/api.ts +9 -5
  53. package/dist/store/reducers/executeQuery.ts +1 -1
  54. package/dist/store/reducers/header/header.ts +31 -0
  55. package/dist/store/reducers/header/types.ts +54 -0
  56. package/dist/store/reducers/index.ts +1 -1
  57. package/dist/store/reducers/node/types.ts +2 -0
  58. package/dist/store/reducers/settings/settings.ts +1 -1
  59. package/dist/store/reducers/tablet.ts +18 -1
  60. package/dist/store/reducers/tenant/constants.ts +6 -0
  61. package/dist/store/reducers/tenant/tenant.ts +21 -2
  62. package/dist/store/reducers/tenant/types.ts +9 -2
  63. package/dist/store/reducers/topic.ts +1 -1
  64. package/dist/store/state-url-mapping.js +4 -1
  65. package/dist/types/store/query.ts +5 -0
  66. package/dist/types/store/tablet.ts +7 -4
  67. package/dist/utils/constants.ts +2 -0
  68. package/package.json +2 -1
  69. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.scss +0 -85
  70. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +0 -95
  71. package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.js +0 -161
  72. package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.scss +0 -93
  73. package/dist/containers/Tenant/QueryEditor/i18n/en.json +0 -3
  74. package/dist/containers/Tenant/QueryEditor/i18n/ru.json +0 -3
  75. package/dist/store/reducers/header.ts +0 -26
  76. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/Issues.scss +0 -0
  77. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/Issues.tsx +0 -0
  78. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/models.ts +0 -0
  79. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryDuration/QueryDuration.scss +0 -0
  80. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryDuration/QueryDuration.tsx +0 -0
  81. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/OldQueryEditorControls.tsx +0 -0
  82. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/QueryEditorControls.tsx +0 -0
  83. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/shared.ts +0 -0
  84. /package/dist/containers/Tenant/{QueryEditor → Query}/SaveQuery/SaveQuery.scss +0 -0
  85. /package/dist/containers/Tenant/{QueryEditor → Query}/i18n/index.ts +0 -0
@@ -1,4 +1,4 @@
1
- import routes, {createHref} from '../../routes';
1
+ import routes, {Query, createHref} from '../../routes';
2
2
 
3
3
  export const STORAGE = 'storage';
4
4
  export const TABLETS = 'tablets';
@@ -21,9 +21,13 @@ export const NODE_PAGES = [
21
21
  },
22
22
  ];
23
23
 
24
- export function getDefaultNodePath(nodeId: string | number) {
25
- return createHref(routes.node, {
26
- id: nodeId,
27
- activeTab: OVERVIEW,
28
- });
24
+ export function getDefaultNodePath(nodeId: string | number, query: Query = {}) {
25
+ return createHref(
26
+ routes.node,
27
+ {
28
+ id: nodeId,
29
+ activeTab: OVERVIEW,
30
+ },
31
+ query,
32
+ );
29
33
  }
@@ -74,8 +74,8 @@ function setSortOrder(visibleEntities: keyof typeof VisibleEntities): SortOrder
74
74
  switch (visibleEntities) {
75
75
  case VisibleEntities.All: {
76
76
  return {
77
- columnId: TableColumnsIds.Missing,
78
- order: DataTable.DESCENDING,
77
+ columnId: TableColumnsIds.PoolName,
78
+ order: DataTable.ASCENDING,
79
79
  };
80
80
  }
81
81
  case VisibleEntities.Missing: {
@@ -87,7 +87,7 @@ function setSortOrder(visibleEntities: keyof typeof VisibleEntities): SortOrder
87
87
  case VisibleEntities.Space: {
88
88
  return {
89
89
  columnId: TableColumnsIds.UsedSpaceFlag,
90
- order: DataTable.ASCENDING,
90
+ order: DataTable.DESCENDING,
91
91
  };
92
92
  }
93
93
  default: {
@@ -295,6 +295,14 @@ function StorageGroups({
295
295
 
296
296
  let columns = allColumns;
297
297
 
298
+ if (visibleEntities === VisibleEntities.All) {
299
+ columns = allColumns.filter((col) => {
300
+ return (
301
+ col.name !== TableColumnsIds.Missing && col.name !== TableColumnsIds.UsedSpaceFlag
302
+ );
303
+ });
304
+ }
305
+
298
306
  if (visibleEntities === VisibleEntities.Space) {
299
307
  columns = allColumns.filter((col) => col.name !== TableColumnsIds.Missing);
300
308
 
@@ -1,16 +1,17 @@
1
1
  import {useCallback, useEffect, useRef} from 'react';
2
- import {useParams} from 'react-router';
2
+ import {useLocation, useParams} from 'react-router';
3
3
  import {useDispatch} from 'react-redux';
4
4
  import cn from 'bem-cn-lite';
5
5
  import {Link as ExternalLink} from '@gravity-ui/uikit';
6
6
 
7
7
  import {backend} from '../../store';
8
- import {getTablet, getTabletDescribe} from '../../store/reducers/tablet';
9
- import {setHeader} from '../../store/reducers/header';
10
- import routes, {createHref} from '../../routes';
8
+ import {getTablet, getTabletDescribe, clearTabletData} from '../../store/reducers/tablet';
9
+ import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
11
10
 
12
11
  import {useAutofetcher, useTypedSelector} from '../../utils/hooks';
12
+ import {DEVELOPER_UI} from '../../utils/constants';
13
13
  import '../../services/api';
14
+ import {parseQuery} from '../../routes';
14
15
 
15
16
  import EntityStatus from '../../components/EntityStatus/EntityStatus';
16
17
  import {ResponseError} from '../../components/Errors/ResponseError';
@@ -19,8 +20,6 @@ import {Icon} from '../../components/Icon';
19
20
  import {EmptyState} from '../../components/EmptyState';
20
21
  import {Loader} from '../../components/Loader';
21
22
 
22
- import {getClusterPath} from '../Cluster/utils';
23
-
24
23
  import {TabletTable} from './TabletTable';
25
24
  import {TabletInfo} from './TabletInfo';
26
25
  import {TabletControls} from './TabletControls';
@@ -35,6 +34,7 @@ export const Tablet = () => {
35
34
  const isFirstDataFetchRef = useRef(true);
36
35
 
37
36
  const dispatch = useDispatch();
37
+ const location = useLocation();
38
38
 
39
39
  const params = useParams<{id: string}>();
40
40
  const {id} = params;
@@ -48,6 +48,25 @@ export const Tablet = () => {
48
48
  error,
49
49
  } = useTypedSelector((state) => state.tablet);
50
50
 
51
+ const {
52
+ nodeId: queryNodeId,
53
+ type: queryType,
54
+ state: queryState,
55
+ tenantName: queryTenantName,
56
+ } = parseQuery(location);
57
+
58
+ const nodeId = tablet.NodeId?.toString() || queryNodeId?.toString();
59
+ const tabletState = tablet.State || queryState?.toString();
60
+ const tabletType = tablet.Type || queryType?.toString();
61
+ const tenantName = tenantPath || queryTenantName?.toString();
62
+
63
+ // NOTE: should be reviewed when migrating to React 18
64
+ useEffect(() => {
65
+ return () => {
66
+ dispatch(clearTabletData());
67
+ };
68
+ }, [dispatch]);
69
+
51
70
  useEffect(() => {
52
71
  if (isFirstDataFetchRef.current && tablet && tablet.TenantId) {
53
72
  dispatch(getTabletDescribe(tablet.TenantId));
@@ -63,26 +82,15 @@ export const Tablet = () => {
63
82
 
64
83
  useEffect(() => {
65
84
  dispatch(
66
- setHeader([
67
- {
68
- text: 'Cluster',
69
- link: getClusterPath(),
70
- },
71
- {
72
- text: 'Tablets',
73
- link: createHref(routes.tabletsFilters, undefined, {
74
- nodeIds: tablet.NodeId ? [tablet.NodeId] : [],
75
- state: tablet.State,
76
- type: tablet.Type,
77
- tenantPath,
78
- }),
79
- },
80
- {
81
- text: tablet.TabletId ?? 'Tablet',
82
- },
83
- ]),
85
+ setHeaderBreadcrumbs('tablet', {
86
+ nodeIds: nodeId ? [nodeId] : [],
87
+ state: tabletState,
88
+ type: tabletType,
89
+ tenantName,
90
+ tabletId: id,
91
+ }),
84
92
  );
85
- }, [dispatch, tenantPath, tablet]);
93
+ }, [dispatch, tenantName, id, nodeId, tabletState, tabletType]);
86
94
 
87
95
  const renderExternalLinks = (link: {name: string; path: string}, index: number) => {
88
96
  return (
@@ -114,7 +122,7 @@ export const Tablet = () => {
114
122
 
115
123
  const externalLinks = [
116
124
  {
117
- name: 'Internal viewer - tablet',
125
+ name: `${DEVELOPER_UI} - tablet`,
118
126
  path: `/tablets?TabletID=${TabletId}`,
119
127
  },
120
128
  ];
@@ -138,7 +146,7 @@ export const Tablet = () => {
138
146
  {Leader && <Tag text="Leader" type="blue" />}
139
147
  <span className={b('loader')}>{loading && <Loader size="s" />}</span>
140
148
  </div>
141
- <TabletInfo tablet={tablet} tenantPath={tenantPath} />
149
+ <TabletInfo tablet={tablet} tenantPath={tenantName} />
142
150
  <TabletControls tablet={tablet} fetchData={fetchData} />
143
151
  </div>
144
152
  <div className={b('rigth-pane')}>
@@ -12,7 +12,7 @@ import {b} from '../Tablet';
12
12
 
13
13
  interface TabletInfoProps {
14
14
  tablet: TTabletStateInfo;
15
- tenantPath: string;
15
+ tenantPath?: string;
16
16
  }
17
17
 
18
18
  export const TabletInfo = ({tablet, tenantPath}: TabletInfoProps) => {
@@ -30,7 +30,7 @@ export const TabletInfo = ({tablet, tenantPath}: TabletInfoProps) => {
30
30
  const hasHiveId = HiveId && HiveId !== '0';
31
31
  const hasUptime = State === ETabletState.Active;
32
32
 
33
- const tabletInfo: InfoViewerItem[] = [{label: 'Database', value: tenantPath}];
33
+ const tabletInfo: InfoViewerItem[] = [{label: 'Database', value: tenantPath || '-'}];
34
34
 
35
35
  if (hasHiveId) {
36
36
  tabletInfo.push({
@@ -11,7 +11,7 @@ import ReactList from 'react-list';
11
11
  import {Tablet} from '../../components/Tablet';
12
12
  import {AccessDenied} from '../../components/Errors/403';
13
13
 
14
- import {setHeader} from '../../store/reducers/header';
14
+ import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
15
15
  import {tabletColorToTabletState, tabletStates} from '../../utils/tablet';
16
16
  import {
17
17
  getTabletsInfo,
@@ -22,8 +22,6 @@ import {
22
22
  getTablets,
23
23
  } from '../../store/reducers/tabletsFilters';
24
24
 
25
- import {getClusterPath} from '../Cluster/utils';
26
-
27
25
  import './TabletsFilters.scss';
28
26
 
29
27
  const b = cn('tablets-filters');
@@ -76,7 +74,7 @@ class TabletsFilters extends React.Component {
76
74
  reloadDescriptor = -1;
77
75
 
78
76
  componentDidMount() {
79
- const {setStateFilter, setTypeFilter, setHeader} = this.props;
77
+ const {setStateFilter, setTypeFilter, setHeaderBreadcrumbs} = this.props;
80
78
 
81
79
  const queryParams = qs.parse(this.props.location.search, {
82
80
  ignoreQueryPrefix: true,
@@ -92,15 +90,9 @@ class TabletsFilters extends React.Component {
92
90
  this.makeRequest();
93
91
  });
94
92
 
95
- setHeader([
96
- {
97
- text: 'Cluster',
98
- link: getClusterPath(),
99
- },
100
- {
101
- text: 'Tablets'
102
- }
103
- ]);
93
+ setHeaderBreadcrumbs('tablets', {
94
+ tenantName: path,
95
+ });
104
96
  }
105
97
 
106
98
  componentDidUpdate(prevProps) {
@@ -155,7 +147,13 @@ class TabletsFilters extends React.Component {
155
147
  const {filteredTablets, size} = this.props;
156
148
 
157
149
  return (
158
- <Tablet tablet={filteredTablets[index]} key={key} size={size} className={b('tablet')} />
150
+ <Tablet
151
+ tablet={filteredTablets[index]}
152
+ tenantName={this.state.tenantPath}
153
+ key={key}
154
+ size={size}
155
+ className={b('tablet')}
156
+ />
159
157
  );
160
158
  };
161
159
 
@@ -340,7 +338,7 @@ const mapDispatchToProps = {
340
338
  clearWasLoadingFlag,
341
339
  setStateFilter,
342
340
  setTypeFilter,
343
- setHeader,
341
+ setHeaderBreadcrumbs,
344
342
  };
345
343
 
346
344
  export default connect(mapStateToProps, mapDispatchToProps)(TabletsFilters);
@@ -42,7 +42,7 @@ export const columns: Column<IPreparedConsumerData>[] = [
42
42
  <InternalLink
43
43
  to={createHref(routes.tenant, undefined, {
44
44
  ...queryParams,
45
- [TenantTabsGroups.generalTab]: TENANT_DIAGNOSTICS_TABS_IDS.partitions,
45
+ [TenantTabsGroups.diagnosticsTab]: TENANT_DIAGNOSTICS_TABS_IDS.partitions,
46
46
  selectedConsumer: row.name,
47
47
  })}
48
48
  >
@@ -3,15 +3,19 @@ $section-title-line-height: 24px;
3
3
 
4
4
  .kv-detailed-overview {
5
5
  display: flex;
6
- gap: 20px;
7
6
 
7
+ width: 100%;
8
8
  height: 100%;
9
+ gap: 20px;
9
10
 
10
11
  &__section {
11
12
  display: flex;
12
13
  overflow-x: hidden;
13
14
  flex: 0 0 calc(50% - 10px);
14
15
  flex-direction: column;
16
+
17
+ min-width: 300px;
18
+ height: max-content;
15
19
  }
16
20
 
17
21
  &__modal {
@@ -176,7 +176,7 @@ function Diagnostics(props: DiagnosticsProps) {
176
176
  wrapTo={({id}, node) => {
177
177
  const path = createHref(routes.tenant, undefined, {
178
178
  ...queryParams,
179
- [TenantTabsGroups.generalTab]: id,
179
+ [TenantTabsGroups.diagnosticsTab]: id,
180
180
  });
181
181
 
182
182
  return (
@@ -3,9 +3,11 @@
3
3
  @import '@gravity-ui/uikit/styles/mixins.scss';
4
4
 
5
5
  .healthcheck {
6
- // Since most of the inner containers have fixed width, we can set fixed width here as well
7
- // Thus we will get rid of unneeded layout shift when scrollbar appear
8
- min-width: 885px;
6
+ &_expanded {
7
+ // Since most of the inner containers have fixed width, we can set fixed width here as well
8
+ // Thus we will get rid of unneeded layout shift when scrollbar appear
9
+ min-width: 885px;
10
+ }
9
11
 
10
12
  &__details {
11
13
  padding: 25px 20px 20px;
@@ -99,5 +99,5 @@ export const Healthcheck = (props: HealthcheckProps) => {
99
99
  return <div className="error">{i18n('no-data')}</div>;
100
100
  };
101
101
 
102
- return <div className={b()}>{renderContent()}</div>;
102
+ return <div className={b({expanded: !preview})}>{renderContent()}</div>;
103
103
  };
@@ -105,6 +105,7 @@ class TenantOverview extends React.Component {
105
105
  PoolStats,
106
106
  StateStats = [],
107
107
  MemoryUsed,
108
+ Name,
108
109
  CoresUsed,
109
110
  StorageGroups,
110
111
  StorageAllocatedSize,
@@ -159,7 +160,7 @@ class TenantOverview extends React.Component {
159
160
  <div className={b('system-tablets')}>
160
161
  {SystemTablets &&
161
162
  SystemTablets.map((tablet, tabletIndex) => (
162
- <Tablet key={tabletIndex} tablet={tablet} />
163
+ <Tablet key={tabletIndex} tablet={tablet} tenantName={Name} />
163
164
  ))}
164
165
  </div>
165
166
  <div className={b('common-info')}>
@@ -4,7 +4,7 @@ import {useHistory, useLocation} from 'react-router';
4
4
  import qs from 'qs';
5
5
  import cn from 'bem-cn-lite';
6
6
 
7
- import DataTable, {Column, Settings} from '@gravity-ui/react-data-table';
7
+ import DataTable, {Column} from '@gravity-ui/react-data-table';
8
8
  import {Loader} from '@gravity-ui/uikit';
9
9
 
10
10
  import {DateRange, DateRangeValues} from '../../../../components/DateRange';
@@ -24,27 +24,24 @@ import type {ITopQueriesFilters} from '../../../../types/store/executeTopQueries
24
24
  import type {IQueryResult} from '../../../../types/store/query';
25
25
  import type {TenantGeneralTab} from '../../../../store/reducers/tenant/types';
26
26
 
27
- import {TENANT_GENERAL_TABS_IDS} from '../../../../store/reducers/tenant/constants';
27
+ import {
28
+ TENANT_GENERAL_TABS_IDS,
29
+ TENANT_QUERY_TABS_ID,
30
+ } from '../../../../store/reducers/tenant/constants';
28
31
  import {formatDateTime, formatNumber} from '../../../../utils';
29
- import {DEFAULT_TABLE_SETTINGS, HOUR_IN_SECONDS} from '../../../../utils/constants';
32
+ import {HOUR_IN_SECONDS} from '../../../../utils/constants';
30
33
  import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
31
34
  import {prepareQueryError} from '../../../../utils/query';
32
- import routes, {createHref} from '../../../../routes';
33
35
 
36
+ import {MAX_QUERY_HEIGHT, QUERY_TABLE_SETTINGS} from '../../utils/constants';
34
37
  import {isColumnEntityType} from '../../utils/schema';
35
- import {TenantTabsGroups} from '../../TenantPages';
38
+ import {TenantTabsGroups, getTenantPath} from '../../TenantPages';
36
39
 
37
40
  import i18n from './i18n';
38
41
  import './TopQueries.scss';
39
42
 
40
43
  const b = cn('kv-top-queries');
41
44
 
42
- const TABLE_SETTINGS: Settings = {
43
- ...DEFAULT_TABLE_SETTINGS,
44
- dynamicRenderType: 'variable',
45
- };
46
-
47
- const MAX_QUERY_HEIGHT = 10;
48
45
  const COLUMNS: Column<KeyValueRow>[] = [
49
46
  {
50
47
  name: 'CPUTimeUs',
@@ -178,9 +175,10 @@ export const TopQueries = ({path, type}: TopQueriesProps) => {
178
175
  ignoreQueryPrefix: true,
179
176
  });
180
177
 
181
- const queryPath = createHref(routes.tenant, undefined, {
178
+ const queryPath = getTenantPath({
182
179
  ...queryParams,
183
180
  [TenantTabsGroups.general]: TENANT_GENERAL_TABS_IDS.query,
181
+ [TenantTabsGroups.queryTab]: TENANT_QUERY_TABS_ID.newQuery,
184
182
  });
185
183
 
186
184
  history.push(queryPath);
@@ -222,7 +220,7 @@ export const TopQueries = ({path, type}: TopQueriesProps) => {
222
220
  <DataTable
223
221
  columns={COLUMNS}
224
222
  data={data}
225
- settings={TABLE_SETTINGS}
223
+ settings={QUERY_TABLE_SETTINGS}
226
224
  onRowClick={handleRowClick}
227
225
  theme="yandex-cloud"
228
226
  />
@@ -7,7 +7,7 @@ import {useThemeValue} from '@gravity-ui/uikit';
7
7
  import type {EPathType} from '../../../types/api/schema';
8
8
  import {TENANT_GENERAL_TABS_IDS} from '../../../store/reducers/tenant/constants';
9
9
 
10
- import QueryEditor from '../QueryEditor/QueryEditor';
10
+ import {Query} from '../Query/Query';
11
11
  import Diagnostics from '../Diagnostics/Diagnostics';
12
12
 
13
13
  import './ObjectGeneral.scss';
@@ -35,7 +35,7 @@ function ObjectGeneral(props: ObjectGeneralProps) {
35
35
  const {type, additionalTenantInfo, additionalNodesInfo} = props;
36
36
  switch (generalTab) {
37
37
  case TENANT_GENERAL_TABS_IDS.query: {
38
- return <QueryEditor path={tenantName as string} theme={theme} type={type} />;
38
+ return <Query path={tenantName as string} theme={theme} type={type} />;
39
39
  }
40
40
  default: {
41
41
  return (
@@ -47,8 +47,11 @@ import {
47
47
  PaneVisibilityToggleButtons,
48
48
  } from '../utils/paneVisibilityToggleHelpers';
49
49
  import {setShowPreview} from '../../../store/reducers/schema/schema';
50
- import {setTopLevelTab} from '../../../store/reducers/tenant/tenant';
51
- import {TENANT_GENERAL_TABS_IDS} from '../../../store/reducers/tenant/constants';
50
+ import {setQueryTab, setTopLevelTab} from '../../../store/reducers/tenant/tenant';
51
+ import {
52
+ TENANT_GENERAL_TABS_IDS,
53
+ TENANT_QUERY_TABS_ID,
54
+ } from '../../../store/reducers/tenant/constants';
52
55
 
53
56
  import './ObjectSummary.scss';
54
57
 
@@ -276,6 +279,7 @@ function ObjectSummary(props: ObjectSummaryProps) {
276
279
  const onOpenPreview = () => {
277
280
  dispatch(setShowPreview(true));
278
281
  dispatch(setTopLevelTab(TENANT_GENERAL_TABS_IDS.query));
282
+ dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
279
283
  };
280
284
 
281
285
  const renderCommonInfoControls = () => {
@@ -20,9 +20,9 @@ import {PaneVisibilityToggleButtons} from '../../utils/paneVisibilityToggleHelpe
20
20
  import ResultIssues from '../Issues/Issues';
21
21
  import {QueryDuration} from '../QueryDuration/QueryDuration';
22
22
 
23
- import './QueryResult.scss';
23
+ import './ExecuteResult.scss';
24
24
 
25
- const b = cn('kv-query-result');
25
+ const b = cn('ydb-query-execute-result');
26
26
 
27
27
  const resultOptionsIds = {
28
28
  result: 'result',
@@ -34,7 +34,7 @@ const resultOptions = [
34
34
  {value: resultOptionsIds.stats, content: 'Stats'},
35
35
  ];
36
36
 
37
- function QueryResult(props) {
37
+ export function ExecuteResult(props) {
38
38
  const [activeSection, setActiveSection] = useState(resultOptionsIds.result);
39
39
  const isFullscreen = useSelector((state) => state.fullscreen);
40
40
  const dispatch = useDispatch();
@@ -162,5 +162,3 @@ function QueryResult(props) {
162
162
  </React.Fragment>
163
163
  );
164
164
  }
165
-
166
- export default QueryResult;
@@ -1,6 +1,6 @@
1
1
  @import '../../../../styles/mixins.scss';
2
2
 
3
- .kv-query-result {
3
+ .ydb-query-execute-result {
4
4
  &__result {
5
5
  display: flex;
6
6
  overflow: auto;
@@ -21,9 +21,9 @@ import {LANGUAGE_S_EXPRESSION_ID} from '../../../../utils/monaco';
21
21
 
22
22
  import {PaneVisibilityToggleButtons} from '../../utils/paneVisibilityToggleHelpers';
23
23
 
24
- import './QueryExplain.scss';
24
+ import './ExplainResult.scss';
25
25
 
26
- const b = cn('kv-query-explain');
26
+ const b = cn('ydb-query-explain-result');
27
27
 
28
28
  const EDITOR_OPTIONS = {
29
29
  automaticLayout: true,
@@ -90,7 +90,7 @@ function GraphRoot(props) {
90
90
  return <div id="graphRoot" style={{height: '100vh'}} />;
91
91
  }
92
92
 
93
- function QueryExplain(props) {
93
+ export function ExplainResult(props) {
94
94
  const dispatch = useDispatch();
95
95
  const [activeOption, setActiveOption] = useState(ExplainOptionIds.schema);
96
96
 
@@ -287,5 +287,3 @@ function QueryExplain(props) {
287
287
  </React.Fragment>
288
288
  );
289
289
  }
290
-
291
- export default QueryExplain;
@@ -1,6 +1,6 @@
1
1
  @import '../../../../styles/mixins.scss';
2
2
 
3
- .kv-query-explain {
3
+ .ydb-query-explain-result {
4
4
  &__result {
5
5
  display: flex;
6
6
  overflow: auto;
@@ -0,0 +1,20 @@
1
+ @import '../../../../styles/mixins.scss';
2
+
3
+ .ydb-queries-history {
4
+ overflow: auto;
5
+
6
+ height: 100%;
7
+ padding: 0 16px;
8
+
9
+ @include flex-container();
10
+ @include table-styles;
11
+
12
+ &__query {
13
+ overflow: hidden;
14
+ flex-grow: 1;
15
+
16
+ cursor: pointer;
17
+ white-space: pre;
18
+ text-overflow: ellipsis;
19
+ }
20
+ }
@@ -0,0 +1,60 @@
1
+ import {useDispatch} from 'react-redux';
2
+ import block from 'bem-cn-lite';
3
+
4
+ import DataTable, {Column} from '@gravity-ui/react-data-table';
5
+
6
+ import TruncatedQuery from '../../../../components/TruncatedQuery/TruncatedQuery';
7
+ import {setQueryTab} from '../../../../store/reducers/tenant/tenant';
8
+ import {TENANT_QUERY_TABS_ID} from '../../../../store/reducers/tenant/constants';
9
+ import {useTypedSelector} from '../../../../utils/hooks';
10
+ import {MAX_QUERY_HEIGHT, QUERY_TABLE_SETTINGS} from '../../utils/constants';
11
+
12
+ import i18n from '../i18n';
13
+
14
+ import './QueriesHistory.scss';
15
+
16
+ const b = block('ydb-queries-history');
17
+
18
+ interface QueriesHistoryProps {
19
+ changeUserInput: (value: {input: string}) => void;
20
+ }
21
+
22
+ function QueriesHistory({changeUserInput}: QueriesHistoryProps) {
23
+ const dispatch = useDispatch();
24
+
25
+ const queriesHistory = useTypedSelector((state) => state.executeQuery.history.queries) ?? [];
26
+ const reversedHistory = [...queriesHistory].reverse();
27
+
28
+ const onQueryClick = (queryText: string) => {
29
+ changeUserInput({input: queryText});
30
+ dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
31
+ };
32
+
33
+ const columns: Column<string>[] = [
34
+ {
35
+ name: 'queryText',
36
+ header: 'Query Text',
37
+ render: ({row: query}) => (
38
+ <div className={b('query')}>
39
+ <TruncatedQuery value={query} maxQueryHeight={MAX_QUERY_HEIGHT} />
40
+ </div>
41
+ ),
42
+ sortable: false,
43
+ },
44
+ ];
45
+
46
+ return (
47
+ <div className={b()}>
48
+ <DataTable
49
+ theme="yandex-cloud"
50
+ columns={columns}
51
+ data={reversedHistory}
52
+ settings={QUERY_TABLE_SETTINGS}
53
+ emptyDataMessage={i18n('history.empty')}
54
+ onRowClick={(row) => onQueryClick(row)}
55
+ />
56
+ </div>
57
+ );
58
+ }
59
+
60
+ export default QueriesHistory;
@@ -0,0 +1,16 @@
1
+ @import '../../../styles/mixins.scss';
2
+
3
+ .ydb-query {
4
+ max-height: 100%;
5
+ @include flex-container();
6
+
7
+ &__tabs {
8
+ padding: 13px 20px 16px;
9
+ }
10
+
11
+ &__content {
12
+ overflow: hidden;
13
+
14
+ height: 100%;
15
+ }
16
+ }