mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
Merge remote-tracking branch 'origin/main' into release/v4.5
This commit is contained in:
@@ -4,12 +4,15 @@ namespace App\Livewire\Server;
|
||||
|
||||
use App\Models\Server;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Livewire\Attributes\Locked;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithPagination;
|
||||
|
||||
class DockerImages extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
use WithPagination;
|
||||
|
||||
public Server $server;
|
||||
|
||||
@@ -27,6 +30,19 @@ class DockerImages extends Component
|
||||
|
||||
public bool $loaded = false;
|
||||
|
||||
public int $perPage = 10;
|
||||
|
||||
public function updatedSearch(): void
|
||||
{
|
||||
$this->resetPage();
|
||||
}
|
||||
|
||||
public function updatedPerPage(): void
|
||||
{
|
||||
$this->perPage = max(1, min(100, $this->perPage));
|
||||
$this->resetPage();
|
||||
}
|
||||
|
||||
public function mount(string $server_uuid)
|
||||
{
|
||||
try {
|
||||
@@ -159,10 +175,22 @@ class DockerImages extends Component
|
||||
->contains($search, ignoreCase: true));
|
||||
}
|
||||
|
||||
$this->perPage = max(1, min(100, $this->perPage));
|
||||
$lastPage = max(1, (int) ceil($images->count() / $this->perPage));
|
||||
$page = max(1, min((int) $this->getPage(), $lastPage));
|
||||
if ($page !== $this->getPage()) {
|
||||
$this->setPage($page);
|
||||
}
|
||||
|
||||
return view('livewire.server.docker-images', [
|
||||
// Not "images": Livewire shares public properties with the view, so that name is
|
||||
// already taken by the unfiltered array.
|
||||
'visibleImages' => $images->values(),
|
||||
'visibleImages' => new LengthAwarePaginator(
|
||||
$images->forPage($page, $this->perPage)->values(),
|
||||
$images->count(),
|
||||
$this->perPage,
|
||||
$page,
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
<section {{ $attributes->merge(['class' => 'application-settings-section', 'data-settings-section-title' => $title]) }}>
|
||||
<header>
|
||||
<div class="min-w-0 py-0.5">
|
||||
<div @class(['min-w-0 py-0.5', 'flex flex-wrap items-center gap-2' => isset($badges)])>
|
||||
@if (filled($description ?? $helper))
|
||||
<h3>
|
||||
<x-helper :helper="$description ?? $helper" :label="'More information about '.$title">
|
||||
@@ -19,6 +19,7 @@
|
||||
@else
|
||||
<h3>{{ $title }}</h3>
|
||||
@endif
|
||||
{{ $badges ?? '' }}
|
||||
</div>
|
||||
@isset($actions)
|
||||
<div class="flex min-w-0 max-w-full flex-wrap items-center gap-2">
|
||||
|
||||
@@ -13,11 +13,13 @@
|
||||
<x-application.settings-section id="server-docker-images-section" title="Images"
|
||||
helper="Docker images stored on this server. Images that no container uses can be deleted here."
|
||||
flush>
|
||||
<x-slot:actions>
|
||||
@if ($usage)
|
||||
@if ($usage)
|
||||
<x-slot:badges>
|
||||
<x-status-badge :status="'Total ' . $usage['size']" type="neutral" />
|
||||
<x-status-badge :status="'Reclaimable ' . $usage['reclaimable']" type="warning" />
|
||||
@endif
|
||||
</x-slot:badges>
|
||||
@endif
|
||||
<x-slot:actions>
|
||||
<x-forms.button wire:click="load">
|
||||
<x-reicon name="refresh" class="size-3.5" />
|
||||
Refresh
|
||||
@@ -104,6 +106,15 @@
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<x-table-pagination :from="$visibleImages->firstItem()" :to="$visibleImages->lastItem()"
|
||||
:total="$visibleImages->total()" :current-page="$visibleImages->currentPage()"
|
||||
:last-page="$visibleImages->lastPage()" wire-target="previousPage,nextPage,perPage"
|
||||
previous-action="previousPage" next-action="nextPage">
|
||||
<x-slot:pageSize>
|
||||
<x-page-size-select model="perPage" livewire
|
||||
storage-key="coolify.page-size.server-docker-images" />
|
||||
</x-slot:pageSize>
|
||||
</x-table-pagination>
|
||||
@endif
|
||||
</x-application.settings-section>
|
||||
</div>
|
||||
|
||||
@@ -101,3 +101,32 @@ it('filters images by the search term', function () use ($fakeDocker, $nginxId,
|
||||
->assertSee('1.27')
|
||||
->assertDontSee(str_repeat('b', 12));
|
||||
});
|
||||
|
||||
it('paginates images and returns to the first page when the search changes', function () {
|
||||
Process::fake([
|
||||
'*docker image ls*' => Process::result(output: collect(range(1, 12))
|
||||
->map(fn (int $i) => json_encode([
|
||||
'Repository' => sprintf('app-%02d', $i), 'Tag' => 'latest', 'ID' => 'sha256:'.str_repeat(dechex($i), 64),
|
||||
'Size' => '1MB', 'CreatedSince' => '1 day ago',
|
||||
]))
|
||||
->implode("\n")),
|
||||
'*docker ps -a*' => Process::result(output: ''),
|
||||
'*docker system df*' => Process::result(output: ''),
|
||||
]);
|
||||
|
||||
Livewire::test(DockerImages::class, ['server_uuid' => $this->server->uuid])
|
||||
->call('load')
|
||||
->assertSee('app-10')
|
||||
->assertDontSee('app-11')
|
||||
->assertSee('1–10 of 12')
|
||||
->call('nextPage')
|
||||
->assertSee('app-12')
|
||||
->assertDontSee('app-01')
|
||||
->assertSee('11–12 of 12')
|
||||
->set('search', 'app-0')
|
||||
->assertSee('app-01')
|
||||
->assertSee('1–9 of 9')
|
||||
->set('perPage', 5)
|
||||
->assertSee('1–5 of 9')
|
||||
->assertDontSee('app-06');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user