diff --git a/app/Livewire/Server/DockerCleanupExecutions.php b/app/Livewire/Server/DockerCleanupExecutions.php new file mode 100644 index 000000000..56d613064 --- /dev/null +++ b/app/Livewire/Server/DockerCleanupExecutions.php @@ -0,0 +1,132 @@ +user()->currentTeam()->id; + + return [ + "echo-private:team.{$teamId},DockerCleanupDone" => 'refreshExecutions', + ]; + } + + public function mount(Server $server) + { + $this->server = $server; + $this->refreshExecutions(); + } + + public function refreshExecutions(): void + { + $this->executions = $this->server->dockerCleanupExecutions() + ->orderBy('created_at', 'desc') + ->take(20) + ->get(); + + if ($this->selectedKey) { + $this->selectedExecution = DockerCleanupExecution::find($this->selectedKey); + if ($this->selectedExecution && $this->selectedExecution->status !== 'running') { + $this->isPollingActive = false; + } + } + } + + public function selectExecution($key): void + { + if ($key == $this->selectedKey) { + $this->selectedKey = null; + $this->selectedExecution = null; + $this->currentPage = 1; + $this->isPollingActive = false; + + return; + } + $this->selectedKey = $key; + $this->selectedExecution = DockerCleanupExecution::find($key); + $this->currentPage = 1; + + if ($this->selectedExecution && $this->selectedExecution->status === 'running') { + $this->isPollingActive = true; + } + } + + public function polling() + { + if ($this->selectedExecution && $this->isPollingActive) { + $this->selectedExecution->refresh(); + if ($this->selectedExecution->status !== 'running') { + $this->isPollingActive = false; + } + } + $this->refreshExecutions(); + } + + public function loadMoreLogs() + { + $this->currentPage++; + } + + public function getLogLinesProperty() + { + if (! $this->selectedExecution) { + return collect(); + } + + if (! $this->selectedExecution->message) { + return collect(['Waiting for execution output...']); + } + + $lines = collect(explode("\n", $this->selectedExecution->message)); + + return $lines->take($this->currentPage * $this->logsPerPage); + } + + public function downloadLogs(int $executionId) + { + $execution = $this->executions->firstWhere('id', $executionId); + if (! $execution) { + return; + } + + return response()->streamDownload(function () use ($execution) { + echo $execution->message; + }, "docker-cleanup-{$execution->uuid}.log"); + } + + public function hasMoreLogs() + { + if (! $this->selectedExecution || ! $this->selectedExecution->message) { + return false; + } + $lines = collect(explode("\n", $this->selectedExecution->message)); + + return $lines->count() > ($this->currentPage * $this->logsPerPage); + } + + public function render() + { + return view('livewire.server.docker-cleanup-executions'); + } +} diff --git a/resources/views/livewire/server/docker-cleanup-executions.blade.php b/resources/views/livewire/server/docker-cleanup-executions.blade.php new file mode 100644 index 000000000..ea0aa7098 --- /dev/null +++ b/resources/views/livewire/server/docker-cleanup-executions.blade.php @@ -0,0 +1,127 @@ +
+ @forelse($executions as $execution) + data_get($execution, 'id') == $selectedKey, + 'border-blue-500/50 border-dashed' => data_get($execution, 'status') === 'running', + 'border-error' => data_get($execution, 'status') === 'failed', + 'border-success' => data_get($execution, 'status') === 'success', + ])> + @if (data_get($execution, 'status') === 'running') +
+ +
+ @endif +
+ data_get($execution, 'status') === 'running', + 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-200 dark:shadow-red-900/5' => data_get($execution, 'status') === 'failed', + 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200 dark:shadow-green-900/5' => data_get($execution, 'status') === 'success', + ])> + @php + $statusText = match(data_get($execution, 'status')) { + 'success' => 'Success', + 'running' => 'In Progress', + 'failed' => 'Failed', + default => ucfirst(data_get($execution, 'status')) + }; + @endphp + {{ $statusText }} + +
+
+ Started: {{ formatDateInServerTimezone(data_get($execution, 'created_at', now()), $server) }} + @if(data_get($execution, 'status') !== 'running') +
Ended: {{ formatDateInServerTimezone(data_get($execution, 'updated_at'), $server) }} +
Duration: {{ calculateDuration(data_get($execution, 'created_at'), data_get($execution, 'updated_at')) }} + @endif +
+
+ @if (strlen(data_get($execution, 'message', '')) > 0) +
+ + Download Logs + +
+ @endif + @if (data_get($execution, 'id') == $selectedKey) +
+
+ @if (data_get($execution, 'status') === 'running') +
+ Execution is running... + +
+ @endif + @if ($this->logLines->isNotEmpty()) +
+

Status Message:

+
+@foreach ($this->logLines as $line)
+{{ $line }}
+@endforeach
+
+
+ @if ($this->hasMoreLogs()) + + Load More + + @endif +
+
+ @else +
+
Status Message:
+
No output was recorded for this execution.
+
+ @endif + + @if (data_get($execution, 'cleanup_log')) +
+

Cleanup Log:

+ @foreach(json_decode(data_get($execution, 'cleanup_log'), true) as $result) +
+
+ + + + {{ data_get($result, 'command') }} +
+ @php + $output = data_get($result, 'output'); + $hasOutput = !empty(trim($output)); + @endphp +
+ @if($hasOutput) +
{{ $output }}
+ @else +

+ No output returned - command completed successfully +

+ @endif +
+
+ @endforeach +
+ @endif +
+
+ @endif + @empty +
No executions found.
+ @endforelse +
diff --git a/resources/views/livewire/server/docker-cleanup.blade.php b/resources/views/livewire/server/docker-cleanup.blade.php index 70bbb5db7..da3f8bcba 100644 --- a/resources/views/livewire/server/docker-cleanup.blade.php +++ b/resources/views/livewire/server/docker-cleanup.blade.php @@ -72,6 +72,11 @@ " /> + +
+

Recent executions (click to check output)

+ +
\ No newline at end of file