ydb-embedded-ui 4.6.0 → 4.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. package/CHANGELOG.md +27 -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/AsideNavigation/AsideNavigation.tsx +50 -18
  8. package/dist/containers/Cluster/Cluster.tsx +6 -13
  9. package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +3 -3
  10. package/dist/containers/Cluster/{utils.ts → utils.tsx} +11 -0
  11. package/dist/containers/Header/Header.scss +9 -0
  12. package/dist/containers/Header/Header.tsx +70 -14
  13. package/dist/containers/Header/breadcrumbs.ts +146 -0
  14. package/dist/containers/Node/Node.tsx +21 -27
  15. package/dist/containers/Node/NodePages.ts +10 -6
  16. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +11 -3
  17. package/dist/containers/Tablet/Tablet.tsx +35 -27
  18. package/dist/containers/Tablet/TabletInfo/TabletInfo.tsx +2 -2
  19. package/dist/containers/TabletsFilters/TabletsFilters.js +13 -15
  20. package/dist/containers/Tenant/Diagnostics/Consumers/columns/columns.tsx +1 -1
  21. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +5 -1
  22. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +4 -14
  23. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +5 -3
  24. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +1 -1
  25. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +2 -1
  26. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +9 -16
  27. package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +11 -11
  28. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +7 -3
  29. package/dist/containers/Tenant/{QueryEditor/QueryResult/QueryResult.js → Query/ExecuteResult/ExecuteResult.js} +3 -5
  30. package/dist/containers/Tenant/{QueryEditor/QueryResult/QueryResult.scss → Query/ExecuteResult/ExecuteResult.scss} +1 -1
  31. package/dist/containers/Tenant/{QueryEditor/QueryExplain/QueryExplain.js → Query/ExplainResult/ExplainResult.js} +3 -5
  32. package/dist/containers/Tenant/{QueryEditor/QueryExplain/QueryExplain.scss → Query/ExplainResult/ExplainResult.scss} +1 -1
  33. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.scss +20 -0
  34. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.tsx +60 -0
  35. package/dist/containers/Tenant/Query/Query.scss +16 -0
  36. package/dist/containers/Tenant/Query/Query.tsx +73 -0
  37. package/dist/containers/Tenant/{QueryEditor → Query/QueryEditor}/QueryEditor.js +39 -88
  38. package/dist/containers/Tenant/{QueryEditor → Query/QueryEditor}/QueryEditor.scss +7 -23
  39. package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/QueryEditorControls.scss +1 -4
  40. package/dist/containers/Tenant/Query/QueryTabs/QueryTabs.tsx +59 -0
  41. package/dist/containers/Tenant/{QueryEditor → Query}/SaveQuery/SaveQuery.js +5 -5
  42. package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.scss +55 -0
  43. package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.tsx +150 -0
  44. package/dist/containers/Tenant/Query/i18n/en.json +12 -0
  45. package/dist/containers/Tenant/Query/i18n/ru.json +12 -0
  46. package/dist/containers/Tenant/Query/utils/getPreparedResult.ts +30 -0
  47. package/dist/containers/Tenant/Tenant.scss +0 -8
  48. package/dist/containers/Tenant/Tenant.tsx +24 -46
  49. package/dist/containers/Tenant/TenantPages.tsx +7 -16
  50. package/dist/containers/Tenant/utils/constants.ts +10 -0
  51. package/dist/containers/Tenant/utils/schemaActions.ts +9 -4
  52. package/dist/containers/Tenants/Tenants.js +26 -13
  53. package/dist/routes.ts +21 -7
  54. package/dist/services/api.ts +9 -5
  55. package/dist/store/reducers/executeQuery.ts +18 -4
  56. package/dist/store/reducers/header/header.ts +31 -0
  57. package/dist/store/reducers/header/types.ts +54 -0
  58. package/dist/store/reducers/index.ts +1 -1
  59. package/dist/store/reducers/node/types.ts +2 -0
  60. package/dist/store/reducers/settings/settings.ts +8 -3
  61. package/dist/store/reducers/tablet.ts +18 -1
  62. package/dist/store/reducers/tenant/constants.ts +9 -1
  63. package/dist/store/reducers/tenant/tenant.ts +23 -4
  64. package/dist/store/reducers/tenant/types.ts +9 -5
  65. package/dist/store/reducers/topic.ts +1 -1
  66. package/dist/store/state-url-mapping.js +6 -3
  67. package/dist/types/store/executeQuery.ts +4 -1
  68. package/dist/types/store/query.ts +5 -0
  69. package/dist/types/store/tablet.ts +7 -4
  70. package/dist/utils/constants.ts +5 -1
  71. package/package.json +2 -1
  72. package/dist/containers/Tenant/ObjectGeneralTabs/ObjectGeneralTabs.scss +0 -9
  73. package/dist/containers/Tenant/ObjectGeneralTabs/ObjectGeneralTabs.tsx +0 -68
  74. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.scss +0 -85
  75. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +0 -95
  76. package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.js +0 -161
  77. package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.scss +0 -93
  78. package/dist/containers/Tenant/QueryEditor/i18n/en.json +0 -3
  79. package/dist/containers/Tenant/QueryEditor/i18n/ru.json +0 -3
  80. package/dist/store/reducers/header.ts +0 -26
  81. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/Issues.scss +0 -0
  82. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/Issues.tsx +0 -0
  83. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/models.ts +0 -0
  84. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryDuration/QueryDuration.scss +0 -0
  85. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryDuration/QueryDuration.tsx +0 -0
  86. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/OldQueryEditorControls.tsx +0 -0
  87. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/QueryEditorControls.tsx +0 -0
  88. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/shared.ts +0 -0
  89. /package/dist/containers/Tenant/{QueryEditor → Query}/SaveQuery/SaveQuery.scss +0 -0
  90. /package/dist/containers/Tenant/{QueryEditor → Query}/i18n/index.ts +0 -0
@@ -5,11 +5,8 @@
5
5
  align-items: flex-end;
6
6
 
7
7
  min-height: 40px;
8
- padding: 5px 20px;
8
+ padding: 5px 0px;
9
9
 
10
- border-top: 1px solid var(--yc-color-line-generic);
11
- border-bottom: 1px solid var(--yc-color-line-generic);
12
- background-color: var(--yc-color-base-background);
13
10
  gap: 24px;
14
11
 
15
12
  &__left {
@@ -0,0 +1,59 @@
1
+ import {useLocation} from 'react-router';
2
+
3
+ import {Tabs} from '@gravity-ui/uikit';
4
+
5
+ import type {TenantQueryTab} from '../../../../store/reducers/tenant/types';
6
+ import {TENANT_QUERY_TABS_ID} from '../../../../store/reducers/tenant/constants';
7
+ import {InternalLink} from '../../../../components/InternalLink/InternalLink';
8
+ import {parseQuery} from '../../../../routes';
9
+
10
+ import {TenantTabsGroups, getTenantPath} from '../../TenantPages';
11
+
12
+ import i18n from '../i18n';
13
+
14
+ const newQuery = {
15
+ id: TENANT_QUERY_TABS_ID.newQuery,
16
+ title: i18n('tabs.newQuery'),
17
+ };
18
+ const history = {
19
+ id: TENANT_QUERY_TABS_ID.history,
20
+ title: i18n('tabs.history'),
21
+ };
22
+ const saved = {
23
+ id: TENANT_QUERY_TABS_ID.saved,
24
+ title: i18n('tabs.saved'),
25
+ };
26
+
27
+ const queryEditorTabs = [newQuery, history, saved];
28
+
29
+ interface QueryEditorTabsProps {
30
+ className?: string;
31
+ activeTab?: TenantQueryTab;
32
+ }
33
+
34
+ export const QueryTabs = ({className, activeTab}: QueryEditorTabsProps) => {
35
+ const location = useLocation();
36
+ const queryParams = parseQuery(location);
37
+
38
+ return (
39
+ <div className={className}>
40
+ <Tabs
41
+ size="l"
42
+ allowNotSelected={true}
43
+ activeTab={activeTab}
44
+ items={queryEditorTabs}
45
+ wrapTo={({id}, node) => {
46
+ const path = getTenantPath({
47
+ ...queryParams,
48
+ [TenantTabsGroups.queryTab]: id,
49
+ });
50
+ return (
51
+ <InternalLink to={path} key={id}>
52
+ {node}
53
+ </InternalLink>
54
+ );
55
+ }}
56
+ />
57
+ </div>
58
+ );
59
+ };
@@ -105,21 +105,21 @@ function SaveQuery({savedQueries, onSaveQuery, saveButtonDisabled}) {
105
105
  const renderSaveButton = (onClick) => {
106
106
  return (
107
107
  <Button onClick={onClick} disabled={saveButtonDisabled}>
108
- Save query
108
+ {queryNameToEdit ? 'Edit query' : 'Save query'}
109
109
  </Button>
110
110
  );
111
111
  };
112
112
 
113
113
  const renderSaveDropdownMenu = () => {
114
114
  const items = [
115
- {
116
- action: onSaveQueryClick,
117
- text: 'Save as new',
118
- },
119
115
  {
120
116
  action: onEditQueryClick,
121
117
  text: 'Edit existing',
122
118
  },
119
+ {
120
+ action: onSaveQueryClick,
121
+ text: 'Save as new',
122
+ },
123
123
  ];
124
124
  return (
125
125
  <DropdownMenu items={items} switcher={renderSaveButton()} popupPlacement={['top']} />
@@ -0,0 +1,55 @@
1
+ @import '../../../../styles/mixins.scss';
2
+
3
+ .ydb-saved-queries {
4
+ $block: &;
5
+
6
+ overflow: auto;
7
+
8
+ height: 100%;
9
+ padding: 0 16px;
10
+
11
+ @include flex-container();
12
+ @include table-styles;
13
+
14
+ &__row {
15
+ cursor: pointer;
16
+
17
+ :hover {
18
+ #{$block}__controls {
19
+ display: flex;
20
+ }
21
+ }
22
+ }
23
+
24
+ &__query-name {
25
+ overflow: hidden;
26
+
27
+ white-space: pre-wrap;
28
+ text-overflow: ellipsis;
29
+ }
30
+
31
+ &__query {
32
+ display: flex;
33
+ flex-direction: row;
34
+ justify-content: space-between;
35
+ align-items: center;
36
+ }
37
+
38
+ &__query-body {
39
+ overflow: hidden;
40
+ flex-grow: 1;
41
+
42
+ max-width: 100%;
43
+
44
+ white-space: pre;
45
+ text-overflow: ellipsis;
46
+ }
47
+
48
+ &__controls {
49
+ display: none;
50
+ }
51
+
52
+ &__dialog-query-name {
53
+ font-weight: 500;
54
+ }
55
+ }
@@ -0,0 +1,150 @@
1
+ import {MouseEvent, useState} from 'react';
2
+ import {useDispatch} from 'react-redux';
3
+ import block from 'bem-cn-lite';
4
+
5
+ import {Dialog, Button} from '@gravity-ui/uikit';
6
+ import DataTable, {Column} from '@gravity-ui/react-data-table';
7
+
8
+ import type {SavedQuery} from '../../../../types/store/query';
9
+ import {setQueryNameToEdit} from '../../../../store/reducers/saveQuery';
10
+ import {setQueryTab} from '../../../../store/reducers/tenant/tenant';
11
+ import {TENANT_QUERY_TABS_ID} from '../../../../store/reducers/tenant/constants';
12
+
13
+ import TruncatedQuery from '../../../../components/TruncatedQuery/TruncatedQuery';
14
+ import {IconWrapper} from '../../../../components/Icon';
15
+
16
+ import {MAX_QUERY_HEIGHT, QUERY_TABLE_SETTINGS} from '../../utils/constants';
17
+
18
+ import i18n from '../i18n';
19
+
20
+ import './SavedQueries.scss';
21
+
22
+ const b = block('ydb-saved-queries');
23
+
24
+ interface DeleteDialogProps {
25
+ visible: boolean;
26
+ queryName: string;
27
+ onCancelClick: VoidFunction;
28
+ onConfirmClick: VoidFunction;
29
+ }
30
+
31
+ const DeleteDialog = ({visible, queryName, onCancelClick, onConfirmClick}: DeleteDialogProps) => {
32
+ return (
33
+ <Dialog
34
+ open={visible}
35
+ hasCloseButton={false}
36
+ size="s"
37
+ onClose={onCancelClick}
38
+ onEnterKeyDown={onConfirmClick}
39
+ >
40
+ <Dialog.Header caption={i18n('delete-dialog.header')} />
41
+ <Dialog.Body className={b('dialog-body')}>
42
+ {i18n('delete-dialog.question')}
43
+ <span className={b('dialog-query-name')}>{` ${queryName}?`}</span>
44
+ </Dialog.Body>
45
+ <Dialog.Footer
46
+ textButtonApply={i18n('delete-dialog.delete')}
47
+ textButtonCancel={i18n('delete-dialog.cancel')}
48
+ onClickButtonCancel={onCancelClick}
49
+ onClickButtonApply={onConfirmClick}
50
+ />
51
+ </Dialog>
52
+ );
53
+ };
54
+
55
+ interface SavedQueriesProps {
56
+ savedQueries: SavedQuery[];
57
+ changeUserInput: (value: {input: string}) => void;
58
+ onDeleteQuery: (queryName: string) => void;
59
+ }
60
+
61
+ export const SavedQueries = ({savedQueries, changeUserInput, onDeleteQuery}: SavedQueriesProps) => {
62
+ const dispatch = useDispatch();
63
+
64
+ const [isDeleteDialogVisible, setIsDeleteDialogVisible] = useState(false);
65
+ const [queryNameToDelete, setQueryNameToDelete] = useState<string>('');
66
+
67
+ const closeDeleteDialog = () => {
68
+ setIsDeleteDialogVisible(false);
69
+ setQueryNameToDelete('');
70
+ };
71
+
72
+ const onCancelDeleteClick = () => {
73
+ closeDeleteDialog();
74
+ };
75
+
76
+ const onConfirmDeleteClick = () => {
77
+ closeDeleteDialog();
78
+ onDeleteQuery(queryNameToDelete);
79
+ setQueryNameToDelete('');
80
+ };
81
+
82
+ const onQueryClick = (queryText: string, queryName: string) => {
83
+ changeUserInput({input: queryText});
84
+ dispatch(setQueryNameToEdit(queryName));
85
+ dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
86
+ };
87
+
88
+ const onDeleteQueryClick = (queryName: string) => {
89
+ return (event: MouseEvent) => {
90
+ event.stopPropagation();
91
+ setIsDeleteDialogVisible(true);
92
+ setQueryNameToDelete(queryName);
93
+ };
94
+ };
95
+
96
+ const columns: Column<SavedQuery>[] = [
97
+ {
98
+ name: 'name',
99
+ header: 'Name',
100
+ render: ({row: query}) => <div className={b('query-name')}>{query.name}</div>,
101
+ width: 200,
102
+ },
103
+ {
104
+ name: 'body',
105
+ header: 'Query Text',
106
+ render: ({row: query}) => (
107
+ <div className={b('query')}>
108
+ <div className={b('query-body')}>
109
+ <TruncatedQuery value={query.body} maxQueryHeight={MAX_QUERY_HEIGHT} />
110
+ </div>
111
+ <span className={b('controls')}>
112
+ <Button view="flat-secondary">
113
+ <IconWrapper name="pencil" viewBox="0 0 24 24" />
114
+ </Button>
115
+ <Button view="flat-secondary" onClick={onDeleteQueryClick(query.name)}>
116
+ <IconWrapper name="trash" viewBox="0 0 24 24" />
117
+ </Button>
118
+ </span>
119
+ </div>
120
+ ),
121
+ sortable: false,
122
+ },
123
+ ];
124
+
125
+ return (
126
+ <>
127
+ <div className={b()}>
128
+ <DataTable
129
+ theme="yandex-cloud"
130
+ columns={columns}
131
+ data={savedQueries}
132
+ settings={QUERY_TABLE_SETTINGS}
133
+ emptyDataMessage={i18n('saved.empty')}
134
+ rowClassName={() => b('row')}
135
+ onRowClick={(row) => onQueryClick(row.body, row.name)}
136
+ initialSortOrder={{
137
+ columnId: 'name',
138
+ order: DataTable.ASCENDING,
139
+ }}
140
+ />
141
+ </div>
142
+ <DeleteDialog
143
+ visible={isDeleteDialogVisible}
144
+ queryName={queryNameToDelete}
145
+ onCancelClick={onCancelDeleteClick}
146
+ onConfirmClick={onConfirmDeleteClick}
147
+ />
148
+ </>
149
+ );
150
+ };
@@ -0,0 +1,12 @@
1
+ {
2
+ "controls.query-mode-selector_type": "Type:",
3
+ "tabs.newQuery": "New query",
4
+ "tabs.history": "History",
5
+ "tabs.saved": "Saved",
6
+ "history.empty": "History is empty",
7
+ "saved.empty": "There are no saved queries",
8
+ "delete-dialog.header": "Delete query",
9
+ "delete-dialog.question": "Are you sure you want to delete query",
10
+ "delete-dialog.delete": "Delete",
11
+ "delete-dialog.cancel": "Cancel"
12
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "controls.query-mode-selector_type": "Тип:",
3
+ "tabs.newQuery": "Новый запрос",
4
+ "tabs.history": "История",
5
+ "tabs.saved": "Сохраненные",
6
+ "history.empty": "История пуста",
7
+ "saved.empty": "Нет сохраненных запросов",
8
+ "delete-dialog.header": "Удалить запрос",
9
+ "delete-dialog.question": "Вы уверены что хотите удалить запрос",
10
+ "delete-dialog.delete": "Удалить",
11
+ "delete-dialog.cancel": "Отменить"
12
+ }
@@ -0,0 +1,30 @@
1
+ import type {KeyValueRow} from '../../../../types/api/query';
2
+ import type {IQueryResult} from '../../../../types/store/query';
3
+
4
+ export const getPreparedResult = (data: IQueryResult) => {
5
+ const columnDivider = '\t';
6
+ const rowDivider = '\n';
7
+
8
+ if (!data?.result?.length) {
9
+ return '';
10
+ }
11
+
12
+ const columnHeaders = Object.keys(data.result[0]);
13
+ const rows = Array<string[] | KeyValueRow[]>(columnHeaders).concat(data.result);
14
+
15
+ return rows
16
+ .map((item) => {
17
+ const row = [];
18
+
19
+ for (const field in item) {
20
+ if (typeof item[field] === 'object' || Array.isArray(item[field])) {
21
+ row.push(JSON.stringify(item[field]));
22
+ } else {
23
+ row.push(item[field]);
24
+ }
25
+ }
26
+
27
+ return row.join(columnDivider);
28
+ })
29
+ .join(rowDivider);
30
+ };
@@ -6,12 +6,4 @@
6
6
  font-size: var(--yc-text-body-2-font-size);
7
7
  line-height: var(--yc-text-body-2-line-height);
8
8
  @include flex-container();
9
-
10
- .yc-tabs {
11
- overflow: initial;
12
- }
13
-
14
- &__tab-content {
15
- height: calc(100% - 56px); // general tabs height
16
- }
17
9
  }
@@ -8,17 +8,13 @@ import type {TEvDescribeSchemeResult} from '../../types/api/schema';
8
8
 
9
9
  import {DEFAULT_IS_TENANT_SUMMARY_COLLAPSED, DEFAULT_SIZE_TENANT_KEY} from '../../utils/constants';
10
10
  import {useTypedSelector} from '../../utils/hooks';
11
- import routes, {createHref} from '../../routes';
12
- import {setHeader} from '../../store/reducers/header';
11
+ import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
13
12
  import {disableAutorefresh, getSchema} from '../../store/reducers/schema/schema';
14
13
  import {getSchemaAcl} from '../../store/reducers/schemaAcl/schemaAcl';
15
14
 
16
15
  import SplitPane from '../../components/SplitPane';
17
16
  import {AccessDenied} from '../../components/Errors/403';
18
17
 
19
- import {getClusterPath} from '../Cluster/utils';
20
-
21
- import ObjectGeneralTabs from './ObjectGeneralTabs/ObjectGeneralTabs';
22
18
  import ObjectSummary from './ObjectSummary/ObjectSummary';
23
19
  import ObjectGeneral from './ObjectGeneral/ObjectGeneral';
24
20
 
@@ -92,20 +88,7 @@ function Tenant(props: TenantProps) {
92
88
 
93
89
  useEffect(() => {
94
90
  if (tenantName) {
95
- dispatch(
96
- setHeader([
97
- {
98
- text: 'Cluster',
99
- link: getClusterPath(),
100
- },
101
- {
102
- text: tenantName.startsWith('/') ? tenantName.slice(1) : tenantName,
103
- link: createHref(routes.tenant, undefined, {
104
- name: tenantName,
105
- }),
106
- },
107
- ]),
108
- );
91
+ dispatch(setHeaderBreadcrumbs('tenant', {tenantName}));
109
92
  }
110
93
  }, [tenantName, dispatch]);
111
94
 
@@ -127,33 +110,28 @@ function Tenant(props: TenantProps) {
127
110
  {showBlockingError ? (
128
111
  <AccessDenied />
129
112
  ) : (
130
- <>
131
- <ObjectGeneralTabs />
132
- <div className={b('tab-content')}>
133
- <SplitPane
134
- defaultSizePaneKey={DEFAULT_SIZE_TENANT_KEY}
135
- defaultSizes={[25, 75]}
136
- triggerCollapse={summaryVisibilityState.triggerCollapse}
137
- triggerExpand={summaryVisibilityState.triggerExpand}
138
- minSize={[36, 200]}
139
- onSplitStartDragAdditional={onSplitStartDragAdditional}
140
- >
141
- <ObjectSummary
142
- type={preloadedPathType || currentPathType}
143
- subType={preloadedPathSubType || currentPathSubType}
144
- onCollapseSummary={onCollapseSummaryHandler}
145
- onExpandSummary={onExpandSummaryHandler}
146
- isCollapsed={summaryVisibilityState.collapsed}
147
- additionalTenantInfo={props.additionalTenantInfo}
148
- />
149
- <ObjectGeneral
150
- type={preloadedPathType || currentPathType}
151
- additionalTenantInfo={props.additionalTenantInfo}
152
- additionalNodesInfo={props.additionalNodesInfo}
153
- />
154
- </SplitPane>
155
- </div>
156
- </>
113
+ <SplitPane
114
+ defaultSizePaneKey={DEFAULT_SIZE_TENANT_KEY}
115
+ defaultSizes={[25, 75]}
116
+ triggerCollapse={summaryVisibilityState.triggerCollapse}
117
+ triggerExpand={summaryVisibilityState.triggerExpand}
118
+ minSize={[36, 200]}
119
+ onSplitStartDragAdditional={onSplitStartDragAdditional}
120
+ >
121
+ <ObjectSummary
122
+ type={preloadedPathType || currentPathType}
123
+ subType={preloadedPathSubType || currentPathSubType}
124
+ onCollapseSummary={onCollapseSummaryHandler}
125
+ onExpandSummary={onExpandSummaryHandler}
126
+ isCollapsed={summaryVisibilityState.collapsed}
127
+ additionalTenantInfo={props.additionalTenantInfo}
128
+ />
129
+ <ObjectGeneral
130
+ type={preloadedPathType || currentPathType}
131
+ additionalTenantInfo={props.additionalTenantInfo}
132
+ additionalNodesInfo={props.additionalNodesInfo}
133
+ />
134
+ </SplitPane>
157
135
  )}
158
136
  </div>
159
137
  );
@@ -1,5 +1,4 @@
1
- import {Icon} from '../../components/Icon';
2
- import {TENANT_GENERAL_TABS_IDS} from '../../store/reducers/tenant/constants';
1
+ import routes, {createHref} from '../../routes';
3
2
 
4
3
  export enum TenantInfoTabsIds {
5
4
  overview = 'overview',
@@ -9,22 +8,10 @@ export enum TenantInfoTabsIds {
9
8
 
10
9
  export enum TenantTabsGroups {
11
10
  info = 'info',
12
- general = 'general',
13
- generalTab = 'generalTab',
11
+ queryTab = 'queryTab',
12
+ diagnosticsTab = 'diagnosticsTab',
14
13
  }
15
14
 
16
- export const TENANT_GENERAL_TABS = [
17
- {
18
- id: TENANT_GENERAL_TABS_IDS.query,
19
- title: 'Query',
20
- icon: <Icon name="query" viewBox="0 0 16 16" />,
21
- },
22
- {
23
- id: TENANT_GENERAL_TABS_IDS.diagnostics,
24
- title: 'Diagnostics',
25
- icon: <Icon name="diagnostics" viewBox="0 0 17 16" />,
26
- },
27
- ];
28
15
  export const TENANT_INFO_TABS = [
29
16
  {
30
17
  id: TenantInfoTabsIds.overview,
@@ -42,3 +29,7 @@ export const TENANT_SCHEMA_TAB = [
42
29
  title: 'Schema',
43
30
  },
44
31
  ];
32
+
33
+ export const getTenantPath = (query = {}) => {
34
+ return createHref(routes.tenant, undefined, query);
35
+ };
@@ -0,0 +1,10 @@
1
+ import type {Settings} from '@gravity-ui/react-data-table';
2
+
3
+ import {DEFAULT_TABLE_SETTINGS} from '../../../utils/constants';
4
+
5
+ export const MAX_QUERY_HEIGHT = 6;
6
+
7
+ export const QUERY_TABLE_SETTINGS: Settings = {
8
+ ...DEFAULT_TABLE_SETTINGS,
9
+ dynamicRenderType: 'variable',
10
+ };
@@ -3,8 +3,11 @@ import type {NavigationTreeNodeType, NavigationTreeProps} from 'ydb-ui-component
3
3
 
4
4
  import {changeUserInput} from '../../../store/reducers/executeQuery';
5
5
  import {setShowPreview} from '../../../store/reducers/schema/schema';
6
- import {setTopLevelTab} from '../../../store/reducers/tenant/tenant';
7
- import {TENANT_GENERAL_TABS_IDS} from '../../../store/reducers/tenant/constants';
6
+ import {setQueryTab, setTenantPage} from '../../../store/reducers/tenant/tenant';
7
+ import {
8
+ TENANT_QUERY_TABS_ID,
9
+ TENANT_PAGES_IDS,
10
+ } from '../../../store/reducers/tenant/constants';
8
11
  import createToast from '../../../utils/createToast';
9
12
 
10
13
  const createTableTemplate = (path: string) => {
@@ -37,7 +40,8 @@ const bindActions = (
37
40
  ) => {
38
41
  const inputQuery = (tmpl: (path: string) => string) => () => {
39
42
  dispatch(changeUserInput({input: tmpl(path)}));
40
- dispatch(setTopLevelTab(TENANT_GENERAL_TABS_IDS.query));
43
+ dispatch(setTenantPage(TENANT_PAGES_IDS.query));
44
+ dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
41
45
  setActivePath(path);
42
46
  };
43
47
 
@@ -66,7 +70,8 @@ const bindActions = (
66
70
  },
67
71
  openPreview: () => {
68
72
  dispatch(setShowPreview(true));
69
- dispatch(setTopLevelTab(TENANT_GENERAL_TABS_IDS.query));
73
+ dispatch(setTenantPage(TENANT_PAGES_IDS.query));
74
+ dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
70
75
  setActivePath(path);
71
76
  },
72
77
  };
@@ -18,7 +18,8 @@ import {AutoFetcher} from '../../utils/autofetcher';
18
18
  import routes, {createHref} from '../../routes';
19
19
  import {formatCPU, formatBytesToGigabyte, formatNumber} from '../../utils';
20
20
  import {withSearch} from '../../HOCS';
21
- import {DEFAULT_TABLE_SETTINGS, TENANT_INITIAL_TAB_KEY} from '../../utils/constants';
21
+ import {DEFAULT_TABLE_SETTINGS, TENANT_INITIAL_PAGE_KEY} from '../../utils/constants';
22
+ import {TENANT_PAGES_IDS} from '../../store/reducers/tenant/constants';
22
23
  import {getTenantsInfo} from '../../store/reducers/tenants/tenants';
23
24
  import {
24
25
  changeFilter,
@@ -27,7 +28,7 @@ import {
27
28
  } from '../../store/reducers/settings/settings';
28
29
 
29
30
  import {clusterName} from '../../store';
30
- import {TenantTabsGroups, TENANT_GENERAL_TABS, TENANT_INFO_TABS} from '../Tenant/TenantPages';
31
+ import {TenantTabsGroups, TENANT_INFO_TABS} from '../Tenant/TenantPages';
31
32
 
32
33
  import './Tenants.scss';
33
34
 
@@ -123,18 +124,22 @@ class Tenants extends React.Component {
123
124
  });
124
125
  const filteredTenants = Tenants.filterTenants(filteredTenantsBySearch, filter);
125
126
 
126
- const initialTenantGeneralTab = savedTenantInitialTab || TENANT_GENERAL_TABS[0].id;
127
+ const initialTenantGeneralTab = savedTenantInitialTab || TENANT_PAGES_IDS.query;
127
128
  const initialTenantInfoTab = TENANT_INFO_TABS[0].id;
128
129
 
130
+ const getTenantBackend = (tenant) => {
131
+ const backend = tenant.MonitoringEndpoint ?? tenant.backend;
132
+ return additionalTenantsInfo.tenantBackend
133
+ ? additionalTenantsInfo.tenantBackend(backend)
134
+ : undefined;
135
+ };
136
+
129
137
  const columns = [
130
138
  {
131
139
  name: 'Name',
132
140
  header: 'Database',
133
141
  render: ({value, row}) => {
134
- const backend = row.MonitoringEndpoint ?? row.backend;
135
- const tenantBackend = additionalTenantsInfo.tenantBackend
136
- ? additionalTenantsInfo.tenantBackend(backend)
137
- : undefined;
142
+ const backend = getTenantBackend(row);
138
143
  const isExternalLink = Boolean(backend);
139
144
  return (
140
145
  <div className={b('name-wrapper')}>
@@ -147,7 +152,7 @@ class Tenants extends React.Component {
147
152
  hasClipboardButton
148
153
  path={createHref(routes.tenant, undefined, {
149
154
  name: value,
150
- backend: tenantBackend,
155
+ backend,
151
156
  [TenantTabsGroups.info]: initialTenantInfoTab,
152
157
  [TenantTabsGroups.general]: initialTenantGeneralTab,
153
158
  })}
@@ -287,12 +292,20 @@ class Tenants extends React.Component {
287
292
  header: 'Tablets States',
288
293
  sortable: false,
289
294
  width: 430,
290
- render: ({value, row}) =>
291
- value ? (
292
- <TabletsStatistic path={row.Name} tablets={value} nodeIds={row.NodeIds} />
295
+ render: ({value, row}) => {
296
+ const backend = getTenantBackend(row);
297
+
298
+ return value ? (
299
+ <TabletsStatistic
300
+ path={row.Name}
301
+ tablets={value}
302
+ nodeIds={row.NodeIds}
303
+ backend={backend}
304
+ />
293
305
  ) : (
294
306
  '—'
295
- ),
307
+ );
308
+ },
296
309
  },
297
310
  ];
298
311
 
@@ -347,7 +360,7 @@ const mapStateToProps = (state) => {
347
360
  loading,
348
361
  error,
349
362
  filter: state.settings.problemFilter,
350
- savedTenantInitialTab: getSettingValue(state, TENANT_INITIAL_TAB_KEY),
363
+ savedTenantInitialTab: getSettingValue(state, TENANT_INITIAL_PAGE_KEY),
351
364
  };
352
365
  };
353
366