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.
- package/CHANGELOG.md +16 -0
- package/dist/components/GroupTreeViewer/GroupTreeViewer.js +3 -2
- package/dist/components/GroupTreeViewer/GroupTreeViewer.scss +0 -2
- package/dist/components/SplitPane/SplitPane.tsx +8 -8
- package/dist/containers/App/App.js +1 -0
- package/dist/containers/App/App.scss +0 -26
- package/dist/containers/Tenant/Diagnostics/Healthcheck/IssuesViewer/IssueViewer.scss +11 -23
- package/dist/containers/Tenant/Diagnostics/Healthcheck/IssuesViewer/IssuesViewer.js +7 -7
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.scss +9 -15
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +16 -15
- package/dist/containers/Tenant/QueryEditor/QueryEditor.js +2 -2
- package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +64 -0
- package/dist/containers/Tenant/Tenant.tsx +2 -2
- package/dist/containers/Tenant/utils/schema.ts +17 -0
- package/dist/containers/Tenant/utils/schemaActions.ts +130 -0
- package/dist/services/api.d.ts +3 -0
- package/dist/services/api.js +2 -2
- package/package.json +8 -4
- package/dist/components/TreeView/TreeView.js +0 -60
- package/dist/components/TreeView/TreeView.scss +0 -39
- package/dist/containers/Tenant/Schema/SchemaNode/SchemaNode.js +0 -170
- package/dist/containers/Tenant/Schema/SchemaNode/SchemaNode.scss +0 -62
- package/dist/containers/Tenant/Schema/SchemaNodeActions/SchemaNodeActions.scss +0 -17
- package/dist/containers/Tenant/Schema/SchemaNodeActions/SchemaNodeActions.tsx +0 -125
- package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.js +0 -116
- package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.scss +0 -17
- 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
|
-
|
54
|
+
name={label2}
|
54
55
|
collapsed={collapsed}
|
55
56
|
onClick={onClick}
|
56
57
|
>
|
@@ -18,8 +18,8 @@ interface SplitPaneProps {
|
|
18
18
|
minSize?: number[];
|
19
19
|
triggerCollapse?: boolean;
|
20
20
|
triggerExpand?: boolean;
|
21
|
-
|
22
|
-
|
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 {
|
45
|
-
if (
|
46
|
-
|
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 {
|
53
|
-
if (
|
54
|
-
|
52
|
+
const {onSplitStartDragAdditional} = props;
|
53
|
+
if (onSplitStartDragAdditional) {
|
54
|
+
onSplitStartDragAdditional();
|
55
55
|
}
|
56
56
|
setInnerSizes(undefined);
|
57
57
|
};
|
@@ -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 '
|
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 *
|
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
|
-
|
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:
|
30
|
-
right:
|
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
|
-
|
10
|
+
|
11
11
|
import SplitPane from '../../../components/SplitPane';
|
12
|
-
|
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
|
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
|
-
{
|
204
|
-
<
|
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
|
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
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
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
|
+
};
|
package/dist/services/api.js
CHANGED
@@ -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}) {
|