feat(logs): Add dropdown to download displayed or all logs
Users can now choose between downloading only the currently displayed logs or fetching and downloading all available logs from the container. Changes: - Add downloadAllLogs() method that fetches all logs without limit - Replace download button with dropdown menu - Options: "Download displayed logs" and "Download all logs" Addresses #7803
This commit is contained in:
parent
b484c0cc25
commit
bbb2aa9ad4
2 changed files with 87 additions and 8 deletions
|
|
@ -188,6 +188,50 @@ public function copyLogs(): string
|
||||||
return sanitizeLogsForExport($this->outputs);
|
return sanitizeLogsForExport($this->outputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function downloadAllLogs(): string
|
||||||
|
{
|
||||||
|
if (! $this->server->isFunctional() || ! $this->container) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->showTimeStamps) {
|
||||||
|
if ($this->server->isSwarm()) {
|
||||||
|
$command = "docker service logs -t {$this->container}";
|
||||||
|
} else {
|
||||||
|
$command = "docker logs -t {$this->container}";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($this->server->isSwarm()) {
|
||||||
|
$command = "docker service logs {$this->container}";
|
||||||
|
} else {
|
||||||
|
$command = "docker logs {$this->container}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->server->isNonRoot()) {
|
||||||
|
$command = parseCommandsByLineForSudo(collect($command), $this->server);
|
||||||
|
$command = $command[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$sshCommand = SshMultiplexingHelper::generateSshCommand($this->server, $command);
|
||||||
|
|
||||||
|
$allLogs = '';
|
||||||
|
Process::run($sshCommand, function (string $type, string $output) use (&$allLogs) {
|
||||||
|
$allLogs .= removeAnsiColors($output);
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($this->showTimeStamps) {
|
||||||
|
$allLogs = str($allLogs)->split('/\n/')->sort(function ($a, $b) {
|
||||||
|
$a = explode(' ', $a);
|
||||||
|
$b = explode(' ', $b);
|
||||||
|
|
||||||
|
return $a[0] <=> $b[0];
|
||||||
|
})->join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sanitizeLogsForExport($allLogs);
|
||||||
|
}
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
return view('livewire.project.shared.get-logs');
|
return view('livewire.project.shared.get-logs');
|
||||||
|
|
|
||||||
|
|
@ -316,14 +316,49 @@ class="p-1 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-
|
||||||
d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75" />
|
d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<button x-on:click="downloadLogs()" title="Download Logs"
|
<div x-data="{ downloadMenuOpen: false }" class="relative">
|
||||||
class="p-1 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
|
<button x-on:click="downloadMenuOpen = !downloadMenuOpen" title="Download Logs"
|
||||||
<svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
class="p-1 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
|
||||||
stroke-width="1.5" stroke="currentColor">
|
<svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
||||||
<path stroke-linecap="round" stroke-linejoin="round"
|
stroke-width="1.5" stroke="currentColor">
|
||||||
d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" />
|
<path stroke-linecap="round" stroke-linejoin="round"
|
||||||
</svg>
|
d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" />
|
||||||
</button>
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div x-show="downloadMenuOpen" x-on:click.away="downloadMenuOpen = false"
|
||||||
|
x-transition:enter="transition ease-out duration-100"
|
||||||
|
x-transition:enter-start="transform opacity-0 scale-95"
|
||||||
|
x-transition:enter-end="transform opacity-100 scale-100"
|
||||||
|
x-transition:leave="transition ease-in duration-75"
|
||||||
|
x-transition:leave-start="transform opacity-100 scale-100"
|
||||||
|
x-transition:leave-end="transform opacity-0 scale-95"
|
||||||
|
class="absolute right-0 z-50 mt-2 w-48 origin-top-right rounded-md bg-white dark:bg-coolgray-200 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
|
||||||
|
<div class="py-1">
|
||||||
|
<button x-on:click="downloadLogs(); downloadMenuOpen = false"
|
||||||
|
class="block w-full px-4 py-2 text-left text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-coolgray-300">
|
||||||
|
Download displayed logs
|
||||||
|
</button>
|
||||||
|
<button x-on:click="
|
||||||
|
$wire.downloadAllLogs().then(logs => {
|
||||||
|
if (!logs) return;
|
||||||
|
const blob = new Blob([logs], { type: 'text/plain' });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
const timestamp = new Date().toISOString().slice(0,19).replace(/[T:]/g, '-');
|
||||||
|
a.download = containerName + '-all-logs-' + timestamp + '.txt';
|
||||||
|
a.click();
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
Livewire.dispatch('success', ['All logs downloaded.']);
|
||||||
|
});
|
||||||
|
downloadMenuOpen = false;
|
||||||
|
"
|
||||||
|
class="block w-full px-4 py-2 text-left text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-coolgray-300">
|
||||||
|
Download all logs
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<button wire:click="toggleTimestamps" title="Toggle Timestamps"
|
<button wire:click="toggleTimestamps" title="Toggle Timestamps"
|
||||||
class="p-1 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 {{ $showTimeStamps ? '!text-warning' : '' }}">
|
class="p-1 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 {{ $showTimeStamps ? '!text-warning' : '' }}">
|
||||||
<svg class="w-4 h-4" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none"
|
<svg class="w-4 h-4" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue