diff --git a/source/compose.manager/include/ComposeList.php b/source/compose.manager/include/ComposeList.php index a176f5a..72fc3c9 100755 --- a/source/compose.manager/include/ComposeList.php +++ b/source/compose.manager/include/ComposeList.php @@ -24,38 +24,23 @@ $composeFile = $stackInfo->composeFilePath ?? ($stackInfo->composeSource . '/' . COMPOSE_FILE_NAMES[0]); $overridePath = $stackInfo->getOverridePath(); - // Use StackInfo's getDefinedServices for accurate service count - $definedServicesList = $stackInfo->getDefinedServices(); - $definedServices = count($definedServicesList); - - $projectContainers = $stackInfo->getContainerList(); - $runningCount = 0; - $stoppedCount = 0; - $pausedCount = 0; - $restartingCount = 0; - - foreach ($projectContainers as $ct) { - $ctState = $ct['State'] ?? ''; - if ($ctState === 'running') { - $runningCount++; - } elseif ($ctState === 'exited') { - $stoppedCount++; - } elseif ($ctState === 'paused') { - $pausedCount++; - } elseif ($ctState === 'restarting') { - $restartingCount++; - } - } - - // Container counts - $actualContainerCount = count($projectContainers); - $containerCount = $definedServices > 0 ? $definedServices : $actualContainerCount; + // getStackState() internally calls getContainerCounts(), which caches + // the result. Calling getContainerCounts() afterwards is free. + $stackState = $stackInfo->getStackState(); + $counts = $stackInfo->getContainerCounts(); + + $runningCount = $counts['running']; + $stoppedCount = $counts['stopped']; + $pausedCount = $counts['paused']; + $restartingCount = $counts['restarting']; + $actualContainerCount = $counts['total']; + $containerCount = $counts['total']; // Collect container names for the hide-from-docker feature (data attribute) $containerNamesList = []; // Collect short container IDs for CPU/MEM load mapping (docker stats uses 12-char short IDs) $containerIdsList = []; - foreach ($projectContainers as $ct) { + foreach ($stackInfo->getContainerList() as $ct) { $n = $ct['Names'] ?? ''; if ($n) $containerNamesList[] = $n; $ctId = $ct['ID'] ?? ''; @@ -124,24 +109,12 @@ $hasInvalidIndirect = ($invalidIndirectPath !== null && trim($invalidIndirectPath) !== ''); $invalidIndirectPathHtml = htmlspecialchars($invalidIndirectPath ?? '', ENT_QUOTES, 'UTF-8'); - // Status like Docker tab (started/stopped with icon) - $status = $isrunning ? ($runningCount == $containerCount ? 'started' : 'partial') : 'stopped'; - // Use exclamation icon for partial state so it looks like a warning - if ($status === 'partial') { - $shape = 'exclamation-circle'; - } elseif ($isrunning) { - $shape = 'play'; - } else { - $shape = 'square'; - } - $color = $status == 'started' ? 'green-text' : ($status == 'partial' ? 'orange-text' : 'grey-text'); - // Use 'partial' outer class for partial state to allow correct styling - $outerClass = $isrunning ? ($runningCount == $containerCount ? 'started' : 'partial') : 'stopped'; - - $statusLabel = $status; - if ($status == 'partial') { - $statusLabel = "partial ($runningCount/$containerCount)"; - } + // Status icon, label, color — derived from centralized getStackState() + $status = $stackState['state']; + $shape = $stackState['shape']; + $color = $stackState['color']; + $outerClass = $status; + $statusLabel = $stackState['label']; // Get stack started_at timestamp via StackInfo $stackStartedAt = $stackInfo->getStartedAt(); diff --git a/source/compose.manager/include/ComposeManager.php b/source/compose.manager/include/ComposeManager.php index c384f77..51e284f 100755 --- a/source/compose.manager/include/ComposeManager.php +++ b/source/compose.manager/include/ComposeManager.php @@ -275,6 +275,7 @@ function compose_manager_cpu_spec_count($cpuSpec) +