mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
@@ -2952,13 +2952,14 @@ input[type="search"]::-webkit-search-results-decoration {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.data-table-row.service-backup-table-grid {
|
||||
background: var(--coollabs-base);
|
||||
border-bottom: 1px solid var(--coollabs-fill);
|
||||
.data-table-header.service-backup-table-grid {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.data-table-row.service-backup-table-grid:last-child {
|
||||
border-bottom: 0;
|
||||
/* Rows are reordered with CSS order, so dividers must not depend on DOM position. */
|
||||
.data-table-row.service-backup-table-grid {
|
||||
background: var(--coollabs-base);
|
||||
border-top: 1px solid var(--coollabs-fill);
|
||||
}
|
||||
|
||||
.data-table-row.service-backup-table-grid:hover {
|
||||
|
||||
@@ -167,7 +167,7 @@
|
||||
</div>
|
||||
|
||||
@if ($backups->isNotEmpty())
|
||||
<div class="data-table w-full overflow-x-auto" x-show="filteredBackups.length > 0">
|
||||
<div class="data-table flex w-full flex-col overflow-x-auto" x-show="filteredBackups.length > 0">
|
||||
<div class="data-table-header backup-table-grid">
|
||||
<span>Target</span>
|
||||
<span>Type</span>
|
||||
|
||||
@@ -240,7 +240,7 @@
|
||||
|
||||
@if ($backups->isNotEmpty() || $databaseBackups->isNotEmpty())
|
||||
<div class="data-table w-full overflow-x-auto" x-show="filteredBackups.length > 0">
|
||||
<div class="min-w-[64rem]">
|
||||
<div class="flex min-w-[64rem] flex-col">
|
||||
<div class="data-table-header backup-table-grid service-backup-table-grid">
|
||||
<span>Target</span>
|
||||
<span>Type</span>
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
use App\Models\LocalPersistentVolume;
|
||||
use App\Models\ScheduledVolumeBackup;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
$this->stack = seedBrowserResourceStack();
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates volume backups for bravo, alpha, and charlie, in that order from oldest to newest.
|
||||
*/
|
||||
function createSortableVolumeBackups(Model $resource): void
|
||||
{
|
||||
foreach (['bravo', 'alpha', 'charlie'] as $index => $name) {
|
||||
$volume = LocalPersistentVolume::create([
|
||||
'uuid' => (string) new Cuid2,
|
||||
'name' => $name.'-data',
|
||||
'mount_path' => '/data/'.$name,
|
||||
'resource_id' => $resource->id,
|
||||
'resource_type' => $resource->getMorphClass(),
|
||||
]);
|
||||
|
||||
$backup = ScheduledVolumeBackup::create([
|
||||
'backupable_type' => $volume->getMorphClass(),
|
||||
'backupable_id' => $volume->id,
|
||||
'team_id' => 0,
|
||||
'frequency' => '0 0 * * *',
|
||||
'enabled' => true,
|
||||
]);
|
||||
|
||||
ScheduledVolumeBackup::whereKey($backup->id)->update(['created_at' => now()->subDays(10 - $index)]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the backup target names in the order the browser shows them, top to bottom.
|
||||
*/
|
||||
function visibleBackupOrderScript(): string
|
||||
{
|
||||
return <<<'JS'
|
||||
() => [...document.querySelectorAll('.data-table-row')]
|
||||
.filter((row) => row.offsetParent !== null)
|
||||
.sort((left, right) => left.getBoundingClientRect().top - right.getBoundingClientRect().top)
|
||||
.map((row) => row.querySelector('span').textContent.trim())
|
||||
.join(',')
|
||||
JS;
|
||||
}
|
||||
|
||||
function assertBackupSortOrders(mixed $page, string $screenshot): void
|
||||
{
|
||||
$page->assertSee('alpha-data')
|
||||
->assertScript(visibleBackupOrderScript(), 'alpha-data,bravo-data,charlie-data')
|
||||
->click('Sort')
|
||||
->click('Target Z–A')
|
||||
->assertScript(visibleBackupOrderScript(), 'charlie-data,bravo-data,alpha-data')
|
||||
->click('Sort')
|
||||
->click('Oldest first')
|
||||
->assertScript(visibleBackupOrderScript(), 'bravo-data,alpha-data,charlie-data')
|
||||
->click('Sort')
|
||||
->click('Newest first')
|
||||
->assertScript(visibleBackupOrderScript(), 'charlie-data,alpha-data,bravo-data')
|
||||
->screenshot(filename: $screenshot);
|
||||
}
|
||||
|
||||
it('reorders application storage backups when the sort option changes', function () {
|
||||
$application = createBrowserApplication($this->stack, [
|
||||
'uuid' => 'app-browser-backup-sort',
|
||||
'name' => 'Backup Sort App',
|
||||
]);
|
||||
createSortableVolumeBackups($application);
|
||||
|
||||
loginAndSkipBoarding();
|
||||
|
||||
$page = visit(applicationConfigurationUrl($this->stack['project'], $this->stack['environment'], $application).'/backups');
|
||||
|
||||
assertBackupSortOrders($page, 'application-backup-sort');
|
||||
});
|
||||
|
||||
it('reorders service storage backups when the sort option changes', function () {
|
||||
['service' => $service, 'serviceApplication' => $serviceApplication] = createBrowserService($this->stack, [
|
||||
'uuid' => 'svc-browser-backup-sort',
|
||||
]);
|
||||
createSortableVolumeBackups($serviceApplication);
|
||||
|
||||
loginAndSkipBoarding();
|
||||
|
||||
$page = visit(serviceConfigurationUrl($this->stack['project'], $this->stack['environment'], $service).'/storage-backups');
|
||||
|
||||
assertBackupSortOrders($page, 'service-backup-sort');
|
||||
});
|
||||
Reference in New Issue
Block a user