ydb-embedded-ui 4.23.0 → 4.25.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 +15 -0
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +11 -79
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.scss +0 -51
- package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.tsx +5 -12
- package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +1 -10
- package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.scss +3 -16
- package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.tsx +4 -27
- package/dist/containers/Tenant/Query/i18n/en.json +0 -2
- package/dist/containers/Tenant/Query/i18n/ru.json +0 -2
- package/dist/containers/Tenant/utils/schemaActions.ts +11 -18
- package/dist/containers/UserSettings/i18n/en.json +1 -7
- package/dist/containers/UserSettings/i18n/ru.json +1 -7
- package/dist/containers/UserSettings/settings.ts +1 -19
- package/dist/services/api.ts +2 -2
- package/dist/store/reducers/settings/settings.ts +14 -16
- package/dist/utils/constants.ts +0 -11
- package/dist/utils/hooks/useQueryModes.ts +3 -32
- package/dist/utils/query.ts +0 -4
- package/dist/utils/settings.ts +4 -1
- package/package.json +1 -1
- package/dist/containers/Tenant/Diagnostics/OldHealthcheck/Details/Details.tsx +0 -64
- package/dist/containers/Tenant/Diagnostics/OldHealthcheck/Details/index.ts +0 -1
- package/dist/containers/Tenant/Diagnostics/OldHealthcheck/Healthcheck.scss +0 -137
- package/dist/containers/Tenant/Diagnostics/OldHealthcheck/Healthcheck.tsx +0 -92
- package/dist/containers/Tenant/Diagnostics/OldHealthcheck/Preview/Preview.tsx +0 -82
- package/dist/containers/Tenant/Diagnostics/OldHealthcheck/Preview/index.ts +0 -1
- package/dist/containers/Tenant/Diagnostics/OldHealthcheck/index.ts +0 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/OldTenantOverview.tsx +0 -155
- package/dist/utils/hooks/i18n/en.json +0 -3
- package/dist/utils/hooks/i18n/index.ts +0 -11
- package/dist/utils/hooks/i18n/ru.json +0 -3
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [4.25.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.24.0...v4.25.0) (2023-12-07)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* **Diagnostics:** remove tenant diagnostics cards setting ([#602](https://github.com/ydb-platform/ydb-embedded-ui/issues/602)) ([fe61df8](https://github.com/ydb-platform/ydb-embedded-ui/commit/fe61df86048013432c4e4788d1e621298ecb1fb2))
|
9
|
+
* **Query:** remove query modes setting ([#600](https://github.com/ydb-platform/ydb-embedded-ui/issues/600)) ([78c63e4](https://github.com/ydb-platform/ydb-embedded-ui/commit/78c63e4a2e60950970914eaba49304b68aad0f80))
|
10
|
+
|
11
|
+
## [4.24.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.23.0...v4.24.0) (2023-12-07)
|
12
|
+
|
13
|
+
|
14
|
+
### Features
|
15
|
+
|
16
|
+
* always use localStorage if no settingsApi ([#603](https://github.com/ydb-platform/ydb-embedded-ui/issues/603)) ([ff692df](https://github.com/ydb-platform/ydb-embedded-ui/commit/ff692dffa99d278f6b261bbf1aac0ee24c661a6d))
|
17
|
+
|
3
18
|
## [4.23.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.22.0...v4.23.0) (2023-12-06)
|
4
19
|
|
5
20
|
|
@@ -1,18 +1,10 @@
|
|
1
|
-
import React, {useState} from 'react';
|
2
1
|
import {useSelector} from 'react-redux';
|
3
2
|
import cn from 'bem-cn-lite';
|
4
3
|
|
5
|
-
import {Button, Modal} from '@gravity-ui/uikit';
|
6
|
-
|
7
4
|
import type {EPathType} from '../../../../types/api/schema';
|
8
5
|
import type {AdditionalNodesProps, AdditionalTenantsProps} from '../../../../types/additionalProps';
|
9
|
-
import {Icon} from '../../../../components/Icon';
|
10
|
-
import {useSetting} from '../../../../utils/hooks';
|
11
|
-
import {DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS} from '../../../../utils/constants';
|
12
6
|
import Overview from '../Overview/Overview';
|
13
|
-
import {Healthcheck} from '../OldHealthcheck';
|
14
7
|
import {TenantOverview} from '../TenantOverview/TenantOverview';
|
15
|
-
import {OldTenantOverview} from '../TenantOverview/OldTenantOverview';
|
16
8
|
|
17
9
|
import './DetailedOverview.scss';
|
18
10
|
|
@@ -29,86 +21,26 @@ const b = cn('kv-detailed-overview');
|
|
29
21
|
function DetailedOverview(props: DetailedOverviewProps) {
|
30
22
|
const {type, tenantName, additionalTenantProps, additionalNodesProps} = props;
|
31
23
|
|
32
|
-
const [isModalVisible, setIsModalVisible] = useState(false);
|
33
|
-
|
34
24
|
const {currentSchemaPath} = useSelector((state: any) => state.schema);
|
35
25
|
|
36
|
-
const [displayMetricsCards] = useSetting(DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS);
|
37
|
-
|
38
|
-
const openModalHandler = () => {
|
39
|
-
setIsModalVisible(true);
|
40
|
-
};
|
41
|
-
|
42
|
-
const closeModalHandler = () => {
|
43
|
-
setIsModalVisible(false);
|
44
|
-
};
|
45
|
-
|
46
|
-
const renderModal = () => {
|
47
|
-
return (
|
48
|
-
<Modal open={isModalVisible} onClose={closeModalHandler} className={b('modal')}>
|
49
|
-
<Healthcheck tenant={props.tenantName} fetchData={false} />
|
50
|
-
<Button
|
51
|
-
className={b('close-modal-button')}
|
52
|
-
onClick={closeModalHandler}
|
53
|
-
view="flat-secondary"
|
54
|
-
title="Close"
|
55
|
-
>
|
56
|
-
<Icon name="close" viewBox={'0 0 16 16 '} height={20} width={20} />
|
57
|
-
</Button>
|
58
|
-
</Modal>
|
59
|
-
);
|
60
|
-
};
|
61
|
-
|
62
26
|
const renderTenantOverview = () => {
|
63
|
-
if (displayMetricsCards) {
|
64
|
-
return (
|
65
|
-
<div className={b('section')}>
|
66
|
-
<TenantOverview
|
67
|
-
tenantName={tenantName}
|
68
|
-
additionalTenantProps={additionalTenantProps}
|
69
|
-
additionalNodesProps={additionalNodesProps}
|
70
|
-
/>
|
71
|
-
</div>
|
72
|
-
);
|
73
|
-
}
|
74
|
-
|
75
|
-
return (
|
76
|
-
<>
|
77
|
-
<div className={b('section')}>
|
78
|
-
<OldTenantOverview
|
79
|
-
tenantName={tenantName}
|
80
|
-
additionalTenantProps={additionalTenantProps}
|
81
|
-
/>
|
82
|
-
</div>
|
83
|
-
<div className={b('section')}>
|
84
|
-
<Healthcheck
|
85
|
-
tenant={tenantName}
|
86
|
-
preview={true}
|
87
|
-
showMoreHandler={openModalHandler}
|
88
|
-
/>
|
89
|
-
</div>
|
90
|
-
</>
|
91
|
-
);
|
92
|
-
};
|
93
|
-
|
94
|
-
const renderContent = () => {
|
95
|
-
const isTenant = tenantName === currentSchemaPath;
|
96
27
|
return (
|
97
|
-
<div className={b()}>
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
28
|
+
<div className={b('section')}>
|
29
|
+
<TenantOverview
|
30
|
+
tenantName={tenantName}
|
31
|
+
additionalTenantProps={additionalTenantProps}
|
32
|
+
additionalNodesProps={additionalNodesProps}
|
33
|
+
/>
|
103
34
|
</div>
|
104
35
|
);
|
105
36
|
};
|
106
37
|
|
38
|
+
const isTenant = tenantName === currentSchemaPath;
|
39
|
+
|
107
40
|
return (
|
108
|
-
<
|
109
|
-
{
|
110
|
-
|
111
|
-
</React.Fragment>
|
41
|
+
<div className={b()}>
|
42
|
+
{isTenant ? renderTenantOverview() : <Overview type={type} tenantName={tenantName} />}
|
43
|
+
</div>
|
112
44
|
);
|
113
45
|
}
|
114
46
|
|
@@ -33,57 +33,6 @@
|
|
33
33
|
gap: 10px;
|
34
34
|
}
|
35
35
|
|
36
|
-
&__common-info {
|
37
|
-
display: flex;
|
38
|
-
gap: 20px;
|
39
|
-
|
40
|
-
flex-direction: column;
|
41
|
-
justify-content: flex-start;
|
42
|
-
align-items: stretch;
|
43
|
-
}
|
44
|
-
|
45
|
-
&__system-tablets {
|
46
|
-
display: flex;
|
47
|
-
flex-wrap: wrap;
|
48
|
-
align-items: center;
|
49
|
-
|
50
|
-
margin-bottom: 35px;
|
51
|
-
}
|
52
|
-
|
53
|
-
&__collapse-title {
|
54
|
-
font-size: var(--yc-text-body-2-font-size);
|
55
|
-
font-weight: 500;
|
56
|
-
line-height: var(--yc-text-body-2-line-height);
|
57
|
-
}
|
58
|
-
|
59
|
-
&__section {
|
60
|
-
border-radius: 10px;
|
61
|
-
|
62
|
-
&_metrics {
|
63
|
-
.info-viewer__label {
|
64
|
-
min-width: 150px;
|
65
|
-
}
|
66
|
-
.info-viewer__value {
|
67
|
-
min-width: 100px;
|
68
|
-
}
|
69
|
-
}
|
70
|
-
|
71
|
-
&_pools {
|
72
|
-
display: grid;
|
73
|
-
grid-gap: 7px 20px;
|
74
|
-
|
75
|
-
grid-template-columns: 110px 110px;
|
76
|
-
}
|
77
|
-
}
|
78
|
-
|
79
|
-
&__section-title {
|
80
|
-
margin-bottom: 20px;
|
81
|
-
|
82
|
-
font-size: var(--yc-text-body-2-font-size);
|
83
|
-
font-weight: 600;
|
84
|
-
line-height: var(--yc-text-body-2-line-height);
|
85
|
-
}
|
86
|
-
|
87
36
|
&__info {
|
88
37
|
position: sticky;
|
89
38
|
left: 0;
|
@@ -9,7 +9,7 @@ import {setQueryTab} from '../../../../store/reducers/tenant/tenant';
|
|
9
9
|
import {selectQueriesHistory} from '../../../../store/reducers/executeQuery';
|
10
10
|
import {TENANT_QUERY_TABS_ID} from '../../../../store/reducers/tenant/constants';
|
11
11
|
import {useQueryModes, useTypedSelector} from '../../../../utils/hooks';
|
12
|
-
import {QUERY_MODES,
|
12
|
+
import {QUERY_MODES, QUERY_SYNTAX} from '../../../../utils/query';
|
13
13
|
import {MAX_QUERY_HEIGHT, QUERY_TABLE_SETTINGS} from '../../utils/constants';
|
14
14
|
|
15
15
|
import i18n from '../i18n';
|
@@ -31,22 +31,15 @@ function QueriesHistory({changeUserInput}: QueriesHistoryProps) {
|
|
31
31
|
const reversedHistory = [...queriesHistory].reverse();
|
32
32
|
|
33
33
|
const onQueryClick = (query: QueryInHistory) => {
|
34
|
-
let isQueryModeSet = true;
|
35
|
-
|
36
34
|
if (query.syntax === QUERY_SYNTAX.pg && queryMode !== QUERY_MODES.pg) {
|
37
|
-
|
38
|
-
QUERY_MODES.pg,
|
39
|
-
i18n('history.cannot-set-mode', {mode: QUERY_MODES_TITLES[QUERY_MODES.pg]}),
|
40
|
-
);
|
35
|
+
setQueryMode(QUERY_MODES.pg);
|
41
36
|
} else if (query.syntax !== QUERY_SYNTAX.pg && queryMode === QUERY_MODES.pg) {
|
42
37
|
// Set query mode for queries with yql syntax
|
43
|
-
|
38
|
+
setQueryMode(QUERY_MODES.script);
|
44
39
|
}
|
45
40
|
|
46
|
-
|
47
|
-
|
48
|
-
dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
|
49
|
-
}
|
41
|
+
changeUserInput({input: query.queryText});
|
42
|
+
dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
|
50
43
|
};
|
51
44
|
|
52
45
|
const columns: Column<QueryInHistory>[] = [
|
@@ -23,12 +23,11 @@ import {
|
|
23
23
|
DEFAULT_IS_QUERY_RESULT_COLLAPSED,
|
24
24
|
DEFAULT_SIZE_RESULT_PANE_KEY,
|
25
25
|
SAVED_QUERIES_KEY,
|
26
|
-
ENABLE_ADDITIONAL_QUERY_MODES,
|
27
26
|
LAST_USED_QUERY_ACTION_KEY,
|
28
27
|
QUERY_USE_MULTI_SCHEMA_KEY,
|
29
28
|
} from '../../../../utils/constants';
|
30
29
|
import {useSetting, useQueryModes} from '../../../../utils/hooks';
|
31
|
-
import {QUERY_ACTIONS
|
30
|
+
import {QUERY_ACTIONS} from '../../../../utils/query';
|
32
31
|
|
33
32
|
import {
|
34
33
|
PaneVisibilityActionTypes,
|
@@ -85,16 +84,9 @@ function QueryEditor(props) {
|
|
85
84
|
|
86
85
|
const [isResultLoaded, setIsResultLoaded] = useState(false);
|
87
86
|
const [queryMode, setQueryMode] = useQueryModes();
|
88
|
-
const [enableAdditionalQueryModes] = useSetting(ENABLE_ADDITIONAL_QUERY_MODES);
|
89
87
|
const [useMultiSchema] = useSetting(QUERY_USE_MULTI_SCHEMA_KEY);
|
90
88
|
const [lastUsedQueryAction, setLastUsedQueryAction] = useSetting(LAST_USED_QUERY_ACTION_KEY);
|
91
89
|
|
92
|
-
useEffect(() => {
|
93
|
-
if (isNewQueryMode(queryMode) && !enableAdditionalQueryModes) {
|
94
|
-
setQueryMode(QUERY_MODES.script);
|
95
|
-
}
|
96
|
-
}, [enableAdditionalQueryModes, queryMode, setQueryMode]);
|
97
|
-
|
98
90
|
useEffect(() => {
|
99
91
|
if (savedPath !== path) {
|
100
92
|
if (savedPath) {
|
@@ -470,7 +462,6 @@ function QueryEditor(props) {
|
|
470
462
|
disabled={!executeQuery.input}
|
471
463
|
onUpdateQueryMode={setQueryMode}
|
472
464
|
queryMode={queryMode}
|
473
|
-
enableAdditionalQueryModes={enableAdditionalQueryModes}
|
474
465
|
highlitedAction={lastUsedQueryAction}
|
475
466
|
/>
|
476
467
|
);
|
@@ -27,7 +27,7 @@
|
|
27
27
|
$b: &;
|
28
28
|
|
29
29
|
&__button {
|
30
|
-
width:
|
30
|
+
width: 241px;
|
31
31
|
margin-left: 2px;
|
32
32
|
}
|
33
33
|
|
@@ -36,24 +36,11 @@
|
|
36
36
|
justify-content: space-between;
|
37
37
|
align-items: center;
|
38
38
|
|
39
|
-
width:
|
39
|
+
width: 215px;
|
40
40
|
}
|
41
41
|
|
42
42
|
&__popup {
|
43
|
-
width:
|
44
|
-
|
45
|
-
&_extended {
|
46
|
-
width: 241px;
|
47
|
-
}
|
48
|
-
}
|
49
|
-
|
50
|
-
&_extended {
|
51
|
-
#{$b}__button {
|
52
|
-
width: 241px;
|
53
|
-
}
|
54
|
-
#{$b}__button-content {
|
55
|
-
width: 215px;
|
56
|
-
}
|
43
|
+
width: 241px;
|
57
44
|
}
|
58
45
|
}
|
59
46
|
|
@@ -19,17 +19,6 @@ const queryModeSelectorPopupQa = 'query-mode-selector-popup';
|
|
19
19
|
|
20
20
|
const b = block('ydb-query-editor-controls');
|
21
21
|
|
22
|
-
const OldQueryModeSelectorOptions = {
|
23
|
-
[QUERY_MODES.script]: {
|
24
|
-
title: QUERY_MODES_TITLES[QUERY_MODES.script],
|
25
|
-
description: i18n('method-description.script'),
|
26
|
-
},
|
27
|
-
[QUERY_MODES.scan]: {
|
28
|
-
title: QUERY_MODES_TITLES[QUERY_MODES.scan],
|
29
|
-
description: i18n('method-description.scan'),
|
30
|
-
},
|
31
|
-
} as const;
|
32
|
-
|
33
22
|
const QueryModeSelectorOptions = {
|
34
23
|
[QUERY_MODES.script]: {
|
35
24
|
title: QUERY_MODES_TITLES[QUERY_MODES.script],
|
@@ -63,7 +52,6 @@ interface QueryEditorControlsProps {
|
|
63
52
|
disabled: boolean;
|
64
53
|
onUpdateQueryMode: (mode: QueryMode) => void;
|
65
54
|
queryMode: QueryMode;
|
66
|
-
enableAdditionalQueryModes: boolean;
|
67
55
|
highlitedAction: QueryAction;
|
68
56
|
}
|
69
57
|
|
@@ -78,14 +66,9 @@ export const QueryEditorControls = ({
|
|
78
66
|
onUpdateQueryMode,
|
79
67
|
queryMode,
|
80
68
|
highlitedAction,
|
81
|
-
enableAdditionalQueryModes,
|
82
69
|
}: QueryEditorControlsProps) => {
|
83
70
|
const querySelectorMenuItems = useMemo(() => {
|
84
|
-
|
85
|
-
? QueryModeSelectorOptions
|
86
|
-
: OldQueryModeSelectorOptions;
|
87
|
-
|
88
|
-
return Object.entries(options).map(([mode, {title, description}]) => {
|
71
|
+
return Object.entries(QueryModeSelectorOptions).map(([mode, {title, description}]) => {
|
89
72
|
return {
|
90
73
|
text: (
|
91
74
|
<LabelWithPopover
|
@@ -100,7 +83,7 @@ export const QueryEditorControls = ({
|
|
100
83
|
},
|
101
84
|
};
|
102
85
|
});
|
103
|
-
}, [onUpdateQueryMode
|
86
|
+
}, [onUpdateQueryMode]);
|
104
87
|
|
105
88
|
const runView: ButtonView | undefined = highlitedAction === 'execute' ? 'action' : undefined;
|
106
89
|
const explainView: ButtonView | undefined =
|
@@ -132,17 +115,11 @@ export const QueryEditorControls = ({
|
|
132
115
|
>
|
133
116
|
Explain
|
134
117
|
</Button>
|
135
|
-
<div
|
136
|
-
className={b('mode-selector', {
|
137
|
-
extended: enableAdditionalQueryModes,
|
138
|
-
})}
|
139
|
-
>
|
118
|
+
<div className={b('mode-selector')}>
|
140
119
|
<DropdownMenu
|
141
120
|
items={querySelectorMenuItems}
|
142
121
|
popupProps={{
|
143
|
-
className: b('mode-selector__popup',
|
144
|
-
extended: enableAdditionalQueryModes,
|
145
|
-
}),
|
122
|
+
className: b('mode-selector__popup'),
|
146
123
|
qa: queryModeSelectorPopupQa,
|
147
124
|
}}
|
148
125
|
switcher={
|
@@ -8,8 +8,6 @@
|
|
8
8
|
"history.empty": "History is empty",
|
9
9
|
"saved.empty": "There are no saved queries",
|
10
10
|
|
11
|
-
"history.cannot-set-mode": "This query is available only with '{{mode}}' query mode. You need to turn in additional query modes in settings to enable it",
|
12
|
-
|
13
11
|
"delete-dialog.header": "Delete query",
|
14
12
|
"delete-dialog.question": "Are you sure you want to delete query",
|
15
13
|
"delete-dialog.delete": "Delete",
|
@@ -8,8 +8,6 @@
|
|
8
8
|
"history.empty": "История пуста",
|
9
9
|
"saved.empty": "Нет сохраненных запросов",
|
10
10
|
|
11
|
-
"history.cannot-set-mode": "Этот запрос доступен только в режиме '{{mode}}'. Вам необходимо включить дополнительные режимы выполнения запросов в настройках",
|
12
|
-
|
13
11
|
"delete-dialog.header": "Удалить запрос",
|
14
12
|
"delete-dialog.question": "Вы уверены что хотите удалить запрос",
|
15
13
|
"delete-dialog.delete": "Удалить",
|
@@ -4,7 +4,6 @@ import copy from 'copy-to-clipboard';
|
|
4
4
|
import type {NavigationTreeNodeType, NavigationTreeProps} from 'ydb-ui-components';
|
5
5
|
|
6
6
|
import type {QueryMode} from '../../../types/store/query';
|
7
|
-
import type {SetQueryModeIfAvailable} from '../../../utils/hooks';
|
8
7
|
import {changeUserInput} from '../../../store/reducers/executeQuery';
|
9
8
|
import {setQueryTab, setTenantPage} from '../../../store/reducers/tenant/tenant';
|
10
9
|
import {TENANT_QUERY_TABS_ID, TENANT_PAGES_IDS} from '../../../store/reducers/tenant/constants';
|
@@ -25,7 +24,7 @@ import {
|
|
25
24
|
} from './queryTemplates';
|
26
25
|
|
27
26
|
interface ActionsAdditionalEffects {
|
28
|
-
setQueryMode:
|
27
|
+
setQueryMode: (mode: QueryMode) => void;
|
29
28
|
setActivePath: (path: string) => void;
|
30
29
|
}
|
31
30
|
|
@@ -36,18 +35,16 @@ const bindActions = (
|
|
36
35
|
) => {
|
37
36
|
const {setActivePath, setQueryMode} = additionalEffects;
|
38
37
|
|
39
|
-
const inputQuery =
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
const inputQuery = (tmpl: (path: string) => string, mode?: QueryMode) => () => {
|
39
|
+
if (mode) {
|
40
|
+
setQueryMode(mode);
|
41
|
+
}
|
43
42
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
}
|
50
|
-
};
|
43
|
+
dispatch(changeUserInput({input: tmpl(path)}));
|
44
|
+
dispatch(setTenantPage(TENANT_PAGES_IDS.query));
|
45
|
+
dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
|
46
|
+
setActivePath(path);
|
47
|
+
};
|
51
48
|
|
52
49
|
return {
|
53
50
|
createTable: inputQuery(createTableTemplate, 'script'),
|
@@ -56,11 +53,7 @@ const bindActions = (
|
|
56
53
|
upsertQuery: inputQuery(upsertQueryTemplate),
|
57
54
|
createExternalTable: inputQuery(createExternalTableTemplate, 'script'),
|
58
55
|
dropExternalTable: inputQuery(dropExternalTableTemplate, 'script'),
|
59
|
-
selectQueryFromExternalTable: inputQuery(
|
60
|
-
selectQueryTemplate,
|
61
|
-
'query',
|
62
|
-
i18n('actions.externalTableSelectUnavailable'),
|
63
|
-
),
|
56
|
+
selectQueryFromExternalTable: inputQuery(selectQueryTemplate, 'query'),
|
64
57
|
createTopic: inputQuery(createTopicTemplate, 'script'),
|
65
58
|
alterTopic: inputQuery(alterTopicTemplate, 'script'),
|
66
59
|
dropTopic: inputQuery(dropTopicTemplate, 'script'),
|
@@ -22,12 +22,6 @@
|
|
22
22
|
"settings.useBackendParamsForTables.title": "Use virtual table for cluster Nodes tab",
|
23
23
|
"settings.useBackendParamsForTables.popover": "Use table with data load on scroll. It will increase performance, but could work unstable",
|
24
24
|
|
25
|
-
"settings.enableAdditionalQueryModes.title": "Enable additional query modes",
|
26
|
-
"settings.enableAdditionalQueryModes.popover": "Adds 'Data', 'YQL - QueryService' and 'PostgreSQL' modes. May not work on some versions",
|
27
|
-
|
28
25
|
"settings.queryUseMultiSchema.title": "Allow queries with multiple result sets",
|
29
|
-
"settings.queryUseMultiSchema.popover": "Use 'multi' schema for queries that enables queries with multiple result sets. Returns nothing on versions 23-3 and older"
|
30
|
-
|
31
|
-
"settings.tenantDiagnostics.title": "Display metrics cards for database diagnostics",
|
32
|
-
"settings.tenantDiagnostics.popover": "Adds indicators of database resources usage. Incomplete data may be displayed for some databases"
|
26
|
+
"settings.queryUseMultiSchema.popover": "Use 'multi' schema for queries that enables queries with multiple result sets. Returns nothing on versions 23-3 and older"
|
33
27
|
}
|
@@ -22,12 +22,6 @@
|
|
22
22
|
"settings.useBackendParamsForTables.title": "Использовать виртуализированную таблицу для вкладки Nodes кластера",
|
23
23
|
"settings.useBackendParamsForTables.popover": "Использовать таблицу с загрузкой данных по скроллу. Это улучшит производительность, но может работать нестабильно",
|
24
24
|
|
25
|
-
"settings.enableAdditionalQueryModes.title": "Включить дополнительные режимы выполнения запросов",
|
26
|
-
"settings.enableAdditionalQueryModes.popover": "Добавляет режимы 'Data', 'YQL - QueryService' и 'PostgreSQL'. Может работать некорректно на некоторых версиях",
|
27
|
-
|
28
25
|
"settings.queryUseMultiSchema.title": "Разрешить запросы с несколькими результатами",
|
29
|
-
"settings.queryUseMultiSchema.popover": "Использовать для запросов схему 'multi', которая позволяет выполнять запросы с несколькими результатами. На версиях 23-3 и старше результат не возвращается вообще"
|
30
|
-
|
31
|
-
"settings.tenantDiagnostics.title": "Показывать карточки с метриками в диагностике базы данных",
|
32
|
-
"settings.tenantDiagnostics.popover": "Добавляет индикаторы использования ресурсов базы данных. Для некоторых баз могут отображаться неполные данные"
|
26
|
+
"settings.queryUseMultiSchema.popover": "Использовать для запросов схему 'multi', которая позволяет выполнять запросы с несколькими результатами. На версиях 23-3 и старше результат не возвращается вообще"
|
33
27
|
}
|
@@ -4,8 +4,6 @@ import favoriteFilledIcon from '../../assets/icons/star.svg';
|
|
4
4
|
import flaskIcon from '../../assets/icons/flask.svg';
|
5
5
|
|
6
6
|
import {
|
7
|
-
ENABLE_ADDITIONAL_QUERY_MODES,
|
8
|
-
DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS,
|
9
7
|
INVERTED_DISKS_KEY,
|
10
8
|
LANGUAGE_KEY,
|
11
9
|
THEME_KEY,
|
@@ -91,21 +89,11 @@ export const useBackendParamsForTables: SettingProps = {
|
|
91
89
|
title: i18n('settings.useBackendParamsForTables.title'),
|
92
90
|
helpPopoverContent: i18n('settings.useBackendParamsForTables.popover'),
|
93
91
|
};
|
94
|
-
export const enableQueryModesForExplainSetting: SettingProps = {
|
95
|
-
settingKey: ENABLE_ADDITIONAL_QUERY_MODES,
|
96
|
-
title: i18n('settings.enableAdditionalQueryModes.title'),
|
97
|
-
helpPopoverContent: i18n('settings.enableAdditionalQueryModes.popover'),
|
98
|
-
};
|
99
92
|
export const queryUseMultiSchemaSetting: SettingProps = {
|
100
93
|
settingKey: QUERY_USE_MULTI_SCHEMA_KEY,
|
101
94
|
title: i18n('settings.queryUseMultiSchema.title'),
|
102
95
|
helpPopoverContent: i18n('settings.queryUseMultiSchema.popover'),
|
103
96
|
};
|
104
|
-
export const enableNewTenantDiagnosticsDesign: SettingProps = {
|
105
|
-
settingKey: DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS,
|
106
|
-
title: i18n('settings.tenantDiagnostics.title'),
|
107
|
-
helpPopoverContent: i18n('settings.tenantDiagnostics.popover'),
|
108
|
-
};
|
109
97
|
|
110
98
|
export const appearanceSection: SettingsSection = {
|
111
99
|
id: 'appearanceSection',
|
@@ -115,13 +103,7 @@ export const appearanceSection: SettingsSection = {
|
|
115
103
|
export const experimentsSection: SettingsSection = {
|
116
104
|
id: 'experimentsSection',
|
117
105
|
title: i18n('section.experiments'),
|
118
|
-
settings: [
|
119
|
-
useNodesEndpointSetting,
|
120
|
-
useBackendParamsForTables,
|
121
|
-
enableQueryModesForExplainSetting,
|
122
|
-
queryUseMultiSchemaSetting,
|
123
|
-
enableNewTenantDiagnosticsDesign,
|
124
|
-
],
|
106
|
+
settings: [useNodesEndpointSetting, useBackendParamsForTables, queryUseMultiSchemaSetting],
|
125
107
|
};
|
126
108
|
|
127
109
|
export const generalPage: SettingsPage = {
|
package/dist/services/api.ts
CHANGED
@@ -34,11 +34,10 @@ import type {StorageApiRequestParams} from '../store/reducers/storage/types';
|
|
34
34
|
|
35
35
|
import {backend as BACKEND} from '../store';
|
36
36
|
import {prepareSortValue} from '../utils/filters';
|
37
|
+
import {settingsApi} from '../utils/settings';
|
37
38
|
|
38
39
|
const config = {withCredentials: !window.custom_backend};
|
39
40
|
|
40
|
-
const settingsApi = window.web_version ? window.systemSettings?.settingsApi : undefined;
|
41
|
-
|
42
41
|
type AxiosOptions = {
|
43
42
|
concurrentId?: string;
|
44
43
|
};
|
@@ -106,6 +105,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
106
105
|
{concurrentId},
|
107
106
|
);
|
108
107
|
}
|
108
|
+
/** @deprecated use getNodes instead */
|
109
109
|
getCompute(
|
110
110
|
{sortOrder, sortValue, ...params}: ComputeApiRequestParams,
|
111
111
|
{concurrentId}: AxiosOptions = {},
|
@@ -10,18 +10,21 @@ import {
|
|
10
10
|
USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
|
11
11
|
PARTITIONS_HIDDEN_COLUMNS_KEY,
|
12
12
|
QUERY_INITIAL_MODE_KEY,
|
13
|
-
ENABLE_ADDITIONAL_QUERY_MODES,
|
14
13
|
CLUSTER_INFO_HIDDEN_KEY,
|
15
14
|
LAST_USED_QUERY_ACTION_KEY,
|
16
15
|
USE_BACKEND_PARAMS_FOR_TABLES_KEY,
|
17
16
|
LANGUAGE_KEY,
|
18
|
-
DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS,
|
19
17
|
QUERY_USE_MULTI_SCHEMA_KEY,
|
20
18
|
} from '../../../utils/constants';
|
21
19
|
import '../../../services/api';
|
22
20
|
import {parseJson} from '../../../utils/utils';
|
23
21
|
import {QUERY_ACTIONS, QUERY_MODES} from '../../../utils/query';
|
24
|
-
import {
|
22
|
+
import {
|
23
|
+
readSavedSettingsValue,
|
24
|
+
settingsApi,
|
25
|
+
systemSettings,
|
26
|
+
userSettings,
|
27
|
+
} from '../../../utils/settings';
|
25
28
|
|
26
29
|
import {TENANT_PAGES_IDS} from '../tenant/constants';
|
27
30
|
|
@@ -53,15 +56,7 @@ export const initialState = {
|
|
53
56
|
USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
|
54
57
|
'false',
|
55
58
|
),
|
56
|
-
[ENABLE_ADDITIONAL_QUERY_MODES]: readSavedSettingsValue(
|
57
|
-
ENABLE_ADDITIONAL_QUERY_MODES,
|
58
|
-
'true',
|
59
|
-
),
|
60
59
|
[QUERY_USE_MULTI_SCHEMA_KEY]: readSavedSettingsValue(QUERY_USE_MULTI_SCHEMA_KEY, 'false'),
|
61
|
-
[DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS]: readSavedSettingsValue(
|
62
|
-
DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS,
|
63
|
-
'true',
|
64
|
-
),
|
65
60
|
[SAVED_QUERIES_KEY]: readSavedSettingsValue(SAVED_QUERIES_KEY, '[]'),
|
66
61
|
[TENANT_INITIAL_PAGE_KEY]: readSavedSettingsValue(
|
67
62
|
TENANT_INITIAL_PAGE_KEY,
|
@@ -115,13 +110,16 @@ export const setSettingValue = (
|
|
115
110
|
name: string,
|
116
111
|
value: string,
|
117
112
|
): ThunkAction<void, RootState, unknown, SetSettingValueAction> => {
|
118
|
-
return (dispatch
|
113
|
+
return (dispatch) => {
|
119
114
|
dispatch({type: SET_SETTING_VALUE, data: {name, value}});
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
} else {
|
115
|
+
|
116
|
+
// If there is no settingsApi, use localStorage
|
117
|
+
if (settingsApi) {
|
124
118
|
window.api.postSetting(name, value);
|
119
|
+
} else {
|
120
|
+
try {
|
121
|
+
localStorage.setItem(name, value);
|
122
|
+
} catch {}
|
125
123
|
}
|
126
124
|
};
|
127
125
|
};
|
package/dist/utils/constants.ts
CHANGED
@@ -19,14 +19,6 @@ export const DAY_IN_SECONDS = 24 * HOUR_IN_SECONDS;
|
|
19
19
|
|
20
20
|
export const MS_IN_NANOSECONDS = 1000000;
|
21
21
|
|
22
|
-
export const TABLET_STATES = {
|
23
|
-
TABLET_VOLATILE_STATE_UNKNOWN: 'unknown',
|
24
|
-
TABLET_VOLATILE_STATE_STOPPED: 'stopped',
|
25
|
-
TABLET_VOLATILE_STATE_BOOTING: 'booting',
|
26
|
-
TABLET_VOLATILE_STATE_STARTING: 'starting',
|
27
|
-
TABLET_VOLATILE_STATE_RUNNING: 'running',
|
28
|
-
};
|
29
|
-
|
30
22
|
export const TABLET_COLORS = {
|
31
23
|
Created: 'gray',
|
32
24
|
ResolveStateStorage: 'lightgray',
|
@@ -89,9 +81,6 @@ export const THEME_KEY = 'theme';
|
|
89
81
|
export const LANGUAGE_KEY = 'language';
|
90
82
|
export const INVERTED_DISKS_KEY = 'invertedDisks';
|
91
83
|
export const USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY = 'useNodesEndpointInDiagnostics';
|
92
|
-
export const ENABLE_ADDITIONAL_QUERY_MODES = 'enableAdditionalQueryModes';
|
93
|
-
// Remain key name "enableNewTenantDiagnosticsDesign" for backward compatibility
|
94
|
-
export const DISPLAY_METRICS_CARDS_FOR_TENANT_DIAGNOSTICS = 'enableNewTenantDiagnosticsDesign';
|
95
84
|
export const SAVED_QUERIES_KEY = 'saved_queries';
|
96
85
|
export const ASIDE_HEADER_COMPACT_KEY = 'asideHeaderCompact';
|
97
86
|
export const QUERIES_HISTORY_KEY = 'queries_history';
|
@@ -1,36 +1,7 @@
|
|
1
1
|
import type {QueryMode} from '../../types/store/query';
|
2
|
-
import {
|
3
|
-
import {QUERY_MODES_TITLES, isNewQueryMode} from '../query';
|
4
|
-
import createToast from '../createToast';
|
2
|
+
import {QUERY_INITIAL_MODE_KEY} from '../constants';
|
5
3
|
import {useSetting} from './useSetting';
|
6
|
-
import i18n from './i18n';
|
7
4
|
|
8
|
-
export
|
9
|
-
|
10
|
-
errorMessage?: string | undefined,
|
11
|
-
) => boolean;
|
12
|
-
|
13
|
-
export const useQueryModes = (): [QueryMode, SetQueryModeIfAvailable] => {
|
14
|
-
const [queryMode, setQueryMode] = useSetting<QueryMode>(QUERY_INITIAL_MODE_KEY);
|
15
|
-
const [enableAdditionalQueryModes] = useSetting<boolean>(ENABLE_ADDITIONAL_QUERY_MODES);
|
16
|
-
|
17
|
-
const setQueryModeIfAvailable: SetQueryModeIfAvailable = (value, errorMessage) => {
|
18
|
-
if (isNewQueryMode(value) && !enableAdditionalQueryModes) {
|
19
|
-
createToast({
|
20
|
-
name: 'QueryModeCannotBeSet',
|
21
|
-
title:
|
22
|
-
errorMessage ??
|
23
|
-
i18n('useQueryModes.queryModeCannotBeSet', {mode: QUERY_MODES_TITLES[value]}),
|
24
|
-
type: 'error',
|
25
|
-
});
|
26
|
-
|
27
|
-
return false;
|
28
|
-
} else {
|
29
|
-
setQueryMode(value);
|
30
|
-
|
31
|
-
return true;
|
32
|
-
}
|
33
|
-
};
|
34
|
-
|
35
|
-
return [queryMode, setQueryModeIfAvailable];
|
5
|
+
export const useQueryModes = () => {
|
6
|
+
return useSetting<QueryMode>(QUERY_INITIAL_MODE_KEY);
|
36
7
|
};
|
package/dist/utils/query.ts
CHANGED
@@ -38,10 +38,6 @@ export const QUERY_SYNTAX = {
|
|
38
38
|
pg: 'pg',
|
39
39
|
} as const;
|
40
40
|
|
41
|
-
export const isNewQueryMode = (value: QueryMode) => {
|
42
|
-
return value !== QUERY_MODES.script && value !== QUERY_MODES.scan;
|
43
|
-
};
|
44
|
-
|
45
41
|
// eslint-disable-next-line complexity
|
46
42
|
export const getColumnType = (type: string) => {
|
47
43
|
switch (type.replace(/\?$/, '')) {
|
package/dist/utils/settings.ts
CHANGED
@@ -3,8 +3,11 @@ import {getValueFromLS} from './utils';
|
|
3
3
|
export const userSettings = window.userSettings || {};
|
4
4
|
export const systemSettings = window.systemSettings || {};
|
5
5
|
|
6
|
+
export const settingsApi = window.web_version ? systemSettings.settingsApi : undefined;
|
7
|
+
|
6
8
|
export function readSavedSettingsValue(key: string, defaultValue?: string) {
|
7
|
-
|
9
|
+
// If there is no settingsApi, use localStorage
|
10
|
+
const savedValue = settingsApi ? userSettings[key] : getValueFromLS(key);
|
8
11
|
|
9
12
|
return savedValue ?? defaultValue;
|
10
13
|
}
|
package/package.json
CHANGED
@@ -1,64 +0,0 @@
|
|
1
|
-
import cn from 'bem-cn-lite';
|
2
|
-
|
3
|
-
import {Button, Icon} from '@gravity-ui/uikit';
|
4
|
-
|
5
|
-
import updateArrow from '../../../../../assets/icons/update-arrow.svg';
|
6
|
-
|
7
|
-
import type {IResponseError} from '../../../../../types/api/error';
|
8
|
-
import type {IIssuesTree} from '../../../../../types/store/healthcheck';
|
9
|
-
import {ResponseError} from '../../../../../components/Errors/ResponseError';
|
10
|
-
|
11
|
-
import IssueTree from '../../TenantOverview/Healthcheck/IssuesViewer/IssueTree';
|
12
|
-
|
13
|
-
import i18n from '../../TenantOverview/Healthcheck/i18n';
|
14
|
-
|
15
|
-
const b = cn('old-healthcheck');
|
16
|
-
|
17
|
-
interface DetailsProps {
|
18
|
-
issueTrees?: IIssuesTree[];
|
19
|
-
loading?: boolean;
|
20
|
-
onUpdate: VoidFunction;
|
21
|
-
error?: IResponseError;
|
22
|
-
}
|
23
|
-
|
24
|
-
export const Details = (props: DetailsProps) => {
|
25
|
-
const {loading, onUpdate, issueTrees, error} = props;
|
26
|
-
|
27
|
-
const renderHealthcheckHeader = () => {
|
28
|
-
return (
|
29
|
-
<div className={b('details-header')}>
|
30
|
-
<h3 className={b('details-header-title')}>{i18n('title.healthcheck')}</h3>
|
31
|
-
<div className={b('details-header-update')}>
|
32
|
-
<Button size="s" onClick={onUpdate} loading={loading} view="flat-secondary">
|
33
|
-
<Icon data={updateArrow} height={20} width={20} />
|
34
|
-
</Button>
|
35
|
-
</div>
|
36
|
-
</div>
|
37
|
-
);
|
38
|
-
};
|
39
|
-
|
40
|
-
const renderContent = () => {
|
41
|
-
if (error) {
|
42
|
-
return <ResponseError error={error} defaultMessage={i18n('no-data')} />;
|
43
|
-
}
|
44
|
-
|
45
|
-
if (!issueTrees || !issueTrees.length) {
|
46
|
-
return i18n('status_message.ok');
|
47
|
-
}
|
48
|
-
|
49
|
-
return (
|
50
|
-
<>
|
51
|
-
{issueTrees.map((issueTree) => (
|
52
|
-
<IssueTree key={issueTree.id} issueTree={issueTree} />
|
53
|
-
))}
|
54
|
-
</>
|
55
|
-
);
|
56
|
-
};
|
57
|
-
|
58
|
-
return (
|
59
|
-
<div className={b('details')}>
|
60
|
-
{renderHealthcheckHeader()}
|
61
|
-
<div className={b('details-content-wrapper')}>{renderContent()}</div>
|
62
|
-
</div>
|
63
|
-
);
|
64
|
-
};
|
@@ -1 +0,0 @@
|
|
1
|
-
export * from './Details';
|
@@ -1,137 +0,0 @@
|
|
1
|
-
@import '../../../../styles/mixins.scss';
|
2
|
-
@import '@gravity-ui/uikit/styles/mixins.scss';
|
3
|
-
|
4
|
-
.old-healthcheck {
|
5
|
-
display: flex;
|
6
|
-
|
7
|
-
&_expanded {
|
8
|
-
// Since most of the inner containers have fixed width, we can set fixed width here as well
|
9
|
-
// Thus we will get rid of unneeded layout shift when scrollbar appear
|
10
|
-
min-width: 885px;
|
11
|
-
}
|
12
|
-
|
13
|
-
&__details {
|
14
|
-
width: 860px;
|
15
|
-
padding: 25px 20px 20px;
|
16
|
-
}
|
17
|
-
|
18
|
-
&__issue-preview {
|
19
|
-
margin-bottom: 15px;
|
20
|
-
}
|
21
|
-
|
22
|
-
&__details-content-wrapper {
|
23
|
-
overflow-x: hidden;
|
24
|
-
overflow-y: auto;
|
25
|
-
|
26
|
-
height: 70vh;
|
27
|
-
max-height: 70vh;
|
28
|
-
}
|
29
|
-
|
30
|
-
&__message-container {
|
31
|
-
padding: 15px 0;
|
32
|
-
}
|
33
|
-
|
34
|
-
&__details-header {
|
35
|
-
display: flex;
|
36
|
-
align-items: center;
|
37
|
-
|
38
|
-
margin-bottom: 20px;
|
39
|
-
}
|
40
|
-
|
41
|
-
&__details-header-title {
|
42
|
-
margin: 0 10px 0 0;
|
43
|
-
|
44
|
-
@include text-header-1();
|
45
|
-
}
|
46
|
-
|
47
|
-
&__details-header-update {
|
48
|
-
margin-left: 10px;
|
49
|
-
}
|
50
|
-
|
51
|
-
&__preview {
|
52
|
-
width: 206px;
|
53
|
-
padding: 16px;
|
54
|
-
padding-bottom: 28px;
|
55
|
-
|
56
|
-
border: 1px solid var(--yc-color-line-generic);
|
57
|
-
border-radius: 8px;
|
58
|
-
background-color: transparent;
|
59
|
-
}
|
60
|
-
|
61
|
-
&__preview-header {
|
62
|
-
margin-bottom: var(--diagnostics-section-title-margin);
|
63
|
-
gap: 8px;
|
64
|
-
}
|
65
|
-
|
66
|
-
&__preview-title {
|
67
|
-
font-weight: 600;
|
68
|
-
@include lead-typography();
|
69
|
-
}
|
70
|
-
|
71
|
-
&__preview-content {
|
72
|
-
line-height: 24px;
|
73
|
-
}
|
74
|
-
|
75
|
-
&__preview-title-wrapper {
|
76
|
-
display: flex;
|
77
|
-
align-items: center;
|
78
|
-
|
79
|
-
margin-bottom: 4px;
|
80
|
-
|
81
|
-
gap: 8px;
|
82
|
-
}
|
83
|
-
|
84
|
-
&__issues-statistics {
|
85
|
-
display: flex;
|
86
|
-
flex-wrap: wrap;
|
87
|
-
align-items: center;
|
88
|
-
|
89
|
-
margin: 8px 0;
|
90
|
-
|
91
|
-
gap: 10px;
|
92
|
-
}
|
93
|
-
|
94
|
-
&__self-check-status-indicator {
|
95
|
-
display: inline-block;
|
96
|
-
|
97
|
-
padding: 0 8px;
|
98
|
-
|
99
|
-
font-size: 13px;
|
100
|
-
line-height: 24px;
|
101
|
-
|
102
|
-
border-radius: 4px;
|
103
|
-
|
104
|
-
&_good,
|
105
|
-
&_green {
|
106
|
-
color: var(--yc-color-text-positive);
|
107
|
-
background-color: var(--yc-color-base-positive);
|
108
|
-
}
|
109
|
-
&_degraded,
|
110
|
-
&_yellow {
|
111
|
-
color: var(--yc-color-text-warning);
|
112
|
-
background-color: var(--yc-color-base-warning);
|
113
|
-
}
|
114
|
-
|
115
|
-
&_blue {
|
116
|
-
color: var(--yc-color-text-info);
|
117
|
-
background-color: var(--yc-color-base-info);
|
118
|
-
}
|
119
|
-
|
120
|
-
&_emergency,
|
121
|
-
&_red {
|
122
|
-
color: var(--yc-color-text-danger);
|
123
|
-
background-color: var(--yc-color-base-danger);
|
124
|
-
}
|
125
|
-
&_unspecified,
|
126
|
-
&_gray,
|
127
|
-
&_grey {
|
128
|
-
color: var(--yc-color-text-misc);
|
129
|
-
background-color: var(--yc-color-base-misc);
|
130
|
-
}
|
131
|
-
&_maintenance_required,
|
132
|
-
&_orange {
|
133
|
-
color: var(--yc-color-text-warning-heavy);
|
134
|
-
background-color: var(--yc-color-infographics-warning-light);
|
135
|
-
}
|
136
|
-
}
|
137
|
-
}
|
@@ -1,92 +0,0 @@
|
|
1
|
-
import {useCallback} from 'react';
|
2
|
-
import {useDispatch} from 'react-redux';
|
3
|
-
import cn from 'bem-cn-lite';
|
4
|
-
|
5
|
-
import {Loader} from '@gravity-ui/uikit';
|
6
|
-
|
7
|
-
import {SelfCheckResult} from '../../../../types/api/healthcheck';
|
8
|
-
import {useTypedSelector, useAutofetcher} from '../../../../utils/hooks';
|
9
|
-
import {
|
10
|
-
getHealthcheckInfo,
|
11
|
-
selectIssuesStatistics,
|
12
|
-
selectIssuesTrees,
|
13
|
-
setDataWasNotLoaded,
|
14
|
-
} from '../../../../store/reducers/healthcheckInfo';
|
15
|
-
|
16
|
-
import {Details} from './Details';
|
17
|
-
import {Preview} from './Preview';
|
18
|
-
|
19
|
-
import './Healthcheck.scss';
|
20
|
-
|
21
|
-
interface HealthcheckProps {
|
22
|
-
tenant: string;
|
23
|
-
preview?: boolean;
|
24
|
-
fetchData?: boolean;
|
25
|
-
showMoreHandler?: VoidFunction;
|
26
|
-
}
|
27
|
-
|
28
|
-
const b = cn('old-healthcheck');
|
29
|
-
|
30
|
-
export const Healthcheck = (props: HealthcheckProps) => {
|
31
|
-
const {tenant, preview, fetchData = true, showMoreHandler} = props;
|
32
|
-
|
33
|
-
const dispatch = useDispatch();
|
34
|
-
|
35
|
-
const {data, loading, wasLoaded, error} = useTypedSelector((state) => state.healthcheckInfo);
|
36
|
-
const issuesStatistics = useTypedSelector(selectIssuesStatistics);
|
37
|
-
const issueTrees = useTypedSelector(selectIssuesTrees);
|
38
|
-
const {autorefresh} = useTypedSelector((state) => state.schema);
|
39
|
-
|
40
|
-
const selfCheckResult = data?.self_check_result || SelfCheckResult.UNSPECIFIED;
|
41
|
-
|
42
|
-
const fetchHealthcheck = useCallback(
|
43
|
-
(isBackground = true) => {
|
44
|
-
if (!isBackground) {
|
45
|
-
dispatch(setDataWasNotLoaded());
|
46
|
-
}
|
47
|
-
|
48
|
-
dispatch(getHealthcheckInfo(tenant));
|
49
|
-
},
|
50
|
-
[dispatch, tenant],
|
51
|
-
);
|
52
|
-
|
53
|
-
useAutofetcher(
|
54
|
-
(isBackground) => {
|
55
|
-
if (fetchData) {
|
56
|
-
fetchHealthcheck(isBackground);
|
57
|
-
}
|
58
|
-
},
|
59
|
-
[fetchData, fetchHealthcheck],
|
60
|
-
autorefresh,
|
61
|
-
);
|
62
|
-
|
63
|
-
const renderContent = () => {
|
64
|
-
if (loading && !wasLoaded) {
|
65
|
-
return (
|
66
|
-
<div className={b('old-preview', {loader: true})}>
|
67
|
-
<Loader size="m" />
|
68
|
-
</div>
|
69
|
-
);
|
70
|
-
}
|
71
|
-
|
72
|
-
return preview ? (
|
73
|
-
<Preview
|
74
|
-
issuesStatistics={issuesStatistics}
|
75
|
-
selfCheckResult={selfCheckResult}
|
76
|
-
loading={loading}
|
77
|
-
onShowMore={showMoreHandler}
|
78
|
-
onUpdate={fetchHealthcheck}
|
79
|
-
error={error}
|
80
|
-
/>
|
81
|
-
) : (
|
82
|
-
<Details
|
83
|
-
loading={loading}
|
84
|
-
onUpdate={fetchHealthcheck}
|
85
|
-
issueTrees={issueTrees}
|
86
|
-
error={error}
|
87
|
-
/>
|
88
|
-
);
|
89
|
-
};
|
90
|
-
|
91
|
-
return <div className={b({expanded: !preview})}>{renderContent()}</div>;
|
92
|
-
};
|
@@ -1,82 +0,0 @@
|
|
1
|
-
import cn from 'bem-cn-lite';
|
2
|
-
|
3
|
-
import {Button, Icon, Link} from '@gravity-ui/uikit';
|
4
|
-
|
5
|
-
import updateArrow from '../../../../../assets/icons/update-arrow.svg';
|
6
|
-
|
7
|
-
import {SelfCheckResult, type StatusFlag} from '../../../../../types/api/healthcheck';
|
8
|
-
import type {IResponseError} from '../../../../../types/api/error';
|
9
|
-
import EntityStatus from '../../../../../components/EntityStatus/EntityStatus';
|
10
|
-
import {ResponseError} from '../../../../../components/Errors/ResponseError';
|
11
|
-
|
12
|
-
import i18n from '../../TenantOverview/Healthcheck/i18n';
|
13
|
-
|
14
|
-
const b = cn('old-healthcheck');
|
15
|
-
|
16
|
-
interface PreviewProps {
|
17
|
-
selfCheckResult: SelfCheckResult;
|
18
|
-
issuesStatistics?: [StatusFlag, number][];
|
19
|
-
loading?: boolean;
|
20
|
-
onShowMore?: VoidFunction;
|
21
|
-
onUpdate: VoidFunction;
|
22
|
-
error?: IResponseError;
|
23
|
-
}
|
24
|
-
|
25
|
-
export const Preview = (props: PreviewProps) => {
|
26
|
-
const {selfCheckResult, issuesStatistics, loading, onShowMore, onUpdate, error} = props;
|
27
|
-
|
28
|
-
const renderHeader = () => {
|
29
|
-
const modifier = selfCheckResult.toLowerCase();
|
30
|
-
|
31
|
-
return (
|
32
|
-
<div className={b('preview-header')}>
|
33
|
-
<div className={b('preview-title-wrapper')}>
|
34
|
-
<div className={b('preview-title')}>{i18n('title.healthcheck')}</div>
|
35
|
-
<Button size="s" onClick={onUpdate} loading={loading} view="flat-secondary">
|
36
|
-
<Icon data={updateArrow} width={20} height={20} />
|
37
|
-
</Button>
|
38
|
-
</div>
|
39
|
-
<div className={b('self-check-status-indicator', {[modifier]: true})}>
|
40
|
-
{selfCheckResult}
|
41
|
-
</div>
|
42
|
-
</div>
|
43
|
-
);
|
44
|
-
};
|
45
|
-
|
46
|
-
const renderContent = () => {
|
47
|
-
if (error) {
|
48
|
-
return <ResponseError error={error} defaultMessage={i18n('no-data')} />;
|
49
|
-
}
|
50
|
-
|
51
|
-
return (
|
52
|
-
<div className={b('preview-content')}>
|
53
|
-
{!issuesStatistics || !issuesStatistics.length ? (
|
54
|
-
i18n('status_message.ok')
|
55
|
-
) : (
|
56
|
-
<>
|
57
|
-
<div>{i18n('label.issues')}</div>
|
58
|
-
<div className={b('issues-statistics')}>
|
59
|
-
{issuesStatistics.map(([status, count]) => (
|
60
|
-
<EntityStatus
|
61
|
-
key={status}
|
62
|
-
mode="icons"
|
63
|
-
status={status}
|
64
|
-
label={count.toString()}
|
65
|
-
size="l"
|
66
|
-
/>
|
67
|
-
))}
|
68
|
-
</div>
|
69
|
-
<Link onClick={() => onShowMore?.()}>{i18n('label.show-details')}</Link>
|
70
|
-
</>
|
71
|
-
)}
|
72
|
-
</div>
|
73
|
-
);
|
74
|
-
};
|
75
|
-
|
76
|
-
return (
|
77
|
-
<div className={b('preview')}>
|
78
|
-
{renderHeader()}
|
79
|
-
{renderContent()}
|
80
|
-
</div>
|
81
|
-
);
|
82
|
-
};
|
@@ -1 +0,0 @@
|
|
1
|
-
export * from './Preview';
|
@@ -1 +0,0 @@
|
|
1
|
-
export * from './Healthcheck';
|
@@ -1,155 +0,0 @@
|
|
1
|
-
import cn from 'bem-cn-lite';
|
2
|
-
import {useCallback} from 'react';
|
3
|
-
import {useDispatch} from 'react-redux';
|
4
|
-
|
5
|
-
import {Loader} from '@gravity-ui/uikit';
|
6
|
-
|
7
|
-
import {InfoViewer} from '../../../../components/InfoViewer';
|
8
|
-
import {PoolUsage} from '../../../../components/PoolUsage/PoolUsage';
|
9
|
-
import {Tablet} from '../../../../components/Tablet';
|
10
|
-
import EntityStatus from '../../../../components/EntityStatus/EntityStatus';
|
11
|
-
import {formatCPU} from '../../../../utils/dataFormatters/dataFormatters';
|
12
|
-
import {TABLET_STATES, TENANT_DEFAULT_TITLE} from '../../../../utils/constants';
|
13
|
-
import {bytesToGB} from '../../../../utils/utils';
|
14
|
-
import {mapDatabaseTypeToDBName} from '../../utils/schema';
|
15
|
-
import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
|
16
|
-
import type {ETabletVolatileState} from '../../../../types/api/tenant';
|
17
|
-
import type {AdditionalTenantsProps} from '../../../../types/additionalProps';
|
18
|
-
import {getTenantInfo, setDataWasNotLoaded} from '../../../../store/reducers/tenant/tenant';
|
19
|
-
|
20
|
-
import i18n from './i18n';
|
21
|
-
import './TenantOverview.scss';
|
22
|
-
|
23
|
-
const b = cn('tenant-overview');
|
24
|
-
|
25
|
-
interface OldTenantOverviewProps {
|
26
|
-
tenantName: string;
|
27
|
-
additionalTenantProps?: AdditionalTenantsProps;
|
28
|
-
}
|
29
|
-
|
30
|
-
export function OldTenantOverview({tenantName, additionalTenantProps}: OldTenantOverviewProps) {
|
31
|
-
const {tenant, loading, wasLoaded} = useTypedSelector((state) => state.tenant);
|
32
|
-
const {autorefresh} = useTypedSelector((state) => state.schema);
|
33
|
-
const dispatch = useDispatch();
|
34
|
-
const fetchTenant = useCallback(
|
35
|
-
(isBackground = true) => {
|
36
|
-
if (!isBackground) {
|
37
|
-
dispatch(setDataWasNotLoaded());
|
38
|
-
}
|
39
|
-
dispatch(getTenantInfo({path: tenantName}));
|
40
|
-
},
|
41
|
-
[dispatch, tenantName],
|
42
|
-
);
|
43
|
-
|
44
|
-
useAutofetcher(fetchTenant, [fetchTenant], autorefresh);
|
45
|
-
|
46
|
-
const {
|
47
|
-
Metrics = {},
|
48
|
-
PoolStats,
|
49
|
-
StateStats = [],
|
50
|
-
MemoryUsed,
|
51
|
-
Name,
|
52
|
-
State,
|
53
|
-
CoresUsed,
|
54
|
-
StorageGroups,
|
55
|
-
StorageAllocatedSize,
|
56
|
-
Type,
|
57
|
-
SystemTablets,
|
58
|
-
} = tenant || {};
|
59
|
-
|
60
|
-
const tenantType = mapDatabaseTypeToDBName(Type);
|
61
|
-
const memoryRaw = MemoryUsed ?? Metrics.Memory;
|
62
|
-
|
63
|
-
const memory = (memoryRaw && bytesToGB(memoryRaw)) || i18n('no-data');
|
64
|
-
const storage = (Metrics.Storage && bytesToGB(Metrics.Storage)) || i18n('no-data');
|
65
|
-
const storageGroups = StorageGroups ?? i18n('no-data');
|
66
|
-
const blobStorage =
|
67
|
-
(StorageAllocatedSize && bytesToGB(StorageAllocatedSize)) || i18n('no-data');
|
68
|
-
const storageEfficiency =
|
69
|
-
Metrics.Storage && StorageAllocatedSize
|
70
|
-
? `${((parseInt(Metrics.Storage) * 100) / parseInt(StorageAllocatedSize)).toFixed(2)}%`
|
71
|
-
: i18n('no-data');
|
72
|
-
|
73
|
-
const cpuRaw = CoresUsed !== undefined ? Number(CoresUsed) * 1_000_000 : Metrics.CPU;
|
74
|
-
|
75
|
-
const cpu = formatCPU(cpuRaw);
|
76
|
-
|
77
|
-
const metricsInfo = [
|
78
|
-
{label: 'Type', value: Type},
|
79
|
-
{label: 'Memory', value: memory},
|
80
|
-
{label: 'CPU', value: cpu},
|
81
|
-
{label: 'Tablet storage', value: storage},
|
82
|
-
{label: 'Storage groups', value: storageGroups},
|
83
|
-
{label: 'Blob storage', value: blobStorage},
|
84
|
-
{label: 'Storage efficiency', value: storageEfficiency},
|
85
|
-
];
|
86
|
-
|
87
|
-
const tabletsInfo = StateStats.filter(
|
88
|
-
(item): item is {VolatileState: ETabletVolatileState; Count: number} => {
|
89
|
-
return item.VolatileState !== undefined && item.Count !== undefined;
|
90
|
-
},
|
91
|
-
).map((info) => {
|
92
|
-
return {label: TABLET_STATES[info.VolatileState], value: info.Count};
|
93
|
-
});
|
94
|
-
|
95
|
-
const renderName = () => {
|
96
|
-
return (
|
97
|
-
<div className={b('tenant-name-wrapper')}>
|
98
|
-
<EntityStatus
|
99
|
-
status={State}
|
100
|
-
name={Name || TENANT_DEFAULT_TITLE}
|
101
|
-
withLeftTrim
|
102
|
-
hasClipboardButton={Boolean(tenant)}
|
103
|
-
clipboardButtonAlwaysVisible
|
104
|
-
/>
|
105
|
-
</div>
|
106
|
-
);
|
107
|
-
};
|
108
|
-
|
109
|
-
if (loading && !wasLoaded) {
|
110
|
-
return (
|
111
|
-
<div className={b('loader')}>
|
112
|
-
<Loader size="m" />
|
113
|
-
</div>
|
114
|
-
);
|
115
|
-
}
|
116
|
-
|
117
|
-
return (
|
118
|
-
<div className={b()}>
|
119
|
-
<div className={b('top-label')}>{tenantType}</div>
|
120
|
-
<div className={b('top')}>
|
121
|
-
{renderName()}
|
122
|
-
{additionalTenantProps?.getMonitoringLink?.(Name, Type)}
|
123
|
-
</div>
|
124
|
-
<div className={b('system-tablets')}>
|
125
|
-
{SystemTablets &&
|
126
|
-
SystemTablets.map((tablet, tabletIndex) => (
|
127
|
-
<Tablet key={tabletIndex} tablet={tablet} tenantName={Name} />
|
128
|
-
))}
|
129
|
-
</div>
|
130
|
-
<div className={b('common-info')}>
|
131
|
-
<div>
|
132
|
-
<div className={b('section-title')}>{i18n('title.pools')}</div>
|
133
|
-
{PoolStats ? (
|
134
|
-
<div className={b('section', {pools: true})}>
|
135
|
-
{PoolStats.map((pool, poolIndex) => (
|
136
|
-
<PoolUsage key={poolIndex} data={pool} />
|
137
|
-
))}
|
138
|
-
</div>
|
139
|
-
) : (
|
140
|
-
<div className="error">{i18n('no-pools-data')}</div>
|
141
|
-
)}
|
142
|
-
</div>
|
143
|
-
<InfoViewer
|
144
|
-
title={i18n('title.metrics')}
|
145
|
-
className={b('section', {metrics: true})}
|
146
|
-
info={metricsInfo}
|
147
|
-
/>
|
148
|
-
|
149
|
-
<div className={b('section')}>
|
150
|
-
<InfoViewer info={tabletsInfo} title="Tablets" />
|
151
|
-
</div>
|
152
|
-
</div>
|
153
|
-
</div>
|
154
|
-
);
|
155
|
-
}
|
@@ -1,11 +0,0 @@
|
|
1
|
-
import {i18n, Lang} from '../../../utils/i18n';
|
2
|
-
|
3
|
-
import en from './en.json';
|
4
|
-
import ru from './ru.json';
|
5
|
-
|
6
|
-
const COMPONENT = 'ydb-hooks';
|
7
|
-
|
8
|
-
i18n.registerKeyset(Lang.En, COMPONENT, en);
|
9
|
-
i18n.registerKeyset(Lang.Ru, COMPONENT, ru);
|
10
|
-
|
11
|
-
export default i18n.keyset(COMPONENT);
|