ydb-embedded-ui 1.4.2 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/components/GroupTreeViewer/GroupTreeViewer.js +3 -2
  3. package/dist/components/GroupTreeViewer/GroupTreeViewer.scss +0 -2
  4. package/dist/components/SplitPane/SplitPane.tsx +8 -8
  5. package/dist/containers/App/App.js +1 -0
  6. package/dist/containers/App/App.scss +0 -26
  7. package/dist/containers/Tenant/Diagnostics/Healthcheck/IssuesViewer/IssueViewer.scss +11 -23
  8. package/dist/containers/Tenant/Diagnostics/Healthcheck/IssuesViewer/IssuesViewer.js +7 -7
  9. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.scss +9 -15
  10. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +16 -15
  11. package/dist/containers/Tenant/QueryEditor/QueryEditor.js +2 -2
  12. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +64 -0
  13. package/dist/containers/Tenant/Tenant.tsx +2 -2
  14. package/dist/containers/Tenant/utils/schema.ts +17 -0
  15. package/dist/containers/Tenant/utils/schemaActions.ts +130 -0
  16. package/dist/services/api.d.ts +3 -0
  17. package/dist/services/api.js +2 -2
  18. package/package.json +8 -4
  19. package/dist/components/TreeView/TreeView.js +0 -60
  20. package/dist/components/TreeView/TreeView.scss +0 -39
  21. package/dist/containers/Tenant/Schema/SchemaNode/SchemaNode.js +0 -170
  22. package/dist/containers/Tenant/Schema/SchemaNode/SchemaNode.scss +0 -62
  23. package/dist/containers/Tenant/Schema/SchemaNodeActions/SchemaNodeActions.scss +0 -17
  24. package/dist/containers/Tenant/Schema/SchemaNodeActions/SchemaNodeActions.tsx +0 -125
  25. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.js +0 -116
  26. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.scss +0 -17
  27. package/dist/styles/react-treeview.scss +0 -45
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.5.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.4.2...v1.5.0) (2022-05-24)
4
+
5
+
6
+ ### Features
7
+
8
+ * **Healthcheck:** use TreeView in issues viewer ([bcd81e5](https://github.com/ydb-platform/ydb-embedded-ui/commit/bcd81e56dc613cf3e9f31d77d930b79e070372e4))
9
+ * **Tenant:** use NavigationTree for schemas ([f2867e1](https://github.com/ydb-platform/ydb-embedded-ui/commit/f2867e18898028ca265df46fcc8bfa4f929173f0))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * **Healthcheck:** don't display reasonsItems in issues viewer ([f0a545f](https://github.com/ydb-platform/ydb-embedded-ui/commit/f0a545f7c70d449c121d64f8d1820e53b880a0fc))
15
+ * **Tenant:** add ellipsis to menu items inserting queries ([09135a2](https://github.com/ydb-platform/ydb-embedded-ui/commit/09135a2777ec9183ddf71bd2a4de66c5ef422ac8))
16
+ * **Tenant:** change messages for path copy toasts ([09adfa5](https://github.com/ydb-platform/ydb-embedded-ui/commit/09adfa52735bf706deb1ee9bf37f4bfa459b3758))
17
+ * **Tenant:** switch to query tab for inserted query ([991f156](https://github.com/ydb-platform/ydb-embedded-ui/commit/991f156ff819c58ff79146a44b57fb400729f325))
18
+
3
19
  ### [1.4.2](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.4.1...v1.4.2) (2022-05-23)
4
20
 
5
21
 
@@ -3,10 +3,11 @@ import PropTypes from 'prop-types';
3
3
  import cn from 'bem-cn-lite';
4
4
  import {withRouter} from 'react-router';
5
5
 
6
+ import {TreeView} from 'ydb-ui-components';
7
+
6
8
  import GroupViewer from '../GroupViewer/GroupViewer';
7
9
  import PDiskViewer from '../PDiskViewer/PDiskViewer';
8
10
  import EntityStatus from '../EntityStatus/EntityStatus';
9
- import TreeView from '../TreeView/TreeView';
10
11
  import {stringifyVdiskId} from '../../utils';
11
12
  import routes, {createHref} from '../../routes';
12
13
  import {backend} from '../../store';
@@ -50,7 +51,7 @@ class GroupTreeViewer extends React.Component {
50
51
  <div className={b()}>
51
52
  <TreeView
52
53
  key={group.GroupID}
53
- nodeLabel={label2}
54
+ name={label2}
54
55
  collapsed={collapsed}
55
56
  onClick={onClick}
56
57
  >
@@ -1,5 +1,3 @@
1
- @import '../../styles/react-treeview';
2
-
3
1
  .group-tree-viewer {
4
2
  &__row {
5
3
  display: flex;
@@ -18,8 +18,8 @@ interface SplitPaneProps {
18
18
  minSize?: number[];
19
19
  triggerCollapse?: boolean;
20
20
  triggerExpand?: boolean;
21
- onSplitStartDrugAdditional?: VoidFunction;
22
- onSplitDrugAdditional?: VoidFunction;
21
+ onSplitStartDragAdditional?: VoidFunction;
22
+ onSplitDragAdditional?: VoidFunction;
23
23
  }
24
24
 
25
25
  const minSizeDefaultInner = [0, 100];
@@ -41,17 +41,17 @@ function SplitPane(props: SplitPaneProps) {
41
41
  localStorage.setItem(defaultSizePaneKey, sizes.join(','));
42
42
  };
43
43
  const onDragHandler = (sizes: number[]) => {
44
- const {onSplitDrugAdditional} = props;
45
- if (onSplitDrugAdditional) {
46
- onSplitDrugAdditional();
44
+ const {onSplitDragAdditional} = props;
45
+ if (onSplitDragAdditional) {
46
+ onSplitDragAdditional();
47
47
  }
48
48
  setDefaultSizePane(sizes);
49
49
  };
50
50
 
51
51
  const onDragStartHandler = () => {
52
- const {onSplitStartDrugAdditional} = props;
53
- if (onSplitStartDrugAdditional) {
54
- onSplitStartDrugAdditional();
52
+ const {onSplitStartDragAdditional} = props;
53
+ if (onSplitStartDragAdditional) {
54
+ onSplitStartDragAdditional();
55
55
  }
56
56
  setInnerSizes(undefined);
57
57
  };
@@ -25,6 +25,7 @@ class App extends React.Component {
25
25
  constructor(props) {
26
26
  super(props);
27
27
  i18n.setLang(I18N.LANGS.en);
28
+ I18N.setDefaultLang(I18N.LANGS.en); // for the peer dependency ydb-ui-components, should match the language above
28
29
  }
29
30
 
30
31
  componentDidMount() {
@@ -117,32 +117,6 @@ body,
117
117
  border-color: var(--yc-color-text-danger);
118
118
  }
119
119
 
120
- .tree-view_item {
121
- /* stylelint-disable-next-line declaration-no-important*/
122
- cursor: default !important;
123
- }
124
-
125
- .tree-view_children {
126
- margin-left: 25px;
127
- }
128
-
129
- .tree-view_arrow {
130
- padding: 2px;
131
-
132
- line-height: 0.8;
133
-
134
- transform: rotate(90deg);
135
- }
136
-
137
- .tree-view_arrow-collapsed {
138
- transform: rotate(0deg);
139
- }
140
-
141
- .tree-view_arrow:after {
142
- font-size: var(--yc-text-body2-font-size);
143
- content: '❯';
144
- }
145
-
146
120
  .data-table__row:hover .entity-status__clipboard-button {
147
121
  display: flex;
148
122
  }
@@ -5,37 +5,14 @@
5
5
  align-items: center;
6
6
 
7
7
  height: 40px;
8
- margin-left: 36px;
9
8
 
10
9
  cursor: pointer;
11
- .km-tree-view__arrow-icon + & {
12
- margin-left: 0;
13
- }
14
10
 
15
11
  &_active {
16
12
  border-radius: 4px;
17
13
  background: var(--yc-color-base-info);
18
14
  }
19
15
 
20
- &__wpapper {
21
- & .km-tree-view__node-wrapper {
22
- height: 40px;
23
-
24
- & .km-tree-view__arrow-icon {
25
- display: flex;
26
- align-items: center;
27
-
28
- width: 36px;
29
- height: 36px;
30
- margin: 0;
31
- }
32
- }
33
-
34
- & .tree-view_item {
35
- margin: 0;
36
- }
37
- }
38
-
39
16
  &__field {
40
17
  padding: 0 10px;
41
18
 
@@ -173,4 +150,15 @@
173
150
  }
174
151
  }
175
152
  }
153
+
154
+ .ydb-tree-view {
155
+ &__item {
156
+ height: 40px;
157
+ }
158
+
159
+ .tree-view_arrow {
160
+ width: 40px;
161
+ height: 40px;
162
+ }
163
+ }
176
164
  }
@@ -7,7 +7,8 @@ import _filter from 'lodash/fp/filter';
7
7
  import _sortBy from 'lodash/fp/sortBy';
8
8
  import _uniqBy from 'lodash/fp/uniqBy';
9
9
 
10
- import TreeView from '../../../../../components/TreeView/TreeView';
10
+ import {TreeView} from 'ydb-ui-components';
11
+
11
12
  import EntityStatus from '../../../../../components/EntityStatus/EntityStatus';
12
13
 
13
14
  import './IssueViewer.scss';
@@ -29,7 +30,7 @@ const issueBlock = cn('issue');
29
30
 
30
31
  const IssueRow = ({data, treeLevel, active, setInfoForActive, onClick}) => {
31
32
  // eslint-disable-next-line no-unused-vars
32
- const {id, status, message, type, ...rest} = data;
33
+ const {id, status, message, type, reasonsItems, ...rest} = data;
33
34
 
34
35
  useEffect(() => {
35
36
  if (active) {
@@ -45,7 +46,7 @@ const IssueRow = ({data, treeLevel, active, setInfoForActive, onClick}) => {
45
46
  </div>
46
47
  <div
47
48
  className={issueBlock('field', {message: true})}
48
- style={{marginLeft: -treeLevel * 25 + 'px'}}
49
+ style={{marginLeft: -treeLevel * 24 + 'px'}}
49
50
  >
50
51
  {message}
51
52
  </div>
@@ -85,21 +86,20 @@ const IssuesViewer = ({issues}) => {
85
86
  return (
86
87
  <TreeView
87
88
  key={id}
88
- nodeLabel={
89
+ name={
89
90
  <IssueRow
90
91
  data={item}
91
92
  treeLevel={treeLevel}
92
93
  active={isActive}
93
94
  setInfoForActive={setInfoData}
94
- onClick={() => setActiveItem(id)}
95
95
  />
96
96
  }
97
- className={issueBlock('wpapper', {active: isActive})}
98
97
  collapsed={
99
98
  typeof collapsedIssues[id] === 'undefined' || collapsedIssues[id]
100
99
  }
101
100
  hasArrow={hasArrow}
102
- onClick={() => {
101
+ onClick={() => setActiveItem(id)}
102
+ onArrowClick={() => {
103
103
  const newValue =
104
104
  typeof collapsedIssues[id] === 'undefined'
105
105
  ? false
@@ -26,8 +26,8 @@
26
26
 
27
27
  &__action-button {
28
28
  position: absolute;
29
- top: 12px;
30
- right: 4px;
29
+ top: 8px; // centered relative to the heading
30
+ right: 5px; // centered relative to the collapsed panel
31
31
 
32
32
  background-color: var(--yc-color-base-background);
33
33
  &_hidden {
@@ -41,32 +41,26 @@
41
41
  align-items: center;
42
42
  }
43
43
 
44
- &__tree {
44
+ &__tree-wrapper {
45
45
  display: flex;
46
- overflow: scroll;
47
- flex: 0 0 auto;
48
46
  flex-direction: column;
47
+ }
48
+
49
+ &__tree {
50
+ overflow-y: scroll;
51
+ flex: 1 1 auto;
49
52
 
50
53
  height: 100%;
51
54
  padding: 0 12px 12px;
52
-
53
- .tree-view_item {
54
- margin: 0;
55
- padding: 2px 0;
56
- }
57
-
58
- & > div > .tree-view {
59
- padding-bottom: 15px;
60
- }
61
55
  }
62
56
 
63
57
  &__tree-header {
64
58
  display: flex;
59
+ flex: 0 0 auto;
65
60
  justify-content: space-between;
66
61
  align-items: center;
67
62
 
68
63
  padding: 12px 12px 8px;
69
- @include sticky-top();
70
64
  }
71
65
 
72
66
  &__tree-title {
@@ -7,18 +7,13 @@ import qs from 'qs';
7
7
  import _ from 'lodash';
8
8
 
9
9
  import {Button, HelpTooltip, Loader, Tabs} from '@yandex-cloud/uikit';
10
- //@ts-ignore
10
+
11
11
  import SplitPane from '../../../components/SplitPane';
12
- //@ts-ignore
13
- import SchemaNode from '../Schema/SchemaNode/SchemaNode';
14
- //@ts-ignore
12
+ import {SchemaTree} from '../Schema/SchemaTree/SchemaTree';
15
13
  import Acl from '../Acl/Acl';
16
- //@ts-ignore
17
14
  import SchemaViewer from '../Schema/SchemaViewer/SchemaViewer';
18
15
  import CopyToClipboard from '../../../components/CopyToClipboard/CopyToClipboard';
19
- //@ts-ignore
20
16
  import InfoViewer from '../../../components/InfoViewer/InfoViewer';
21
- //@ts-ignore
22
17
  import Icon from '../../../components/Icon/Icon';
23
18
 
24
19
  import {OLAP_TABLE_TYPE, TABLE_TYPE} from '../Tenant';
@@ -26,7 +21,6 @@ import {OLAP_TABLE_TYPE, TABLE_TYPE} from '../Tenant';
26
21
  import {
27
22
  DEFAULT_IS_TENANT_COMMON_INFO_COLLAPSED,
28
23
  DEFAULT_SIZE_TENANT_SUMMARY_KEY,
29
- //@ts-ignore
30
24
  } from '../../../utils/constants';
31
25
  import {
32
26
  TenantGeneralTabsIds,
@@ -41,10 +35,10 @@ import {
41
35
  paneVisibilityToggleReducerCreator,
42
36
  PaneVisibilityToggleButtons,
43
37
  } from '../utils/paneVisibilityToggleHelpers';
44
- //@ts-ignore
45
38
  import {setShowPreview} from '../../../store/reducers/schema';
46
39
 
47
40
  import './ObjectSummary.scss';
41
+
48
42
  const b = cn('object-summary');
49
43
 
50
44
  const getInitialIsSummaryCollapsed = () => {
@@ -103,7 +97,7 @@ function ObjectSummary(props: ObjectSummaryProps) {
103
97
  });
104
98
 
105
99
  const {name: tenantName, info: infoTab} = queryParams;
106
- const tenantData = _.get(data[tenantName as string], 'PathDescription.Self');
100
+ const pathData = _.get(data[tenantName as string], 'PathDescription.Self');
107
101
  const currentSchemaData = _.get(data[currentSchemaPath], 'PathDescription.Self');
108
102
 
109
103
  const tableSchema =
@@ -195,13 +189,20 @@ function ObjectSummary(props: ObjectSummaryProps) {
195
189
 
196
190
  const renderTree = () => {
197
191
  return (
198
- <div>
192
+ <div className={b('tree-wrapper')}>
199
193
  <div className={b('tree-header')}>
200
194
  <div className={b('tree-title')}>Navigation</div>
201
195
  </div>
202
196
  <div className={b('tree')}>
203
- {tenantData && (
204
- <SchemaNode fullPath={tenantName as string} data={tenantData} isRoot />
197
+ {pathData && (
198
+ <SchemaTree
199
+ rootPath={tenantName as string}
200
+ // for the root pathData.Name contains the same string as tenantName,
201
+ // but without the leading slash
202
+ rootName={pathData?.Name || tenantName}
203
+ rootType={pathData.PathType}
204
+ currentPath={currentSchemaPath}
205
+ />
205
206
  )}
206
207
  </div>
207
208
  </div>
@@ -215,7 +216,7 @@ function ObjectSummary(props: ObjectSummaryProps) {
215
216
  dispatchCommonInfoVisibilityState(PaneVisibilityActionTypes.triggerExpand);
216
217
  };
217
218
 
218
- const onSplitStartDrugAdditional = () => {
219
+ const onSplitStartDragAdditional = () => {
219
220
  dispatchCommonInfoVisibilityState(PaneVisibilityActionTypes.clear);
220
221
  };
221
222
 
@@ -278,7 +279,7 @@ function ObjectSummary(props: ObjectSummaryProps) {
278
279
  <SplitPane
279
280
  direction="vertical"
280
281
  defaultSizePaneKey={DEFAULT_SIZE_TENANT_SUMMARY_KEY}
281
- onSplitStartDrugAdditional={onSplitStartDrugAdditional}
282
+ onSplitStartDragAdditional={onSplitStartDragAdditional}
282
283
  triggerCollapse={commonInfoVisibilityState.triggerCollapse}
283
284
  triggerExpand={commonInfoVisibilityState.triggerExpand}
284
285
  minSize={[200, 52]}
@@ -298,7 +298,7 @@ function QueryEditor(props) {
298
298
  dispatchResultVisibilityState(PaneVisibilityActionTypes.triggerExpand);
299
299
  };
300
300
 
301
- const onSplitStartDrugAdditional = () => {
301
+ const onSplitStartDragAdditional = () => {
302
302
  dispatchResultVisibilityState(PaneVisibilityActionTypes.clear);
303
303
  };
304
304
 
@@ -636,7 +636,7 @@ function QueryEditor(props) {
636
636
  triggerExpand={resultVisibilityState.triggerExpand}
637
637
  minSize={[0, 52]}
638
638
  collapsedSizes={[100, 0]}
639
- onSplitStartDrugAdditional={onSplitStartDrugAdditional}
639
+ onSplitStartDragAdditional={onSplitStartDragAdditional}
640
640
  >
641
641
  <div className={b('pane-wrapper')}>
642
642
  <div className={b('monaco-wrapper')}>
@@ -0,0 +1,64 @@
1
+ import {useDispatch} from 'react-redux';
2
+ import {useHistory} from 'react-router';
3
+
4
+ import {NavigationTree} from 'ydb-ui-components';
5
+
6
+ import {setCurrentSchemaPath, getSchema} from '../../../../store/reducers/schema';
7
+ import {getDescribe} from '../../../../store/reducers/describe';
8
+ import {getSchemaAcl} from '../../../../store/reducers/schemaAcl';
9
+
10
+ import {calcNavigationTreeType} from '../../utils/schema';
11
+ import {getActions} from '../../utils/schemaActions';
12
+
13
+ interface SchemaTreeProps {
14
+ rootPath: string;
15
+ rootName: string;
16
+ rootType: string;
17
+ currentPath: string;
18
+ }
19
+
20
+ export function SchemaTree(props: SchemaTreeProps) {
21
+ const {
22
+ rootPath,
23
+ rootName,
24
+ rootType,
25
+ currentPath,
26
+ } = props;
27
+
28
+ const dispatch = useDispatch();
29
+ const history = useHistory();
30
+
31
+ const fetchPath = (path: string) => window.api.getSchema(
32
+ {path},
33
+ {concurrentId: `NavigationTree.getSchema|${path}`},
34
+ )
35
+ .then(({PathDescription: {Children = []} = {}}) => {
36
+ return Children.map(({Name, PathType}) => ({
37
+ name: Name,
38
+ type: calcNavigationTreeType(PathType),
39
+ }));
40
+ });
41
+
42
+ const handleActivePathUpdate = (activePath: string) => {
43
+ dispatch(setCurrentSchemaPath(activePath));
44
+ dispatch(getSchema({path: activePath}));
45
+ dispatch(getDescribe({path: activePath}));
46
+ dispatch(getSchemaAcl({path: activePath}));
47
+ };
48
+
49
+ return (
50
+ <NavigationTree
51
+ rootState={{
52
+ path: rootPath,
53
+ name: rootName,
54
+ type: calcNavigationTreeType(rootType),
55
+ collapsed: false,
56
+ }}
57
+ fetchPath={fetchPath}
58
+ getActions={getActions(dispatch, history, handleActivePathUpdate)}
59
+ activePath={currentPath}
60
+ onActivePathUpdate={handleActivePathUpdate}
61
+ cache={false}
62
+ />
63
+ );
64
+ }
@@ -127,7 +127,7 @@ function Tenant(props: TenantProps) {
127
127
  dispatchSummaryVisibilityAction(PaneVisibilityActionTypes.triggerExpand);
128
128
  };
129
129
 
130
- const onSplitStartDrugAdditional = () => {
130
+ const onSplitStartDragAdditional = () => {
131
131
  dispatchSummaryVisibilityAction(PaneVisibilityActionTypes.clear);
132
132
  };
133
133
 
@@ -139,7 +139,7 @@ function Tenant(props: TenantProps) {
139
139
  triggerCollapse={summaryVisibilityState.triggerCollapse}
140
140
  triggerExpand={summaryVisibilityState.triggerExpand}
141
141
  minSize={[36, 200]}
142
- onSplitStartDrugAdditional={onSplitStartDrugAdditional}
142
+ onSplitStartDragAdditional={onSplitStartDragAdditional}
143
143
  >
144
144
  <ObjectSummary
145
145
  type={entityType as string}
@@ -0,0 +1,17 @@
1
+ import type {NavigationTreeNodeType} from "ydb-ui-components";
2
+
3
+ const DB_TYPES = new Set(['EPathTypeSubDomain']);
4
+ const TABLE_TYPES = new Set(['EPathTypeTable', 'EPathTypeOlapTable']);
5
+ const DIR_TYPES = new Set(['EPathTypeDir', 'EPathTypeOlapStore']);
6
+
7
+ export const calcNavigationTreeType = (type: string): NavigationTreeNodeType => {
8
+ if (DIR_TYPES.has(type)) {
9
+ return 'directory';
10
+ } else if (TABLE_TYPES.has(type)) {
11
+ return 'table';
12
+ } else if (DB_TYPES.has(type)) {
13
+ return 'database';
14
+ }
15
+
16
+ return 'directory';
17
+ };
@@ -0,0 +1,130 @@
1
+ import qs from 'qs';
2
+ import {Dispatch} from 'react';
3
+ import {History} from 'history';
4
+ import type {NavigationTreeNodeType} from 'ydb-ui-components';
5
+
6
+ import routes, {createHref} from '../../../routes';
7
+ import {changeUserInput} from '../../../store/reducers/executeQuery';
8
+ import {setShowPreview} from '../../../store/reducers/schema';
9
+ import createToast from '../../../utils/createToast';
10
+ import {TenantGeneralTabsIds, TenantTabsGroups} from '../TenantPages';
11
+
12
+ const createTableTemplate = (path: string) => {
13
+ return `CREATE TABLE \`${path}/my_table\`
14
+ (
15
+ \`id\` Uint64,
16
+ \`name\` String,
17
+ PRIMARY KEY (\`id\`)
18
+ );`;
19
+ };
20
+
21
+ const alterTableTemplate = (path: string) => {
22
+ return `ALTER TABLE \`${path}\`
23
+ ADD COLUMN is_deleted Bool;`;
24
+ };
25
+ const selectQueryTemplate = (path: string) => {
26
+ return `SELECT \`id\`, \`name\`
27
+ FROM \`${path}\`
28
+ ORDER BY \`id\`
29
+ LIMIT 10;`;
30
+ };
31
+ const upsertQueryTemplate = (path: string) => {
32
+ return `UPSERT INTO \`${path}\`
33
+ ( \`id\`, \`name\` )
34
+ VALUES ( );`;
35
+ };
36
+
37
+ export const getActions = (
38
+ dispatch: Dispatch<any>,
39
+ history: History<unknown>,
40
+ setActivePath: (path: string) => void,
41
+ ) =>
42
+ (path: string, type: NavigationTreeNodeType) => {
43
+ const queryParams = qs.parse(location.search, {
44
+ ignoreQueryPrefix: true,
45
+ });
46
+
47
+ const switchTabToQuery = () => {
48
+ history.push(
49
+ createHref(routes.tenant, undefined, {
50
+ ...queryParams,
51
+ [TenantTabsGroups.general]: TenantGeneralTabsIds.query,
52
+ }),
53
+ );
54
+ };
55
+
56
+ const onCreateTableClick = () => {
57
+ dispatch(changeUserInput({input: createTableTemplate(path)}));
58
+ switchTabToQuery();
59
+ // here and in the other handlers this should be called after switching tab:
60
+ // redux-location-state catches the history.push event from the tab switching
61
+ // before active path updates in url, preventing its update at all
62
+ setActivePath(path);
63
+ };
64
+
65
+ const onAlterTableClick = () => {
66
+ dispatch(changeUserInput({input: alterTableTemplate(path)}));
67
+ switchTabToQuery();
68
+ setActivePath(path);
69
+ };
70
+
71
+ const onSelectQueryClick = () => {
72
+ dispatch(changeUserInput({input: selectQueryTemplate(path)}));
73
+ switchTabToQuery();
74
+ setActivePath(path);
75
+ };
76
+
77
+ const onUpsertQueryClick = () => {
78
+ dispatch(changeUserInput({input: upsertQueryTemplate(path)}));
79
+ switchTabToQuery();
80
+ setActivePath(path);
81
+ };
82
+
83
+ const onCopyPathClick = () => {
84
+ navigator.clipboard
85
+ .writeText(path)
86
+ .then(() => {
87
+ createToast({
88
+ name: 'Copied',
89
+ title: 'The path is copied to the clipboard',
90
+ type: 'success',
91
+ });
92
+ })
93
+ .catch(() => {
94
+ createToast({
95
+ name: 'Not copied',
96
+ title: 'Couldn’t copy the path',
97
+ type: 'error',
98
+ });
99
+ });
100
+ };
101
+
102
+ const onOpenPreviewClick = () => {
103
+ dispatch(setShowPreview(true));
104
+ switchTabToQuery();
105
+ setActivePath(path);
106
+ };
107
+
108
+ const copyItem = {text: 'Copy path', action: onCopyPathClick};
109
+
110
+ return type === 'table'
111
+ ? [
112
+ [
113
+ {text: 'Open preview', action: onOpenPreviewClick},
114
+ copyItem,
115
+ ],
116
+ [
117
+ {text: 'Alter table...', action: onAlterTableClick},
118
+ {text: 'Select query...', action: onSelectQueryClick},
119
+ {text: 'Upsert query...', action: onUpsertQueryClick},
120
+ ],
121
+ ]
122
+ : [
123
+ [
124
+ copyItem,
125
+ ],
126
+ [
127
+ {text: 'Create table...', action: onCreateTableClick},
128
+ ],
129
+ ];
130
+ };
@@ -0,0 +1,3 @@
1
+ interface Window {
2
+ api: any;
3
+ }
@@ -76,7 +76,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
76
76
  enums: true,
77
77
  });
78
78
  }
79
- getSchema({path}) {
79
+ getSchema({path}, {concurrentId} = {}) {
80
80
  return this.get(
81
81
  this.getPath('/viewer/json/describe'),
82
82
  {
@@ -88,7 +88,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
88
88
  partition_stats: false,
89
89
  partitioning_info: false,
90
90
  },
91
- {concurrentId: `getSchema|${path}`},
91
+ {concurrentId: concurrentId || `getSchema|${path}`},
92
92
  );
93
93
  }
94
94
  getDescribe({path}) {