Hoist workload filter to top on platform overview pages

Move the WorkloadsFilter to the top of the Proxmox, Kubernetes, TrueNAS,
and vSphere overview surfaces so every workload page renders the filter
bar above its tables, matching the Docker pattern. The mid-page filter
placement was inconsistent across pages and pushed the search input
below the fold on busy hosts/nodes/clusters tables.

Each page lifts useWorkloadsState to its overview component, renders
WorkloadsFilter directly, and passes the state into WorkloadsSurface
(removing showFilterToolbar and the filter* configuration props from
the surface). Filter scope is unchanged — it still governs the embedded
workloads table only.
This commit is contained in:
rcourtman
2026-05-19 21:45:40 +01:00
parent a13bf7da6d
commit 58b2e10c1f
4 changed files with 430 additions and 145 deletions
@@ -1,6 +1,8 @@
import ShipWheelIcon from 'lucide-solid/icons/ship-wheel';
import { Show, createMemo } from 'solid-js';
import { Show, createMemo, type Accessor } from 'solid-js';
import { WorkloadsFilter } from '@/components/Workloads/WorkloadsFilter';
import { WorkloadsSurface } from '@/components/Workloads/WorkloadsSurface';
import { useWorkloadsState } from '@/components/Workloads/useWorkloadsState';
import type { WorkloadsStatusOption } from '@/components/Workloads/workloadsFilterModel';
import { useUnifiedResources } from '@/hooks/useUnifiedResources';
import {
@@ -11,7 +13,11 @@ import {
import { KubernetesClustersTable } from './KubernetesClustersTable';
import { KubernetesDeploymentsTable } from './KubernetesDeploymentsTable';
import { KubernetesNodesTable } from './KubernetesNodesTable';
import { KUBERNETES_TAB_SPECS, buildKubernetesPageModel } from './kubernetesPageModel';
import {
KUBERNETES_TAB_SPECS,
buildKubernetesPageModel,
type KubernetesPageModel,
} from './kubernetesPageModel';
// Include `agent` rows so K8s nodes that the backend registry merged onto
// the linked agent host (sources=['agent','kubernetes']) still appear in the
@@ -76,51 +82,7 @@ export function KubernetesPageSurface() {
/>
}
>
<div class="space-y-4">
<KubernetesClustersTable
clusters={model().clusters}
scope={model().resources}
emptyIcon={k8sIcon()}
emptyTitle="No clusters reported"
emptyDescription="Kubernetes clusters appear here once at least one agent reports cluster context."
showToolbar={false}
/>
<KubernetesNodesTable
resources={model().nodes}
emptyIcon={k8sIcon()}
emptyTitle="No nodes reported"
emptyDescription="Kubernetes nodes appear here as soon as the agent enumerates them."
showToolbar={false}
/>
<WorkloadsSurface
vms={[]}
containers={[]}
nodes={[]}
useWorkloads
embedded
tableOnly
showFilterToolbar
suppressPlatformFilter
allowEmbeddedScopeFilters
forcedPlatform={KUBERNETES_PLATFORM_FILTER}
forcedViewMode={KUBERNETES_WORKLOAD_FORCED_VIEW_MODE}
filterAriaLabel="Kubernetes pod filters"
filterSearchPlaceholder="Search pods by name, namespace, image, cluster, or node"
filterSearchEmptyMessage="Recent Kubernetes pod searches appear here."
filterStatusOptions={KUBERNETES_POD_STATUS_OPTIONS}
columnVisibilityStorageScope={KUBERNETES_WORKLOAD_COLUMN_SCOPE}
compactGroupHeaders
/>
<Show when={model().deployments.length > 0}>
<KubernetesDeploymentsTable
resources={model().deployments}
emptyIcon={k8sIcon()}
emptyTitle="No deployments reported"
emptyDescription="Deployments appear here once the cluster reports them."
showToolbar={false}
/>
</Show>
</div>
<KubernetesOverview model={model} />
</Show>
</Show>
</Show>
@@ -128,4 +90,112 @@ export function KubernetesPageSurface() {
);
}
interface KubernetesOverviewProps {
model: Accessor<KubernetesPageModel>;
}
function KubernetesOverview(props: KubernetesOverviewProps) {
const workloadsState = useWorkloadsState({
vms: [],
containers: [],
nodes: [],
useWorkloads: true,
embedded: true,
tableOnly: true,
forcedPlatform: KUBERNETES_PLATFORM_FILTER,
forcedViewMode: KUBERNETES_WORKLOAD_FORCED_VIEW_MODE,
showFilterToolbar: true,
suppressPlatformFilter: true,
allowEmbeddedScopeFilters: true,
columnVisibilityStorageScope: KUBERNETES_WORKLOAD_COLUMN_SCOPE,
compactGroupHeaders: true,
});
const showSharedFilterToolbar = createMemo(
() =>
workloadsState.surfaceConnected() &&
workloadsState.surfaceInitialDataReceived() &&
workloadsState.allGuests().length > 0,
);
return (
<div class="space-y-4">
<Show when={showSharedFilterToolbar()}>
<div data-summary-clear-ignore>
<WorkloadsFilter
search={workloadsState.search}
setSearch={workloadsState.setSearch}
viewMode={workloadsState.viewMode}
setViewMode={workloadsState.setViewMode}
statusMode={workloadsState.statusMode}
setStatusMode={workloadsState.setStatusMode}
groupingMode={workloadsState.groupingMode}
setGroupingMode={workloadsState.setGroupingMode}
setSortKey={workloadsState.setSortKey}
setSortDirection={workloadsState.setSortDirection}
onBeforeAutoFocus={workloadsState.handleBeforeAutoFocus}
ariaLabel="Kubernetes pod filters"
searchPlaceholder="Search pods by name, namespace, image, cluster, or node"
searchEmptyMessage="Recent Kubernetes pod searches appear here."
statusOptions={KUBERNETES_POD_STATUS_OPTIONS}
columnVisibility={workloadsState.workloadsFilterColumnVisibility()}
containerRuntimeFilter={workloadsState.containerRuntimeFilterConfig()}
hostFilter={workloadsState.hostFilterConfig()}
namespaceFilter={workloadsState.namespaceFilterConfig()}
platformFilter={undefined}
suppressTypeFilter
metricDisplayMode={workloadsState.workloadMetricDisplayMode}
setMetricDisplayMode={workloadsState.setWorkloadMetricDisplayMode}
metricHistoryRange={workloadsState.workloadMetricHistoryRange}
setMetricHistoryRange={workloadsState.setWorkloadMetricHistoryRange}
forcedPlatform={KUBERNETES_PLATFORM_FILTER}
pinnedSelectionActive={() =>
Boolean(
workloadsState.selectedGuestId() ||
workloadsState.focusedSummaryWorkloadGroupId(),
)
}
onClearPinnedSelection={workloadsState.clearPinnedSummaryScope}
/>
</div>
</Show>
<KubernetesClustersTable
clusters={props.model().clusters}
scope={props.model().resources}
emptyIcon={k8sIcon()}
emptyTitle="No clusters reported"
emptyDescription="Kubernetes clusters appear here once at least one agent reports cluster context."
showToolbar={false}
/>
<KubernetesNodesTable
resources={props.model().nodes}
emptyIcon={k8sIcon()}
emptyTitle="No nodes reported"
emptyDescription="Kubernetes nodes appear here as soon as the agent enumerates them."
showToolbar={false}
/>
<WorkloadsSurface
state={workloadsState}
vms={[]}
containers={[]}
nodes={[]}
useWorkloads
embedded
tableOnly
forcedPlatform={KUBERNETES_PLATFORM_FILTER}
forcedViewMode={KUBERNETES_WORKLOAD_FORCED_VIEW_MODE}
compactGroupHeaders
/>
<Show when={props.model().deployments.length > 0}>
<KubernetesDeploymentsTable
resources={props.model().deployments}
emptyIcon={k8sIcon()}
emptyTitle="No deployments reported"
emptyDescription="Deployments appear here once the cluster reports them."
showToolbar={false}
/>
</Show>
</div>
);
}
export default KubernetesPageSurface;
@@ -1,7 +1,9 @@
import { useLocation } from '@solidjs/router';
import { Show, createMemo } from 'solid-js';
import { Show, createMemo, type Accessor } from 'solid-js';
import StorageSurface from '@/components/Storage/Storage';
import { WorkloadsFilter } from '@/components/Workloads/WorkloadsFilter';
import { WorkloadsSurface } from '@/components/Workloads/WorkloadsSurface';
import { useWorkloadsState } from '@/components/Workloads/useWorkloadsState';
import {
DEFAULT_WORKLOADS_METRIC_DISPLAY_MODE,
type WorkloadsStatusOption,
@@ -30,6 +32,7 @@ import {
PROXMOX_TAB_SPECS,
buildProxmoxPageModel,
buildVisibleProxmoxTabSpecs,
type ProxmoxPageModel,
type ProxmoxPageTabId,
} from './proxmoxPageModel';
@@ -132,42 +135,13 @@ export function ProxmoxPageSurface() {
}
>
<Show when={activeTab() === 'overview'}>
<div class="space-y-4">
<ProxmoxNodesTable
nodes={model().pveNodes}
guests={model().guests}
metricDisplayMode={metricDisplayMode}
metricHistoryRange={metricHistoryRange}
emptyIcon={<ProxmoxIcon class="h-6 w-6 text-slate-400" />}
emptyTitle="No Proxmox VE nodes"
emptyDescription="Proxmox VE nodes appear here once a PVE host reports inventory."
/>
<WorkloadsSurface
vms={[]}
containers={[]}
nodes={[]}
useWorkloads
embedded
tableOnly
showFilterToolbar
suppressPlatformFilter
allowEmbeddedScopeFilters
forcedPlatform={PROXMOX_PLATFORM_FILTER}
statusModeStorageScope={PROXMOX_WORKLOAD_STATUS_STORAGE_SCOPE}
filterAriaLabel="Proxmox workload filters"
filterSearchPlaceholder="Search VMs and LXCs by name, VMID, node, or status"
filterSearchEmptyMessage="Recent Proxmox workload searches appear here."
filterStatusOptions={PROXMOX_WORKLOAD_STATUS_OPTIONS}
compactGroupHeaders
groupNodeDrawerMode="disabled"
metricDisplayMode={metricDisplayMode}
onMetricDisplayModeChange={setMetricDisplayMode}
metricHistoryRange={metricHistoryRange}
onMetricHistoryRangeChange={setMetricHistoryRange}
emptyStateTitle="No Proxmox workloads"
emptyStateDescription="Proxmox VMs and LXCs appear here when inventory is available."
/>
</div>
<ProxmoxOverview
model={model}
metricDisplayMode={metricDisplayMode}
setMetricDisplayMode={setMetricDisplayMode}
metricHistoryRange={metricHistoryRange}
setMetricHistoryRange={setMetricHistoryRange}
/>
</Show>
<Show when={activeTab() === 'storage'}>
<StorageSurface
@@ -212,4 +186,106 @@ export function ProxmoxPageSurface() {
);
}
interface ProxmoxOverviewProps {
model: Accessor<ProxmoxPageModel>;
metricDisplayMode: Accessor<WorkloadsMetricDisplayMode>;
setMetricDisplayMode: (value: WorkloadsMetricDisplayMode) => void;
metricHistoryRange: Accessor<WorkloadTableMetricHistoryRange>;
setMetricHistoryRange: (value: WorkloadTableMetricHistoryRange) => void;
}
function ProxmoxOverview(props: ProxmoxOverviewProps) {
const workloadsState = useWorkloadsState({
vms: [],
containers: [],
nodes: [],
useWorkloads: true,
embedded: true,
tableOnly: true,
forcedPlatform: PROXMOX_PLATFORM_FILTER,
showFilterToolbar: true,
suppressPlatformFilter: true,
allowEmbeddedScopeFilters: true,
statusModeStorageScope: PROXMOX_WORKLOAD_STATUS_STORAGE_SCOPE,
compactGroupHeaders: true,
groupNodeDrawerMode: 'disabled',
metricDisplayMode: props.metricDisplayMode,
onMetricDisplayModeChange: props.setMetricDisplayMode,
metricHistoryRange: props.metricHistoryRange,
onMetricHistoryRangeChange: props.setMetricHistoryRange,
});
const showSharedFilterToolbar = createMemo(
() =>
workloadsState.surfaceConnected() &&
workloadsState.surfaceInitialDataReceived() &&
workloadsState.allGuests().length > 0,
);
return (
<div class="space-y-4">
<Show when={showSharedFilterToolbar()}>
<div data-summary-clear-ignore>
<WorkloadsFilter
search={workloadsState.search}
setSearch={workloadsState.setSearch}
viewMode={workloadsState.viewMode}
setViewMode={workloadsState.setViewMode}
statusMode={workloadsState.statusMode}
setStatusMode={workloadsState.setStatusMode}
groupingMode={workloadsState.groupingMode}
setGroupingMode={workloadsState.setGroupingMode}
setSortKey={workloadsState.setSortKey}
setSortDirection={workloadsState.setSortDirection}
onBeforeAutoFocus={workloadsState.handleBeforeAutoFocus}
ariaLabel="Proxmox workload filters"
searchPlaceholder="Search VMs and LXCs by name, VMID, node, or status"
searchEmptyMessage="Recent Proxmox workload searches appear here."
statusOptions={PROXMOX_WORKLOAD_STATUS_OPTIONS}
columnVisibility={workloadsState.workloadsFilterColumnVisibility()}
containerRuntimeFilter={workloadsState.containerRuntimeFilterConfig()}
hostFilter={workloadsState.hostFilterConfig()}
namespaceFilter={workloadsState.namespaceFilterConfig()}
platformFilter={undefined}
metricDisplayMode={workloadsState.workloadMetricDisplayMode}
setMetricDisplayMode={workloadsState.setWorkloadMetricDisplayMode}
metricHistoryRange={workloadsState.workloadMetricHistoryRange}
setMetricHistoryRange={workloadsState.setWorkloadMetricHistoryRange}
forcedPlatform={PROXMOX_PLATFORM_FILTER}
pinnedSelectionActive={() =>
Boolean(
workloadsState.selectedGuestId() ||
workloadsState.focusedSummaryWorkloadGroupId(),
)
}
onClearPinnedSelection={workloadsState.clearPinnedSummaryScope}
/>
</div>
</Show>
<ProxmoxNodesTable
nodes={props.model().pveNodes}
guests={props.model().guests}
metricDisplayMode={props.metricDisplayMode}
metricHistoryRange={props.metricHistoryRange}
emptyIcon={<ProxmoxIcon class="h-6 w-6 text-slate-400" />}
emptyTitle="No Proxmox VE nodes"
emptyDescription="Proxmox VE nodes appear here once a PVE host reports inventory."
/>
<WorkloadsSurface
state={workloadsState}
vms={[]}
containers={[]}
nodes={[]}
useWorkloads
embedded
tableOnly
forcedPlatform={PROXMOX_PLATFORM_FILTER}
compactGroupHeaders
groupNodeDrawerMode="disabled"
emptyStateTitle="No Proxmox workloads"
emptyStateDescription="Proxmox VMs and LXCs appear here when inventory is available."
/>
</div>
);
}
export default ProxmoxPageSurface;
@@ -1,8 +1,10 @@
import { useLocation } from '@solidjs/router';
import DatabaseIcon from 'lucide-solid/icons/database';
import { Show, createMemo } from 'solid-js';
import { Show, createMemo, type Accessor } from 'solid-js';
import StorageSurface from '@/components/Storage/Storage';
import { WorkloadsFilter } from '@/components/Workloads/WorkloadsFilter';
import { WorkloadsSurface } from '@/components/Workloads/WorkloadsSurface';
import { useWorkloadsState } from '@/components/Workloads/useWorkloadsState';
import type { WorkloadsStatusOption } from '@/components/Workloads/workloadsFilterModel';
import { useUnifiedResources } from '@/hooks/useUnifiedResources';
import {
@@ -14,6 +16,7 @@ import { TrueNASSystemsTable } from './TrueNASSystemsTable';
import {
TRUENAS_TAB_SPECS,
buildTrueNASPageModel,
type TrueNASPageModel,
type TrueNASPageTabId,
} from './truenasPageModel';
@@ -86,36 +89,7 @@ export function TrueNASPageSurface() {
}
>
<Show when={activeTab() === 'overview'}>
<div class="space-y-4">
<TrueNASSystemsTable
systems={model().systems}
scope={model().resources}
emptyIcon={truenasIcon()}
emptyTitle="No TrueNAS systems"
emptyDescription="TrueNAS systems appear here once a TrueNAS connection reports its top-level appliance."
showToolbar={false}
/>
<Show when={model().apps.length > 0}>
<WorkloadsSurface
vms={[]}
containers={[]}
nodes={[]}
useWorkloads
embedded
tableOnly
showFilterToolbar
suppressPlatformFilter
allowEmbeddedScopeFilters
forcedPlatform={TRUENAS_PLATFORM_FILTER}
forcedViewMode="app-container"
filterAriaLabel="TrueNAS app filters"
filterSearchPlaceholder="Search TrueNAS apps by name, image, namespace, or system"
filterSearchEmptyMessage="Recent TrueNAS app searches appear here."
filterStatusOptions={TRUENAS_APP_STATUS_OPTIONS}
compactGroupHeaders
/>
</Show>
</div>
<TrueNASOverview model={model} />
</Show>
<Show when={activeTab() === 'storage'}>
<StorageSurface
@@ -135,4 +109,98 @@ export function TrueNASPageSurface() {
);
}
interface TrueNASOverviewProps {
model: Accessor<TrueNASPageModel>;
}
function TrueNASOverview(props: TrueNASOverviewProps) {
const workloadsState = useWorkloadsState({
vms: [],
containers: [],
nodes: [],
useWorkloads: true,
embedded: true,
tableOnly: true,
forcedPlatform: TRUENAS_PLATFORM_FILTER,
forcedViewMode: 'app-container',
showFilterToolbar: true,
suppressPlatformFilter: true,
allowEmbeddedScopeFilters: true,
compactGroupHeaders: true,
});
const showSharedFilterToolbar = createMemo(
() =>
props.model().apps.length > 0 &&
workloadsState.surfaceConnected() &&
workloadsState.surfaceInitialDataReceived() &&
workloadsState.allGuests().length > 0,
);
return (
<div class="space-y-4">
<Show when={showSharedFilterToolbar()}>
<div data-summary-clear-ignore>
<WorkloadsFilter
search={workloadsState.search}
setSearch={workloadsState.setSearch}
viewMode={workloadsState.viewMode}
setViewMode={workloadsState.setViewMode}
statusMode={workloadsState.statusMode}
setStatusMode={workloadsState.setStatusMode}
groupingMode={workloadsState.groupingMode}
setGroupingMode={workloadsState.setGroupingMode}
setSortKey={workloadsState.setSortKey}
setSortDirection={workloadsState.setSortDirection}
onBeforeAutoFocus={workloadsState.handleBeforeAutoFocus}
ariaLabel="TrueNAS app filters"
searchPlaceholder="Search TrueNAS apps by name, image, namespace, or system"
searchEmptyMessage="Recent TrueNAS app searches appear here."
statusOptions={TRUENAS_APP_STATUS_OPTIONS}
columnVisibility={workloadsState.workloadsFilterColumnVisibility()}
containerRuntimeFilter={workloadsState.containerRuntimeFilterConfig()}
hostFilter={workloadsState.hostFilterConfig()}
namespaceFilter={workloadsState.namespaceFilterConfig()}
platformFilter={undefined}
suppressTypeFilter
metricDisplayMode={workloadsState.workloadMetricDisplayMode}
setMetricDisplayMode={workloadsState.setWorkloadMetricDisplayMode}
metricHistoryRange={workloadsState.workloadMetricHistoryRange}
setMetricHistoryRange={workloadsState.setWorkloadMetricHistoryRange}
forcedPlatform={TRUENAS_PLATFORM_FILTER}
pinnedSelectionActive={() =>
Boolean(
workloadsState.selectedGuestId() ||
workloadsState.focusedSummaryWorkloadGroupId(),
)
}
onClearPinnedSelection={workloadsState.clearPinnedSummaryScope}
/>
</div>
</Show>
<TrueNASSystemsTable
systems={props.model().systems}
scope={props.model().resources}
emptyIcon={truenasIcon()}
emptyTitle="No TrueNAS systems"
emptyDescription="TrueNAS systems appear here once a TrueNAS connection reports its top-level appliance."
showToolbar={false}
/>
<Show when={props.model().apps.length > 0}>
<WorkloadsSurface
state={workloadsState}
vms={[]}
containers={[]}
nodes={[]}
useWorkloads
embedded
tableOnly
forcedPlatform={TRUENAS_PLATFORM_FILTER}
forcedViewMode="app-container"
compactGroupHeaders
/>
</Show>
</div>
);
}
export default TrueNASPageSurface;
@@ -1,8 +1,10 @@
import { useLocation } from '@solidjs/router';
import CpuIcon from 'lucide-solid/icons/cpu';
import { Show, createMemo } from 'solid-js';
import { Show, createMemo, type Accessor } from 'solid-js';
import StorageSurface from '@/components/Storage/Storage';
import { WorkloadsFilter } from '@/components/Workloads/WorkloadsFilter';
import { WorkloadsSurface } from '@/components/Workloads/WorkloadsSurface';
import { useWorkloadsState } from '@/components/Workloads/useWorkloadsState';
import type { WorkloadsStatusOption } from '@/components/Workloads/workloadsFilterModel';
import { useUnifiedResources } from '@/hooks/useUnifiedResources';
import {
@@ -11,7 +13,12 @@ import {
PlatformTableEmptyState,
} from '@/features/platformPage/sharedPlatformPage';
import { VsphereHostsTable } from './VsphereHostsTable';
import { VMWARE_TAB_SPECS, buildVmwarePageModel, type VmwarePageTabId } from './vmwarePageModel';
import {
VMWARE_TAB_SPECS,
buildVmwarePageModel,
type VmwarePageModel,
type VmwarePageTabId,
} from './vmwarePageModel';
// `datastore` is not a first-class type token at the API boundary; vSphere
// datastores are emitted as canonical `storage` rows. Including it
@@ -80,34 +87,7 @@ export function VmwarePageSurface() {
}
>
<Show when={activeTab() === 'overview'}>
<div class="space-y-4">
<VsphereHostsTable
hosts={model().hosts}
scope={model().resources}
emptyIcon={vmwareIcon()}
emptyTitle="No vSphere hosts"
emptyDescription="Hosts appear here once the vCenter connection enumerates them."
showToolbar={false}
/>
<WorkloadsSurface
vms={[]}
containers={[]}
nodes={[]}
useWorkloads
embedded
tableOnly
showFilterToolbar
suppressPlatformFilter
allowEmbeddedScopeFilters
forcedPlatform={VMWARE_PLATFORM_FILTER}
forcedViewMode="vm"
filterAriaLabel="vSphere VM filters"
filterSearchPlaceholder="Search vSphere VMs by name, VM ID, host, or status"
filterSearchEmptyMessage="Recent vSphere VM searches appear here."
filterStatusOptions={VMWARE_VM_STATUS_OPTIONS}
compactGroupHeaders
/>
</div>
<VmwareOverview model={model} />
</Show>
<Show when={activeTab() === 'storage'}>
<StorageSurface
@@ -128,4 +108,95 @@ export function VmwarePageSurface() {
);
}
interface VmwareOverviewProps {
model: Accessor<VmwarePageModel>;
}
function VmwareOverview(props: VmwareOverviewProps) {
const workloadsState = useWorkloadsState({
vms: [],
containers: [],
nodes: [],
useWorkloads: true,
embedded: true,
tableOnly: true,
forcedPlatform: VMWARE_PLATFORM_FILTER,
forcedViewMode: 'vm',
showFilterToolbar: true,
suppressPlatformFilter: true,
allowEmbeddedScopeFilters: true,
compactGroupHeaders: true,
});
const showSharedFilterToolbar = createMemo(
() =>
workloadsState.surfaceConnected() &&
workloadsState.surfaceInitialDataReceived() &&
workloadsState.allGuests().length > 0,
);
return (
<div class="space-y-4">
<Show when={showSharedFilterToolbar()}>
<div data-summary-clear-ignore>
<WorkloadsFilter
search={workloadsState.search}
setSearch={workloadsState.setSearch}
viewMode={workloadsState.viewMode}
setViewMode={workloadsState.setViewMode}
statusMode={workloadsState.statusMode}
setStatusMode={workloadsState.setStatusMode}
groupingMode={workloadsState.groupingMode}
setGroupingMode={workloadsState.setGroupingMode}
setSortKey={workloadsState.setSortKey}
setSortDirection={workloadsState.setSortDirection}
onBeforeAutoFocus={workloadsState.handleBeforeAutoFocus}
ariaLabel="vSphere VM filters"
searchPlaceholder="Search vSphere VMs by name, VM ID, host, or status"
searchEmptyMessage="Recent vSphere VM searches appear here."
statusOptions={VMWARE_VM_STATUS_OPTIONS}
columnVisibility={workloadsState.workloadsFilterColumnVisibility()}
containerRuntimeFilter={workloadsState.containerRuntimeFilterConfig()}
hostFilter={workloadsState.hostFilterConfig()}
namespaceFilter={workloadsState.namespaceFilterConfig()}
platformFilter={undefined}
suppressTypeFilter
metricDisplayMode={workloadsState.workloadMetricDisplayMode}
setMetricDisplayMode={workloadsState.setWorkloadMetricDisplayMode}
metricHistoryRange={workloadsState.workloadMetricHistoryRange}
setMetricHistoryRange={workloadsState.setWorkloadMetricHistoryRange}
forcedPlatform={VMWARE_PLATFORM_FILTER}
pinnedSelectionActive={() =>
Boolean(
workloadsState.selectedGuestId() ||
workloadsState.focusedSummaryWorkloadGroupId(),
)
}
onClearPinnedSelection={workloadsState.clearPinnedSummaryScope}
/>
</div>
</Show>
<VsphereHostsTable
hosts={props.model().hosts}
scope={props.model().resources}
emptyIcon={vmwareIcon()}
emptyTitle="No vSphere hosts"
emptyDescription="Hosts appear here once the vCenter connection enumerates them."
showToolbar={false}
/>
<WorkloadsSurface
state={workloadsState}
vms={[]}
containers={[]}
nodes={[]}
useWorkloads
embedded
tableOnly
forcedPlatform={VMWARE_PLATFORM_FILTER}
forcedViewMode="vm"
compactGroupHeaders
/>
</div>
);
}
export default VmwarePageSurface;