mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-14 20:17:05 +00:00
fix(ui): polish mobile layouts, error pages, and volume backups
Keep error pages full-viewport, lift the unsaved bar above the mobile keyboard, make status/heading layouts stack cleanly on small screens, route service DB backups to volume-backups, and tighten volume backup grid/forms. Cover with feature tests.
This commit is contained in:
1 parent
262ad8981a
commit
e4fa2b6964
31 files changed
+172
-83
No files matched your search
@@ -12,7 +12,8 @@ it('shows internal Docker access details in application general settings', funct
|
||||
->toContain('<h3 class="mb-3 text-sm font-semibold text-black dark:text-fg">Public access</h3>')
|
||||
->toContain("Str::plural('domain', \$domainCount)")
|
||||
->toContain('Domains, DNS checks, and redirect settings')
|
||||
->toContain('class="icon-button shrink-0 self-start sm:self-auto"')
|
||||
->toContain('class="flex items-center gap-3 rounded-lg')
|
||||
->toContain('class="icon-button ml-auto shrink-0"')
|
||||
->toContain('aria-label="Manage domains"')
|
||||
->toContain('<x-reicon name="settings" class="size-4" />')
|
||||
->not->toContain('<x-reicon name="arrow-right" class="size-3.5" />')
|
||||
|
||||
@@ -16,6 +16,7 @@ it('renders redesigned error pages with shared shell and actions', function (str
|
||||
$html = view($view, ['exception' => $exception])->render();
|
||||
|
||||
expect($html)
|
||||
->toContain('error-page-body')
|
||||
->toContain('error-shell')
|
||||
->toContain('error-code')
|
||||
->toContain('error-title')
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
<?php
|
||||
|
||||
it('keeps the volume backup executions table horizontally scrollable on mobile', function () {
|
||||
$view = file_get_contents(resource_path('views/livewire/project/shared/storages/volume-backups/executions.blade.php'));
|
||||
$css = file_get_contents(resource_path('css/app.css'));
|
||||
|
||||
expect($view)
|
||||
->toContain('volume-backup-executions-grid')
|
||||
->toContain('data-table w-full overflow-x-auto')
|
||||
->and($css)
|
||||
->toContain('.volume-backup-executions-grid')
|
||||
->toContain('min-width: 50rem;')
|
||||
->not->toContain('.data-table-header.volume-backup-executions-grid');
|
||||
});
|
||||
|
||||
use App\Livewire\Project\Service\VolumeBackup\Create as CreateServiceVolumeBackup;
|
||||
use App\Livewire\Project\Shared\Storages\All;
|
||||
use App\Models\Application;
|
||||
|
||||
@@ -13,7 +13,9 @@ it('aggregates preview container and health check status', function () {
|
||||
->toContain('Not configured')
|
||||
->toContain('aria-label="About unconfigured health checks"')
|
||||
->toContain('Traffic can still be routed to the container')
|
||||
->toContain('aria-haspopup="menu"');
|
||||
->toContain('aria-haspopup="menu"')
|
||||
->toContain('right-auto! left-0!')
|
||||
->toContain('w-[min(16rem,calc(100vw-1.5rem))]!');
|
||||
});
|
||||
|
||||
it('uses the aggregated preview status in the previews list', function () {
|
||||
|
||||
@@ -33,6 +33,27 @@ it('uses a single unified navbar for application, service, database, and server
|
||||
->not->toContain('border-l border-neutral-200 pl-1');
|
||||
});
|
||||
|
||||
it('uses interactive status summaries in mobile resource headings', function () {
|
||||
$headings = [
|
||||
resource_path('views/livewire/project/application/heading.blade.php') => '<x-status-summary :status="$application->status" />',
|
||||
resource_path('views/livewire/project/database/heading.blade.php') => '<x-status-summary :status="$database->status" title="Database status" />',
|
||||
resource_path('views/livewire/project/service/heading.blade.php') => '<x-status-summary :status="$service->status" title="Service status" container-name="Containers" />',
|
||||
];
|
||||
|
||||
foreach ($headings as $path => $statusSummary) {
|
||||
$mobileHeading = str(file_get_contents($path))
|
||||
->after('<div class="mb-3 w-full xl:hidden">')
|
||||
->before('<div class="w-full xl:hidden">')
|
||||
->toString();
|
||||
|
||||
expect($mobileHeading)
|
||||
->toContain('flex min-w-0 flex-col items-start gap-2')
|
||||
->toContain('min-w-0 max-w-full truncate')
|
||||
->toContain($statusSummary)
|
||||
->not->toContain('<x-status-badge');
|
||||
}
|
||||
});
|
||||
|
||||
it('docks desktop resource actions in the top bar instead of floating over content', function () {
|
||||
$layout = file_get_contents(resource_path('views/layouts/app.blade.php'));
|
||||
$files = [
|
||||
|
||||
@@ -56,6 +56,16 @@ test('unsaved bar stays above floating notifications so save actions remain acce
|
||||
->and($popup)->toContain('z-999');
|
||||
});
|
||||
|
||||
test('unsaved bar stays above the mobile keyboard', function () {
|
||||
$contents = file_get_contents(resource_path('views/components/unsaved-bar.blade.php'));
|
||||
|
||||
expect($contents)
|
||||
->toContain('window.visualViewport')
|
||||
->toContain('keyboardInset')
|
||||
->toContain('--keyboard-inset')
|
||||
->toContain('removeEventListener');
|
||||
});
|
||||
|
||||
test('settings general unsaved bar excludes auto-saving instance timezone', function () {
|
||||
$path = resource_path('views/livewire/settings/index.blade.php');
|
||||
$contents = file_get_contents($path);
|
||||
|
||||
@@ -36,8 +36,11 @@ it('aligns compose resource columns and uses icon actions', function () {
|
||||
|
||||
expect($configuration)->toContain($columns)
|
||||
->and($resourceCard)->toContain($columns)
|
||||
->toContain('flex flex-wrap items-center justify-end gap-1 sm:contents')
|
||||
->toContain('aria-label="Resource settings"')
|
||||
->toContain('aria-label="Database backups"')
|
||||
->toContain('aria-label="Service backups"')
|
||||
->toContain("route('project.service.volume-backups.index', \$parameters)")
|
||||
->not->toContain("route('project.service.database.backups'")
|
||||
->not->toContain('>Settings</a>')
|
||||
->not->toContain('>Backups</a>');
|
||||
});
|
||||
@@ -74,6 +74,16 @@ it('shows the service sidebar on the storage backups page', function () {
|
||||
->toContain('xl:grid-cols-[210px_minmax(0,1fr)]');
|
||||
});
|
||||
|
||||
it('links compose database backups to the parent service backups page', function () {
|
||||
$sidebar = file_get_contents(resource_path('views/components/service-database/sidebar.blade.php'));
|
||||
|
||||
expect($sidebar)
|
||||
->toContain("'route' => 'project.service.volume-backups.index'")
|
||||
->toContain("'parameters' => \$serviceParameters")
|
||||
->toContain("\$item['parameters'] ?? \$parameters")
|
||||
->not->toContain("'route' => 'project.service.database.backups'");
|
||||
});
|
||||
|
||||
it('uses a distinct backup icon across resource sidebars', function () {
|
||||
$sidebars = [
|
||||
resource_path('views/components/application/configuration-sidebar.blade.php'),
|
||||
|
||||
@@ -826,6 +826,7 @@ it('enables and disables volume S3 backups from the S3 title action', function (
|
||||
'section' => 's3',
|
||||
])
|
||||
->assertSee('Enable S3')
|
||||
->assertDontSee('You do not have permission to perform this action.')
|
||||
->call('toggleS3')
|
||||
->assertSet('saveToS3', true)
|
||||
->assertSee('Disable S3');
|
||||
@@ -865,6 +866,22 @@ it('shows and saves volume S3 retention while S3 backups are disabled', function
|
||||
->and($backup->retention_max_storage_s3)->toBe(4.5);
|
||||
});
|
||||
|
||||
it('allows team owners to edit volume backup retention settings', function () {
|
||||
$team = Team::factory()->create();
|
||||
signInForVolumeBackups($this, $team);
|
||||
[$application, $volume] = createVolumeBackupApplication($team);
|
||||
$volume->scheduledBackups()->create([
|
||||
'team_id' => $team->id,
|
||||
'frequency' => 'daily',
|
||||
]);
|
||||
|
||||
Livewire::test(VolumeBackups::class, [
|
||||
'storage' => $volume,
|
||||
'resource' => $application,
|
||||
'section' => 'retention',
|
||||
])->assertDontSee('You do not have permission to perform this action.');
|
||||
});
|
||||
|
||||
it('only updates S3 fields when toggling volume S3 backups', function () {
|
||||
$team = Team::factory()->create();
|
||||
signInForVolumeBackups($this, $team);
|
||||
|
||||
Reference in new issue
Block a user