Add shared status-summary and icon-tooltip components and wire them into application, service, and database headings, breadcrumbs, and previews. Badge production and PR domain links, prefer helper popups below the trigger, keep full wire targets for button loading, and cover the UI with feature tests.
222 lines
14 KiB
PHP
222 lines
14 KiB
PHP
@php
|
|
$gridClass = match (true) {
|
|
$supportsPreviewSuffix => 'volumes-table-grid-with-pr',
|
|
$showActionsColumn => 'volumes-table-grid',
|
|
default => 'volumes-table-grid-readonly',
|
|
};
|
|
@endphp
|
|
|
|
<div class="flex w-full flex-col">
|
|
@if (data_get($resource, 'build_pack') === 'dockercompose')
|
|
<div
|
|
class="border-b border-neutral-200 px-4 py-3 text-[13px] leading-5 text-amber-800 dark:border-white/[0.08] dark:text-amber-300/90">
|
|
Docker Compose volume mounts are read-only here. Edit the compose file and reload it to change volumes.
|
|
</div>
|
|
@endif
|
|
|
|
@if ($resource->persistentStorages->isNotEmpty())
|
|
<div class="data-table w-full">
|
|
<div class="data-table-header {{ $gridClass }}">
|
|
<span>Volume Name</span>
|
|
<span class="volumes-col-source">Source Path</span>
|
|
<span>Destination Path</span>
|
|
@if ($supportsPreviewSuffix)
|
|
<span class="volumes-col-pr"
|
|
title="Whether preview deployments receive an isolated -pr-N volume suffix.">
|
|
PR suffix
|
|
</span>
|
|
@endif
|
|
<span class="volumes-col-backup text-center">Backup</span>
|
|
@if ($showActionsColumn)
|
|
<span class="volumes-col-actions text-right">Actions</span>
|
|
@endif
|
|
</div>
|
|
|
|
@foreach ($this->storages as $storage)
|
|
@php
|
|
$id = $storage->id;
|
|
$form = $forms[$id] ?? null;
|
|
if (! $form) {
|
|
continue;
|
|
}
|
|
$backupMeta = $volumeBackupMeta[$id] ?? ['enabled' => false, 'url' => null];
|
|
$hasEnabledBackup = $backupMeta['enabled'];
|
|
$backupUrl = $backupMeta['url'];
|
|
$inputsReadonly = $form['isReadOnly'];
|
|
$displayHostPath = filled($form['hostPath']) ? $form['hostPath'] : '—';
|
|
@endphp
|
|
|
|
@if ($inputsReadonly)
|
|
<div class="env-table-item" wire:key="storage-row-{{ $id }}">
|
|
<div class="data-table-row {{ $gridClass }} text-[13px] text-neutral-700 dark:text-fg-dim">
|
|
<div class="volumes-cell-name min-w-0">
|
|
<span class="volumes-mobile-label volumes-field-label">Volume Name</span>
|
|
<div class="flex min-w-0 items-center gap-2">
|
|
<span
|
|
class="min-w-0 truncate text-[13px] font-medium text-neutral-950 dark:text-fg"
|
|
title="{{ $form['name'] }}">{{ $form['name'] }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="volumes-col-source min-w-0">
|
|
<span class="volumes-mobile-label volumes-field-label">Source Path</span>
|
|
<span class="block min-w-0 truncate text-[13px]"
|
|
title="{{ $form['hostPath'] }}">{{ $displayHostPath }}</span>
|
|
</div>
|
|
|
|
<div class="volumes-cell-dest min-w-0">
|
|
<span class="volumes-mobile-label volumes-field-label">Destination Path</span>
|
|
<span
|
|
class="block min-w-0 truncate text-[13px] text-neutral-950 dark:text-fg"
|
|
title="{{ $form['mountPath'] }}">{{ $form['mountPath'] }}</span>
|
|
</div>
|
|
|
|
@if ($supportsPreviewSuffix)
|
|
<div class="volumes-col-pr min-w-0">
|
|
<span class="volumes-mobile-label volumes-field-label">PR suffix</span>
|
|
<span>{{ $form['isPreviewSuffixEnabled'] ? 'Add suffix' : 'Share volume' }}</span>
|
|
</div>
|
|
@endif
|
|
|
|
<div class="volumes-col-backup data-table-cell-check">
|
|
<span class="volumes-mobile-label volumes-field-label">Backup</span>
|
|
@if ($hasEnabledBackup)
|
|
<a @if ($backupUrl) href="{{ $backupUrl }}" @endif title="Volume backup is enabled">
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
|
stroke-width="2" stroke="currentColor" class="size-4">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" />
|
|
</svg>
|
|
</a>
|
|
@else
|
|
<span class="data-table-cell-dash">-</span>
|
|
@endif
|
|
</div>
|
|
|
|
@if ($showBackupAction)
|
|
<div
|
|
class="volumes-col-actions volumes-cell-actions flex flex-wrap items-center justify-end gap-1.5">
|
|
@if ($canUpdate)
|
|
<x-modal-input title="Configure Volume Backup" :wireIgnore="false">
|
|
<x-slot:content>
|
|
<button type="button" class="icon-button" title="Configure backup"
|
|
aria-label="Configure backup">
|
|
<x-reicon name="database" class="size-4" />
|
|
</button>
|
|
</x-slot:content>
|
|
@if ($resource instanceof \App\Models\Application)
|
|
<livewire:project.application.backup.create :application="$resource"
|
|
:selected-target-key="'volume:' . $id"
|
|
wire:key="configure-volume-backup-{{ $id }}" />
|
|
@else
|
|
<livewire:project.service.volume-backup.create :service="$resource->service"
|
|
:selected-target-key="'volume:' . $id"
|
|
wire:key="configure-service-volume-backup-{{ $id }}" />
|
|
@endif
|
|
</x-modal-input>
|
|
@else
|
|
<span class="text-neutral-400 dark:text-fg-faint">—</span>
|
|
@endif
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@else
|
|
<form wire:submit="submit({{ $id }})" class="env-table-item" wire:key="storage-row-{{ $id }}">
|
|
<div class="data-table-row {{ $gridClass }}">
|
|
<div class="volumes-cell-name min-w-0">
|
|
<span class="volumes-mobile-label volumes-field-label">Volume Name</span>
|
|
<div class="flex min-w-0 items-center gap-2">
|
|
<div class="min-w-0 flex-1">
|
|
<x-forms.input id="forms.{{ $id }}.name" required />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="volumes-col-source min-w-0">
|
|
<span class="volumes-mobile-label volumes-field-label">Source Path</span>
|
|
<x-forms.input id="forms.{{ $id }}.hostPath" placeholder="Host path (optional)" />
|
|
</div>
|
|
|
|
<div class="volumes-cell-dest min-w-0">
|
|
<span class="volumes-mobile-label volumes-field-label">Destination Path</span>
|
|
<x-forms.input id="forms.{{ $id }}.mountPath" required
|
|
placeholder="/path/in/container" />
|
|
</div>
|
|
|
|
@if ($supportsPreviewSuffix)
|
|
<div class="volumes-col-pr min-w-0">
|
|
<span class="volumes-mobile-label volumes-field-label">PR suffix</span>
|
|
<x-forms.listbox id="forms.{{ $id }}.isPreviewSuffixEnabled" :options="[
|
|
['value' => true, 'label' => 'Add suffix'],
|
|
['value' => false, 'label' => 'Share volume'],
|
|
]" />
|
|
</div>
|
|
@endif
|
|
|
|
<div class="volumes-col-backup data-table-cell-check">
|
|
<span class="volumes-mobile-label volumes-field-label">Backup</span>
|
|
@if ($hasEnabledBackup)
|
|
<a @if ($backupUrl) href="{{ $backupUrl }}" @endif title="Volume backup is enabled">
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
|
stroke-width="2" stroke="currentColor" class="size-4">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" />
|
|
</svg>
|
|
</a>
|
|
@else
|
|
<span class="data-table-cell-dash">-</span>
|
|
@endif
|
|
</div>
|
|
|
|
<div
|
|
class="volumes-col-actions volumes-cell-actions flex flex-wrap items-center justify-end gap-1.5">
|
|
<x-forms.button type="submit" class="!px-2.5 !text-xs">
|
|
Update
|
|
</x-forms.button>
|
|
|
|
@if ($showBackupAction)
|
|
<x-modal-input title="Configure Volume Backup" :wireIgnore="false">
|
|
<x-slot:content>
|
|
<button type="button" class="icon-button" title="Configure backup"
|
|
aria-label="Configure backup">
|
|
<x-reicon name="database" class="size-4" />
|
|
</button>
|
|
</x-slot:content>
|
|
@if ($resource instanceof \App\Models\Application)
|
|
<livewire:project.application.backup.create :application="$resource"
|
|
:selected-target-key="'volume:' . $id"
|
|
wire:key="configure-volume-backup-{{ $id }}" />
|
|
@else
|
|
<livewire:project.service.volume-backup.create :service="$resource->service"
|
|
:selected-target-key="'volume:' . $id"
|
|
wire:key="configure-service-volume-backup-{{ $id }}" />
|
|
@endif
|
|
</x-modal-input>
|
|
@elseif (method_exists($resource, 'isBackupSolutionAvailable') && $resource->isBackupSolutionAvailable())
|
|
<x-modal-input title="New Scheduled Backup" :wireIgnore="false">
|
|
<x-slot:content>
|
|
<button type="button" class="icon-button" title="Configure backup"
|
|
aria-label="Configure backup">
|
|
<x-reicon name="database" class="size-4" />
|
|
</button>
|
|
</x-slot:content>
|
|
<livewire:project.database.create-scheduled-backup :database="$resource"
|
|
wire:key="configure-database-backup-{{ $id }}" />
|
|
</x-modal-input>
|
|
@endif
|
|
|
|
<x-modal-confirmation title="Confirm persistent storage deletion?" isErrorButton
|
|
buttonTitle="Delete" submitAction="delete({{ $id }})" :actions="[
|
|
'The selected persistent storage/volume will be permanently deleted.',
|
|
'If the persistent storage/volume is actvily used by a resource data will be lost.',
|
|
]" confirmationText="{{ $form['name'] }}"
|
|
confirmationLabel="Please confirm the execution of the actions by entering the Storage Name below"
|
|
shortConfirmationLabel="Storage Name" />
|
|
</div>
|
|
</div>
|
|
</form>
|
|
@endif
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
|
|
</div>
|