mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-27 10:46:51 +00:00
feat: live-refresh stack detail container and health state (#1712)
* feat: live-refresh stack detail container and health state Keep the open stack's container cards in sync with Docker via state-invalidate events and a visibility-aware poll, without reloading compose, env, or logs. * fix: remove unused _ms parameter from visibilityInterval mock Fixes the @typescript-eslint/no-unused-vars ESLint error in CI lint job. * fix: stop stack detail live-refresh when leaving the editor Gate poll and invalidate handling on editor visibility, refresh the current selection after a mid-flight stack switch, and skip starting visibilityInterval when the tab is already hidden. * fix: avoid return in finally for stack detail live-refresh Satisfy no-unsafe-finally by gating the trailing refresh with a positive condition instead of early returns inside the finally block.
This commit is contained in:
@@ -17,6 +17,7 @@ import { useUrlSync } from './EditorLayout/hooks/useUrlSync';
|
||||
import { shouldClearPendingDetailStack } from './EditorLayout/mobile-pending-detail';
|
||||
import { useOverlayState } from './EditorLayout/hooks/useOverlayState';
|
||||
import { useStackActions, NODE_SWITCH_PENDING_TOKEN } from './EditorLayout/hooks/useStackActions';
|
||||
import { useSelectedStackLiveRefresh } from './EditorLayout/hooks/useSelectedStackLiveRefresh';
|
||||
import { useTheme } from '@/hooks/use-theme';
|
||||
import { ThemeQuickSwitch } from './theme/ThemeQuickSwitch';
|
||||
import { useNotifications } from './EditorLayout/hooks/useNotifications';
|
||||
@@ -296,6 +297,16 @@ export default function EditorLayout() {
|
||||
// Wire the ref now that stackActions is available
|
||||
resetEditorStateRef.current = stackActions.resetEditorState;
|
||||
|
||||
const { syncStale: containersSyncStale, retrySync: retryContainersSync } = useSelectedStackLiveRefresh({
|
||||
selectedFile,
|
||||
activeNodeId: activeNode?.id,
|
||||
isDetailVisible: activeView === 'editor',
|
||||
containers,
|
||||
composeContent: content,
|
||||
containersLoadStatus,
|
||||
refreshSelectedContainers: stackActions.refreshSelectedContainers,
|
||||
});
|
||||
|
||||
// A failed health gate routes into the existing recovery affordance: record
|
||||
// a failure for the stack so RecoveryChip/RecoveryPanel offer the same
|
||||
// explicit, user-confirmed rollback as any failed operation. Keyed by gate
|
||||
@@ -623,6 +634,8 @@ export default function EditorLayout() {
|
||||
containersLoadStatus={containersLoadStatus}
|
||||
containersLoadError={containersLoadError}
|
||||
onRetryContainersLoad={() => { void stackActions.retryContainersLoad(); }}
|
||||
containersSyncStale={containersSyncStale}
|
||||
onRetrySync={retryContainersSync}
|
||||
containerStats={containerStats}
|
||||
containerStatsError={containerStatsError}
|
||||
content={content}
|
||||
@@ -684,10 +697,10 @@ export default function EditorLayout() {
|
||||
onRefreshState={async () => {
|
||||
if (!selectedFile) return;
|
||||
const name = selectedFile.replace(/\.(yml|yaml)$/, '');
|
||||
const ok = await stackActions.refreshSelectedContainers(name, selectedFile);
|
||||
const outcome = await stackActions.refreshSelectedContainers(name, selectedFile);
|
||||
await refreshStacks(true);
|
||||
if (ok) toast.success('Refreshed container state.');
|
||||
else toast.error('Could not refresh container state.');
|
||||
if (outcome === 'ok') toast.success('Refreshed container state.');
|
||||
else if (outcome === 'failed') toast.error('Could not refresh container state.');
|
||||
}}
|
||||
onDismissRecovery={() => { if (selectedFile) dismissActionResult(selectedFile); }}
|
||||
panelStartedAt={panelStartedAt}
|
||||
|
||||
Reference in New Issue
Block a user