feat(web): make footer legal links configurable

Add a "main.footer-links" config option so the footer Imprint and
Privacy Policy links can point at internal pages (default) or external
URLs. External http(s) targets open in a new tab; empty/unset values
fall back to the built-in /imprint and /privacy routes, keeping the
existing ./var/*.tmpl override mechanism intact.

Closes #517

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: c5dca72c848f
This commit is contained in:
2026-06-17 17:29:50 +02:00
parent 9d1efcd55d
commit 411bc9b317
6 changed files with 75 additions and 2 deletions

View File

@@ -74,6 +74,32 @@ type PlotConfiguration struct {
ColorScheme []string `json:"color-scheme"`
}
const (
defaultImprintLink = "/imprint"
defaultPrivacyLink = "/privacy"
)
// FooterLink is the render-time representation of a single footer legal link.
type FooterLink struct {
URL string // Resolved target: internal path or external URL.
External bool // True if the target is an external URL (opened in a new tab).
}
// FooterLinks holds the resolved legal links shown in the site footer.
type FooterLinks struct {
Imprint FooterLink
Privacy FooterLink
}
// resolveFooterLink falls back to def when v is empty and flags external URLs.
func resolveFooterLink(v, def string) FooterLink {
if v == "" {
v = def
}
external := strings.HasPrefix(v, "http://") || strings.HasPrefix(v, "https://")
return FooterLink{URL: v, External: external}
}
var UIDefaults = WebConfig{
JobList: JobListConfig{
UsePaging: false,
@@ -266,6 +292,7 @@ type Page struct {
Config map[string]any // UI settings for the currently logged in user (e.g. line width, ...)
Resampling *config.ResampleConfig // If not nil, defines resampling trigger and resolutions
Redirect string // The originally requested URL, for intermediate login handling
FooterLinks FooterLinks // Resolved legal links for the site footer
}
func RenderTemplate(rw http.ResponseWriter, file string, page *Page) {
@@ -289,6 +316,11 @@ func RenderTemplate(rw http.ResponseWriter, file string, page *Page) {
}
}
page.FooterLinks = FooterLinks{
Imprint: resolveFooterLink(config.Keys.FooterLinks.Imprint, defaultImprintLink),
Privacy: resolveFooterLink(config.Keys.FooterLinks.Privacy, defaultPrivacyLink),
}
cclog.Debugf("Page config : %v\n", page.Config)
if err := t.Execute(rw, page); err != nil {
cclog.Errorf("Template error: %s", err.Error())