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/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "ydb-embedded-ui",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.5.0",
|
4
4
|
"files": [
|
5
5
|
"dist"
|
6
6
|
],
|
@@ -13,7 +13,7 @@
|
|
13
13
|
"@testing-library/react": "11.2.7",
|
14
14
|
"@testing-library/user-event": "12.8.3",
|
15
15
|
"@types/qs": "6.9.7",
|
16
|
-
"@yandex-cloud/i18n": "0.
|
16
|
+
"@yandex-cloud/i18n": "0.4.0",
|
17
17
|
"@yandex-cloud/paranoid": "1.0.0",
|
18
18
|
"@yandex-cloud/react-data-table": "0.2.1",
|
19
19
|
"axios": "0.19.2",
|
@@ -34,13 +34,13 @@
|
|
34
34
|
"react-scripts": "4.0.3",
|
35
35
|
"react-split": "2.0.14",
|
36
36
|
"react-transition-group": "4.4.2",
|
37
|
-
"react-treeview": "0.4.7",
|
38
37
|
"redux": "4.0.1",
|
39
38
|
"redux-location-state": "2.6.0",
|
40
39
|
"redux-thunk": "2.3.0",
|
41
40
|
"reselect": "4.0.0",
|
42
41
|
"sass": "1.32.8",
|
43
|
-
"web-vitals": "1.1.2"
|
42
|
+
"web-vitals": "1.1.2",
|
43
|
+
"ydb-ui-components": "1.2.3"
|
44
44
|
},
|
45
45
|
"scripts": {
|
46
46
|
"start": "react-app-rewired start",
|
@@ -88,6 +88,7 @@
|
|
88
88
|
"@types/react-transition-group": "^4.4.4",
|
89
89
|
"@types/react-virtualized-auto-sizer": "^1.0.1",
|
90
90
|
"@yandex-cloud/axios-wrapper": "^1.0.2",
|
91
|
+
"@yandex-cloud/browserslist-config": "1.0.1",
|
91
92
|
"@yandex-cloud/eslint-config": "^1.0.0",
|
92
93
|
"@yandex-cloud/prettier-config": "^1.0.0",
|
93
94
|
"@yandex-cloud/stylelint-config": "^1.1.0",
|
@@ -104,5 +105,8 @@
|
|
104
105
|
"react-dom": "^17.0.2",
|
105
106
|
"stylelint": "^14.3.0",
|
106
107
|
"typescript": "^4.5.5"
|
108
|
+
},
|
109
|
+
"peerDependencies": {
|
110
|
+
"@yandex-cloud/browserslist-config": "^1.0.1"
|
107
111
|
}
|
108
112
|
}
|
@@ -1,60 +0,0 @@
|
|
1
|
-
import PropTypes from 'prop-types';
|
2
|
-
import cn from 'bem-cn-lite';
|
3
|
-
import TreeViewBase from 'react-treeview';
|
4
|
-
import Icon from '../Icon/Icon';
|
5
|
-
|
6
|
-
import './TreeView.scss';
|
7
|
-
|
8
|
-
const b = cn('km-tree-view');
|
9
|
-
|
10
|
-
const TreeView = (props) => {
|
11
|
-
const {
|
12
|
-
children,
|
13
|
-
nodeLabel,
|
14
|
-
onClick,
|
15
|
-
collapsed,
|
16
|
-
clickableLabel = false,
|
17
|
-
className,
|
18
|
-
hasArrow = true,
|
19
|
-
...rest
|
20
|
-
} = props;
|
21
|
-
|
22
|
-
const newNodeLabel = (
|
23
|
-
<div
|
24
|
-
className={b('node-wrapper', {clickable: clickableLabel})}
|
25
|
-
onClick={clickableLabel ? onClick : undefined}
|
26
|
-
>
|
27
|
-
{hasArrow ? (
|
28
|
-
<span
|
29
|
-
className={b('arrow-icon', {extended: !collapsed})}
|
30
|
-
onClick={clickableLabel ? undefined : onClick}
|
31
|
-
>
|
32
|
-
<Icon name="arrow-right" viewBox="0 0 6 11" width={6} height={11} />
|
33
|
-
</span>
|
34
|
-
) : null}
|
35
|
-
{nodeLabel}
|
36
|
-
</div>
|
37
|
-
);
|
38
|
-
|
39
|
-
return (
|
40
|
-
<TreeViewBase
|
41
|
-
{...rest}
|
42
|
-
treeViewClassName={b(null, className)}
|
43
|
-
nodeLabel={newNodeLabel}
|
44
|
-
collapsed={collapsed}
|
45
|
-
>
|
46
|
-
{children}
|
47
|
-
</TreeViewBase>
|
48
|
-
);
|
49
|
-
};
|
50
|
-
|
51
|
-
TreeView.propTypes = {
|
52
|
-
children: PropTypes.any,
|
53
|
-
nodeLabel: PropTypes.node,
|
54
|
-
onClick: PropTypes.func,
|
55
|
-
collapsed: PropTypes.bool,
|
56
|
-
clickableLabel: PropTypes.bool,
|
57
|
-
className: PropTypes.string,
|
58
|
-
};
|
59
|
-
|
60
|
-
export default TreeView;
|
@@ -1,39 +0,0 @@
|
|
1
|
-
.km-tree-view {
|
2
|
-
& .tree-view_arrow {
|
3
|
-
display: none;
|
4
|
-
}
|
5
|
-
|
6
|
-
&__node-wrapper {
|
7
|
-
display: flex;
|
8
|
-
overflow: hidden;
|
9
|
-
align-items: center;
|
10
|
-
|
11
|
-
width: 100%;
|
12
|
-
|
13
|
-
&_clickable {
|
14
|
-
cursor: pointer;
|
15
|
-
}
|
16
|
-
}
|
17
|
-
|
18
|
-
&__arrow-icon {
|
19
|
-
display: flex;
|
20
|
-
justify-content: center;
|
21
|
-
|
22
|
-
width: 11px;
|
23
|
-
margin-right: 8px;
|
24
|
-
|
25
|
-
cursor: pointer;
|
26
|
-
|
27
|
-
&_extended {
|
28
|
-
transform: rotate(90deg);
|
29
|
-
}
|
30
|
-
|
31
|
-
& .yc-icon {
|
32
|
-
vertical-align: middle;
|
33
|
-
}
|
34
|
-
}
|
35
|
-
.yc-icon {
|
36
|
-
display: flex;
|
37
|
-
flex-shrink: 0;
|
38
|
-
}
|
39
|
-
}
|
@@ -1,170 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import {connect} from 'react-redux';
|
3
|
-
import PropTypes from 'prop-types';
|
4
|
-
import cn from 'bem-cn-lite';
|
5
|
-
|
6
|
-
import TreeView from '../../../../components/TreeView/TreeView';
|
7
|
-
import SchemaTree from '../../../Tenant/Schema/SchemaTree/SchemaTree';
|
8
|
-
import Icon from '../../../../components/Icon/Icon';
|
9
|
-
|
10
|
-
import {getSchema, setCurrentSchemaPath} from '../../../../store/reducers/schema';
|
11
|
-
import {getDescribe} from '../../../../store/reducers/describe';
|
12
|
-
import {getSchemaAcl} from '../../../../store/reducers/schemaAcl';
|
13
|
-
|
14
|
-
import './SchemaNode.scss';
|
15
|
-
import SchemaNodeActions from '../SchemaNodeActions/SchemaNodeActions';
|
16
|
-
import {isTableType} from '../../Tenant';
|
17
|
-
|
18
|
-
const b = cn('schema-node');
|
19
|
-
|
20
|
-
export const SUBDOMAIN_FOLDER_TYPE = 'EPathTypeSubDomain';
|
21
|
-
export const TABLE_TYPE = 'EPathTypeTable';
|
22
|
-
export const OLAP_TABLE_TYPE = 'EPathTypeOlapTable';
|
23
|
-
|
24
|
-
export const FOLDERS_TYPE = ['EPathTypeDir', 'EPathTypeExtSubDomain', 'EPathTypeOlapStore'];
|
25
|
-
|
26
|
-
class SchemaNode extends React.Component {
|
27
|
-
static propTypes = {
|
28
|
-
data: PropTypes.object.isRequired,
|
29
|
-
fullPath: PropTypes.string.isRequired,
|
30
|
-
getSchema: PropTypes.func.isRequired,
|
31
|
-
setCurrentSchemaPath: PropTypes.func,
|
32
|
-
currentSchemaPath: PropTypes.string,
|
33
|
-
isRoot: PropTypes.bool,
|
34
|
-
};
|
35
|
-
|
36
|
-
state = {
|
37
|
-
collapsed: true,
|
38
|
-
active: false,
|
39
|
-
};
|
40
|
-
|
41
|
-
schemaNodeRef = React.createRef();
|
42
|
-
|
43
|
-
componentDidMount() {
|
44
|
-
const {currentSchemaPath, isRoot} = this.props;
|
45
|
-
const schemaPath = this.getSchemaPath();
|
46
|
-
|
47
|
-
if (schemaPath === currentSchemaPath && !this.state.active) {
|
48
|
-
this.addActiveClass();
|
49
|
-
}
|
50
|
-
|
51
|
-
if (
|
52
|
-
(currentSchemaPath &&
|
53
|
-
currentSchemaPath.startsWith(schemaPath) &&
|
54
|
-
currentSchemaPath !== schemaPath) ||
|
55
|
-
isRoot
|
56
|
-
) {
|
57
|
-
this.setState({collapsed: false});
|
58
|
-
}
|
59
|
-
}
|
60
|
-
|
61
|
-
componentDidUpdate() {
|
62
|
-
const {currentSchemaPath} = this.props;
|
63
|
-
const schemaPath = this.getSchemaPath();
|
64
|
-
|
65
|
-
if (schemaPath === currentSchemaPath && !this.state.active) {
|
66
|
-
this.addActiveClass();
|
67
|
-
}
|
68
|
-
}
|
69
|
-
|
70
|
-
getSchemaPath = () => {
|
71
|
-
const {data, fullPath, isRoot} = this.props;
|
72
|
-
|
73
|
-
return isRoot ? fullPath : `${fullPath}/${data.Name}`;
|
74
|
-
};
|
75
|
-
|
76
|
-
invertCollapsed = () => {
|
77
|
-
this.setState({collapsed: !this.state.collapsed});
|
78
|
-
};
|
79
|
-
|
80
|
-
setIcon = (data) => {
|
81
|
-
const viewBox = '0 0 16 16';
|
82
|
-
const {collapsed} = this.state;
|
83
|
-
if (FOLDERS_TYPE.indexOf(data.PathType) !== -1) {
|
84
|
-
return collapsed ? (
|
85
|
-
<Icon name="folder" viewBox={viewBox} width={16} height={16} />
|
86
|
-
) : (
|
87
|
-
<Icon name="openFolder" viewBox={viewBox} width={16} height={16} />
|
88
|
-
);
|
89
|
-
} else if (data.PathType === TABLE_TYPE || data.PathType === OLAP_TABLE_TYPE) {
|
90
|
-
return <Icon name="table" viewBox={viewBox} width={16} height={16} />;
|
91
|
-
} else if (data.PathType === SUBDOMAIN_FOLDER_TYPE) {
|
92
|
-
return <Icon name="subdomain" viewBox={viewBox} width={16} height={16} />;
|
93
|
-
}
|
94
|
-
};
|
95
|
-
|
96
|
-
addActiveClass = () => {
|
97
|
-
const activeClass = 'schema-node_active';
|
98
|
-
const currentActiveSchemaNode = document.querySelector(`.${activeClass}`);
|
99
|
-
if (currentActiveSchemaNode) {
|
100
|
-
currentActiveSchemaNode.classList.remove(activeClass);
|
101
|
-
}
|
102
|
-
const activeNode = this.schemaNodeRef.current;
|
103
|
-
if (activeNode) {
|
104
|
-
this.setState({active: true});
|
105
|
-
activeNode.classList.add(activeClass);
|
106
|
-
}
|
107
|
-
};
|
108
|
-
|
109
|
-
handleClick = (e) => {
|
110
|
-
const {getSchema, getDescribe, getSchemaAcl, setCurrentSchemaPath} = this.props;
|
111
|
-
e.stopPropagation();
|
112
|
-
this.addActiveClass();
|
113
|
-
|
114
|
-
const schemaPath = this.getSchemaPath();
|
115
|
-
setCurrentSchemaPath(schemaPath);
|
116
|
-
getSchema({path: schemaPath});
|
117
|
-
getDescribe({path: schemaPath});
|
118
|
-
getSchemaAcl({path: schemaPath});
|
119
|
-
};
|
120
|
-
|
121
|
-
render() {
|
122
|
-
const {data, fullPath, isRoot = false, currentSchemaPath, currentItem = {}} = this.props;
|
123
|
-
const {collapsed} = this.state;
|
124
|
-
|
125
|
-
if (!data) {
|
126
|
-
return null;
|
127
|
-
}
|
128
|
-
const currentPathType = currentItem.PathDescription?.Self?.PathType;
|
129
|
-
const type = isTableType(currentPathType);
|
130
|
-
|
131
|
-
const hasArrow = data.PathType !== TABLE_TYPE;
|
132
|
-
const label = (
|
133
|
-
<div className={b('label')}>
|
134
|
-
{this.setIcon(data)}
|
135
|
-
<div className={b('name-wrapper')}>
|
136
|
-
<div className={b('name')}>{data.Name}</div>
|
137
|
-
<SchemaNodeActions name={currentSchemaPath} isTableType={type} />
|
138
|
-
</div>
|
139
|
-
</div>
|
140
|
-
);
|
141
|
-
return (
|
142
|
-
<div onClick={this.handleClick} ref={this.schemaNodeRef}>
|
143
|
-
<TreeView
|
144
|
-
nodeLabel={label}
|
145
|
-
collapsed={collapsed}
|
146
|
-
onClick={this.invertCollapsed}
|
147
|
-
hasArrow={hasArrow}
|
148
|
-
>
|
149
|
-
<SchemaTree path={isRoot ? fullPath : `${fullPath}/${data.Name}`} />
|
150
|
-
</TreeView>
|
151
|
-
</div>
|
152
|
-
);
|
153
|
-
}
|
154
|
-
}
|
155
|
-
|
156
|
-
function mapStateToProps(state) {
|
157
|
-
return {
|
158
|
-
currentSchemaPath: state.schema.currentSchemaPath,
|
159
|
-
currentItem: state.schema.currentSchema,
|
160
|
-
};
|
161
|
-
}
|
162
|
-
|
163
|
-
const mapDispatchToProps = {
|
164
|
-
getSchema,
|
165
|
-
getDescribe,
|
166
|
-
getSchemaAcl,
|
167
|
-
setCurrentSchemaPath,
|
168
|
-
};
|
169
|
-
|
170
|
-
export default connect(mapStateToProps, mapDispatchToProps)(SchemaNode);
|
@@ -1,62 +0,0 @@
|
|
1
|
-
.schema-node {
|
2
|
-
display: flex;
|
3
|
-
align-items: center;
|
4
|
-
|
5
|
-
.tree-view_item {
|
6
|
-
flex-wrap: wrap;
|
7
|
-
|
8
|
-
margin: 0;
|
9
|
-
padding: 5px 0;
|
10
|
-
}
|
11
|
-
|
12
|
-
.tree-view_children {
|
13
|
-
margin: 0;
|
14
|
-
padding-left: 15px;
|
15
|
-
}
|
16
|
-
|
17
|
-
&__label {
|
18
|
-
display: flex;
|
19
|
-
overflow: hidden;
|
20
|
-
align-items: center;
|
21
|
-
|
22
|
-
width: 100%;
|
23
|
-
height: 20px;
|
24
|
-
padding: 0 5px;
|
25
|
-
|
26
|
-
cursor: pointer;
|
27
|
-
|
28
|
-
& > svg {
|
29
|
-
color: var(--yc-color-text-hint);
|
30
|
-
}
|
31
|
-
}
|
32
|
-
|
33
|
-
&_active > .tree-view > .tree-view_item {
|
34
|
-
font-weight: 600;
|
35
|
-
|
36
|
-
background-color: var(--yc-color-base-info);
|
37
|
-
}
|
38
|
-
|
39
|
-
&__name-wrapper {
|
40
|
-
display: inline-flex;
|
41
|
-
justify-content: space-between;
|
42
|
-
|
43
|
-
width: 100%;
|
44
|
-
}
|
45
|
-
|
46
|
-
&__name {
|
47
|
-
display: inline;
|
48
|
-
overflow: hidden;
|
49
|
-
|
50
|
-
margin-left: 6px;
|
51
|
-
|
52
|
-
white-space: nowrap;
|
53
|
-
text-overflow: ellipsis;
|
54
|
-
}
|
55
|
-
}
|
56
|
-
|
57
|
-
.tree-view_item {
|
58
|
-
border-bottom: 1px solid var(--yc-color-line-generic);
|
59
|
-
&:hover {
|
60
|
-
background-color: var(--yc-color-base-simple-hover);
|
61
|
-
}
|
62
|
-
}
|
@@ -1,125 +0,0 @@
|
|
1
|
-
import {useDispatch} from 'react-redux';
|
2
|
-
import {useHistory} from 'react-router';
|
3
|
-
import cn from 'bem-cn-lite';
|
4
|
-
import {DropdownMenu} from '@yandex-cloud/uikit';
|
5
|
-
import qs from 'qs';
|
6
|
-
|
7
|
-
import {changeUserInput} from '../../../../store/reducers/executeQuery';
|
8
|
-
import {setShowPreview} from '../../../../store/reducers/schema';
|
9
|
-
import routes, {createHref} from '../../../../routes';
|
10
|
-
|
11
|
-
import './SchemaNodeActions.scss';
|
12
|
-
import {TenantGeneralTabsIds, TenantTabsGroups} from '../../TenantPages';
|
13
|
-
import createToast from '../../../../utils/createToast';
|
14
|
-
|
15
|
-
const b = cn('kv-schema-node-actions');
|
16
|
-
|
17
|
-
const createTableTemplate = (path: string) => {
|
18
|
-
return `CREATE TABLE \`${path}/my_table\`
|
19
|
-
(
|
20
|
-
\`id\` Uint64,
|
21
|
-
\`name\` String,
|
22
|
-
PRIMARY KEY (\`id\`)
|
23
|
-
);`;
|
24
|
-
};
|
25
|
-
|
26
|
-
const alterTableTemplate = (path: string) => {
|
27
|
-
return `ALTER TABLE \`${path}\`
|
28
|
-
ADD COLUMN is_deleted Bool;`;
|
29
|
-
};
|
30
|
-
const selectQueryTemplate = (path: string) => {
|
31
|
-
return `SELECT \`id\`, \`name\`
|
32
|
-
FROM \`${path}\`
|
33
|
-
ORDER BY \`id\`
|
34
|
-
LIMIT 10;`;
|
35
|
-
};
|
36
|
-
const upsertQueryTemplate = (path: string) => {
|
37
|
-
return `UPSERT INTO \`${path}\`
|
38
|
-
( \`id\`, \`name\` )
|
39
|
-
VALUES ( );`;
|
40
|
-
};
|
41
|
-
|
42
|
-
interface SchemaNodeActionsProps {
|
43
|
-
name: string;
|
44
|
-
isTableType: boolean;
|
45
|
-
}
|
46
|
-
|
47
|
-
function SchemaNodeActions({name, isTableType}: SchemaNodeActionsProps) {
|
48
|
-
const dispatch = useDispatch();
|
49
|
-
const history = useHistory();
|
50
|
-
|
51
|
-
const queryParams = qs.parse(location.search, {
|
52
|
-
ignoreQueryPrefix: true,
|
53
|
-
});
|
54
|
-
|
55
|
-
const onCreateTableClick = () => {
|
56
|
-
dispatch(changeUserInput({input: createTableTemplate(name)}));
|
57
|
-
};
|
58
|
-
|
59
|
-
const onAlterTableClick = () => {
|
60
|
-
dispatch(changeUserInput({input: alterTableTemplate(name)}));
|
61
|
-
};
|
62
|
-
|
63
|
-
const onSelectQueryClick = () => {
|
64
|
-
dispatch(changeUserInput({input: selectQueryTemplate(name)}));
|
65
|
-
};
|
66
|
-
|
67
|
-
const onUpsertQueryClick = () => {
|
68
|
-
dispatch(changeUserInput({input: upsertQueryTemplate(name)}));
|
69
|
-
};
|
70
|
-
|
71
|
-
const onCopyPathClick = () => {
|
72
|
-
navigator.clipboard
|
73
|
-
.writeText(name)
|
74
|
-
.then(() => {
|
75
|
-
createToast({
|
76
|
-
name: 'Copied',
|
77
|
-
title: 'Path was copied to clipboard successfully',
|
78
|
-
type: 'success',
|
79
|
-
});
|
80
|
-
})
|
81
|
-
.catch(() => {
|
82
|
-
createToast({
|
83
|
-
name: 'Not copied',
|
84
|
-
title: 'Path was not copied to clipboard successfully',
|
85
|
-
type: 'error',
|
86
|
-
});
|
87
|
-
});
|
88
|
-
};
|
89
|
-
|
90
|
-
const onOpenPreviewClick = () => {
|
91
|
-
dispatch(setShowPreview(true));
|
92
|
-
history.push(
|
93
|
-
createHref(routes.tenant, undefined, {
|
94
|
-
...queryParams,
|
95
|
-
[TenantTabsGroups.general]: TenantGeneralTabsIds.query,
|
96
|
-
}),
|
97
|
-
);
|
98
|
-
};
|
99
|
-
|
100
|
-
const copyItem = {text: 'Copy path', action: onCopyPathClick};
|
101
|
-
|
102
|
-
const tableItems = [
|
103
|
-
[{text: 'Open preview', action: onOpenPreviewClick}, copyItem],
|
104
|
-
[
|
105
|
-
{text: 'Alter table', action: onAlterTableClick},
|
106
|
-
{text: 'Select query', action: onSelectQueryClick},
|
107
|
-
{text: 'Upsert query', action: onUpsertQueryClick},
|
108
|
-
],
|
109
|
-
];
|
110
|
-
|
111
|
-
const catalogItems = [[copyItem], [{text: 'Create table', action: onCreateTableClick}]];
|
112
|
-
|
113
|
-
const items = isTableType ? tableItems : catalogItems;
|
114
|
-
|
115
|
-
return (
|
116
|
-
<DropdownMenu
|
117
|
-
items={items}
|
118
|
-
switcherWrapperClassName={b()}
|
119
|
-
popupClassName={b('popup')}
|
120
|
-
popupPlacement={['bottom-end']}
|
121
|
-
/>
|
122
|
-
);
|
123
|
-
}
|
124
|
-
|
125
|
-
export default SchemaNodeActions;
|
@@ -1,116 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import ReactDOM from 'react-dom';
|
3
|
-
import cn from 'bem-cn-lite';
|
4
|
-
import PropTypes from 'prop-types';
|
5
|
-
import {connect} from 'react-redux';
|
6
|
-
import {Loader} from '@yandex-cloud/uikit';
|
7
|
-
import {getSchema} from '../../../../store/reducers/schema';
|
8
|
-
import './SchemaTree.scss';
|
9
|
-
|
10
|
-
import SchemaNode from '../SchemaNode/SchemaNode';
|
11
|
-
|
12
|
-
const b = cn('schema');
|
13
|
-
|
14
|
-
class SchemaTree extends React.Component {
|
15
|
-
static propTypes = {
|
16
|
-
className: PropTypes.string,
|
17
|
-
loading: PropTypes.bool,
|
18
|
-
error: PropTypes.object,
|
19
|
-
schema: PropTypes.object,
|
20
|
-
wasLoaded: PropTypes.bool,
|
21
|
-
getSchema: PropTypes.func,
|
22
|
-
path: PropTypes.string.isRequired,
|
23
|
-
tenantPath: PropTypes.string,
|
24
|
-
};
|
25
|
-
|
26
|
-
componentDidMount() {
|
27
|
-
const {path: tenantPath, getSchema} = this.props;
|
28
|
-
|
29
|
-
getSchema({path: tenantPath});
|
30
|
-
}
|
31
|
-
|
32
|
-
emptySchema = React.createRef();
|
33
|
-
|
34
|
-
renderLoader() {
|
35
|
-
return (
|
36
|
-
<div className={b('loader')}>
|
37
|
-
<Loader size="m" />
|
38
|
-
</div>
|
39
|
-
);
|
40
|
-
}
|
41
|
-
|
42
|
-
removeArrow = () => {
|
43
|
-
// And how else to solve this problem, except to get into the DOM?
|
44
|
-
const nodeWithArrow =
|
45
|
-
// eslint-disable-next-line react/no-find-dom-node
|
46
|
-
ReactDOM.findDOMNode(this)?.parentNode?.parentNode?.querySelector('.tree-view_arrow');
|
47
|
-
if (nodeWithArrow) {
|
48
|
-
nodeWithArrow.setAttribute('style', 'visibility: hidden');
|
49
|
-
}
|
50
|
-
|
51
|
-
return '';
|
52
|
-
};
|
53
|
-
|
54
|
-
showEmptyNode() {
|
55
|
-
const {tenantPath, schema} = this.props;
|
56
|
-
if (schema.Path === tenantPath) {
|
57
|
-
return 'no data';
|
58
|
-
} else {
|
59
|
-
return String(this.removeArrow());
|
60
|
-
}
|
61
|
-
}
|
62
|
-
|
63
|
-
renderContent = () => {
|
64
|
-
const {schema, path} = this.props;
|
65
|
-
if (schema && schema.Status === 'StatusSuccess') {
|
66
|
-
return (
|
67
|
-
<div className={b()}>
|
68
|
-
{schema && schema.PathDescription && schema.PathDescription.Children ? (
|
69
|
-
schema.PathDescription.Children.map((it, key) => (
|
70
|
-
<SchemaNode key={key} fullPath={path} data={it} />
|
71
|
-
))
|
72
|
-
) : (
|
73
|
-
<div ref={this.emptySchema}>{this.showEmptyNode()}</div>
|
74
|
-
)}
|
75
|
-
</div>
|
76
|
-
);
|
77
|
-
} else {
|
78
|
-
return null;
|
79
|
-
}
|
80
|
-
};
|
81
|
-
|
82
|
-
render() {
|
83
|
-
const {loading, wasLoaded, error, currentSchema: schema} = this.props;
|
84
|
-
|
85
|
-
if (loading && !wasLoaded) {
|
86
|
-
return this.renderLoader();
|
87
|
-
} else if (
|
88
|
-
(error && !error.isCancelled) ||
|
89
|
-
(schema && schema.Status === 'StatusAccessDenied')
|
90
|
-
) {
|
91
|
-
return <div>{error?.statusText || 'Access denied'}</div>;
|
92
|
-
} else {
|
93
|
-
return this.renderContent();
|
94
|
-
}
|
95
|
-
}
|
96
|
-
}
|
97
|
-
|
98
|
-
function mapStateToProps(state, ownProps) {
|
99
|
-
const {data: schema = {}, loading, wasLoaded, error, currentSchema} = state.schema;
|
100
|
-
const tenantPath = state.tenant.tenant.Name;
|
101
|
-
const {path} = ownProps;
|
102
|
-
return {
|
103
|
-
tenantPath,
|
104
|
-
schema: schema[`${path}`],
|
105
|
-
loading,
|
106
|
-
wasLoaded,
|
107
|
-
error,
|
108
|
-
currentSchema,
|
109
|
-
};
|
110
|
-
}
|
111
|
-
|
112
|
-
const mapDispatchToProps = {
|
113
|
-
getSchema,
|
114
|
-
};
|
115
|
-
|
116
|
-
export default connect(mapStateToProps, mapDispatchToProps)(SchemaTree);
|
@@ -1,17 +0,0 @@
|
|
1
|
-
@import '../../../../styles/mixins.scss';
|
2
|
-
|
3
|
-
.schema {
|
4
|
-
.tree-view_item {
|
5
|
-
margin: 0;
|
6
|
-
padding: 2px 0;
|
7
|
-
}
|
8
|
-
|
9
|
-
.tree-view_children {
|
10
|
-
margin: 0;
|
11
|
-
padding-left: 15px;
|
12
|
-
}
|
13
|
-
&__loader {
|
14
|
-
display: flex;
|
15
|
-
justify-content: center;
|
16
|
-
}
|
17
|
-
}
|
@@ -1,45 +0,0 @@
|
|
1
|
-
/* the tree node's style */
|
2
|
-
|
3
|
-
.tree-view {
|
4
|
-
overflow-y: hidden;
|
5
|
-
}
|
6
|
-
|
7
|
-
.tree-view_item {
|
8
|
-
display: flex;
|
9
|
-
align-items: center;
|
10
|
-
|
11
|
-
margin: 10px 0;
|
12
|
-
|
13
|
-
cursor: pointer;
|
14
|
-
white-space: nowrap;
|
15
|
-
}
|
16
|
-
|
17
|
-
.tree-view_children {
|
18
|
-
margin-left: 35px;
|
19
|
-
|
20
|
-
cursor: pointer;
|
21
|
-
white-space: nowrap;
|
22
|
-
}
|
23
|
-
|
24
|
-
.tree-view_children-collapsed {
|
25
|
-
height: 0px;
|
26
|
-
}
|
27
|
-
|
28
|
-
.tree-view_arrow {
|
29
|
-
display: inline-block;
|
30
|
-
|
31
|
-
margin-right: 6px;
|
32
|
-
|
33
|
-
cursor: pointer;
|
34
|
-
user-select: none;
|
35
|
-
}
|
36
|
-
|
37
|
-
.tree-view_arrow:after {
|
38
|
-
content: '▾';
|
39
|
-
}
|
40
|
-
|
41
|
-
/* rotate the triangle to close it */
|
42
|
-
|
43
|
-
.tree-view_arrow-collapsed {
|
44
|
-
transform: rotate(-90deg);
|
45
|
-
}
|