mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-18 14:33:19 +00:00
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:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { Button } from './ui/button';
|
||||
import { Plus } from 'lucide-react';
|
||||
import { UserProfileDropdown } from './UserProfileDropdown';
|
||||
@@ -32,6 +32,10 @@ import { useDeployFeedback } from '@/context/DeployFeedbackContext';
|
||||
import { useTrivyStatus } from '@/hooks/useTrivyStatus';
|
||||
import { StackSidebar } from '@/components/sidebar/StackSidebar';
|
||||
import type { StackRowStatus } from '@/components/sidebar/stack-status-utils';
|
||||
import { useSidebarActivitySummary, countEnabledAutoUpdates } from '@/components/sidebar/useSidebarActivitySummary';
|
||||
import { useNextAutoUpdateRun } from '@/components/sidebar/useNextAutoUpdateRun';
|
||||
import { usePanelSessionStartedAt } from '@/components/sidebar/usePanelSessionStartedAt';
|
||||
import type { SidebarActivityAction } from '@/components/sidebar/SidebarActivityTicker';
|
||||
import { useComposeDiffPreviewEnabled } from '@/hooks/use-compose-diff-preview-enabled';
|
||||
import { toast } from '@/components/ui/toast-store';
|
||||
|
||||
@@ -39,7 +43,7 @@ export default function EditorLayout() {
|
||||
const { isAdmin, can } = useAuth();
|
||||
const { isPaid, license } = useLicense();
|
||||
const { status: trivy } = useTrivyStatus();
|
||||
const { runWithLog } = useDeployFeedback();
|
||||
const { runWithLog, panelState } = useDeployFeedback();
|
||||
|
||||
const editorState = useEditorViewState();
|
||||
const {
|
||||
@@ -64,6 +68,7 @@ export default function EditorLayout() {
|
||||
|
||||
const stackListState = useStackListState();
|
||||
const {
|
||||
files,
|
||||
selectedFile,
|
||||
isLoading,
|
||||
stackActions: stackActionMap,
|
||||
@@ -71,6 +76,7 @@ export default function EditorLayout() {
|
||||
searchQuery, setSearchQuery,
|
||||
stackStatuses,
|
||||
stackLabelMap,
|
||||
autoUpdateSettings,
|
||||
filterChip, setFilterChip,
|
||||
bulkMode,
|
||||
selectedFiles,
|
||||
@@ -178,6 +184,40 @@ export default function EditorLayout() {
|
||||
pendingLogsRef,
|
||||
} = stackActions;
|
||||
|
||||
const panelStartedAt = usePanelSessionStartedAt(panelState);
|
||||
|
||||
const autoUpdateEnabledCount = useMemo(
|
||||
() => countEnabledAutoUpdates(files, autoUpdateSettings),
|
||||
[files, autoUpdateSettings],
|
||||
);
|
||||
|
||||
const nextAutoUpdateRunAt = useNextAutoUpdateRun();
|
||||
const activitySummary = useSidebarActivitySummary({
|
||||
notifications,
|
||||
tickerConnected,
|
||||
panelState,
|
||||
panelStartedAt,
|
||||
autoUpdateEnabledCount,
|
||||
totalStackCount: files.length,
|
||||
nextAutoUpdateRunAt,
|
||||
});
|
||||
|
||||
const handleActivityAction = useCallback((action: SidebarActivityAction) => {
|
||||
switch (action.kind) {
|
||||
case 'open-stack-notification':
|
||||
stackActions.navigateToNotification(action.summary.notif);
|
||||
return;
|
||||
case 'open-auto-updates':
|
||||
setActiveView('auto-updates');
|
||||
return;
|
||||
case 'open-activity':
|
||||
setActiveView('global-observability');
|
||||
return;
|
||||
case 'noop':
|
||||
return;
|
||||
}
|
||||
}, [stackActions, setActiveView]);
|
||||
|
||||
const loadingAction = selectedFile ? (stackActionMap[selectedFile] ?? null) : null;
|
||||
const stackName = selectedFile || '';
|
||||
|
||||
@@ -303,9 +343,8 @@ export default function EditorLayout() {
|
||||
if (node) void stackActions.loadFileOnNode(node, file);
|
||||
},
|
||||
}}
|
||||
notifications={notifications}
|
||||
tickerConnected={tickerConnected}
|
||||
onOpenActivity={() => setActiveView('global-observability')}
|
||||
activitySummary={activitySummary}
|
||||
onActivityAction={handleActivityAction}
|
||||
bulkMode={bulkMode}
|
||||
selectedFiles={selectedFiles}
|
||||
isPaid={isPaid}
|
||||
|
||||
Reference in New Issue
Block a user