Add navigation.PageInfo

- Highlight sidebar entries
- Add PageInfo wiring example
This commit is contained in:
David Vogel 2023-05-12 22:07:04 +02:00
parent 0dda9f7767
commit df7d956874
7 changed files with 238 additions and 156 deletions

View File

@ -0,0 +1,59 @@
package navigation
import "github.com/vugu/vugu"
// PageInfo represents the path of a route.
// This is used by navigation components.
type PageInfo struct {
Path string // URL path.
Title string // Title that can be defined by the page component.
LongTitle string
ShortTitle string
MetaDescription string // Meta description tag that can be defined by the page component.
}
func NewPageInfo(path string, component vugu.Builder) PageInfo {
var title, longTitle, shortTitle string
if c, ok := component.(PageTitleGetter); ok {
title, longTitle, shortTitle = c.PageTitle()
}
var metaDescription string
if c, ok := component.(PageMetaGetter); ok {
metaDescription = c.PageMetaDescription()
}
return PageInfo{
Path: path,
Title: title,
LongTitle: longTitle,
ShortTitle: shortTitle,
MetaDescription: metaDescription,
}
}
type PageInfoRef struct {
*PageInfo
}
func (p *PageInfoRef) PageInfoSet(pageInfo *PageInfo) {
p.PageInfo = pageInfo
}
type PageInfoSetter interface {
PageInfoSet(*PageInfo)
}
var _ PageInfoSetter = &PageInfoRef{}
// Can be implemented by page components to define their page title.
type PageTitleGetter interface {
PageTitle() (title, longTitle, shortTitle string)
}
// Can be implemented by page components to define their meta description.
type PageMetaGetter interface {
PageMetaDescription() (metaDescription string)
}

View File

@ -1,13 +1,18 @@
package navigation package navigation
import ( import (
"log"
"github.com/vugu/vgrouter" "github.com/vugu/vgrouter"
"github.com/vugu/vugu" "github.com/vugu/vugu"
) )
type SidebarEntry struct { type SidebarEntry struct {
vgrouter.NavigatorRef vgrouter.NavigatorRef
PageInfoRef
AttrMap vugu.AttrMap AttrMap vugu.AttrMap
classes string // TODO: Use AttrMap to handle classes or something else
SymbolSlot vugu.Builder // Slot for the symbol. SymbolSlot vugu.Builder // Slot for the symbol.
DefaultSlot vugu.Builder // Slot for the text and other stuff. Should be a div element! DefaultSlot vugu.Builder // Slot for the text and other stuff. Should be a div element!
@ -18,3 +23,12 @@ type SidebarEntry struct {
func (c *SidebarEntry) handleClick(event vugu.DOMEvent) { func (c *SidebarEntry) handleClick(event vugu.DOMEvent) {
c.Navigate(c.URL, nil) c.Navigate(c.URL, nil)
} }
func (c *SidebarEntry) Compute(ctx vugu.ComputeCtx) {
log.Printf("%v", c.PageInfo)
if c.PageInfo != nil && c.PageInfo.Path == c.URL {
c.classes = "d3c-1683622560-selected"
} else {
c.classes = ""
}
}

View File

@ -1,4 +1,4 @@
<button vg-attr="c.AttrMap" class="d3c-1683622560" @click="c.handleClick(event)"> <button vg-attr="c.AttrMap" :class='"d3c-1683622560 " + c.classes' @click="c.handleClick(event)">
<vg-comp expr="c.SymbolSlot"></vg-comp><vg-comp expr="c.DefaultSlot"></vg-comp> <vg-comp expr="c.SymbolSlot"></vg-comp><vg-comp expr="c.DefaultSlot"></vg-comp>
</button> </button>

View File

@ -15,8 +15,9 @@ func (c *SidebarEntry) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
var vgiterkey interface{} var vgiterkey interface{}
_ = vgiterkey _ = vgiterkey
var vgn *vugu.VGNode var vgn *vugu.VGNode
vgn = &vugu.VGNode{Type: vugu.VGNodeType(3), Namespace: "", Data: "button", Attr: []vugu.VGAttribute{vugu.VGAttribute{Namespace: "", Key: "class", Val: "d3c-1683622560"}}} vgn = &vugu.VGNode{Type: vugu.VGNodeType(3), Namespace: "", Data: "button", Attr: []vugu.VGAttribute(nil)}
vgout.Out = append(vgout.Out, vgn) // root for output vgout.Out = append(vgout.Out, vgn) // root for output
vgn.AddAttrInterface("class", "d3c-1683622560 "+c.classes)
vgn.AddAttrList(c.AttrMap) vgn.AddAttrList(c.AttrMap)
vgn.DOMEventHandlerSpecList = append(vgn.DOMEventHandlerSpecList, vugu.DOMEventHandlerSpec{ vgn.DOMEventHandlerSpecList = append(vgn.DOMEventHandlerSpecList, vugu.DOMEventHandlerSpec{
EventType: "click", EventType: "click",

File diff suppressed because it is too large Load Diff

View File

@ -46,7 +46,7 @@ func (c *Root) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t\t"} vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t\t"}
vgparent.AppendChild(vgn) vgparent.AppendChild(vgn)
{ {
vgcompKey := vugu.MakeCompKey(0x2E9A2E5DC2291CAD^vgin.CurrentPositionHash(), vgiterkey) vgcompKey := vugu.MakeCompKey(0x96BAA0E9FEE668E^vgin.CurrentPositionHash(), vgiterkey)
// ask BuildEnv for prior instance of this specific component // ask BuildEnv for prior instance of this specific component
vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*navigation.Sidebar) vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*navigation.Sidebar)
if vgcomp == nil { if vgcomp == nil {
@ -67,7 +67,7 @@ func (c *Root) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t\t\t\t"} vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t\t\t\t"}
vgparent.AppendChild(vgn) vgparent.AppendChild(vgn)
{ {
vgcompKey := vugu.MakeCompKey(0x686B5692725EA031^vgin.CurrentPositionHash(), vgiterkey) vgcompKey := vugu.MakeCompKey(0x4254F6AC259DD09A^vgin.CurrentPositionHash(), vgiterkey)
// ask BuildEnv for prior instance of this specific component // ask BuildEnv for prior instance of this specific component
vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*navigation.ButtonFullscreen) vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*navigation.ButtonFullscreen)
if vgcomp == nil { if vgcomp == nil {
@ -94,7 +94,7 @@ func (c *Root) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t\t\t\t"} vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t\t\t\t"}
vgparent.AppendChild(vgn) vgparent.AppendChild(vgn)
{ {
vgcompKey := vugu.MakeCompKey(0x5D38B25E830DE580^vgin.CurrentPositionHash(), vgiterkey) vgcompKey := vugu.MakeCompKey(0xD3CD788A91C5BE1E^vgin.CurrentPositionHash(), vgiterkey)
// ask BuildEnv for prior instance of this specific component // ask BuildEnv for prior instance of this specific component
vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*navigation.SidebarEntry) vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*navigation.SidebarEntry)
if vgcomp == nil { if vgcomp == nil {
@ -112,7 +112,7 @@ func (c *Root) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
_ = vgparent _ = vgparent
{ {
vgcompKey := vugu.MakeCompKey(0xE1B3F56AA51B2DB3^vgin.CurrentPositionHash(), vgiterkey) vgcompKey := vugu.MakeCompKey(0x3293FE053FAB9D98^vgin.CurrentPositionHash(), vgiterkey)
// ask BuildEnv for prior instance of this specific component // ask BuildEnv for prior instance of this specific component
vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*icons.LHome) vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*icons.LHome)
if vgcomp == nil { if vgcomp == nil {
@ -151,7 +151,7 @@ func (c *Root) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t\t\t\t"} vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t\t\t\t"}
vgparent.AppendChild(vgn) vgparent.AppendChild(vgn)
{ {
vgcompKey := vugu.MakeCompKey(0xEBE260D8ADE95FBE^vgin.CurrentPositionHash(), vgiterkey) vgcompKey := vugu.MakeCompKey(0x653843F952D5523D^vgin.CurrentPositionHash(), vgiterkey)
// ask BuildEnv for prior instance of this specific component // ask BuildEnv for prior instance of this specific component
vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*navigation.SidebarEntry) vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*navigation.SidebarEntry)
if vgcomp == nil { if vgcomp == nil {
@ -169,7 +169,7 @@ func (c *Root) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
_ = vgparent _ = vgparent
{ {
vgcompKey := vugu.MakeCompKey(0x52BB52A71CBC3F81^vgin.CurrentPositionHash(), vgiterkey) vgcompKey := vugu.MakeCompKey(0xF6FF874D2C468F9B^vgin.CurrentPositionHash(), vgiterkey)
// ask BuildEnv for prior instance of this specific component // ask BuildEnv for prior instance of this specific component
vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*icons.LStar) vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*icons.LStar)
if vgcomp == nil { if vgcomp == nil {
@ -208,7 +208,7 @@ func (c *Root) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t\t\t\t"} vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t\t\t\t"}
vgparent.AppendChild(vgn) vgparent.AppendChild(vgn)
{ {
vgcompKey := vugu.MakeCompKey(0x2AF1551B8C561CD9^vgin.CurrentPositionHash(), vgiterkey) vgcompKey := vugu.MakeCompKey(0xB45B66A540EA6780^vgin.CurrentPositionHash(), vgiterkey)
// ask BuildEnv for prior instance of this specific component // ask BuildEnv for prior instance of this specific component
vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*navigation.SidebarEntry) vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*navigation.SidebarEntry)
if vgcomp == nil { if vgcomp == nil {
@ -226,7 +226,7 @@ func (c *Root) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
_ = vgparent _ = vgparent
{ {
vgcompKey := vugu.MakeCompKey(0xFDC8CD2FD0424FED^vgin.CurrentPositionHash(), vgiterkey) vgcompKey := vugu.MakeCompKey(0x905E00464605D91A^vgin.CurrentPositionHash(), vgiterkey)
// ask BuildEnv for prior instance of this specific component // ask BuildEnv for prior instance of this specific component
vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*icons.LInfoCircle) vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*icons.LInfoCircle)
if vgcomp == nil { if vgcomp == nil {
@ -276,7 +276,7 @@ func (c *Root) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t\t\t\t"} vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t\t\t\t"}
vgparent.AppendChild(vgn) vgparent.AppendChild(vgn)
{ {
vgcompKey := vugu.MakeCompKey(0xCF5E40696C88BAC9^vgin.CurrentPositionHash(), vgiterkey) vgcompKey := vugu.MakeCompKey(0x4F533E698911F9BC^vgin.CurrentPositionHash(), vgiterkey)
// ask BuildEnv for prior instance of this specific component // ask BuildEnv for prior instance of this specific component
vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*navigation.SidebarEntry) vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*navigation.SidebarEntry)
if vgcomp == nil { if vgcomp == nil {
@ -294,7 +294,7 @@ func (c *Root) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
_ = vgparent _ = vgparent
{ {
vgcompKey := vugu.MakeCompKey(0xF36D7D0B128ECD49^vgin.CurrentPositionHash(), vgiterkey) vgcompKey := vugu.MakeCompKey(0x7EE378DF12BAD1B9^vgin.CurrentPositionHash(), vgiterkey)
// ask BuildEnv for prior instance of this specific component // ask BuildEnv for prior instance of this specific component
vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*icons.LGlobe) vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*icons.LGlobe)
if vgcomp == nil { if vgcomp == nil {
@ -333,7 +333,7 @@ func (c *Root) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t\t\t\t"} vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t\t\t\t"}
vgparent.AppendChild(vgn) vgparent.AppendChild(vgn)
{ {
vgcompKey := vugu.MakeCompKey(0x1D39634A579B7FEA^vgin.CurrentPositionHash(), vgiterkey) vgcompKey := vugu.MakeCompKey(0x3E4E9B21705434D6^vgin.CurrentPositionHash(), vgiterkey)
// ask BuildEnv for prior instance of this specific component // ask BuildEnv for prior instance of this specific component
vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*navigation.SidebarEntry) vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*navigation.SidebarEntry)
if vgcomp == nil { if vgcomp == nil {
@ -351,7 +351,7 @@ func (c *Root) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {
_ = vgparent _ = vgparent
{ {
vgcompKey := vugu.MakeCompKey(0xECD3DBB2A4682E34^vgin.CurrentPositionHash(), vgiterkey) vgcompKey := vugu.MakeCompKey(0x398A831BD02CA2C2^vgin.CurrentPositionHash(), vgiterkey)
// ask BuildEnv for prior instance of this specific component // ask BuildEnv for prior instance of this specific component
vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*icons.LSettings) vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*icons.LSettings)
if vgcomp == nil { if vgcomp == nil {

View File

@ -5,6 +5,7 @@ package main
import ( import (
"log" "log"
"git.d3nexus.de/Dadido3/D3vugu-components/components/navigation"
"github.com/vugu/vgrouter" "github.com/vugu/vgrouter"
"github.com/vugu/vugu" "github.com/vugu/vugu"
) )
@ -26,32 +27,39 @@ func vuguSetup(buildEnv *vugu.BuildEnv, eventEnv vugu.EventEnv) vugu.Builder {
// Create root object. // Create root object.
root := &Root{} root := &Root{}
var pageInfo navigation.PageInfo
buildEnv.SetWireFunc(func(b vugu.Builder) { buildEnv.SetWireFunc(func(b vugu.Builder) {
// Make our wire function populate anything that wants a "Navigator". // Make our wire function populate anything that wants a "Navigator".
if c, ok := b.(vgrouter.NavigatorSetter); ok { if c, ok := b.(vgrouter.NavigatorSetter); ok {
c.NavigatorSet(router) c.NavigatorSet(router)
} }
if c, ok := b.(navigation.PageInfoSetter); ok {
c.PageInfoSet(&pageInfo)
}
}) })
// Wire the root component. (Not sure if that is really needed) // Call wire function on root component.
buildEnv.WireComponent(root) buildEnv.WireComponent(root)
// Add routes. // Add routes.
router.MustAddRouteExact("/", router.MustAddRouteExact("/", vgrouter.RouteHandlerFunc(func(rm *vgrouter.RouteMatch) {
vgrouter.RouteHandlerFunc(func(rm *vgrouter.RouteMatch) {
root.Body = nil root.Body = nil
})) }))
router.MustAddRouteExact("/icons/", router.MustAddRouteExact("/icons", vgrouter.RouteHandlerFunc(func(rm *vgrouter.RouteMatch) {
vgrouter.RouteHandlerFunc(func(rm *vgrouter.RouteMatch) {
root.Body = &PageIcons{} root.Body = &PageIcons{}
})) }))
router.SetNotFound(vgrouter.RouteHandlerFunc( router.SetNotFound(vgrouter.RouteHandlerFunc(func(rm *vgrouter.RouteMatch) {
func(rm *vgrouter.RouteMatch) {
root.Body = nil root.Body = nil
})) }))
// add another route at the end that always runs and handles the page info
router.MustAddRoute("/", vgrouter.RouteHandlerFunc(func(rm *vgrouter.RouteMatch) {
pageInfo = navigation.NewPageInfo(rm.Path, root.Body)
}))
// Tell the router to listen to the browser changing URLs. // Tell the router to listen to the browser changing URLs.
err := router.ListenForPopState() err := router.ListenForPopState()
if err != nil { if err != nil {