ydb-embedded-ui 2.0.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +46 -0
- package/dist/assets/icons/update-arrow.svg +6 -0
- package/dist/components/EntityStatus/EntityStatus.js +37 -10
- package/dist/components/EntityStatus/EntityStatus.scss +36 -6
- package/dist/components/NodesViewer/NodesViewer.js +1 -0
- package/dist/components/ShortyString/ShortyString.tsx +21 -8
- package/dist/components/ShortyString/i18n/en.json +10 -0
- package/dist/components/ShortyString/i18n/index.ts +11 -0
- package/dist/components/ShortyString/i18n/ru.json +10 -0
- package/dist/containers/Cluster/Cluster.tsx +3 -3
- package/dist/containers/Nodes/Nodes.js +6 -6
- package/dist/containers/Storage/StorageFilter/StorageFilter.tsx +1 -0
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +2 -2
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +16 -9
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +18 -5
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +83 -0
- package/dist/containers/Tenant/Diagnostics/Healthcheck/IssuePreview/IssuePreview.tsx +35 -0
- package/dist/containers/Tenant/Diagnostics/Healthcheck/IssuePreview/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Healthcheck/IssuesList/IssuesList.tsx +62 -0
- package/dist/containers/Tenant/Diagnostics/Healthcheck/IssuesList/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Healthcheck/IssuesViewer/IssueViewer.scss +21 -15
- package/dist/containers/Tenant/Diagnostics/Healthcheck/IssuesViewer/IssuesViewer.js +52 -86
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Preview/Preview.tsx +74 -0
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Preview/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Healthcheck/i18n/en.json +7 -0
- package/dist/containers/Tenant/Diagnostics/Healthcheck/i18n/index.ts +11 -0
- package/dist/containers/Tenant/Diagnostics/Healthcheck/i18n/ru.json +7 -0
- package/dist/containers/Tenant/Diagnostics/Healthcheck/index.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +4 -21
- package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.js +18 -19
- package/dist/containers/Tenant/QueryEditor/QueryResult/QueryResult.scss +1 -0
- package/dist/containers/Tenant/Tenant.tsx +2 -2
- package/dist/containers/Tenants/Tenants.js +7 -7
- package/dist/services/api.d.ts +9 -0
- package/dist/types/api/healthcheck.ts +91 -0
- package/dist/types/store/healthcheck.ts +3 -0
- package/dist/utils/hooks/index.ts +1 -0
- package/dist/utils/hooks/useAutofetcher.ts +29 -0
- package/package.json +4 -1
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.js +0 -195
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,51 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [2.2.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v2.1.0...v2.2.0) (2022-10-14)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* **Healthcheck:** rework issues list in modal ([e7cb0df](https://github.com/ydb-platform/ydb-embedded-ui/commit/e7cb0df58e22c8c9cd25aae83b78be4808e9ba81))
|
9
|
+
|
10
|
+
|
11
|
+
### Bug Fixes
|
12
|
+
|
13
|
+
* **EntityStatus:** enable component to left trim links ([fbc6c51](https://github.com/ydb-platform/ydb-embedded-ui/commit/fbc6c51f9fbea3c1a7f5f70cb542971a41f4d8b3))
|
14
|
+
* fix pre-commit prettier linting and add json linting ([#189](https://github.com/ydb-platform/ydb-embedded-ui/issues/189)) ([047415d](https://github.com/ydb-platform/ydb-embedded-ui/commit/047415d2d69ecf4a2d99f0092b9e6735bd8efbc0))
|
15
|
+
* **Healthcheck:** delete unneeded i18n translations ([0c6de90](https://github.com/ydb-platform/ydb-embedded-ui/commit/0c6de9031607e4cde1387387393a9cfc9e1e2b8f))
|
16
|
+
* **Healthcheck:** enable update button in modal to fetch data ([de0b06e](https://github.com/ydb-platform/ydb-embedded-ui/commit/de0b06e7f2d3536df1b3896cbf86a947b2e7a291))
|
17
|
+
* **Healthcheck:** fix layout shift on scrollbar appearance ([ccdde6e](https://github.com/ydb-platform/ydb-embedded-ui/commit/ccdde6e065abbdb1c22a2c3bdd17e63f706d0f77))
|
18
|
+
* **Healthcheck:** fix styles for long issues trees ([32f1a8d](https://github.com/ydb-platform/ydb-embedded-ui/commit/32f1a8db58d9f84073327b92dcd80a5b4626a526))
|
19
|
+
* **Healthcheck:** fix variable typo ([0f0e056](https://github.com/ydb-platform/ydb-embedded-ui/commit/0f0e056576b9ec18fc3ce574d3742d55e5da6e35))
|
20
|
+
* **Healthcheck:** full check status in a preview ([bc0b51e](https://github.com/ydb-platform/ydb-embedded-ui/commit/bc0b51eedd4ff3b4ae1650946832f463a6703c12))
|
21
|
+
* **Healthcheck:** make modal show only one first level issue ([cdc95a7](https://github.com/ydb-platform/ydb-embedded-ui/commit/cdc95a7412c1266d990df7e2807630a8f4c88780))
|
22
|
+
* **Healthcheck:** redesign healthcheck header ([867f57a](https://github.com/ydb-platform/ydb-embedded-ui/commit/867f57aed84b7b72c22a816c6ac02387490ff495))
|
23
|
+
* **Healthcheck:** replace update button with icon ([709a994](https://github.com/ydb-platform/ydb-embedded-ui/commit/709a994544f068db1b0fe09009ecb4d8db46fc38))
|
24
|
+
* **Healthcheck:** update styles to be closer to the design ([aa1083d](https://github.com/ydb-platform/ydb-embedded-ui/commit/aa1083d299e24590336eeb3d913a9c53fd77bad6))
|
25
|
+
* **Nodes:** case insensitive search ([11d2c98](https://github.com/ydb-platform/ydb-embedded-ui/commit/11d2c985e0c30bb74ed07e22273d8b3459b54c89))
|
26
|
+
* **QueryEditor:** smarter error message trim ([8632948](https://github.com/ydb-platform/ydb-embedded-ui/commit/863294828090dc8eb2595884283d0996156c3785))
|
27
|
+
* **Tenants:** case insensitive search ([0ad93f5](https://github.com/ydb-platform/ydb-embedded-ui/commit/0ad93f57dcbba7d9746be54a4ba7b76ab4d45108))
|
28
|
+
* **Tenants:** fix filtering by ControlPlane name ([4941c82](https://github.com/ydb-platform/ydb-embedded-ui/commit/4941c821cdbb7c5d0da26a3b0d5c00d8979401c0))
|
29
|
+
* **Tenants:** left trim db names in db list ([81bf0fa](https://github.com/ydb-platform/ydb-embedded-ui/commit/81bf0fafe901d3601dc04fdf71939e914493ff1c))
|
30
|
+
|
31
|
+
## [2.1.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v2.0.0...v2.1.0) (2022-10-04)
|
32
|
+
|
33
|
+
|
34
|
+
### Features
|
35
|
+
|
36
|
+
* autofocus all text search fields ([a38ee84](https://github.com/ydb-platform/ydb-embedded-ui/commit/a38ee84abad4202f5e9b8af897eb68d2c006233a))
|
37
|
+
* **Healthcheck:** display first level issues in overview ([10b4bf5](https://github.com/ydb-platform/ydb-embedded-ui/commit/10b4bf5d15d32f028702ff8cfecca0e06bc5616f))
|
38
|
+
|
39
|
+
|
40
|
+
### Bug Fixes
|
41
|
+
|
42
|
+
* fix production assets paths ([8eaad0f](https://github.com/ydb-platform/ydb-embedded-ui/commit/8eaad0f1db109c4cf3cbf7d11ad32ea335a6b0c1))
|
43
|
+
* **Healthcheck:** add translations ([75f9851](https://github.com/ydb-platform/ydb-embedded-ui/commit/75f9851a35766ef692805a6f154d40340b003487))
|
44
|
+
* move eslint hooks rule extension to src config ([179b81d](https://github.com/ydb-platform/ydb-embedded-ui/commit/179b81d60adf422addc8d72f947800c72bd3e4c5))
|
45
|
+
* **QueryEditor:** disable fullscreen button for empty result ([4825b5b](https://github.com/ydb-platform/ydb-embedded-ui/commit/4825b5b8dcb89fcafd828dabbace521ddc429922))
|
46
|
+
* **QueryEditor:** fix query stats spacings ([b836d72](https://github.com/ydb-platform/ydb-embedded-ui/commit/b836d72824a791b3fde2b9e4585c6c9b42385265))
|
47
|
+
* **useAutofetcher:** private autofetcher instance for each usage ([3f34b7a](https://github.com/ydb-platform/ydb-embedded-ui/commit/3f34b7aee2042562a42e6d1a7daf03ffddd888c0))
|
48
|
+
|
3
49
|
## [2.0.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.14.2...v2.0.0) (2022-09-26)
|
4
50
|
|
5
51
|
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<path d="M21 12C21 16.9706 16.9706 21 12 21C9.5 21 6.5 19 5 17" stroke='currentColor' stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
3
|
+
<path d="M5 21L5 17L9 17" stroke='currentColor' stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
4
|
+
<path d="M3 12C3 7.02944 7.02944 3 12 3C14.5 3 17.5 5 19 7" stroke='currentColor' stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
5
|
+
<path d="M19 3L19 7L15 7" stroke='currentColor' stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
6
|
+
</svg>
|
@@ -2,10 +2,22 @@ import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
3
3
|
import cn from 'bem-cn-lite';
|
4
4
|
import {Link} from 'react-router-dom';
|
5
|
-
import {ClipboardButton, Link as
|
5
|
+
import {ClipboardButton, Link as UIKitLink, Button, Icon} from '@gravity-ui/uikit';
|
6
|
+
|
7
|
+
import circleInfoIcon from '../../assets/icons/circle-info.svg';
|
8
|
+
import circleExclamationIcon from '../../assets/icons/circle-exclamation.svg';
|
9
|
+
import triangleExclamationIcon from '../../assets/icons/triangle-exclamation.svg';
|
10
|
+
import circleTimesIcon from '../../assets/icons/circle-xmark.svg';
|
6
11
|
|
7
12
|
import './EntityStatus.scss';
|
8
13
|
|
14
|
+
const icons = {
|
15
|
+
BLUE: circleInfoIcon,
|
16
|
+
YELLOW: circleExclamationIcon,
|
17
|
+
ORANGE: triangleExclamationIcon,
|
18
|
+
RED: circleTimesIcon,
|
19
|
+
};
|
20
|
+
|
9
21
|
const b = cn('entity-status');
|
10
22
|
|
11
23
|
class EntityStatus extends React.Component {
|
@@ -22,6 +34,8 @@ class EntityStatus extends React.Component {
|
|
22
34
|
showStatus: PropTypes.bool,
|
23
35
|
externalLink: PropTypes.bool,
|
24
36
|
className: PropTypes.string,
|
37
|
+
mode: PropTypes.oneOf(['color', 'icons']),
|
38
|
+
withLeftTrim: PropTypes.bool,
|
25
39
|
};
|
26
40
|
|
27
41
|
static defaultProps = {
|
@@ -31,35 +45,47 @@ class EntityStatus extends React.Component {
|
|
31
45
|
label: '',
|
32
46
|
showStatus: true,
|
33
47
|
externalLink: false,
|
48
|
+
mode: 'color',
|
49
|
+
withLeftTrim: false,
|
34
50
|
};
|
35
51
|
renderIcon() {
|
36
|
-
const {status, size, showStatus} = this.props;
|
52
|
+
const {status, size, showStatus, mode} = this.props;
|
37
53
|
|
38
54
|
if (!showStatus) {
|
39
55
|
return null;
|
40
56
|
}
|
41
57
|
|
42
|
-
|
58
|
+
const modifiers = {state: status.toLowerCase(), size};
|
59
|
+
|
60
|
+
if (mode === 'icons' && icons[status]) {
|
61
|
+
return <Icon className={b('status-icon', modifiers)} data={icons[status]} />;
|
62
|
+
}
|
63
|
+
|
64
|
+
return <div className={b('status-color', modifiers)} />;
|
43
65
|
}
|
44
66
|
renderStatusLink() {
|
45
67
|
const {iconPath} = this.props;
|
46
68
|
|
47
69
|
return (
|
48
|
-
<
|
70
|
+
<UIKitLink target="_blank" href={iconPath}>
|
49
71
|
{this.renderIcon()}
|
50
|
-
</
|
72
|
+
</UIKitLink>
|
51
73
|
);
|
52
74
|
}
|
53
75
|
renderLink() {
|
54
76
|
const {externalLink, name, path, onNameMouseEnter, onNameMouseLeave} = this.props;
|
55
77
|
|
56
78
|
if (externalLink) {
|
57
|
-
return
|
79
|
+
return (
|
80
|
+
<UIKitLink className={b('name')} href={path}>
|
81
|
+
{name}
|
82
|
+
</UIKitLink>
|
83
|
+
);
|
58
84
|
}
|
59
85
|
|
60
86
|
return path ? (
|
61
87
|
<Link
|
62
|
-
|
88
|
+
className={b('name')}
|
63
89
|
to={path}
|
64
90
|
onMouseEnter={onNameMouseEnter}
|
65
91
|
onMouseLeave={onNameMouseLeave}
|
@@ -70,7 +96,6 @@ class EntityStatus extends React.Component {
|
|
70
96
|
name && (
|
71
97
|
<span
|
72
98
|
className={b('name')}
|
73
|
-
title={name}
|
74
99
|
onMouseEnter={onNameMouseEnter}
|
75
100
|
onMouseLeave={onNameMouseLeave}
|
76
101
|
>
|
@@ -83,14 +108,16 @@ class EntityStatus extends React.Component {
|
|
83
108
|
const {name, label, iconPath, hasClipboardButton, className} = this.props;
|
84
109
|
|
85
110
|
return (
|
86
|
-
<div className={b(null, className)}>
|
111
|
+
<div className={b(null, className)} title={name}>
|
87
112
|
{iconPath ? this.renderStatusLink() : this.renderIcon()}
|
88
113
|
{label && (
|
89
114
|
<span title={label} className={b('label')}>
|
90
115
|
{label}
|
91
116
|
</span>
|
92
117
|
)}
|
93
|
-
{this.
|
118
|
+
<span className={b('link', {'with-left-trim': this.props.withLeftTrim})}>
|
119
|
+
{this.renderLink()}
|
120
|
+
</span>
|
94
121
|
{hasClipboardButton && (
|
95
122
|
<Button
|
96
123
|
component="span"
|
@@ -31,11 +31,7 @@
|
|
31
31
|
}
|
32
32
|
|
33
33
|
a {
|
34
|
-
overflow: hidden;
|
35
|
-
|
36
|
-
white-space: nowrap;
|
37
34
|
text-decoration: none;
|
38
|
-
text-overflow: ellipsis;
|
39
35
|
|
40
36
|
color: var(--yc-color-text-link);
|
41
37
|
}
|
@@ -53,30 +49,49 @@
|
|
53
49
|
color: var(--yc-color-text-complementary);
|
54
50
|
}
|
55
51
|
|
56
|
-
&
|
52
|
+
&__link {
|
53
|
+
overflow: hidden;
|
54
|
+
|
57
55
|
white-space: nowrap;
|
56
|
+
text-overflow: ellipsis;
|
57
|
+
}
|
58
|
+
|
59
|
+
&__link_with-left-trim {
|
60
|
+
direction: rtl;
|
61
|
+
|
62
|
+
.entity-status__name {
|
63
|
+
unicode-bidi: plaintext;
|
64
|
+
}
|
58
65
|
}
|
59
66
|
|
67
|
+
&__status-color,
|
60
68
|
&__status-icon {
|
69
|
+
flex-shrink: 0;
|
70
|
+
|
61
71
|
margin-right: 8px;
|
62
72
|
|
63
73
|
border-radius: 3px;
|
64
74
|
&_size_xs {
|
65
75
|
aspect-ratio: 1;
|
66
76
|
|
77
|
+
width: 12px;
|
67
78
|
height: 12px;
|
68
79
|
}
|
69
80
|
&_size_s {
|
70
81
|
aspect-ratio: 1;
|
71
82
|
|
83
|
+
width: 16px;
|
72
84
|
height: 16px;
|
73
85
|
}
|
74
86
|
&_size_m {
|
75
87
|
aspect-ratio: 1;
|
76
88
|
|
89
|
+
width: 18px;
|
77
90
|
height: 18px;
|
78
91
|
}
|
92
|
+
}
|
79
93
|
|
94
|
+
&__status-color {
|
80
95
|
&_state_running,
|
81
96
|
&_state_green {
|
82
97
|
background-color: var(--yc-color-infographics-positive-heavy);
|
@@ -96,7 +111,22 @@
|
|
96
111
|
background: var(--yc-color-text-complementary);
|
97
112
|
}
|
98
113
|
&_state_orange {
|
99
|
-
background: var(--yc-color-
|
114
|
+
background: var(--yc-color-base-warning-orange);
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
&__status-icon {
|
119
|
+
&_state_blue {
|
120
|
+
color: var(--yc-color-infographics-info-heavy);
|
121
|
+
}
|
122
|
+
&_state_yellow {
|
123
|
+
color: var(--yc-color-infographics-warning-heavy);
|
124
|
+
}
|
125
|
+
&_state_orange {
|
126
|
+
color: var(--yc-color-base-warning-orange);
|
127
|
+
}
|
128
|
+
&_state_red {
|
129
|
+
color: var(--yc-color-infographics-danger-heavy);
|
100
130
|
}
|
101
131
|
}
|
102
132
|
|
@@ -106,6 +106,7 @@ class NodesViewer extends React.PureComponent {
|
|
106
106
|
text={searchQuery}
|
107
107
|
onUpdate={handleSearchQuery}
|
108
108
|
hasClear
|
109
|
+
autoFocus
|
109
110
|
/>
|
110
111
|
<ProblemFilter value={filter} onChange={this.onChangeProblemFilter} />
|
111
112
|
<Label theme="info" size="m">{`Nodes: ${nodesToShow.length}`}</Label>
|
@@ -3,6 +3,7 @@ import cn from 'bem-cn-lite';
|
|
3
3
|
|
4
4
|
import {Link} from '@gravity-ui/uikit';
|
5
5
|
|
6
|
+
import i18n from './i18n';
|
6
7
|
import './ShortyString.scss';
|
7
8
|
|
8
9
|
const block = cn('kv-shorty-string');
|
@@ -10,6 +11,8 @@ const block = cn('kv-shorty-string');
|
|
10
11
|
type Props = {
|
11
12
|
value?: string;
|
12
13
|
limit?: number;
|
14
|
+
/** in strict mode the text always trims at the limit, otherwise it is allowed to overflow a little */
|
15
|
+
strict?: boolean;
|
13
16
|
displayLength?: boolean;
|
14
17
|
render?: (value: string) => React.ReactNode;
|
15
18
|
onToggle?: () => void;
|
@@ -20,19 +23,29 @@ type Props = {
|
|
20
23
|
export default function ShortyString({
|
21
24
|
value = '',
|
22
25
|
limit = 200,
|
26
|
+
strict = false,
|
23
27
|
displayLength = true,
|
24
28
|
render = (v: string) => v,
|
25
29
|
onToggle,
|
26
|
-
expandLabel = '
|
27
|
-
collapseLabel = '
|
30
|
+
expandLabel = i18n('default_expand_label'),
|
31
|
+
collapseLabel = i18n('default_collapse_label'),
|
28
32
|
}: Props) {
|
29
33
|
const [expanded, setExpanded] = React.useState(false);
|
30
|
-
const hasToggle = value.length > limit;
|
31
|
-
const length =
|
32
|
-
displayLength && !expanded ? `(${value.length} symbols)` : undefined;
|
33
34
|
|
34
|
-
const
|
35
|
-
const
|
35
|
+
const toggleLabelAction = expanded ? collapseLabel : expandLabel;
|
36
|
+
const toggleLabelSymbolsCount = displayLength && !expanded
|
37
|
+
? i18n('chars_count', {count: value.length})
|
38
|
+
: '';
|
39
|
+
const toggleLabel = toggleLabelAction + toggleLabelSymbolsCount;
|
40
|
+
|
41
|
+
// showing toogle button with a label that is longer than the hidden part is pointless,
|
42
|
+
// hence compare to limit + length in the not-strict mode
|
43
|
+
const hasToggle = value.length > limit + (strict ? 0 : toggleLabel.length);
|
44
|
+
|
45
|
+
const text = expanded || !hasToggle
|
46
|
+
? value
|
47
|
+
: value.slice(0, limit - 4) + '\u00a0...';
|
48
|
+
|
36
49
|
return (
|
37
50
|
<div className={block()}>
|
38
51
|
{render(text)}
|
@@ -45,7 +58,7 @@ export default function ShortyString({
|
|
45
58
|
onToggle?.();
|
46
59
|
}}
|
47
60
|
>
|
48
|
-
{
|
61
|
+
{toggleLabel}
|
49
62
|
</Link>
|
50
63
|
) : null}
|
51
64
|
</div>
|
@@ -0,0 +1,11 @@
|
|
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-shorty-string';
|
7
|
+
|
8
|
+
i18n.registerKeyset(Lang.En, COMPONENT, en);
|
9
|
+
i18n.registerKeyset(Lang.Ru, COMPONENT, ru);
|
10
|
+
|
11
|
+
export default i18n.keyset(COMPONENT);
|
@@ -14,9 +14,9 @@ import ClusterInfo from '../../components/ClusterInfo/ClusterInfo';
|
|
14
14
|
const b = cn('cluster');
|
15
15
|
|
16
16
|
interface ClusterProps {
|
17
|
-
additionalClusterInfo
|
18
|
-
additionalTenantsInfo
|
19
|
-
additionalNodesInfo
|
17
|
+
additionalClusterInfo?: any;
|
18
|
+
additionalTenantsInfo?: any;
|
19
|
+
additionalNodesInfo?: any;
|
20
20
|
}
|
21
21
|
|
22
22
|
function Cluster(props: ClusterProps) {
|
@@ -87,6 +87,7 @@ class Nodes extends React.Component {
|
|
87
87
|
text={searchQuery}
|
88
88
|
onUpdate={this.handleSearchQueryChange}
|
89
89
|
hasClear
|
90
|
+
autoFocus
|
90
91
|
/>
|
91
92
|
<ProblemFilter value={filter} onChange={this.handleFilterChange} />
|
92
93
|
<Label theme="info" size="m">{`Nodes: ${nodes?.length}`}</Label>
|
@@ -113,11 +114,10 @@ class Nodes extends React.Component {
|
|
113
114
|
});
|
114
115
|
|
115
116
|
let preparedNodes = searchQuery
|
116
|
-
? nodes.filter((node) =>
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
)
|
117
|
+
? nodes.filter((node) => {
|
118
|
+
const re = new RegExp(searchQuery, 'i');
|
119
|
+
return node.Host ? re.test(node.Host) || re.test(String(node.NodeId)) : true;
|
120
|
+
})
|
121
121
|
: nodes;
|
122
122
|
preparedNodes = preparedNodes.map((node) => ({
|
123
123
|
...node,
|
@@ -142,7 +142,7 @@ class Nodes extends React.Component {
|
|
142
142
|
columnId: 'NodeId',
|
143
143
|
order: DataTable.ASCENDING,
|
144
144
|
}}
|
145
|
-
emptyDataMessage=
|
145
|
+
emptyDataMessage="No such nodes"
|
146
146
|
/>
|
147
147
|
</div>
|
148
148
|
</div>
|
@@ -8,8 +8,7 @@ import type {EPathType} from '../../../../types/api/schema';
|
|
8
8
|
//@ts-ignore
|
9
9
|
import Icon from '../../../../components/Icon/Icon';
|
10
10
|
import Overview from '../Overview/Overview';
|
11
|
-
|
12
|
-
import Healthcheck from '../Healthcheck/Healthcheck';
|
11
|
+
import {Healthcheck} from '../Healthcheck';
|
13
12
|
//@ts-ignore
|
14
13
|
import TenantOverview from '../TenantOverview/TenantOverview';
|
15
14
|
|
@@ -27,11 +26,12 @@ const b = cn('kv-detailed-overview');
|
|
27
26
|
function DetailedOverview(props: DetailedOverviewProps) {
|
28
27
|
const [isModalVisible, setIsModalVisible] = useState(false);
|
29
28
|
|
30
|
-
const
|
31
|
-
|
32
|
-
} = useSelector((state: any) => state.schema);
|
29
|
+
const [expandedIssueId, setExpandedIssueId] = useState<string>();
|
30
|
+
|
31
|
+
const {currentSchemaPath} = useSelector((state: any) => state.schema);
|
33
32
|
|
34
|
-
const openModalHandler = () => {
|
33
|
+
const openModalHandler = (id: string) => {
|
34
|
+
setExpandedIssueId(id);
|
35
35
|
setIsModalVisible(true);
|
36
36
|
};
|
37
37
|
|
@@ -42,12 +42,16 @@ function DetailedOverview(props: DetailedOverviewProps) {
|
|
42
42
|
const renderModal = () => {
|
43
43
|
return (
|
44
44
|
<Modal open={isModalVisible} onClose={closeModalHandler} className={b('modal')}>
|
45
|
-
<Healthcheck
|
45
|
+
<Healthcheck
|
46
|
+
tenant={props.tenantName}
|
47
|
+
fetchData={false}
|
48
|
+
expandedIssueId={expandedIssueId}
|
49
|
+
/>
|
46
50
|
<Button
|
47
51
|
className={b('close-modal-button')}
|
48
52
|
onClick={closeModalHandler}
|
49
53
|
view="flat-secondary"
|
50
|
-
title=
|
54
|
+
title="Close"
|
51
55
|
>
|
52
56
|
<Icon name="close" viewBox={'0 0 16 16 '} height={20} width={20} />
|
53
57
|
</Button>
|
@@ -63,7 +67,10 @@ function DetailedOverview(props: DetailedOverviewProps) {
|
|
63
67
|
{isTenant ? (
|
64
68
|
<>
|
65
69
|
<div className={b('section')}>
|
66
|
-
<TenantOverview
|
70
|
+
<TenantOverview
|
71
|
+
tenantName={tenantName}
|
72
|
+
additionalTenantInfo={additionalTenantInfo}
|
73
|
+
/>
|
67
74
|
</div>
|
68
75
|
<div className={b('section')}>
|
69
76
|
<Healthcheck
|
@@ -1,8 +1,19 @@
|
|
1
1
|
@use '../DetailedOverview/DetailedOverview.scss' as detailedOverview;
|
2
2
|
@import '../../../../styles/mixins.scss';
|
3
|
+
@import '@gravity-ui/uikit/styles/mixins.scss';
|
3
4
|
|
4
5
|
.healthcheck {
|
5
|
-
|
6
|
+
// Since most of the inner containers have fixed width, we can set fixed width here as well
|
7
|
+
// Thus we will get rid of unneeded layout shift when scrollbar appear
|
8
|
+
min-width: 885px;
|
9
|
+
|
10
|
+
&__issues-list {
|
11
|
+
padding: 25px 20px 20px;
|
12
|
+
}
|
13
|
+
|
14
|
+
&__issue-preview {
|
15
|
+
margin-bottom: 15px;
|
16
|
+
}
|
6
17
|
|
7
18
|
&__issues {
|
8
19
|
overflow-x: hidden;
|
@@ -21,19 +32,21 @@
|
|
21
32
|
padding: 15px 0;
|
22
33
|
}
|
23
34
|
|
24
|
-
&
|
35
|
+
&__issues-list-header {
|
25
36
|
display: flex;
|
26
37
|
align-items: center;
|
27
38
|
|
28
39
|
margin-bottom: 20px;
|
29
40
|
}
|
30
41
|
|
31
|
-
&
|
42
|
+
&__issues-list-header-title {
|
32
43
|
margin: 0 10px 0 0;
|
44
|
+
|
45
|
+
@include text-header-1();
|
33
46
|
}
|
34
47
|
|
35
|
-
&
|
36
|
-
margin-left:
|
48
|
+
&__issues-list-header-update {
|
49
|
+
margin-left: 10px;
|
37
50
|
}
|
38
51
|
|
39
52
|
&__status-wrapper {
|
@@ -0,0 +1,83 @@
|
|
1
|
+
import {useCallback} from 'react';
|
2
|
+
import {useDispatch, useSelector} from 'react-redux';
|
3
|
+
import cn from 'bem-cn-lite';
|
4
|
+
|
5
|
+
import {Loader} from '@gravity-ui/uikit';
|
6
|
+
|
7
|
+
import {getHealthcheckInfo} from '../../../../store/reducers/healthcheckInfo';
|
8
|
+
import {useAutofetcher} from '../../../../utils/hooks';
|
9
|
+
|
10
|
+
import {IssuesList} from './IssuesList';
|
11
|
+
import {Preview} from './Preview';
|
12
|
+
|
13
|
+
import i18n from './i18n';
|
14
|
+
import './Healthcheck.scss';
|
15
|
+
|
16
|
+
interface HealthcheckProps {
|
17
|
+
tenant: string;
|
18
|
+
preview?: boolean;
|
19
|
+
fetchData?: boolean;
|
20
|
+
expandedIssueId?: string;
|
21
|
+
showMoreHandler?: (id: string) => void;
|
22
|
+
}
|
23
|
+
|
24
|
+
const b = cn('healthcheck');
|
25
|
+
|
26
|
+
export const Healthcheck = (props: HealthcheckProps) => {
|
27
|
+
const {tenant, preview, fetchData = true, showMoreHandler, expandedIssueId} = props;
|
28
|
+
|
29
|
+
const dispatch = useDispatch();
|
30
|
+
|
31
|
+
const {data, loading, wasLoaded, error} = useSelector((state: any) => state.healthcheckInfo);
|
32
|
+
const {autorefresh} = useSelector((state: any) => state.schema);
|
33
|
+
|
34
|
+
const fetchHealthcheck = useCallback(() => {
|
35
|
+
dispatch(getHealthcheckInfo(tenant));
|
36
|
+
}, [dispatch, tenant]);
|
37
|
+
|
38
|
+
useAutofetcher(
|
39
|
+
() => {
|
40
|
+
if (fetchData) {
|
41
|
+
fetchHealthcheck();
|
42
|
+
}
|
43
|
+
},
|
44
|
+
[fetchData, fetchHealthcheck],
|
45
|
+
autorefresh,
|
46
|
+
);
|
47
|
+
|
48
|
+
const renderContent = () => {
|
49
|
+
if (error) {
|
50
|
+
return error.statusText;
|
51
|
+
}
|
52
|
+
|
53
|
+
if (loading && !wasLoaded) {
|
54
|
+
return (
|
55
|
+
<div className={b('loader')}>
|
56
|
+
<Loader size="m" />
|
57
|
+
</div>
|
58
|
+
);
|
59
|
+
}
|
60
|
+
|
61
|
+
if (data && data['self_check_result']) {
|
62
|
+
return preview ? (
|
63
|
+
<Preview
|
64
|
+
data={data}
|
65
|
+
loading={loading}
|
66
|
+
onShowMore={showMoreHandler}
|
67
|
+
onUpdate={fetchHealthcheck}
|
68
|
+
/>
|
69
|
+
) : (
|
70
|
+
<IssuesList
|
71
|
+
data={data}
|
72
|
+
expandedIssueId={expandedIssueId}
|
73
|
+
loading={loading}
|
74
|
+
onUpdate={fetchHealthcheck}
|
75
|
+
/>
|
76
|
+
);
|
77
|
+
}
|
78
|
+
|
79
|
+
return <div className="error">{i18n('no-data')}</div>;
|
80
|
+
};
|
81
|
+
|
82
|
+
return <div className={b()}>{renderContent()}</div>;
|
83
|
+
};
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import cn from 'bem-cn-lite';
|
2
|
+
|
3
|
+
import {Link, Text} from '@gravity-ui/uikit';
|
4
|
+
|
5
|
+
import EntityStatus from '../../../../../components/EntityStatus/EntityStatus';
|
6
|
+
import {IssueLog} from '../../../../../types/api/healthcheck';
|
7
|
+
|
8
|
+
import i18n from '../i18n';
|
9
|
+
|
10
|
+
const b = cn('healthcheck');
|
11
|
+
|
12
|
+
interface IssuePreviewProps {
|
13
|
+
data?: IssueLog;
|
14
|
+
onShowMore?: (id: string) => void;
|
15
|
+
}
|
16
|
+
|
17
|
+
export const IssuePreview = (props: IssuePreviewProps) => {
|
18
|
+
const {data, onShowMore} = props;
|
19
|
+
|
20
|
+
if (!data) {
|
21
|
+
return null;
|
22
|
+
}
|
23
|
+
|
24
|
+
return (
|
25
|
+
<div className={b('issue-preview')}>
|
26
|
+
<EntityStatus mode="icons" status={data.status} name={data.type} />
|
27
|
+
<Text as="div" color="secondary" variant="body-2">
|
28
|
+
{data.message}
|
29
|
+
</Text>
|
30
|
+
<Link onClick={() => onShowMore && onShowMore(data.id)}>
|
31
|
+
{i18n('label.show-details')}
|
32
|
+
</Link>
|
33
|
+
</div>
|
34
|
+
);
|
35
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './IssuePreview';
|