mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-23 20:25:56 +00:00
Keep the Proxmox guest Backup badge whole at laptop widths (#2525)
## Problem
The Proxmox guest table's Backup badge doesn't truncate, but its column
was too narrow for it.
- **Badge widths, with the shield:** Running 73px, Unknown 79px, None
58px, month ages ("12mo") 61px.
- **Column room:** the compact layout gave Backup a weight of 5, which
left a 33–58px content box from 1000 to 1513px. The wide layout gave it
72px.
- **Result:** Running and Unknown were cut inside their pill at every
width up to 1600px, and None and month ages up to about 1500px.
Running is the badge that says a backup is in progress.
## Change
In `guestRowModel.tsx`:
| Layout | Backup | Taken from | Why that column can give |
|---|---|---|---|
| Compact | weight 5 → 10 | Type 7 → 5.4 | It still fits the VM/LXC
badge and the sorted "TYPE▲" header (about 51px). |
| Compact | | CPU 13 → 9.6 | Its bar only shows a percentage and core
count. |
| Wide | 72px → 96px | CPU 140px → 116px | Same reason. |
Name, ID, Uptime, Net I/O, Disk I/O and the memory and disk bars keep
their widths, and their used/total figures. Views without a Backup
column (pods, Docker) give them slightly more, so two
`GuestRow.test.tsx` width expectations change. The peer whose claim
covers that file agreed to the edit; its own PR, #2524, edits a distant
hunk.
## Verification
Mock-mode private stack on main ebd6d09337, before against after, at 15
widths from 390 to 1920px:
- **Badge fit:** every Backup label fits at every width where the column
shows (1000–1920px). Main clipped Running and Unknown everywhere up to
1600px.
- **Clip sweep:** Proxmox goes from 464 to 452 clipped elements and
vSphere from 2 to 1. No column clips more at any width, and the memory
and disk used/total figures and the CPU core counts are unchanged in
every row.
- **Interactions:** clicking the Running badge opens the backup evidence
dialog at 1024, 1280 and 1600px, and Escape closes it. Row details open.
No console errors.
- **Tests:** a new check in
`WorkloadsSurface.performance.contract.test.tsx` covers the narrowest
compact table and the wide width, and fails against main's source. All
94 Workloads test files pass.
The browser receipt is
`frontend-modern/browser-verification/0c24a36bf1559a9d.json`.
**Known residual:** if a user enables an extra compact column, Backup's
share shrinks, and Unknown can clip again at the narrowest compact
width.
This commit is contained in:
@@ -3766,6 +3766,18 @@ returns focus to the originating disclosure. Nested evidence activation must
|
||||
not trigger the enclosing guest row. Touch targets are at least 44px; compact
|
||||
desktop shields and the existing status colours remain.
|
||||
|
||||
The Backup column badge does not truncate. Running (73px with its shield) and
|
||||
Unknown (79px) need about 95px with cell padding, so the compact layout weights
|
||||
give Backup 10 against Type 5.4 and CPU 9.6, and the wide column is 96px with
|
||||
the extra 24px taken from CPU (116px). Type still fits its VM/LXC badge and
|
||||
sorted header, and CPU its percentage and core count, while Name, ID, Uptime,
|
||||
Net I/O, Disk I/O and the memory and disk bars keep their widths and used/total
|
||||
sublabels; views without a Backup column (pods, Docker) give them slightly more.
|
||||
Before this, Running was cut inside its pill at every width up to 1600px, and
|
||||
None and month ages up to about 1500px.
|
||||
`WorkloadsSurface.performance.contract.test.tsx` checks the narrowest compact
|
||||
table and the wide width.
|
||||
|
||||
The evidence content is reactive to the same guest identity: running is not
|
||||
completion, malformed/future times are unknown, and only the existing absence
|
||||
sentinels mean no backup recorded. A removed row unmounts its disclosure and
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"version": 1,
|
||||
"base_sha": "ebd6d09337d5e4cd17b327df5a69a58dae739a27",
|
||||
"verified_at": "2026-10-05T15:39:31Z",
|
||||
"result": "passed",
|
||||
"changed_paths": [
|
||||
"frontend-modern/src/components/Workloads/guestRowModel.tsx"
|
||||
],
|
||||
"content_sha256": {
|
||||
"frontend-modern/src/components/Workloads/guestRowModel.tsx": "fa970cac1cde21056bc707a5ec6dc056d9f4dc9362f83a5bf8b59d5c2af1f75f"
|
||||
},
|
||||
"routes": [
|
||||
"/proxmox/overview",
|
||||
"/vmware/overview"
|
||||
],
|
||||
"viewports": [
|
||||
{
|
||||
"width": 390,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 600,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 768,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 900,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 973,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 1000,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 1024,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 1100,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 1180,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 1280,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 1366,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 1440,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 1513,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 1600,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 1920,
|
||||
"height": 900
|
||||
}
|
||||
],
|
||||
"states": [
|
||||
"Private mock stack (PULSE_MOCK_MODE, random metrics off) serving this tree on main ebd6d09337; before = main, after = main plus this change, measured in the same session",
|
||||
"Backup badge fit (each label cloned at natural width into the narrowest Backup cell): Running 73px, Unknown 79px, None 58px, 12mo 61px, 21d 52px with the shield. On main the column content box was 33-65px from 1000 to 1600 (compact layout weight 5, wide 72px), so Running and Unknown clipped at every width up to 1600 and None and month ages up to 1440-1513; patched the content box is 81-132px and every label fits at every width where the column shows (1000 to 1920)",
|
||||
"Clip sweep over every cell of the Workloads table and its overflow-hidden or ellipsis descendants, .sr-only excluded, 15 widths 390 to 1920: Proxmox 464 to 452 and vSphere 2 to 1 clipped elements, no column clips more at any width, and the memory and disk used/total sublabels and the CPU core counts are unchanged in every row",
|
||||
"Column widths patched at 1024: Name 259, Type 54, ID 70, CPU 96, Mem 140, Disk 140, Uptime 80, Backup 100 (main 259/70/70/130/140/140/80/50); at 1600 (wide) Name 224, CPU 130, Backup 108, Net I/O and Disk I/O 191 (main 224/157/81/191)",
|
||||
"Before and after element screenshots of the guest table around the Running row at 1024, 1280 and 1600: Running cut inside its pill on main, whole patched"
|
||||
],
|
||||
"interactions": [
|
||||
"Loaded each route fresh, waited for the row count to settle, resized through every viewport before measuring",
|
||||
"Clicked the Running backup badge at 1024, 1280 and 1600: the Backup status evidence dialog opened (Backup running now\u2026) and Escape closed it",
|
||||
"Clicked a guest row's name cell to open its details on both routes; no console errors"
|
||||
]
|
||||
}
|
||||
@@ -1815,7 +1815,7 @@ describe('GUEST_COLUMNS', () => {
|
||||
'aiContext',
|
||||
]);
|
||||
expect(getGuestColumnWidthStyle('name', false, 'compact', compactPodColumnIds)).toEqual({
|
||||
width: '25%',
|
||||
width: '25.8449%',
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1834,7 +1834,7 @@ describe('GUEST_COLUMNS', () => {
|
||||
expect(
|
||||
getGuestColumnWidthStyle('update', false, 'compact', compactDockerRuntimeColumnIds),
|
||||
).toEqual({
|
||||
width: '8.9286%',
|
||||
width: '9.2081%',
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+24
@@ -5,6 +5,7 @@ import { Route, Router } from '@solidjs/router';
|
||||
import type { Resource } from '@/types/resource';
|
||||
import { syncSessionSettingsCapabilities } from '@/stores/sessionSettingsCapabilities';
|
||||
import { WorkloadsSurface } from '../WorkloadsSurface';
|
||||
import { WORKLOAD_TABLE_CONTAINER_TABLET_WIDTH, getGuestColumnStyle } from '../guestRowModel';
|
||||
import workloadsSource from '../WorkloadsSurface.tsx?raw';
|
||||
import workloadsFilterSource from '../WorkloadsFilter.tsx?raw';
|
||||
import workloadsWorkloadTableSource from '../WorkloadsTable.tsx?raw';
|
||||
@@ -1870,3 +1871,26 @@ describe('Workloads performance contract', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Workloads Backup column fit', () => {
|
||||
// The backup badge does not truncate: Running is 73px and Unknown 79px with
|
||||
// the shield, plus 8px of cell padding a side. The compact layout starts at a
|
||||
// 900px table, where the Proxmox guest columns all show.
|
||||
const badgeWidth = 79 + 16;
|
||||
|
||||
it('keeps the widest backup badge whole at the narrowest compact table', () => {
|
||||
const proxmoxColumns = ['name', 'type', 'vmid', 'cpu', 'memory', 'disk', 'uptime', 'backup'];
|
||||
const percent = Number.parseFloat(
|
||||
String(getGuestColumnStyle('backup', false, 'compact', proxmoxColumns)?.width),
|
||||
);
|
||||
expect((percent / 100) * WORKLOAD_TABLE_CONTAINER_TABLET_WIDTH).toBeGreaterThanOrEqual(
|
||||
badgeWidth,
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps the widest backup badge whole in the wide layout', () => {
|
||||
expect(
|
||||
Number.parseFloat(String(getGuestColumnStyle('backup', false, 'wide')?.width)),
|
||||
).toBeGreaterThanOrEqual(badgeWidth);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -241,7 +241,7 @@ export const GUEST_COLUMNS: ColumnDef[] = [
|
||||
createVisibleCanonicalTypeColumn(),
|
||||
{ id: 'info', label: 'Info', width: '100px', sortKey: 'info', kind: 'numeric-value' },
|
||||
{ id: 'vmid', label: 'ID', width: '45px', sortKey: 'vmid', kind: 'numeric-value' },
|
||||
{ id: 'cpu', label: 'CPU', width: '140px', sortKey: 'cpu', kind: 'metric-bar' },
|
||||
{ id: 'cpu', label: 'CPU', width: '116px', sortKey: 'cpu', kind: 'metric-bar' },
|
||||
{ id: 'memory', label: 'Mem', width: '140px', sortKey: 'memory', kind: 'metric-bar' },
|
||||
{
|
||||
id: 'disk',
|
||||
@@ -411,8 +411,12 @@ export const GUEST_COLUMNS: ColumnDef[] = [
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
width: '72px',
|
||||
minWidth: '68px',
|
||||
// The badge does not truncate: Running is 73px and Unknown 79px with the
|
||||
// shield, so the wide column keeps room for both with cell padding. Its
|
||||
// extra 24px comes from CPU, whose bar shows only a percentage and core
|
||||
// count, so the other wide columns keep their widths.
|
||||
width: '96px',
|
||||
minWidth: '90px',
|
||||
toggleable: true,
|
||||
kind: 'badge',
|
||||
},
|
||||
@@ -519,17 +523,22 @@ const GUEST_COLUMN_RESPONSIVE_WEIGHTS: Record<
|
||||
memory: 17,
|
||||
disk: 17,
|
||||
},
|
||||
// The Backup badge needs about 95px with cell padding for Unknown (79px)
|
||||
// and Running (73px) at the narrowest compact table. Its room comes from Type, whose VM/LXC
|
||||
// badge and sorted header need about 51px, and from CPU, whose bar shows
|
||||
// only a percentage and core count; Name, ID, Uptime and the memory and
|
||||
// disk bars keep their widths, so their used/total sublabels stay.
|
||||
compact: {
|
||||
name: 26,
|
||||
runtime: 10,
|
||||
type: 7,
|
||||
type: 5.4,
|
||||
info: 7,
|
||||
vmid: 7,
|
||||
cpu: 13,
|
||||
cpu: 9.6,
|
||||
memory: 14,
|
||||
disk: 14,
|
||||
uptime: 8,
|
||||
backup: 5,
|
||||
backup: 10,
|
||||
image: 18,
|
||||
namespace: 11,
|
||||
context: 13,
|
||||
|
||||
Reference in New Issue
Block a user