ydb-embedded-ui 4.1.0 → 4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/components/LabelWithPopover/LabelWithPopover.tsx +10 -4
- package/dist/components/TabletsStatistic/TabletsStatistic.scss +1 -1
- package/dist/containers/App/App.scss +7 -4
- package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +3 -12
- 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/UserSettings/UserSettings.tsx +19 -17
- package/dist/services/api.ts +9 -9
- package/dist/store/reducers/node.js +5 -1
- package/dist/store/reducers/nodesList.ts +2 -7
- package/dist/store/reducers/storage.js +12 -0
- package/dist/store/reducers/tablet.ts +16 -2
- package/dist/types/store/tablet.ts +1 -0
- package/dist/utils/createToast.tsx +3 -3
- package/dist/utils/nodes.ts +11 -0
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,28 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [4.2.1](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.2.0...v4.2.1) (2023-05-18)
|
4
|
+
|
5
|
+
|
6
|
+
### Bug Fixes
|
7
|
+
|
8
|
+
* export toaster ([b5d12c0](https://github.com/ydb-platform/ydb-embedded-ui/commit/b5d12c0aa39ea3877a9b74071e3124f89a309ca3))
|
9
|
+
|
10
|
+
## [4.2.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.1.0...v4.2.0) (2023-05-16)
|
11
|
+
|
12
|
+
|
13
|
+
### Features
|
14
|
+
|
15
|
+
* **Tablet:** display node fqdn in table ([4d8099a](https://github.com/ydb-platform/ydb-embedded-ui/commit/4d8099a454f34fc76886b26ca948895171c57ab8))
|
16
|
+
|
17
|
+
|
18
|
+
### Bug Fixes
|
19
|
+
|
20
|
+
* **api:** change nulls to empty objects ([0ab14e8](https://github.com/ydb-platform/ydb-embedded-ui/commit/0ab14e883a47aeac2f2bab437f2214a32ccb1c9b))
|
21
|
+
* display storage pool in VDisks popups ([5b5dd8a](https://github.com/ydb-platform/ydb-embedded-ui/commit/5b5dd8a4e6cb4bcc1ead78a7c06d2e80a81424cc))
|
22
|
+
* fix Select label and values align ([f796730](https://github.com/ydb-platform/ydb-embedded-ui/commit/f7967309fe4a042e7637de212f33b1ebfc6877fc))
|
23
|
+
* **Overview:** partitioning by size disabled for 0 SizeToSpit ([1028e7d](https://github.com/ydb-platform/ydb-embedded-ui/commit/1028e7d8d3566f5f5e6b2ebe04112ef135d7b55e))
|
24
|
+
* **Schema:** display NotNull columns ([d61eaa4](https://github.com/ydb-platform/ydb-embedded-ui/commit/d61eaa4ccff357c1e9ca6efde855ec46be24a314))
|
25
|
+
|
3
26
|
## [4.1.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.0.0...v4.1.0) (2023-05-10)
|
4
27
|
|
5
28
|
|
@@ -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
|
);
|
@@ -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 {
|
@@ -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
|
})}
|
@@ -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 = {
|
@@ -86,9 +86,10 @@ const prepareTableGeneralInfo = (PartitionConfig: TPartitionConfig, TTLSettings?
|
|
86
86
|
|
87
87
|
const generalTableInfo: InfoViewerItem[] = [];
|
88
88
|
|
89
|
-
const partitioningBySize =
|
90
|
-
|
91
|
-
|
89
|
+
const partitioningBySize =
|
90
|
+
PartitioningPolicy.SizeToSplit && Number(PartitioningPolicy.SizeToSplit) > 0
|
91
|
+
? `Enabled, split size: ${formatBytes(PartitioningPolicy.SizeToSplit)}`
|
92
|
+
: 'Disabled';
|
92
93
|
|
93
94
|
const partitioningByLoad = PartitioningPolicy.SplitByLoadSettings?.Enabled
|
94
95
|
? 'Enabled'
|
@@ -61,7 +61,7 @@ export const QueryEditorControls = ({
|
|
61
61
|
</Button>
|
62
62
|
<DropdownMenu
|
63
63
|
items={querySelectorMenuItems}
|
64
|
-
|
64
|
+
popupProps={{className: b('mode-selector__popup')}}
|
65
65
|
switcher={
|
66
66
|
<Button className={b('mode-selector__button')}>
|
67
67
|
<span className={b('mode-selector__button-content')}>
|
@@ -16,6 +16,7 @@ const SchemaViewerColumns = {
|
|
16
16
|
name: 'Name',
|
17
17
|
key: 'Key',
|
18
18
|
type: 'Type',
|
19
|
+
notNull: 'NotNull',
|
19
20
|
};
|
20
21
|
|
21
22
|
class SchemaViewer extends React.Component {
|
@@ -59,6 +60,17 @@ class SchemaViewer extends React.Component {
|
|
59
60
|
name: SchemaViewerColumns.type,
|
60
61
|
width: 100,
|
61
62
|
},
|
63
|
+
{
|
64
|
+
name: SchemaViewerColumns.notNull,
|
65
|
+
width: 100,
|
66
|
+
render: ({row}) => {
|
67
|
+
if (row.NotNull) {
|
68
|
+
return '\u2713';
|
69
|
+
}
|
70
|
+
|
71
|
+
return undefined;
|
72
|
+
},
|
73
|
+
},
|
62
74
|
];
|
63
75
|
|
64
76
|
const tableData = [...keyColumns, ...restColumns];
|
@@ -2,12 +2,14 @@ import {ReactNode} from 'react';
|
|
2
2
|
import {connect} from 'react-redux';
|
3
3
|
import cn from 'bem-cn-lite';
|
4
4
|
|
5
|
-
import {RadioButton, Switch
|
5
|
+
import {RadioButton, Switch} from '@gravity-ui/uikit';
|
6
6
|
import {Settings} from '@gravity-ui/navigation';
|
7
7
|
|
8
8
|
import favoriteFilledIcon from '../../assets/icons/star.svg';
|
9
9
|
import flaskIcon from '../../assets/icons/flask.svg';
|
10
10
|
|
11
|
+
import {LabelWithPopover} from '../../components/LabelWithPopover/LabelWithPopover';
|
12
|
+
|
11
13
|
import {
|
12
14
|
ENABLE_QUERY_MODES_FOR_EXPLAIN,
|
13
15
|
INVERTED_DISKS_KEY,
|
@@ -46,27 +48,27 @@ function UserSettings(props: any) {
|
|
46
48
|
|
47
49
|
const renderBreakNodesSettingsItem = (title: ReactNode) => {
|
48
50
|
return (
|
49
|
-
<
|
50
|
-
{
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
51
|
+
<LabelWithPopover
|
52
|
+
className={b('item-with-popup')}
|
53
|
+
contentClassName={b('popup')}
|
54
|
+
text={title}
|
55
|
+
popoverContent={
|
56
|
+
'Use /viewer/json/nodes endpoint for Nodes Tab in diagnostics. It returns incorrect data on older versions'
|
57
|
+
}
|
58
|
+
/>
|
57
59
|
);
|
58
60
|
};
|
59
61
|
|
60
62
|
const renderEnableExplainQueryModesItem = (title: ReactNode) => {
|
61
63
|
return (
|
62
|
-
<
|
63
|
-
{
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
64
|
+
<LabelWithPopover
|
65
|
+
className={b('item-with-popup')}
|
66
|
+
contentClassName={b('popup')}
|
67
|
+
text={title}
|
68
|
+
popoverContent={
|
69
|
+
'Enable script | scan query mode selector for both run and explain. May not work on some versions'
|
70
|
+
}
|
71
|
+
/>
|
70
72
|
);
|
71
73
|
};
|
72
74
|
|
package/dist/services/api.ts
CHANGED
@@ -287,7 +287,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
287
287
|
stats,
|
288
288
|
timeout: 600000,
|
289
289
|
},
|
290
|
-
|
290
|
+
{},
|
291
291
|
{
|
292
292
|
concurrentId,
|
293
293
|
timeout: 9 * 60 * 1000,
|
@@ -307,7 +307,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
307
307
|
action: action || 'explain',
|
308
308
|
timeout: 600000,
|
309
309
|
},
|
310
|
-
|
310
|
+
{},
|
311
311
|
);
|
312
312
|
}
|
313
313
|
getExplainQueryAst(query: string, database: string) {
|
@@ -319,7 +319,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
319
319
|
action: 'explain-ast',
|
320
320
|
timeout: 600000,
|
321
321
|
},
|
322
|
-
|
322
|
+
{},
|
323
323
|
);
|
324
324
|
}
|
325
325
|
getHotKeys(path: string, enableSampling: boolean) {
|
@@ -334,18 +334,18 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
334
334
|
});
|
335
335
|
}
|
336
336
|
killTablet(id?: string) {
|
337
|
-
return this.get<string>(this.getPath(`/tablets?KillTabletID=${id}`),
|
337
|
+
return this.get<string>(this.getPath(`/tablets?KillTabletID=${id}`), {});
|
338
338
|
}
|
339
339
|
stopTablet(id?: string, hiveId?: string) {
|
340
340
|
return this.get<string>(
|
341
341
|
this.getPath(`/tablets/app?TabletID=${hiveId}&page=StopTablet&tablet=${id}`),
|
342
|
-
|
342
|
+
{},
|
343
343
|
);
|
344
344
|
}
|
345
345
|
resumeTablet(id?: string, hiveId?: string) {
|
346
346
|
return this.get<string>(
|
347
347
|
this.getPath(`/tablets/app?TabletID=${hiveId}&page=ResumeTablet&tablet=${id}`),
|
348
|
-
|
348
|
+
{},
|
349
349
|
);
|
350
350
|
}
|
351
351
|
getTabletDescribe(tenantId: TDomainKey) {
|
@@ -368,14 +368,14 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
368
368
|
user,
|
369
369
|
password,
|
370
370
|
},
|
371
|
-
|
371
|
+
{},
|
372
372
|
);
|
373
373
|
}
|
374
374
|
logout() {
|
375
|
-
return this.post(this.getPath('/logout'),
|
375
|
+
return this.post(this.getPath('/logout'), {}, {});
|
376
376
|
}
|
377
377
|
whoami() {
|
378
|
-
return this.get<TUserToken>(this.getPath('/viewer/json/whoami'),
|
378
|
+
return this.get<TUserToken>(this.getPath('/viewer/json/whoami'), {});
|
379
379
|
}
|
380
380
|
}
|
381
381
|
|
@@ -116,7 +116,11 @@ export const selectNodeStructure = createSelector(
|
|
116
116
|
if (!structure[String(pDiskId)]) {
|
117
117
|
structure[String(pDiskId)] = {vDisks: {}, ...vd.PDisk};
|
118
118
|
}
|
119
|
-
structure[String(pDiskId)].vDisks[vDiskId] =
|
119
|
+
structure[String(pDiskId)].vDisks[vDiskId] = {
|
120
|
+
...vd,
|
121
|
+
// VDisk doesn't have its own StoragePoolName when located inside StoragePool data
|
122
|
+
StoragePoolName: pool.Name,
|
123
|
+
};
|
120
124
|
});
|
121
125
|
});
|
122
126
|
});
|
@@ -4,10 +4,10 @@ import type {
|
|
4
4
|
NodesListState,
|
5
5
|
NodesListAction,
|
6
6
|
NodesListRootStateSlice,
|
7
|
-
NodesMap,
|
8
7
|
} from '../../types/store/nodesList';
|
9
8
|
import '../../services/api';
|
10
9
|
import {createRequestActionTypes, createApiRequest} from '../utils';
|
10
|
+
import {prepareNodesMap} from '../../utils/nodes';
|
11
11
|
|
12
12
|
export const FETCH_NODES_LIST = createRequestActionTypes('nodesList', 'FETCH_NODES_LIST');
|
13
13
|
|
@@ -50,11 +50,6 @@ export function getNodesList() {
|
|
50
50
|
}
|
51
51
|
|
52
52
|
export const selectNodesMap = (state: NodesListRootStateSlice) =>
|
53
|
-
state.nodesList.data
|
54
|
-
if (node.Id && node.Host) {
|
55
|
-
nodesMap.set(node.Id, node.Host);
|
56
|
-
}
|
57
|
-
return nodesMap;
|
58
|
-
}, new Map());
|
53
|
+
prepareNodesMap(state.nodesList.data);
|
59
54
|
|
60
55
|
export default nodesList;
|
@@ -271,10 +271,22 @@ export const getFlatListStorageGroups = createSelector([getStoragePools], (stora
|
|
271
271
|
? currentType
|
272
272
|
: 'Mixed';
|
273
273
|
}, '');
|
274
|
+
|
275
|
+
// VDisk doesn't have its own StoragePoolName when located inside StoragePool data
|
276
|
+
const vDisks = group.VDisks?.map((vdisk) => ({
|
277
|
+
...vdisk,
|
278
|
+
StoragePoolName: pool.Name,
|
279
|
+
Donors: vdisk.Donors?.map((donor) => ({
|
280
|
+
...donor,
|
281
|
+
StoragePoolName: pool.Name,
|
282
|
+
})),
|
283
|
+
}));
|
284
|
+
|
274
285
|
return [
|
275
286
|
...acc,
|
276
287
|
{
|
277
288
|
...group,
|
289
|
+
VDisks: vDisks,
|
278
290
|
Read: readSpeedBytesPerSec,
|
279
291
|
Write: writeSpeedBytesPerSec,
|
280
292
|
PoolName: pool.Name,
|
@@ -11,6 +11,7 @@ import type {
|
|
11
11
|
import '../../services/api';
|
12
12
|
|
13
13
|
import {createRequestActionTypes, createApiRequest} from '../utils';
|
14
|
+
import {prepareNodesMap} from '../../utils/nodes';
|
14
15
|
|
15
16
|
export const FETCH_TABLET = createRequestActionTypes('TABLET', 'FETCH_TABLET');
|
16
17
|
export const FETCH_TABLET_DESCRIBE = createRequestActionTypes('TABLET', 'FETCH_TABLET_DESCRIBE');
|
@@ -63,9 +64,19 @@ const tablet: Reducer<ITabletState, ITabletAction> = (state = initialState, acti
|
|
63
64
|
|
64
65
|
export const getTablet = (id: string) => {
|
65
66
|
return createApiRequest({
|
66
|
-
request: Promise.all([
|
67
|
+
request: Promise.all([
|
68
|
+
window.api.getTablet({id}),
|
69
|
+
window.api.getTabletHistory({id}),
|
70
|
+
window.api.getNodesList(),
|
71
|
+
]),
|
67
72
|
actions: FETCH_TABLET,
|
68
|
-
dataHandler: ([
|
73
|
+
dataHandler: ([
|
74
|
+
tabletResponseData,
|
75
|
+
historyResponseData,
|
76
|
+
nodesList,
|
77
|
+
]): ITabletHandledResponse => {
|
78
|
+
const nodesMap = prepareNodesMap(nodesList);
|
79
|
+
|
69
80
|
const historyData = Object.keys(historyResponseData).reduce<
|
70
81
|
ITabletPreparedHistoryItem[]
|
71
82
|
>((list, nodeId) => {
|
@@ -75,6 +86,8 @@ export const getTablet = (id: string) => {
|
|
75
86
|
|
76
87
|
const {ChangeTime, Generation, State, Leader, FollowerId} = leaderTablet;
|
77
88
|
|
89
|
+
const fqdn = nodesMap && nodeId ? nodesMap.get(Number(nodeId)) : undefined;
|
90
|
+
|
78
91
|
list.push({
|
79
92
|
nodeId,
|
80
93
|
generation: Generation,
|
@@ -82,6 +95,7 @@ export const getTablet = (id: string) => {
|
|
82
95
|
state: State,
|
83
96
|
leader: Leader,
|
84
97
|
followerId: FollowerId,
|
98
|
+
fqdn,
|
85
99
|
});
|
86
100
|
}
|
87
101
|
return list;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import {Toaster} from '@gravity-ui/uikit';
|
2
2
|
|
3
|
-
const toaster = new Toaster();
|
3
|
+
export const toaster = new Toaster();
|
4
4
|
|
5
5
|
interface CreateToastProps {
|
6
6
|
name?: string;
|
@@ -10,13 +10,13 @@ interface CreateToastProps {
|
|
10
10
|
}
|
11
11
|
|
12
12
|
function createToast({name, title, type, content}: CreateToastProps) {
|
13
|
-
return toaster.
|
13
|
+
return toaster.add({
|
14
14
|
name: name ?? 'Request succeeded',
|
15
15
|
title: title ?? 'Request succeeded',
|
16
16
|
type: type ?? 'success',
|
17
17
|
content: content,
|
18
18
|
isClosable: true,
|
19
|
-
|
19
|
+
autoHiding: type === 'success' ? 5000 : false,
|
20
20
|
});
|
21
21
|
}
|
22
22
|
|
package/dist/utils/nodes.ts
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
import type {TSystemStateInfo} from '../types/api/nodes';
|
2
|
+
import type {TNodeInfo} from '../types/api/nodesList';
|
2
3
|
import type {INodesPreparedEntity} from '../types/store/nodes';
|
4
|
+
import type {NodesMap} from '../types/store/nodesList';
|
3
5
|
import {EFlag} from '../types/api/enums';
|
4
6
|
|
5
7
|
export enum NodesUptimeFilterValues {
|
@@ -20,3 +22,12 @@ export type NodeAddress = Pick<TSystemStateInfo, 'Host' | 'Endpoints'>;
|
|
20
22
|
export interface AdditionalNodesInfo extends Record<string, unknown> {
|
21
23
|
getNodeRef?: (node?: NodeAddress) => string;
|
22
24
|
}
|
25
|
+
|
26
|
+
export const prepareNodesMap = (nodesList?: TNodeInfo[]) => {
|
27
|
+
return nodesList?.reduce<NodesMap>((nodesMap, node) => {
|
28
|
+
if (node.Id && node.Host) {
|
29
|
+
nodesMap.set(Number(node.Id), node.Host);
|
30
|
+
}
|
31
|
+
return nodesMap;
|
32
|
+
}, new Map());
|
33
|
+
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "ydb-embedded-ui",
|
3
|
-
"version": "4.1
|
3
|
+
"version": "4.2.1",
|
4
4
|
"files": [
|
5
5
|
"dist"
|
6
6
|
],
|
@@ -12,7 +12,7 @@
|
|
12
12
|
"@gravity-ui/axios-wrapper": "^1.3.0",
|
13
13
|
"@gravity-ui/date-utils": "^1.1.1",
|
14
14
|
"@gravity-ui/i18n": "^1.0.0",
|
15
|
-
"@gravity-ui/navigation": "^0.
|
15
|
+
"@gravity-ui/navigation": "^0.4.0",
|
16
16
|
"@gravity-ui/paranoid": "^1.4.0",
|
17
17
|
"@gravity-ui/react-data-table": "^1.0.3",
|
18
18
|
"axios": "0.19.2",
|
@@ -39,7 +39,7 @@
|
|
39
39
|
"reselect": "4.1.6",
|
40
40
|
"sass": "1.32.8",
|
41
41
|
"web-vitals": "1.1.2",
|
42
|
-
"ydb-ui-components": "^3.0
|
42
|
+
"ydb-ui-components": "^3.1.0"
|
43
43
|
},
|
44
44
|
"scripts": {
|
45
45
|
"start": "react-app-rewired start",
|
@@ -105,7 +105,7 @@
|
|
105
105
|
"@gravity-ui/prettier-config": "^1.0.1",
|
106
106
|
"@gravity-ui/stylelint-config": "^1.0.1",
|
107
107
|
"@gravity-ui/tsconfig": "^1.0.0",
|
108
|
-
"@gravity-ui/uikit": "^
|
108
|
+
"@gravity-ui/uikit": "^4.11.1",
|
109
109
|
"@playwright/test": "^1.31.1",
|
110
110
|
"@testing-library/jest-dom": "^5.15.0",
|
111
111
|
"@testing-library/react": "^11.2.7",
|