ydb-embedded-ui 4.0.0 → 4.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 +28 -0
- package/dist/components/ClusterInfo/ClusterInfo.tsx +3 -3
- package/dist/components/LabelWithPopover/LabelWithPopover.tsx +10 -4
- package/dist/{containers/Nodes/NodesTable.scss → components/NodeHostWrapper/NodeHostWrapper.scss} +4 -6
- package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +60 -0
- package/dist/components/TabletsStatistic/TabletsStatistic.scss +1 -1
- package/dist/containers/App/App.scss +7 -4
- package/dist/containers/AsideNavigation/AsideNavigation.tsx +1 -11
- package/dist/containers/Header/Header.tsx +1 -1
- package/dist/containers/Nodes/getNodesColumns.tsx +7 -46
- package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +3 -12
- package/dist/containers/Storage/StorageNodes/StorageNodes.scss +0 -24
- package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +2 -39
- package/dist/containers/Storage/VDisk/VDisk.tsx +4 -11
- package/dist/containers/Storage/VDiskPopup/VDiskPopup.tsx +13 -16
- package/dist/containers/Storage/utils/types.ts +2 -1
- package/dist/containers/Tablet/Tablet.scss +4 -0
- package/dist/containers/Tablet/TabletTable/TabletTable.tsx +28 -6
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +1 -1
- package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo.ts +4 -3
- package/dist/containers/Tenant/QueryEditor/Issues/Issues.scss +1 -1
- package/dist/containers/Tenant/QueryEditor/QueryEditorControls/OldQueryEditorControls.tsx +1 -1
- package/dist/containers/Tenant/QueryEditor/QueryEditorControls/QueryEditorControls.tsx +1 -1
- package/dist/containers/Tenant/Schema/SchemaViewer/SchemaViewer.js +12 -0
- package/dist/containers/Tenants/Tenants.js +1 -1
- package/dist/containers/UserSettings/UserSettings.tsx +19 -17
- package/dist/services/api.ts +383 -0
- package/dist/store/reducers/{cluster.js → cluster/cluster.ts} +9 -14
- package/dist/store/reducers/cluster/types.ts +13 -0
- package/dist/store/reducers/executeTopQueries.ts +2 -2
- package/dist/store/reducers/index.ts +5 -4
- package/dist/store/reducers/node.js +5 -1
- package/dist/store/reducers/nodesList.ts +2 -7
- package/dist/store/reducers/settings.js +1 -14
- package/dist/store/reducers/storage.js +12 -0
- package/dist/store/reducers/tablet.ts +16 -2
- package/dist/store/reducers/{tenants.js → tenants/tenants.ts} +14 -9
- package/dist/store/reducers/tenants/types.ts +17 -0
- package/dist/store/utils.ts +3 -2
- package/dist/types/api/acl.ts +25 -0
- package/dist/types/api/cluster.ts +3 -0
- package/dist/types/api/compute.ts +5 -3
- package/dist/types/api/netInfo.ts +48 -0
- package/dist/types/api/nodes.ts +5 -3
- package/dist/types/api/pdisk.ts +11 -2
- package/dist/types/api/storage.ts +5 -3
- package/dist/types/api/tenant.ts +18 -3
- package/dist/types/api/vdisk.ts +10 -2
- package/dist/types/api/whoami.ts +19 -0
- package/dist/types/store/tablet.ts +1 -0
- package/dist/types/window.d.ts +5 -0
- package/dist/utils/createToast.tsx +2 -2
- package/dist/utils/hooks/useTypedSelector.ts +2 -2
- package/dist/utils/nodes.ts +14 -1
- package/package.json +4 -4
- package/dist/services/api.d.ts +0 -87
- package/dist/services/api.js +0 -278
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,33 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [4.2.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.1.0...v4.2.0) (2023-05-16)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* **Tablet:** display node fqdn in table ([4d8099a](https://github.com/ydb-platform/ydb-embedded-ui/commit/4d8099a454f34fc76886b26ca948895171c57ab8))
|
9
|
+
|
10
|
+
|
11
|
+
### Bug Fixes
|
12
|
+
|
13
|
+
* **api:** change nulls to empty objects ([0ab14e8](https://github.com/ydb-platform/ydb-embedded-ui/commit/0ab14e883a47aeac2f2bab437f2214a32ccb1c9b))
|
14
|
+
* display storage pool in VDisks popups ([5b5dd8a](https://github.com/ydb-platform/ydb-embedded-ui/commit/5b5dd8a4e6cb4bcc1ead78a7c06d2e80a81424cc))
|
15
|
+
* fix Select label and values align ([f796730](https://github.com/ydb-platform/ydb-embedded-ui/commit/f7967309fe4a042e7637de212f33b1ebfc6877fc))
|
16
|
+
* **Overview:** partitioning by size disabled for 0 SizeToSpit ([1028e7d](https://github.com/ydb-platform/ydb-embedded-ui/commit/1028e7d8d3566f5f5e6b2ebe04112ef135d7b55e))
|
17
|
+
* **Schema:** display NotNull columns ([d61eaa4](https://github.com/ydb-platform/ydb-embedded-ui/commit/d61eaa4ccff357c1e9ca6efde855ec46be24a314))
|
18
|
+
|
19
|
+
## [4.1.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.0.0...v4.1.0) (2023-05-10)
|
20
|
+
|
21
|
+
|
22
|
+
### Features
|
23
|
+
|
24
|
+
* **Navigation:** remove legacy navigation setting support ([8544f11](https://github.com/ydb-platform/ydb-embedded-ui/commit/8544f114255ba44834d38cd9e709450c49e4a96a))
|
25
|
+
|
26
|
+
|
27
|
+
### Bug Fixes
|
28
|
+
|
29
|
+
* disable link and popover for unavailable nodes ([990a9fa](https://github.com/ydb-platform/ydb-embedded-ui/commit/990a9fa42a7133a6c40d07e11c3518240e18b4a9))
|
30
|
+
|
3
31
|
## [4.0.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v3.5.0...v4.0.0) (2023-04-28)
|
4
32
|
|
5
33
|
|
@@ -15,7 +15,7 @@ import {Tablet} from '../Tablet';
|
|
15
15
|
//@ts-ignore
|
16
16
|
import {hideTooltip, showTooltip} from '../../store/reducers/tooltip';
|
17
17
|
//@ts-ignore
|
18
|
-
import {getClusterInfo} from '../../store/reducers/cluster';
|
18
|
+
import {getClusterInfo} from '../../store/reducers/cluster/cluster';
|
19
19
|
//@ts-ignore
|
20
20
|
import {clusterName, backend, customBackend} from '../../store';
|
21
21
|
|
@@ -68,6 +68,8 @@ class ClusterInfo extends React.Component<ClusterInfoProps> {
|
|
68
68
|
return 0;
|
69
69
|
}
|
70
70
|
|
71
|
+
private autofetcher: any;
|
72
|
+
|
71
73
|
componentDidMount() {
|
72
74
|
const {setHeader} = this.props;
|
73
75
|
setHeader([
|
@@ -107,8 +109,6 @@ class ClusterInfo extends React.Component<ClusterInfoProps> {
|
|
107
109
|
return <div className={b(null, className)}>{helper || this.renderContent()}</div>;
|
108
110
|
}
|
109
111
|
|
110
|
-
private autofetcher: any;
|
111
|
-
|
112
112
|
private getInfo() {
|
113
113
|
const {cluster = {}, additionalClusterInfo = [], singleClusterMode} = this.props;
|
114
114
|
const {StorageTotal, StorageUsed} = cluster;
|
@@ -3,14 +3,20 @@ import type {ReactNode} from 'react';
|
|
3
3
|
import {HelpPopover} from '@gravity-ui/uikit';
|
4
4
|
|
5
5
|
interface LabelWithPopoverProps {
|
6
|
-
text:
|
6
|
+
text: ReactNode;
|
7
7
|
popoverContent: ReactNode;
|
8
8
|
className?: string;
|
9
|
+
contentClassName?: string;
|
9
10
|
}
|
10
11
|
|
11
|
-
export const LabelWithPopover = ({
|
12
|
+
export const LabelWithPopover = ({
|
13
|
+
text,
|
14
|
+
popoverContent,
|
15
|
+
className,
|
16
|
+
contentClassName,
|
17
|
+
}: LabelWithPopoverProps) => (
|
12
18
|
<div className={className}>
|
13
|
-
{text}
|
14
|
-
<HelpPopover content={popoverContent} />
|
19
|
+
{text + '\u00a0'}
|
20
|
+
<HelpPopover content={popoverContent} contentClassName={contentClassName} />
|
15
21
|
</div>
|
16
22
|
);
|
package/dist/{containers/Nodes/NodesTable.scss → components/NodeHostWrapper/NodeHostWrapper.scss}
RENAMED
@@ -1,12 +1,10 @@
|
|
1
|
-
.ydb-
|
2
|
-
|
3
|
-
display: flex;
|
4
|
-
}
|
1
|
+
.ydb-node-host-wrapper {
|
2
|
+
display: flex;
|
5
3
|
|
6
4
|
&__host-wrapper {
|
7
5
|
display: flex;
|
8
6
|
|
9
|
-
|
7
|
+
width: 330px;
|
10
8
|
}
|
11
9
|
|
12
10
|
&__host {
|
@@ -21,7 +19,7 @@
|
|
21
19
|
}
|
22
20
|
|
23
21
|
.data-table__row:hover {
|
24
|
-
.ydb-
|
22
|
+
.ydb-node-host-wrapper__external-button {
|
25
23
|
display: inline-flex;
|
26
24
|
}
|
27
25
|
}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import block from 'bem-cn-lite';
|
2
|
+
|
3
|
+
import {Button, Popover, PopoverBehavior} from '@gravity-ui/uikit';
|
4
|
+
|
5
|
+
import type {INodesPreparedEntity} from '../../types/store/nodes';
|
6
|
+
import {getDefaultNodePath} from '../../containers/Node/NodePages';
|
7
|
+
import {isUnavailableNode, NodeAddress} from '../../utils/nodes';
|
8
|
+
|
9
|
+
import EntityStatus from '../EntityStatus/EntityStatus';
|
10
|
+
import {NodeEndpointsTooltip} from '../Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip';
|
11
|
+
import {IconWrapper} from '../Icon';
|
12
|
+
|
13
|
+
import './NodeHostWrapper.scss';
|
14
|
+
|
15
|
+
const b = block('ydb-node-host-wrapper');
|
16
|
+
|
17
|
+
interface NodeHostWrapperProps {
|
18
|
+
node: INodesPreparedEntity;
|
19
|
+
getNodeRef?: (node?: NodeAddress) => string;
|
20
|
+
}
|
21
|
+
|
22
|
+
export const NodeHostWrapper = ({node, getNodeRef}: NodeHostWrapperProps) => {
|
23
|
+
if (!node.Host) {
|
24
|
+
return <span>—</span>;
|
25
|
+
}
|
26
|
+
|
27
|
+
const isNodeAvailable = !isUnavailableNode(node);
|
28
|
+
const nodeRef = isNodeAvailable && getNodeRef ? getNodeRef(node) + 'internal' : undefined;
|
29
|
+
|
30
|
+
return (
|
31
|
+
<div className={b()}>
|
32
|
+
<Popover
|
33
|
+
disabled={!isNodeAvailable}
|
34
|
+
content={<NodeEndpointsTooltip data={node} />}
|
35
|
+
placement={['top', 'bottom']}
|
36
|
+
behavior={PopoverBehavior.Immediate}
|
37
|
+
>
|
38
|
+
<div className={b('host-wrapper')}>
|
39
|
+
<EntityStatus
|
40
|
+
name={node.Host}
|
41
|
+
status={node.SystemState}
|
42
|
+
path={isNodeAvailable ? getDefaultNodePath(node.NodeId) : undefined}
|
43
|
+
hasClipboardButton
|
44
|
+
className={b('host')}
|
45
|
+
/>
|
46
|
+
{nodeRef && (
|
47
|
+
<Button
|
48
|
+
size="s"
|
49
|
+
href={nodeRef}
|
50
|
+
className={b('external-button')}
|
51
|
+
target="_blank"
|
52
|
+
>
|
53
|
+
<IconWrapper name="external" />
|
54
|
+
</Button>
|
55
|
+
)}
|
56
|
+
</div>
|
57
|
+
</Popover>
|
58
|
+
</div>
|
59
|
+
);
|
60
|
+
};
|
@@ -34,10 +34,6 @@ body,
|
|
34
34
|
--ydb-data-table-color-hover: var(--yc-color-base-float-hover);
|
35
35
|
}
|
36
36
|
|
37
|
-
.yc-select__label {
|
38
|
-
font-weight: 600;
|
39
|
-
}
|
40
|
-
|
41
37
|
:is(#tab, .yc-tabs-item_active .yc-tabs-item__title) {
|
42
38
|
color: var(--yc-color-text-primary) !important;
|
43
39
|
}
|
@@ -110,10 +106,17 @@ body,
|
|
110
106
|
align-items: center;
|
111
107
|
}
|
112
108
|
|
109
|
+
// Should be removed after https://github.com/ydb-platform/ydb-embedded-ui/issues/344
|
113
110
|
.yc-button__text {
|
114
111
|
display: flex;
|
115
112
|
align-items: center;
|
116
113
|
}
|
114
|
+
|
115
|
+
.g-select {
|
116
|
+
.yc-button__text {
|
117
|
+
align-items: baseline;
|
118
|
+
}
|
119
|
+
}
|
117
120
|
}
|
118
121
|
|
119
122
|
.error {
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import React, {
|
1
|
+
import React, {useState} from 'react';
|
2
2
|
import {connect} from 'react-redux';
|
3
3
|
import {useLocation} from 'react-router';
|
4
4
|
import {useHistory} from 'react-router-dom';
|
@@ -170,16 +170,6 @@ function AsideNavigation(props: AsideNavigationProps) {
|
|
170
170
|
props.setSettingValue(ASIDE_HEADER_COMPACT_KEY, JSON.stringify(compact));
|
171
171
|
};
|
172
172
|
|
173
|
-
// navigation managed its compact state internally before, and its approach is not compatible with settings
|
174
|
-
// to migrate, save the incoming value again; save only `false` because `true` is the default value
|
175
|
-
// assume it is safe to remove this code block if it is at least a few months old
|
176
|
-
// there a two of these, search for a similar comment
|
177
|
-
useEffect(() => {
|
178
|
-
if (props.compact === false) {
|
179
|
-
setIsCompact(props.compact);
|
180
|
-
}
|
181
|
-
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
182
|
-
|
183
173
|
const menuItems: AsideHeaderMenuItem[] = React.useMemo(() => {
|
184
174
|
const {pathname} = location;
|
185
175
|
const isClusterPage = pathname === '/cluster';
|
@@ -8,7 +8,7 @@ import Divider from '../../components/Divider/Divider';
|
|
8
8
|
import {Icon} from '../../components/Icon';
|
9
9
|
|
10
10
|
import {clusterName as clusterNameLocation, backend, customBackend} from '../../store';
|
11
|
-
import {getClusterInfo} from '../../store/reducers/cluster';
|
11
|
+
import {getClusterInfo} from '../../store/reducers/cluster/cluster';
|
12
12
|
import {getHostInfo} from '../../store/reducers/host';
|
13
13
|
import {HeaderItemType} from '../../store/reducers/header';
|
14
14
|
|
@@ -1,29 +1,22 @@
|
|
1
|
-
import cn from 'bem-cn-lite';
|
2
1
|
import DataTable, {Column} from '@gravity-ui/react-data-table';
|
3
|
-
import {
|
2
|
+
import {Popover} from '@gravity-ui/uikit';
|
4
3
|
|
5
|
-
import {IconWrapper} from '../../components/Icon';
|
6
|
-
import EntityStatus from '../../components/EntityStatus/EntityStatus';
|
7
4
|
import PoolsGraph from '../../components/PoolsGraph/PoolsGraph';
|
8
5
|
import ProgressViewer from '../../components/ProgressViewer/ProgressViewer';
|
9
6
|
import {TabletsStatistic} from '../../components/TabletsStatistic';
|
10
|
-
import {
|
7
|
+
import {NodeHostWrapper} from '../../components/NodeHostWrapper/NodeHostWrapper';
|
11
8
|
|
9
|
+
import type {NodeAddress} from '../../utils/nodes';
|
12
10
|
import {formatBytesToGigabyte} from '../../utils/index';
|
13
|
-
import {INodesPreparedEntity} from '../../types/store/nodes';
|
14
|
-
import {showTooltip as externalShowTooltip} from '../../store/reducers/tooltip';
|
15
|
-
|
16
|
-
import {getDefaultNodePath} from '../Node/NodePages';
|
17
|
-
|
18
|
-
import './NodesTable.scss';
|
19
11
|
|
20
|
-
|
12
|
+
import type {INodesPreparedEntity} from '../../types/store/nodes';
|
13
|
+
import {showTooltip as externalShowTooltip} from '../../store/reducers/tooltip';
|
21
14
|
|
22
15
|
interface GetNodesColumnsProps {
|
23
16
|
showTooltip: (...args: Parameters<typeof externalShowTooltip>) => void;
|
24
17
|
hideTooltip: VoidFunction;
|
25
18
|
tabletsPath?: string;
|
26
|
-
getNodeRef?:
|
19
|
+
getNodeRef?: (node?: NodeAddress) => string;
|
27
20
|
}
|
28
21
|
|
29
22
|
export function getNodesColumns({
|
@@ -42,39 +35,7 @@ export function getNodesColumns({
|
|
42
35
|
{
|
43
36
|
name: 'Host',
|
44
37
|
render: ({row}) => {
|
45
|
-
|
46
|
-
if (typeof row.Host === 'undefined') {
|
47
|
-
return <span>—</span>;
|
48
|
-
}
|
49
|
-
return (
|
50
|
-
<div className={b('host-field-wrapper')}>
|
51
|
-
<Popover
|
52
|
-
content={<NodeEndpointsTooltip data={row} />}
|
53
|
-
placement={['top', 'bottom']}
|
54
|
-
behavior={PopoverBehavior.Immediate}
|
55
|
-
>
|
56
|
-
<div className={b('host-wrapper')}>
|
57
|
-
<EntityStatus
|
58
|
-
name={row.Host}
|
59
|
-
status={row.SystemState}
|
60
|
-
path={getDefaultNodePath(row.NodeId)}
|
61
|
-
hasClipboardButton
|
62
|
-
className={b('host')}
|
63
|
-
/>
|
64
|
-
{nodeRef && (
|
65
|
-
<Button
|
66
|
-
size="s"
|
67
|
-
href={nodeRef}
|
68
|
-
className={b('external-button')}
|
69
|
-
target="_blank"
|
70
|
-
>
|
71
|
-
<IconWrapper name="external" />
|
72
|
-
</Button>
|
73
|
-
)}
|
74
|
-
</div>
|
75
|
-
</Popover>
|
76
|
-
</div>
|
77
|
-
);
|
38
|
+
return <NodeHostWrapper node={row} getNodeRef={getNodeRef} />;
|
78
39
|
},
|
79
40
|
width: '350px',
|
80
41
|
align: DataTable.LEFT,
|
@@ -256,18 +256,14 @@ function StorageGroups({
|
|
256
256
|
name: TableColumnsIds.VDisks,
|
257
257
|
className: b('vdisks-column'),
|
258
258
|
header: tableColumnsNames[TableColumnsIds.VDisks],
|
259
|
-
render: ({value
|
259
|
+
render: ({value}) => (
|
260
260
|
<div className={b('vdisks-wrapper')}>
|
261
261
|
{_.map(value as TVDiskStateInfo[], (el) => {
|
262
262
|
const donors = el.Donors;
|
263
263
|
|
264
264
|
return donors && donors.length > 0 ? (
|
265
265
|
<Stack className={b('vdisks-item')} key={stringifyVdiskId(el.VDiskId)}>
|
266
|
-
<VDisk
|
267
|
-
data={el}
|
268
|
-
poolName={row[TableColumnsIds.PoolName]}
|
269
|
-
nodes={nodes}
|
270
|
-
/>
|
266
|
+
<VDisk data={el} nodes={nodes} />
|
271
267
|
{donors.map((donor) => {
|
272
268
|
const isFullData = isFullVDiskData(donor);
|
273
269
|
|
@@ -275,7 +271,6 @@ function StorageGroups({
|
|
275
271
|
<VDisk
|
276
272
|
data={isFullData ? donor : {...donor, DonorMode: true}}
|
277
273
|
// donor and acceptor are always in the same group
|
278
|
-
poolName={row[TableColumnsIds.PoolName]}
|
279
274
|
nodes={nodes}
|
280
275
|
key={stringifyVdiskId(
|
281
276
|
isFullData ? donor.VDiskId : donor,
|
@@ -286,11 +281,7 @@ function StorageGroups({
|
|
286
281
|
</Stack>
|
287
282
|
) : (
|
288
283
|
<div className={b('vdisks-item')} key={stringifyVdiskId(el.VDiskId)}>
|
289
|
-
<VDisk
|
290
|
-
data={el}
|
291
|
-
poolName={row[TableColumnsIds.PoolName]}
|
292
|
-
nodes={nodes}
|
293
|
-
/>
|
284
|
+
<VDisk data={el} nodes={nodes} />
|
294
285
|
</div>
|
295
286
|
);
|
296
287
|
})}
|
@@ -20,18 +20,6 @@
|
|
20
20
|
margin-right: 0px;
|
21
21
|
}
|
22
22
|
}
|
23
|
-
&__fqdn-field-wrapper {
|
24
|
-
width: 330px;
|
25
|
-
}
|
26
|
-
&__fqdn-wrapper {
|
27
|
-
display: flex;
|
28
|
-
align-items: center;
|
29
|
-
|
30
|
-
max-width: 330px;
|
31
|
-
}
|
32
|
-
&__fqdn {
|
33
|
-
overflow: hidden;
|
34
|
-
}
|
35
23
|
|
36
24
|
&__group-id {
|
37
25
|
font-weight: 500;
|
@@ -40,16 +28,4 @@
|
|
40
28
|
&__node_unavailable {
|
41
29
|
opacity: 0.6;
|
42
30
|
}
|
43
|
-
|
44
|
-
&__external-button {
|
45
|
-
display: none;
|
46
|
-
|
47
|
-
margin-left: 4px;
|
48
|
-
}
|
49
|
-
}
|
50
|
-
|
51
|
-
.data-table__row:hover {
|
52
|
-
.global-storage-nodes__external-button {
|
53
|
-
display: inline-flex;
|
54
|
-
}
|
55
31
|
}
|
@@ -2,11 +2,6 @@ import _ from 'lodash';
|
|
2
2
|
import cn from 'bem-cn-lite';
|
3
3
|
|
4
4
|
import DataTable, {Column, Settings, SortOrder} from '@gravity-ui/react-data-table';
|
5
|
-
import {Button, Popover, PopoverBehavior} from '@gravity-ui/uikit';
|
6
|
-
|
7
|
-
import {NodeEndpointsTooltip} from '../../../components/Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip';
|
8
|
-
import EntityStatus from '../../../components/EntityStatus/EntityStatus';
|
9
|
-
import {IconWrapper} from '../../../components/Icon';
|
10
5
|
|
11
6
|
import {VisibleEntities} from '../../../store/reducers/storage';
|
12
7
|
import {
|
@@ -15,7 +10,7 @@ import {
|
|
15
10
|
NodesUptimeFilterValues,
|
16
11
|
} from '../../../utils/nodes';
|
17
12
|
|
18
|
-
import {
|
13
|
+
import {NodeHostWrapper} from '../../../components/NodeHostWrapper/NodeHostWrapper';
|
19
14
|
|
20
15
|
import {EmptyFilter} from '../EmptyFilter/EmptyFilter';
|
21
16
|
import {PDisk} from '../PDisk';
|
@@ -100,39 +95,7 @@ function StorageNodes({
|
|
100
95
|
header: tableColumnsNames[TableColumnsIds.FQDN],
|
101
96
|
width: 350,
|
102
97
|
render: ({row}) => {
|
103
|
-
|
104
|
-
if (!row.Host) {
|
105
|
-
return <span>—</span>;
|
106
|
-
}
|
107
|
-
return (
|
108
|
-
<div className={b('fqdn-field-wrapper')}>
|
109
|
-
<Popover
|
110
|
-
content={<NodeEndpointsTooltip data={row} />}
|
111
|
-
placement={['top', 'bottom']}
|
112
|
-
behavior={PopoverBehavior.Immediate}
|
113
|
-
>
|
114
|
-
<div className={b('fqdn-wrapper')}>
|
115
|
-
<EntityStatus
|
116
|
-
name={row.Host}
|
117
|
-
showStatus={false}
|
118
|
-
path={getDefaultNodePath(row.NodeId)}
|
119
|
-
hasClipboardButton
|
120
|
-
className={b('fqdn')}
|
121
|
-
/>
|
122
|
-
{nodeRef && (
|
123
|
-
<Button
|
124
|
-
size="s"
|
125
|
-
href={nodeRef}
|
126
|
-
className={b('external-button')}
|
127
|
-
target="_blank"
|
128
|
-
>
|
129
|
-
<IconWrapper name="external" />
|
130
|
-
</Button>
|
131
|
-
)}
|
132
|
-
</div>
|
133
|
-
</Popover>
|
134
|
-
</div>
|
135
|
-
);
|
98
|
+
return <NodeHostWrapper node={row} getNodeRef={getNodeRef} />;
|
136
99
|
},
|
137
100
|
align: DataTable.LEFT,
|
138
101
|
},
|
@@ -16,7 +16,7 @@ import {STRUCTURE} from '../../Node/NodePages';
|
|
16
16
|
import {DiskStateProgressBar, EDiskStateSeverity} from '../DiskStateProgressBar';
|
17
17
|
import {VDiskPopup} from '../VDiskPopup';
|
18
18
|
|
19
|
-
import type {
|
19
|
+
import type {UnavailableDonor} from '../utils/types';
|
20
20
|
import {NOT_AVAILABLE_SEVERITY} from '../utils';
|
21
21
|
|
22
22
|
import './VDisk.scss';
|
@@ -49,13 +49,12 @@ const getColorSeverity = (color?: EFlag) => {
|
|
49
49
|
};
|
50
50
|
|
51
51
|
interface VDiskProps {
|
52
|
-
data?: TVDiskStateInfo |
|
53
|
-
poolName?: string;
|
52
|
+
data?: TVDiskStateInfo | UnavailableDonor;
|
54
53
|
nodes?: NodesMap;
|
55
54
|
compact?: boolean;
|
56
55
|
}
|
57
56
|
|
58
|
-
export const VDisk = ({data = {},
|
57
|
+
export const VDisk = ({data = {}, nodes, compact}: VDiskProps) => {
|
59
58
|
const isFullData = isFullVDiskData(data);
|
60
59
|
|
61
60
|
const [severity, setSeverity] = useState(
|
@@ -125,13 +124,7 @@ export const VDisk = ({data = {}, poolName, nodes, compact}: VDiskProps) => {
|
|
125
124
|
|
126
125
|
return (
|
127
126
|
<React.Fragment>
|
128
|
-
<VDiskPopup
|
129
|
-
data={data}
|
130
|
-
poolName={poolName}
|
131
|
-
nodes={nodes}
|
132
|
-
anchorRef={anchor}
|
133
|
-
open={isPopupVisible}
|
134
|
-
/>
|
127
|
+
<VDiskPopup data={data} nodes={nodes} anchorRef={anchor} open={isPopupVisible} />
|
135
128
|
<div className={b()} ref={anchor} onMouseEnter={showPopup} onMouseLeave={hidePopup}>
|
136
129
|
{data.NodeId && isFullData ? (
|
137
130
|
<InternalLink
|
@@ -13,7 +13,7 @@ import {stringifyVdiskId} from '../../../utils';
|
|
13
13
|
import {bytesToGB, bytesToSpeed} from '../../../utils/utils';
|
14
14
|
import {isFullVDiskData} from '../../../utils/storage';
|
15
15
|
|
16
|
-
import type {
|
16
|
+
import type {UnavailableDonor} from '../utils/types';
|
17
17
|
|
18
18
|
import {preparePDiskData} from '../PDiskPopup';
|
19
19
|
|
@@ -21,13 +21,13 @@ import './VDiskPopup.scss';
|
|
21
21
|
|
22
22
|
const b = cn('vdisk-storage-popup');
|
23
23
|
|
24
|
-
const prepareUnavailableVDiskData = (data:
|
25
|
-
const {NodeId, PDiskId, VSlotId} = data;
|
24
|
+
const prepareUnavailableVDiskData = (data: UnavailableDonor) => {
|
25
|
+
const {NodeId, PDiskId, VSlotId, StoragePoolName} = data;
|
26
26
|
|
27
27
|
const vdiskData: InfoViewerItem[] = [{label: 'State', value: 'not available'}];
|
28
28
|
|
29
|
-
if (
|
30
|
-
vdiskData.push({label: 'StoragePool', value:
|
29
|
+
if (StoragePoolName) {
|
30
|
+
vdiskData.push({label: 'StoragePool', value: StoragePoolName});
|
31
31
|
}
|
32
32
|
|
33
33
|
vdiskData.push(
|
@@ -39,7 +39,7 @@ const prepareUnavailableVDiskData = (data: IUnavailableDonor, poolName?: string)
|
|
39
39
|
return vdiskData;
|
40
40
|
};
|
41
41
|
|
42
|
-
const prepareVDiskData = (data: TVDiskStateInfo
|
42
|
+
const prepareVDiskData = (data: TVDiskStateInfo) => {
|
43
43
|
const {
|
44
44
|
VDiskId,
|
45
45
|
VDiskState,
|
@@ -51,6 +51,7 @@ const prepareVDiskData = (data: TVDiskStateInfo, poolName?: string) => {
|
|
51
51
|
AllocatedSize,
|
52
52
|
ReadThroughput,
|
53
53
|
WriteThroughput,
|
54
|
+
StoragePoolName,
|
54
55
|
} = data;
|
55
56
|
|
56
57
|
const vdiskData: InfoViewerItem[] = [
|
@@ -58,8 +59,8 @@ const prepareVDiskData = (data: TVDiskStateInfo, poolName?: string) => {
|
|
58
59
|
{label: 'State', value: VDiskState ?? 'not available'},
|
59
60
|
];
|
60
61
|
|
61
|
-
if (
|
62
|
-
vdiskData.push({label: 'StoragePool', value:
|
62
|
+
if (StoragePoolName) {
|
63
|
+
vdiskData.push({label: 'StoragePool', value: StoragePoolName});
|
63
64
|
}
|
64
65
|
|
65
66
|
if (SatisfactionRank && SatisfactionRank.FreshRank?.Flag !== EFlag.Green) {
|
@@ -128,20 +129,16 @@ const prepareVDiskData = (data: TVDiskStateInfo, poolName?: string) => {
|
|
128
129
|
};
|
129
130
|
|
130
131
|
interface VDiskPopupProps extends PopupProps {
|
131
|
-
data: TVDiskStateInfo |
|
132
|
-
poolName?: string;
|
132
|
+
data: TVDiskStateInfo | UnavailableDonor;
|
133
133
|
nodes?: NodesMap;
|
134
134
|
}
|
135
135
|
|
136
|
-
export const VDiskPopup = ({data,
|
136
|
+
export const VDiskPopup = ({data, nodes, ...props}: VDiskPopupProps) => {
|
137
137
|
const isFullData = isFullVDiskData(data);
|
138
138
|
|
139
139
|
const vdiskInfo = useMemo(
|
140
|
-
() =>
|
141
|
-
|
142
|
-
? prepareVDiskData(data, poolName)
|
143
|
-
: prepareUnavailableVDiskData(data, poolName),
|
144
|
-
[data, poolName, isFullData],
|
140
|
+
() => (isFullData ? prepareVDiskData(data) : prepareUnavailableVDiskData(data)),
|
141
|
+
[data, isFullData],
|
145
142
|
);
|
146
143
|
const pdiskInfo = useMemo(
|
147
144
|
() => isFullData && data.PDisk && preparePDiskData(data.PDisk, nodes),
|
@@ -1,7 +1,13 @@
|
|
1
1
|
import DataTable, {Column} from '@gravity-ui/react-data-table';
|
2
2
|
|
3
|
+
import EntityStatus from '../../../components/EntityStatus/EntityStatus';
|
4
|
+
import {InternalLink} from '../../../components/InternalLink/InternalLink';
|
5
|
+
|
3
6
|
import type {ITabletPreparedHistoryItem} from '../../../types/store/tablet';
|
4
7
|
import {calcUptime} from '../../../utils';
|
8
|
+
import {getDefaultNodePath} from '../../Node/NodePages';
|
9
|
+
|
10
|
+
import {b} from '../Tablet';
|
5
11
|
|
6
12
|
const columns: Column<ITabletPreparedHistoryItem>[] = [
|
7
13
|
{
|
@@ -9,12 +15,6 @@ const columns: Column<ITabletPreparedHistoryItem>[] = [
|
|
9
15
|
align: DataTable.RIGHT,
|
10
16
|
render: ({row}) => row.generation,
|
11
17
|
},
|
12
|
-
{
|
13
|
-
name: 'Node ID',
|
14
|
-
align: DataTable.RIGHT,
|
15
|
-
sortable: false,
|
16
|
-
render: ({row}) => row.nodeId,
|
17
|
-
},
|
18
18
|
{
|
19
19
|
name: 'Change time',
|
20
20
|
align: DataTable.RIGHT,
|
@@ -33,6 +33,28 @@ const columns: Column<ITabletPreparedHistoryItem>[] = [
|
|
33
33
|
return row.leader ? 'leader' : row.followerId;
|
34
34
|
},
|
35
35
|
},
|
36
|
+
{
|
37
|
+
name: 'Node ID',
|
38
|
+
align: DataTable.RIGHT,
|
39
|
+
sortable: false,
|
40
|
+
render: ({row}) => {
|
41
|
+
return <InternalLink to={getDefaultNodePath(row.nodeId)}>{row.nodeId}</InternalLink>;
|
42
|
+
},
|
43
|
+
},
|
44
|
+
{
|
45
|
+
name: 'Node FQDN',
|
46
|
+
sortable: false,
|
47
|
+
render: ({row}) => {
|
48
|
+
if (!row.fqdn) {
|
49
|
+
return <span>—</span>;
|
50
|
+
}
|
51
|
+
return (
|
52
|
+
<div className={b('host')}>
|
53
|
+
<EntityStatus name={row.fqdn} showStatus={false} hasClipboardButton />
|
54
|
+
</div>
|
55
|
+
);
|
56
|
+
},
|
57
|
+
},
|
36
58
|
];
|
37
59
|
|
38
60
|
const TABLE_SETTINGS = {
|