feat: add support bundle notice to viewer

This commit is contained in:
Mikhail Chusavitin
2026-03-16 18:21:34 +03:00
parent a71f55a6f9
commit e5b2ba652c
5 changed files with 69 additions and 9 deletions

View File

@@ -62,7 +62,7 @@ func newHandler(opts HandlerOptions) http.Handler {
return return
} }
page, err := buildPageData([]byte(payload), title) page, err := buildPageData([]byte(payload), title, RenderOptions{})
if err != nil { if err != nil {
if opts.Standalone { if opts.Standalone {
html, renderErr := web.RenderUpload(pageData{ html, renderErr := web.RenderUpload(pageData{

View File

@@ -1,11 +1,15 @@
package viewer package viewer
type pageData struct { type pageData struct {
Title string Title string
HasSnapshot bool HasSnapshot bool
Error string Error string
Meta []fieldRow NoticeTitle string
Sections []sectionView NoticeBody string
DownloadArchiveURL string
DownloadArchiveLabel string
Meta []fieldRow
Sections []sectionView
} }
type sectionView struct { type sectionView struct {

View File

@@ -81,16 +81,33 @@ var preferredColumns = map[string][]string{
"other": {"name", "value", "unit"}, "other": {"name", "value", "unit"},
} }
type RenderOptions struct {
DownloadArchiveURL string
DownloadArchiveLabel string
NoticeTitle string
NoticeBody string
}
func RenderHTML(snapshot []byte, title string) ([]byte, error) { func RenderHTML(snapshot []byte, title string) ([]byte, error) {
page, err := buildPageData(snapshot, title) return RenderHTMLWithOptions(snapshot, title, RenderOptions{})
}
func RenderHTMLWithOptions(snapshot []byte, title string, opts RenderOptions) ([]byte, error) {
page, err := buildPageData(snapshot, title, opts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return web.Render(page) return web.Render(page)
} }
func buildPageData(snapshot []byte, title string) (pageData, error) { func buildPageData(snapshot []byte, title string, opts RenderOptions) (pageData, error) {
page := pageData{Title: title} page := pageData{
Title: title,
NoticeTitle: strings.TrimSpace(opts.NoticeTitle),
NoticeBody: strings.TrimSpace(opts.NoticeBody),
DownloadArchiveURL: strings.TrimSpace(opts.DownloadArchiveURL),
DownloadArchiveLabel: strings.TrimSpace(opts.DownloadArchiveLabel),
}
if strings.TrimSpace(string(snapshot)) == "" { if strings.TrimSpace(string(snapshot)) == "" {
return page, nil return page, nil
} }

View File

@@ -31,6 +31,10 @@ body {
} }
.page-header { .page-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 16px;
padding: 24px 28px 18px; padding: 24px 28px 18px;
border-bottom: 1px solid rgba(0, 0, 0, 0.08); border-bottom: 1px solid rgba(0, 0, 0, 0.08);
} }
@@ -46,6 +50,22 @@ body {
color: var(--muted); color: var(--muted);
} }
.header-actions {
display: flex;
align-items: center;
}
.header-action {
display: inline-block;
text-decoration: none;
border-radius: 999px;
background: var(--accent);
color: #fff;
padding: 10px 16px;
font-weight: 700;
white-space: nowrap;
}
.page-main { .page-main {
width: min(1500px, calc(100vw - 32px)); width: min(1500px, calc(100vw - 32px));
margin: 0 auto; margin: 0 auto;
@@ -54,6 +74,7 @@ body {
.empty-panel, .empty-panel,
.meta-panel, .meta-panel,
.notice-panel,
.section-card, .section-card,
.upload-panel { .upload-panel {
background: var(--panel); background: var(--panel);
@@ -67,6 +88,7 @@ body {
.empty-panel h2, .empty-panel h2,
.section-card h2, .section-card h2,
.meta-panel h2, .meta-panel h2,
.notice-panel h2,
.upload-panel h2 { .upload-panel h2 {
display: block; display: block;
margin: 0 0 12px; margin: 0 0 12px;
@@ -74,6 +96,7 @@ body {
} }
.empty-panel p, .empty-panel p,
.notice-panel p,
.upload-panel p { .upload-panel p {
margin: 0; margin: 0;
color: var(--muted); color: var(--muted);
@@ -259,6 +282,10 @@ body {
} }
@media (max-width: 720px) { @media (max-width: 720px) {
.page-header {
flex-direction: column;
}
.page-main { .page-main {
width: min(100vw - 20px, 1500px); width: min(100vw - 20px, 1500px);
} }

View File

@@ -11,9 +11,21 @@
<div> <div>
<h1>{{ .Title }}</h1> <h1>{{ .Title }}</h1>
</div> </div>
{{ if .DownloadArchiveURL }}
<div class="header-actions">
<a class="header-action" href="{{ .DownloadArchiveURL }}">{{ if .DownloadArchiveLabel }}{{ .DownloadArchiveLabel }}{{ else }}Download archive{{ end }}</a>
</div>
{{ end }}
</header> </header>
<main class="page-main"> <main class="page-main">
{{ if .NoticeTitle }}
<section class="notice-panel">
<h2>{{ .NoticeTitle }}</h2>
<p>{{ .NoticeBody }}</p>
</section>
{{ end }}
{{ if .HasSnapshot }} {{ if .HasSnapshot }}
<section class="meta-panel"> <section class="meta-panel">
<h2>Snapshot Metadata</h2> <h2>Snapshot Metadata</h2>