ydb-embedded-ui 1.0.0 → 1.0.3
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 +23 -0
- package/dist/containers/Header/Header.scss +12 -0
- package/dist/containers/Header/Header.tsx +28 -6
- package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +4 -1
- package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +6 -1
- package/dist/containers/Tenant/Acl/Acl.scss +4 -4
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.scss +10 -0
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +12 -4
- package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +3 -2
- package/dist/containers/Tenant/QueryEditor/QueryEditor.js +2 -9
- package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.js +25 -21
- package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.scss +1 -0
- package/dist/containers/Tenant/QueryEditor/QueryResult/QueryResult.scss +1 -0
- package/dist/containers/Tenant/Schema/SchemaViewer/SchemaViewer.js +1 -1
- package/dist/store/reducers/executeQuery.js +17 -3
- package/dist/store/reducers/storage.js +2 -2
- package/dist/utils/constants.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,28 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
### [1.0.3](https://www.github.com/ydb-platform/ydb-embedded-ui/compare/v1.0.2...v1.0.3) (2022-03-21)
|
4
|
+
|
5
|
+
|
6
|
+
### Bug Fixes
|
7
|
+
|
8
|
+
* query status should not be shown when query is loading ([d214eee](https://www.github.com/ydb-platform/ydb-embedded-ui/commit/d214eee575b63341082f0be33163e3fce520df88))
|
9
|
+
* should set correct initial current index in queries history ([c3228d7](https://www.github.com/ydb-platform/ydb-embedded-ui/commit/c3228d7a6a0c810982db1bdbec7762889ac44ffa))
|
10
|
+
* **Storage:** wording fixed [YDB-1552] ([3f487ff](https://www.github.com/ydb-platform/ydb-embedded-ui/commit/3f487ff01117963760b676d14281e93e5f3002c0))
|
11
|
+
|
12
|
+
### [1.0.2](https://www.github.com/ydb-platform/ydb-embedded-ui/compare/v1.0.1...v1.0.2) (2022-03-11)
|
13
|
+
|
14
|
+
|
15
|
+
### Bug Fixes
|
16
|
+
|
17
|
+
* **Header:** add link to internal viewer ([64af24f](https://www.github.com/ydb-platform/ydb-embedded-ui/commit/64af24f8d78cf0d34466ac129be10c0764cce3d4))
|
18
|
+
|
19
|
+
### [1.0.1](https://www.github.com/ydb-platform/ydb-embedded-ui/compare/v1.0.0...v1.0.1) (2022-03-05)
|
20
|
+
|
21
|
+
|
22
|
+
### Bug Fixes
|
23
|
+
|
24
|
+
* **QueriesHistory:** should save history to local storage ([#8](https://www.github.com/ydb-platform/ydb-embedded-ui/issues/8)) ([57031ab](https://www.github.com/ydb-platform/ydb-embedded-ui/commit/57031ab16900e9d1112bbf506d5c777f94f883bb))
|
25
|
+
|
3
26
|
## [1.0.0](https://www.github.com/ydb-platform/ydb-embedded-ui/compare/v0.2.0...v1.0.0) (2022-03-01)
|
4
27
|
|
5
28
|
|
@@ -1,15 +1,19 @@
|
|
1
|
-
import {useEffect} from 'react';
|
1
|
+
import React, {useEffect} from 'react';
|
2
2
|
import {useDispatch, useSelector} from 'react-redux';
|
3
3
|
import cn from 'bem-cn-lite';
|
4
4
|
import {useHistory, useLocation} from 'react-router';
|
5
|
+
import {Breadcrumbs, BreadcrumbsItem, Link} from '@yandex-cloud/uikit';
|
5
6
|
|
6
|
-
import
|
7
|
+
import Divider from '../../components/Divider/Divider';
|
8
|
+
//@ts-ignore
|
9
|
+
import Icon from '../../components/Icon/Icon';
|
10
|
+
|
11
|
+
import {clusterName as clusterNameLocation, backend, customBackend} from '../../store';
|
7
12
|
import {getClusterInfo} from '../../store/reducers/cluster';
|
8
13
|
import {getHostInfo} from '../../store/reducers/host';
|
14
|
+
import {HeaderItemType} from '../../store/reducers/header';
|
9
15
|
|
10
16
|
import './Header.scss';
|
11
|
-
import {Breadcrumbs, BreadcrumbsItem} from '@yandex-cloud/uikit';
|
12
|
-
import {HeaderItemType} from '../../store/reducers/header';
|
13
17
|
|
14
18
|
const b = cn('header');
|
15
19
|
|
@@ -49,6 +53,12 @@ function Header() {
|
|
49
53
|
const renderHeader = () => {
|
50
54
|
const clusterNameFinal = singleClusterMode ? host.ClusterName : clusterName;
|
51
55
|
|
56
|
+
let link = backend + '/internal';
|
57
|
+
|
58
|
+
if (singleClusterMode && !customBackend) {
|
59
|
+
link = `/internal`;
|
60
|
+
}
|
61
|
+
|
52
62
|
const breadcrumbItems = header.reduce((acc, el) => {
|
53
63
|
acc.push({text: el.text, action: () => history.push(el.link)});
|
54
64
|
return acc;
|
@@ -63,8 +73,20 @@ function Header() {
|
|
63
73
|
firstDisplayedItemsCount={1}
|
64
74
|
/>
|
65
75
|
</div>
|
66
|
-
|
67
|
-
|
76
|
+
|
77
|
+
<div className={b('cluster-name-wrapper')}>
|
78
|
+
<Link href={link} target="_blank">
|
79
|
+
Internal viewer{' '}
|
80
|
+
<Icon name="external" viewBox={'0 0 16 16'} width={16} height={16} />
|
81
|
+
</Link>
|
82
|
+
{clusterNameFinal && (
|
83
|
+
<React.Fragment>
|
84
|
+
<div className={b('divider')}>
|
85
|
+
<Divider />
|
86
|
+
</div>
|
87
|
+
<ClusterName name={clusterNameFinal} />
|
88
|
+
</React.Fragment>
|
89
|
+
)}
|
68
90
|
</div>
|
69
91
|
</header>
|
70
92
|
);
|
@@ -210,13 +210,16 @@ function StorageGroups({data, tableSettings, visibleEntities, nodes}: StorageGro
|
|
210
210
|
];
|
211
211
|
|
212
212
|
let columns = allColumns;
|
213
|
+
let emptyMessage = 'No such groups.';
|
213
214
|
|
214
215
|
if (visibleEntities === VisibleEntities.Space) {
|
215
216
|
columns = allColumns.filter((col) => col.name !== TableColumnsIds.Missing);
|
217
|
+
emptyMessage = 'No storage groups with space problems.';
|
216
218
|
}
|
217
219
|
|
218
220
|
if (visibleEntities === VisibleEntities.Missing) {
|
219
221
|
columns = allColumns.filter((col) => col.name !== TableColumnsIds.UsedSpaceFlag);
|
222
|
+
emptyMessage = 'No degraded groups.';
|
220
223
|
}
|
221
224
|
return data ? (
|
222
225
|
<DataTable
|
@@ -226,7 +229,7 @@ function StorageGroups({data, tableSettings, visibleEntities, nodes}: StorageGro
|
|
226
229
|
columns={columns}
|
227
230
|
settings={tableSettings}
|
228
231
|
initialSortOrder={setSortOrder(visibleEntities)}
|
229
|
-
emptyDataMessage=
|
232
|
+
emptyDataMessage={emptyMessage}
|
230
233
|
/>
|
231
234
|
) : null;
|
232
235
|
}
|
@@ -114,9 +114,14 @@ function StorageNodes({data, tableSettings, visibleEntities}: StorageGroupsProps
|
|
114
114
|
];
|
115
115
|
|
116
116
|
let columns = allColumns;
|
117
|
+
let emptyMessage = 'No such nodes.';
|
117
118
|
|
118
119
|
if (visibleEntities === VisibleEntities.Space) {
|
119
120
|
columns = allColumns.filter((col) => col.name !== TableColumnsIds.Missing);
|
121
|
+
emptyMessage = 'No nodes with space problems.';
|
122
|
+
}
|
123
|
+
if (visibleEntities === VisibleEntities.Missing) {
|
124
|
+
emptyMessage = 'No degraded nodes.';
|
120
125
|
}
|
121
126
|
|
122
127
|
return data ? (
|
@@ -127,7 +132,7 @@ function StorageNodes({data, tableSettings, visibleEntities}: StorageGroupsProps
|
|
127
132
|
columns={columns}
|
128
133
|
settings={tableSettings}
|
129
134
|
initialSortOrder={setSortOrder(visibleEntities)}
|
130
|
-
emptyDataMessage=
|
135
|
+
emptyDataMessage={emptyMessage}
|
131
136
|
/>
|
132
137
|
) : null;
|
133
138
|
}
|
@@ -1,6 +1,10 @@
|
|
1
1
|
@import '../../../styles/mixins.scss';
|
2
2
|
|
3
3
|
.kv-acl {
|
4
|
+
display: flex;
|
5
|
+
overflow: auto;
|
6
|
+
flex-grow: 1;
|
7
|
+
|
4
8
|
padding: 0 12px 16px;
|
5
9
|
@include query-data-table;
|
6
10
|
&__message-container {
|
@@ -38,8 +42,4 @@
|
|
38
42
|
color: var(--yc-color-text-danger);
|
39
43
|
}
|
40
44
|
}
|
41
|
-
|
42
|
-
&__result {
|
43
|
-
overflow: auto;
|
44
|
-
}
|
45
45
|
}
|
@@ -13,7 +13,9 @@
|
|
13
13
|
max-height: 100%;
|
14
14
|
|
15
15
|
&__overview-wrapper {
|
16
|
+
display: flex;
|
16
17
|
overflow: auto;
|
18
|
+
flex-grow: 1;
|
17
19
|
|
18
20
|
padding: 0 12px 16px;
|
19
21
|
}
|
@@ -91,7 +93,15 @@
|
|
91
93
|
}
|
92
94
|
|
93
95
|
&__info {
|
96
|
+
display: flex;
|
94
97
|
overflow: hidden;
|
98
|
+
flex-direction: column;
|
99
|
+
}
|
100
|
+
|
101
|
+
&__schema {
|
102
|
+
display: flex;
|
103
|
+
overflow: auto;
|
104
|
+
flex-grow: 1;
|
95
105
|
}
|
96
106
|
|
97
107
|
&__info-controls {
|
@@ -78,7 +78,7 @@ interface ObjectSummaryProps {
|
|
78
78
|
onCollapseSummary: VoidFunction;
|
79
79
|
onExpandSummary: VoidFunction;
|
80
80
|
isCollapsed: boolean;
|
81
|
-
additionalTenantInfo?: any
|
81
|
+
additionalTenantInfo?: any;
|
82
82
|
}
|
83
83
|
|
84
84
|
function ObjectSummary(props: ObjectSummaryProps) {
|
@@ -168,10 +168,16 @@ function ObjectSummary(props: ObjectSummaryProps) {
|
|
168
168
|
const renderTabContent = () => {
|
169
169
|
switch (infoTab) {
|
170
170
|
case TenantInfoTabsIds.acl: {
|
171
|
-
return <Acl additionalTenantInfo={props.additionalTenantInfo}/>;
|
171
|
+
return <Acl additionalTenantInfo={props.additionalTenantInfo} />;
|
172
172
|
}
|
173
173
|
case TenantInfoTabsIds.schema: {
|
174
|
-
return loadingSchema ?
|
174
|
+
return loadingSchema ? (
|
175
|
+
renderLoader()
|
176
|
+
) : (
|
177
|
+
<div className={b('schema')}>
|
178
|
+
<SchemaViewer data={schema} />
|
179
|
+
</div>
|
180
|
+
);
|
175
181
|
}
|
176
182
|
default: {
|
177
183
|
return renderObjectOverview();
|
@@ -194,7 +200,9 @@ function ObjectSummary(props: ObjectSummaryProps) {
|
|
194
200
|
<div className={b('tree-title')}>Navigation</div>
|
195
201
|
</div>
|
196
202
|
<div className={b('tree')}>
|
197
|
-
{tenantData &&
|
203
|
+
{tenantData && (
|
204
|
+
<SchemaNode fullPath={tenantName as string} data={tenantData} isRoot />
|
205
|
+
)}
|
198
206
|
</div>
|
199
207
|
</div>
|
200
208
|
);
|
@@ -38,6 +38,7 @@ function QueriesHistory(props: QueriesHistoryProps) {
|
|
38
38
|
};
|
39
39
|
|
40
40
|
const renderSavedQueries = () => {
|
41
|
+
const reversedHistory = ([] as string[]).concat(history).reverse();
|
41
42
|
return (
|
42
43
|
<Popup
|
43
44
|
className={b('popup-wrapper')}
|
@@ -47,7 +48,7 @@ function QueriesHistory(props: QueriesHistoryProps) {
|
|
47
48
|
onClose={onCloseHistory}
|
48
49
|
>
|
49
50
|
<div className={b()}>
|
50
|
-
{
|
51
|
+
{reversedHistory.length === 0 ? (
|
51
52
|
<div className={b('empty')}>History is empty</div>
|
52
53
|
) : (
|
53
54
|
<React.Fragment>
|
@@ -57,7 +58,7 @@ function QueriesHistory(props: QueriesHistoryProps) {
|
|
57
58
|
</div>
|
58
59
|
</div>
|
59
60
|
<div>
|
60
|
-
{
|
61
|
+
{reversedHistory.map((query, index) => {
|
61
62
|
return (
|
62
63
|
<div
|
63
64
|
className={b('saved-queries-row')}
|
@@ -154,7 +154,7 @@ function QueryEditor(props) {
|
|
154
154
|
useEffect(() => {
|
155
155
|
const {monacoHotKey, setMonacoHotKey} = props;
|
156
156
|
if (monacoHotKey === null) {
|
157
|
-
return
|
157
|
+
return;
|
158
158
|
}
|
159
159
|
setMonacoHotKey(null);
|
160
160
|
switch (monacoHotKey) {
|
@@ -464,19 +464,12 @@ function QueryEditor(props) {
|
|
464
464
|
};
|
465
465
|
|
466
466
|
const getExecuteResult = () => {
|
467
|
-
const {
|
468
|
-
data = [],
|
469
|
-
error,
|
470
|
-
loading,
|
471
|
-
history: {queries},
|
472
|
-
} = props.executeQuery;
|
467
|
+
const {data = [], error} = props.executeQuery;
|
473
468
|
|
474
469
|
if (error) {
|
475
470
|
return error.data || error;
|
476
471
|
} else if (data.length > 0) {
|
477
472
|
return data;
|
478
|
-
} else if (!loading && queries.length) {
|
479
|
-
return 'The request was successful';
|
480
473
|
} else {
|
481
474
|
return '';
|
482
475
|
}
|
@@ -252,28 +252,32 @@ function QueryExplain(props) {
|
|
252
252
|
return (
|
253
253
|
<React.Fragment>
|
254
254
|
<div className={b('controls')}>
|
255
|
-
|
256
|
-
<
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
255
|
+
{!props.loading && (
|
256
|
+
<React.Fragment>
|
257
|
+
<div className={b('controls-right')}>
|
258
|
+
<QueryExecutionStatus hasError={Boolean(props.error)} />
|
259
|
+
{!props.error && (
|
260
|
+
<React.Fragment>
|
261
|
+
<Divider />
|
262
|
+
<RadioButton
|
263
|
+
options={explainOptions}
|
264
|
+
value={activeOption}
|
265
|
+
onUpdate={onSelectOption}
|
266
|
+
/>
|
267
|
+
</React.Fragment>
|
268
|
+
)}
|
269
|
+
</div>
|
270
|
+
<div className={b('controls-left')}>
|
271
|
+
<EnableFullscreenButton disabled={Boolean(props.error)} />
|
272
|
+
<PaneVisibilityToggleButtons
|
273
|
+
onCollapse={props.onCollapseResults}
|
274
|
+
onExpand={props.onExpandResults}
|
275
|
+
isCollapsed={props.isResultsCollapsed}
|
276
|
+
initialDirection="bottom"
|
264
277
|
/>
|
265
|
-
</
|
266
|
-
|
267
|
-
|
268
|
-
<div className={b('controls-left')}>
|
269
|
-
<EnableFullscreenButton disabled={Boolean(props.error)} />
|
270
|
-
<PaneVisibilityToggleButtons
|
271
|
-
onCollapse={props.onCollapseResults}
|
272
|
-
onExpand={props.onExpandResults}
|
273
|
-
isCollapsed={props.isResultsCollapsed}
|
274
|
-
initialDirection="bottom"
|
275
|
-
/>
|
276
|
-
</div>
|
278
|
+
</div>
|
279
|
+
</React.Fragment>
|
280
|
+
)}
|
277
281
|
</div>
|
278
282
|
<div className={b('result')}>{renderContent()}</div>
|
279
283
|
</React.Fragment>
|
@@ -67,7 +67,7 @@ class SchemaViewer extends React.Component {
|
|
67
67
|
theme="yandex-cloud"
|
68
68
|
data={tableData}
|
69
69
|
columns={columns}
|
70
|
-
settings={
|
70
|
+
settings={DEFAULT_TABLE_SETTINGS}
|
71
71
|
dynamicRender={true}
|
72
72
|
initialSortOrder={{columnId: SchemaViewerColumns.key, order: DataTable.DESCENDING}}
|
73
73
|
/>
|
@@ -1,5 +1,9 @@
|
|
1
1
|
import {createRequestActionTypes, createApiRequest} from '../utils';
|
2
2
|
import '../../services/api';
|
3
|
+
import {getValueFromLS, parseJson} from '../../utils/utils';
|
4
|
+
import {QUERIES_HISTORY_KEY} from '../../utils/constants';
|
5
|
+
|
6
|
+
const MAXIMUM_QUERIES_IN_HISTORY = 20;
|
3
7
|
|
4
8
|
const SEND_QUERY = createRequestActionTypes('query', 'SEND_QUERY');
|
5
9
|
const CHANGE_USER_INPUT = 'query/CHANGE_USER_INPUT';
|
@@ -9,6 +13,10 @@ const GO_TO_NEXT_QUERY = 'query/GO_TO_NEXT_QUERY';
|
|
9
13
|
const SELECT_RUN_ACTION = 'query/SELECT_RUN_ACTION';
|
10
14
|
const MONACO_HOT_KEY = 'query/MONACO_HOT_KEY';
|
11
15
|
|
16
|
+
const queriesHistoryInitial = parseJson(getValueFromLS(QUERIES_HISTORY_KEY, []));
|
17
|
+
|
18
|
+
const sliceLimit = queriesHistoryInitial.length - MAXIMUM_QUERIES_IN_HISTORY;
|
19
|
+
|
12
20
|
export const RUN_ACTIONS_VALUES = {
|
13
21
|
script: 'execute-script',
|
14
22
|
scan: 'execute-scan',
|
@@ -25,8 +33,11 @@ const initialState = {
|
|
25
33
|
loading: false,
|
26
34
|
input: '',
|
27
35
|
history: {
|
28
|
-
queries:
|
29
|
-
currentIndex:
|
36
|
+
queries: queriesHistoryInitial.slice(sliceLimit < 0 ? 0 : sliceLimit),
|
37
|
+
currentIndex:
|
38
|
+
queriesHistoryInitial.length > MAXIMUM_QUERIES_IN_HISTORY
|
39
|
+
? MAXIMUM_QUERIES_IN_HISTORY - 1
|
40
|
+
: queriesHistoryInitial.length - 1,
|
30
41
|
},
|
31
42
|
runAction: RUN_ACTIONS_VALUES.script,
|
32
43
|
monacoHotKey: null,
|
@@ -76,7 +87,10 @@ const executeQuery = (state = initialState, action) => {
|
|
76
87
|
|
77
88
|
case SAVE_QUERY_TO_HISTORY: {
|
78
89
|
const query = action.data;
|
79
|
-
const newQueries = [...state.history.queries, query]
|
90
|
+
const newQueries = [...state.history.queries, query].slice(
|
91
|
+
state.history.queries.length >= MAXIMUM_QUERIES_IN_HISTORY ? 1 : 0,
|
92
|
+
);
|
93
|
+
window.localStorage.setItem(QUERIES_HISTORY_KEY, JSON.stringify(newQueries));
|
80
94
|
const currentIndex = newQueries.length - 1;
|
81
95
|
|
82
96
|
return {
|
package/dist/utils/constants.js
CHANGED
@@ -120,6 +120,7 @@ export const PROBLEMS = 'With problems';
|
|
120
120
|
|
121
121
|
export const THEME_KEY = 'theme';
|
122
122
|
export const SAVED_QUERIES_KEY = 'saved_queries';
|
123
|
+
export const QUERIES_HISTORY_KEY = 'queries_history';
|
123
124
|
export const DATA_QA_TUNE_COLUMNS_POPUP = 'tune-columns-popup';
|
124
125
|
|
125
126
|
export const defaultUserSettings = {
|