templating: Move actions into template
This commit is contained in:
parent
313af2b9e3
commit
202599aaeb
23 changed files with 153 additions and 105 deletions
|
|
@ -30,9 +30,11 @@ type componentContext struct {
|
|||
}
|
||||
|
||||
func (admin *Admin) components(r *http.Request) (cp componentContext, err error) {
|
||||
admin.Dependencies.Custom.Update(&cp, r, []component.MenuItem{
|
||||
{Title: "Admin", Path: "/admin/"},
|
||||
{Title: "Components", Path: "/admin/components/"},
|
||||
admin.Dependencies.Custom.Update(&cp, r, custom.BaseContextGaps{
|
||||
Crumbs: []component.MenuItem{
|
||||
{Title: "Admin", Path: "/admin/"},
|
||||
{Title: "Components", Path: "/admin/components/"},
|
||||
},
|
||||
})
|
||||
|
||||
cp.Analytics = *admin.Analytics
|
||||
|
|
@ -56,10 +58,12 @@ type ingredientsContext struct {
|
|||
func (admin *Admin) ingredients(r *http.Request) (cp ingredientsContext, err error) {
|
||||
slug := httprouter.ParamsFromContext(r.Context()).ByName("slug")
|
||||
|
||||
admin.Dependencies.Custom.Update(&cp, r, []component.MenuItem{
|
||||
{Title: "Admin", Path: "/admin/"},
|
||||
{Title: "Instance", Path: template.URL("/admin/instance/" + slug)},
|
||||
{Title: "Ingredients", Path: template.URL("/admin/instance/" + slug + "/ingredients/")},
|
||||
admin.Dependencies.Custom.Update(&cp, r, custom.BaseContextGaps{
|
||||
Crumbs: []component.MenuItem{
|
||||
{Title: "Admin", Path: "/admin/"},
|
||||
{Title: "Instance", Path: template.URL("/admin/instance/" + slug)},
|
||||
{Title: "Ingredients", Path: template.URL("/admin/instance/" + slug + "/ingredients/")},
|
||||
},
|
||||
})
|
||||
|
||||
// find the instance itself!
|
||||
|
|
|
|||
|
|
@ -40,10 +40,12 @@ type grantsContext struct {
|
|||
}
|
||||
|
||||
func (gc *grantsContext) use(r *http.Request, slug string, admin *Admin) (err error) {
|
||||
admin.Dependencies.Custom.Update(gc, r, []component.MenuItem{
|
||||
{Title: "Admin", Path: "/admin/"},
|
||||
{Title: "Instance", Path: template.URL("/admin/instance/" + slug)},
|
||||
{Title: "Grants", Path: template.URL("/admin/instance/" + slug + "/grants/")},
|
||||
admin.Dependencies.Custom.Update(gc, r, custom.BaseContextGaps{
|
||||
Crumbs: []component.MenuItem{
|
||||
{Title: "Admin", Path: "/admin/"},
|
||||
{Title: "Instance", Path: template.URL("/admin/instance/" + slug)},
|
||||
{Title: "Grants", Path: template.URL("/admin/instance/" + slug + "/grants/")},
|
||||
},
|
||||
})
|
||||
|
||||
// find the instance itself
|
||||
|
|
|
|||
|
|
@ -1,15 +1,6 @@
|
|||
{{ template "_base.html" . }}
|
||||
{{ define "title" }}Admin{{ end }}
|
||||
|
||||
{{ define "header" }}
|
||||
<p>
|
||||
<div class="pure-button-group" role="group" aria-label="Actions">
|
||||
<a class="pure-button" href="/admin/users">Users</a>
|
||||
<a class="pure-button pure-button-small" href="/admin/components">Components</a>
|
||||
</div>
|
||||
</p>
|
||||
{{ end }}
|
||||
|
||||
{{ define "content" }}
|
||||
<div class="pure-u-1-1">
|
||||
<h2 id="overview">Distillery Configuration</h2>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,6 @@
|
|||
{{ template "_base.html" . }}
|
||||
{{ define "title" }}{{ .Instance.Slug }}{{ end }}
|
||||
|
||||
{{ define "header" }}
|
||||
<p>
|
||||
<div class="pure-button-group" role="group" aria-label="Actions">
|
||||
<a class="pure-button" href="/admin/grants/{{ .Info.Slug }}">Grants</a>
|
||||
<a class="pure-button pure-button-small" href="/admin/ingredients/{{ .Instance.Slug }}">Ingredients</a>
|
||||
</div>
|
||||
</p>
|
||||
{{ end }}
|
||||
|
||||
{{ define "content" }}
|
||||
<div class="pure-u-1-1">
|
||||
<h2 id="overview">Info & Status</h2>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,5 @@
|
|||
{{ template "_base.html" . }}
|
||||
{{ define "title" }}Admin Users{{ end }}
|
||||
|
||||
{{ define "header" }}
|
||||
<p>
|
||||
<div class="pure-button-group" role="group" aria-label="Actions">
|
||||
<a class="pure-button" href="/admin/users/create">Create New</a>
|
||||
</div>
|
||||
</p>
|
||||
{{ end }}
|
||||
{{ define "title" }}Users{{ end }}
|
||||
|
||||
{{ define "content" }}
|
||||
|
||||
|
|
|
|||
|
|
@ -87,8 +87,14 @@ type indexContext struct {
|
|||
}
|
||||
|
||||
func (admin *Admin) index(r *http.Request) (idx indexContext, err error) {
|
||||
admin.Dependencies.Custom.Update(&idx, r, []component.MenuItem{
|
||||
{Title: "Admin", Path: "/admin/"},
|
||||
admin.Dependencies.Custom.Update(&idx, r, custom.BaseContextGaps{
|
||||
Crumbs: []component.MenuItem{
|
||||
{Title: "Admin", Path: "/admin/"},
|
||||
},
|
||||
Actions: []component.MenuItem{
|
||||
{Title: "Users", Path: "/admin/users/"},
|
||||
{Title: "Components", Path: "/admin/components/", Priority: component.SmallButton},
|
||||
},
|
||||
})
|
||||
idx.Distillery, idx.Instances, err = admin.Status(r.Context(), true)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -32,9 +32,15 @@ type instanceContext struct {
|
|||
func (admin *Admin) instance(r *http.Request) (is instanceContext, err error) {
|
||||
slug := httprouter.ParamsFromContext(r.Context()).ByName("slug")
|
||||
|
||||
admin.Dependencies.Custom.Update(&is, r, []component.MenuItem{
|
||||
{Title: "Admin", Path: "/admin/"},
|
||||
{Title: "Instance", Path: template.URL("/admin/instance/" + slug)},
|
||||
admin.Dependencies.Custom.Update(&is, r, custom.BaseContextGaps{
|
||||
Crumbs: []component.MenuItem{
|
||||
{Title: "Admin", Path: "/admin/"},
|
||||
{Title: "Instance", Path: template.URL("/admin/instance/" + slug)},
|
||||
},
|
||||
Actions: []component.MenuItem{
|
||||
{Title: "Grants", Path: template.URL("/admin/grants/" + slug)},
|
||||
{Title: "Ingredients", Path: template.URL("/admin/ingredients/" + slug), Priority: component.SmallButton},
|
||||
},
|
||||
})
|
||||
|
||||
// find the instance itself!
|
||||
|
|
|
|||
|
|
@ -32,9 +32,11 @@ type userContext struct {
|
|||
}
|
||||
|
||||
func (admin *Admin) users(r *http.Request) (uc userContext, err error) {
|
||||
admin.Dependencies.Custom.Update(&uc, r, []component.MenuItem{
|
||||
{Title: "Admin", Path: "/admin/"},
|
||||
{Title: "Users", Path: "/admin/users/"},
|
||||
admin.Dependencies.Custom.Update(&uc, r, custom.BaseContextGaps{
|
||||
Crumbs: []component.MenuItem{
|
||||
{Title: "Admin", Path: "/admin/"},
|
||||
{Title: "Users", Path: "/admin/users/"},
|
||||
},
|
||||
})
|
||||
|
||||
uc.Error = r.URL.Query().Get("error")
|
||||
|
|
@ -62,10 +64,15 @@ type createUserResult struct {
|
|||
|
||||
func (admin *Admin) createUser(ctx context.Context) http.Handler {
|
||||
userCreateTemplate := admin.Dependencies.Custom.Template(userCreateTemplate)
|
||||
crumbs := []component.MenuItem{
|
||||
{Title: "Admin", Path: "/admin/"},
|
||||
{Title: "Users", Path: "/admin/users"},
|
||||
{Title: "Create", Path: "/admin/users/create"},
|
||||
gaps := custom.BaseContextGaps{
|
||||
Crumbs: []component.MenuItem{
|
||||
{Title: "Admin", Path: "/admin/"},
|
||||
{Title: "Users", Path: "/admin/users"},
|
||||
{Title: "Create", Path: "/admin/users/create"},
|
||||
},
|
||||
Actions: []component.MenuItem{
|
||||
{Title: "Create New", Path: "/admin/users/create/"},
|
||||
},
|
||||
}
|
||||
|
||||
return &httpx.Form[createUserResult]{
|
||||
|
|
@ -78,7 +85,7 @@ func (admin *Admin) createUser(ctx context.Context) http.Handler {
|
|||
|
||||
RenderTemplate: userCreateTemplate,
|
||||
RenderTemplateContext: func(ctx httpx.FormContext, r *http.Request) any {
|
||||
return admin.Dependencies.Custom.NewForm(ctx, r, crumbs)
|
||||
return admin.Dependencies.Custom.NewForm(ctx, r, gaps)
|
||||
},
|
||||
|
||||
Validate: func(r *http.Request, values map[string]string) (cu createUserResult, err error) {
|
||||
|
|
|
|||
|
|
@ -25,8 +25,10 @@ type publicContext struct {
|
|||
}
|
||||
|
||||
func (home *Home) publicHandler(ctx context.Context) http.Handler {
|
||||
crumbs := []component.MenuItem{
|
||||
{Title: "WissKI Distillery", Path: "/"},
|
||||
gaps := custom.BaseContextGaps{
|
||||
Crumbs: []component.MenuItem{
|
||||
{Title: "WissKI Distillery", Path: "/"},
|
||||
},
|
||||
}
|
||||
return httpx.HTMLHandler[publicContext]{
|
||||
Handler: func(r *http.Request) (pc publicContext, err error) {
|
||||
|
|
@ -35,7 +37,7 @@ func (home *Home) publicHandler(ctx context.Context) http.Handler {
|
|||
return pc, httpx.ErrNotFound
|
||||
}
|
||||
|
||||
home.Dependencies.Custom.Update(&pc, r, crumbs)
|
||||
home.Dependencies.Custom.Update(&pc, r, gaps)
|
||||
|
||||
pc.Instances = home.homeInstances.Get(nil)
|
||||
pc.SelfRedirect = home.Config.SelfRedirect.String()
|
||||
|
|
|
|||
|
|
@ -59,8 +59,10 @@ type legalContext struct {
|
|||
}
|
||||
|
||||
func (legal *Legal) context(r *http.Request) (lc legalContext, err error) {
|
||||
legal.Dependencies.Custom.Update(&lc, r, []component.MenuItem{
|
||||
{Title: "Legal", Path: "/legal/"},
|
||||
legal.Dependencies.Custom.Update(&lc, r, custom.BaseContextGaps{
|
||||
Crumbs: []component.MenuItem{
|
||||
{Title: "Legal", Path: "/legal/"},
|
||||
},
|
||||
})
|
||||
|
||||
lc.LegalNotices = cli.LegalNotices
|
||||
|
|
|
|||
|
|
@ -123,8 +123,10 @@ type newsContext struct {
|
|||
|
||||
// HandleRoute returns the handler for the requested path
|
||||
func (news *News) HandleRoute(ctx context.Context, path string) (http.Handler, error) {
|
||||
crumbs := []component.MenuItem{
|
||||
{Title: "News", Path: "/news/"},
|
||||
gaps := custom.BaseContextGaps{
|
||||
Crumbs: []component.MenuItem{
|
||||
{Title: "News", Path: "/news/"},
|
||||
},
|
||||
}
|
||||
|
||||
items, itemsErr := Items()
|
||||
|
|
@ -134,7 +136,7 @@ func (news *News) HandleRoute(ctx context.Context, path string) (http.Handler, e
|
|||
|
||||
return httpx.HTMLHandler[newsContext]{
|
||||
Handler: func(r *http.Request) (nc newsContext, err error) {
|
||||
news.Dependencies.Custom.Update(&nc, r, crumbs)
|
||||
news.Dependencies.Custom.Update(&nc, r, gaps)
|
||||
nc.Items, err = items, itemsErr
|
||||
|
||||
return
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ type BaseContext struct {
|
|||
GeneratedAt time.Time // time this page was generated at
|
||||
|
||||
// Menu and breadcrumbs
|
||||
Menu []component.MenuItem
|
||||
Crumbs []component.MenuItem
|
||||
Menu []component.MenuItem
|
||||
BaseContextGaps
|
||||
|
||||
CSRF template.HTML // CSRF Field
|
||||
}
|
||||
|
|
@ -43,12 +43,24 @@ const (
|
|||
requestNilError template.HTML = errorPrefix + "<code>BaseContext.use()</code> called with nil request" + errorSuffix
|
||||
)
|
||||
|
||||
type BaseContextGaps struct {
|
||||
Crumbs []component.MenuItem
|
||||
Actions []component.MenuItem
|
||||
}
|
||||
|
||||
func (bcg BaseContextGaps) Clone() BaseContextGaps {
|
||||
return BaseContextGaps{
|
||||
Crumbs: slices.Clone(bcg.Crumbs),
|
||||
Actions: slices.Clone(bcg.Actions),
|
||||
}
|
||||
}
|
||||
|
||||
// Use updates this context to use the values from the given base.
|
||||
//
|
||||
// The given request *must not* be nil.
|
||||
//
|
||||
// For convenience the passed context is also returned.
|
||||
func (tc *BaseContext) use(custom *Custom, r *http.Request, crumbs []component.MenuItem) *BaseContext {
|
||||
func (tc *BaseContext) use(custom *Custom, r *http.Request, gaps BaseContextGaps) *BaseContext {
|
||||
// tc.custom = custom
|
||||
tc.inited = true
|
||||
tc.requestWasNil = r == nil
|
||||
|
|
@ -65,7 +77,7 @@ func (tc *BaseContext) use(custom *Custom, r *http.Request, crumbs []component.M
|
|||
tc.Menu = custom.BuildMenu(r)
|
||||
|
||||
// build the breadcrumbs
|
||||
tc.Crumbs = slices.Clone(crumbs)
|
||||
tc.BaseContextGaps = gaps.Clone()
|
||||
last := len(tc.Crumbs) - 1
|
||||
for i := range tc.Crumbs {
|
||||
tc.Crumbs[i].Active = i == last
|
||||
|
|
@ -86,9 +98,9 @@ func (bc BaseContext) DoInitCheck() template.HTML {
|
|||
}
|
||||
|
||||
// NewForm is like New, but returns a new BaseFormContext
|
||||
func (custom *Custom) NewForm(context httpx.FormContext, r *http.Request, crumbs []component.MenuItem) (ctx BaseFormContext) {
|
||||
func (custom *Custom) NewForm(context httpx.FormContext, r *http.Request, bcg BaseContextGaps) (ctx BaseFormContext) {
|
||||
ctx.FormContext = context
|
||||
ctx.use(custom, r, crumbs)
|
||||
ctx.use(custom, r, bcg)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -96,11 +108,11 @@ func (custom *Custom) NewForm(context httpx.FormContext, r *http.Request, crumbs
|
|||
//
|
||||
// Assumes that context is a pointer to a struct type.
|
||||
// If this is not the case, might call panic().
|
||||
func (custom *Custom) Update(context any, r *http.Request, crumbs []component.MenuItem) *BaseContext {
|
||||
func (custom *Custom) Update(context any, r *http.Request, bcg BaseContextGaps) *BaseContext {
|
||||
ctx := reflect.ValueOf(context).
|
||||
Elem().FieldByName(baseContextName).Addr().
|
||||
Interface().(*BaseContext)
|
||||
ctx.use(custom, r, crumbs)
|
||||
ctx.use(custom, r, bcg)
|
||||
return ctx
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<div class="pure-u-1-1">
|
||||
<h2 id="components">Components</h2>
|
||||
<h2 id="structs">Structs</h2>
|
||||
</div>
|
||||
|
||||
{{ range $name, $comp := .Components }}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<body>
|
||||
{{ .BaseContext.DoInitCheck }}
|
||||
<nav class="pure-menu pure-menu-horizontal">
|
||||
<ul class="pure-menu-list">
|
||||
<ul class="pure-menu-list" role="menubar">
|
||||
{{ range .BaseContext.Menu }}
|
||||
<li class="pure-menu-item{{ if .Active }} pure-menu-selected{{ end }}">
|
||||
<a href="{{ .Path }}" class="pure-menu-link">{{ .Title }}</a>
|
||||
|
|
@ -27,7 +27,13 @@
|
|||
|
||||
<header>
|
||||
<h1 id="top">{{ template "title" . }}</h1>
|
||||
{{ block "header" . }}<!-- no header by default -->{{ end }}
|
||||
{{ if .BaseContext.Actions }}
|
||||
<div class="pure-button-group" role="group" aria-label="Actions">
|
||||
{{ range .BaseContext.Actions }}
|
||||
<a href="{{ .Path }}" class="pure-button{{ if eq .Priority -1 }} pure-button-small{{end}}">{{ .Title }}</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</header>
|
||||
<main>
|
||||
<div class="pure-g">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue