diff --git a/packages/frontend/src/components/DockerManager.vue b/packages/frontend/src/components/DockerManager.vue index f2035f5..c0748b7 100644 --- a/packages/frontend/src/components/DockerManager.vue +++ b/packages/frontend/src/components/DockerManager.vue @@ -51,11 +51,11 @@ const error = ref(null); const isDockerAvailable = ref(true); // This will now reflect remote docker availability let refreshInterval: ReturnType | null = null; let wsUnsubscribeHooks: (() => void)[] = []; // To store unsubscribe functions -// --- NEW: State for expansion --- -const expandedContainerId = ref(null); -const containerStats = ref(null); -const isStatsLoading = ref(false); -const statsError = ref(null); +// --- NEW: State for expansion (multiple allowed) --- +const expandedContainerIds = ref>(new Set()); // Use a Set to store multiple IDs +const containerStats = ref>(new Map()); // Map: containerId -> stats +const isStatsLoading = ref>(new Map()); // Map: containerId -> loading state +const statsError = ref>(new Map()); // Map: containerId -> error message // --- Computed --- @@ -133,21 +133,22 @@ const setupWsListeners = () => { // --- NEW: Listen for stats updates --- const unsubStatsUpdate = wsManager.onMessage('docker:stats:update', (payload) => { - // Ensure the update is for the currently expanded container - if (payload?.containerId === expandedContainerId.value) { + // Update stats for the specific container if it's being tracked + if (payload?.containerId && expandedContainerIds.value.has(payload.containerId)) { console.log(`[DockerManager] Received stats update for ${payload.containerId}:`, payload.stats); - containerStats.value = payload.stats as DockerStats; // Assuming payload.stats matches DockerStats - isStatsLoading.value = false; - statsError.value = null; + containerStats.value.set(payload.containerId, payload.stats as DockerStats); + isStatsLoading.value.set(payload.containerId, false); + statsError.value.set(payload.containerId, null); } }); const unsubStatsError = wsManager.onMessage('docker:stats:error', (payload) => { - if (payload?.containerId === expandedContainerId.value) { + // Update error status for the specific container if it's being tracked + if (payload?.containerId && expandedContainerIds.value.has(payload.containerId)) { console.error(`[DockerManager] Error fetching stats for ${payload.containerId}:`, payload.message); - containerStats.value = null; - isStatsLoading.value = false; - statsError.value = payload.message || t('dockerManager.stats.errorGeneric'); + containerStats.value.set(payload.containerId, null); + isStatsLoading.value.set(payload.containerId, false); + statsError.value.set(payload.containerId, payload.message || t('dockerManager.stats.errorGeneric')); } }); @@ -215,20 +216,26 @@ const sendDockerCommand = (containerId: string, command: 'start' | 'stop' | 'res }); }; -// --- NEW: Method to toggle expansion and fetch stats --- +// --- UPDATED: Method to toggle expansion for a specific container --- const toggleExpand = (containerId: string) => { - if (expandedContainerId.value === containerId) { - // Collapse - expandedContainerId.value = null; - containerStats.value = null; - statsError.value = null; - isStatsLoading.value = false; + const currentlyExpanded = expandedContainerIds.value.has(containerId); + + if (currentlyExpanded) { + // Collapse this specific container + expandedContainerIds.value.delete(containerId); + // Clear its stats data + containerStats.value.delete(containerId); + isStatsLoading.value.delete(containerId); + statsError.value.delete(containerId); + console.log(`[DockerManager] Collapsed container ${containerId}. Remaining expanded:`, Array.from(expandedContainerIds.value)); } else { - // Expand - expandedContainerId.value = containerId; - containerStats.value = null; // Clear previous stats - statsError.value = null; - isStatsLoading.value = true; + // Expand this specific container + expandedContainerIds.value.add(containerId); + // Initialize its stats state + containerStats.value.set(containerId, null); + statsError.value.set(containerId, null); + isStatsLoading.value.set(containerId, true); + console.log(`[DockerManager] Expanded container ${containerId}. All expanded:`, Array.from(expandedContainerIds.value)); // Request stats from backend if (activeSession.value && sshConnectionStatus.value === 'connected') { @@ -239,8 +246,8 @@ const toggleExpand = (containerId: string) => { }); } else { console.warn('[DockerManager] Cannot fetch stats, SSH not connected.'); - statsError.value = t('dockerManager.error.sshNotConnected'); - isStatsLoading.value = false; + statsError.value.set(containerId, t('dockerManager.error.sshNotConnected')); + isStatsLoading.value.set(containerId, false); } } }; @@ -267,14 +274,15 @@ watch([currentSessionId, sshConnectionStatus], ([newSessionId, newSshStatus], [o } clearWsListeners(); // Clear listeners on disconnect or session change // --- Add: Collapse container when session changes or disconnects --- - if (expandedContainerId.value && (newSessionId !== oldSessionId || (newSessionId && (newSshStatus === 'disconnected' || newSshStatus === 'error')))) { - console.log('[DockerManager] Session changed/disconnected, collapsing stats view.'); - expandedContainerId.value = null; - containerStats.value = null; - statsError.value = null; - isStatsLoading.value = false; + // --- Add: Collapse ALL containers when session changes or disconnects --- + if (expandedContainerIds.value.size > 0) { + console.log('[DockerManager] Session changed/disconnected, collapsing all stats views.'); + expandedContainerIds.value.clear(); + containerStats.value.clear(); + statsError.value.clear(); + isStatsLoading.value.clear(); } - // --- End Add --- + // --- End Add --- } // --- Setup listeners and fetch data when session is active AND SSH is connected --- @@ -380,11 +388,11 @@ onUnmounted(() => {