ydb-embedded-ui 1.4.0 → 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 +42 -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/App/NodesTable.scss +0 -2
- 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/QueryEditor/SaveQuery/SaveQuery.js +36 -54
- package/dist/containers/Tenant/QueryEditor/SaveQuery/SaveQuery.scss +7 -5
- package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.js +1 -0
- 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/containers/Tenants/Tenants.js +2 -2
- package/dist/containers/Tenants/Tenants.scss +7 -1
- 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,47 @@
|
|
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
|
+
|
19
|
+
### [1.4.2](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.4.1...v1.4.2) (2022-05-23)
|
20
|
+
|
21
|
+
|
22
|
+
### UI Updates
|
23
|
+
|
24
|
+
* **QueryEditor:** replace warning for query losing with note about how query are saved ([89820ca](https://github.com/ydb-platform/ydb-embedded-ui/commit/89820ca7e2d02f880eb81d484b8947d599798d5f))
|
25
|
+
|
26
|
+
|
27
|
+
### Bug Fixes
|
28
|
+
|
29
|
+
* **QueryEditor:** confirm query deletion with enter ([d3dadbd](https://github.com/ydb-platform/ydb-embedded-ui/commit/d3dadbd0244fead5f41bd98445669c4f5ce23c43))
|
30
|
+
* **QueryEditor:** field autofocus in query save dialog ([9225238](https://github.com/ydb-platform/ydb-embedded-ui/commit/92252384dc68c40191f7898fff9a2c1106b0b2f1))
|
31
|
+
* **QueryEditor:** save query with enter ([5f9c450](https://github.com/ydb-platform/ydb-embedded-ui/commit/5f9c450aedc90f0e162515294a74000c006f9be7))
|
32
|
+
|
33
|
+
### [1.4.1](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.4.0...v1.4.1) (2022-05-17)
|
34
|
+
|
35
|
+
|
36
|
+
### UI Updates
|
37
|
+
|
38
|
+
* **Tenant:** add tenant name wrapper ([8176d28](https://github.com/ydb-platform/ydb-embedded-ui/commit/8176d28a5769b2b95d667ed960ad34d7a0d9bb4c))
|
39
|
+
|
40
|
+
|
41
|
+
### Bug Fixes
|
42
|
+
|
43
|
+
* **NodesTable:** align external link icon ([a379796](https://github.com/ydb-platform/ydb-embedded-ui/commit/a379796c6b8087f25f95ce3db4be33f18da71e04))
|
44
|
+
|
3
45
|
## [1.4.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.3.0...v1.4.0) (2022-05-16)
|
4
46
|
|
5
47
|
|
@@ -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')}>
|
@@ -1,31 +1,24 @@
|
|
1
|
-
import React, {useState
|
1
|
+
import React, {useState} from 'react';
|
2
2
|
import _ from 'lodash';
|
3
3
|
import cn from 'bem-cn-lite';
|
4
4
|
import {useDispatch, useSelector} from 'react-redux';
|
5
|
-
import {Dialog, DropdownMenu,
|
5
|
+
import {Dialog, DropdownMenu, TextInput, Button} from '@yandex-cloud/uikit';
|
6
6
|
|
7
|
-
import Icon from '../../../../components/Icon/Icon';
|
8
7
|
import {setQueryNameToEdit} from '../../../../store/reducers/saveQuery';
|
9
8
|
|
10
9
|
import './SaveQuery.scss';
|
11
10
|
|
12
11
|
const b = cn('kv-save-query');
|
13
12
|
|
14
|
-
const EMBEDDED_VERSION_WARNING =
|
15
|
-
'Please be aware: after cookies delete your saved queries will be lost.';
|
16
|
-
|
17
13
|
function SaveQuery({savedQueries, onSaveQuery, saveButtonDisabled}) {
|
18
14
|
const singleClusterMode = useSelector((state) => state.singleClusterMode);
|
19
15
|
const [isDialogVisible, setIsDialogVisible] = useState(false);
|
20
|
-
const [isEmbeddedWarningVisible, setIsEmbeddedWarningVisible] = useState(false);
|
21
16
|
const [queryName, setQueryName] = useState('');
|
22
17
|
const [validationError, setValidationError] = useState(null);
|
23
18
|
|
24
19
|
const queryNameToEdit = useSelector((state) => state.saveQuery);
|
25
20
|
const dispatch = useDispatch();
|
26
21
|
|
27
|
-
const warningRef = useRef();
|
28
|
-
|
29
22
|
const onSaveQueryClick = () => {
|
30
23
|
setIsDialogVisible(true);
|
31
24
|
dispatch(setQueryNameToEdit(null));
|
@@ -42,13 +35,6 @@ function SaveQuery({savedQueries, onSaveQuery, saveButtonDisabled}) {
|
|
42
35
|
setValidationError(validateQueryName(value));
|
43
36
|
};
|
44
37
|
|
45
|
-
const onEmbeddedWarningOpen = () => {
|
46
|
-
setIsEmbeddedWarningVisible(true);
|
47
|
-
};
|
48
|
-
const onEmbeddedWarningClose = () => {
|
49
|
-
setIsEmbeddedWarningVisible(false);
|
50
|
-
};
|
51
|
-
|
52
38
|
const validateQueryName = (value) => {
|
53
39
|
if (_.some(savedQueries, (q) => q.name.toLowerCase() === value.trim().toLowerCase())) {
|
54
40
|
return 'This name already exists';
|
@@ -57,9 +43,11 @@ function SaveQuery({savedQueries, onSaveQuery, saveButtonDisabled}) {
|
|
57
43
|
};
|
58
44
|
|
59
45
|
const onSaveClick = () => {
|
60
|
-
if (queryName
|
61
|
-
|
46
|
+
if (!queryName || validationError) {
|
47
|
+
return;
|
62
48
|
}
|
49
|
+
|
50
|
+
onSaveQuery(queryName);
|
63
51
|
onCloseDialog();
|
64
52
|
};
|
65
53
|
|
@@ -70,18 +58,38 @@ function SaveQuery({savedQueries, onSaveQuery, saveButtonDisabled}) {
|
|
70
58
|
|
71
59
|
const renderDialog = () => {
|
72
60
|
return (
|
73
|
-
<Dialog
|
61
|
+
<Dialog
|
62
|
+
open={isDialogVisible}
|
63
|
+
hasCloseButton={false}
|
64
|
+
size="s"
|
65
|
+
onClose={onCloseDialog}
|
66
|
+
onEnterKeyDown={onSaveClick}
|
67
|
+
>
|
74
68
|
<Dialog.Header caption="Save query" />
|
75
69
|
<Dialog.Body className={b('dialog-body')}>
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
70
|
+
{singleClusterMode && (
|
71
|
+
<div className={b('dialog-row')}>
|
72
|
+
The query will be saved in your browser
|
73
|
+
</div>
|
74
|
+
)}
|
75
|
+
<div className={b('dialog-row')}>
|
76
|
+
<label
|
77
|
+
htmlFor="queryName"
|
78
|
+
className={b('field-title', 'required')}
|
79
|
+
>
|
80
|
+
Query name
|
81
|
+
</label>
|
82
|
+
<div className={b('control-wrapper')}>
|
83
|
+
<TextInput
|
84
|
+
id="queryName"
|
85
|
+
placeholder="Enter query name"
|
86
|
+
text={queryName}
|
87
|
+
onUpdate={onQueryNameChange}
|
88
|
+
hasClear
|
89
|
+
autoFocus
|
90
|
+
/>
|
91
|
+
<span className={b('error')}>{validationError}</span>
|
92
|
+
</div>
|
85
93
|
</div>
|
86
94
|
</Dialog.Body>
|
87
95
|
<Dialog.Footer
|
@@ -121,36 +129,10 @@ function SaveQuery({savedQueries, onSaveQuery, saveButtonDisabled}) {
|
|
121
129
|
);
|
122
130
|
};
|
123
131
|
|
124
|
-
const renderEmbeddedVersionWarning = () => {
|
125
|
-
return (
|
126
|
-
<React.Fragment>
|
127
|
-
<Popup
|
128
|
-
className={b('embedded-popup')}
|
129
|
-
anchorRef={warningRef}
|
130
|
-
placement={['top']}
|
131
|
-
open={isEmbeddedWarningVisible}
|
132
|
-
hasArrow
|
133
|
-
>
|
134
|
-
{EMBEDDED_VERSION_WARNING}
|
135
|
-
</Popup>
|
136
|
-
<div
|
137
|
-
className={b('embedded-tooltip')}
|
138
|
-
ref={warningRef}
|
139
|
-
onMouseEnter={onEmbeddedWarningOpen}
|
140
|
-
onMouseLeave={onEmbeddedWarningClose}
|
141
|
-
>
|
142
|
-
<Icon name="question" height={18} width={18} viewBox="0 0 24 24" />
|
143
|
-
</div>
|
144
|
-
</React.Fragment>
|
145
|
-
);
|
146
|
-
};
|
147
|
-
|
148
132
|
return (
|
149
133
|
<React.Fragment>
|
150
134
|
{queryNameToEdit ? renderSaveDropdownMenu() : renderSaveButton(onSaveQueryClick)}
|
151
135
|
{isDialogVisible && renderDialog()}
|
152
|
-
|
153
|
-
{singleClusterMode && renderEmbeddedVersionWarning()}
|
154
136
|
</React.Fragment>
|
155
137
|
);
|
156
138
|
}
|
@@ -1,17 +1,19 @@
|
|
1
|
-
@import '../../../../styles/mixins.scss';
|
2
|
-
|
3
1
|
.kv-save-query {
|
4
|
-
&__dialog-
|
2
|
+
&__dialog-row {
|
5
3
|
display: flex;
|
6
4
|
align-items: flex-start;
|
5
|
+
|
6
|
+
& + & {
|
7
|
+
margin-top: var(--yc-text-body-line-height);
|
8
|
+
}
|
7
9
|
}
|
8
10
|
&__field-title {
|
9
11
|
margin-right: 12px;
|
10
12
|
|
11
13
|
font-weight: 500;
|
12
|
-
line-height:
|
14
|
+
line-height: 28px;
|
13
15
|
white-space: nowrap;
|
14
|
-
|
16
|
+
|
15
17
|
&.required {
|
16
18
|
&::after {
|
17
19
|
content: '*';
|
@@ -71,6 +71,7 @@ function SavedQueries({savedQueries, changeUserInput, onDeleteQuery}) {
|
|
71
71
|
hasCloseButton={false}
|
72
72
|
size="s"
|
73
73
|
onClose={onClickCancelDelete}
|
74
|
+
onEnterKeyDown={onConfirmDeleteClick}
|
74
75
|
>
|
75
76
|
<Dialog.Header caption="Delete query" />
|
76
77
|
<Dialog.Body className={b('dialog-body')}>
|