Skip to content

Commit eb53209

Browse files
committed
feat(frontend): improve legibility for unallocated and user partitions
Add stripes to unallocated space, to distinguish it from allocated space. For unknown volumes, cycle through a wheel of colors. Signed-off-by: Edward Sammut Alessi <edward.sammutalessi@siderolabs.com>
1 parent 2c4940a commit eb53209

2 files changed

Lines changed: 69 additions & 33 deletions

File tree

frontend/src/views/Machines/MachineDisks.stories.ts

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//
33
// Use of this software is governed by the Business Source License
44
// included in the LICENSE file.
5+
import { faker } from '@faker-js/faker'
56
import { createWatchStreamHandler } from '@msw/helpers'
67
import type { Meta, StoryObj } from '@storybook/vue3-vite'
78

@@ -44,7 +45,6 @@ export const WithData = {
4445
},
4546
spec: {
4647
dev_path: '/dev/vda',
47-
pretty_size: '20 GB',
4848
size: 21474836480,
4949
transport: 'virtio',
5050
},
@@ -66,7 +66,6 @@ export const WithData = {
6666
},
6767
spec: {
6868
dev_path: '/dev/vda',
69-
pretty_size: '20 GB',
7069
size: 21474836480,
7170
type: 'disk',
7271
},
@@ -83,7 +82,6 @@ export const WithData = {
8382
parent: 'vda',
8483
partition_index: 1,
8584
partition_label: 'EFI',
86-
pretty_size: '105 MB',
8785
size: 105906176,
8886
type: 'partition',
8987
},
@@ -100,7 +98,6 @@ export const WithData = {
10098
parent: 'vda',
10199
partition_index: 2,
102100
partition_label: 'BOOT',
103-
pretty_size: '1.0 GB',
104101
size: 1073741824,
105102
type: 'partition',
106103
},
@@ -117,7 +114,6 @@ export const WithData = {
117114
parent: 'vda',
118115
partition_index: 3,
119116
partition_label: 'STATE',
120-
pretty_size: '104 MB',
121117
size: 104857600,
122118
type: 'partition',
123119
},
@@ -134,9 +130,25 @@ export const WithData = {
134130
parent: 'vda',
135131
partition_index: 4,
136132
partition_label: 'EPHEMERAL',
137-
pretty_size: '4.1 GB',
138133
size: 4131389440,
139-
uuid: 'faa1a56a-4934-4317-b6d1-272712353c5c',
134+
uuid: faker.string.uuid(),
135+
type: 'partition',
136+
},
137+
},
138+
{
139+
metadata: {
140+
id: 'vda5',
141+
namespace: TalosRuntimeNamespace,
142+
type: TalosDiscoveredVolumeType,
143+
},
144+
spec: {
145+
dev_path: '/dev/vda4',
146+
name: 'xfs',
147+
parent: 'vda',
148+
partition_index: 4,
149+
partition_label: 'USER',
150+
size: 3267896320,
151+
uuid: faker.string.uuid(),
140152
type: 'partition',
141153
},
142154
},
@@ -244,7 +256,6 @@ export const WithCdrom: Story = {
244256
spec: {
245257
cdrom: true,
246258
dev_path: '/dev/sr0',
247-
pretty_size: '750 MB',
248259
size: 786432000,
249260
readonly: true,
250261
transport: 'ata',
@@ -260,7 +271,6 @@ export const WithCdrom: Story = {
260271
spec: {
261272
cdrom: true,
262273
dev_path: '/dev/sr1',
263-
pretty_size: '0 B',
264274
size: 0,
265275
readonly: true,
266276
},
@@ -284,7 +294,6 @@ export const WithCdrom: Story = {
284294
spec: {
285295
dev_path: '/dev/sr0',
286296
name: 'iso9660',
287-
pretty_size: '750 MB',
288297
size: 786432000,
289298
type: 'disk',
290299
},
@@ -301,7 +310,6 @@ export const WithCdrom: Story = {
301310
spec: {
302311
dev_path: '/dev/sr1',
303312
name: '',
304-
pretty_size: '0 B',
305313
size: 0,
306314
type: 'disk',
307315
},
@@ -339,7 +347,6 @@ export const WithLuksEncryption: Story = {
339347
},
340348
spec: {
341349
dev_path: '/dev/vda',
342-
pretty_size: '20 GB',
343350
size: 21474836480,
344351
transport: 'virtio',
345352
},
@@ -354,7 +361,6 @@ export const WithLuksEncryption: Story = {
354361
},
355362
spec: {
356363
dev_path: '/dev/dm-0',
357-
pretty_size: '104 MB',
358364
size: 104857600,
359365
},
360366
},
@@ -379,7 +385,6 @@ export const WithLuksEncryption: Story = {
379385
parent: 'vda',
380386
partition_index: 1,
381387
partition_label: 'EFI',
382-
pretty_size: '105 MB',
383388
size: 105906176,
384389
type: 'partition',
385390
},
@@ -398,7 +403,6 @@ export const WithLuksEncryption: Story = {
398403
parent: 'vda',
399404
partition_index: 2,
400405
partition_label: 'EPHEMERAL',
401-
pretty_size: '19 GB',
402406
size: 20265148416,
403407
type: 'partition',
404408
},

frontend/src/views/Nodes/components/DiskUsageBar.vue

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,52 +32,80 @@ const unallocatedPercent = computed(() => {
3232
return Math.max(0, partitionPercent(diskSize - usedSpace.value, diskSize))
3333
})
3434
35+
const knownLabelColors = {
36+
efi: 'bg-yellow-500',
37+
boot: 'bg-orange-500',
38+
state: 'bg-purple-500',
39+
ephemeral: 'bg-blue-500',
40+
}
41+
42+
const unknownLabelColors = computed(
43+
() =>
44+
new Map(
45+
volumes
46+
.filter((v) => {
47+
const label = v.spec.partition_label?.toLowerCase()
48+
49+
return !label || !(label in knownLabelColors)
50+
})
51+
.map((v, i) => {
52+
const hue = ((i + 1) * 137.508) % 360
53+
54+
return [v.metadata.id!, `hsl(${hue.toFixed(1)}deg 55% 30%)`] as const
55+
}),
56+
),
57+
)
58+
3559
const getVolumeClass = (volume: Resource<DiscoveredVolumeSpec>) => {
36-
const fsType = volume.spec.name?.toLowerCase()
37-
const label = volume.spec.partition_label?.toLowerCase()
38-
39-
if (label?.includes('efi')) return 'bg-yellow-500'
40-
if (label?.includes('boot')) return 'bg-orange-500'
41-
if (label?.includes('state')) return 'bg-purple-500'
42-
if (label?.includes('ephemeral')) return 'bg-blue-500'
43-
if (fsType?.includes('luks')) return 'bg-indigo-500'
44-
if (fsType?.includes('xfs') || fsType?.includes('ext')) return 'bg-green-600'
45-
if (fsType?.includes('vfat') || fsType?.includes('fat')) return 'bg-yellow-600'
46-
if (fsType?.includes('swap')) return 'bg-red-500'
47-
return 'bg-naturals-n9'
60+
const label = volume.spec.partition_label?.toLowerCase() as keyof typeof knownLabelColors
61+
62+
return label ? knownLabelColors[label] : undefined
63+
}
64+
65+
const getVolumeStyle = (volume: Resource<DiscoveredVolumeSpec>) => {
66+
const color = unknownLabelColors.value.get(volume.metadata.id!)
67+
68+
return color ? { backgroundColor: color } : undefined
4869
}
4970
</script>
5071

5172
<template>
5273
<div>
53-
<div class="flex h-8 w-full overflow-hidden rounded bg-naturals-n5">
74+
<div class="flex h-8 w-full overflow-hidden rounded bg-naturals-n5 text-xs">
5475
<div
5576
v-for="volume in volumes"
5677
:key="volume.metadata.id"
5778
:title="`${volume.spec.partition_label || volume.spec.label || volume.spec.dev_path} — ${prettyBytes(volume.spec.size ?? 0)}`"
5879
:class="getVolumeClass(volume)"
5980
:style="{
6081
width: `${partitionPercent(volume.spec.size, disk.spec.size)}%`,
82+
...getVolumeStyle(volume),
6183
}"
62-
class="flex min-w-0 items-center justify-center overflow-hidden text-xs text-naturals-n14 last:border-r-0"
84+
class="flex min-w-0 items-center justify-center overflow-hidden text-naturals-n14 last:border-r-0"
6385
>
6486
<span
6587
v-if="partitionPercent(volume.spec.size, disk.spec.size) > 10"
66-
class="truncate px-1.5 text-xs font-medium drop-shadow-xs drop-shadow-black"
88+
class="truncate px-1.5 font-medium drop-shadow-xs drop-shadow-black"
6789
>
6890
{{ volume.spec.partition_label || volume.spec.label || '' }}
6991
<span class="opacity-80">
7092
{{ prettyBytes(volume.spec.size ?? 0) }}
7193
</span>
7294
</span>
7395
</div>
96+
7497
<div
7598
v-if="unallocatedPercent > 0"
7699
:style="{ width: `${unallocatedPercent}%` }"
77100
title="Unallocated"
78-
class="flex min-w-0 items-center justify-center overflow-hidden text-xs text-naturals-n12"
101+
class="flex min-w-0 items-center justify-center overflow-hidden bg-[repeating-linear-gradient(-45deg,var(--stripe-color),var(--stripe-color)_var(--stripe-size),transparent_var(--stripe-size),transparent_calc(var(--stripe-size)*2))] text-naturals-n12 [--stripe-color:var(--color-naturals-n7)] [--stripe-size:12px]"
79102
>
80-
<span v-if="unallocatedPercent > 10" class="truncate px-1.5">Unallocated</span>
103+
<span
104+
v-if="unallocatedPercent > 10"
105+
class="truncate px-1.5 font-medium drop-shadow-xs drop-shadow-black"
106+
>
107+
Unallocated
108+
</span>
81109
</div>
82110
</div>
83111

@@ -87,7 +115,11 @@ const getVolumeClass = (volume: Resource<DiscoveredVolumeSpec>) => {
87115
:key="'legend-' + volume.metadata.id"
88116
class="flex items-center gap-1.5"
89117
>
90-
<span class="inline-block size-2.5 rounded-sm" :class="getVolumeClass(volume)" />
118+
<span
119+
class="inline-block size-2.5 rounded-sm"
120+
:class="getVolumeClass(volume)"
121+
:style="getVolumeStyle(volume)"
122+
/>
91123
<span class="font-medium text-naturals-n12">
92124
{{ volume.spec.partition_label || volume.spec.label || volume.spec.dev_path }}
93125
</span>

0 commit comments

Comments
 (0)