Files
at-container-registry/pkg/appview/templates/pages/digest.html
2026-04-19 17:35:41 -05:00

107 lines
6.2 KiB
HTML

{{ define "digest" }}
<!DOCTYPE html>
<html lang="en">
<head>
{{ template "head" . }}
{{ template "meta" .Meta }}
</head>
<body>
{{ template "nav" . }}
<main id="main-content" class="container mx-auto px-4 py-8">
<div class="space-y-6">
<!-- Breadcrumb -->
<div class="text-sm breadcrumbs min-w-0">
<ul>
<li class="min-w-0"><a href="/u/{{ .Owner.Handle }}" class="link link-primary truncate">{{ .Owner.Handle }}</a></li>
<li class="min-w-0"><a href="/r/{{ .Owner.Handle }}/{{ .Repository }}" class="link link-primary truncate">{{ .Repository }}</a></li>
<li class="min-w-0"><code class="font-mono text-xs truncate">{{ truncateDigest (trimPrefix "sha256:" .Manifest.Digest) 16 }}</code></li>
</ul>
</div>
<!-- Digest Header -->
<div class="card bg-base-200 shadow-sm border border-base-300 p-6 space-y-3">
<div class="flex flex-wrap items-start justify-between gap-4">
<div class="space-y-2 min-w-0">
<!-- Title: tags or truncated digest -->
<div class="flex flex-wrap items-center gap-2">
{{ if .Manifest.Tags }}
<h1 class="text-xl font-bold">{{ range $i, $tag := .Manifest.Tags }}{{ if $i }}{{ if lt $i 3 }}, {{ end }}{{ end }}{{ if lt $i 3 }}{{ $tag }}{{ end }}{{ end }}{{ if gt (len .Manifest.Tags) 3 }} <span class="text-sm font-normal text-base-content/60" title="{{ range $i, $tag := .Manifest.Tags }}{{ if $i }}, {{ end }}{{ $tag }}{{ end }}">+{{ sub (len .Manifest.Tags) 3 }} more</span>{{ end }}</h1>
{{ else }}
<h1 class="text-xl font-bold font-mono" title="{{ .Manifest.Digest }}">{{ truncateDigest (trimPrefix "sha256:" .Manifest.Digest) 16 }}</h1>
{{ end }}
{{ if .Manifest.IsManifestList }}
<span class="badge badge-md badge-soft badge-accent">Multi-arch</span>
{{ else if eq .Manifest.ArtifactType "helm-chart" }}
<span class="badge badge-md badge-soft badge-helm">{{ icon "helm" "size-3" }} Helm</span>
{{ end }}
{{ if .Manifest.HasAttestations }}
<span class="badge badge-md badge-soft badge-success">{{ icon "shield-check" "size-3" }} Attested</span>
{{ end }}
</div>
<!-- Digest (small) -->
<div class="flex items-center gap-2 text-base-content/70">
<code class="font-mono text-xs" title="{{ .Manifest.Digest }}">{{ truncateDigest (trimPrefix "sha256:" .Manifest.Digest) 16 }}</code>
<button class="btn btn-ghost btn-xs" data-action="copy" data-copy="{{ .Manifest.Digest }}" aria-label="Copy digest">{{ icon "copy" "size-3" }}</button>
</div>
</div>
<div class="flex items-center gap-2 shrink-0">
<span class="text-base-content text-sm flex items-center gap-1" title="{{ .Manifest.CreatedAt.Format "2006-01-02T15:04:05Z07:00" }}">{{ icon "history" "size-4" }}{{ timeAgoShort .Manifest.CreatedAt }}</span>
</div>
</div>
{{ if .Manifest.IsManifestList }}
<!-- Architecture Dropdown -->
<div class="flex items-center gap-3 pt-2 border-t border-base-300">
<label for="arch-select" class="text-sm font-medium whitespace-nowrap">{{ icon "cpu" "size-4" }} Architecture</label>
<select id="arch-select" class="select select-sm select-bordered"
name="digest"
hx-get="/api/digest-content/{{ .Owner.Handle }}/{{ .Repository }}"
hx-trigger="change"
hx-target="#digest-content"
hx-swap="innerHTML"
hx-indicator="#arch-loading">
{{ range .Manifest.Platforms }}
<option value="{{ .Digest }}"{{ if eq .Digest $.SelectedPlatform }} selected{{ end }}>{{ .OS }}/{{ .Architecture }}{{ if .Variant }}/{{ .Variant }}{{ end }}{{ if .CompressedSize }} ({{ humanizeBytes .CompressedSize }}){{ end }}</option>
{{ end }}
</select>
<span id="arch-loading" class="htmx-indicator" aria-hidden="true">
{{ icon "loader" "size-4 animate-spin" }}
</span>
</div>
{{ end }}
</div>
<!-- Upgrade Banner (HTMX lazy-loaded) -->
<div id="upgrade-banner"
hx-get="/api/upgrade-banner/{{ .Owner.Handle }}/{{ .Repository }}?digest={{ .Manifest.Digest }}{{ if .Manifest.HoldEndpoint }}&holdEndpoint={{ .Manifest.HoldEndpoint }}{{ end }}"
hx-trigger="load"
hx-swap="innerHTML">
</div>
<!-- Content: Layers + Vulnerabilities -->
<div id="digest-content">
{{ if .Manifest.IsManifestList }}
<!-- Auto-load selected platform -->
{{ if .Manifest.Platforms }}
<div hx-get="/api/digest-content/{{ .Owner.Handle }}/{{ .Repository }}?digest={{ .SelectedPlatform }}"
hx-trigger="load"
hx-target="#digest-content"
hx-swap="innerHTML"
class="flex items-center justify-center py-12">
{{ icon "loader" "size-6 animate-spin text-base-content/40" }}
<span class="ml-2 text-base-content/60">Loading layers and vulnerabilities...</span>
</div>
{{ end }}
{{ else }}
{{ template "digest-content" . }}
{{ end }}
</div>
</div>
</main>
{{ template "footer" . }}
</body>
</html>
{{ end }}