Add white label template for starter
This commit is contained in:
@@ -0,0 +1,226 @@
|
||||
package page
|
||||
|
||||
import (
|
||||
. "ersteller-lib"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
. "maragu.dev/gomponents"
|
||||
. "maragu.dev/gomponents/components"
|
||||
. "maragu.dev/gomponents/html"
|
||||
)
|
||||
|
||||
const DeIndexUrl = "/de/index"
|
||||
const EnIndexUrl = "/en/index"
|
||||
const DefaultLanguage = En
|
||||
|
||||
var _texts *Texts
|
||||
|
||||
func CreatePage(req HtmxContext, metadata PageWebsiteMetaData, content ...Node) {
|
||||
metadata.Lang = req.GetLanguage()
|
||||
|
||||
var contentForFunction Node
|
||||
if len(content) > 0 {
|
||||
contentForFunction = Div(content...)
|
||||
} else if len(content) == 0 {
|
||||
contentForFunction = Div()
|
||||
} else if len(content) == 1 {
|
||||
contentForFunction = content[0]
|
||||
}
|
||||
|
||||
styles := []string{
|
||||
"/static/styles.css",
|
||||
}
|
||||
for _, src := range metadata.StyleSrcs {
|
||||
styles = append(styles, src)
|
||||
}
|
||||
|
||||
scripts := []string{
|
||||
"/static/scripts/language-select.js",
|
||||
"/static/htmx.js",
|
||||
}
|
||||
for _, src := range metadata.ScriptSrcs {
|
||||
scripts = append(scripts, src)
|
||||
}
|
||||
|
||||
page := HTML5(HTML5Props{
|
||||
Title: "White Label App " + metadata.Title.From(req),
|
||||
Language: string(metadata.Lang),
|
||||
Description: metadata.Description.From(req),
|
||||
Head: []Node{
|
||||
Map(styles, func(s string) Node {
|
||||
return Link(Rel("stylesheet"), Href(s))
|
||||
}),
|
||||
Map(scripts, func(s string) Node {
|
||||
return Script(Type("text/javascript"), Src(s))
|
||||
}),
|
||||
addLanguageSelectScript(metadata),
|
||||
},
|
||||
Body: []Node{
|
||||
Header(Class("header"),
|
||||
Div(Class("header-content"),
|
||||
Div(Class("logo"),
|
||||
Span(Class("logo-icon"), Text("🚀")),
|
||||
Span(Class("logo-text"), Text("White Label App")),
|
||||
),
|
||||
getNav(req, metadata),
|
||||
getLanguageSwitcher(req, metadata),
|
||||
),
|
||||
),
|
||||
Div(Class("container"),
|
||||
contentForFunction,
|
||||
),
|
||||
Footer(Class("footer"),
|
||||
Div(Class("footer-menu"), Aria("label", "Footer Menu"),
|
||||
getFooterMenu(req, metadata),
|
||||
),
|
||||
P(Class("footer-disclaimer"), Text(getTexts().disclaimer.From(req))),
|
||||
P(Text(getTexts().getCopyright(req.GetLanguage()))),
|
||||
),
|
||||
},
|
||||
})
|
||||
req.Render(page)
|
||||
}
|
||||
|
||||
func addLanguageSelectScript(metadata PageWebsiteMetaData) Node {
|
||||
script := InlineTemplate(`
|
||||
(function() {
|
||||
const langs = {
|
||||
de: "$.DeUrl$",
|
||||
en: "$.EnUrl$",
|
||||
};
|
||||
const currentLang = "$.CurrentLang$";
|
||||
const defaultLang = "$.DefaultLang$";
|
||||
selectWebsiteLanguage(currentLang, langs, defaultLang);
|
||||
})();`, struct {
|
||||
CurrentLang string
|
||||
DeUrl string
|
||||
EnUrl string
|
||||
DefaultLang string
|
||||
}{
|
||||
CurrentLang: string(metadata.Lang),
|
||||
DeUrl: DeIndexUrl,
|
||||
EnUrl: EnIndexUrl,
|
||||
DefaultLang: string(DefaultLanguage),
|
||||
})
|
||||
return Script(Type("text/javascript"), Raw(script))
|
||||
}
|
||||
|
||||
func getNav(c HtmxContext, metadata PageWebsiteMetaData) Node {
|
||||
return Nav(Class("nav"), Aria("label", "Main Menu"),
|
||||
Map(metadata.NavItems, func(path ActivePath) Node {
|
||||
return createNavItem(c, path)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
func createNavItem(c HtmxContext, activePath ActivePath) Node {
|
||||
isActive := activePath.IsActive(c)
|
||||
return A(
|
||||
Href(activePath.GetPath(c.GetLanguage())),
|
||||
Text(activePath.From(c)),
|
||||
If(isActive, Attr("aria-current", "page")),
|
||||
If(isActive, Class("selected")),
|
||||
)
|
||||
}
|
||||
|
||||
func getLanguageSwitcher(c HtmxContext, metadata PageWebsiteMetaData) Node {
|
||||
currentLang := c.GetLanguage()
|
||||
|
||||
var currentRoute HtmxRoute
|
||||
for _, route := range c.GetAllRoutes() {
|
||||
if route.IsCurrentRoute(c) {
|
||||
currentRoute = route
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return Div(Class("language-switcher"),
|
||||
createLanguageButton(En, currentLang, currentRoute, c),
|
||||
createLanguageButton(De, currentLang, currentRoute, c),
|
||||
)
|
||||
}
|
||||
|
||||
func getFooterMenu(c HtmxContext, metadata PageWebsiteMetaData) Node {
|
||||
lang := c.GetLanguage()
|
||||
return Div(
|
||||
Map(metadata.FooterNavItems, func(path ActivePath) Node {
|
||||
return Span(
|
||||
A(Href(path.GetPath(lang)), Class("footer-link"), Text(path.From(c))),
|
||||
)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
func createLanguageButton(lang Language, currentLang Language, route HtmxRoute, c HtmxContext) Node {
|
||||
isActive := lang == currentLang
|
||||
var href string
|
||||
|
||||
if route != nil {
|
||||
href = route.ToUrlFromContext(c, lang)
|
||||
} else {
|
||||
// Fallback to index page if no active path found
|
||||
if lang == En {
|
||||
href = EnIndexUrl
|
||||
} else {
|
||||
href = DeIndexUrl
|
||||
}
|
||||
}
|
||||
|
||||
var langText string
|
||||
if lang == En {
|
||||
langText = "EN"
|
||||
} else {
|
||||
langText = "DE"
|
||||
}
|
||||
|
||||
// Combine classes properly
|
||||
var classes string
|
||||
if isActive {
|
||||
classes = "language-button active"
|
||||
} else {
|
||||
classes = "language-button inactive"
|
||||
}
|
||||
|
||||
return A(
|
||||
Href(href),
|
||||
Text(langText),
|
||||
Class(classes),
|
||||
)
|
||||
}
|
||||
|
||||
type Texts struct {
|
||||
disclaimer I18nText
|
||||
copyright I18nText
|
||||
}
|
||||
|
||||
func NewTexts() *Texts {
|
||||
return &Texts{
|
||||
disclaimer: NewI18nText(map[Language]string{
|
||||
De: "Dies ist eine White-Label-Vorlage. Passen Sie den Inhalt an Ihre Bedürfnisse an.",
|
||||
En: "This is a white label template. Customize the content to fit your needs.",
|
||||
}),
|
||||
copyright: NewI18nText(map[Language]string{
|
||||
De: "© 2020 - $Year$ White Label App. Alle Rechte vorbehalten.",
|
||||
En: "© 2020 - $Year$ White Label App. All rights reserved.",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Texts) getCopyright(lang Language) string {
|
||||
currentYear := fmt.Sprint(time.Now().Year())
|
||||
text := t.copyright.FromLang(lang)
|
||||
return InlineTemplate(text, struct {
|
||||
Year string
|
||||
}{
|
||||
Year: currentYear,
|
||||
})
|
||||
}
|
||||
|
||||
func getTexts() *Texts {
|
||||
if _texts != nil {
|
||||
return _texts
|
||||
}
|
||||
_texts = NewTexts()
|
||||
return _texts
|
||||
}
|
||||
Reference in New Issue
Block a user