A "Csomag készítése" gomb a felületen láthatatlan volt: a text-white benne van a lefordított CSS-ben, a bg-primary-600 viszont nincs, így fehér szöveg került fehér kártyára. Ugyanezért jelentek meg a státusz-badge-ek is színtelen szövegként. Ok: egy új blade fájlban használt Tailwind utility class csak npm run build után kerül be a bundle-be (a theme.css scanneli a resources/views/filament mappát, de a CSS-t nem generálja újra magától). Ezért a kézzel stílusozott elemek helyett a Filament saját button/badge komponenseit használjuk, amiknek a stílusa már a lefordított CSS-ben van - így a felület build nélkül is helyesen jelenik meg. A színes figyelmeztető dobozok maradtak nyers utility class-okkal: azok build hiányában is olvashatók (keretes doboz), csak a színüket kapják meg npm run build után. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
415 lines
24 KiB
PHP
415 lines
24 KiB
PHP
@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';
|
||
@endphp
|
||
|
||
<x-filament-panels::page>
|
||
<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 }}">
|
||
<h6 class="mb-4 text-lg font-semibold text-gray-900 dark:text-white">Környezetek állapota</h6>
|
||
|
||
<div class="grid gap-4 md:grid-cols-2">
|
||
@foreach ($environments as $environment)
|
||
<div class="p-4 border rounded-lg {{ $environment['mismatch'] ? $warningStyles['danger'] : 'border-gray-200 dark:border-gray-700' }}">
|
||
<div class="flex items-start justify-between gap-3">
|
||
<div>
|
||
<p class="font-semibold text-gray-900 dark:text-white">{{ $environment['target']['label'] }}</p>
|
||
<p class="text-xs font-mono text-gray-500 dark:text-gray-400">{{ $environment['target']['remote_path'] }}</p>
|
||
</div>
|
||
<x-filament::button size="xs" color="gray"
|
||
wire:click="fetchLiveVersion('{{ $environment['target']['key'] }}')">
|
||
Élő állapot
|
||
</x-filament::button>
|
||
</div>
|
||
|
||
<div class="mt-3 space-y-1 text-sm text-gray-600 dark:text-gray-300">
|
||
@if ($environment['package'])
|
||
<p>
|
||
Utoljára kirakva:
|
||
<code>{{ substr($environment['package']->to_commit, 0, 7) }}</code>
|
||
· {{ $environment['package']->deployed_at?->format('Y.m.d H:i') }}
|
||
</p>
|
||
@if ($environment['behind'] !== null)
|
||
<p>
|
||
Lemaradás a kiválasztott branchhez képest:
|
||
<strong>{{ $environment['behind'] }}</strong> commit
|
||
</p>
|
||
@endif
|
||
@else
|
||
<p class="text-gray-400">Még nincs kirakottként megjelölt csomag.</p>
|
||
@endif
|
||
|
||
@if ($environment['live'])
|
||
@if ($environment['live']['ok'])
|
||
<p>
|
||
A szerver szerint:
|
||
<code>{{ substr($environment['live']['data']['commit'] ?? '?', 0, 7) }}</code>
|
||
@if (($environment['live']['data']['packaged_at'] ?? null))
|
||
· {{ \Illuminate\Support\Carbon::parse($environment['live']['data']['packaged_at'])->format('Y.m.d H:i') }}
|
||
@endif
|
||
</p>
|
||
@else
|
||
<p class="text-gray-400">Élő állapot nem lekérdezhető: {{ $environment['live']['error'] }}</p>
|
||
@endif
|
||
@endif
|
||
|
||
@if ($environment['mismatch'])
|
||
<p class="font-semibold">
|
||
A szerveren futó commit eltér a naplózottól — elmaradt vagy félbemaradt feltöltés.
|
||
</p>
|
||
@endif
|
||
</div>
|
||
</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-4 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>
|
||
|
||
@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 font-mono text-xs whitespace-nowrap">{{ $commit['short'] }}</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>
|