mirror of
https://github.com/Theodor-Springmann-Stiftung/musenalm.git
synced 2026-02-04 10:35:30 +00:00
+extra page table
This commit is contained in:
104
app/pb.go
104
app/pb.go
@@ -38,6 +38,8 @@ type App struct {
|
|||||||
dataMutex sync.RWMutex
|
dataMutex sync.RWMutex
|
||||||
htmlCache *PrefixCache
|
htmlCache *PrefixCache
|
||||||
htmlMutex sync.RWMutex
|
htmlMutex sync.RWMutex
|
||||||
|
pagesCache map[string]PageMetaData
|
||||||
|
pagesMutex sync.RWMutex
|
||||||
imagesCache map[string]*dbmodels.Image
|
imagesCache map[string]*dbmodels.Image
|
||||||
imagesMutex sync.RWMutex
|
imagesMutex sync.RWMutex
|
||||||
}
|
}
|
||||||
@@ -205,48 +207,39 @@ func (app *App) createEngine() (*templating.Engine, error) {
|
|||||||
}
|
}
|
||||||
return template.HTML(value)
|
return template.HTML(value)
|
||||||
})
|
})
|
||||||
|
app.ResetPagesCache()
|
||||||
engine.AddFunc("pageMeta", func(name string) map[string]any {
|
engine.AddFunc("pageMeta", func(name string) map[string]any {
|
||||||
app.ensureDataCache()
|
app.ensurePagesCache()
|
||||||
key := "page." + name
|
app.pagesMutex.RLock()
|
||||||
app.dataMutex.RLock()
|
meta, ok := app.pagesCache[name]
|
||||||
value := app.dataCache.Get(key)
|
app.pagesMutex.RUnlock()
|
||||||
app.dataMutex.RUnlock()
|
if !ok {
|
||||||
if value == nil {
|
|
||||||
return map[string]any{}
|
return map[string]any{}
|
||||||
}
|
}
|
||||||
if meta, ok := value.(map[string]any); ok {
|
return map[string]any{
|
||||||
return meta
|
"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 {
|
engine.AddFunc("pageMetaField", func(name, field string) string {
|
||||||
app.ensureDataCache()
|
app.ensurePagesCache()
|
||||||
key := "page." + name
|
app.pagesMutex.RLock()
|
||||||
app.dataMutex.RLock()
|
meta, ok := app.pagesCache[name]
|
||||||
value := app.dataCache.Get(key)
|
app.pagesMutex.RUnlock()
|
||||||
app.dataMutex.RUnlock()
|
|
||||||
if value == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
meta, ok := value.(map[string]any)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
if metaAlt, ok := value.(map[string]interface{}); ok {
|
|
||||||
meta = map[string]any(metaAlt)
|
|
||||||
} else {
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
}
|
switch field {
|
||||||
fieldValue, ok := meta[field]
|
case "title":
|
||||||
if !ok || fieldValue == nil {
|
return meta.Title
|
||||||
|
case "description":
|
||||||
|
return meta.Description
|
||||||
|
case "keywords":
|
||||||
|
return meta.Keywords
|
||||||
|
default:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
if s, ok := fieldValue.(string); ok {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
return fmt.Sprint(fieldValue)
|
|
||||||
})
|
})
|
||||||
engine.AddFunc("pageHtml", func(name string, section ...string) template.HTML {
|
engine.AddFunc("pageHtml", func(name string, section ...string) template.HTML {
|
||||||
app.ensureHtmlCache()
|
app.ensureHtmlCache()
|
||||||
@@ -305,11 +298,23 @@ func (app *App) ResetImagesCache() {
|
|||||||
app.imagesCache = make(map[string]*dbmodels.Image)
|
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 {
|
type PrefixCache struct {
|
||||||
data map[string]any
|
data map[string]any
|
||||||
keys []string
|
keys []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PageMetaData struct {
|
||||||
|
Title string
|
||||||
|
Description string
|
||||||
|
Keywords string
|
||||||
|
}
|
||||||
|
|
||||||
func NewPrefixCache() *PrefixCache {
|
func NewPrefixCache() *PrefixCache {
|
||||||
return &PrefixCache{
|
return &PrefixCache{
|
||||||
data: make(map[string]any),
|
data: make(map[string]any),
|
||||||
@@ -418,6 +423,43 @@ func (app *App) ensureHtmlCache() {
|
|||||||
app.htmlMutex.Unlock()
|
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() {
|
func (app *App) ensureImagesCache() {
|
||||||
app.imagesMutex.RLock()
|
app.imagesMutex.RLock()
|
||||||
if app.imagesCache != nil && len(app.imagesCache) > 0 {
|
if app.imagesCache != nil && len(app.imagesCache) > 0 {
|
||||||
|
|||||||
@@ -18,6 +18,14 @@ func (p *Page) URL() string {
|
|||||||
return p.GetString(URL_FIELD)
|
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) {
|
func (p *Page) SetURL(url string) {
|
||||||
p.Set(URL_FIELD, url)
|
p.Set(URL_FIELD, url)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,6 +155,12 @@ func Data_All(app core.App) ([]*Data, error) {
|
|||||||
return data, err
|
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) {
|
func Html_All(app core.App) ([]*HTML, error) {
|
||||||
html := make([]*HTML, 0)
|
html := make([]*HTML, 0)
|
||||||
err := app.RecordQuery(HTML_TABLE).All(&html)
|
err := app.RecordQuery(HTML_TABLE).All(&html)
|
||||||
|
|||||||
@@ -582,6 +582,7 @@ func pagesTable() *core.Collection {
|
|||||||
func pagesTableFields() core.FieldsList {
|
func pagesTableFields() core.FieldsList {
|
||||||
fields := core.NewFieldsList(
|
fields := core.NewFieldsList(
|
||||||
&core.TextField{Name: dbmodels.KEY_FIELD, Required: true, Presentable: true},
|
&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.URL_FIELD, Required: false},
|
||||||
&core.TextField{Name: dbmodels.TEMPLATE_FIELD, Required: false},
|
&core.TextField{Name: dbmodels.TEMPLATE_FIELD, Required: false},
|
||||||
&core.TextField{Name: dbmodels.LAYOUT_FIELD, Required: false},
|
&core.TextField{Name: dbmodels.LAYOUT_FIELD, Required: false},
|
||||||
|
|||||||
@@ -325,42 +325,42 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var pageMetaSeed = map[string]PageMeta{
|
var pageMetaSeed = map[string]PageMeta{
|
||||||
pageDataKey(pagemodels.P_INDEX_NAME): {
|
pagemodels.P_INDEX_NAME: {
|
||||||
Title: INDEX_TITLE,
|
Title: INDEX_TITLE,
|
||||||
Description: INDEX_DESCRIPTION,
|
Description: INDEX_DESCRIPTION,
|
||||||
Keywords: "",
|
Keywords: "",
|
||||||
},
|
},
|
||||||
pageDataKey(pagemodels.P_REIHEN_NAME): {
|
pagemodels.P_REIHEN_NAME: {
|
||||||
Title: REIHEN_TITLE,
|
Title: REIHEN_TITLE,
|
||||||
Description: REIHEN_DESCRIPTION,
|
Description: REIHEN_DESCRIPTION,
|
||||||
Keywords: "",
|
Keywords: "",
|
||||||
},
|
},
|
||||||
pageDataKey(pagemodels.P_DANK_NAME): {
|
pagemodels.P_DANK_NAME: {
|
||||||
Title: "Danksagungen",
|
Title: "Danksagungen",
|
||||||
Description: DANKSAGUNGEN_DESCRIPTION,
|
Description: DANKSAGUNGEN_DESCRIPTION,
|
||||||
Keywords: "",
|
Keywords: "",
|
||||||
},
|
},
|
||||||
pageDataKey(pagemodels.P_EINFUEHRUNG_NAME): {
|
pagemodels.P_EINFUEHRUNG_NAME: {
|
||||||
Title: EINLEITUNG_TITLE,
|
Title: EINLEITUNG_TITLE,
|
||||||
Description: EINLEITUNG_DESCRIPTION,
|
Description: EINLEITUNG_DESCRIPTION,
|
||||||
Keywords: "",
|
Keywords: "",
|
||||||
},
|
},
|
||||||
pageDataKey(pagemodels.P_KONTAKT_NAME): {
|
pagemodels.P_KONTAKT_NAME: {
|
||||||
Title: KONTAKT_TITLE,
|
Title: KONTAKT_TITLE,
|
||||||
Description: KONTAKT_DESCRIPTION,
|
Description: KONTAKT_DESCRIPTION,
|
||||||
Keywords: "",
|
Keywords: "",
|
||||||
},
|
},
|
||||||
pageDataKey(pagemodels.P_LIT_NAME): {
|
pagemodels.P_LIT_NAME: {
|
||||||
Title: LITERATUR_TITLE,
|
Title: LITERATUR_TITLE,
|
||||||
Description: LITERATUR_DESCRIPTION,
|
Description: LITERATUR_DESCRIPTION,
|
||||||
Keywords: "",
|
Keywords: "",
|
||||||
},
|
},
|
||||||
pageDataKey(pagemodels.P_DOK_NAME): {
|
pagemodels.P_DOK_NAME: {
|
||||||
Title: DOKUMENTATION_TITLE,
|
Title: DOKUMENTATION_TITLE,
|
||||||
Description: DOKUMENTATION_DESCRIPTION,
|
Description: DOKUMENTATION_DESCRIPTION,
|
||||||
Keywords: "",
|
Keywords: "",
|
||||||
},
|
},
|
||||||
pageDataKey(pagemodels.P_KABINETT_NAME): {
|
pagemodels.P_KABINETT_NAME: {
|
||||||
Title: KABINETT_TITLE,
|
Title: KABINETT_TITLE,
|
||||||
Description: KABINETT_DESCRIPTION,
|
Description: KABINETT_DESCRIPTION,
|
||||||
Keywords: "",
|
Keywords: "",
|
||||||
@@ -382,7 +382,7 @@ var pageHTMLSeed = map[string]string{
|
|||||||
func init() {
|
func init() {
|
||||||
m.Register(func(app core.App) error {
|
m.Register(func(app core.App) error {
|
||||||
for key, meta := range pageMetaSeed {
|
for key, meta := range pageMetaSeed {
|
||||||
if err := upsertData(app, key, meta); err != nil {
|
if err := upsertPageMeta(app, key, meta); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -413,7 +413,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for key := range pageMetaSeed {
|
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
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,6 @@ type PageMeta struct {
|
|||||||
Keywords string `json:"keywords"`
|
Keywords string `json:"keywords"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func pageDataKey(name string) string {
|
|
||||||
return "page." + name
|
|
||||||
}
|
|
||||||
|
|
||||||
func pageHTMLKey(name, section string) string {
|
func pageHTMLKey(name, section string) string {
|
||||||
if section == "" {
|
if section == "" {
|
||||||
return "page." + name
|
return "page." + name
|
||||||
@@ -22,6 +18,33 @@ func pageHTMLKey(name, section string) string {
|
|||||||
return "page." + name + "." + section
|
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 {
|
func upsertHTML(app core.App, key, value string) error {
|
||||||
collection, err := app.FindCollectionByNameOrId(dbmodels.HTML_TABLE)
|
collection, err := app.FindCollectionByNameOrId(dbmodels.HTML_TABLE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user