mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-24 12:13:28 +00:00
editor: drop redundant two-mode fork on Add connection
The ledger's "How Pulse collects data" explainer already teaches the
Platform API / Pulse Unified Agent split. Repeating that split as a
choose-your-path screen when the user clicks Add connection was a dead
decision step — the subtitle ("Paste an address. Pulse detects the
product…") already commits to API-first, then the body below
contradicted it with a 50/50 fork between API and Agent.
Collapse the fallback to: one address probe (the primary path), the
existing manual-type picker under "Enter credentials manually", and the
agent install as a one-line contextual offramp beneath ("Setting up
bare-metal Linux, Unraid, or FreeBSD…? Install the Unified Agent on a
host."). The agent CTA is still there — it's just not presented as an
equal-weight peer to the probe.
Tests adjusted: the former "two cards mirroring the explainer" case is
replaced with "leads with address probe; agent install is an offramp,"
which pins the same buttons but explicitly forbids a "Platform API"
card header from reappearing. Architecture snapshot simplified to pin
only the shape-level anchors (AddressProbeStep import, manual-type
list, agent offramp CTA), not copy details.
This commit is contained in:
@@ -76,64 +76,47 @@ export const ConnectionEditor: Component<ConnectionEditorProps> = (props) => {
|
||||
<Show
|
||||
when={showCredentialSlot()}
|
||||
fallback={
|
||||
<div class="space-y-4 p-4">
|
||||
<section class="space-y-3 rounded-md border border-border bg-surface-alt/30 p-3">
|
||||
<div>
|
||||
<div class="space-y-5 p-4">
|
||||
<AddressProbeStep
|
||||
state={state}
|
||||
onSelectCandidate={chooseCandidate}
|
||||
onChooseManually={() => setManualPickerOpen((v) => !v)}
|
||||
/>
|
||||
|
||||
<Show when={manualPickerOpen()}>
|
||||
<div class="space-y-2 rounded-md border border-border bg-surface p-3">
|
||||
<div class="text-xs font-semibold uppercase tracking-wide text-muted">
|
||||
Platform API
|
||||
</div>
|
||||
<div class="text-[11px] text-muted">
|
||||
Proxmox VE / PBS / PMG, VMware, TrueNAS
|
||||
Choose Platform API type manually
|
||||
</div>
|
||||
<ul class="divide-y divide-border rounded-md border border-border">
|
||||
{manualOptions().map((type) => (
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
class="flex w-full items-center justify-between px-3 py-2 text-left text-sm text-base-content transition-colors hover:bg-surface-hover"
|
||||
onClick={() => chooseManualType(type)}
|
||||
>
|
||||
<span>{CONNECTION_TYPE_LABELS[type] ?? type}</span>
|
||||
<span class="text-xs text-muted">{type}</span>
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
<AddressProbeStep
|
||||
state={state}
|
||||
onSelectCandidate={chooseCandidate}
|
||||
onChooseManually={() => setManualPickerOpen((v) => !v)}
|
||||
/>
|
||||
|
||||
<Show when={manualPickerOpen()}>
|
||||
<div class="space-y-2 rounded-md border border-border bg-surface p-3">
|
||||
<div class="text-xs font-semibold uppercase tracking-wide text-muted">
|
||||
Choose Platform API type manually
|
||||
</div>
|
||||
<ul class="divide-y divide-border rounded-md border border-border">
|
||||
{manualOptions().map((type) => (
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
class="flex w-full items-center justify-between px-3 py-2 text-left text-sm text-base-content transition-colors hover:bg-surface-hover"
|
||||
onClick={() => chooseManualType(type)}
|
||||
>
|
||||
<span>{CONNECTION_TYPE_LABELS[type] ?? type}</span>
|
||||
<span class="text-xs text-muted">{type}</span>
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</Show>
|
||||
</section>
|
||||
|
||||
<section class="space-y-3 rounded-md border border-blue-200 bg-blue-50/40 p-3 dark:border-blue-900 dark:bg-blue-950/20">
|
||||
<div>
|
||||
<div class="text-xs font-semibold uppercase tracking-wide text-muted">
|
||||
Pulse Unified Agent
|
||||
</div>
|
||||
<div class="text-[11px] text-muted">
|
||||
Host-level metrics on Proxmox / VMware / TrueNAS, or the only path on
|
||||
bare-metal Linux, Unraid, FreeBSD.
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-t border-border pt-3 text-xs text-muted">
|
||||
Setting up bare-metal Linux, Unraid, or FreeBSD, or adding host-level
|
||||
metrics (CPU/disk temps, SMART, power) on Proxmox, VMware, or TrueNAS?{' '}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => chooseManualType('agent')}
|
||||
class="inline-flex items-center rounded-md border border-blue-600 bg-blue-600 px-3 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-500"
|
||||
class="font-medium text-blue-600 underline underline-offset-2 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
|
||||
>
|
||||
Install the Unified Agent on a host
|
||||
</button>
|
||||
</section>
|
||||
.
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
|
||||
+10
-3
@@ -94,7 +94,7 @@ describe('ConnectionEditor', () => {
|
||||
expect(lastCall.candidate).toBeNull();
|
||||
});
|
||||
|
||||
it('surfaces Platform API and Pulse Unified Agent as the two add-paths, mirroring the explainer', () => {
|
||||
it('leads with the address probe; agent install is an offramp, not a peer fork', () => {
|
||||
render(() => (
|
||||
<ConnectionEditor
|
||||
renderCredentialSlot={() => <div />}
|
||||
@@ -102,8 +102,15 @@ describe('ConnectionEditor', () => {
|
||||
/>
|
||||
));
|
||||
|
||||
expect(screen.getByText('Platform API')).toBeInTheDocument();
|
||||
expect(screen.getByText('Pulse Unified Agent')).toBeInTheDocument();
|
||||
// Primary path is probe-the-address. The explainer on the ledger already
|
||||
// taught the user the two-mode split, so the editor must not restate it
|
||||
// as a second decision screen — no "Platform API" card header here.
|
||||
expect(screen.getByRole('button', { name: /probe address/i })).toBeInTheDocument();
|
||||
expect(screen.getByRole('button', { name: /enter credentials manually/i })).toBeInTheDocument();
|
||||
expect(screen.queryByText('Platform API')).toBeNull();
|
||||
|
||||
// Agent install is still reachable, but as a contextual offramp beneath
|
||||
// the probe, not as an equal-weight card.
|
||||
expect(
|
||||
screen.getByRole('button', { name: /install the unified agent on a host/i }),
|
||||
).toBeInTheDocument();
|
||||
|
||||
@@ -77,10 +77,8 @@ describe('settings architecture guardrails', () => {
|
||||
it('keeps probe-first connection setup and inline node credentials on the shared editor model', () => {
|
||||
expect(connectionEditorSource).toContain("import { AddressProbeStep } from './AddressProbeStep';");
|
||||
expect(connectionEditorSource).toContain('const DEFAULT_MANUAL_TYPES: ConnectionType[] =');
|
||||
expect(connectionEditorSource).toContain('Platform API');
|
||||
expect(connectionEditorSource).toContain('Pulse Unified Agent');
|
||||
expect(connectionEditorSource).toContain('Install the Unified Agent on a host');
|
||||
expect(connectionEditorSource).toContain('<AddressProbeStep');
|
||||
expect(connectionEditorSource).toContain('Install the Unified Agent on a host');
|
||||
expect(connectionEditorSource).not.toContain('NodeModal');
|
||||
|
||||
expect(addressProbeStepSource).toContain('Probe address');
|
||||
|
||||
Reference in New Issue
Block a user