component.DummyMenuItem: Force early replacement
This commit is contained in:
parent
2466238388
commit
a7309d5268
7 changed files with 75 additions and 27 deletions
|
|
@ -34,7 +34,12 @@ type GrantWithURL struct {
|
|||
URL template.URL
|
||||
}
|
||||
|
||||
var (
|
||||
totpActionItem = component.DummyMenuItem()
|
||||
)
|
||||
|
||||
func (panel *UserPanel) routeUser(ctx context.Context) http.Handler {
|
||||
|
||||
tpl := userTemplate.Prepare(
|
||||
panel.Dependencies.Templating,
|
||||
templating.Crumbs(
|
||||
|
|
@ -42,7 +47,7 @@ func (panel *UserPanel) routeUser(ctx context.Context) http.Handler {
|
|||
),
|
||||
templating.Actions(
|
||||
component.MenuItem{Title: "Change Password", Path: "/user/password/"},
|
||||
component.DummyMenuItem,
|
||||
totpActionItem,
|
||||
component.MenuItem{Title: "SSH Keys", Path: "/user/ssh/"},
|
||||
),
|
||||
)
|
||||
|
|
@ -68,7 +73,7 @@ func (panel *UserPanel) routeUser(ctx context.Context) http.Handler {
|
|||
}
|
||||
}
|
||||
funcs = []templating.FlagFunc{
|
||||
templating.ReplaceAction(1, totpAction),
|
||||
templating.ReplaceAction(totpActionItem, totpAction),
|
||||
templating.Title(uc.AuthUser.User.User),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package component
|
|||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Menuable is a component that provides a menu
|
||||
|
|
@ -16,13 +17,35 @@ type MenuItem struct {
|
|||
Path template.URL
|
||||
Active bool
|
||||
|
||||
Priority MenuPriority // menu priority
|
||||
Priority MenuPriority
|
||||
|
||||
replaceID uint64 // internal id used to replace an item
|
||||
}
|
||||
|
||||
// DummyMenuItem is a dummy menu item
|
||||
// It should be replaced before being displayed to the user
|
||||
var DummyMenuItem = MenuItem{
|
||||
Title: "* to be replaced *",
|
||||
var dummyCounter uint64
|
||||
|
||||
// DummyMenuItem creates a new Dummy Menu Item to be replaced
|
||||
func DummyMenuItem() MenuItem {
|
||||
return MenuItem{
|
||||
replaceID: atomic.AddUint64(&dummyCounter, 1),
|
||||
}
|
||||
}
|
||||
|
||||
// ReplaceWith replaces this MenuItem with a different MenuItem.
|
||||
// This method returns true if an appropriate DummyMenuItem exists.
|
||||
func (mi MenuItem) ReplaceWith(new MenuItem, items []MenuItem) bool {
|
||||
if mi.replaceID == 0 {
|
||||
// never replace non-dummy items
|
||||
return false
|
||||
}
|
||||
for i, item := range items {
|
||||
if mi.replaceID == item.replaceID {
|
||||
items[i] = new
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func MenuItemSort(a, b MenuItem) bool {
|
||||
|
|
|
|||
|
|
@ -47,14 +47,19 @@ func (admin *Admin) components(ctx context.Context) http.Handler {
|
|||
})
|
||||
}
|
||||
|
||||
var (
|
||||
instanceCrumb = component.DummyMenuItem()
|
||||
ingredientsCrumb = component.DummyMenuItem()
|
||||
)
|
||||
|
||||
func (admin *Admin) ingredients(ctx context.Context) http.Handler {
|
||||
tpl := analTemplate.Prepare(
|
||||
admin.Dependencies.Templating,
|
||||
templating.Crumbs(
|
||||
component.MenuItem{Title: "Admin", Path: "/admin/"},
|
||||
component.MenuItem{Title: "Instances", Path: "/admin/instance/"},
|
||||
component.DummyMenuItem,
|
||||
component.DummyMenuItem,
|
||||
instanceCrumb,
|
||||
ingredientsCrumb,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -70,8 +75,8 @@ func (admin *Admin) ingredients(ctx context.Context) http.Handler {
|
|||
return ac, nil, err
|
||||
}
|
||||
funcs = []templating.FlagFunc{
|
||||
templating.ReplaceCrumb(2, component.MenuItem{Title: "Instance", Path: template.URL("/admin/instance/" + slug)}),
|
||||
templating.ReplaceCrumb(3, component.MenuItem{Title: "Ingredients", Path: template.URL("/admin/instance/" + slug + "/ingredients/")}),
|
||||
templating.ReplaceCrumb(instanceCrumb, component.MenuItem{Title: "Instance", Path: template.URL("/admin/instance/" + slug)}),
|
||||
templating.ReplaceCrumb(ingredientsCrumb, component.MenuItem{Title: "Ingredients", Path: template.URL("/admin/instance/" + slug + "/ingredients/")}),
|
||||
templating.Title(instance.Name() + " - Ingredients"),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,14 +41,19 @@ type grantsContext struct {
|
|||
Drupals []string // unusued drupal usernames
|
||||
}
|
||||
|
||||
var (
|
||||
instancePageCrumb = component.DummyMenuItem()
|
||||
grantsPageCrumb = component.DummyMenuItem()
|
||||
)
|
||||
|
||||
func (admin *Admin) grants(ctx context.Context) http.Handler {
|
||||
tpl := grantsTemplate.Prepare(
|
||||
admin.Dependencies.Templating,
|
||||
templating.Crumbs(
|
||||
component.MenuItem{Title: "Admin", Path: "/admin/"},
|
||||
component.MenuItem{Title: "Instances", Path: "/admin/instance/"},
|
||||
component.DummyMenuItem,
|
||||
component.DummyMenuItem,
|
||||
instancePageCrumb,
|
||||
grantsPageCrumb,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -137,8 +142,8 @@ func (gc *grantsContext) use(r *http.Request, slug string, admin *Admin) (funcs
|
|||
|
||||
// replace the functions
|
||||
funcs = []templating.FlagFunc{
|
||||
templating.ReplaceCrumb(2, component.MenuItem{Title: "Instance", Path: template.URL("/admin/instance/" + slug)}),
|
||||
templating.ReplaceCrumb(3, component.MenuItem{Title: "Grants", Path: template.URL("/admin/instance/" + slug + "/grants/")}),
|
||||
templating.ReplaceCrumb(instancePageCrumb, component.MenuItem{Title: "Instance", Path: template.URL("/admin/instance/" + slug)}),
|
||||
templating.ReplaceCrumb(grantsPageCrumb, component.MenuItem{Title: "Grants", Path: template.URL("/admin/instance/" + slug + "/grants/")}),
|
||||
templating.Title(gc.Instance.Slug + " - Grants"),
|
||||
}
|
||||
return funcs, nil
|
||||
|
|
|
|||
|
|
@ -31,17 +31,23 @@ type instanceContext struct {
|
|||
Info status.WissKI
|
||||
}
|
||||
|
||||
var (
|
||||
instancesPageCrumb = component.DummyMenuItem()
|
||||
grantsAction = component.DummyMenuItem()
|
||||
ingredientsAction = component.DummyMenuItem()
|
||||
)
|
||||
|
||||
func (admin *Admin) instance(ctx context.Context) http.Handler {
|
||||
tpl := instanceTemplate.Prepare(
|
||||
admin.Dependencies.Templating,
|
||||
templating.Crumbs(
|
||||
component.MenuItem{Title: "Admin", Path: "/admin/"},
|
||||
component.MenuItem{Title: "Instances", Path: "/admin/instance/"},
|
||||
component.DummyMenuItem,
|
||||
instancesPageCrumb,
|
||||
),
|
||||
templating.Actions(
|
||||
component.DummyMenuItem,
|
||||
component.DummyMenuItem,
|
||||
grantsAction,
|
||||
ingredientsAction,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -65,9 +71,9 @@ func (admin *Admin) instance(ctx context.Context) http.Handler {
|
|||
}
|
||||
|
||||
funcs = []templating.FlagFunc{
|
||||
templating.ReplaceCrumb(2, component.MenuItem{Title: "Instance", Path: template.URL("/admin/instance/" + slug)}),
|
||||
templating.ReplaceAction(0, component.MenuItem{Title: "Grants", Path: template.URL("/admin/grants/" + slug)}),
|
||||
templating.ReplaceAction(1, component.MenuItem{Title: "Ingredients", Path: template.URL("/admin/ingredients/" + slug), Priority: component.SmallButton}),
|
||||
templating.ReplaceCrumb(instancesPageCrumb, component.MenuItem{Title: "Instance", Path: template.URL("/admin/instance/" + slug)}),
|
||||
templating.ReplaceAction(grantsAction, component.MenuItem{Title: "Grants", Path: template.URL("/admin/grants/" + slug)}),
|
||||
templating.ReplaceAction(ingredientsAction, component.MenuItem{Title: "Ingredients", Path: template.URL("/admin/ingredients/" + slug), Priority: component.SmallButton}),
|
||||
|
||||
templating.Title(instance.Slug),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -203,7 +203,6 @@ const (
|
|||
)
|
||||
|
||||
func (ctx *tContext[C]) doMain(err error) (template.HTML, error) {
|
||||
zerolog.Ctx(ctx.ctx).Info().Msg("doMain")
|
||||
if err != nil {
|
||||
zerolog.Ctx(ctx.ctx).Err(err).Msg("error lazy loading template")
|
||||
return errUnknown, nil
|
||||
|
|
@ -220,7 +219,6 @@ func (ctx *tContext[C]) doMain(err error) (template.HTML, error) {
|
|||
}
|
||||
|
||||
func (ctx *tContext[C]) AfterBody() (template.HTML, error) {
|
||||
zerolog.Ctx(ctx.ctx).Info().Msg("AfterBody()")
|
||||
// everything was done already
|
||||
if !ctx.cWaiting {
|
||||
return "", nil
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
package templating
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/assets"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/tkw1536/goprogram/lib/reflectx"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
|
@ -77,17 +79,21 @@ func Actions(actions ...component.MenuItem) FlagFunc {
|
|||
}
|
||||
|
||||
// ReplaceAction replaces a specific action
|
||||
func ReplaceAction(index int, action component.MenuItem) FlagFunc {
|
||||
func ReplaceAction(old component.MenuItem, action component.MenuItem) FlagFunc {
|
||||
return func(flags Flags, r *http.Request) Flags {
|
||||
flags.Actions[index] = action
|
||||
if !old.ReplaceWith(action, flags.Actions) {
|
||||
zerolog.Ctx(r.Context()).Warn().Str("action", fmt.Sprint(action)).Str("actions", fmt.Sprint(flags.Actions)).Msg("did not replace menu item")
|
||||
}
|
||||
return flags
|
||||
}
|
||||
}
|
||||
|
||||
// ReplaceCrumb replaces a specific crum
|
||||
func ReplaceCrumb(index int, action component.MenuItem) FlagFunc {
|
||||
func ReplaceCrumb(old component.MenuItem, action component.MenuItem) FlagFunc {
|
||||
return func(flags Flags, r *http.Request) Flags {
|
||||
flags.Crumbs[index] = action
|
||||
if !old.ReplaceWith(action, flags.Crumbs) {
|
||||
zerolog.Ctx(r.Context()).Warn().Str("action", fmt.Sprint(action)).Str("actions", fmt.Sprint(flags.Actions)).Msg("did not replace menu item")
|
||||
}
|
||||
return flags
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue