ydb-embedded-ui 2.0.0 → 2.2.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 +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';
|