e.key === 'Escape' && (searchQuery = '')} class="pl-8 h-8 w-48 text-sm" />
{#if $canAccess('containers', 'create')} {/if} {#if batchUpdateContainerIds.length > 0} {/if} {#if $canAccess('containers', 'remove')} confirmPrune = open} unstyled > {#snippet children({ open })} {/snippet} {/if}
{#if selectedContainers.size > 0}
{selectedInFilter.length} selected {#if selectedStopped.length > 0 && $canAccess('containers', 'start')} confirmBulkStart = open} > {#snippet children({ open })} Start {/snippet} {/if} {#if selectedRunning.length > 0 && $canAccess('containers', 'stop')} confirmBulkStop = open} > {#snippet children({ open })} Stop {/snippet} confirmBulkPause = open} > {#snippet children({ open })} Pause {/snippet} {/if} {#if selectedPaused.length > 0 && $canAccess('containers', 'start')} confirmBulkUnpause = open} > {#snippet children({ open })} Unpause {/snippet} {/if} {#if $canAccess('containers', 'restart')} confirmBulkRestart = open} > {#snippet children({ open })} Restart {/snippet} {/if} {#if $canAccess('containers', 'remove')} confirmBulkRemove = open} > {#snippet children({ open })} Remove {/snippet} {/if} {#if selectedHaveUpdates} {/if} {#if bulkActionInProgress} {/if}
{/if} {#if $environments.length === 0 || !$currentEnvironment} {:else if !loading && containers.length === 0} {:else}
{ sortField = state.field as SortField; sortDirection = state.direction; }} highlightedKey={highlightedRowId} rowClass={(container) => { let classes = ''; if (currentLogsContainerId === container.id) classes += 'bg-blue-500/10 hover:bg-blue-500/15 '; if (currentTerminalContainerId === container.id) classes += 'bg-green-500/10 hover:bg-green-500/15 '; if ($appSettings.highlightUpdates && containersWithUpdatesSet.has(container.id)) classes += 'has-update '; return classes; }} onRowClick={(container, e) => { if (activeLogs.length > 0 || activeTerminals.length > 0) { selectContainer(container); } highlightedRowId = highlightedRowId === container.id ? null : container.id; }} > {#snippet cell(column, container, rowState)} {@const ports = formatPorts(container.ports)} {@const stack = getComposeProject(container.labels)} {#if column.id === 'name'} {container.name} {:else if column.id === 'image'}
{#if containersWithUpdatesSet.has(container.id)} {/if} {container.image}
{:else if column.id === 'state'} {@const StateIcon = getStatusIcon(container.state)} {container.state} {:else if column.id === 'health'} {#if container.health}
{#if container.health === 'healthy'} {:else if container.health === 'unhealthy'} {:else} {/if}
{:else}
-
{/if} {:else if column.id === 'uptime'} {formatUptime(container.status)} {:else if column.id === 'restartCount'} {#if container.restartCount > 0} {container.restartCount} {:else} - {/if} {:else if column.id === 'cpu'}
{#if containerStats.get(container.id)} {@const stats = containerStats.get(container.id)} {stats.cpuPercent.toFixed(1)}% {:else if container.state === 'running'} ... {:else} - {/if}
{:else if column.id === 'memory'}
{#if containerStats.get(container.id)} {@const stats = containerStats.get(container.id)} {formatBytes(stats.memoryUsage)} {:else if container.state === 'running'} ... {:else} - {/if}
{:else if column.id === 'networkIO'}
{#if containerStats.get(container.id)} {@const stats = containerStats.get(container.id)} {formatBytes(stats.networkRx, 0)} {formatBytes(stats.networkTx, 0)} {:else if container.state === 'running'} ... {:else} - {/if}
{:else if column.id === 'diskIO'}
{#if containerStats.get(container.id)} {@const stats = containerStats.get(container.id)} r{formatBytes(stats.blockRead, 0)} w{formatBytes(stats.blockWrite, 0)} {:else if container.state === 'running'} ... {:else} - {/if}
{:else if column.id === 'ip'} {getContainerIp(container.networks)} {:else if column.id === 'ports'} {#if ports.length > 0}
{#each ports.slice(0, 2) as port} {@const url = currentEnvDetails ? getPortUrl(port.publicPort) : null} {#if url} e.stopPropagation()} class="inline-flex items-center gap-0.5 text-xs bg-muted hover:bg-blue-500/20 hover:text-blue-500 px-1 py-0.5 rounded transition-colors" title="Open {url} in new tab" > {port.display} {:else} {port.display} {/if} {/each} {#if ports.length > 2} +{ports.length - 2} {/if}
{:else} - {/if} {:else if column.id === 'autoUpdate'} {#if autoUpdateSettings.get(container.name)?.enabled} {@const settings = autoUpdateSettings.get(container.name)}
{settings?.label} {#if envHasScanning} {@const criteria = settings?.vulnerabilityCriteria || 'never'} {@const icon = vulnerabilityCriteriaIcons[criteria]} {#if icon} {@const IconComponent = icon.component} {/if} {/if}
{:else} - {/if} {:else if column.id === 'stack'} {#if stack} {stack} {:else} - {/if} {:else if column.id === 'actions'}
{#if containersWithUpdatesSet.has(container.id)} {/if} {#if container.state === 'running' || container.state === 'restarting'} {#if $canAccess('containers', 'stop')} stopContainer(container.id)} onOpenChange={(open) => confirmStopId = open ? container.id : null} > {#snippet children({ open })} {/snippet} {#if container.state === 'running'} {/if} {/if} {:else if container.state === 'paused'} {#if $canAccess('containers', 'start')} {/if} {:else} {#if $canAccess('containers', 'start')} {/if} {/if} {#if $canAccess('containers', 'restart')} restartContainer(container.id)} onOpenChange={(open) => confirmRestartId = open ? container.id : null} > {#snippet children({ open })} {/snippet} {/if} {#if container.state === 'running' && $canAccess('containers', 'exec')} {/if} {#if $canAccess('containers', 'create')} {/if} {#if $canAccess('containers', 'logs')} {#if hasActiveLogs(container.id)} {:else} {/if} {/if} {#if container.state === 'running' && $canAccess('containers', 'exec')} {#if hasActiveTerminal(container.id)} {:else} { terminalPopoverStates[container.id] = open; }}> e.stopPropagation()} class="p-0.5 rounded hover:bg-muted transition-colors opacity-70 hover:opacity-100 cursor-pointer" >
{container.name}
{shellOptions.find(o => o.value === terminalShell)?.label || 'Select'} {#each shellOptions as option} {option.label} {/each}
{userOptions.find(o => o.value === terminalUser)?.label || 'Select'} {#each userOptions as option} {option.label} {/each}
{/if} {/if} {#if $canAccess('containers', 'remove')} removeContainer(container.id)} onOpenChange={(open) => confirmDeleteId = open ? container.id : null} > {#snippet children({ open })} {/snippet} {/if} {#if operationError?.id === container.id}
{operationError.message}
{/if}
{/if} {/snippet}
{#if layoutMode === 'vertical' && (currentLogsContainerId || currentTerminalContainerId)}
{#if currentLogsContainerId} {@const activeLog = activeLogs.find(l => l.containerId === currentLogsContainerId)} {#if activeLog}
closeLogs(activeLog.containerId)} />
{/if} {/if} {#if currentTerminalContainerId} {@const activeTerminal = activeTerminals.find(t => t.containerId === currentTerminalContainerId)} {#if activeTerminal}
closeTerminal(activeTerminal.containerId)} />
{/if} {/if}
{/if}
{#if layoutMode === 'horizontal'} {#if currentLogsContainerId} {@const activeLog = activeLogs.find(l => l.containerId === currentLogsContainerId)} {#if activeLog} closeLogs(activeLog.containerId)} /> {/if} {/if} {#if currentTerminalContainerId} {@const activeTerminal = activeTerminals.find(t => t.containerId === currentTerminalContainerId)} {#if activeTerminal} closeTerminal(activeTerminal.containerId)} /> {/if} {/if} {/if} {/if}
(showCreateModal = false)} onSuccess={fetchContainers} /> (showEditModal = false)} onSuccess={fetchContainers} /> { // Update the container name in the local state inspectContainerName = newName; // Refresh the container list fetchContainers(); }} /> showFileBrowserModal = false} />