From 659e9d66c8ff1bfc89319a55d301e005d5089671 Mon Sep 17 00:00:00 2001 From: Brad Groux <3053586+BradGroux@users.noreply.github.com> Date: Wed, 2 Sep 2026 20:19:08 -0500 Subject: [PATCH] feat: reorganize Maintenance settings workflows (#1329) --- .../SETTINGS-INFORMATION-ARCHITECTURE.md | 2 +- .../settings-maintenance-mantine.test.tsx | 11 +- .../settings/tabs/MaintenanceTab.tsx | 314 ++++++++++-------- 3 files changed, 176 insertions(+), 151 deletions(-) diff --git a/docs/design/SETTINGS-INFORMATION-ARCHITECTURE.md b/docs/design/SETTINGS-INFORMATION-ARCHITECTURE.md index 902c16c7..1bd008b3 100644 --- a/docs/design/SETTINGS-INFORMATION-ARCHITECTURE.md +++ b/docs/design/SETTINGS-INFORMATION-ARCHITECTURE.md @@ -26,7 +26,7 @@ In Board Only mode, General, Board, and Tasks are marked as the primary path. Ev - `SettingsLocalNav` is reserved for related sections on a long page. It uses in-page anchors, remains horizontally scrollable at narrow widths, and does not promote subsections into global destinations. - `SettingsHelpText`, `SettingsErrorText`, `SettingsUnit`, and `SettingsActionGroup` standardize secondary explanation, validation, numeric units, routine transfer actions, and destructive actions. -General, Board, Tasks, and Data are the reference migrations. Data demonstrates continuous local navigation; simpler pages omit it. Agents extends that pattern with anchored Providers, Compatibility, Profiles, Health, and Policies workflows. Notifications uses Health, Buzz, Reply Adapters, Delivery, and Preferences to separate diagnostics and sensitive delivery configuration from routine choices. Multi-user uses Workspace, Members, Invitations, Devices, and API Access to keep routine collaboration separate from sensitive device and credential controls. Maintenance still requires dedicated workflow decomposition because it combines several independent operational surfaces. +General, Board, Tasks, and Data are the reference migrations. Data demonstrates continuous local navigation; simpler pages omit it. Agents extends that pattern with anchored Providers, Compatibility, Profiles, Health, and Policies workflows. Notifications uses Health, Buzz, Reply Adapters, Delivery, and Preferences to separate diagnostics and sensitive delivery configuration from routine choices. Multi-user uses Workspace, Members, Invitations, Devices, and API Access to keep routine collaboration separate from sensitive device and credential controls. Maintenance uses Overview, Cleanup, Logs, Backup/Restore, and Lifecycle to separate routine diagnostics from destructive cleanup and advanced data movement. ## Focus and responsive behavior diff --git a/web/src/__tests__/settings-maintenance-mantine.test.tsx b/web/src/__tests__/settings-maintenance-mantine.test.tsx index 8b987e3c..7eae7963 100644 --- a/web/src/__tests__/settings-maintenance-mantine.test.tsx +++ b/web/src/__tests__/settings-maintenance-mantine.test.tsx @@ -185,9 +185,14 @@ describe('Maintenance settings tab', () => { }); it('renders health, storage, cleanup preview, logs, lifecycle, and backup controls', async () => { - renderWithProviders(); + const { container } = renderWithProviders(); - expect(await screen.findByText('Maintenance Center')).toBeDefined(); + expect(await screen.findByRole('heading', { name: 'Maintenance' })).toBeDefined(); + expect(screen.getByRole('navigation', { name: 'Maintenance settings sections' })).toBeDefined(); + expect(screen.getByRole('link', { name: 'Backup/Restore' }).getAttribute('href')).toBe( + '#maintenance-backup' + ); + expect(container.querySelectorAll('[data-settings-section]')).toHaveLength(5); expect(screen.getByText('Runtime storage is readable and writable.')).toBeDefined(); expect(screen.getByText('Archived report')).toBeDefined(); expect( @@ -232,7 +237,7 @@ describe('Maintenance settings tab', () => { it('submits backup export with optional workspace scope', async () => { renderWithProviders(); - await screen.findByText('Maintenance Center'); + await screen.findByRole('heading', { name: 'Maintenance' }); fireEvent.change(screen.getByRole('textbox', { name: 'SQLite path' }), { target: { value: '/tmp/veritas.db' }, }); diff --git a/web/src/components/settings/tabs/MaintenanceTab.tsx b/web/src/components/settings/tabs/MaintenanceTab.tsx index 737b115f..6eb11782 100644 --- a/web/src/components/settings/tabs/MaintenanceTab.tsx +++ b/web/src/components/settings/tabs/MaintenanceTab.tsx @@ -40,6 +40,7 @@ import type { MaintenanceHealthCheck, MaintenanceStorageCategory, } from '@veritas-kanban/shared'; +import { SettingsLocalNav, SettingsPage, SettingsSection } from '../shared'; const HEALTH_COLORS: Record = { ok: 'green', @@ -116,39 +117,44 @@ function HealthCheckList({ checks }: { checks: MaintenanceHealthCheck[] }) { function StorageTable({ categories }: { categories: MaintenanceStorageCategory[] }) { return ( - - - - Artifact - Items - Size - Cleanup - Last used - - - - {categories.map((category) => ( - - - - {category.label} - - - {category.retainedReason} - - - {category.itemCount} - {formatBytes(category.bytes)} - - 0 ? 'yellow' : 'gray'} variant="light"> - {category.cleanupEligibleCount} - - - {formatDate(category.lastUsedAt)} + +
+ + + Artifact + Items + Size + Cleanup + Last used - ))} - -
+ + + {categories.map((category) => ( + + + + {category.label} + + + {category.retainedReason} + + + {category.itemCount} + {formatBytes(category.bytes)} + + 0 ? 'yellow' : 'gray'} + variant="light" + > + {category.cleanupEligibleCount} + + + {formatDate(category.lastUsedAt)} + + ))} + + + ); } @@ -309,17 +315,10 @@ export function MaintenanceTab() { : 0; return ( - - -
- - Maintenance Center - - - {summary.storageMode} storage, {summary.mode} mode, refreshed{' '} - {formatDate(summary.generatedAt)} - -
+ -
- - - - -
- - Logs - - -