ydb-embedded-ui 4.5.2 → 4.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/assets/icons/versions.svg +3 -0
  3. package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +7 -2
  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 +8 -4
  7. package/dist/containers/AsideNavigation/AsideNavigation.tsx +4 -50
  8. package/dist/containers/Cluster/Cluster.scss +7 -48
  9. package/dist/containers/Cluster/Cluster.tsx +129 -20
  10. package/dist/containers/Cluster/ClusterInfo/ClusterInfo.scss +34 -17
  11. package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +58 -92
  12. package/dist/containers/Cluster/ClusterInfoSkeleton/ClusterInfoSkeleton.scss +48 -0
  13. package/dist/containers/Cluster/ClusterInfoSkeleton/ClusterInfoSkeleton.tsx +34 -0
  14. package/dist/containers/Cluster/utils.tsx +45 -0
  15. package/dist/containers/Header/Header.scss +4 -19
  16. package/dist/containers/Header/Header.tsx +72 -46
  17. package/dist/containers/Header/breadcrumbs.ts +146 -0
  18. package/dist/containers/Node/Node.tsx +25 -29
  19. package/dist/containers/Node/NodePages.ts +10 -6
  20. package/dist/containers/Nodes/Nodes.tsx +0 -16
  21. package/dist/containers/Nodes/getNodesColumns.tsx +1 -1
  22. package/dist/containers/Storage/Storage.js +1 -11
  23. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +11 -3
  24. package/dist/containers/Tablet/Tablet.tsx +40 -4
  25. package/dist/containers/Tablet/TabletInfo/TabletInfo.tsx +2 -2
  26. package/dist/containers/TabletsFilters/TabletsFilters.js +15 -2
  27. package/dist/containers/Tenant/Diagnostics/Consumers/columns/columns.tsx +1 -1
  28. package/dist/containers/Tenant/Diagnostics/Describe/Describe.tsx +1 -1
  29. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +7 -0
  30. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +4 -4
  31. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +5 -3
  32. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +1 -1
  33. package/dist/containers/Tenant/Diagnostics/Overview/ChangefeedInfo/ChangefeedInfo.tsx +4 -6
  34. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +56 -53
  35. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +2 -1
  36. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +11 -13
  37. package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +1 -1
  38. package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +2 -2
  39. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +7 -3
  40. package/dist/containers/Tenant/Preview/Preview.js +1 -1
  41. package/dist/containers/Tenant/{QueryEditor/QueryResult/QueryResult.js → Query/ExecuteResult/ExecuteResult.js} +3 -5
  42. package/dist/containers/Tenant/{QueryEditor/QueryResult/QueryResult.scss → Query/ExecuteResult/ExecuteResult.scss} +1 -1
  43. package/dist/containers/Tenant/{QueryEditor/QueryExplain/QueryExplain.js → Query/ExplainResult/ExplainResult.js} +3 -5
  44. package/dist/containers/Tenant/{QueryEditor/QueryExplain/QueryExplain.scss → Query/ExplainResult/ExplainResult.scss} +1 -1
  45. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.scss +20 -0
  46. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.tsx +60 -0
  47. package/dist/containers/Tenant/Query/Query.scss +16 -0
  48. package/dist/containers/Tenant/Query/Query.tsx +73 -0
  49. package/dist/containers/Tenant/{QueryEditor → Query/QueryEditor}/QueryEditor.js +43 -100
  50. package/dist/containers/Tenant/{QueryEditor → Query/QueryEditor}/QueryEditor.scss +7 -23
  51. package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/OldQueryEditorControls.tsx +10 -3
  52. package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/QueryEditorControls.scss +1 -4
  53. package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/QueryEditorControls.tsx +8 -1
  54. package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/shared.ts +1 -6
  55. package/dist/containers/Tenant/Query/QueryTabs/QueryTabs.tsx +59 -0
  56. package/dist/containers/Tenant/{QueryEditor → Query}/SaveQuery/SaveQuery.js +5 -5
  57. package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.scss +55 -0
  58. package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.tsx +150 -0
  59. package/dist/containers/Tenant/Query/i18n/en.json +12 -0
  60. package/dist/containers/Tenant/Query/i18n/ru.json +12 -0
  61. package/dist/containers/Tenant/Query/utils/getPreparedResult.ts +30 -0
  62. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +1 -1
  63. package/dist/containers/Tenant/Tenant.tsx +4 -25
  64. package/dist/containers/Tenant/TenantPages.tsx +8 -2
  65. package/dist/containers/Tenant/utils/constants.ts +10 -0
  66. package/dist/containers/Tenant/utils/schemaActions.ts +8 -3
  67. package/dist/containers/Tenants/Tenants.js +39 -37
  68. package/dist/containers/Tenants/Tenants.scss +2 -4
  69. package/dist/containers/UserSettings/i18n/en.json +2 -2
  70. package/dist/containers/UserSettings/i18n/ru.json +2 -2
  71. package/dist/containers/UserSettings/settings.ts +4 -4
  72. package/dist/containers/Versions/Versions.scss +0 -4
  73. package/dist/containers/Versions/Versions.tsx +74 -66
  74. package/dist/routes.ts +8 -6
  75. package/dist/services/api.ts +15 -7
  76. package/dist/store/reducers/clusterNodes/clusterNodes.tsx +4 -0
  77. package/dist/store/reducers/executeQuery.ts +1 -1
  78. package/dist/store/reducers/header/header.ts +31 -0
  79. package/dist/store/reducers/header/types.ts +54 -0
  80. package/dist/store/reducers/index.ts +4 -2
  81. package/dist/store/reducers/node/types.ts +2 -0
  82. package/dist/store/reducers/overview/overview.ts +109 -0
  83. package/dist/store/reducers/overview/types.ts +24 -0
  84. package/dist/store/reducers/{schema.ts → schema/schema.ts} +24 -50
  85. package/dist/{types/store/schema.ts → store/reducers/schema/types.ts} +16 -15
  86. package/dist/store/reducers/settings/settings.ts +5 -3
  87. package/dist/store/reducers/tablet.ts +18 -1
  88. package/dist/store/reducers/tenant/constants.ts +6 -0
  89. package/dist/store/reducers/tenant/tenant.ts +21 -2
  90. package/dist/store/reducers/tenant/types.ts +9 -2
  91. package/dist/store/reducers/topic.ts +1 -1
  92. package/dist/store/state-url-mapping.js +4 -1
  93. package/dist/types/api/query.ts +78 -44
  94. package/dist/types/store/explainQuery.ts +2 -2
  95. package/dist/types/store/query.ts +9 -2
  96. package/dist/types/store/tablet.ts +7 -4
  97. package/dist/utils/constants.ts +5 -1
  98. package/dist/utils/nodes.ts +1 -1
  99. package/dist/utils/query.ts +3 -3
  100. package/package.json +2 -1
  101. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.scss +0 -85
  102. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +0 -95
  103. package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.js +0 -161
  104. package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.scss +0 -93
  105. package/dist/containers/Tenant/QueryEditor/i18n/en.json +0 -3
  106. package/dist/containers/Tenant/QueryEditor/i18n/ru.json +0 -3
  107. package/dist/store/reducers/header.ts +0 -26
  108. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/Issues.scss +0 -0
  109. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/Issues.tsx +0 -0
  110. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/models.ts +0 -0
  111. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryDuration/QueryDuration.scss +0 -0
  112. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryDuration/QueryDuration.tsx +0 -0
  113. /package/dist/containers/Tenant/{QueryEditor → Query}/SaveQuery/SaveQuery.scss +0 -0
  114. /package/dist/containers/Tenant/{QueryEditor → Query}/i18n/index.ts +0 -0
@@ -1,85 +1,88 @@
1
1
  import {ReactNode, useCallback} from 'react';
2
- import {shallowEqual, useDispatch, useSelector} from 'react-redux';
2
+ import {shallowEqual, useDispatch} from 'react-redux';
3
3
 
4
4
  import {Loader} from '../../../../components/Loader';
5
-
6
- //@ts-ignore
7
5
  import {TableIndexInfo} from '../../../../components/InfoViewer/schemaInfo';
8
6
  import {ResponseError} from '../../../../components/Errors/ResponseError';
9
7
 
10
- import {TopicInfo} from './TopicInfo';
11
- import {ChangefeedInfo} from './ChangefeedInfo';
12
- import {TableInfo} from './TableInfo';
13
-
14
8
  import {EPathType} from '../../../../types/api/schema';
9
+ import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
10
+ import {selectSchemaMergedChildrenPaths} from '../../../../store/reducers/schema/schema';
11
+ import {getTopic} from '../../../../store/reducers/topic';
12
+ import {
13
+ getOlapStats,
14
+ resetLoadingState as resetOlapLoadingState,
15
+ } from '../../../../store/reducers/olapStats';
16
+ import {
17
+ getOverview,
18
+ getOverviewBatched,
19
+ setCurrentOverviewPath,
20
+ setDataWasNotLoaded,
21
+ } from '../../../../store/reducers/overview/overview';
22
+
15
23
  import {
16
24
  isEntityWithMergedImplementation,
17
25
  isColumnEntityType,
18
26
  isTableType,
19
27
  isPathTypeWithTopic,
20
28
  } from '../../utils/schema';
21
- //@ts-ignore
22
- import {
23
- getSchema,
24
- getSchemaBatched,
25
- resetLoadingState,
26
- selectSchemaMergedChildrenPaths,
27
- } from '../../../../store/reducers/schema';
28
- import {getTopic} from '../../../../store/reducers/topic';
29
- //@ts-ignore
30
- import {
31
- getOlapStats,
32
- resetLoadingState as resetOlapLoadingState,
33
- } from '../../../../store/reducers/olapStats';
34
- import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
29
+
30
+ import {TopicInfo} from './TopicInfo';
31
+ import {ChangefeedInfo} from './ChangefeedInfo';
32
+ import {TableInfo} from './TableInfo';
35
33
 
36
34
  interface OverviewProps {
37
35
  type?: EPathType;
38
- className?: string;
39
36
  tenantName?: string;
40
37
  }
41
38
 
42
- function Overview({type, tenantName, className}: OverviewProps) {
39
+ function Overview({type, tenantName}: OverviewProps) {
43
40
  const dispatch = useDispatch();
44
41
 
42
+ const {autorefresh, currentSchemaPath} = useTypedSelector((state) => state.schema);
45
43
  const {
46
- currentSchema: currentItem = {},
47
- loading: schemaLoading,
48
- wasLoaded,
49
- autorefresh,
50
- currentSchemaPath,
51
- error,
52
- } = useSelector((state: any) => state.schema);
53
-
54
- const {data: {result: olapStats} = {result: undefined}, loading: olapStatsLoading} =
55
- useTypedSelector((state) => state.olapStats);
56
-
57
- const loading = schemaLoading || olapStatsLoading;
44
+ data,
45
+ additionalData,
46
+ loading: overviewLoading,
47
+ wasLoaded: overviewWasLoaded,
48
+ error: overviewError,
49
+ } = useTypedSelector((state) => state.overview);
50
+ const {
51
+ data: {result: olapStats} = {result: undefined},
52
+ loading: olapStatsLoading,
53
+ wasLoaded: olapStatsWasLoaded,
54
+ } = useTypedSelector((state) => state.olapStats);
58
55
 
59
56
  const isEntityWithMergedImpl = isEntityWithMergedImplementation(type);
60
57
 
61
- // There is a circular dependency here. Fetch data depends on children paths
62
- // When data in store updated on fetch request,
63
- // new object is set there, so source children array is updated
64
- // This updates selector, the selector returns a new array, and data is fetched again
65
- // To prevent it, shallowEqual, which compares array content, was added
58
+ // shalloEqual prevents rerenders when new schema data is loaded
66
59
  const mergedChildrenPaths = useTypedSelector(
67
60
  (state) => selectSchemaMergedChildrenPaths(state, currentSchemaPath, type),
68
61
  shallowEqual,
69
62
  );
70
63
 
64
+ const entityLoading =
65
+ (overviewLoading && !overviewWasLoaded) || (olapStatsLoading && !olapStatsWasLoaded);
66
+ const entityNotReady = isEntityWithMergedImpl && !mergedChildrenPaths;
67
+
71
68
  const fetchData = useCallback(
72
69
  (isBackground: boolean) => {
73
- if (!isBackground) {
74
- dispatch(resetLoadingState());
70
+ const schemaPath = currentSchemaPath || tenantName;
71
+
72
+ if (!schemaPath) {
73
+ return;
75
74
  }
76
75
 
77
- const schemaPath = currentSchemaPath || tenantName;
76
+ dispatch(setCurrentOverviewPath(schemaPath));
77
+
78
+ if (!isBackground) {
79
+ dispatch(setDataWasNotLoaded());
80
+ }
78
81
 
79
82
  if (!isEntityWithMergedImpl) {
80
- dispatch(getSchema({path: schemaPath}));
83
+ dispatch(getOverview({path: schemaPath}));
81
84
  } else if (mergedChildrenPaths) {
82
- dispatch(getSchemaBatched([schemaPath, ...mergedChildrenPaths]));
85
+ dispatch(getOverviewBatched([schemaPath, ...mergedChildrenPaths]));
83
86
  }
84
87
 
85
88
  if (isTableType(type) && isColumnEntityType(type)) {
@@ -113,32 +116,32 @@ function Overview({type, tenantName, className}: OverviewProps) {
113
116
  [EPathType.EPathTypeDir]: undefined,
114
117
  [EPathType.EPathTypeTable]: undefined,
115
118
  [EPathType.EPathTypeSubDomain]: undefined,
116
- [EPathType.EPathTypeTableIndex]: () => <TableIndexInfo data={currentItem} />,
119
+ [EPathType.EPathTypeTableIndex]: () => <TableIndexInfo data={data} />,
117
120
  [EPathType.EPathTypeExtSubDomain]: undefined,
118
121
  [EPathType.EPathTypeColumnStore]: undefined,
119
122
  [EPathType.EPathTypeColumnTable]: undefined,
120
123
  [EPathType.EPathTypeCdcStream]: () => (
121
- <ChangefeedInfo data={currentItem} childrenPaths={mergedChildrenPaths} />
124
+ <ChangefeedInfo data={data} topic={additionalData?.[0]} />
122
125
  ),
123
- [EPathType.EPathTypePersQueueGroup]: () => <TopicInfo data={currentItem} />,
126
+ [EPathType.EPathTypePersQueueGroup]: () => <TopicInfo data={data} />,
124
127
  };
125
128
 
126
129
  return (
127
130
  (type && pathTypeToComponent[type]?.()) || (
128
- <TableInfo data={currentItem} type={type} olapStats={olapStats} />
131
+ <TableInfo data={data} type={type} olapStats={olapStats} />
129
132
  )
130
133
  );
131
134
  };
132
135
 
133
- if ((loading && !wasLoaded) || (isEntityWithMergedImpl && !mergedChildrenPaths)) {
136
+ if (entityLoading || entityNotReady) {
134
137
  return <Loader size="m" />;
135
138
  }
136
139
 
137
- if (error) {
138
- return <ResponseError error={error} />;
140
+ if (overviewError) {
141
+ return <ResponseError error={overviewError} />;
139
142
  }
140
143
 
141
- return <div className={className}>{renderContent()}</div>;
144
+ return <div>{renderContent()}</div>;
142
145
  }
143
146
 
144
147
  export default Overview;
@@ -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
  />
@@ -16,7 +16,7 @@ import {
16
16
  setShardsState,
17
17
  setShardsQueryFilters,
18
18
  } from '../../../../store/reducers/shardsWorkload';
19
- import {setCurrentSchemaPath, getSchema} from '../../../../store/reducers/schema';
19
+ import {setCurrentSchemaPath, getSchema} from '../../../../store/reducers/schema/schema';
20
20
  import {EShardsWorkloadMode, IShardsWorkloadFilters} from '../../../../types/store/shardsWorkload';
21
21
 
22
22
  import type {EPathType} from '../../../../types/api/schema';
@@ -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 (
@@ -46,9 +46,12 @@ import {
46
46
  paneVisibilityToggleReducerCreator,
47
47
  PaneVisibilityToggleButtons,
48
48
  } from '../utils/paneVisibilityToggleHelpers';
49
- import {setShowPreview} from '../../../store/reducers/schema';
50
- import {setTopLevelTab} from '../../../store/reducers/tenant/tenant';
51
- import {TENANT_GENERAL_TABS_IDS} from '../../../store/reducers/tenant/constants';
49
+ import {setShowPreview} from '../../../store/reducers/schema/schema';
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 = () => {
@@ -15,7 +15,7 @@ import {prepareQueryError} from '../../../utils/query';
15
15
  import {isTableType} from '../utils/schema';
16
16
  import {AutoFetcher} from '../../../utils/autofetcher';
17
17
  import EnableFullscreenButton from '../../../components/EnableFullscreenButton/EnableFullscreenButton';
18
- import {setShowPreview} from '../../../store/reducers/schema';
18
+ import {setShowPreview} from '../../../store/reducers/schema/schema';
19
19
 
20
20
  import './Preview.scss';
21
21
 
@@ -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
+ }
@@ -0,0 +1,73 @@
1
+ import {useDispatch} from 'react-redux';
2
+ import block from 'bem-cn-lite';
3
+
4
+ import type {EPathType} from '../../../types/api/schema';
5
+ import type {SavedQuery} from '../../../types/store/query';
6
+ import {changeUserInput} from '../../../store/reducers/executeQuery';
7
+ import {TENANT_QUERY_TABS_ID} from '../../../store/reducers/tenant/constants';
8
+ import {useSetting, useTypedSelector} from '../../../utils/hooks';
9
+ import {SAVED_QUERIES_KEY} from '../../../utils/constants';
10
+
11
+ import {QueryTabs} from './QueryTabs/QueryTabs';
12
+ import {SavedQueries} from './SavedQueries/SavedQueries';
13
+ import QueriesHistory from './QueriesHistory/QueriesHistory';
14
+ import QueryEditor from './QueryEditor/QueryEditor';
15
+
16
+ import './Query.scss';
17
+
18
+ const b = block('ydb-query');
19
+
20
+ interface QueryProps {
21
+ theme: string;
22
+ path?: string;
23
+ type?: EPathType;
24
+ }
25
+
26
+ export const Query = (props: QueryProps) => {
27
+ const dispatch = useDispatch();
28
+
29
+ const {queryTab = TENANT_QUERY_TABS_ID.newQuery} = useTypedSelector((state) => state.tenant);
30
+
31
+ const [savedQueries, setSavedQueries] = useSetting<SavedQuery[]>(SAVED_QUERIES_KEY, []);
32
+
33
+ const handleDeleteQuery = (queryName: string) => {
34
+ const newSavedQueries = savedQueries.filter(
35
+ (el) => el.name.toLowerCase() !== queryName.toLowerCase(),
36
+ );
37
+ setSavedQueries(newSavedQueries);
38
+ };
39
+
40
+ const handleUserInputChange = (value: {input: string}) => {
41
+ dispatch(changeUserInput(value));
42
+ };
43
+
44
+ const renderContent = () => {
45
+ switch (queryTab) {
46
+ case TENANT_QUERY_TABS_ID.newQuery: {
47
+ return <QueryEditor changeUserInput={handleUserInputChange} {...props} />;
48
+ }
49
+ case TENANT_QUERY_TABS_ID.history: {
50
+ return <QueriesHistory changeUserInput={handleUserInputChange} />;
51
+ }
52
+ case TENANT_QUERY_TABS_ID.saved: {
53
+ return (
54
+ <SavedQueries
55
+ changeUserInput={handleUserInputChange}
56
+ savedQueries={savedQueries}
57
+ onDeleteQuery={handleDeleteQuery}
58
+ />
59
+ );
60
+ }
61
+ default: {
62
+ return null;
63
+ }
64
+ }
65
+ };
66
+
67
+ return (
68
+ <div className={b()}>
69
+ <QueryTabs className={b('tabs')} activeTab={queryTab} />
70
+ <div className={b('content')}>{renderContent()}</div>
71
+ </div>
72
+ );
73
+ };