@use('App\Models\UpdateVersion') @php /* | Requires in scope: $version, $counts (activity by status), $isLatest, | $canManage. Everything reads the collection the controller loaded plus the | one grouped activity query the page already made. */ $downloads = (int) ($counts['downloaded'] ?? 0); $installed = (int) ($counts['installed'] ?? 0); $failed = (int) ($counts['failed'] ?? 0); $hasPackage = $version->hasPackage(); $signed = filled($version->signature); $summary = \Illuminate\Support\Str::of((string) $version->release_notes) ->replaceMatches('/^#{1,6}\s*/m', '') ->replaceMatches('/[*`>]/', '') ->squish() ->limit(90); @endphp {{-- Version: the number, what it is called, and the two labels that change how it should be read at a glance. --}}
$hasPackage, 'bg-slate-100 text-slate-400 ring-slate-500/20 dark:bg-white/5 dark:text-slate-500 dark:ring-white/10' => ! $hasPackage, ]) aria-hidden="true"> @if ($isLatest) Latest @endif {{ $version->product === UpdateVersion::PRODUCT_AI ? 'AI' : 'CMS' }} {{ $version->release_name ?: 'No release name' }}
{{-- Release notes: a summary in the row, the full text one click away without leaving the page. --}} @if (filled($summary)) @else No release notes @endif {{ ucfirst($version->channel) }} {{-- Package: size, and whether there is anything publishable here at all. --}} @if ($hasPackage) {{ $version->file_size >= 1048576 ? number_format($version->file_size / 1048576, 1).' MB' : number_format($version->file_size / 1024).' KB' }} {{ $signed ? 'Signed' : 'Unsigned' }} @else No package @endif
@if ($version->security_update) Security @endif @if ($version->force_update) Force @endif @if ($version->package_type === 'patch') Patch @endif @if (! $version->security_update && ! $version->force_update && $version->package_type !== 'patch') — @endif
@if ($version->published_at)
{{ $version->published_at->format('d M Y') }} {{ $version->published_at->diffForHumans(short: true) }}
@else Not published @endif {{-- Downloads relative to the most-downloaded release, so the bar answers "is this one being taken up?" rather than showing a raw number twice. --}} {{ number_format($downloads) }} {{-- Relative to the most-downloaded release, computed once for the whole table rather than per row. --}} @if ($installed + $failed > 0) {{ round($installed / ($installed + $failed) * 100) }}% ok @else no installs @endif View details Open release page @if ($canManage) Edit & upload package @endif @if ($hasPackage)
Copy checksum @endif @if ($canManage)
{{-- Publish is refused server-side without a package and an offline signature. The menu says so up front rather than letting the click produce a red banner. --}} @if (! $version->isPublished()) @if ($hasPackage && $signed)
@csrf Publish
@else Publish ({{ $hasPackage ? 'unsigned' : 'no package' }}) @endif @else
@csrf Hide from installs
@csrf Roll back
@endif
{{-- Deleting a published release is refused by the server; the hint names the way out rather than just greying it. --}} @if ($version->isPublished()) Delete (hide it first) @else
@csrf @method('DELETE') Delete release
@endif @endif
{{-- Expandable release notes. A real table row so the columns above it stay aligned; hidden until asked for, and moved with its version when sorted. --}} @if (filled($version->release_notes)) {{-- The notes come from the Alpine model the page already carries, not a second inline copy — with 3 KB of notes per release the duplicate was a third of the page's HTML. --}}
Open the full release page @endif