ydb-embedded-ui 4.5.1 → 4.6.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 (75) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/components/FullNodeViewer/FullNodeViewer.js +1 -1
  3. package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +1 -1
  4. package/dist/components/PoolUsage/PoolUsage.scss +1 -1
  5. package/dist/components/PoolUsage/PoolUsage.tsx +50 -0
  6. package/dist/containers/App/Content.js +3 -2
  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 +136 -20
  10. package/dist/containers/Cluster/ClusterInfo/ClusterInfo.scss +34 -17
  11. package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +57 -91
  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.ts +34 -0
  15. package/dist/containers/Header/Header.scss +0 -24
  16. package/dist/containers/Header/Header.tsx +14 -44
  17. package/dist/containers/Node/Node.tsx +23 -21
  18. package/dist/containers/Node/NodeStructure/NodeStructure.tsx +19 -17
  19. package/dist/containers/Nodes/Nodes.tsx +0 -16
  20. package/dist/containers/Nodes/getNodesColumns.tsx +1 -1
  21. package/dist/containers/Storage/Storage.js +1 -11
  22. package/dist/containers/Tablet/Tablet.tsx +28 -0
  23. package/dist/containers/TabletsFilters/TabletsFilters.js +16 -1
  24. package/dist/containers/Tenant/Diagnostics/Describe/Describe.tsx +1 -1
  25. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +3 -0
  26. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +3 -3
  27. package/dist/containers/Tenant/Diagnostics/Network/Network.js +2 -2
  28. package/dist/containers/Tenant/Diagnostics/Overview/ChangefeedInfo/ChangefeedInfo.tsx +4 -6
  29. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +56 -53
  30. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +1 -1
  31. package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +1 -1
  32. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +1 -1
  33. package/dist/containers/Tenant/Preview/Preview.js +1 -1
  34. package/dist/containers/Tenant/QueryEditor/QueryEditor.js +26 -22
  35. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/OldQueryEditorControls.tsx +10 -3
  36. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/QueryEditorControls.tsx +8 -1
  37. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/shared.ts +1 -6
  38. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +1 -1
  39. package/dist/containers/Tenant/Tenant.tsx +8 -13
  40. package/dist/containers/Tenant/utils/schemaActions.ts +1 -1
  41. package/dist/containers/Tenants/Tenants.js +18 -28
  42. package/dist/containers/Tenants/Tenants.scss +2 -4
  43. package/dist/containers/UserSettings/i18n/en.json +2 -2
  44. package/dist/containers/UserSettings/i18n/ru.json +2 -2
  45. package/dist/containers/UserSettings/settings.ts +4 -4
  46. package/dist/containers/Versions/GroupedNodesTree/GroupedNodesTree.scss +1 -0
  47. package/dist/containers/Versions/NodesTable/NodesTable.tsx +2 -3
  48. package/dist/containers/Versions/Versions.scss +0 -4
  49. package/dist/containers/Versions/Versions.tsx +74 -66
  50. package/dist/routes.ts +0 -7
  51. package/dist/services/api.ts +8 -4
  52. package/dist/store/reducers/clusterNodes/clusterNodes.tsx +4 -0
  53. package/dist/store/reducers/index.ts +6 -4
  54. package/dist/store/reducers/{network.js → network/network.ts} +11 -8
  55. package/dist/store/reducers/network/types.ts +16 -0
  56. package/dist/store/reducers/node/node.ts +102 -0
  57. package/dist/store/reducers/node/selectors.ts +59 -0
  58. package/dist/store/reducers/node/types.ts +44 -0
  59. package/dist/store/reducers/overview/overview.ts +109 -0
  60. package/dist/store/reducers/overview/types.ts +24 -0
  61. package/dist/store/reducers/{schema.ts → schema/schema.ts} +24 -50
  62. package/dist/{types/store/schema.ts → store/reducers/schema/types.ts} +16 -15
  63. package/dist/store/reducers/{schemaAcl.js → schemaAcl/schemaAcl.ts} +20 -9
  64. package/dist/store/reducers/schemaAcl/types.ts +15 -0
  65. package/dist/store/reducers/settings/settings.ts +5 -3
  66. package/dist/types/api/acl.ts +1 -1
  67. package/dist/types/api/query.ts +78 -44
  68. package/dist/types/store/explainQuery.ts +2 -2
  69. package/dist/types/store/query.ts +4 -2
  70. package/dist/utils/constants.ts +3 -1
  71. package/dist/utils/nodes.ts +1 -1
  72. package/dist/utils/query.ts +3 -3
  73. package/package.json +1 -1
  74. package/dist/components/PoolUsage/PoolUsage.js +0 -54
  75. package/dist/store/reducers/node.js +0 -141
@@ -35,8 +35,6 @@ import {getNodesList, selectNodesMap} from '../../store/reducers/nodesList';
35
35
  import StorageGroups from './StorageGroups/StorageGroups';
36
36
  import StorageNodes from './StorageNodes/StorageNodes';
37
37
  import {DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
38
- import {setHeader} from '../../store/reducers/header';
39
- import routes, {CLUSTER_PAGES, createHref} from '../../routes';
40
38
 
41
39
  import './Storage.scss';
42
40
 
@@ -67,7 +65,6 @@ class Storage extends React.Component {
67
65
  setStorageFilter: PropTypes.func,
68
66
  setVisibleEntities: PropTypes.func,
69
67
  visibleEntities: PropTypes.string,
70
- setHeader: PropTypes.func,
71
68
  tenant: PropTypes.string,
72
69
  nodeId: PropTypes.string,
73
70
  nodesUptimeFilter: PropTypes.string,
@@ -77,7 +74,7 @@ class Storage extends React.Component {
77
74
  };
78
75
 
79
76
  componentDidMount() {
80
- const {tenant, nodeId, setVisibleEntities, storageType, setHeader, getNodesList} =
77
+ const {tenant, nodeId, setVisibleEntities, storageType, getNodesList} =
81
78
  this.props;
82
79
 
83
80
  this.autofetcher = new AutoFetcher();
@@ -89,12 +86,6 @@ class Storage extends React.Component {
89
86
  type: storageType,
90
87
  });
91
88
  } else {
92
- setHeader([
93
- {
94
- text: CLUSTER_PAGES.storage.title,
95
- link: createHref(routes.cluster, {activeTab: CLUSTER_PAGES.storage.id}),
96
- },
97
- ]);
98
89
  this.getStorageInfo({
99
90
  filter: FILTER_OPTIONS.Missing,
100
91
  type: storageType,
@@ -375,7 +366,6 @@ const mapDispatchToProps = {
375
366
  setNodesUptimeFilter,
376
367
  getNodesList,
377
368
  setStorageType,
378
- setHeader,
379
369
  setDataWasNotLoaded,
380
370
  };
381
371
 
@@ -6,6 +6,9 @@ import {Link as ExternalLink} from '@gravity-ui/uikit';
6
6
 
7
7
  import {backend} from '../../store';
8
8
  import {getTablet, getTabletDescribe} from '../../store/reducers/tablet';
9
+ import {setHeader} from '../../store/reducers/header';
10
+ import routes, {createHref} from '../../routes';
11
+
9
12
  import {useAutofetcher, useTypedSelector} from '../../utils/hooks';
10
13
  import '../../services/api';
11
14
 
@@ -16,6 +19,8 @@ import {Icon} from '../../components/Icon';
16
19
  import {EmptyState} from '../../components/EmptyState';
17
20
  import {Loader} from '../../components/Loader';
18
21
 
22
+ import {getClusterPath} from '../Cluster/utils';
23
+
19
24
  import {TabletTable} from './TabletTable';
20
25
  import {TabletInfo} from './TabletInfo';
21
26
  import {TabletControls} from './TabletControls';
@@ -56,6 +61,29 @@ export const Tablet = () => {
56
61
 
57
62
  useAutofetcher(fetchData, [fetchData], true);
58
63
 
64
+ useEffect(() => {
65
+ 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
+ ]),
84
+ );
85
+ }, [dispatch, tenantPath, tablet]);
86
+
59
87
  const renderExternalLinks = (link: {name: string; path: string}, index: number) => {
60
88
  return (
61
89
  <li key={index} className={b('link', {external: true})}>
@@ -11,6 +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
15
  import {tabletColorToTabletState, tabletStates} from '../../utils/tablet';
15
16
  import {
16
17
  getTabletsInfo,
@@ -21,6 +22,8 @@ import {
21
22
  getTablets,
22
23
  } from '../../store/reducers/tabletsFilters';
23
24
 
25
+ import {getClusterPath} from '../Cluster/utils';
26
+
24
27
  import './TabletsFilters.scss';
25
28
 
26
29
  const b = cn('tablets-filters');
@@ -41,6 +44,7 @@ class TabletsFilters extends React.Component {
41
44
  stateFilter: PropTypes.array,
42
45
  typeFilter: PropTypes.array,
43
46
  error: PropTypes.oneOf([PropTypes.string, PropTypes.object]),
47
+ setHeader: PropTypes.func,
44
48
  };
45
49
 
46
50
  static renderLoader() {
@@ -72,7 +76,7 @@ class TabletsFilters extends React.Component {
72
76
  reloadDescriptor = -1;
73
77
 
74
78
  componentDidMount() {
75
- const {setStateFilter, setTypeFilter} = this.props;
79
+ const {setStateFilter, setTypeFilter, setHeader} = this.props;
76
80
 
77
81
  const queryParams = qs.parse(this.props.location.search, {
78
82
  ignoreQueryPrefix: true,
@@ -87,6 +91,16 @@ class TabletsFilters extends React.Component {
87
91
  this.setState({nodeFilter: nodes, tenantPath: path}, () => {
88
92
  this.makeRequest();
89
93
  });
94
+
95
+ setHeader([
96
+ {
97
+ text: 'Cluster',
98
+ link: getClusterPath(),
99
+ },
100
+ {
101
+ text: 'Tablets'
102
+ }
103
+ ]);
90
104
  }
91
105
 
92
106
  componentDidUpdate(prevProps) {
@@ -326,6 +340,7 @@ const mapDispatchToProps = {
326
340
  clearWasLoadingFlag,
327
341
  setStateFilter,
328
342
  setTypeFilter,
343
+ setHeader,
329
344
  };
330
345
 
331
346
  export default connect(mapStateToProps, mapDispatchToProps)(TabletsFilters);
@@ -15,7 +15,7 @@ import {
15
15
  setCurrentDescribePath,
16
16
  getDescribeBatched,
17
17
  } from '../../../../store/reducers/describe';
18
- import {selectSchemaMergedChildrenPaths} from '../../../../store/reducers/schema';
18
+ import {selectSchemaMergedChildrenPaths} from '../../../../store/reducers/schema/schema';
19
19
  import type {EPathType} from '../../../../types/api/schema';
20
20
 
21
21
  import {isEntityWithMergedImplementation} from '../../utils/schema';
@@ -4,6 +4,9 @@ $section-title-line-height: 24px;
4
4
  .kv-detailed-overview {
5
5
  display: flex;
6
6
  gap: 20px;
7
+
8
+ height: 100%;
9
+
7
10
  &__section {
8
11
  display: flex;
9
12
  overflow-x: hidden;
@@ -12,7 +12,7 @@ import type {EPathType} from '../../../types/api/schema';
12
12
  import {useTypedSelector} from '../../../utils/hooks';
13
13
  import routes, {createHref} from '../../../routes';
14
14
  import type {TenantDiagnosticsTab, TenantGeneralTab} from '../../../store/reducers/tenant/types';
15
- import {enableAutorefresh, disableAutorefresh} from '../../../store/reducers/schema';
15
+ import {enableAutorefresh, disableAutorefresh} from '../../../store/reducers/schema/schema';
16
16
  import {setTopLevelTab, setDiagnosticsTab} from '../../../store/reducers/tenant/tenant';
17
17
  import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../store/reducers/tenant/constants';
18
18
 
@@ -49,8 +49,8 @@ const b = cn('kv-tenant-diagnostics');
49
49
 
50
50
  function Diagnostics(props: DiagnosticsProps) {
51
51
  const dispatch = useDispatch();
52
- const {currentSchemaPath, autorefresh} = useSelector((state: any) => state.schema);
53
- const {diagnosticsTab = TENANT_DIAGNOSTICS_TABS_IDS.overview, wasLoaded} = useTypedSelector(
52
+ const {currentSchemaPath, autorefresh, wasLoaded} = useSelector((state: any) => state.schema);
53
+ const {diagnosticsTab = TENANT_DIAGNOSTICS_TABS_IDS.overview} = useTypedSelector(
54
54
  (state) => state.tenant,
55
55
  );
56
56
 
@@ -12,7 +12,7 @@ import {Icon} from '../../../../components/Icon';
12
12
  import {ProblemFilter} from '../../../../components/ProblemFilter';
13
13
  import {Illustration} from '../../../../components/Illustration';
14
14
 
15
- import {getNetworkInfo, setDataWasNotLoaded} from '../../../../store/reducers/network';
15
+ import {getNetworkInfo, setDataWasNotLoaded} from '../../../../store/reducers/network/network';
16
16
  import {hideTooltip, showTooltip} from '../../../../store/reducers/tooltip';
17
17
  import {changeFilter, ProblemFilterValues} from '../../../../store/reducers/settings/settings';
18
18
  import {AutoFetcher} from '../../../../utils/autofetcher';
@@ -361,7 +361,7 @@ class Network extends React.Component {
361
361
  }
362
362
 
363
363
  const mapStateToProps = (state) => {
364
- const {wasLoaded, loading, data: netWorkInfo} = state.network;
364
+ const {wasLoaded, loading, data: netWorkInfo = {}} = state.network;
365
365
  const {autorefresh} = state.schema;
366
366
  return {
367
367
  netWorkInfo,
@@ -7,7 +7,6 @@ import {
7
7
  } from '../../../../../components/InfoViewer/formatters';
8
8
 
9
9
  import {useTypedSelector} from '../../../../../utils/hooks';
10
- import {selectSchemaData} from '../../../../../store/reducers/schema';
11
10
 
12
11
  import {getEntityName} from '../../../utils';
13
12
 
@@ -42,27 +41,26 @@ const prepareChangefeedInfo = (
42
41
 
43
42
  interface ChangefeedProps {
44
43
  data?: TEvDescribeSchemeResult;
45
- childrenPaths?: string[];
44
+ topic?: TEvDescribeSchemeResult;
46
45
  }
47
46
 
48
47
  /** Displays overview for CDCStream EPathType */
49
- export const ChangefeedInfo = ({data, childrenPaths}: ChangefeedProps) => {
48
+ export const ChangefeedInfo = ({data, topic}: ChangefeedProps) => {
50
49
  const entityName = getEntityName(data?.PathDescription);
51
50
 
52
51
  const {error: schemaError} = useTypedSelector((state) => state.schema);
53
- const pqGroupData = useTypedSelector((state) => selectSchemaData(state, childrenPaths?.[0]));
54
52
 
55
53
  if (schemaError) {
56
54
  return <div className="error">{schemaError.statusText}</div>;
57
55
  }
58
56
 
59
- if (!data || !pqGroupData) {
57
+ if (!data || !topic) {
60
58
  return <div className="error">No {entityName} data</div>;
61
59
  }
62
60
 
63
61
  return (
64
62
  <div>
65
- <InfoViewer title={entityName} info={prepareChangefeedInfo(data, pqGroupData)} />
63
+ <InfoViewer title={entityName} info={prepareChangefeedInfo(data, topic)} />
66
64
  <TopicStats />
67
65
  </div>
68
66
  );
@@ -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;
@@ -6,7 +6,7 @@ import {Loader} from '@gravity-ui/uikit';
6
6
 
7
7
  import EntityStatus from '../../../../components/EntityStatus/EntityStatus';
8
8
  import InfoViewer from '../../../../components/InfoViewer/InfoViewer';
9
- import PoolUsage from '../../../../components/PoolUsage/PoolUsage';
9
+ import {PoolUsage} from '../../../../components/PoolUsage/PoolUsage';
10
10
  import {Tablet} from '../../../../components/Tablet';
11
11
 
12
12
  import {getTenantInfo} from '../../../../store/reducers/tenant/tenant';
@@ -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';
@@ -46,7 +46,7 @@ import {
46
46
  paneVisibilityToggleReducerCreator,
47
47
  PaneVisibilityToggleButtons,
48
48
  } from '../utils/paneVisibilityToggleHelpers';
49
- import {setShowPreview} from '../../../store/reducers/schema';
49
+ import {setShowPreview} from '../../../store/reducers/schema/schema';
50
50
  import {setTopLevelTab} from '../../../store/reducers/tenant/tenant';
51
51
  import {TENANT_GENERAL_TABS_IDS} from '../../../store/reducers/tenant/constants';
52
52
 
@@ -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
 
@@ -8,12 +8,6 @@ import MonacoEditor from 'react-monaco-editor';
8
8
  import SplitPane from '../../../components/SplitPane';
9
9
  import {QueryResultTable} from '../../../components/QueryResultTable';
10
10
 
11
- import SavedQueries from './SavedQueries/SavedQueries';
12
- import QueryResult from './QueryResult/QueryResult';
13
- import QueryExplain from './QueryExplain/QueryExplain';
14
- import {QueryEditorControls} from './QueryEditorControls/QueryEditorControls';
15
- import {OldQueryEditorControls} from './QueryEditorControls/OldQueryEditorControls';
16
-
17
11
  import {
18
12
  sendExecuteQuery,
19
13
  changeUserInput,
@@ -25,22 +19,31 @@ import {
25
19
  } from '../../../store/reducers/executeQuery';
26
20
  import {getExplainQuery, getExplainQueryAst} from '../../../store/reducers/explainQuery';
27
21
  import {getParsedSettingValue, setSettingValue} from '../../../store/reducers/settings/settings';
22
+ import {setShowPreview} from '../../../store/reducers/schema/schema';
28
23
  import {
29
24
  DEFAULT_IS_QUERY_RESULT_COLLAPSED,
30
25
  DEFAULT_SIZE_RESULT_PANE_KEY,
31
26
  SAVED_QUERIES_KEY,
32
27
  QUERY_INITIAL_MODE_KEY,
33
- ENABLE_QUERY_MODES_FOR_EXPLAIN,
28
+ ENABLE_ADDITIONAL_QUERY_MODES,
34
29
  } from '../../../utils/constants';
30
+ import {useSetting} from '../../../utils/hooks';
31
+ import {QueryModes} from '../../../types/store/query';
35
32
 
36
- import './QueryEditor.scss';
37
- import QueriesHistory from './QueriesHistory/QueriesHistory';
38
33
  import {
39
34
  PaneVisibilityActionTypes,
40
35
  paneVisibilityToggleReducerCreator,
41
36
  } from '../utils/paneVisibilityToggleHelpers';
42
37
  import Preview from '../Preview/Preview';
43
- import {setShowPreview} from '../../../store/reducers/schema';
38
+
39
+ import SavedQueries from './SavedQueries/SavedQueries';
40
+ import QueryResult from './QueryResult/QueryResult';
41
+ import QueryExplain from './QueryExplain/QueryExplain';
42
+ import {QueryEditorControls} from './QueryEditorControls/QueryEditorControls';
43
+ import {OldQueryEditorControls} from './QueryEditorControls/OldQueryEditorControls';
44
+ import QueriesHistory from './QueriesHistory/QueriesHistory';
45
+
46
+ import './QueryEditor.scss';
44
47
 
45
48
  const TABLE_SETTINGS = {
46
49
  sortable: false,
@@ -83,7 +86,15 @@ function QueryEditor(props) {
83
86
  const [resultType, setResultType] = useState(RESULT_TYPES.EXECUTE);
84
87
 
85
88
  const [isResultLoaded, setIsResultLoaded] = useState(false);
86
- const [queryMode, setQueryMode] = useState(props.initialQueryMode);
89
+ const [queryMode, setQueryMode] = useSetting(QUERY_INITIAL_MODE_KEY);
90
+ const [enableAdditionalQueryModes] = useSetting(ENABLE_ADDITIONAL_QUERY_MODES);
91
+
92
+ useEffect(() => {
93
+ const isNewQueryMode = queryMode !== QueryModes.script && queryMode !== QueryModes.scan;
94
+ if (!enableAdditionalQueryModes && isNewQueryMode) {
95
+ setQueryMode(QueryModes.script);
96
+ }
97
+ }, [enableAdditionalQueryModes, queryMode, setQueryMode]);
87
98
 
88
99
  const [resultVisibilityState, dispatchResultVisibilityState] = useReducer(
89
100
  paneVisibilityToggleReducerCreator(DEFAULT_IS_QUERY_RESULT_COLLAPSED),
@@ -510,15 +521,10 @@ function QueryEditor(props) {
510
521
  setSettingValue(SAVED_QUERIES_KEY, JSON.stringify(newSavedQueries));
511
522
  };
512
523
 
513
- const onUpdateQueryMode = (mode) => {
514
- setQueryMode(mode);
515
- props.setSettingValue(QUERY_INITIAL_MODE_KEY, mode);
516
- };
517
-
518
524
  const renderControls = () => {
519
- const {executeQuery, explainQuery, savedQueries, enableQueryModesForExplain} = props;
525
+ const {executeQuery, explainQuery, savedQueries} = props;
520
526
 
521
- if (enableQueryModesForExplain) {
527
+ if (enableAdditionalQueryModes) {
522
528
  return (
523
529
  <QueryEditorControls
524
530
  onRunButtonClick={handleSendExecuteClick}
@@ -528,7 +534,7 @@ function QueryEditor(props) {
528
534
  onSaveQueryClick={onSaveQueryHandler}
529
535
  savedQueries={savedQueries}
530
536
  disabled={!executeQuery.input}
531
- onUpdateQueryMode={onUpdateQueryMode}
537
+ onUpdateQueryMode={setQueryMode}
532
538
  queryMode={queryMode}
533
539
  />
534
540
  );
@@ -543,7 +549,7 @@ function QueryEditor(props) {
543
549
  onSaveQueryClick={onSaveQueryHandler}
544
550
  savedQueries={savedQueries}
545
551
  disabled={!executeQuery.input}
546
- onUpdateQueryMode={onUpdateQueryMode}
552
+ onUpdateQueryMode={setQueryMode}
547
553
  queryMode={queryMode}
548
554
  />
549
555
  );
@@ -607,8 +613,6 @@ const mapStateToProps = (state) => {
607
613
  executeQuery: state.executeQuery,
608
614
  explainQuery: state.explainQuery,
609
615
  savedQueries: getParsedSettingValue(state, SAVED_QUERIES_KEY),
610
- initialQueryMode: getParsedSettingValue(state, QUERY_INITIAL_MODE_KEY),
611
- enableQueryModesForExplain: getParsedSettingValue(state, ENABLE_QUERY_MODES_FOR_EXPLAIN),
612
616
  showPreview: state.schema.showPreview,
613
617
  currentSchema: state.schema.currentSchema,
614
618
  monacoHotKey: state.executeQuery?.monacoHotKey,
@@ -6,10 +6,17 @@ import {Icon} from '../../../../components/Icon';
6
6
 
7
7
  import SaveQuery from '../SaveQuery/SaveQuery';
8
8
 
9
- import {b, QueryEditorControlsProps, QueryModeSelectorTitles} from './shared';
9
+ import {QueryEditorControlsProps, b} from './shared';
10
10
 
11
11
  import './QueryEditorControls.scss';
12
12
 
13
+ type OldQueryModes = QueryModes.script | QueryModes.scan;
14
+
15
+ export const QueryModeSelectorTitles = {
16
+ [QueryModes.script]: 'Script',
17
+ [QueryModes.scan]: 'Scan',
18
+ } as const;
19
+
13
20
  export const OldQueryEditorControls = ({
14
21
  onRunButtonClick,
15
22
  runIsLoading,
@@ -26,7 +33,7 @@ export const OldQueryEditorControls = ({
26
33
  return {
27
34
  text: `Run ${title}`,
28
35
  action: () => {
29
- onUpdateQueryMode(mode as QueryModes);
36
+ onUpdateQueryMode(mode as OldQueryModes);
30
37
  },
31
38
  };
32
39
  });
@@ -44,7 +51,7 @@ export const OldQueryEditorControls = ({
44
51
  loading={runIsLoading}
45
52
  >
46
53
  <Icon name="startPlay" viewBox="0 0 16 16" width={16} height={16} />
47
- {`Run ${QueryModeSelectorTitles[queryMode]}`}
54
+ {`Run ${QueryModeSelectorTitles[queryMode as OldQueryModes]}`}
48
55
  </Button>
49
56
  <DropdownMenu
50
57
  items={runModeSelectorMenuItems}
@@ -8,10 +8,17 @@ import SaveQuery from '../SaveQuery/SaveQuery';
8
8
 
9
9
  import i18n from '../i18n';
10
10
 
11
- import {b, QueryEditorControlsProps, QueryModeSelectorTitles} from './shared';
11
+ import {QueryEditorControlsProps, b} from './shared';
12
12
 
13
13
  import './QueryEditorControls.scss';
14
14
 
15
+ export const QueryModeSelectorTitles = {
16
+ [QueryModes.script]: 'Script',
17
+ [QueryModes.scan]: 'Scan',
18
+ [QueryModes.data]: 'Data',
19
+ [QueryModes.query]: 'Query',
20
+ } as const;
21
+
15
22
  export const QueryEditorControls = ({
16
23
  onRunButtonClick,
17
24
  runIsLoading,
@@ -1,14 +1,9 @@
1
1
  import block from 'bem-cn-lite';
2
2
 
3
- import {QueryModes} from '../../../../types/store/query';
3
+ import type {QueryModes} from '../../../../types/store/query';
4
4
 
5
5
  export const b = block('ydb-query-editor-controls');
6
6
 
7
- export const QueryModeSelectorTitles = {
8
- [QueryModes.script]: 'Script',
9
- [QueryModes.scan]: 'Scan',
10
- } as const;
11
-
12
7
  export interface QueryEditorControlsProps {
13
8
  onRunButtonClick: (mode?: QueryModes) => void;
14
9
  runIsLoading: boolean;