feat: add sidebar update indicator toggle and Stack Health badge (#1570)

* feat: add sidebar update indicator toggle and Stack Health badge

- Add image_update_sidebar_indicators setting (default off, node-scoped)
- Gate the Updates filter chip and sidebar status indicators on the setting
- Add "Update available" badge to Stack Health table (always visible)
- Extend ImageUpdateStatus with sidebarIndicators boolean
- Poll /api/image-updates/status alongside /detail in useImageUpdates
- React to SENCHO_SETTINGS_CHANGED for instant toggle propagation
- Reset sidebar state on node switch; generation-guard stale responses
- Disable toggle when status is null (loading) or field is absent (old node)
- Wire stackUpdates through ViewRouter → HomeDashboard → StackHealthTable
- Update settings registry, operator docs, and sidebar/dashboard docs

* fix: guard against stale node renders, memo drift, and cross-node error toasts

- Track owning node ID in useImageUpdates state so React never renders
  node B with node A's data before the passive effect resets (P2)
- Replace incorrect stackUpdates dependency with sidebarStackUpdates in
  chipFilteredFiles useMemo (P3)
- Guard the error toast in handleSidebarIndicatorsChange so a stale PATCH
  failure from node A does not surface while viewing node B (P3)

* fix: default sidebar update indicators to on (opt-out)

The sidebar indicators are a safe convenience that most users want.
Switching the default from off to on matches the opt-out convention
used by prune_on_update, reclaim_hero, and health_gate_enabled.
This commit is contained in:
Anso
2026-07-05 02:52:17 -04:00
committed by GitHub
parent c677b8bb66
commit bb35c1bc92
19 changed files with 256 additions and 47 deletions
+5 -1
View File
@@ -128,6 +128,8 @@ export default function EditorLayout() {
toggleBulkMode, toggleSelect, clearSelection, handleBulkAction,
stackUpdates,
fetchImageUpdates,
sidebarIndicators,
sidebarStackUpdates,
pinned,
isCollapsed, toggleCollapse,
remoteSearchLoading,
@@ -669,7 +671,7 @@ export default function EditorLayout() {
stackLabelMap,
stackStatuses: stackStatuses as Record<string, StackRowStatus | undefined>,
stackCounts,
stackUpdates,
stackUpdates: sidebarStackUpdates,
gitSourcePendingMap,
pinnedFiles: pinned,
isCollapsed,
@@ -697,6 +699,7 @@ export default function EditorLayout() {
onToggleSelect={toggleSelect}
onClearSelection={clearSelection}
onBulkAction={handleBulkAction}
showUpdatesChip={sidebarIndicators}
/>
);
@@ -777,6 +780,7 @@ export default function EditorLayout() {
fleetTab={fleetTab}
onFleetTabConsumed={() => setFleetTab(null)}
renderEditor={renderEditor}
stackUpdates={stackUpdates}
/>
</div>
);