228 lines
16 KiB
PHP
228 lines
16 KiB
PHP
<x-filament-panels::page>
|
|
@php
|
|
$supportUpdateAuthUser = auth()->user();
|
|
$supportCanRunUpdate = $supportUpdateAuthUser && method_exists($supportUpdateAuthUser, 'hasAnyRole') && $supportUpdateAuthUser->hasAnyRole(['super-admin', 'admin', 'amministratore']);
|
|
@endphp
|
|
|
|
<div class="space-y-4 text-xs">
|
|
<div class="rounded-xl border border-sky-200 bg-sky-50 p-4">
|
|
<div class="flex flex-wrap items-start justify-between gap-3">
|
|
<div>
|
|
<div class="text-sm font-semibold text-sky-900">Launcher esterno per update e sync Git</div>
|
|
<div class="mt-1 text-[11px] text-sky-800">
|
|
Usa questa pagina per lanciare aggiornamenti senza restare dentro la pagina completa Modifiche mentre Livewire e i file vengono riallineati. Il flusso principale da Gitea ora blocca nuove richieste, crea il backup pre-update, aggiorna DB e ricostruisce l'app prima di riaprire il nodo.
|
|
</div>
|
|
</div>
|
|
<div class="flex flex-wrap gap-2">
|
|
<a href="{{ \App\Filament\Pages\Supporto\Modifiche::getUrl(panel: 'admin-filament') }}" class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-xs font-medium text-sky-900 ring-1 ring-sky-200 hover:bg-sky-100">
|
|
Apri Modifiche completo
|
|
</a>
|
|
<x-filament::button size="sm" color="gray" wire:click="reloadDashboardData">
|
|
Rileggi stato
|
|
</x-filament::button>
|
|
</div>
|
|
</div>
|
|
@if(! $supportCanRunUpdate)
|
|
<div class="mt-3 rounded-md border border-amber-300 bg-amber-50 px-3 py-2 text-[11px] text-amber-900">
|
|
I lanci update/sync sono abilitati solo per super-admin, admin e amministratore.
|
|
</div>
|
|
@endif
|
|
</div>
|
|
|
|
<div class="grid gap-4 xl:grid-cols-[1.2fr_0.8fr]">
|
|
<div class="rounded-xl border bg-white p-4">
|
|
<div class="text-sm font-semibold text-slate-900">Refresh nodo da Gitea</div>
|
|
<div class="mt-1 text-[11px] text-slate-500">Flusso consigliato per staging e nodi interni: backup, finestra protetta, sync Git, dipendenze, migrate e cache rebuild.</div>
|
|
|
|
@if(! $this->ticketAttachmentMetadataReady)
|
|
<div class="mt-3 rounded-lg border border-amber-300 bg-amber-50 p-3 text-[11px] text-amber-900">
|
|
Il nodo non ha ancora la colonna <span class="font-mono">ticket_attachments.metadata</span>. Finche non applichi le migration da questa pagina, GPS ed EXIF dei ticket non possono essere persistiti correttamente.
|
|
</div>
|
|
@endif
|
|
|
|
<div class="mt-3 grid gap-2 sm:grid-cols-3">
|
|
<label class="block">
|
|
<span class="mb-1 block text-[11px] font-medium">Remote</span>
|
|
<input type="text" wire:model="gitRemote" class="w-full rounded-md border-gray-300 text-xs" />
|
|
</label>
|
|
<label class="block">
|
|
<span class="mb-1 block text-[11px] font-medium">Branch</span>
|
|
<input type="text" wire:model="gitBranch" class="w-full rounded-md border-gray-300 text-xs" />
|
|
</label>
|
|
<label class="inline-flex items-center gap-2 rounded-md border bg-white px-2 py-1.5 text-[11px] sm:mt-6">
|
|
<input type="checkbox" wire:model="gitForce" class="rounded border-gray-300" />
|
|
Force con working tree sporco
|
|
</label>
|
|
</div>
|
|
|
|
<div class="mt-3 flex flex-wrap gap-2">
|
|
<x-filament::button size="sm" color="success" wire:click="runNodeRefresh" :disabled="!$supportCanRunUpdate">
|
|
Aggiorna nodo completo da Gitea
|
|
</x-filament::button>
|
|
<x-filament::button size="sm" color="warning" wire:click="runNodeRefresh" :disabled="!$supportCanRunUpdate">
|
|
Aggiorna staging da Gitea
|
|
</x-filament::button>
|
|
<x-filament::button size="sm" color="gray" wire:click="runNodeRefreshFallback" :disabled="!$supportCanRunUpdate">
|
|
Refresh di riserva senza maintenance
|
|
</x-filament::button>
|
|
<x-filament::button size="sm" wire:click="runGitSync" :disabled="!$supportCanRunUpdate">
|
|
Solo sync Git avanzata
|
|
</x-filament::button>
|
|
<x-filament::button size="sm" color="info" wire:click="refreshUpdateProgress" :disabled="!$this->updateInProgress">
|
|
Aggiorna avanzamento refresh
|
|
</x-filament::button>
|
|
</div>
|
|
|
|
<div class="mt-3 rounded-lg border border-amber-200 bg-amber-50 p-3 text-[11px] text-amber-900">
|
|
Il pulsante <span class="font-semibold">Aggiorna staging da Gitea</span> esegue il refresh completo del nodo: backup pre-update, maintenance mode per bloccare nuove operazioni utente, sync da Gitea, <span class="font-mono">composer install</span>, tentativo di build frontend se disponibile, <span class="font-mono">migrate --force</span>, pulizia cache, rebuild Blade e riapertura automatica del sistema.
|
|
</div>
|
|
|
|
<div class="mt-3 rounded-lg border border-slate-200 bg-slate-50 p-3 text-[11px] text-slate-600">
|
|
Se la macchina remota fallisce su <span class="font-mono">Maintenance mode non attivata</span>, prima allinea il nodo con <span class="font-semibold">Solo sync Git avanzata</span> e poi usa <span class="font-semibold">Refresh di riserva senza maintenance</span>. E un percorso di recupero per nodi dove il blocco accessi Laravel non parte correttamente.
|
|
</div>
|
|
|
|
@if($this->updateInProgress)
|
|
<div class="mt-3 rounded-lg border bg-slate-50 p-3" wire:poll.2s="refreshUpdateProgress">
|
|
@else
|
|
<div class="mt-3 rounded-lg border bg-slate-50 p-3">
|
|
@endif
|
|
<div class="mb-1 flex items-center justify-between text-[11px] text-gray-600">
|
|
<span class="font-semibold">Avanzamento refresh nodo</span>
|
|
<span class="font-mono">{{ (int) $this->updateProgressPercent }}%</span>
|
|
</div>
|
|
<div class="h-2 w-full overflow-hidden rounded bg-gray-200">
|
|
<div class="h-2 {{ $this->updateProgressStatus === 'failed' ? 'bg-rose-500' : 'bg-emerald-500' }}" style="width: {{ max(0, min(100, (int) $this->updateProgressPercent)) }}%"></div>
|
|
</div>
|
|
<div class="mt-1 text-[11px] text-gray-600">{{ $this->updateProgressMessage }}</div>
|
|
@if(filled($this->lastUpdateIssue))
|
|
<div class="mt-2 rounded border border-amber-300 bg-amber-50 px-2 py-2 text-[11px] text-amber-900">{{ $this->lastUpdateIssue }}</div>
|
|
@endif
|
|
</div>
|
|
|
|
@if(filled($this->lastUpdateOutput))
|
|
<div class="mt-3 rounded-lg border bg-slate-950 p-3">
|
|
<div class="mb-1 text-[11px] font-semibold text-slate-200">Output completo ultimo refresh nodo</div>
|
|
<pre class="max-h-64 overflow-auto whitespace-pre-wrap text-[11px] leading-relaxed text-slate-100">{{ $this->lastUpdateOutput }}</pre>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
|
|
<div class="rounded-xl border bg-white p-4">
|
|
<div class="text-sm font-semibold text-slate-900">Stato nodo</div>
|
|
<div class="mt-3 space-y-1 text-[11px] text-slate-600">
|
|
<div>Repository Git sorgente: <span class="font-mono font-medium">{{ $this->gitWorkspacePath ?? '-' }}</span></div>
|
|
<div>Branch locale: <span class="font-mono font-medium">{{ $this->gitCurrentBranch ?? '-' }}</span></div>
|
|
<div>Commit deploy/ultimo sync: <span class="font-mono font-medium">{{ $this->gitCurrentCommit ?? '-' }}</span></div>
|
|
<div>Data commit deploy: <span class="font-medium">{{ $this->gitCurrentCommitDate ?? '-' }}</span></div>
|
|
@if($this->gitStatusUsesSyncSummary && filled($this->gitSourceCommit) && $this->gitSourceCommit !== $this->gitCurrentCommit)
|
|
<div>Commit repository sorgente cache: <span class="font-mono font-medium">{{ $this->gitSourceCommit }}</span></div>
|
|
<div>Data commit repository sorgente: <span class="font-medium">{{ $this->gitSourceCommitDate ?? '-' }}</span></div>
|
|
@endif
|
|
<div>Commit remoto: <span class="font-mono font-medium">{{ $this->gitRemoteCommit ?? '-' }}</span></div>
|
|
<div>Data commit remoto: <span class="font-medium">{{ $this->gitRemoteCommitDate ?? '-' }}</span></div>
|
|
<div>Tracking: <span class="font-medium">{{ $this->gitAheadBehind }}</span></div>
|
|
<div>Aggiornamenti da caricare sul nodo: <span class="font-semibold {{ (int) $this->pendingGitCommitCount > 0 ? 'text-amber-700' : 'text-emerald-700' }}">{{ $this->gitWorkspacePath === null && filled($this->pendingGitPreviewIssue) ? 'n/d' : (int) $this->pendingGitCommitCount }}</span></div>
|
|
<div>Commit locali da inviare: <span class="font-semibold {{ (int) $this->gitAheadCount > 0 ? 'text-sky-700' : 'text-slate-700' }}">{{ (int) $this->gitAheadCount }}</span></div>
|
|
<div>Working tree: <span class="font-medium {{ $this->gitWorkingTreeDirty ? 'text-rose-700' : 'text-emerald-700' }}">{{ $this->gitWorkingTreeDirty ? 'sporco' : 'pulito' }}</span></div>
|
|
<div>Ultima sync Git: <span class="font-medium">{{ $this->lastGitSyncAt ?? '-' }}</span></div>
|
|
<div>Ultimo update: <span class="font-medium">{{ $this->lastUpdateAt ?? '-' }}</span></div>
|
|
</div>
|
|
|
|
<div class="mt-3 rounded-lg border border-slate-200 bg-slate-50 p-3 text-[11px] text-slate-600">
|
|
Il flusso consigliato del nodo e: push su Gitea, poi "Aggiorna staging da Gitea" da questa pagina. I dati utente non vengono distribuiti via Git: per questo il launcher esegue prima il backup pre-update e poi una finestra di maintenance per evitare scritture concorrenti durante il riallineamento del nodo.
|
|
</div>
|
|
|
|
@if(filled($this->pendingGitPreviewIssue))
|
|
<div class="mt-3 rounded-lg border border-amber-300 bg-amber-50 p-3 text-[11px] text-amber-900">
|
|
{{ $this->pendingGitPreviewIssue }}
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid gap-4 xl:grid-cols-[1.2fr_0.8fr]">
|
|
<div class="rounded-xl border bg-white p-4">
|
|
<div class="text-sm font-semibold text-slate-900">Aggiornamento distribution</div>
|
|
<div class="mt-1 text-[11px] text-slate-500">Usare solo quando il manifest update sul server distribution e valido.</div>
|
|
|
|
<div class="mt-3 grid gap-2 sm:grid-cols-4">
|
|
<label class="block">
|
|
<span class="mb-1 block text-[11px] font-medium">Canale</span>
|
|
<select wire:model="updateChannel" class="w-full rounded-md border-gray-300 text-xs">
|
|
<option value="free">free</option>
|
|
<option value="licensed">licensed</option>
|
|
</select>
|
|
</label>
|
|
<label class="inline-flex items-center gap-2 rounded-md border bg-white px-2 py-1.5 text-[11px] sm:mt-6">
|
|
<input type="checkbox" wire:model="updateDryRun" class="rounded border-gray-300" />
|
|
Dry run
|
|
</label>
|
|
<label class="inline-flex items-center gap-2 rounded-md border bg-white px-2 py-1.5 text-[11px] sm:mt-6">
|
|
<input type="checkbox" wire:model="updateForce" class="rounded border-gray-300" />
|
|
Force
|
|
</label>
|
|
<label class="inline-flex items-center gap-2 rounded-md border border-amber-300 bg-amber-50 px-2 py-1.5 text-[11px] text-amber-900 sm:mt-6">
|
|
<input type="checkbox" wire:model="updateSkipBackup" class="rounded border-gray-300" />
|
|
Salta backup
|
|
</label>
|
|
</div>
|
|
|
|
<div class="mt-3 flex flex-wrap gap-2">
|
|
<x-filament::button size="sm" color="success" wire:click="runMaintenanceMigrate" :disabled="!$supportCanRunUpdate">
|
|
Applica migration
|
|
</x-filament::button>
|
|
<x-filament::button size="sm" wire:click="runUpdate" :disabled="!$supportCanRunUpdate">
|
|
Lancia aggiornamento
|
|
</x-filament::button>
|
|
<x-filament::button size="sm" color="warning" wire:click="runUpdateFallback" :disabled="!$supportCanRunUpdate">
|
|
Lancia aggiornamento (riserva)
|
|
</x-filament::button>
|
|
<x-filament::button size="sm" color="info" wire:click="runUpdateConnectivityCheck">
|
|
Check connettivita update
|
|
</x-filament::button>
|
|
<x-filament::button size="sm" color="gray" wire:click="runMaintenanceOptimizeClear" :disabled="!$supportCanRunUpdate">
|
|
optimize:clear
|
|
</x-filament::button>
|
|
<x-filament::button size="sm" color="gray" wire:click="runMaintenanceViewRebuild" :disabled="!$supportCanRunUpdate">
|
|
Rebuild view
|
|
</x-filament::button>
|
|
</div>
|
|
|
|
@if($this->updateInProgress)
|
|
<div class="mt-3 rounded-lg border bg-slate-50 p-3" wire:poll.2s="refreshUpdateProgress">
|
|
@else
|
|
<div class="mt-3 rounded-lg border bg-slate-50 p-3">
|
|
@endif
|
|
<div class="mb-1 flex items-center justify-between text-[11px] text-gray-600">
|
|
<span class="font-semibold">Avanzamento aggiornamento</span>
|
|
<span class="font-mono">{{ (int) $this->updateProgressPercent }}%</span>
|
|
</div>
|
|
<div class="h-2 w-full overflow-hidden rounded bg-gray-200">
|
|
<div class="h-2 {{ $this->updateProgressStatus === 'failed' ? 'bg-rose-500' : 'bg-emerald-500' }}" style="width: {{ max(0, min(100, (int) $this->updateProgressPercent)) }}%"></div>
|
|
</div>
|
|
<div class="mt-1 text-[11px] text-gray-600">{{ $this->updateProgressMessage }}</div>
|
|
@if(filled($this->lastUpdateIssue))
|
|
<div class="mt-2 rounded border border-amber-300 bg-amber-50 px-2 py-2 text-[11px] text-amber-900">{{ $this->lastUpdateIssue }}</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
<div class="rounded-xl border bg-white p-4">
|
|
<div class="text-sm font-semibold text-slate-900">Esito e backup</div>
|
|
<div class="mt-3 space-y-1 text-[11px] text-slate-600">
|
|
<div>Exit update: <span class="font-medium">{{ $this->lastUpdateExitCode !== null ? $this->lastUpdateExitCode : '-' }}</span></div>
|
|
<div>Exit sync Git: <span class="font-medium">{{ $this->lastGitSyncExitCode !== null ? $this->lastGitSyncExitCode : '-' }}</span></div>
|
|
<div>Backup snapshot: <span class="font-medium">{{ $this->latestBackupSummary['snapshot_id'] ?? '-' }}</span></div>
|
|
<div>Backup creato il: <span class="font-medium">{{ $this->latestBackupSummary['created_at'] ?? '-' }}</span></div>
|
|
</div>
|
|
|
|
@if(filled($this->lastConnectivityCheckOutput))
|
|
<div class="mt-3 rounded-lg border bg-slate-950 p-3">
|
|
<div class="mb-1 text-[11px] font-semibold text-slate-200">Ultimo check connettivita</div>
|
|
<pre class="max-h-48 overflow-auto whitespace-pre-wrap text-[11px] leading-relaxed text-slate-100">{{ $this->lastConnectivityCheckOutput }}</pre>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</x-filament-panels::page> |