d2d.emegrendeles.hu/resources/views/filament/pages/deployment-package.blade.php
E98Developer 4bb89ae6a1 FIX Deployment csomagoló d2d alapértelmezés és automatikus környezet-állapot
- A célkörnyezet alapértelmezése a d2d (azt frissítjük sűrűbben). A config targets
  tömbjének sorrendje adja az alapértelmezést, ezért csak a sorrend cserélődött.
- A "Környezetek állapota" panel betöltéskor magától lekérdezi a deploy-version.json-t,
  percenkénti cache-sel (a hibás választ is cache-eljük, hogy egy nem válaszoló
  környezet ne lassítsa minden kattintásnál a felületet). A Frissítés gomb kényszerít.
- A panel tömörebb, és valóban két hasábos: a md:grid-cols-2 nincs benne a lefordított
  CSS-ben, ezért saját, media query-s stílussal oldjuk meg - így build nélkül is működik.
- A commitlistában a hash mellett jelöljük, melyik környezet áll azon a commiton:
  zöld a szervertől lekérdezett, szürke a napló szerinti állapot.

Teszt: a beforeEach Http::fake() catch-all stubja minden URL-re illeszkedik és a factory
az első találatot adja vissza, ezért a konkrét választ váró teszt új factory-t kap.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 22:48:09 +02:00

438 lines
25 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@php
// A fázis 1 felülete csak olvas: a git történetet listázza és a kijelölt tartomány
// diffjét mutatja. A számított property-ket egy helyen kérjük le, hogy a hibabanner
// (gitError) már a renderelés elején beállított állapotot lássa.
$commits = $this->commits;
$changeSet = $this->changeSet;
$highlighted = $this->highlightedHashes;
$target = $this->target();
$environments = $this->environmentStatuses;
$recentPackages = $this->recentPackages;
// Filament saját szín-nevei (badge/button komponensek), nem nyers Tailwind osztályok:
// egy új blade-ben használt utility class csak npm run build után kerül a CSS-be, a
// Filament komponensek stílusa viszont már benne van a lefordított bundle-ben.
$statusStyles = [
'A' => ['label' => 'új', 'color' => 'success'],
'M' => ['label' => 'módosult', 'color' => 'warning'],
'D' => ['label' => 'törölt', 'color' => 'danger'],
'R' => ['label' => 'átnevezett', 'color' => 'info'],
'C' => ['label' => 'másolt', 'color' => 'info'],
];
$warningStyles = [
'danger' => 'border-red-300 bg-red-50 text-red-900 dark:border-red-800 dark:bg-red-950 dark:text-red-200',
'warning' => 'border-amber-300 bg-amber-50 text-amber-900 dark:border-amber-800 dark:bg-amber-950 dark:text-amber-200',
'info' => 'border-gray-300 bg-gray-50 text-gray-800 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300',
];
$cardClass = 'p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700';
$commitMarkers = $this->commitMarkers;
@endphp
<x-filament-panels::page>
{{--
Saját stílus, nem Tailwind utility: egy új blade-ben használt osztály csak
npm run build után kerül a bundle-be (a md:grid-cols-2 pl. jelenleg nincs benne),
így a kétoszlopos elrendezés build nélkül is működik.
--}}
<style>
.fi-deployment-env-grid {
display: grid;
gap: 0.75rem;
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.fi-deployment-env-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
</style>
<div class="space-y-6">
<div class="{{ $cardClass }}">
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Deployment csomagoló</h5>
<p class="font-normal text-gray-700 dark:text-gray-400">
Válaszd ki a célkörnyezetet, majd két commitot: a köztük változott fájlok kerülnek majd a csomagba
(a kezdő commit kizárva, a záró beleértve).
</p>
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">
A csomag ide készül: <code>{{ config('deployment.output_path') }}</code>
</p>
</div>
<div class="{{ $cardClass }}">
<div class="flex items-center justify-between gap-3 mb-3">
<h6 class="text-lg font-semibold text-gray-900 dark:text-white">Környezetek állapota</h6>
<x-filament::button size="xs" color="gray" wire:click="fetchAllLiveVersions(true)">
Frissítés
</x-filament::button>
</div>
<div class="fi-deployment-env-grid">
@foreach ($environments as $environment)
<div class="p-3 border rounded-lg {{ $environment['mismatch'] ? $warningStyles['danger'] : 'border-gray-200 dark:border-gray-700' }}">
<div class="flex items-center justify-between gap-2">
<span class="font-semibold text-gray-900 dark:text-white">{{ $environment['target']['label'] }}</span>
@if ($environment['live'] && $environment['live']['ok'])
<span class="font-mono text-xs text-gray-600 dark:text-gray-300">
élő: {{ substr($environment['live']['data']['commit'] ?? '?', 0, 7) }}
</span>
@elseif ($environment['live'])
<span class="text-xs text-gray-400">élő: nem elérhető</span>
@endif
</div>
<div class="mt-1 text-sm text-gray-600 dark:text-gray-300">
@if ($environment['package'])
<span>napló: <code>{{ substr($environment['package']->to_commit, 0, 7) }}</code></span>
<span class="text-gray-400">·</span>
<span>{{ $environment['package']->deployed_at?->format('Y.m.d H:i') }}</span>
@if ($environment['behind'] !== null)
<span class="text-gray-400">·</span>
<span>{{ $environment['behind'] }} commit lemaradás</span>
@endif
@else
<span class="text-gray-400">Még nincs kirakottként megjelölt csomag.</span>
@endif
</div>
@if ($environment['mismatch'])
<p class="mt-1 text-sm font-semibold">
A szerveren futó commit eltér a naplózottól elmaradt vagy félbemaradt feltöltés.
</p>
@endif
</div>
@endforeach
</div>
</div>
@if ($this->lastPackage)
<div class="p-4 border rounded-lg {{ $this->lastPackage['counts']['missing'] > 0 ? $warningStyles['warning'] : 'border-emerald-300 bg-emerald-50 text-emerald-900 dark:border-emerald-800 dark:bg-emerald-950 dark:text-emerald-200' }}">
<p class="font-semibold">Elkészült: {{ $this->lastPackage['name'] }}</p>
<p class="mt-1 text-sm">
{{ $this->lastPackage['counts']['copied'] }} fájl másolva,
{{ $this->lastPackage['counts']['deleted'] }} törlendő,
{{ $this->lastPackage['counts']['skipped'] }} kézzel kivéve.
</p>
<p class="mt-2 text-xs font-mono break-all">{{ $this->lastPackage['path'] }}</p>
@if ($this->lastPackage['counts']['missing'] > 0)
<p class="mt-2 text-sm font-semibold">
Figyelem: {{ $this->lastPackage['counts']['missing'] }} fájl nem került a csomagba,
a listájuk a _MANIFEST.txt végén van.
</p>
@endif
<p class="mt-2 text-sm">
A lépéseket a csomagban lévő <code>_TEENDOK.md</code> tartalmazza.
</p>
</div>
@endif
@if ($this->gitError)
<div class="p-4 border rounded-lg {{ $warningStyles['danger'] }}">
<p class="font-semibold">Git hiba</p>
<p class="mt-1 text-sm">{{ $this->gitError }}</p>
</div>
@elseif (! $this->isRepositoryAvailable())
<div class="p-4 border rounded-lg {{ $warningStyles['danger'] }}">
<p class="font-semibold">Nem érhető el git repó</p>
<p class="mt-1 text-sm">
A(z) <code>{{ config('deployment.repo_path') }}</code> útvonalon nincs git working copy,
vagy a git parancs nem található.
</p>
</div>
@endif
<div class="{{ $cardClass }}">
{{ $this->form }}
</div>
<div class="{{ $cardClass }}">
<div class="flex flex-wrap items-center justify-between gap-4">
<div class="flex flex-wrap items-center gap-3 text-sm">
<span class="text-gray-500 dark:text-gray-400">Tartomány:</span>
@if ($this->fromCommit)
<code class="px-2 py-1 rounded bg-gray-100 dark:bg-gray-900">{{ substr($this->fromCommit, 0, 7) }}</code>
@else
<span class="text-gray-400">nincs kezdő commit</span>
@endif
<span class="text-gray-400"></span>
@if ($this->toCommit)
<code class="px-2 py-1 rounded bg-gray-100 dark:bg-gray-900">{{ substr($this->toCommit, 0, 7) }}</code>
@else
<span class="text-gray-400">nincs záró commit</span>
@endif
@if ($changeSet)
<span class="text-gray-500 dark:text-gray-400">
· {{ $changeSet['counts']['copied'] }} másolandó
@if ($changeSet['counts']['deleted'] > 0)
, {{ $changeSet['counts']['deleted'] }} törlendő
@endif
</span>
@endif
</div>
<div class="flex items-center gap-2">
<x-filament::button size="xs" color="gray" wire:click="swapRange">Csere</x-filament::button>
<x-filament::button size="xs" color="gray" wire:click="clearRange">Törlés</x-filament::button>
</div>
</div>
@if ($target)
<p class="mt-3 text-sm text-gray-500 dark:text-gray-400">
Cél: <strong>{{ $target['label'] }}</strong> a fájlok ide kerülnek majd feltöltésre:
<code>{{ $target['remote_path'] }}</code>
</p>
@endif
</div>
<div class="{{ $cardClass }}">
<h6 class="mb-1 text-lg font-semibold text-gray-900 dark:text-white">
Commitok
<span class="ml-1 text-sm font-normal text-gray-500 dark:text-gray-400">({{ count($commits) }} db)</span>
</h6>
<p class="mb-4 text-xs text-gray-500 dark:text-gray-400">
A hash melletti jelölés mutatja, melyik környezet áll azon a commiton
zöld: a szervertől lekérdezve, szürke: a napló szerint.
</p>
@if ($commits === [])
<p class="text-sm text-gray-500 dark:text-gray-400">Nincs megjeleníthető commit.</p>
@else
<div class="overflow-x-auto">
<table class="w-full text-sm text-left">
<thead class="text-xs uppercase text-gray-600 border-b border-gray-200 dark:text-gray-300 dark:border-gray-700">
<tr>
<th class="py-2 pr-4">Kijelölés</th>
<th class="py-2 pr-4">Hash</th>
<th class="py-2 pr-4">Dátum</th>
<th class="py-2 pr-4">Szerző</th>
<th class="py-2 pr-4">Üzenet</th>
<th class="py-2 text-right">Fájl</th>
</tr>
</thead>
<tbody>
@foreach ($commits as $commit)
@php
$isFrom = $this->fromCommit === $commit['hash'];
$isTo = $this->toCommit === $commit['hash'];
$inRange = in_array($commit['hash'], $highlighted, true);
@endphp
<tr wire:key="commit-{{ $commit['hash'] }}"
class="border-b border-gray-100 dark:border-gray-700 {{ $inRange ? 'bg-primary-50 dark:bg-gray-900' : '' }}">
<td class="py-2 pr-4 whitespace-nowrap">
<div class="flex items-center gap-1">
<x-filament::button size="xs" :color="$isFrom ? 'primary' : 'gray'"
wire:click="selectFrom('{{ $commit['hash'] }}')">
Kezdő
</x-filament::button>
<x-filament::button size="xs" :color="$isTo ? 'primary' : 'gray'"
wire:click="selectTo('{{ $commit['hash'] }}')">
Záró
</x-filament::button>
</div>
</td>
<td class="py-2 pr-4 whitespace-nowrap">
<div class="flex items-center gap-1">
<span class="font-mono text-xs">{{ $commit['short'] }}</span>
{{-- Melyik környezet áll ezen a commiton (élő állapot, vagy napló szerint). --}}
@foreach ($commitMarkers[$commit['hash']] ?? [] as $marker)
<x-filament::badge size="xs" :color="$marker['live'] ? 'success' : 'gray'">
{{ $marker['key'] }}
</x-filament::badge>
@endforeach
</div>
</td>
<td class="py-2 pr-4 whitespace-nowrap text-gray-600 dark:text-gray-300">
{{ \Illuminate\Support\Carbon::parse($commit['date'])->format('Y.m.d H:i') }}
</td>
<td class="py-2 pr-4 whitespace-nowrap text-gray-600 dark:text-gray-300">{{ $commit['author'] }}</td>
<td class="py-2 pr-4 text-gray-800 dark:text-gray-100">{{ $commit['subject'] }}</td>
<td class="py-2 text-right text-gray-500 dark:text-gray-400">{{ $commit['file_count'] ?? '' }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
</div>
@if ($changeSet)
<div class="{{ $cardClass }}">
<h6 class="mb-4 text-lg font-semibold text-gray-900 dark:text-white">
Változott fájlok
<span class="ml-1 text-sm font-normal text-gray-500 dark:text-gray-400">
({{ $changeSet['counts']['total'] }} db)
</span>
</h6>
@foreach ($changeSet['warnings'] as $warning)
<div class="p-4 mb-3 border rounded-lg {{ $warningStyles[$warning['level']] ?? $warningStyles['info'] }}">
<p class="font-semibold">{{ $warning['title'] }}</p>
<p class="mt-1 text-sm">{{ $warning['body'] }}</p>
</div>
@endforeach
@if ($changeSet['files'] !== [])
<div class="overflow-x-auto">
<table class="w-full text-sm text-left">
<thead class="text-xs uppercase text-gray-600 border-b border-gray-200 dark:text-gray-300 dark:border-gray-700">
<tr>
<th class="py-2 pr-4">Csomagba</th>
<th class="py-2 pr-4">Állapot</th>
<th class="py-2 pr-4">Útvonal</th>
<th class="py-2">Művelet</th>
</tr>
</thead>
<tbody>
@foreach ($changeSet['files'] as $file)
@php
$style = $statusStyles[$file['status']] ?? ['label' => $file['status'], 'color' => 'gray'];
$isSkipped = in_array($file['path'], $this->skippedPaths, true);
@endphp
<tr wire:key="file-{{ $loop->index }}" class="border-b border-gray-100 dark:border-gray-700 {{ $file['excluded'] || $isSkipped ? 'opacity-50' : '' }}">
<td class="py-2 pr-4 whitespace-nowrap">
@if ($file['action'] === 'copy')
<input type="checkbox"
wire:click="toggleFile(@js($file['path']))"
@checked(! $isSkipped)
class="rounded border-gray-300 dark:border-gray-600">
@else
<span class="text-gray-300 dark:text-gray-600"></span>
@endif
</td>
<td class="py-2 pr-4 whitespace-nowrap">
<x-filament::badge :color="$style['color']">
{{ $file['status'] }} · {{ $style['label'] }}
</x-filament::badge>
</td>
<td class="py-2 pr-4 font-mono text-xs break-all text-gray-800 dark:text-gray-100">
{{ $file['path'] }}
@if ($file['old_path'])
<span class="block text-gray-400"> {{ $file['old_path'] }}</span>
@endif
</td>
<td class="py-2 whitespace-nowrap text-gray-600 dark:text-gray-300">
@switch($file['action'])
@case('copy') {{ $isSkipped ? 'kézzel kivéve' : 'másolandó' }} @break
@case('delete') törlendő a célgépen @break
@default kihagyva (kizárási lista)
@endswitch
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
@php
$packageCount = count(array_diff($changeSet['copied'], $this->skippedPaths));
@endphp
<div class="flex flex-wrap items-center justify-between gap-4 pt-4 mt-4 border-t border-gray-200 dark:border-gray-700">
<p class="text-sm text-gray-600 dark:text-gray-300">
A csomagba <strong>{{ $packageCount }}</strong> fájl kerül
@if ($changeSet['counts']['deleted'] > 0)
, és {{ $changeSet['counts']['deleted'] }} fájl a törlendők listájára
@endif
@if ($target)
· cél: <strong>{{ $target['label'] }}</strong>
@endif
</p>
<x-filament::button
icon="heroicon-m-archive-box-arrow-down"
wire:click="createPackage"
wire:confirm="Elkészítjük a csomagot: {{ $packageCount }} fájl{{ $target ? ' a(z) '.$target['label'].' környezethez' : '' }}. Folytatod?"
:disabled="$packageCount === 0 && $changeSet['counts']['deleted'] === 0">
Csomag készítése
</x-filament::button>
</div>
</div>
@endif
@if ($recentPackages->isNotEmpty())
<div class="{{ $cardClass }}">
<h6 class="mb-4 text-lg font-semibold text-gray-900 dark:text-white">
Korábbi csomagok
<span class="ml-1 text-sm font-normal text-gray-500 dark:text-gray-400">
({{ $target ? $target['label'] : 'összes' }})
</span>
</h6>
<div class="overflow-x-auto">
<table class="w-full text-sm text-left">
<thead class="text-xs uppercase text-gray-600 border-b border-gray-200 dark:text-gray-300 dark:border-gray-700">
<tr>
<th class="py-2 pr-4">Csomag</th>
<th class="py-2 pr-4">Tartomány</th>
<th class="py-2 pr-4">Fájlok</th>
<th class="py-2 pr-4">Készült</th>
<th class="py-2 pr-4">Kirakva</th>
<th class="py-2 text-right">Műveletek</th>
</tr>
</thead>
<tbody>
@foreach ($recentPackages as $package)
<tr wire:key="package-{{ $package->id }}" class="border-b border-gray-100 dark:border-gray-700">
<td class="py-2 pr-4 font-mono text-xs break-all text-gray-800 dark:text-gray-100">{{ $package->name }}</td>
<td class="py-2 pr-4 font-mono text-xs whitespace-nowrap text-gray-600 dark:text-gray-300">
{{ substr($package->from_commit, 0, 7) }} {{ substr($package->to_commit, 0, 7) }}
</td>
<td class="py-2 pr-4 whitespace-nowrap text-gray-600 dark:text-gray-300">
{{ $package->copied_count }}
@if ($package->deleted_count > 0)
<span class="text-gray-400">/ {{ $package->deleted_count }} törl.</span>
@endif
</td>
<td class="py-2 pr-4 whitespace-nowrap text-gray-600 dark:text-gray-300">
{{ $package->created_at?->format('Y.m.d H:i') }}
</td>
<td class="py-2 pr-4 whitespace-nowrap">
@if ($package->isDeployed())
<span class="px-2 py-0.5 text-xs font-semibold rounded bg-emerald-100 text-emerald-800 dark:bg-emerald-900 dark:text-emerald-200">
{{ $package->deployed_at?->format('Y.m.d H:i') }}
</span>
@else
<span class="text-gray-400"></span>
@endif
</td>
<td class="py-2 whitespace-nowrap">
<div class="flex items-center justify-end gap-1">
@if ($package->zip_path)
<x-filament::button size="xs" color="gray"
wire:click="downloadPackage({{ $package->id }})">
ZIP
</x-filament::button>
@endif
@unless ($package->isDeployed())
<x-filament::button size="xs" color="gray"
wire:click="markDeployed({{ $package->id }})"
wire:confirm="Megjelöljük kirakottként? Innentől ez lesz a következő csomag kezdő commitja ezen a környezeten.">
Kirakva
</x-filament::button>
@endunless
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endif
</div>
</x-filament-panels::page>