mirror of
https://github.com/Theodor-Springmann-Stiftung/lenz-web.git
synced 2026-03-21 13:55:30 +00:00
Better inital
This commit is contained in:
114
app/app.go
114
app/app.go
@@ -1,27 +1,121 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
gitpkg "github.com/Theodor-Springmann-Stiftung/lenz-web/git"
|
||||
"github.com/Theodor-Springmann-Stiftung/lenz-web/git"
|
||||
"github.com/Theodor-Springmann-Stiftung/lenz-web/xmlmodels"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
mu sync.Mutex
|
||||
lib atomic.Pointer[xmlmodels.Library]
|
||||
mu sync.Mutex
|
||||
lib atomic.Pointer[xmlmodels.Library]
|
||||
repo atomic.Pointer[git.Repo]
|
||||
tmpl *template.Template
|
||||
routes []Route
|
||||
err error
|
||||
}
|
||||
|
||||
func New() *App {
|
||||
return &App{}
|
||||
func New(cfg Config) (*App, error) {
|
||||
a := &App{}
|
||||
if err := a.init(cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func (a *App) Library() *xmlmodels.Library {
|
||||
return a.lib.Load()
|
||||
}
|
||||
|
||||
func (a *App) RefreshLibrary(dir string, commit *gitpkg.Commit) (*xmlmodels.Library, error) {
|
||||
func (a *App) Repo() *git.Repo {
|
||||
return a.repo.Load()
|
||||
}
|
||||
|
||||
func (a *App) Templates() *template.Template {
|
||||
return a.tmpl
|
||||
}
|
||||
|
||||
func (a *App) Routes() []Route {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
||||
ret := make([]Route, len(a.routes))
|
||||
copy(ret, a.routes)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (a *App) RenderPath(path string) ([]byte, error) {
|
||||
a.mu.Lock()
|
||||
var route *Route
|
||||
for i := range a.routes {
|
||||
if a.routes[i].Path == path {
|
||||
r := a.routes[i]
|
||||
route = &r
|
||||
break
|
||||
}
|
||||
}
|
||||
a.mu.Unlock()
|
||||
|
||||
if route == nil || route.page == nil {
|
||||
return nil, fmt.Errorf("no route for path: %s", path)
|
||||
}
|
||||
|
||||
model, err := route.page.Model(a, *route)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return route.page.Render(a, *route, model)
|
||||
}
|
||||
|
||||
func (a *App) init(cfg Config) error {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
||||
path := filepath.Join(cfg.BaseDIR, cfg.GITPath)
|
||||
|
||||
repo, err := git.OpenOrClone(path, cfg.GitURL, cfg.GitBranch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := repo.Pull(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
latest, err := repo.Latest()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lib, err := xmlmodels.Parse(repo.Path, latest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmpl, err := parseTemplates()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.repo.Store(repo)
|
||||
a.lib.Store(lib)
|
||||
a.tmpl = tmpl
|
||||
|
||||
routes, err := discoverPages(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.routes = routes
|
||||
a.err = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) RefreshLibrary(dir string, commit *git.Commit) (*xmlmodels.Library, error) {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
||||
@@ -31,5 +125,13 @@ func (a *App) RefreshLibrary(dir string, commit *gitpkg.Commit) (*xmlmodels.Libr
|
||||
}
|
||||
|
||||
a.lib.Store(lib)
|
||||
|
||||
routes, err := discoverPages(a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
a.routes = routes
|
||||
a.err = nil
|
||||
return lib, nil
|
||||
}
|
||||
|
||||
55
app/helpers.go
Normal file
55
app/helpers.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"io/fs"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/Theodor-Springmann-Stiftung/lenz-web/templates"
|
||||
)
|
||||
|
||||
func (a *App) Error() error {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
return a.err
|
||||
}
|
||||
|
||||
func discoverPages(app *App) ([]Route, error) {
|
||||
var routes []Route
|
||||
for _, page := range RegisteredPages() {
|
||||
discovered, err := page.Discover(app)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range discovered {
|
||||
discovered[i].page = page
|
||||
}
|
||||
routes = append(routes, discovered...)
|
||||
}
|
||||
return routes, nil
|
||||
}
|
||||
|
||||
func parseTemplates() (*template.Template, error) {
|
||||
paths := make([]string, 0, 16)
|
||||
|
||||
err := fs.WalkDir(templates.FS, ".", func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch strings.ToLower(filepath.Ext(path)) {
|
||||
case ".tmpl", ".html", ".gohtml":
|
||||
paths = append(paths, path)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return template.New("root").ParseFS(templates.FS, paths...)
|
||||
}
|
||||
40
app/pages.go
Normal file
40
app/pages.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package app
|
||||
|
||||
import "sync"
|
||||
|
||||
type Route struct {
|
||||
Path string
|
||||
Kind string
|
||||
ID string
|
||||
page Page
|
||||
}
|
||||
|
||||
type Page interface {
|
||||
Discover(app *App) ([]Route, error)
|
||||
Model(app *App, route Route) (map[string]any, error)
|
||||
Render(app *App, route Route, model map[string]any) ([]byte, error)
|
||||
}
|
||||
|
||||
var (
|
||||
pagesMu sync.RWMutex
|
||||
pages []Page
|
||||
)
|
||||
|
||||
func RegisterPage(page Page) {
|
||||
if page == nil {
|
||||
panic("cannot register nil page")
|
||||
}
|
||||
|
||||
pagesMu.Lock()
|
||||
defer pagesMu.Unlock()
|
||||
pages = append(pages, page)
|
||||
}
|
||||
|
||||
func RegisteredPages() []Page {
|
||||
pagesMu.RLock()
|
||||
defer pagesMu.RUnlock()
|
||||
|
||||
ret := make([]Page, len(pages))
|
||||
copy(ret, pages)
|
||||
return ret
|
||||
}
|
||||
Reference in New Issue
Block a user