mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-21 18:46:08 +00:00
Add back-to-inventory header on infrastructure subviews
The connections-table flip in 00c6dc2dd removed the workspace's top-of-
page subtab strip but left the install panel and platforms workspace
rendering bare with no path back to the inventory table. Operators who
clicked Add a system, picked a platform, and landed on
/settings/infrastructure/install or /settings/infrastructure/platforms/*
had to leave Settings entirely and return to the tab to get back to the
table.
Render a persistent breadcrumb header above every non-inventory view
inside InfrastructureWorkspace: a "← Connections and Inventory" button
that navigates back to the bare /settings/infrastructure route, plus a
heading naming the current subview. Inventory itself is unchanged.
Bring agent-lifecycle rule 7 into line by requiring this back-to-
inventory affordance on every detail route under /settings/infrastructure
so deeper surfaces are never reachable without a visible return path.
Cover the new header on install and platforms subviews — and its absence
on the inventory landing — in InfrastructureWorkspace.test.tsx.
This commit is contained in:
parent
2dc4e43033
commit
8d0aec6e4d
3 changed files with 69 additions and 5 deletions
|
|
@ -371,10 +371,15 @@ an add-only capacity posture.
|
|||
`/settings/infrastructure/operations` remain reachable as detail routes
|
||||
for install, platform connections, and legacy reporting/control surfaces
|
||||
respectively, but the workspace shell must not gate inventory visibility
|
||||
behind tab navigation. Read-only sessions must continue to redirect the
|
||||
install detail route back to the unified inventory view and suppress the
|
||||
add-system entry point on the base table so presentation-policy
|
||||
restrictions still hold.
|
||||
behind tab navigation. Every non-inventory detail route under
|
||||
`/settings/infrastructure/*` must render a persistent breadcrumb header
|
||||
that includes a one-click `Connections and Inventory` control returning
|
||||
to the bare `/settings/infrastructure` route, so operators are never
|
||||
stranded on a deeper install or platform-connection surface without a
|
||||
visible path back to the unified table. Read-only sessions must continue
|
||||
to redirect the install detail route back to the unified inventory view
|
||||
and suppress the add-system entry point on the base table so
|
||||
presentation-policy restrictions still hold.
|
||||
8. Keep post-install lifecycle completion explicit inside
|
||||
`frontend-modern/src/components/Settings/InfrastructureInstallerSection.tsx`
|
||||
and `frontend-modern/src/components/Settings/useInfrastructureInstallState.tsx`.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, Match, Switch, createEffect, createMemo, createSignal } from 'solid-js';
|
||||
import { Component, Match, Show, Switch, createEffect, createMemo, createSignal } from 'solid-js';
|
||||
import { useLocation, useNavigate } from '@solidjs/router';
|
||||
import { presentationPolicyIsReadOnly } from '@/stores/sessionPresentationPolicy';
|
||||
import { InfrastructureInstallPanel } from './InfrastructureInstallPanel';
|
||||
|
|
@ -57,8 +57,36 @@ export const InfrastructureWorkspace: Component<InfrastructureWorkspaceProps> =
|
|||
}
|
||||
});
|
||||
|
||||
const subviewHeading = createMemo(() => {
|
||||
switch (activeView()) {
|
||||
case 'install':
|
||||
return 'Install on a host';
|
||||
case 'platforms':
|
||||
return 'Platform connections';
|
||||
case 'operations':
|
||||
return 'Reporting';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<div class="space-y-6">
|
||||
<Show when={activeView() !== 'inventory'}>
|
||||
<div class="flex items-center gap-2 text-sm">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => navigate(buildInfrastructureWorkspacePath('inventory'))}
|
||||
class="inline-flex items-center gap-1 rounded-md border border-border bg-surface px-2.5 py-1 text-muted hover:bg-surface-hover hover:text-base-content"
|
||||
>
|
||||
<span aria-hidden="true">←</span>
|
||||
<span>Connections and Inventory</span>
|
||||
</button>
|
||||
<span class="text-muted" aria-hidden="true">/</span>
|
||||
<span class="font-medium text-base-content">{subviewHeading()}</span>
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
<Switch>
|
||||
<Match when={activeView() === 'inventory'}>
|
||||
<ConnectionsTable
|
||||
|
|
|
|||
|
|
@ -158,6 +158,37 @@ describe('InfrastructureWorkspace', () => {
|
|||
expect(screen.getByTestId('reporting-panel')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders a back-to-inventory header on the install subview', () => {
|
||||
mockPathname = '/settings/infrastructure/install';
|
||||
renderWorkspace();
|
||||
|
||||
const backButton = screen.getByRole('button', { name: /Connections and Inventory/i });
|
||||
expect(backButton).toBeInTheDocument();
|
||||
expect(screen.getByText('Install on a host')).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(backButton);
|
||||
expect(navigateSpy).toHaveBeenCalledWith('/settings/infrastructure');
|
||||
});
|
||||
|
||||
it('renders a back-to-inventory header on the platforms subview', () => {
|
||||
mockPathname = '/settings/infrastructure/platforms/truenas';
|
||||
renderWorkspace();
|
||||
|
||||
const backButton = screen.getByRole('button', { name: /Connections and Inventory/i });
|
||||
expect(backButton).toBeInTheDocument();
|
||||
expect(screen.getByText('Platform connections')).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(backButton);
|
||||
expect(navigateSpy).toHaveBeenCalledWith('/settings/infrastructure');
|
||||
});
|
||||
|
||||
it('does not render the back-to-inventory header on the inventory landing', () => {
|
||||
mockPathname = '/settings/infrastructure';
|
||||
renderWorkspace();
|
||||
|
||||
expect(screen.queryByRole('button', { name: /^Connections and Inventory$/ })).toBeNull();
|
||||
});
|
||||
|
||||
it('hides the add-system action and redirects install routes in read-only mode', () => {
|
||||
presentationPolicyIsReadOnlyMock.mockReturnValue(true);
|
||||
mockPathname = '/settings/infrastructure/install';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue