Skip to content

Commit 38969b6

Browse files
committed
feat: vdisks in 2 rows
1 parent 44e079a commit 38969b6

File tree

4 files changed

+202
-34
lines changed

4 files changed

+202
-34
lines changed

src/containers/Storage/PDisk/PDisk.scss

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,35 @@
11
.pdisk-storage {
22
position: relative;
33

4-
width: 120px;
4+
display: flex;
5+
flex-direction: column;
6+
7+
min-width: 120px;
58

69
&__content {
710
position: relative;
811

912
display: block;
13+
flex: 1;
1014

11-
border-radius: 4px; // to match interactive area with disk shape
15+
border-radius: 4px;
1216
}
1317

1418
&__vdisks {
1519
display: flex;
16-
// this breaks disks relative sizes, but disks rarely exceed one line
17-
flex-wrap: wrap;
20+
overflow: hidden; // Prevent overflow
21+
flex: 0 0 auto;
1822
gap: 2px;
1923

2024
margin-bottom: 4px;
25+
26+
white-space: nowrap;
2127
}
2228

2329
&__vdisks-item {
24-
flex-basis: 3px;
25-
flex-shrink: 0;
30+
flex: 0 0 3px;
31+
32+
min-width: 3px;
2633

2734
.stack__layer {
2835
.data-table__row:hover & {

src/containers/Storage/StorageNodes/columns/StorageNodesColumns.scss

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,13 @@
55

66
&__pdisks-wrapper {
77
display: flex;
8-
justify-content: left;
9-
align-items: flex-end;
8+
gap: 10px;
109

11-
width: max-content;
12-
height: 40px;
10+
width: 100%;
1311
}
14-
&__pdisks-item {
15-
flex-grow: 1;
16-
17-
max-width: 200px;
18-
margin-right: 10px;
1912

20-
&:last-child {
21-
margin-right: 0px;
22-
}
13+
&__pdisks-item {
14+
display: flex;
15+
flex-shrink: 0;
2316
}
2417
}

src/containers/Storage/StorageNodes/getNodes.ts

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
NODES_COLUMNS_TO_DATA_FIELDS,
44
getNodesColumnSortField,
55
} from '../../../components/nodesColumns/constants';
6+
import {generateNodes} from '../../../mocks/storage/nodes';
67
import type {
78
PreparedStorageNode,
89
PreparedStorageNodeFilters,
@@ -44,22 +45,31 @@ export const getStorageNodes: FetchData<
4445

4546
const dataFieldsRequired = getRequiredDataFields(columnsIds, NODES_COLUMNS_TO_DATA_FIELDS);
4647

47-
const response = await window.api.viewer.getNodes({
48-
type,
49-
storage,
50-
limit,
51-
offset,
52-
sort,
53-
filter: searchValue,
54-
uptime: getUptimeParamValue(nodesUptimeFilter),
55-
with: visibleEntities,
56-
database,
57-
node_id: nodeId,
58-
group_id: groupId,
59-
filter_group: filterGroup,
60-
filter_group_by: filterGroupBy,
61-
fieldsRequired: dataFieldsRequired,
62-
});
48+
let response;
49+
if (process.env.NODE_ENV === 'development') {
50+
// Get mock configuration from URL parameters or use defaults
51+
const urlParams = new URLSearchParams(window.location.search);
52+
const pdisks = parseInt(urlParams.get('pdisks') || '10', 10);
53+
const vdisksPerPDisk = parseInt(urlParams.get('vdisksPerPDisk') || '2', 10);
54+
response = generateNodes(5, {vdisksCount: pdisks * vdisksPerPDisk, pdisksCount: pdisks});
55+
} else {
56+
response = await window.api.viewer.getNodes({
57+
type,
58+
storage,
59+
limit,
60+
offset,
61+
sort,
62+
filter: searchValue,
63+
uptime: getUptimeParamValue(nodesUptimeFilter),
64+
with: visibleEntities,
65+
database,
66+
node_id: nodeId,
67+
group_id: groupId,
68+
filter_group: filterGroup,
69+
filter_group_by: filterGroupBy,
70+
fieldsRequired: dataFieldsRequired,
71+
});
72+
}
6373
const preparedResponse = prepareStorageNodesResponse(response);
6474
return {
6575
data: preparedResponse.nodes || [],

src/mocks/storage/nodes.ts

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
import {EFlag} from '../../types/api/enums';
2+
import type {
3+
TEndpoint,
4+
TNodeInfo,
5+
TNodesInfo,
6+
TPoolStats,
7+
TSystemStateInfo,
8+
} from '../../types/api/nodes';
9+
import {TPDiskState} from '../../types/api/pdisk';
10+
import {EVDiskState} from '../../types/api/vdisk';
11+
12+
// Different disk sizes to simulate variety (in bytes)
13+
const DISK_SIZES = [
14+
'68719476736', // 64 GB
15+
'137438953472', // 128 GB
16+
'274877906944', // 256 GB
17+
'549755813888', // 512 GB
18+
'1099511627776', // 1 TB
19+
];
20+
21+
const getRandomDiskSize = () => DISK_SIZES[Math.floor(Math.random() * DISK_SIZES.length)];
22+
23+
const generatePoolStats = (count = 5): TPoolStats[] => {
24+
const poolNames = ['System', 'User', 'Batch', 'IO', 'IC'] as const;
25+
return poolNames.slice(0, count).map((Name) => ({
26+
Name,
27+
Usage: Math.random() * 0.02,
28+
Threads: Math.floor(Math.random() * 3) + 1,
29+
}));
30+
};
31+
32+
const generateEndpoints = (): TEndpoint[] => [
33+
{Name: 'ic', Address: ':19001'},
34+
{Name: 'http-mon', Address: ':8765'},
35+
{Name: 'grpcs', Address: ':2135'},
36+
{Name: 'grpc', Address: ':2136'},
37+
];
38+
39+
const generateSystemState = (nodeId: number): TSystemStateInfo => ({
40+
StartTime: '1734358137851',
41+
ChangeTime: '1734358421375',
42+
LoadAverage: [3.381347656, 2.489257813, 1.279296875],
43+
NumberOfCpus: 8,
44+
SystemState: EFlag.Green,
45+
NodeId: nodeId,
46+
Host: `localhost-${nodeId}`,
47+
Version: 'main.95ce0df',
48+
PoolStats: generatePoolStats(),
49+
Endpoints: generateEndpoints(),
50+
Roles: ['Bootstrapper', 'StateStorage', 'StateStorageBoard', 'SchemeBoard', 'Storage'],
51+
MemoryLimit: '2147483648',
52+
MaxDiskUsage: 0.002349853516,
53+
Location: {
54+
DataCenter: '1',
55+
Rack: '1',
56+
Unit: '1',
57+
},
58+
TotalSessions: 0,
59+
CoresUsed: 0.07583969556,
60+
CoresTotal: 8,
61+
});
62+
63+
const generatePDisk = (nodeId: number, pdiskId: number, totalSize = '68719476736') => ({
64+
PDiskId: pdiskId,
65+
ChangeTime: '1734358142074',
66+
Path: `/ydb_data/pdisk${pdiskId}l3ki78no.data`,
67+
Guid: pdiskId.toString(),
68+
Category: '0',
69+
TotalSize: totalSize,
70+
AvailableSize: (Number(totalSize) * 0.9).toString(), // 90% available by default
71+
State: TPDiskState.Normal,
72+
NodeId: nodeId,
73+
Device: EFlag.Green,
74+
Realtime: EFlag.Green,
75+
SerialNumber: '',
76+
SystemSize: '213909504',
77+
LogUsedSize: '35651584',
78+
LogTotalSize: '68486692864',
79+
EnforcedDynamicSlotSize: '22817013760',
80+
});
81+
82+
const generateVDisk = (nodeId: number, vdiskId: number, pdiskId: number) => ({
83+
VDiskId: {
84+
GroupID: vdiskId,
85+
GroupGeneration: 1,
86+
Ring: 0,
87+
Domain: 0,
88+
VDisk: 0,
89+
},
90+
ChangeTime: '1734358420919',
91+
PDiskId: pdiskId,
92+
VDiskSlotId: vdiskId,
93+
Guid: '1',
94+
Kind: '0',
95+
NodeId: nodeId,
96+
VDiskState: EVDiskState.OK,
97+
DiskSpace: EFlag.Green,
98+
SatisfactionRank: {
99+
FreshRank: {
100+
Flag: EFlag.Green,
101+
},
102+
LevelRank: {
103+
Flag: EFlag.Green,
104+
},
105+
},
106+
Replicated: true,
107+
ReplicationProgress: 1,
108+
ReplicationSecondsRemaining: 0,
109+
AllocatedSize: '0',
110+
AvailableSize: '22817013760',
111+
HasUnreadableBlobs: false,
112+
IncarnationGuid: '11528832187803248876',
113+
InstanceGuid: '14836434871903384493',
114+
FrontQueues: EFlag.Green,
115+
StoragePoolName: 'static',
116+
ReadThroughput: '0',
117+
WriteThroughput: '420',
118+
});
119+
120+
interface NodeGeneratorOptions {
121+
vdisksCount?: number;
122+
pdisksCount?: number;
123+
}
124+
125+
const DEFAULT_OPTIONS: NodeGeneratorOptions = {
126+
vdisksCount: 12,
127+
pdisksCount: 4,
128+
};
129+
130+
const generateNode = (nodeId: number, options: NodeGeneratorOptions = {}): TNodeInfo => {
131+
const pdisksCount = options.pdisksCount ?? DEFAULT_OPTIONS.pdisksCount;
132+
const vdisksCount = options.vdisksCount ?? DEFAULT_OPTIONS.vdisksCount;
133+
134+
return {
135+
NodeId: nodeId,
136+
UptimeSeconds: 284,
137+
CpuUsage: 0.00947996,
138+
DiskSpaceUsage: 0.234985,
139+
SystemState: generateSystemState(nodeId),
140+
PDisks: Array.from({length: pdisksCount!}, (_, i) =>
141+
generatePDisk(nodeId, i + 1, getRandomDiskSize()),
142+
),
143+
VDisks: Array.from({length: vdisksCount!}, (_, i) => {
144+
// Distribute VDisks evenly across PDisks
145+
const pdiskId = (i % pdisksCount!) + 1;
146+
return generateVDisk(nodeId, i, pdiskId);
147+
}),
148+
};
149+
};
150+
151+
export const generateNodes = (count = 1, options?: NodeGeneratorOptions): TNodesInfo => {
152+
const nodes = Array.from({length: count}, (_, i) => generateNode(i + 1, options));
153+
return {
154+
TotalNodes: count.toString(),
155+
FoundNodes: count.toString(),
156+
Nodes: nodes,
157+
};
158+
};

0 commit comments

Comments
 (0)