refactor(sidebar): rebuild footer as priority-driven Ops Pulse strip (#1178)

* refactor(sidebar): rebuild footer as priority-driven Ops Pulse strip

Replace the simple notification ticker with a derived activity summary that
picks one of six states (active-op, failure, automation, recent-event,
quiet-live, disconnected) and routes per-state clicks to logs, schedules,
or activity. The hook owns the cascade; the component is pure presentation;
EditorLayout owns wiring.

Failure detection covers unread errors in the last 24h; recent-event is
limited to non-error stack notifications in the last hour; automation reads
the next /scheduled-tasks?action=update run and a debounced state-invalidate
listener; the deploy-panel composite key is used for elapsed-time tracking
so close-then-immediately-reopen counts as a new session.

* refactor(sidebar): apply Ops Pulse audit fixes

- countEnabledAutoUpdates now defaults missing autoUpdateSettings entries to
  enabled, matching the backend's getStackAutoUpdateSettingsForNode contract.
  Previously the automation state could not render even with the documented
  per-row default-true.
- findFailure now requires a stack_name so the sidebar does not select a
  system-level error whose click would no-op through navigateToNotification.
  System errors continue to surface via the top-bar NotificationPanel.
- DeployPanelState gains a monotonic sessionId sourced from the existing
  internal counter, and the new usePanelSessionStartedAt hook keys the
  elapsed-time tracker off it so a same-stack rerun always resets even when
  isOpen stays true across succeeded then preparing.
- buildConfig splits quiet-live out of the default and adds an exhaustiveness
  guard so future SidebarActivitySummary variants fail to compile.
- New unit tests cover the default-true aggregation, the same-stack session
  reset, the non-stack failure guard, and the useNextAutoUpdateRun debounce
  and cleanup paths. Frontend suite: 276 / 276 pass.
This commit is contained in:
Anso
2026-05-23 15:43:06 -04:00
committed by GitHub
parent 21ec5e7e0a
commit bb44db0cb1
11 changed files with 901 additions and 83 deletions
@@ -1,9 +1,8 @@
import { useState, useCallback, type ReactNode } from 'react';
import { Command } from '@/components/ui/command';
import { ScrollArea } from '@/components/ui/scroll-area';
import type { NotificationItem } from '@/components/dashboard/types';
import { SidebarActions } from './SidebarActions';
import { SidebarActivityTicker } from './SidebarActivityTicker';
import { SidebarActivityTicker, type SidebarActivityAction } from './SidebarActivityTicker';
import { SidebarBrand } from './SidebarBrand';
import { SidebarBulkBar } from './SidebarBulkBar';
import { SidebarFilterChips, type FilterCounts } from './SidebarFilterChips';
@@ -11,6 +10,7 @@ import { SidebarSearch } from './SidebarSearch';
import { StackList, type StackListProps } from './StackList';
import type { FilterChip } from './sidebar-types';
import type { BulkAction } from '@/hooks/useBulkStackActions';
import type { SidebarActivitySummary } from './useSidebarActivitySummary';
export interface StackSidebarProps {
isDarkMode: boolean;
@@ -25,9 +25,8 @@ export interface StackSidebarProps {
filterCounts: FilterCounts;
onFilterChipChange: (chip: FilterChip) => void;
list: StackListProps;
notifications: NotificationItem[];
tickerConnected: boolean;
onOpenActivity: () => void;
activitySummary: SidebarActivitySummary;
onActivityAction: (action: SidebarActivityAction) => void;
bulkMode: boolean;
selectedFiles: Set<string>;
isPaid: boolean;
@@ -41,7 +40,7 @@ export function StackSidebar(props: StackSidebarProps) {
const {
isDarkMode, nodeSwitcherSlot, createStackSlot, onScan, isScanning, canCreate,
searchQuery, onSearchChange, filterChip, filterCounts, onFilterChipChange,
list, notifications, tickerConnected, onOpenActivity,
list, activitySummary, onActivityAction,
bulkMode, selectedFiles, isPaid, onToggleBulkMode, onToggleSelect, onClearSelection, onBulkAction,
} = props;
@@ -97,9 +96,8 @@ export function StackSidebar(props: StackSidebarProps) {
</ScrollArea>
</Command>
<SidebarActivityTicker
notifications={notifications}
connected={tickerConnected}
onNavigate={onOpenActivity}
summary={activitySummary}
onAction={onActivityAction}
/>
</div>
);