ydb-embedded-ui 4.5.1 → 4.6.0

Sign up to get free protection for your applications and to get access to all the features.
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;