ydb-embedded-ui 1.4.2 → 1.5.2

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 (31) hide show
  1. package/CHANGELOG.md +31 -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/Authentication/Authentication.tsx +1 -0
  8. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +14 -21
  9. package/dist/containers/Tenant/Diagnostics/Healthcheck/IssuesViewer/IssueViewer.scss +11 -23
  10. package/dist/containers/Tenant/Diagnostics/Healthcheck/IssuesViewer/IssuesViewer.js +7 -7
  11. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.scss +9 -15
  12. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +18 -21
  13. package/dist/containers/Tenant/QueryEditor/QueryEditor.js +2 -2
  14. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +62 -0
  15. package/dist/containers/Tenant/Tenant.tsx +2 -2
  16. package/dist/containers/Tenant/utils/schema.ts +17 -0
  17. package/dist/containers/Tenant/utils/schemaActions.ts +115 -0
  18. package/dist/services/api.d.ts +3 -0
  19. package/dist/services/api.js +2 -2
  20. package/dist/store/reducers/tenant.js +30 -0
  21. package/dist/store/state-url-mapping.js +6 -0
  22. package/package.json +8 -4
  23. package/dist/components/TreeView/TreeView.js +0 -60
  24. package/dist/components/TreeView/TreeView.scss +0 -39
  25. package/dist/containers/Tenant/Schema/SchemaNode/SchemaNode.js +0 -170
  26. package/dist/containers/Tenant/Schema/SchemaNode/SchemaNode.scss +0 -62
  27. package/dist/containers/Tenant/Schema/SchemaNodeActions/SchemaNodeActions.scss +0 -17
  28. package/dist/containers/Tenant/Schema/SchemaNodeActions/SchemaNodeActions.tsx +0 -125
  29. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.js +0 -116
  30. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.scss +0 -17
  31. package/dist/styles/react-treeview.scss +0 -45
@@ -0,0 +1,115 @@
1
+ import {Dispatch} from 'react';
2
+ import type {NavigationTreeNodeType} from 'ydb-ui-components';
3
+
4
+ import {changeUserInput} from '../../../store/reducers/executeQuery';
5
+ import {setShowPreview} from '../../../store/reducers/schema';
6
+ import {setTopLevelTab} from '../../../store/reducers/tenant';
7
+ import createToast from '../../../utils/createToast';
8
+ import {TenantGeneralTabsIds} from '../TenantPages';
9
+
10
+ const createTableTemplate = (path: string) => {
11
+ return `CREATE TABLE \`${path}/my_table\`
12
+ (
13
+ \`id\` Uint64,
14
+ \`name\` String,
15
+ PRIMARY KEY (\`id\`)
16
+ );`;
17
+ };
18
+
19
+ const alterTableTemplate = (path: string) => {
20
+ return `ALTER TABLE \`${path}\`
21
+ ADD COLUMN is_deleted Bool;`;
22
+ };
23
+ const selectQueryTemplate = (path: string) => {
24
+ return `SELECT \`id\`, \`name\`
25
+ FROM \`${path}\`
26
+ ORDER BY \`id\`
27
+ LIMIT 10;`;
28
+ };
29
+ const upsertQueryTemplate = (path: string) => {
30
+ return `UPSERT INTO \`${path}\`
31
+ ( \`id\`, \`name\` )
32
+ VALUES ( );`;
33
+ };
34
+
35
+ export const getActions = (
36
+ dispatch: Dispatch<any>,
37
+ setActivePath: (path: string) => void,
38
+ ) =>
39
+ (path: string, type: NavigationTreeNodeType) => {
40
+ const switchTabToQuery = () => {
41
+ dispatch(setTopLevelTab(TenantGeneralTabsIds.query));
42
+ };
43
+
44
+ const onCreateTableClick = () => {
45
+ dispatch(changeUserInput({input: createTableTemplate(path)}));
46
+ switchTabToQuery();
47
+ setActivePath(path);
48
+ };
49
+
50
+ const onAlterTableClick = () => {
51
+ dispatch(changeUserInput({input: alterTableTemplate(path)}));
52
+ switchTabToQuery();
53
+ setActivePath(path);
54
+ };
55
+
56
+ const onSelectQueryClick = () => {
57
+ dispatch(changeUserInput({input: selectQueryTemplate(path)}));
58
+ switchTabToQuery();
59
+ setActivePath(path);
60
+ };
61
+
62
+ const onUpsertQueryClick = () => {
63
+ dispatch(changeUserInput({input: upsertQueryTemplate(path)}));
64
+ switchTabToQuery();
65
+ setActivePath(path);
66
+ };
67
+
68
+ const onCopyPathClick = () => {
69
+ navigator.clipboard
70
+ .writeText(path)
71
+ .then(() => {
72
+ createToast({
73
+ name: 'Copied',
74
+ title: 'The path is copied to the clipboard',
75
+ type: 'success',
76
+ });
77
+ })
78
+ .catch(() => {
79
+ createToast({
80
+ name: 'Not copied',
81
+ title: 'Couldn’t copy the path',
82
+ type: 'error',
83
+ });
84
+ });
85
+ };
86
+
87
+ const onOpenPreviewClick = () => {
88
+ dispatch(setShowPreview(true));
89
+ switchTabToQuery();
90
+ setActivePath(path);
91
+ };
92
+
93
+ const copyItem = {text: 'Copy path', action: onCopyPathClick};
94
+
95
+ return type === 'table'
96
+ ? [
97
+ [
98
+ {text: 'Open preview', action: onOpenPreviewClick},
99
+ copyItem,
100
+ ],
101
+ [
102
+ {text: 'Alter table...', action: onAlterTableClick},
103
+ {text: 'Select query...', action: onSelectQueryClick},
104
+ {text: 'Upsert query...', action: onUpsertQueryClick},
105
+ ],
106
+ ]
107
+ : [
108
+ [
109
+ copyItem,
110
+ ],
111
+ [
112
+ {text: 'Create table...', action: onCreateTableClick},
113
+ ],
114
+ ];
115
+ };
@@ -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}) {
@@ -3,6 +3,8 @@ import '../../services/api';
3
3
  import _ from 'lodash';
4
4
 
5
5
  const FETCH_TENANT = createRequestActionTypes('tenant', 'FETCH_TENANT');
6
+ const SET_TOP_LEVEL_TAB = 'tenant/SET_TOP_LEVEL_TAB';
7
+ const SET_DIAGNOSTICS_TAB = 'tenant/SET_DIAGNOSTICS_TAB';
6
8
 
7
9
  const tenantReducer = (state = {loading: false, tenant: {}}, action) => {
8
10
  switch (action.type) {
@@ -41,6 +43,20 @@ const tenantReducer = (state = {loading: false, tenant: {}}, action) => {
41
43
  };
42
44
  }
43
45
 
46
+ case SET_TOP_LEVEL_TAB: {
47
+ return {
48
+ ...state,
49
+ topLevelTab: action.data,
50
+ };
51
+ }
52
+
53
+ case SET_DIAGNOSTICS_TAB: {
54
+ return {
55
+ ...state,
56
+ diagnosticsTab: action.data,
57
+ };
58
+ }
59
+
44
60
  default:
45
61
  return state;
46
62
  }
@@ -73,4 +89,18 @@ export const getTenantInfo = ({path}) => {
73
89
  });
74
90
  };
75
91
 
92
+ export function setTopLevelTab(tab) {
93
+ return {
94
+ type: SET_TOP_LEVEL_TAB,
95
+ data: tab,
96
+ };
97
+ }
98
+
99
+ export function setDiagnosticsTab(tab) {
100
+ return {
101
+ type: SET_DIAGNOSTICS_TAB,
102
+ data: tab,
103
+ };
104
+ }
105
+
76
106
  export default tenantReducer;
@@ -42,6 +42,12 @@ const paramSetup = {
42
42
  stateKey: 'tablets.typeFilter',
43
43
  type: 'array',
44
44
  },
45
+ general: {
46
+ stateKey: 'tenant.topLevelTab',
47
+ },
48
+ generalTab: {
49
+ stateKey: 'tenant.diagnosticsTab',
50
+ },
45
51
  },
46
52
  };
47
53
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "1.4.2",
3
+ "version": "1.5.2",
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.2.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,17 +0,0 @@
1
- .kv-schema-node-actions {
2
- visibility: hidden;
3
-
4
- &__popup {
5
- .yc-menu__list-item {
6
- line-height: 36px;
7
- }
8
- }
9
- }
10
-
11
- .tree-view_item {
12
- &:hover {
13
- .kv-schema-node-actions {
14
- visibility: visible;
15
- }
16
- }
17
- }