diff --git a/app/pb.go b/app/pb.go index bcd1e56..858441f 100644 --- a/app/pb.go +++ b/app/pb.go @@ -3,6 +3,9 @@ package app import ( "database/sql" "fmt" + "log/slog" + "sort" + "strings" "sync" "github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels" @@ -30,9 +33,9 @@ type App struct { PB *pocketbase.PocketBase MAConfig Config Pages []pagemodels.IPage - dataCache map[string]any + dataCache *PrefixCache dataMutex sync.RWMutex - htmlCache map[string]any + htmlCache *PrefixCache htmlMutex sync.RWMutex } @@ -63,7 +66,7 @@ func init() { dbx.BuilderFuncMap["pb_sqlite3"] = dbx.BuilderFuncMap["sqlite3"] } -func New(config Config) App { +func New(config Config) *App { app := App{ MAConfig: config, } @@ -71,7 +74,7 @@ func New(config Config) App { app.createPBInstance() app.Bootstrap() - return app + return &app } func (app *App) createPBInstance() { @@ -142,6 +145,10 @@ func (app *App) Serve() error { return app.PB.Start() } +func (app *App) Logger() *slog.Logger { + return app.PB.Logger() +} + func (app *App) createEngine() (*templating.Engine, error) { engine := templating.NewEngine(&views.LayoutFS, &views.RoutesFS) engine.Globals(map[string]interface{}{ @@ -150,61 +157,154 @@ func (app *App) createEngine() (*templating.Engine, error) { "site": map[string]interface{}{ "title": "Musenalm", "lang": "de", - "desc": "Bibliographie deutscher Almanache des 18. und 19. Jahrhunderts", - }}) + "desc": "Bibliographie deutscher Almanache des 18. und 19. Jahrhunderts", + }}) app.ResetDataCache() engine.AddFunc("data", func(key string) any { - if len(app.dataCache) == 0 { - data, err := dbmodels.Data_All(app.PB.App) - if err != nil { - app.PB.Logger().Error("Failed to fetch data cache: %v", err) - return "{}" - } - app.dataMutex.Lock() - for _, d := range data { - app.dataCache[d.Key()] = d.Value() - } - app.dataMutex.Unlock() - } + app.ensureDataCache() app.dataMutex.RLock() defer app.dataMutex.RUnlock() - return app.dataCache[key] + return app.dataCache.Get(key) + }) + engine.AddFunc("dataPrefix", func(prefix string) map[string]any { + app.ensureDataCache() + app.dataMutex.RLock() + defer app.dataMutex.RUnlock() + return app.dataCache.GetPrefix(prefix) }) app.ResetHtmlCache() engine.AddFunc("html", func(key string) any { - if len(app.htmlCache) == 0 { - html, err := dbmodels.Html_All(app.PB.App) - if err != nil { - app.PB.Logger().Error("Failed to fetch html cache: %v", err) - return "{}" - } - app.htmlMutex.Lock() - for _, h := range html { - app.htmlCache[h.Key()] = h.HTML() - } - app.htmlMutex.Unlock() - } + app.ensureHtmlCache() app.htmlMutex.RLock() defer app.htmlMutex.RUnlock() - return app.htmlCache[key] + return app.htmlCache.Get(key) + }) + engine.AddFunc("htmlPrefix", func(prefix string) map[string]any { + app.ensureHtmlCache() + app.htmlMutex.RLock() + defer app.htmlMutex.RUnlock() + return app.htmlCache.GetPrefix(prefix) }) return engine, nil } -// BUG: we cant call this from the templates, bc this App struct is not available +// Core returns the underlying pocketbase core.App +func (app *App) Core() core.App { + return app.PB.App +} + func (app *App) ResetDataCache() { app.dataMutex.Lock() defer app.dataMutex.Unlock() - app.dataCache = make(map[string]any) + app.dataCache = NewPrefixCache() } func (app *App) ResetHtmlCache() { app.htmlMutex.Lock() defer app.htmlMutex.Unlock() - app.htmlCache = make(map[string]any) + app.htmlCache = NewPrefixCache() +} + +type PrefixCache struct { + data map[string]any + keys []string +} + +func NewPrefixCache() *PrefixCache { + return &PrefixCache{ + data: make(map[string]any), + } +} + +func (c *PrefixCache) Get(key string) any { + if c == nil { + return nil + } + return c.data[key] +} + +func (c *PrefixCache) GetPrefix(prefix string) map[string]any { + if c == nil || len(c.keys) == 0 { + return map[string]any{} + } + + start := sort.Search(len(c.keys), func(i int) bool { + return c.keys[i] >= prefix + }) + + matches := make(map[string]any) + for i := start; i < len(c.keys); i++ { + key := c.keys[i] + if !strings.HasPrefix(key, prefix) { + break + } + matches[key] = c.data[key] + } + + return matches +} + +func (app *App) ensureDataCache() { + app.dataMutex.RLock() + if app.dataCache != nil && len(app.dataCache.data) > 0 { + app.dataMutex.RUnlock() + return + } + app.dataMutex.RUnlock() + + data, err := dbmodels.Data_All(app.PB.App) + if err != nil { + app.PB.Logger().Error("Failed to fetch data cache: %v", err) + return + } + + cache := NewPrefixCache() + cache.keys = make([]string, 0, len(data)) + for _, d := range data { + key := d.Key() + cache.data[key] = d.Value() + cache.keys = append(cache.keys, key) + } + sort.Strings(cache.keys) + + app.dataMutex.Lock() + if app.dataCache == nil || len(app.dataCache.data) == 0 { + app.dataCache = cache + } + app.dataMutex.Unlock() +} + +func (app *App) ensureHtmlCache() { + app.htmlMutex.RLock() + if app.htmlCache != nil && len(app.htmlCache.data) > 0 { + app.htmlMutex.RUnlock() + return + } + app.htmlMutex.RUnlock() + + html, err := dbmodels.Html_All(app.PB.App) + if err != nil { + app.PB.Logger().Error("Failed to fetch html cache: %v", err) + return + } + + cache := NewPrefixCache() + cache.keys = make([]string, 0, len(html)) + for _, h := range html { + key := h.Key() + cache.data[key] = h.HTML() + cache.keys = append(cache.keys, key) + } + sort.Strings(cache.keys) + + app.htmlMutex.Lock() + if app.htmlCache == nil || len(app.htmlCache.data) == 0 { + app.htmlCache = cache + } + app.htmlMutex.Unlock() } func (app *App) setWatchers(engine *templating.Engine) { @@ -234,17 +334,17 @@ func (app *App) bindPages(engine *templating.Engine) ServeFunc { // INFO: we put this here, to make sure all migrations are done for _, page := range pages { - err := page.Up(e.App, engine) + err := page.Up(app, engine) if err != nil { app.PB.Logger().Error("Failed to up page %q: %v", "error", err) - page.Down(e.App, engine) + page.Down(app, engine) continue } app.Pages = append(app.Pages, page) } for _, page := range app.Pages { - page.Setup(e.Router, e.App, engine) + page.Setup(e.Router, app, engine) } return e.Next() diff --git a/controllers/404.go b/controllers/404.go index 25a6a7e..3d14fee 100644 --- a/controllers/404.go +++ b/controllers/404.go @@ -24,7 +24,7 @@ type ErrorPage struct { pagemodels.StaticPage } -func (p *ErrorPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *ErrorPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { router.GET(URL_ERROR_404, func(e *core.RequestEvent) error { return engine.Response404(e, nil, nil) }) diff --git a/controllers/abkuerzungen.go b/controllers/abkuerzungen.go index 1b7c8c6..5d73efe 100644 --- a/controllers/abkuerzungen.go +++ b/controllers/abkuerzungen.go @@ -49,12 +49,13 @@ type AbkuerzungenResult struct { Entries []AbkEntry } -func (p *AbkuerzungenPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *AbkuerzungenPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() router.GET(URL_ABKUERZUNGEN, p.GET(engine, app)) rg := router.Group(URL_ABKUERZUNGEN) rg.BindFunc(middleware.IsAdminOrEditor()) - rg.POST("", p.POST(engine, app)) + rg.POST("", p.POST(engine, ia)) return nil } @@ -123,8 +124,9 @@ type abkFormEntry struct { Delete string `form:"_delete"` } -func (p *AbkuerzungenPage) POST(engine *templating.Engine, app core.App) HandleFunc { +func (p *AbkuerzungenPage) POST(engine *templating.Engine, ia pagemodels.IApp) HandleFunc { return func(e *core.RequestEvent) error { + app := ia.Core() req := templating.NewRequest(e) // Parse form manually to handle array syntax @@ -198,6 +200,8 @@ func (p *AbkuerzungenPage) POST(engine *templating.Engine, app core.App) HandleF return p.redirectError(e, "Speichern fehlgeschlagen.") } + go ia.ResetDataCache() + // Redirect with success message redirect := fmt.Sprintf("%s?success=%s", URL_ABKUERZUNGEN, url.QueryEscape("Änderungen gespeichert.")) return e.Redirect(http.StatusSeeOther, redirect) diff --git a/controllers/almanach.go b/controllers/almanach.go index 495fa2b..b0521e1 100644 --- a/controllers/almanach.go +++ b/controllers/almanach.go @@ -80,7 +80,8 @@ type AlmanachPage struct { pagemodels.StaticPage } -func (p *AlmanachPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *AlmanachPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() router.GET(p.URL, p.GET(engine, app)) return nil } diff --git a/controllers/almanach_edit.go b/controllers/almanach_edit.go index 71459b8..fdf0bf9 100644 --- a/controllers/almanach_edit.go +++ b/controllers/almanach_edit.go @@ -40,7 +40,8 @@ type AlmanachEditPage struct { pagemodels.StaticPage } -func (p *AlmanachEditPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *AlmanachEditPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() rg := router.Group(URL_ALMANACH) rg.BindFunc(middleware.IsAdminOrEditor()) rg.GET(URL_ALMANACH_EDIT, p.GET(engine, app)) diff --git a/controllers/almanach_new.go b/controllers/almanach_new.go index 37490d0..db3d7c8 100644 --- a/controllers/almanach_new.go +++ b/controllers/almanach_new.go @@ -35,7 +35,8 @@ type AlmanachNewPage struct { pagemodels.StaticPage } -func (p *AlmanachNewPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *AlmanachNewPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() rg := router.Group(URL_ALMANACH_NEW) rg.BindFunc(middleware.IsAdminOrEditor()) rg.GET("", p.GET(engine, app)) diff --git a/controllers/api_agents.go b/controllers/api_agents.go index 91daa35..0dc48ee 100644 --- a/controllers/api_agents.go +++ b/controllers/api_agents.go @@ -8,6 +8,7 @@ import ( "github.com/Theodor-Springmann-Stiftung/musenalm/app" "github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels" "github.com/Theodor-Springmann-Stiftung/musenalm/middleware" + "github.com/Theodor-Springmann-Stiftung/musenalm/pagemodels" "github.com/Theodor-Springmann-Stiftung/musenalm/templating" "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/tools/router" @@ -24,15 +25,16 @@ func init() { type AgentsAPI struct{} -func (p *AgentsAPI) Up(app core.App, engine *templating.Engine) error { +func (p *AgentsAPI) Up(ia pagemodels.IApp, engine *templating.Engine) error { return nil } -func (p *AgentsAPI) Down(app core.App, engine *templating.Engine) error { +func (p *AgentsAPI) Down(ia pagemodels.IApp, engine *templating.Engine) error { return nil } -func (p *AgentsAPI) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *AgentsAPI) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() rg := router.Group(URL_API_AGENTS) rg.BindFunc(middleware.Authenticated(app)) rg.BindFunc(middleware.IsAdminOrEditor()) diff --git a/controllers/api_entries.go b/controllers/api_entries.go index c5e414b..ee29874 100644 --- a/controllers/api_entries.go +++ b/controllers/api_entries.go @@ -8,6 +8,7 @@ import ( "github.com/Theodor-Springmann-Stiftung/musenalm/app" "github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels" "github.com/Theodor-Springmann-Stiftung/musenalm/middleware" + "github.com/Theodor-Springmann-Stiftung/musenalm/pagemodels" "github.com/Theodor-Springmann-Stiftung/musenalm/templating" "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/tools/router" @@ -24,15 +25,16 @@ func init() { type EntriesAPI struct{} -func (p *EntriesAPI) Up(app core.App, engine *templating.Engine) error { +func (p *EntriesAPI) Up(ia pagemodels.IApp, engine *templating.Engine) error { return nil } -func (p *EntriesAPI) Down(app core.App, engine *templating.Engine) error { +func (p *EntriesAPI) Down(ia pagemodels.IApp, engine *templating.Engine) error { return nil } -func (p *EntriesAPI) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *EntriesAPI) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() rg := router.Group(URL_API_ENTRIES) rg.BindFunc(middleware.Authenticated(app)) rg.BindFunc(middleware.IsAdminOrEditor()) diff --git a/controllers/api_places.go b/controllers/api_places.go index b8a1ce6..de9529e 100644 --- a/controllers/api_places.go +++ b/controllers/api_places.go @@ -8,6 +8,7 @@ import ( "github.com/Theodor-Springmann-Stiftung/musenalm/app" "github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels" "github.com/Theodor-Springmann-Stiftung/musenalm/middleware" + "github.com/Theodor-Springmann-Stiftung/musenalm/pagemodels" "github.com/Theodor-Springmann-Stiftung/musenalm/templating" "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/tools/router" @@ -24,15 +25,16 @@ func init() { type PlacesAPI struct{} -func (p *PlacesAPI) Up(app core.App, engine *templating.Engine) error { +func (p *PlacesAPI) Up(ia pagemodels.IApp, engine *templating.Engine) error { return nil } -func (p *PlacesAPI) Down(app core.App, engine *templating.Engine) error { +func (p *PlacesAPI) Down(ia pagemodels.IApp, engine *templating.Engine) error { return nil } -func (p *PlacesAPI) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *PlacesAPI) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() rg := router.Group(URL_API_PLACES) rg.BindFunc(middleware.Authenticated(app)) rg.BindFunc(middleware.IsAdminOrEditor()) diff --git a/controllers/api_series.go b/controllers/api_series.go index 063a05d..dcc8301 100644 --- a/controllers/api_series.go +++ b/controllers/api_series.go @@ -8,6 +8,7 @@ import ( "github.com/Theodor-Springmann-Stiftung/musenalm/app" "github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels" "github.com/Theodor-Springmann-Stiftung/musenalm/middleware" + "github.com/Theodor-Springmann-Stiftung/musenalm/pagemodels" "github.com/Theodor-Springmann-Stiftung/musenalm/templating" "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/tools/router" @@ -24,15 +25,16 @@ func init() { type SeriesAPI struct{} -func (p *SeriesAPI) Up(app core.App, engine *templating.Engine) error { +func (p *SeriesAPI) Up(ia pagemodels.IApp, engine *templating.Engine) error { return nil } -func (p *SeriesAPI) Down(app core.App, engine *templating.Engine) error { +func (p *SeriesAPI) Down(ia pagemodels.IApp, engine *templating.Engine) error { return nil } -func (p *SeriesAPI) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *SeriesAPI) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() rg := router.Group(URL_API_SERIES) rg.BindFunc(middleware.Authenticated(app)) rg.BindFunc(middleware.IsAdminOrEditor()) diff --git a/controllers/beitrag.go b/controllers/beitrag.go index 590b814..14a18b8 100644 --- a/controllers/beitrag.go +++ b/controllers/beitrag.go @@ -31,7 +31,8 @@ type BeitragPage struct { pagemodels.StaticPage } -func (p *BeitragPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *BeitragPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() router.GET(p.URL, func(e *core.RequestEvent) error { id := e.Request.PathValue("id") data := make(map[string]any) diff --git a/controllers/index.go b/controllers/index.go index 9c01abb..046ee41 100644 --- a/controllers/index.go +++ b/controllers/index.go @@ -25,7 +25,8 @@ type IndexPage struct { } // TODO: -func (p *IndexPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *IndexPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() router.GET("/{$}", func(e *core.RequestEvent) error { bilder := []*pagemodels.IndexBilder{} err := app.RecordQuery(pagemodels.GeneratePageTableName(pagemodels.P_INDEX_NAME, pagemodels.T_INDEX_BILDER)). diff --git a/controllers/login.go b/controllers/login.go index 7f842f2..22b935e 100644 --- a/controllers/login.go +++ b/controllers/login.go @@ -47,7 +47,8 @@ type LoginPage struct { pagemodels.StaticPage } -func (p *LoginPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *LoginPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() router.GET(URL_LOGIN, p.GET(engine, app)) r := router.POST(URL_LOGIN, p.POST(engine, app)) r.BindFunc(middleware.RateLimiter(30, time.Minute*2, time.Hour*6)) diff --git a/controllers/logout.go b/controllers/logout.go index db2038d..7e9928e 100644 --- a/controllers/logout.go +++ b/controllers/logout.go @@ -28,7 +28,8 @@ type LogoutPage struct { pagemodels.StaticPage } -func (p *LogoutPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *LogoutPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() router.GET(p.URL, p.GET(app)) return nil } diff --git a/controllers/ort_edit.go b/controllers/ort_edit.go index 67e2d1b..f7f86db 100644 --- a/controllers/ort_edit.go +++ b/controllers/ort_edit.go @@ -41,7 +41,8 @@ type OrtEditPage struct { pagemodels.StaticPage } -func (p *OrtEditPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *OrtEditPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() rg := router.Group(URL_ORT) rg.BindFunc(middleware.IsAdminOrEditor()) rg.GET(URL_ORT_EDIT, p.GET(engine, app)) diff --git a/controllers/ort_new.go b/controllers/ort_new.go index cfd7b7f..c040a23 100644 --- a/controllers/ort_new.go +++ b/controllers/ort_new.go @@ -36,7 +36,8 @@ type OrtNewPage struct { pagemodels.StaticPage } -func (p *OrtNewPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *OrtNewPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() rg := router.Group(URL_ORTE_NEW) rg.BindFunc(middleware.IsAdminOrEditor()) rg.GET("", p.GET(engine, app)) diff --git a/controllers/orte.go b/controllers/orte.go index 5e9067e..4fb6f1f 100644 --- a/controllers/orte.go +++ b/controllers/orte.go @@ -34,7 +34,8 @@ type OrteResult struct { Places []*dbmodels.Place } -func (p *OrtePage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *OrtePage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() router.GET(URL_ORTE, func(e *core.RequestEvent) error { places := []*dbmodels.Place{} if err := app.RecordQuery(dbmodels.PLACES_TABLE).All(&places); err != nil { diff --git a/controllers/person.go b/controllers/person.go index 9fcf039..b57e5d8 100644 --- a/controllers/person.go +++ b/controllers/person.go @@ -34,7 +34,8 @@ type PersonPage struct { pagemodels.StaticPage } -func (p *PersonPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *PersonPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() router.GET(URL_PERSON, func(e *core.RequestEvent) error { person := e.Request.PathValue("id") data := make(map[string]interface{}) diff --git a/controllers/person_edit.go b/controllers/person_edit.go index 57894bd..1da5f6d 100644 --- a/controllers/person_edit.go +++ b/controllers/person_edit.go @@ -38,7 +38,8 @@ type PersonEditPage struct { pagemodels.StaticPage } -func (p *PersonEditPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *PersonEditPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() rg := router.Group("/person/{id}/") rg.BindFunc(middleware.IsAdminOrEditor()) rg.GET(URL_PERSON_EDIT, p.GET(engine, app)) diff --git a/controllers/person_new.go b/controllers/person_new.go index 61555f8..31ad617 100644 --- a/controllers/person_new.go +++ b/controllers/person_new.go @@ -36,7 +36,8 @@ type PersonNewPage struct { pagemodels.StaticPage } -func (p *PersonNewPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *PersonNewPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() rg := router.Group(URL_PERSONEN_NEW) rg.BindFunc(middleware.IsAdminOrEditor()) rg.GET("", p.GET(engine, app)) diff --git a/controllers/personen.go b/controllers/personen.go index f69ef36..961ee4a 100644 --- a/controllers/personen.go +++ b/controllers/personen.go @@ -28,7 +28,8 @@ type PersonenPage struct { pagemodels.StaticPage } -func (p *PersonenPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *PersonenPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() router.GET(URL_PERSONEN, func(e *core.RequestEvent) error { if e.Request.URL.Query().Get(PARAM_SEARCH) != "" { return p.SearchRequest(app, engine, e) diff --git a/controllers/reihe.go b/controllers/reihe.go index 57199db..c3de180 100644 --- a/controllers/reihe.go +++ b/controllers/reihe.go @@ -31,7 +31,8 @@ type ReihePage struct { } // TODO: data richtig seutzen, damit die Reihe mit dem template _reihe angezeigt wird -func (p *ReihePage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *ReihePage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() router.GET(URL_REIHE, func(e *core.RequestEvent) error { id := e.Request.PathValue("id") data := make(map[string]interface{}) diff --git a/controllers/reihe_edit.go b/controllers/reihe_edit.go index 56d23a8..36e44f4 100644 --- a/controllers/reihe_edit.go +++ b/controllers/reihe_edit.go @@ -39,7 +39,8 @@ type ReiheEditPage struct { pagemodels.StaticPage } -func (p *ReiheEditPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *ReiheEditPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() rg := router.Group(URL_REIHE) rg.BindFunc(middleware.IsAdminOrEditor()) rg.GET(URL_REIHE_EDIT, p.GET(engine, app)) diff --git a/controllers/reihe_new.go b/controllers/reihe_new.go index fe7fe86..b5a257b 100644 --- a/controllers/reihe_new.go +++ b/controllers/reihe_new.go @@ -36,7 +36,8 @@ type ReiheNewPage struct { pagemodels.StaticPage } -func (p *ReiheNewPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *ReiheNewPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() rg := router.Group(URL_REIHEN_NEW) rg.BindFunc(middleware.IsAdminOrEditor()) rg.GET("", p.GET(engine, app)) diff --git a/controllers/reihen.go b/controllers/reihen.go index 84b8847..cad7544 100644 --- a/controllers/reihen.go +++ b/controllers/reihen.go @@ -40,7 +40,8 @@ type ReihenPage struct { pagemodels.DefaultPage[*pagemodels.DefaultPageRecord] } -func (p *ReihenPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *ReihenPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() router.GET(URL_REIHEN, func(e *core.RequestEvent) error { search := e.Request.URL.Query().Get(PARAM_SEARCH) if search != "" { diff --git a/controllers/suche.go b/controllers/suche.go index 2274812..6603259 100644 --- a/controllers/suche.go +++ b/controllers/suche.go @@ -42,7 +42,8 @@ func init() { app.Register(rp) } -func (p *SuchePage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *SuchePage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() router.GET(URL_SUCHE_ALT, func(e *core.RequestEvent) error { return e.Redirect(http.StatusPermanentRedirect, DEFAULT_SUCHE) }) diff --git a/controllers/user_create.go b/controllers/user_create.go index 099d8b7..f5182da 100644 --- a/controllers/user_create.go +++ b/controllers/user_create.go @@ -34,7 +34,8 @@ type UserCreatePage struct { pagemodels.StaticPage } -func (p *UserCreatePage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *UserCreatePage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() rg := router.Group(URL_USER_CREATE) rg.BindFunc(middleware.HasToken()) rg.GET("{"+PATH_VALUE_ROLE+"}", p.GET(engine, app)) diff --git a/controllers/user_edit.go b/controllers/user_edit.go index f02d87e..7cf10a7 100644 --- a/controllers/user_edit.go +++ b/controllers/user_edit.go @@ -40,7 +40,8 @@ type UserEditPage struct { pagemodels.StaticPage } -func (p *UserEditPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *UserEditPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() rg := router.Group(URL_USER) rg.BindFunc(middleware.IsAdminOrUser()) rg.GET(URL_USER_EDIT, p.GET(engine, app)) diff --git a/controllers/user_management.go b/controllers/user_management.go index a0d0c2e..ff9a0eb 100644 --- a/controllers/user_management.go +++ b/controllers/user_management.go @@ -42,7 +42,8 @@ type UserManagementPage struct { pagemodels.StaticPage } -func (p *UserManagementPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *UserManagementPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() rg := router.Group(URL_USER_MANAGEMENT) rg.BindFunc(middleware.IsAdmin()) rg.GET("", p.GET(engine, app)) diff --git a/controllers/user_management_access.go b/controllers/user_management_access.go index c60e10c..53d57ee 100644 --- a/controllers/user_management_access.go +++ b/controllers/user_management_access.go @@ -35,7 +35,8 @@ type UserManagementAccessPage struct { pagemodels.StaticPage } -func (p *UserManagementAccessPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *UserManagementAccessPage) Setup(router *router.Router[*core.RequestEvent], ia pagemodels.IApp, engine *templating.Engine) error { + app := ia.Core() rg := router.Group(URL_USER_MANAGEMENT_ACCESS) rg.BindFunc(middleware.IsAdmin()) rg.GET("{"+PATH_VALUE_ROLE+"}", p.GET(engine, app)) diff --git a/pagemodels/default.go b/pagemodels/default.go index 0086d1b..8848fef 100644 --- a/pagemodels/default.go +++ b/pagemodels/default.go @@ -16,33 +16,33 @@ type DefaultPage[T IPageCollection] struct { URL string } -func (r *DefaultPage[T]) Up(app core.App, engine *templating.Engine) error { - _, err := app.FindCollectionByNameOrId(GeneratePageTableName(r.Name)) +func (r *DefaultPage[T]) Up(app IApp, engine *templating.Engine) error { + _, err := app.Core().FindCollectionByNameOrId(GeneratePageTableName(r.Name)) if err == sql.ErrNoRows { collection := r.Record.Collection(r.Name) - err = app.Save(collection) + err = app.Core().Save(collection) if err != nil { - app.Logger().Error("Error saving collection", "Name", GeneratePageTableName(r.Name), "Error", err, "Collection", collection) + app.Core().Logger().Error("Error saving collection", "Name", GeneratePageTableName(r.Name), "Error", err, "Collection", collection) return err } } else if err != nil { - app.Logger().Error("Error finding collection %s: %s", GeneratePageTableName(r.Name), err) + app.Core().Logger().Error("Error finding collection %s: %s", GeneratePageTableName(r.Name), err) return err } return nil } -func (r *DefaultPage[T]) Down(app core.App, engine *templating.Engine) error { +func (r *DefaultPage[T]) Down(app IApp, engine *templating.Engine) error { return nil } -func (p *DefaultPage[T]) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *DefaultPage[T]) Setup(router *router.Router[*core.RequestEvent], app IApp, engine *templating.Engine) error { router.GET(p.URL, func(e *core.RequestEvent) error { data := make(map[string]interface{}) record := &core.Record{} - err := app.RecordQuery(GeneratePageTableName(p.Name)). + err := app.Core().RecordQuery(GeneratePageTableName(p.Name)). OrderBy("created"). One(record) if err != nil { diff --git a/pagemodels/page.go b/pagemodels/page.go index 8b94825..edccdee 100644 --- a/pagemodels/page.go +++ b/pagemodels/page.go @@ -4,11 +4,18 @@ import ( "github.com/Theodor-Springmann-Stiftung/musenalm/templating" "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/tools/router" + "log/slog" ) -type IPage interface { - Up(app core.App, engine *templating.Engine) error - Down(app core.App, engine *templating.Engine) error - // TODO: pass the cache here - Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error +type IApp interface { + Core() core.App + ResetDataCache() + ResetHtmlCache() + Logger() *slog.Logger +} + +type IPage interface { + Up(app IApp, engine *templating.Engine) error + Down(app IApp, engine *templating.Engine) error + Setup(router *router.Router[*core.RequestEvent], app IApp, engine *templating.Engine) error } diff --git a/pagemodels/static.go b/pagemodels/static.go index b51c4c9..f57e6ca 100644 --- a/pagemodels/static.go +++ b/pagemodels/static.go @@ -13,7 +13,7 @@ type StaticPage struct { URL string } -func (p *StaticPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *StaticPage) Setup(router *router.Router[*core.RequestEvent], ia IApp, engine *templating.Engine) error { router.GET(p.URL, func(e *core.RequestEvent) error { data := map[string]interface{}{} data["record"] = p @@ -22,10 +22,10 @@ func (p *StaticPage) Setup(router *router.Router[*core.RequestEvent], app core.A return nil } -func (p *StaticPage) Up(app core.App, engine *templating.Engine) error { +func (p *StaticPage) Up(ia IApp, engine *templating.Engine) error { return nil } -func (p *StaticPage) Down(app core.App, engine *templating.Engine) error { +func (p *StaticPage) Down(ia IApp, engine *templating.Engine) error { return nil } diff --git a/pagemodels/textpage.go b/pagemodels/textpage.go index 25bc888..ff0a348 100644 --- a/pagemodels/textpage.go +++ b/pagemodels/textpage.go @@ -52,15 +52,16 @@ func (r *TextPage) SetText(text string) { r.Set(F_TEXT, text) } -func (r *TextPage) Up(app core.App, engine *templating.Engine) error { +func (r *TextPage) Up(ia IApp, engine *templating.Engine) error { return nil } -func (r *TextPage) Down(app core.App, engine *templating.Engine) error { +func (r *TextPage) Down(ia IApp, engine *templating.Engine) error { return nil } -func (p *TextPage) Setup(router *router.Router[*core.RequestEvent], app core.App, engine *templating.Engine) error { +func (p *TextPage) Setup(router *router.Router[*core.RequestEvent], ia IApp, engine *templating.Engine) error { + app := ia.Core() router.GET(p.URL, func(e *core.RequestEvent) error { data := make(map[string]interface{}) diff --git a/views/routes/components/_content.gohtml b/views/routes/components/_content.gohtml index c5b71f0..0dff8c6 100644 --- a/views/routes/components/_content.gohtml +++ b/views/routes/components/_content.gohtml @@ -131,7 +131,7 @@