diff --git a/docs/release-control/v6/internal/subsystems/storage-recovery.md b/docs/release-control/v6/internal/subsystems/storage-recovery.md index e81b64526c..2fca9d5a39 100644 --- a/docs/release-control/v6/internal/subsystems/storage-recovery.md +++ b/docs/release-control/v6/internal/subsystems/storage-recovery.md @@ -648,6 +648,10 @@ recovery-specific mini report. Recovery summary cards should prefer concise counts, bars, and badge-backed coverage cues over tall explanatory copy blocks so the protected-item table takes over the page at roughly the same visual density as the infrastructure and workloads monitoring surfaces. +That same summary rule also applies within individual cards: recovery posture, +freshness, attention, footprint, and history cards should favor compact rows +and metric lists over stacked prose callouts so the summary strip reads like +Pulse monitoring telemetry rather than a page-local narrative panel. That same inventory surface should also follow the established monitoring-table scan pattern in its first column. Protected-item rows should lead with a clear status cue, the primary item name, and compact badge-backed item/platform @@ -658,6 +662,11 @@ not just local row styling. When the protected-item page mixes healthy and problematic coverage, the table body should section attention items ahead of healthy coverage so operators can scan the recovery estate the way they scan other grouped monitoring tables in Pulse. +That same table-shell contract must avoid duplicate framing once the view tabs +already establish the active workspace. `RecoveryProtectedInventorySection.tsx` +should keep page/count/sort orientation inside a slim table-shell status row +and let the filter strip lead directly into the grid instead of reintroducing a +second large inventory header card above the same table. That shared unified-resource dependency now also includes policy-governed resource metadata on the frontend decode path: storage and recovery surfaces that route through `frontend-modern/src/hooks/useUnifiedResources.ts` must diff --git a/frontend-modern/src/components/Recovery/Recovery.tsx b/frontend-modern/src/components/Recovery/Recovery.tsx index 2750684675..44b28c8230 100644 --- a/frontend-modern/src/components/Recovery/Recovery.tsx +++ b/frontend-modern/src/components/Recovery/Recovery.tsx @@ -485,13 +485,13 @@ const Recovery: Component = () => { />
-
+
setWorkspaceView(value as RecoveryWorkspaceView)} ariaLabel="Recovery data view" - listClass="flex flex-wrap items-center gap-3" - tabClass="min-h-9 px-2 py-2 text-sm" + listClass="flex flex-wrap items-center gap-2" + tabClass="min-h-8 px-2.5 py-1.5 text-sm" tabs={[ { value: 'inventory', diff --git a/frontend-modern/src/components/Recovery/RecoveryProtectedInventorySection.tsx b/frontend-modern/src/components/Recovery/RecoveryProtectedInventorySection.tsx index 3e727e01ed..e7223f9e70 100644 --- a/frontend-modern/src/components/Recovery/RecoveryProtectedInventorySection.tsx +++ b/frontend-modern/src/components/Recovery/RecoveryProtectedInventorySection.tsx @@ -239,15 +239,34 @@ export const RecoveryProtectedInventorySection: Component< -
-
-
Protected inventory
-
- +
+
+
+ {sortedRollups().length} of {props.rollups().length} items shown + + Page {protectedPage()} / {protectedTotalPages()} + + + Sort:{' '} + + {protectedSortCol() === 'lastBackup' + ? 'Latest point' + : protectedSortCol() === 'item' + ? 'Item' + : protectedSortCol() === 'type' + ? 'Item type' + : protectedSortCol() === 'platform' + ? 'Platform' + : 'Outcome'} + {' '} + {protectedSortDir()} + +
+
0}> {props.rollupsSummary().stale} stale @@ -263,7 +282,7 @@ export const RecoveryProtectedInventorySection: Component<
-
+
props.setQueryFilter(value)} placeholder={getRecoveryProtectedSearchPlaceholder()} class="w-full" - inputClass="py-2.5 text-sm" + inputClass="py-2 text-sm" clearOnEscape history={{ storageKey: STORAGE_KEYS.RECOVERY_SEARCH_HISTORY, @@ -284,9 +303,9 @@ export const RecoveryProtectedInventorySection: Component< onToggle: () => setProtectedFiltersOpen((open) => !open), count: protectedActiveFilterCount(), }} - showFilters={!props.isMobile || protectedFiltersOpen()} - searchRowClass="flex w-full items-center gap-3" - toolbarClass="gap-3 lg:flex-nowrap" + showFilters={!props.isMobile || protectedFiltersOpen()} + searchRowClass="flex w-full items-center gap-3" + toolbarClass="gap-3 lg:flex-nowrap" > (