feat(ui): improve schedule task single view for better UX (#9266)

This commit is contained in:
Andras Bacsai 2026-03-30 15:10:57 +02:00 committed by GitHub
commit 22b267db37
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 38 additions and 21 deletions

View file

@ -52,9 +52,15 @@ class Show extends Component
#[Locked]
public string $task_uuid;
public function mount(string $task_uuid, string $project_uuid, string $environment_uuid, ?string $application_uuid = null, ?string $service_uuid = null)
public function mount()
{
try {
$task_uuid = request()->route('task_uuid');
$project_uuid = request()->route('project_uuid');
$environment_uuid = request()->route('environment_uuid');
$application_uuid = request()->route('application_uuid');
$service_uuid = request()->route('service_uuid');
$this->task_uuid = $task_uuid;
if ($application_uuid) {
$this->type = 'application';
@ -105,6 +111,19 @@ public function syncData(bool $toModel = false)
}
}
public function toggleEnabled()
{
try {
$this->authorize('update', $this->resource);
$this->isEnabled = ! $this->isEnabled;
$this->task->enabled = $this->isEnabled;
$this->task->save();
$this->dispatch('success', $this->isEnabled ? 'Scheduled task enabled.' : 'Scheduled task disabled.');
} catch (\Exception $e) {
return handleError($e);
}
}
public function instantSave()
{
try {

View file

@ -42,7 +42,7 @@
</span>
@endif
</a>
<a class="sub-menu-item" {{ wireNavigate() }} wire:current.exact="menu-item-active"
<a @class(['sub-menu-item', 'menu-item-active' => str($currentRoute)->startsWith('project.application.scheduled-tasks')]) {{ wireNavigate() }}
href="{{ route('project.application.scheduled-tasks.show', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'application_uuid' => $application->uuid]) }}"><span class="menu-item-label">Scheduled Tasks</span></a>
<a class="sub-menu-item" {{ wireNavigate() }} wire:current.exact="menu-item-active"
href="{{ route('project.application.webhooks', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'application_uuid' => $application->uuid]) }}"><span class="menu-item-label">Webhooks</span></a>
@ -84,6 +84,8 @@
<livewire:project.shared.destination :resource="$application" />
@elseif ($currentRoute === 'project.application.scheduled-tasks.show')
<livewire:project.shared.scheduled-task.all :resource="$application" />
@elseif ($currentRoute === 'project.application.scheduled-tasks')
<livewire:project.shared.scheduled-task.show />
@elseif ($currentRoute === 'project.application.webhooks')
<livewire:project.shared.webhooks :resource="$application" />
@elseif ($currentRoute === 'project.application.preview-deployments')

View file

@ -14,7 +14,7 @@
href="{{ route('project.service.environment-variables', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'service_uuid' => $service->uuid]) }}"><span class="menu-item-label">Environment Variables</span></a>
<a class='sub-menu-item' wire:current.exact="menu-item-active" {{ wireNavigate() }}
href="{{ route('project.service.storages', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'service_uuid' => $service->uuid]) }}"><span class="menu-item-label">Persistent Storages</span></a>
<a class='sub-menu-item' wire:current.exact="menu-item-active" {{ wireNavigate() }}
<a @class(['sub-menu-item', 'menu-item-active' => str($currentRoute)->startsWith('project.service.scheduled-tasks')]) {{ wireNavigate() }}
href="{{ route('project.service.scheduled-tasks.show', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'service_uuid' => $service->uuid]) }}"><span class="menu-item-label">Scheduled Tasks</span></a>
<a class='sub-menu-item' wire:current.exact="menu-item-active" {{ wireNavigate() }}
href="{{ route('project.service.webhooks', ['project_uuid' => $project->uuid, 'environment_uuid' => $environment->uuid, 'service_uuid' => $service->uuid]) }}"><span class="menu-item-label">Webhooks</span></a>
@ -189,6 +189,8 @@ class="w-4 h-4 dark:text-warning text-coollabs"
@endforeach
@elseif ($currentRoute === 'project.service.scheduled-tasks.show')
<livewire:project.shared.scheduled-task.all :resource="$service" />
@elseif ($currentRoute === 'project.service.scheduled-tasks')
<livewire:project.shared.scheduled-task.show />
@elseif ($currentRoute === 'project.service.webhooks')
<livewire:project.shared.webhooks :resource="$service" />
@elseif ($currentRoute === 'project.service.resource-operations')

View file

@ -1,18 +1,8 @@
<div>
<x-slot:title>
{{ data_get_str($resource, 'name')->limit(10) }} > Scheduled Tasks | Coolify
</x-slot>
@if ($type === 'application')
<h1>Scheduled Task</h1>
<livewire:project.application.heading :application="$resource" />
@elseif ($type === 'service')
<livewire:project.service.heading :service="$resource" :parameters="$parameters" />
@endif
<form wire:submit="submit" class="w-full">
<div class="flex flex-col gap-2 pb-2">
<div class="flex gap-2 items-end">
<h2>Scheduled Task</h2>
<h2>Task {{ $task->name }}</h2>
<x-forms.button type="submit">
Save
</x-forms.button>
@ -21,6 +11,11 @@
Execute Now
</x-forms.button>
@endif
@if (!$isEnabled)
<x-forms.button wire:click="toggleEnabled" isHighlighted>Enable Task</x-forms.button>
@else
<x-forms.button wire:click="toggleEnabled">Disable Task</x-forms.button>
@endif
<x-modal-confirmation title="Confirm Scheduled Task Deletion?" isErrorButton buttonTitle="Delete"
submitAction="delete({{ $task->id }})" :actions="['The selected scheduled task will be permanently deleted.']" confirmationText="{{ $task->name }}"
confirmationLabel="Please confirm the execution of the actions by entering the Scheduled Task Name below"
@ -28,13 +23,11 @@
step2ButtonText="Permanently Delete" />
</div>
<div class="w-48">
<x-forms.checkbox instantSave id="isEnabled" label="Enabled" />
</div>
<h3 class="pt-4">Configuration</h3>
<div class="flex gap-2 w-full">
<x-forms.input placeholder="Name" id="name" label="Name" required />
<x-forms.input placeholder="php artisan schedule:run" id="command" label="Command" required />
<x-forms.input placeholder="0 0 * * * or daily" id="frequency" label="Frequency" required />
<x-forms.input placeholder="0 0 * * * or daily" id="frequency" label="Frequency"
helper="You can use every_minute, hourly, daily, weekly, monthly, yearly or a cron expression." required />
<x-forms.input type="number" placeholder="300" id="timeout"
helper="Maximum execution time in seconds (60-36000)." label="Timeout (seconds)" required />
@if ($type === 'application')
@ -47,6 +40,7 @@
id="container" label="Service name" />
@endif
</div>
<x-forms.input placeholder="php artisan schedule:run" id="command" label="Command" required />
</form>
<div class="pt-4">

View file

@ -230,7 +230,7 @@
Route::get('/deployment/{deployment_uuid}', DeploymentShow::class)->name('project.application.deployment.show');
Route::get('/logs', Logs::class)->name('project.application.logs');
Route::get('/terminal', ExecuteContainerCommand::class)->name('project.application.command')->middleware('can.access.terminal');
Route::get('/tasks/{task_uuid}', ScheduledTaskShow::class)->name('project.application.scheduled-tasks');
Route::get('/tasks/{task_uuid}', ApplicationConfiguration::class)->name('project.application.scheduled-tasks');
});
Route::prefix('project/{project_uuid}/environment/{environment_uuid}/database/{database_uuid}')->group(function () {
Route::get('/', DatabaseConfiguration::class)->name('project.database.configuration');
@ -264,7 +264,7 @@
Route::get('/{stack_service_uuid}/backups', ServiceDatabaseBackups::class)->name('project.service.database.backups');
Route::get('/{stack_service_uuid}/import', ServiceIndex::class)->name('project.service.database.import')->middleware('can.update.resource');
Route::get('/{stack_service_uuid}', ServiceIndex::class)->name('project.service.index');
Route::get('/tasks/{task_uuid}', ScheduledTaskShow::class)->name('project.service.scheduled-tasks');
Route::get('/tasks/{task_uuid}', ServiceConfiguration::class)->name('project.service.scheduled-tasks');
});
Route::get('/servers', ServerIndex::class)->name('server.index');