Add vSphere placement card to workload drawer

When a vSphere VM opens in the workload drawer, the System card
shows CPUs and Node (the runtime host) but vCenter, Datacenter,
and Cluster context were nowhere to be found. Add a small vSphere
card next to System / Guest Info / Tags showing those three fields,
matching the card-shaped layout the drawer already uses.

Extend WorkloadGuest with a narrow vmware shape (connectionName,
vcenterHost, datacenterName, clusterName) and populate it in
the useWorkloads mapping when platformType is vmware-vsphere.
The card only renders when at least one field is present.

Tools / snapshots / virtual disks / network adapters are not on
this card; surfacing them would require mapping more fields onto
WorkloadGuest and a separate decision on what's drawer-worthy.
This commit is contained in:
rcourtman
2026-05-23 09:12:45 +01:00
parent 62a0027ff8
commit 35bbb5d552
3 changed files with 79 additions and 0 deletions
@@ -156,6 +156,63 @@ export function GuestDrawerOverview(props: GuestDrawerOverviewProps) {
</div>
</div>
{/* vSphere placement card: vCenter / Datacenter / Cluster live on
WorkloadGuest.vmware and aren't surfaced by System (Node already
shows the runtime host). Render only when the workload is a
vSphere VM and at least one of these fields is populated. */}
<Show
when={
(props.guest.platformScopes?.includes('vmware-vsphere') ?? false) &&
(props.guest.vmware?.connectionName ||
props.guest.vmware?.vcenterHost ||
props.guest.vmware?.datacenterName ||
props.guest.vmware?.clusterName)
}
>
<div class="rounded border border-border bg-surface p-3 shadow-sm">
<h3 class="text-[11px] font-medium uppercase tracking-wide text-base-content mb-2">
vSphere
</h3>
<div class="space-y-1.5 text-[11px]">
<Show when={props.guest.vmware?.connectionName || props.guest.vmware?.vcenterHost}>
<div class="flex items-center justify-between gap-2 min-w-0">
<span class="text-muted shrink-0">vCenter</span>
<span
class="font-medium text-base-content truncate"
title={
props.guest.vmware?.vcenterHost || props.guest.vmware?.connectionName || ''
}
>
{props.guest.vmware?.connectionName || props.guest.vmware?.vcenterHost}
</span>
</div>
</Show>
<Show when={props.guest.vmware?.datacenterName}>
<div class="flex items-center justify-between gap-2 min-w-0">
<span class="text-muted shrink-0">Datacenter</span>
<span
class="font-medium text-base-content truncate"
title={props.guest.vmware?.datacenterName || ''}
>
{props.guest.vmware?.datacenterName}
</span>
</div>
</Show>
<Show when={props.guest.vmware?.clusterName}>
<div class="flex items-center justify-between gap-2 min-w-0">
<span class="text-muted shrink-0">Cluster</span>
<span
class="font-medium text-base-content truncate"
title={props.guest.vmware?.clusterName || ''}
>
{props.guest.vmware?.clusterName}
</span>
</div>
</Show>
</div>
</div>
</Show>
<Show when={props.hasOsInfo || props.ipAddresses.length > 0}>
<div class="rounded border border-border bg-surface p-3 shadow-sm">
<h3 class="text-[11px] font-medium uppercase tracking-wide text-base-content mb-2">
+10
View File
@@ -130,6 +130,7 @@ type APIResource = {
};
vmware?: {
connectionName?: string;
vcenterHost?: string;
datacenterName?: string;
clusterName?: string;
runtimeHostName?: string;
@@ -513,6 +514,15 @@ const mapResourceToWorkload = (resource: APIResource): WorkloadGuest | null => {
platformType,
platformScopes,
discoveryTarget,
vmware:
platformType === 'vmware-vsphere' && resource.vmware
? {
connectionName: resource.vmware.connectionName,
vcenterHost: resource.vmware.vcenterHost,
datacenterName: resource.vmware.datacenterName,
clusterName: resource.vmware.clusterName,
}
: undefined,
};
};
+12
View File
@@ -32,4 +32,16 @@ export type WorkloadGuest = (VM | Container) & {
// Canonical discovery ownership. API-backed platforms such as TrueNAS should
// only expose Discovery when the unified resource contract supplies a target.
discoveryTarget?: ResourceDiscoveryTarget;
// vSphere placement context surfaced in the workload drawer's vSphere
// card. Only populated for resources with platformScopes containing
// `vmware-vsphere`. Kept narrow on purpose — operational state like
// Tools / snapshots / disks lives in the unified resource payload and
// hasn't been mapped onto WorkloadGuest because the workload drawer
// hasn't asked for it yet.
vmware?: {
connectionName?: string;
vcenterHost?: string;
datacenterName?: string;
clusterName?: string;
};
};