feat(deployment): add pull request filtering and pagination to deployment and backup execution components
fix(ui): make them more stylish yeah
This commit is contained in:
@@ -3,31 +3,36 @@
|
||||
<h1>Deployments</h1>
|
||||
<livewire:project.shared.configuration-checker :resource="$application" />
|
||||
<livewire:project.application.heading :application="$application" />
|
||||
<div class="flex flex-col gap-2 pb-10"
|
||||
@if (!$skip) wire:poll.5000ms='reload_deployments' @endif>
|
||||
<div class="flex flex-col gap-2 pb-10" @if (!$skip) wire:poll.5000ms='reloadDeployments' @endif>
|
||||
<div class="flex items-end gap-2">
|
||||
<h2>Deployments <span class="text-xs">({{ $deployments_count }})</span></h2>
|
||||
@if ($deployments_count > 0)
|
||||
<x-forms.button disabled="{{ !$show_prev }}" wire:click="previous_page('{{ $default_take }}')">
|
||||
<svg class="w-4 h-4" viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="m14 6l-6 6l6 6z" />
|
||||
</svg>
|
||||
</x-forms.button>
|
||||
<x-forms.button disabled="{{ !$show_next }}" wire:click="next_page('{{ $default_take }}')">
|
||||
<svg class="w-4 h-4" viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="m10 18l6-6l-6-6z" />
|
||||
</svg>
|
||||
</x-forms.button>
|
||||
<div class="flex items-center gap-2">
|
||||
<x-forms.button disabled="{{ !$showPrev }}" wire:click="previousPage('{{ $defaultTake }}')">
|
||||
<svg class="w-4 h-4" viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="m14 6l-6 6l6 6z" />
|
||||
</svg>
|
||||
</x-forms.button>
|
||||
<span class="text-sm text-gray-600 dark:text-gray-400 px-2">
|
||||
Page {{ $currentPage }} of {{ ceil($deployments_count / $defaultTake) }}
|
||||
</span>
|
||||
<x-forms.button disabled="{{ !$showNext }}" wire:click="nextPage('{{ $defaultTake }}')">
|
||||
<svg class="w-4 h-4" viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="m10 18l6-6l-6-6z" />
|
||||
</svg>
|
||||
</x-forms.button>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@if ($deployments_count > 0)
|
||||
<form class="flex items-end gap-2">
|
||||
<x-forms.input id="pull_request_id" label="Pull Request"></x-forms.input>
|
||||
<x-forms.button type="submit">Filter</x-forms.button>
|
||||
</form>
|
||||
@endif
|
||||
<form class="flex items-end gap-2">
|
||||
<x-forms.input id="pull_request_id" type="number" min="1" label="Pull Request Id"></x-forms.input>
|
||||
<x-forms.button type="submit">Filter</x-forms.button>
|
||||
@if ($pull_request_id)
|
||||
<x-forms.button type="button" wire:click="clearFilter">Clear</x-forms.button>
|
||||
@endif
|
||||
</form>
|
||||
@forelse ($deployments as $deployment)
|
||||
<div @class([
|
||||
'p-2 border-l-2 bg-white dark:bg-coolgray-100',
|
||||
|
||||
@@ -1,10 +1,36 @@
|
||||
<div wire:init='refreshBackupExecutions'>
|
||||
@isset($backup)
|
||||
<div class="flex items-center gap-2">
|
||||
<h3 class="py-4">Executions</h3>
|
||||
<h3 class="py-4">Executions <span class="text-xs">({{ $executions_count }})</span></h3>
|
||||
@if ($executions_count > 0)
|
||||
<div class="flex items-center gap-2">
|
||||
<x-forms.button disabled="{{ !$showPrev }}" wire:click="previousPage('{{ $defaultTake }}')">
|
||||
<svg class="w-4 h-4" viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="m14 6l-6 6l6 6z" />
|
||||
</svg>
|
||||
</x-forms.button>
|
||||
<span class="text-sm text-gray-600 dark:text-gray-400 px-2">
|
||||
Page {{ $currentPage }} of {{ ceil($executions_count / $defaultTake) }}
|
||||
</span>
|
||||
<x-forms.button disabled="{{ !$showNext }}" wire:click="nextPage('{{ $defaultTake }}')">
|
||||
<svg class="w-4 h-4" viewBox="0 0 24 24">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="m10 18l6-6l-6-6z" />
|
||||
</svg>
|
||||
</x-forms.button>
|
||||
</div>
|
||||
@endif
|
||||
<x-forms.button wire:click='cleanupFailed'>Cleanup Failed Backups</x-forms.button>
|
||||
<x-modal-confirmation title="Cleanup Deleted Backup Entries?" buttonTitle="Cleanup Deleted" isErrorButton
|
||||
submitAction="cleanupDeleted()"
|
||||
:actions="['This will permanently delete all backup execution entries that are marked as deleted from local storage.', 'This only removes database entries, not actual backup files.']"
|
||||
confirmationText="cleanup deleted backups"
|
||||
confirmationLabel="Please confirm by typing 'cleanup deleted backups' below"
|
||||
shortConfirmationLabel="Confirmation" />
|
||||
</div>
|
||||
<div wire:poll.5000ms="refreshBackupExecutions" class="flex flex-col gap-4">
|
||||
<div @if (!$skip) wire:poll.5000ms="refreshBackupExecutions" @endif
|
||||
class="flex flex-col gap-4">
|
||||
@forelse($executions as $execution)
|
||||
<div wire:key="{{ data_get($execution, 'id') }}" @class([
|
||||
'flex flex-col border-l-2 transition-colors p-4 bg-white dark:bg-coolgray-100 text-black dark:text-white',
|
||||
|
||||
@@ -20,26 +20,183 @@
|
||||
@else
|
||||
@forelse($database->scheduledBackups as $backup)
|
||||
@if ($type == 'database')
|
||||
<a class="box"
|
||||
<a @class([
|
||||
'flex flex-col border-l-2 transition-colors p-4 cursor-pointer bg-white hover:bg-gray-100 dark:bg-coolgray-100 dark:hover:bg-coolgray-200 text-black dark:text-white',
|
||||
'border-blue-500/50 border-dashed' =>
|
||||
$backup->latest_log &&
|
||||
data_get($backup->latest_log, 'status') === 'running',
|
||||
'border-error' =>
|
||||
$backup->latest_log &&
|
||||
data_get($backup->latest_log, 'status') === 'failed',
|
||||
'border-success' =>
|
||||
$backup->latest_log &&
|
||||
data_get($backup->latest_log, 'status') === 'success',
|
||||
'border-gray-200 dark:border-coolgray-300' => !$backup->latest_log,
|
||||
])
|
||||
href="{{ route('project.database.backup.execution', [...$parameters, 'backup_uuid' => $backup->uuid]) }}">
|
||||
<div class="flex flex-col">
|
||||
<div>Frequency: {{ $backup->frequency }}
|
||||
({{ data_get($backup->server(), 'settings.server_timezone', 'Instance timezone') }})
|
||||
@if ($backup->latest_log && data_get($backup->latest_log, 'status') === 'running')
|
||||
<div class="absolute top-2 right-2">
|
||||
<x-loading />
|
||||
</div>
|
||||
<div>Last backup: {{ data_get($backup->latest_log, 'status', 'No backup yet') }}</div>
|
||||
@endif
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
@if ($backup->latest_log)
|
||||
<span @class([
|
||||
'px-3 py-1 rounded-md text-xs font-medium tracking-wide shadow-xs',
|
||||
'bg-blue-100/80 text-blue-700 dark:bg-blue-500/20 dark:text-blue-300 dark:shadow-blue-900/5' =>
|
||||
data_get($backup->latest_log, 'status') === 'running',
|
||||
'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-200 dark:shadow-red-900/5' =>
|
||||
data_get($backup->latest_log, 'status') === 'failed',
|
||||
'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200 dark:shadow-green-900/5' =>
|
||||
data_get($backup->latest_log, 'status') === 'success',
|
||||
])>
|
||||
@php
|
||||
$statusText = match (data_get($backup->latest_log, 'status')) {
|
||||
'success' => 'Success',
|
||||
'running' => 'In Progress',
|
||||
'failed' => 'Failed',
|
||||
default => ucfirst(data_get($backup->latest_log, 'status')),
|
||||
};
|
||||
@endphp
|
||||
{{ $statusText }}
|
||||
</span>
|
||||
@else
|
||||
<span
|
||||
class="px-3 py-1 rounded-md text-xs font-medium tracking-wide shadow-xs bg-gray-100 text-gray-800 dark:bg-gray-900/30 dark:text-gray-200">
|
||||
No executions yet
|
||||
</span>
|
||||
@endif
|
||||
<h3 class="font-semibold">{{ $backup->frequency }}</h3>
|
||||
</div>
|
||||
<div class="text-gray-600 dark:text-gray-400 text-sm">
|
||||
@if ($backup->latest_log)
|
||||
Started:
|
||||
{{ formatDateInServerTimezone(data_get($backup->latest_log, 'created_at'), $backup->server()) }}
|
||||
@if (data_get($backup->latest_log, 'status') !== 'running')
|
||||
<br>Ended:
|
||||
{{ formatDateInServerTimezone(data_get($backup->latest_log, 'finished_at'), $backup->server()) }}
|
||||
<br>Duration:
|
||||
{{ calculateDuration(data_get($backup->latest_log, 'created_at'), data_get($backup->latest_log, 'finished_at')) }}
|
||||
<br>Finished
|
||||
{{ \Carbon\Carbon::parse(data_get($backup->latest_log, 'finished_at'))->diffForHumans() }}
|
||||
@endif
|
||||
@if ($backup->save_s3)
|
||||
<br>S3 Storage: Enabled
|
||||
@endif
|
||||
@if (data_get($backup->latest_log, 'status') === 'success')
|
||||
@php
|
||||
$size = data_get($backup->latest_log, 'size', 0);
|
||||
$sizeFormatted =
|
||||
$size > 0 ? number_format($size / 1024 / 1024, 2) . ' MB' : 'Unknown';
|
||||
@endphp
|
||||
<br>Last Backup Size: {{ $sizeFormatted }}
|
||||
@endif
|
||||
@else
|
||||
Last Run: Never
|
||||
<br>Total Executions: 0
|
||||
@if ($backup->save_s3)
|
||||
<br>S3 Storage: Enabled
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</a>
|
||||
@else
|
||||
<div class="box" wire:click="setSelectedBackup('{{ data_get($backup, 'id') }}')">
|
||||
<div @class([
|
||||
'border-coollabs' =>
|
||||
data_get($backup, 'id') === data_get($selectedBackup, 'id'),
|
||||
'flex flex-col border-l-2 border-transparent',
|
||||
])>
|
||||
<div>Frequency: {{ $backup->frequency }}
|
||||
({{ data_get($backup->server(), 'settings.server_timezone', 'Instance timezone') }})
|
||||
<div @class([
|
||||
'flex flex-col border-l-2 transition-colors p-4 cursor-pointer bg-white hover:bg-gray-100 dark:bg-coolgray-100 dark:hover:bg-coolgray-200 text-black dark:text-white',
|
||||
'bg-gray-200 dark:bg-coolgray-200' =>
|
||||
data_get($backup, 'id') === data_get($selectedBackup, 'id'),
|
||||
'border-blue-500/50 border-dashed' =>
|
||||
$backup->latest_log &&
|
||||
data_get($backup->latest_log, 'status') === 'running',
|
||||
'border-error' =>
|
||||
$backup->latest_log &&
|
||||
data_get($backup->latest_log, 'status') === 'failed',
|
||||
'border-success' =>
|
||||
$backup->latest_log &&
|
||||
data_get($backup->latest_log, 'status') === 'success',
|
||||
'border-gray-200 dark:border-coolgray-300' => !$backup->latest_log,
|
||||
'border-coollabs' =>
|
||||
data_get($backup, 'id') === data_get($selectedBackup, 'id'),
|
||||
]) wire:click="setSelectedBackup('{{ data_get($backup, 'id') }}')">
|
||||
@if ($backup->latest_log && data_get($backup->latest_log, 'status') === 'running')
|
||||
<div class="absolute top-2 right-2">
|
||||
<x-loading />
|
||||
</div>
|
||||
<div>Last backup: {{ data_get($backup->latest_log, 'status', 'No backup yet') }}</div>
|
||||
@endif
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
@if ($backup->latest_log)
|
||||
<span @class([
|
||||
'px-3 py-1 rounded-md text-xs font-medium tracking-wide shadow-xs',
|
||||
'bg-blue-100/80 text-blue-700 dark:bg-blue-500/20 dark:text-blue-300 dark:shadow-blue-900/5' =>
|
||||
data_get($backup->latest_log, 'status') === 'running',
|
||||
'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-200 dark:shadow-red-900/5' =>
|
||||
data_get($backup->latest_log, 'status') === 'failed',
|
||||
'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200 dark:shadow-green-900/5' =>
|
||||
data_get($backup->latest_log, 'status') === 'success',
|
||||
])>
|
||||
@php
|
||||
$statusText = match (data_get($backup->latest_log, 'status')) {
|
||||
'success' => 'Success',
|
||||
'running' => 'In Progress',
|
||||
'failed' => 'Failed',
|
||||
default => ucfirst(data_get($backup->latest_log, 'status')),
|
||||
};
|
||||
@endphp
|
||||
{{ $statusText }}
|
||||
</span>
|
||||
@else
|
||||
<span
|
||||
class="px-3 py-1 rounded-md text-xs font-medium tracking-wide shadow-xs bg-gray-100 text-gray-800 dark:bg-gray-900/30 dark:text-gray-200">
|
||||
No executions yet
|
||||
</span>
|
||||
@endif
|
||||
<h3 class="font-semibold">{{ $backup->frequency }} Backup</h3>
|
||||
</div>
|
||||
<div class="text-gray-600 dark:text-gray-400 text-sm">
|
||||
@if ($backup->latest_log)
|
||||
Started:
|
||||
{{ formatDateInServerTimezone(data_get($backup->latest_log, 'created_at'), $backup->server()) }}
|
||||
@if (data_get($backup->latest_log, 'status') !== 'running')
|
||||
<br>Ended:
|
||||
{{ formatDateInServerTimezone(data_get($backup->latest_log, 'finished_at'), $backup->server()) }}
|
||||
<br>Duration:
|
||||
{{ calculateDuration(data_get($backup->latest_log, 'created_at'), data_get($backup->latest_log, 'finished_at')) }}
|
||||
<br>Finished
|
||||
{{ \Carbon\Carbon::parse(data_get($backup->latest_log, 'finished_at'))->diffForHumans() }}
|
||||
@endif
|
||||
<br><br>Total Executions: {{ $backup->executions()->count() }}
|
||||
@if ($backup->save_s3)
|
||||
<br>S3 Storage: Enabled
|
||||
@endif
|
||||
@php
|
||||
$successCount = $backup->executions()->where('status', 'success')->count();
|
||||
$totalCount = $backup->executions()->count();
|
||||
$successRate = $totalCount > 0 ? round(($successCount / $totalCount) * 100) : 0;
|
||||
@endphp
|
||||
@if ($totalCount > 0)
|
||||
<br>Success Rate: <span @class([
|
||||
'font-medium',
|
||||
'text-green-600' => $successRate >= 80,
|
||||
'text-yellow-600' => $successRate >= 50 && $successRate < 80,
|
||||
'text-red-600' => $successRate < 50,
|
||||
])>{{ $successRate }}%</span>
|
||||
({{ $successCount }}/{{ $totalCount }})
|
||||
@endif
|
||||
@if (data_get($backup->latest_log, 'status') === 'success')
|
||||
@php
|
||||
$size = data_get($backup->latest_log, 'size', 0);
|
||||
$sizeFormatted =
|
||||
$size > 0 ? number_format($size / 1024 / 1024, 2) . ' MB' : 'Unknown';
|
||||
@endphp
|
||||
<br>Last Backup Size: {{ $sizeFormatted }}
|
||||
@endif
|
||||
@else
|
||||
Last Run: Never
|
||||
<br>Total Executions: 0
|
||||
@if ($backup->save_s3)
|
||||
<br>S3 Storage: Enabled
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
Reference in New Issue
Block a user