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

185 lines
9.4 KiB
HTML

{{ define "diff-content" }}
<!-- Layers + Vulnerabilities Diff -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- Layer Diff (Left) -->
<div class="card bg-base-200 shadow-sm border border-base-300 p-6 space-y-4 min-w-0">
<h2 class="text-lg font-semibold">Layers</h2>
{{ if .LayerDiff }}
<div class="overflow-x-auto">
<table class="table table-xs w-full">
<thead>
<tr class="text-xs">
<th class="w-6"></th>
<th class="w-8">#</th>
<th>Command</th>
<th class="text-right w-24">Size</th>
</tr>
</thead>
<tbody>
{{ range .LayerDiff }}
<tr class="{{ if eq .Status "added" }}bg-success/10{{ else if eq .Status "removed" }}bg-error/10{{ else if eq .Status "rebuilt" }}bg-warning/10{{ else }}opacity-60{{ end }}">
<td class="font-mono text-xs text-center font-bold {{ if eq .Status "added" }}text-success{{ else if eq .Status "removed" }}text-error{{ else if eq .Status "rebuilt" }}text-warning{{ end }}">{{ if eq .Status "added" }}+{{ else if eq .Status "removed" }}-{{ else if eq .Status "rebuilt" }}~{{ end }}</td>
<td class="font-mono text-xs">{{ .Layer.Index }}</td>
<td>
{{ if .Layer.Command }}
<code class="font-mono text-xs break-all line-clamp-2" title="{{ .Layer.Command }}">{{ .Layer.Command }}</code>
{{ end }}
</td>
<td class="text-right text-sm whitespace-nowrap">
{{ if not .Layer.EmptyLayer }}{{ humanizeBytes .Layer.Size }}{{ end }}
{{ if and (eq .Status "rebuilt") .PrevLayer }}
{{ if ne .Layer.Size .PrevLayer.Size }}
<span class="text-xs text-base-content/70">({{ humanizeByteDelta (sub64 .Layer.Size .PrevLayer.Size) }})</span>
{{ end }}
{{ end }}
</td>
</tr>
{{ end }}
</tbody>
</table>
</div>
{{ else }}
<p class="text-base-content/60">No layer information available</p>
{{ end }}
</div>
<!-- Vulnerability Diff (Right) -->
<div class="card bg-base-200 shadow-sm border border-base-300 p-6 space-y-4 min-w-0">
<h2 class="text-lg font-semibold">Vulnerabilities</h2>
{{ if not .HasVulnData }}
<p class="text-base-content/60">Vulnerability scan data not available for both manifests</p>
{{ else }}
<!-- Fixed Vulns -->
{{ if .FixedVulns }}
<div class="collapse collapse-arrow bg-success/5 border border-success/20 rounded-lg">
<input type="checkbox" checked aria-label="Toggle fixed vulnerabilities ({{ len .FixedVulns }})" />
<div class="collapse-title font-medium text-sm flex items-center gap-2">
{{ icon "shield-check" "size-4 text-success" }}
Fixed ({{ len .FixedVulns }})
</div>
<div class="collapse-content">
<div class="overflow-x-auto">
<table class="table table-xs w-full">
<thead>
<tr class="text-xs">
<th>CVE</th>
<th>Severity</th>
<th>Package</th>
<th>Was</th>
</tr>
</thead>
<tbody>
{{ range .FixedVulns }}
<tr>
<td>
{{ if .CVEURL }}<a href="{{ .CVEURL }}" target="_blank" rel="noopener" class="link link-primary text-xs font-mono">{{ .CVEID }}</a>
{{ else }}<span class="text-xs font-mono">{{ .CVEID }}</span>{{ end }}
</td>
<td>
<span class="badge badge-xs {{ if eq .Severity "Critical" }}badge-error{{ else if eq .Severity "High" }}badge-warning{{ else if eq .Severity "Medium" }}badge-info{{ else }}badge-ghost{{ end }}">{{ .Severity }}</span>
</td>
<td class="text-xs">{{ .Package }}</td>
<td class="text-xs font-mono">{{ .Version }}</td>
</tr>
{{ end }}
</tbody>
</table>
</div>
</div>
</div>
{{ end }}
<!-- New Vulns -->
{{ if .NewVulns }}
<div class="collapse collapse-arrow bg-error/5 border border-error/20 rounded-lg">
<input type="checkbox" checked aria-label="Toggle new vulnerabilities ({{ len .NewVulns }})" />
<div class="collapse-title font-medium text-sm flex items-center gap-2">
{{ icon "alert-triangle" "size-4 text-error" }}
New ({{ len .NewVulns }})
</div>
<div class="collapse-content">
<div class="overflow-x-auto">
<table class="table table-xs w-full">
<thead>
<tr class="text-xs">
<th>CVE</th>
<th>Severity</th>
<th>Package</th>
<th>Version</th>
<th>Fix</th>
</tr>
</thead>
<tbody>
{{ range .NewVulns }}
<tr>
<td>
{{ if .CVEURL }}<a href="{{ .CVEURL }}" target="_blank" rel="noopener" class="link link-primary text-xs font-mono">{{ .CVEID }}</a>
{{ else }}<span class="text-xs font-mono">{{ .CVEID }}</span>{{ end }}
</td>
<td>
<span class="badge badge-xs {{ if eq .Severity "Critical" }}badge-error{{ else if eq .Severity "High" }}badge-warning{{ else if eq .Severity "Medium" }}badge-info{{ else }}badge-ghost{{ end }}">{{ .Severity }}</span>
</td>
<td class="text-xs">{{ .Package }}</td>
<td class="text-xs font-mono">{{ .Version }}</td>
<td class="text-xs font-mono">{{ .FixedIn }}</td>
</tr>
{{ end }}
</tbody>
</table>
</div>
</div>
</div>
{{ end }}
<!-- Unchanged Vulns -->
{{ if .UnchangedVulns }}
<div class="collapse collapse-arrow bg-base-200/50 border border-base-300 rounded-lg">
<input type="checkbox" aria-label="Toggle unchanged vulnerabilities ({{ len .UnchangedVulns }})" />
<div class="collapse-title font-medium text-sm text-base-content/60">
Unchanged ({{ len .UnchangedVulns }})
</div>
<div class="collapse-content">
<div class="overflow-x-auto">
<table class="table table-xs w-full">
<thead>
<tr class="text-xs">
<th>CVE</th>
<th>Severity</th>
<th>Package</th>
<th>Version</th>
<th>Fix</th>
</tr>
</thead>
<tbody>
{{ range .UnchangedVulns }}
<tr>
<td>
{{ if .CVEURL }}<a href="{{ .CVEURL }}" target="_blank" rel="noopener" class="link link-primary text-xs font-mono">{{ .CVEID }}</a>
{{ else }}<span class="text-xs font-mono">{{ .CVEID }}</span>{{ end }}
</td>
<td>
<span class="badge badge-xs {{ if eq .Severity "Critical" }}badge-error{{ else if eq .Severity "High" }}badge-warning{{ else if eq .Severity "Medium" }}badge-info{{ else }}badge-ghost{{ end }}">{{ .Severity }}</span>
</td>
<td class="text-xs">{{ .Package }}</td>
<td class="text-xs font-mono">{{ .Version }}</td>
<td class="text-xs font-mono">{{ .FixedIn }}</td>
</tr>
{{ end }}
</tbody>
</table>
</div>
</div>
</div>
{{ end }}
{{ if and (not .FixedVulns) (not .NewVulns) (not .UnchangedVulns) }}
<p class="text-base-content/60">No vulnerabilities found in either manifest</p>
{{ end }}
{{ end }}
</div>
</div>
{{ end }}