ydb-embedded-ui 1.4.2 → 1.5.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 (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}) {