refactor: remove step-based UI pattern from Proxmox settings

Replace the misleading "Step 1/Step 2" wizard pattern with a cleaner
dashboard-style layout. This better reflects the actual user flow of
selecting and configuring integrations.

Changes:
- Remove AgentStepSection wrapper and numbered badges
- Replace with standard SectionHeader for consistent typography
- Wrap PVE/PBS/PMG tables in Card components for better visual hierarchy
- Group action buttons (Discovery, Refresh, Add Node) in card headers
- Enhance empty states with icons and better messaging
- Fix spacing between integration selector and configuration sections
- Remove unused AgentStepSection import

All agent types (PVE, PBS, PMG, Docker, Host) now have consistent
presentation and improved visual clarity.
This commit is contained in:
rcourtman 2025-10-24 09:10:52 +00:00
parent b311bdd069
commit f20eccee86

View file

@ -21,7 +21,6 @@ import { SectionHeader } from '@/components/shared/SectionHeader';
import { Toggle } from '@/components/shared/Toggle'; import { Toggle } from '@/components/shared/Toggle';
import type { ToggleChangeEvent } from '@/components/shared/Toggle'; import type { ToggleChangeEvent } from '@/components/shared/Toggle';
import { formField, labelClass, controlClass, formHelpText } from '@/components/shared/Form'; import { formField, labelClass, controlClass, formHelpText } from '@/components/shared/Form';
import { AgentStepSection } from './AgentStepSection';
import Server from 'lucide-solid/icons/server'; import Server from 'lucide-solid/icons/server';
import HardDrive from 'lucide-solid/icons/hard-drive'; import HardDrive from 'lucide-solid/icons/hard-drive';
import Mail from 'lucide-solid/icons/mail'; import Mail from 'lucide-solid/icons/mail';
@ -2130,12 +2129,11 @@ const Settings: Component<SettingsProps> = (props) => {
<div class="p-6 lg:p-8"> <div class="p-6 lg:p-8">
<Show when={activeTab() === 'proxmox'}> <Show when={activeTab() === 'proxmox'}>
<AgentStepSection <SectionHeader
step="Step 1" title="Select an integration"
title="Choose a platform" description="Choose the platform you want to configure. The configuration interface will update based on your selection."
description="Pick the integration you want to configure. Cards switch the guidance shown in the next step." />
> <Card padding="lg" class="space-y-6 mt-6">
<Card padding="lg" class="space-y-6">
<For each={agentGroups}> <For each={agentGroups}>
{(group) => ( {(group) => (
<section class="space-y-3"> <section class="space-y-3">
@ -2199,19 +2197,14 @@ const Settings: Component<SettingsProps> = (props) => {
)} )}
</For> </For>
</Card> </Card>
</AgentStepSection>
</Show> </Show>
{/* PVE Nodes Tab */} {/* PVE Nodes Tab */}
<Show when={activeTab() === 'proxmox' && selectedAgent() === 'pve'}> <Show when={activeTab() === 'proxmox' && selectedAgent() === 'pve'}>
<section class="space-y-6"> <div class="space-y-6 mt-6">
<header class="space-y-1"> <SectionHeader
<h3 class="text-lg font-semibold text-gray-900 dark:text-gray-100"> title="Connect Proxmox VE"
Connect Proxmox VE description="Link Pulse to your Proxmox VE cluster with a dedicated API token. Quick setup can scaffold users, roles, and permissions for you."
</h3> />
<p class="text-sm text-gray-600 dark:text-gray-400 leading-relaxed">
Link Pulse to your Proxmox VE cluster with a dedicated API token. Quick setup can scaffold users, roles, and permissions for you.
</p>
</header>
<div class="space-y-4"> <div class="space-y-4">
<Show when={!initialLoadComplete()}> <Show when={!initialLoadComplete()}>
<div class="flex items-center justify-center rounded-lg border border-dashed border-gray-300 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/40 py-12 text-sm text-gray-500 dark:text-gray-400"> <div class="flex items-center justify-center rounded-lg border border-dashed border-gray-300 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/40 py-12 text-sm text-gray-500 dark:text-gray-400">
@ -2219,10 +2212,11 @@ const Settings: Component<SettingsProps> = (props) => {
</div> </div>
</Show> </Show>
<Show when={initialLoadComplete()}> <Show when={initialLoadComplete()}>
<> <Card padding="lg">
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-4 gap-3"> <div class="space-y-4">
<SectionHeader title="Proxmox VE nodes" size="md" class="flex-1" /> <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
<div class="flex flex-wrap items-center justify-start gap-2 sm:justify-end"> <h4 class="text-base font-semibold text-gray-900 dark:text-gray-100">Proxmox VE nodes</h4>
<div class="flex flex-wrap items-center justify-start gap-2 sm:justify-end">
{/* Discovery toggle */} {/* Discovery toggle */}
<div <div
class="flex items-center gap-2 sm:gap-3" class="flex items-center gap-2 sm:gap-3"
@ -2334,12 +2328,16 @@ const Settings: Component<SettingsProps> = (props) => {
discoveredNodes().filter((n) => n.type === 'pve').length === 0 discoveredNodes().filter((n) => n.type === 'pve').length === 0
} }
> >
<div class="text-center py-8 text-gray-500 dark:text-gray-400"> <div class="flex flex-col items-center justify-center py-12 px-4 text-center">
<p>No PVE nodes configured</p> <div class="rounded-full bg-gray-100 dark:bg-gray-800 p-4 mb-4">
<p class="text-sm mt-1">Add a node to start monitoring</p> <Server class="h-8 w-8 text-gray-400 dark:text-gray-500" />
</div>
<p class="text-base font-medium text-gray-900 dark:text-gray-100 mb-1">No PVE nodes configured</p>
<p class="text-sm text-gray-500 dark:text-gray-400">Add a Proxmox VE node to start monitoring your infrastructure</p>
</div> </div>
</Show> </Show>
</> </div>
</Card>
</Show> </Show>
{/* Discovered PVE nodes - only show when discovery is enabled */} {/* Discovered PVE nodes - only show when discovery is enabled */}
@ -2478,20 +2476,16 @@ const Settings: Component<SettingsProps> = (props) => {
</div> </div>
</Show> </Show>
</div> </div>
</section> </div>
</Show> </Show>
{/* PBS Nodes Tab */} {/* PBS Nodes Tab */}
<Show when={activeTab() === 'proxmox' && selectedAgent() === 'pbs'}> <Show when={activeTab() === 'proxmox' && selectedAgent() === 'pbs'}>
<section class="space-y-6"> <div class="space-y-6 mt-6">
<header class="space-y-1"> <SectionHeader
<h3 class="text-lg font-semibold text-gray-900 dark:text-gray-100"> title="Connect Proxmox Backup Server"
Connect Proxmox Backup Server description="Provide a PBS API token with backup read access. Use quick setup to generate the token and grant the minimum privileges."
</h3> />
<p class="text-sm text-gray-600 dark:text-gray-400 leading-relaxed">
Provide a PBS API token with backup read access. Use quick setup to generate the token and grant the minimum privileges.
</p>
</header>
<div class="space-y-4"> <div class="space-y-4">
<Show when={!initialLoadComplete()}> <Show when={!initialLoadComplete()}>
<div class="flex items-center justify-center rounded-lg border border-dashed border-gray-300 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/40 py-12 text-sm text-gray-500 dark:text-gray-400"> <div class="flex items-center justify-center rounded-lg border border-dashed border-gray-300 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/40 py-12 text-sm text-gray-500 dark:text-gray-400">
@ -2499,10 +2493,11 @@ const Settings: Component<SettingsProps> = (props) => {
</div> </div>
</Show> </Show>
<Show when={initialLoadComplete()}> <Show when={initialLoadComplete()}>
<> <Card padding="lg">
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-4 gap-3"> <div class="space-y-4">
<SectionHeader title="Proxmox Backup Server nodes" size="md" class="flex-1" /> <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
<div class="flex flex-wrap items-center justify-start gap-2 sm:justify-end"> <h4 class="text-base font-semibold text-gray-900 dark:text-gray-100">Proxmox Backup Server nodes</h4>
<div class="flex flex-wrap items-center justify-start gap-2 sm:justify-end">
{/* Discovery toggle */} {/* Discovery toggle */}
<div <div
class="flex items-center gap-2 sm:gap-3" class="flex items-center gap-2 sm:gap-3"
@ -2614,12 +2609,16 @@ const Settings: Component<SettingsProps> = (props) => {
discoveredNodes().filter((n) => n.type === 'pbs').length === 0 discoveredNodes().filter((n) => n.type === 'pbs').length === 0
} }
> >
<div class="text-center py-8 text-gray-500 dark:text-gray-400"> <div class="flex flex-col items-center justify-center py-12 px-4 text-center">
<p>No PBS nodes configured</p> <div class="rounded-full bg-gray-100 dark:bg-gray-800 p-4 mb-4">
<p class="text-sm mt-1">Add a node to start monitoring</p> <HardDrive class="h-8 w-8 text-gray-400 dark:text-gray-500" />
</div>
<p class="text-base font-medium text-gray-900 dark:text-gray-100 mb-1">No PBS nodes configured</p>
<p class="text-sm text-gray-500 dark:text-gray-400">Add a Proxmox Backup Server to monitor your backup infrastructure</p>
</div> </div>
</Show> </Show>
</> </div>
</Card>
</Show> </Show>
{/* Discovered PBS nodes - only show when discovery is enabled */} {/* Discovered PBS nodes - only show when discovery is enabled */}
@ -2758,19 +2757,15 @@ const Settings: Component<SettingsProps> = (props) => {
</div> </div>
</Show> </Show>
</div> </div>
</section> </div>
</Show> </Show>
{/* PMG Nodes Tab */} {/* PMG Nodes Tab */}
<Show when={activeTab() === 'proxmox' && selectedAgent() === 'pmg'}> <Show when={activeTab() === 'proxmox' && selectedAgent() === 'pmg'}>
<section class="space-y-6"> <div class="space-y-6 mt-6">
<header class="space-y-1"> <SectionHeader
<h3 class="text-lg font-semibold text-gray-900 dark:text-gray-100"> title="Connect Proxmox Mail Gateway"
Connect Proxmox Mail Gateway description="Onboard each Mail Gateway with a limited API token so Pulse can read queue depth and quarantine metrics."
</h3> />
<p class="text-sm text-gray-600 dark:text-gray-400 leading-relaxed">
Onboard each Mail Gateway with a limited API token so Pulse can read queue depth and quarantine metrics.
</p>
</header>
<div class="space-y-4"> <div class="space-y-4">
<Show when={!initialLoadComplete()}> <Show when={!initialLoadComplete()}>
<div class="flex items-center justify-center rounded-lg border border-dashed border-gray-300 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/40 py-12 text-sm text-gray-500 dark:text-gray-400"> <div class="flex items-center justify-center rounded-lg border border-dashed border-gray-300 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/40 py-12 text-sm text-gray-500 dark:text-gray-400">
@ -2779,10 +2774,11 @@ const Settings: Component<SettingsProps> = (props) => {
</Show> </Show>
<Show when={initialLoadComplete()}> <Show when={initialLoadComplete()}>
<> <Card padding="lg">
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-4 gap-3"> <div class="space-y-4">
<SectionHeader title="Proxmox Mail Gateway nodes" size="md" class="flex-1" /> <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
<div class="flex flex-wrap items-center justify-start gap-2 sm:justify-end"> <h4 class="text-base font-semibold text-gray-900 dark:text-gray-100">Proxmox Mail Gateway nodes</h4>
<div class="flex flex-wrap items-center justify-start gap-2 sm:justify-end">
{/* Discovery toggle */} {/* Discovery toggle */}
<div <div
class="flex items-center gap-2 sm:gap-3" class="flex items-center gap-2 sm:gap-3"
@ -2876,12 +2872,16 @@ const Settings: Component<SettingsProps> = (props) => {
</Show> </Show>
<Show when={pmgNodes().length === 0}> <Show when={pmgNodes().length === 0}>
<div class="text-center py-8 text-gray-500 dark:text-gray-400"> <div class="flex flex-col items-center justify-center py-12 px-4 text-center">
<p>No PMG nodes configured</p> <div class="rounded-full bg-gray-100 dark:bg-gray-800 p-4 mb-4">
<p class="text-sm mt-1">Add a node to start monitoring mail flow</p> <Mail class="h-8 w-8 text-gray-400 dark:text-gray-500" />
</div>
<p class="text-base font-medium text-gray-900 dark:text-gray-100 mb-1">No PMG nodes configured</p>
<p class="text-sm text-gray-500 dark:text-gray-400">Add a Proxmox Mail Gateway to monitor mail queue and quarantine metrics</p>
</div> </div>
</Show> </Show>
</> </div>
</Card>
</Show> </Show>
{/* Discovered PMG nodes - only show when discovery is enabled */} {/* Discovered PMG nodes - only show when discovery is enabled */}
@ -3029,17 +3029,17 @@ const Settings: Component<SettingsProps> = (props) => {
</div> </div>
</Show> </Show>
</div> </div>
</section> </div>
</Show> </Show>
{/* Docker Tab */} {/* Docker Tab */}
<Show when={activeTab() === 'proxmox' && selectedAgent() === 'docker'}> <Show when={activeTab() === 'proxmox' && selectedAgent() === 'docker'}>
<AgentStepSection <div class="space-y-6 mt-6">
step="Step 2" <SectionHeader
title="Deploy the Docker agent" title="Deploy the Docker agent"
description="Mint a scoped reporting token and copy the install commands for the Docker host you are onboarding." description="Generate a scoped reporting token and copy the install commands for the Docker host you are onboarding."
> />
<DockerAgents /> <DockerAgents />
</AgentStepSection> </div>
</Show> </Show>
{/* Docker Platform Tab */} {/* Docker Platform Tab */}
@ -3070,13 +3070,13 @@ const Settings: Component<SettingsProps> = (props) => {
{/* Host Agents */} {/* Host Agents */}
<Show when={activeTab() === 'proxmox' && selectedAgent() === 'host'}> <Show when={activeTab() === 'proxmox' && selectedAgent() === 'host'}>
<AgentStepSection <div class="space-y-6 mt-6">
step="Step 2" <SectionHeader
title="Install the Pulse host agent" title="Install the Pulse host agent"
description="Pick the operating system, generate a scoped token, and copy the tailored commands for Linux, macOS, or Windows." description="Pick the operating system, generate a scoped token, and copy the tailored commands for Linux, macOS, or Windows."
> />
<HostAgents /> <HostAgents />
</AgentStepSection> </div>
</Show> </Show>
{/* System General Tab */} {/* System General Tab */}