mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-15 16:14:35 +00:00
feat(resources): add responsive mobile navigation menus
Unify application, database, and service headings with mobile-friendly resource menus, route-aware configuration tabs, and confirmation triggers for advanced actions. Standardize restart warnings with status badges and cover the responsive menu and badge rendering behavior with feature tests.
This commit is contained in:
1 parent
51583069f4
commit
a9d9bfdbe3
15 files changed
+1238
-414
No files matched your search
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
it('uses native mobile menus for databases and services', function () {
|
||||
$applicationHeading = file_get_contents(resource_path('views/livewire/project/application/heading.blade.php'));
|
||||
$databaseHeading = file_get_contents(resource_path('views/livewire/project/database/heading.blade.php'));
|
||||
$serviceHeading = file_get_contents(resource_path('views/livewire/project/service/heading.blade.php'));
|
||||
|
||||
expect($applicationHeading)
|
||||
->toContain("'route' => 'project.application.command'")
|
||||
->toContain("'navigate' => false")
|
||||
->toContain("value.startsWith('location|')")
|
||||
->toContain('window.location.href = url');
|
||||
|
||||
expect($databaseHeading)
|
||||
->toContain('database-mobile-section')
|
||||
->toContain('<optgroup label="Database">')
|
||||
->toContain('<optgroup label="Configuration">')
|
||||
->toContain('<optgroup label="Actions">')
|
||||
->toContain("'route' => 'project.database.command'")
|
||||
->toContain("'navigate' => false")
|
||||
->toContain("value.startsWith('location|')")
|
||||
->toContain('window.location.href = url')
|
||||
->toContain('window.Livewire?.navigate ? window.Livewire.navigate(url) : window.location.href = url')
|
||||
->toContain("window.Livewire?.hook?.('morphed'")
|
||||
->toContain('x-model="selected"')
|
||||
->toContain('database-restart-trigger')
|
||||
->toContain('database-stop-trigger')
|
||||
->toContain('scrollbar hidden min-h-10')
|
||||
->not->toContain('<optgroup label="Links">')
|
||||
->not->toContain('@selected');
|
||||
|
||||
expect($serviceHeading)
|
||||
->toContain('service-mobile-section')
|
||||
->toContain('<optgroup label="Service">')
|
||||
->toContain('<optgroup label="Configuration">')
|
||||
->toContain('<optgroup label="Resource">')
|
||||
->toContain('<optgroup label="Links">')
|
||||
->toContain('<optgroup label="Actions">')
|
||||
->toContain("'route' => 'project.service.command'")
|
||||
->toContain("'navigate' => false")
|
||||
->toContain("value.startsWith('location|')")
|
||||
->toContain('window.location.href = url')
|
||||
->toContain('window.Livewire?.navigate ? window.Livewire.navigate(url) : window.location.href = url')
|
||||
->toContain("window.Livewire?.hook?.('morphed'")
|
||||
->toContain('x-model="selected"')
|
||||
->toContain('service-restart-trigger')
|
||||
->toContain('service-stop-trigger')
|
||||
->toContain('service-forceDeploy-trigger')
|
||||
->toContain('service-pullAndRestart-trigger')
|
||||
->toContain('scrollbar hidden min-h-10')
|
||||
->toContain('mb-4 w-full md:mb-0 md:hidden')
|
||||
->toContain('hidden flex-wrap items-center gap-2 md:flex')
|
||||
->not->toContain('order-first flex flex-wrap items-center gap-2 sm:order-last')
|
||||
->not->toContain('@selected');
|
||||
});
|
||||
|
||||
it('keeps configuration sidebars hidden until desktop breakpoint', function () {
|
||||
expect(file_get_contents(resource_path('views/livewire/project/database/configuration.blade.php')))
|
||||
->toContain('sub-menu-wrapper hidden md:flex');
|
||||
|
||||
expect(file_get_contents(resource_path('views/livewire/project/service/configuration.blade.php')))
|
||||
->toContain('sub-menu-wrapper hidden md:flex');
|
||||
|
||||
expect(file_get_contents(resource_path('views/livewire/project/service/index.blade.php')))
|
||||
->toContain('sub-menu-wrapper hidden md:flex');
|
||||
|
||||
expect(file_get_contents(resource_path('views/components/service-database/sidebar.blade.php')))
|
||||
->toContain('sub-menu-wrapper hidden md:flex');
|
||||
});
|
||||
@@ -87,6 +87,35 @@ it('renders responsive checkbox classes on the application configuration page',
|
||||
|
||||
$response->assertSuccessful();
|
||||
$response->assertSee('Use a Build Server?');
|
||||
$response->assertSee('application-mobile-section');
|
||||
$response->assertSee('Application menu');
|
||||
$response->assertSee('<optgroup label="Application">', false);
|
||||
$response->assertSee('<optgroup label="Configuration">', false);
|
||||
$response->assertSee('<optgroup label="Links">', false);
|
||||
$response->assertSee('<optgroup label="Actions">', false);
|
||||
$response->assertSee('value="navigate|application|', false);
|
||||
$response->assertSee('value="navigate|configuration|', false);
|
||||
$response->assertSee('window.Livewire?.navigate ? window.Livewire.navigate(url) : window.location.href = url', false);
|
||||
$response->assertSee('value="action:force-deploy"', false);
|
||||
$response->assertSee('application-mobile-stop-trigger');
|
||||
$response->assertSee('application-mobile-deploy-trigger');
|
||||
$response->assertSee('application-mobile-restart-trigger');
|
||||
$response->assertSee('application-mobile-force-deploy-trigger');
|
||||
$response->assertSee('Confirm Application Deployment?');
|
||||
$response->assertSee('Confirm Application Restart?');
|
||||
$response->assertSee('Confirm Application Force Deployment?');
|
||||
$response->assertSee('sub-menu-wrapper hidden md:flex', false);
|
||||
$response->assertSee('scrollbar hidden min-h-10', false);
|
||||
$response->assertSee(route('project.application.deployment.index', [
|
||||
'project_uuid' => $this->project->uuid,
|
||||
'environment_uuid' => $this->environment->uuid,
|
||||
'application_uuid' => $this->application->uuid,
|
||||
]));
|
||||
$response->assertSee(route('project.application.environment-variables', [
|
||||
'project_uuid' => $this->project->uuid,
|
||||
'environment_uuid' => $this->environment->uuid,
|
||||
'application_uuid' => $this->application->uuid,
|
||||
]));
|
||||
$response->assertSee('form-control flex max-w-full flex-row items-center gap-4 py-1 pr-2', false);
|
||||
$response->assertSee('label flex w-full max-w-full min-w-0 items-center gap-4 px-0', false);
|
||||
$response->assertSee('flex min-w-0 grow gap-2 break-words', false);
|
||||
|
||||
@@ -76,3 +76,39 @@ it('renders health warning helpers as badges instead of warning icons', function
|
||||
->not->toContain('class="px-2"')
|
||||
->not->toContain('viewBox="0 0 256 256"');
|
||||
});
|
||||
|
||||
it('renders restart counts as warning badges', function () {
|
||||
$resource = new class
|
||||
{
|
||||
public string $status = 'running:unknown';
|
||||
|
||||
public int $restart_count = 9;
|
||||
|
||||
public ?int $max_restart_count = null;
|
||||
|
||||
public ?string $last_restart_type = null;
|
||||
|
||||
public $last_restart_at;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->last_restart_at = now();
|
||||
}
|
||||
};
|
||||
|
||||
$html = view('components.status.index', [
|
||||
'resource' => $resource,
|
||||
'showRefreshButton' => false,
|
||||
])->render();
|
||||
$statusIndex = file_get_contents(resource_path('views/components/status/index.blade.php'));
|
||||
|
||||
expect($html)
|
||||
->toContain('9x restarts')
|
||||
->toContain('border-yellow-300 bg-yellow-50')
|
||||
->not->toContain('(9x restarts)');
|
||||
|
||||
expect($statusIndex)
|
||||
->toContain('<x-status-badge')
|
||||
->toContain('restart_count')
|
||||
->not->toContain('class="text-xs dark:text-warning"');
|
||||
});
|
||||
Reference in new issue
Block a user