+extra page table

This commit is contained in:
Simon Martens
2026-01-14 16:36:23 +01:00
parent ca2df2da8a
commit 941ecbecaf
6 changed files with 126 additions and 46 deletions

106
app/pb.go
View File

@@ -38,6 +38,8 @@ type App struct {
dataMutex sync.RWMutex
htmlCache *PrefixCache
htmlMutex sync.RWMutex
pagesCache map[string]PageMetaData
pagesMutex sync.RWMutex
imagesCache map[string]*dbmodels.Image
imagesMutex sync.RWMutex
}
@@ -205,48 +207,39 @@ func (app *App) createEngine() (*templating.Engine, error) {
}
return template.HTML(value)
})
app.ResetPagesCache()
engine.AddFunc("pageMeta", func(name string) map[string]any {
app.ensureDataCache()
key := "page." + name
app.dataMutex.RLock()
value := app.dataCache.Get(key)
app.dataMutex.RUnlock()
if value == nil {
app.ensurePagesCache()
app.pagesMutex.RLock()
meta, ok := app.pagesCache[name]
app.pagesMutex.RUnlock()
if !ok {
return map[string]any{}
}
if meta, ok := value.(map[string]any); ok {
return meta
return map[string]any{
"title": meta.Title,
"description": meta.Description,
"keywords": meta.Keywords,
}
if meta, ok := value.(map[string]interface{}); ok {
return meta
}
return map[string]any{}
})
engine.AddFunc("pageMetaField", func(name, field string) string {
app.ensureDataCache()
key := "page." + name
app.dataMutex.RLock()
value := app.dataCache.Get(key)
app.dataMutex.RUnlock()
if value == nil {
return ""
}
meta, ok := value.(map[string]any)
app.ensurePagesCache()
app.pagesMutex.RLock()
meta, ok := app.pagesCache[name]
app.pagesMutex.RUnlock()
if !ok {
if metaAlt, ok := value.(map[string]interface{}); ok {
meta = map[string]any(metaAlt)
} else {
return ""
}
}
fieldValue, ok := meta[field]
if !ok || fieldValue == nil {
return ""
}
if s, ok := fieldValue.(string); ok {
return s
switch field {
case "title":
return meta.Title
case "description":
return meta.Description
case "keywords":
return meta.Keywords
default:
return ""
}
return fmt.Sprint(fieldValue)
})
engine.AddFunc("pageHtml", func(name string, section ...string) template.HTML {
app.ensureHtmlCache()
@@ -305,11 +298,23 @@ func (app *App) ResetImagesCache() {
app.imagesCache = make(map[string]*dbmodels.Image)
}
func (app *App) ResetPagesCache() {
app.pagesMutex.Lock()
defer app.pagesMutex.Unlock()
app.pagesCache = make(map[string]PageMetaData)
}
type PrefixCache struct {
data map[string]any
keys []string
}
type PageMetaData struct {
Title string
Description string
Keywords string
}
func NewPrefixCache() *PrefixCache {
return &PrefixCache{
data: make(map[string]any),
@@ -418,6 +423,43 @@ func (app *App) ensureHtmlCache() {
app.htmlMutex.Unlock()
}
func (app *App) ensurePagesCache() {
app.pagesMutex.RLock()
if app.pagesCache != nil && len(app.pagesCache) > 0 {
app.pagesMutex.RUnlock()
return
}
app.pagesMutex.RUnlock()
pages, err := dbmodels.Pages_All(app.PB.App)
if err != nil {
app.PB.Logger().Error("Failed to fetch pages cache: %v", err)
return
}
cache := make(map[string]PageMetaData, len(pages))
for _, page := range pages {
meta := PageMetaData{
Title: page.Title(),
}
if data := page.Data(); data != nil {
if value, ok := data["description"]; ok && value != nil {
meta.Description = fmt.Sprint(value)
}
if value, ok := data["keywords"]; ok && value != nil {
meta.Keywords = fmt.Sprint(value)
}
}
cache[page.Key()] = meta
}
app.pagesMutex.Lock()
if app.pagesCache == nil || len(app.pagesCache) == 0 {
app.pagesCache = cache
}
app.pagesMutex.Unlock()
}
func (app *App) ensureImagesCache() {
app.imagesMutex.RLock()
if app.imagesCache != nil && len(app.imagesCache) > 0 {

View File

@@ -18,6 +18,14 @@ func (p *Page) URL() string {
return p.GetString(URL_FIELD)
}
func (p *Page) Title() string {
return p.GetString(TITLE_FIELD)
}
func (p *Page) SetTitle(title string) {
p.Set(TITLE_FIELD, title)
}
func (p *Page) SetURL(url string) {
p.Set(URL_FIELD, url)
}

View File

@@ -155,6 +155,12 @@ func Data_All(app core.App) ([]*Data, error) {
return data, err
}
func Pages_All(app core.App) ([]*Page, error) {
pages := make([]*Page, 0)
err := app.RecordQuery(PAGES_TABLE).All(&pages)
return pages, err
}
func Html_All(app core.App) ([]*HTML, error) {
html := make([]*HTML, 0)
err := app.RecordQuery(HTML_TABLE).All(&html)

View File

@@ -582,6 +582,7 @@ func pagesTable() *core.Collection {
func pagesTableFields() core.FieldsList {
fields := core.NewFieldsList(
&core.TextField{Name: dbmodels.KEY_FIELD, Required: true, Presentable: true},
&core.TextField{Name: dbmodels.TITLE_FIELD, Required: false},
&core.TextField{Name: dbmodels.URL_FIELD, Required: false},
&core.TextField{Name: dbmodels.TEMPLATE_FIELD, Required: false},
&core.TextField{Name: dbmodels.LAYOUT_FIELD, Required: false},

View File

@@ -325,42 +325,42 @@ const (
)
var pageMetaSeed = map[string]PageMeta{
pageDataKey(pagemodels.P_INDEX_NAME): {
pagemodels.P_INDEX_NAME: {
Title: INDEX_TITLE,
Description: INDEX_DESCRIPTION,
Keywords: "",
},
pageDataKey(pagemodels.P_REIHEN_NAME): {
pagemodels.P_REIHEN_NAME: {
Title: REIHEN_TITLE,
Description: REIHEN_DESCRIPTION,
Keywords: "",
},
pageDataKey(pagemodels.P_DANK_NAME): {
pagemodels.P_DANK_NAME: {
Title: "Danksagungen",
Description: DANKSAGUNGEN_DESCRIPTION,
Keywords: "",
},
pageDataKey(pagemodels.P_EINFUEHRUNG_NAME): {
pagemodels.P_EINFUEHRUNG_NAME: {
Title: EINLEITUNG_TITLE,
Description: EINLEITUNG_DESCRIPTION,
Keywords: "",
},
pageDataKey(pagemodels.P_KONTAKT_NAME): {
pagemodels.P_KONTAKT_NAME: {
Title: KONTAKT_TITLE,
Description: KONTAKT_DESCRIPTION,
Keywords: "",
},
pageDataKey(pagemodels.P_LIT_NAME): {
pagemodels.P_LIT_NAME: {
Title: LITERATUR_TITLE,
Description: LITERATUR_DESCRIPTION,
Keywords: "",
},
pageDataKey(pagemodels.P_DOK_NAME): {
pagemodels.P_DOK_NAME: {
Title: DOKUMENTATION_TITLE,
Description: DOKUMENTATION_DESCRIPTION,
Keywords: "",
},
pageDataKey(pagemodels.P_KABINETT_NAME): {
pagemodels.P_KABINETT_NAME: {
Title: KABINETT_TITLE,
Description: KABINETT_DESCRIPTION,
Keywords: "",
@@ -382,7 +382,7 @@ var pageHTMLSeed = map[string]string{
func init() {
m.Register(func(app core.App) error {
for key, meta := range pageMetaSeed {
if err := upsertData(app, key, meta); err != nil {
if err := upsertPageMeta(app, key, meta); err != nil {
return err
}
}
@@ -413,7 +413,7 @@ func init() {
}
for key := range pageMetaSeed {
if err := deleteByKey(app, dbmodels.DATA_TABLE, key); err != nil {
if err := deleteByKey(app, dbmodels.PAGES_TABLE, key); err != nil {
return err
}
}

View File

@@ -11,10 +11,6 @@ type PageMeta struct {
Keywords string `json:"keywords"`
}
func pageDataKey(name string) string {
return "page." + name
}
func pageHTMLKey(name, section string) string {
if section == "" {
return "page." + name
@@ -22,6 +18,33 @@ func pageHTMLKey(name, section string) string {
return "page." + name + "." + section
}
func upsertPageMeta(app core.App, key string, meta PageMeta) error {
collection, err := app.FindCollectionByNameOrId(dbmodels.PAGES_TABLE)
if err != nil {
return err
}
record, _ := app.FindFirstRecordByData(collection.Id, dbmodels.KEY_FIELD, key)
if record == nil {
record = core.NewRecord(collection)
record.Set(dbmodels.KEY_FIELD, key)
}
record.Set(dbmodels.TITLE_FIELD, meta.Title)
data := map[string]any{}
if existing := record.Get(dbmodels.DATA_FIELD); existing != nil {
if existingMap, ok := existing.(map[string]any); ok {
data = existingMap
} else if existingMap, ok := existing.(map[string]interface{}); ok {
data = map[string]any(existingMap)
}
}
data["description"] = meta.Description
data["keywords"] = meta.Keywords
record.Set(dbmodels.DATA_FIELD, data)
return app.Save(record)
}
func upsertHTML(app core.App, key, value string) error {
collection, err := app.FindCollectionByNameOrId(dbmodels.HTML_TABLE)
if err != nil {