From cf950db8251483d7143f34e4decbffa3ad3ae88a Mon Sep 17 00:00:00 2001 From: soup Date: Fri, 15 Nov 2024 16:47:25 -0500 Subject: [PATCH] Big refactor --- Makefile | 4 +-- bin/shelves.go | 32 ----------------- embeds.go | 28 +++++++++++++++ frontend.go | 11 ------ go.mod | 2 +- {auth => internal/auth}/auth.go | 0 {db => internal/db}/db.go | 0 {errorsx => internal/errorsx}/errorsx.go | 0 {forms => internal/forms}/forms.go | 0 {httpx => internal/httpx}/httpx.go | 4 +-- {httpx => internal/httpx}/hx.go | 0 {httpx => internal/httpx}/middleware.go | 2 +- internal/routes/home.go | 26 ++++++++++++++ {routes => internal/routes}/login.go | 35 +++++++++++-------- {routes => internal/routes}/routes.go | 5 ++- {routes => internal/routes}/settings.go | 25 ++++++------- internal/templates/components/component.go | 1 + .../templates/components}/form.go | 7 ++-- internal/templates/components/form.tmpl.html | 5 +++ internal/templates/components/page.go | 23 ++++++++++++ .../templates/components}/page.tmpl.html | 0 internal/templates/templates.go | 22 ++++++++++++ .../templates}/tmpls/form.tmpl.html | 0 internal/templates/views/home.go | 1 + internal/templates/views/home.tmpl.html | 15 ++++++++ internal/templates/views/login.tmpl.html | 6 ++++ {urls => internal/urls}/urls.go | 0 routes/home.go | 20 ----------- templates/page.go | 32 ----------------- templates/templates.go | 28 --------------- templates/tmpls/home.tmpl.html | 3 -- templates/tmpls/page_base.tmpl.html | 0 32 files changed, 174 insertions(+), 163 deletions(-) delete mode 100644 bin/shelves.go create mode 100644 embeds.go delete mode 100644 frontend.go rename {auth => internal/auth}/auth.go (100%) rename {db => internal/db}/db.go (100%) rename {errorsx => internal/errorsx}/errorsx.go (100%) rename {forms => internal/forms}/forms.go (100%) rename {httpx => internal/httpx}/httpx.go (90%) rename {httpx => internal/httpx}/hx.go (100%) rename {httpx => internal/httpx}/middleware.go (97%) create mode 100644 internal/routes/home.go rename {routes => internal/routes}/login.go (79%) rename {routes => internal/routes}/routes.go (95%) rename {routes => internal/routes}/settings.go (87%) create mode 100644 internal/templates/components/component.go rename {templates => internal/templates/components}/form.go (73%) create mode 100644 internal/templates/components/form.tmpl.html create mode 100644 internal/templates/components/page.go rename {templates/tmpls => internal/templates/components}/page.tmpl.html (100%) create mode 100644 internal/templates/templates.go rename {templates => internal/templates}/tmpls/form.tmpl.html (100%) create mode 100644 internal/templates/views/home.go create mode 100644 internal/templates/views/home.tmpl.html create mode 100644 internal/templates/views/login.tmpl.html rename {urls => internal/urls}/urls.go (100%) delete mode 100644 routes/home.go delete mode 100644 templates/page.go delete mode 100644 templates/templates.go delete mode 100644 templates/tmpls/home.tmpl.html delete mode 100644 templates/tmpls/page_base.tmpl.html diff --git a/Makefile b/Makefile index 1e92b18..e067824 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ .PHONY: build build: - go build bin/shelves.go + go build cmd/shelves/main.go run: - go run bin/shelves.go + go run cmd/shelves/main.go watch: fd | entr -cr make run diff --git a/bin/shelves.go b/bin/shelves.go deleted file mode 100644 index 3ec7a14..0000000 --- a/bin/shelves.go +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import ( - "fmt" - "log" - "net/http" - - _ "github.com/mattn/go-sqlite3" - - "shelves/db" - "shelves/httpx" - "shelves/routes" -) - -func main() { - db, migrateResult, err := db.Open("./shelves.db") - if err != nil { - log.Fatalf("Failed to open DB: %v", err) - } - if migrateResult.MigrationError != nil { - log.Printf("An error was encountered while upgrading the database schema. You are on version %v, but the latest is %v. The error was: %v", migrateResult.SchemaVerNew, migrateResult.SchemaVerLatest, migrateResult.MigrationError) - } - schemaNeedsUpdating := migrateResult.SchemaVerNew != migrateResult.SchemaVerLatest - if schemaNeedsUpdating { - log.Printf("Your database schema needs to be updated. The application will continue to run, but you may encounter errors.\n") - } - _ = db - - routes := routes.Routes() - fmt.Println("Listening on localhost:8999") - http.ListenAndServe("localhost:8999", httpx.Log(httpx.WithCtx(db, routes))) -} diff --git a/embeds.go b/embeds.go new file mode 100644 index 0000000..4dff149 --- /dev/null +++ b/embeds.go @@ -0,0 +1,28 @@ +package shelves + +import ( + "embed" + "fmt" + "io/fs" +) + +//go:embed frontend/* +var fe embed.FS + +var Frontend, _ = fs.Sub(fe, "frontend") + +//go:embed internal/templates/views/*.tmpl.* internal/templates/components/*.tmpl.* +var templates embed.FS +var Templates, _ = fs.Sub(templates, "internal/templates") + +func printEmbeddedFiles(efs fs.FS) error { + return fs.WalkDir(efs, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if !d.IsDir() { + fmt.Println(path) + } + return nil + }) +} diff --git a/frontend.go b/frontend.go deleted file mode 100644 index 2f7c500..0000000 --- a/frontend.go +++ /dev/null @@ -1,11 +0,0 @@ -package shelves - -import ( - "embed" - "io/fs" -) - -//go:embed frontend/* -var fe embed.FS - -var Frontend, _ = fs.Sub(fe, "frontend") diff --git a/go.mod b/go.mod index fba7ffa..1a400b7 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module shelves +module git.soup.land/soup/shelves go 1.23 diff --git a/auth/auth.go b/internal/auth/auth.go similarity index 100% rename from auth/auth.go rename to internal/auth/auth.go diff --git a/db/db.go b/internal/db/db.go similarity index 100% rename from db/db.go rename to internal/db/db.go diff --git a/errorsx/errorsx.go b/internal/errorsx/errorsx.go similarity index 100% rename from errorsx/errorsx.go rename to internal/errorsx/errorsx.go diff --git a/forms/forms.go b/internal/forms/forms.go similarity index 100% rename from forms/forms.go rename to internal/forms/forms.go diff --git a/httpx/httpx.go b/internal/httpx/httpx.go similarity index 90% rename from httpx/httpx.go rename to internal/httpx/httpx.go index e275cd2..a829a65 100644 --- a/httpx/httpx.go +++ b/internal/httpx/httpx.go @@ -1,11 +1,11 @@ package httpx import ( + "git.soup.land/soup/shelves/internal/errorsx" + "git.soup.land/soup/shelves/internal/urls" "log" "net/http" "net/url" - "shelves/errorsx" - "shelves/urls" ) func SeeOther(w http.ResponseWriter, location string) { diff --git a/httpx/hx.go b/internal/httpx/hx.go similarity index 100% rename from httpx/hx.go rename to internal/httpx/hx.go diff --git a/httpx/middleware.go b/internal/httpx/middleware.go similarity index 97% rename from httpx/middleware.go rename to internal/httpx/middleware.go index 1fe7b63..7e6ae34 100644 --- a/httpx/middleware.go +++ b/internal/httpx/middleware.go @@ -3,9 +3,9 @@ package httpx import ( "context" "database/sql" + "git.soup.land/soup/shelves/internal/auth" "log" "net/http" - "shelves/auth" "time" ) diff --git a/internal/routes/home.go b/internal/routes/home.go new file mode 100644 index 0000000..3c5d652 --- /dev/null +++ b/internal/routes/home.go @@ -0,0 +1,26 @@ +package routes + +import ( + "net/http" + + "git.soup.land/soup/shelves/internal/httpx" + "git.soup.land/soup/shelves/internal/templates" + "git.soup.land/soup/shelves/internal/templates/components" +) + +type homeTemplate struct { + components.Page +} + +var homeTmpl = templates.MustParseEmbed("views/home.tmpl.html") + +func HomeGet(w http.ResponseWriter, req *http.Request) { + ctx := httpx.GetCtx(req) + + h := components.Page{ + Title: "Home", + SessionInfo: ctx.SessionInfo, + }.HTML() + + html(w, h) +} diff --git a/routes/login.go b/internal/routes/login.go similarity index 79% rename from routes/login.go rename to internal/routes/login.go index 32ab6d8..f762736 100644 --- a/routes/login.go +++ b/internal/routes/login.go @@ -5,11 +5,12 @@ import ( "html/template" "net/http" "net/url" - "shelves/auth" - "shelves/errorsx" - "shelves/forms" - "shelves/httpx" - "shelves/templates" + + "git.soup.land/soup/shelves/internal/auth" + "git.soup.land/soup/shelves/internal/errorsx" + "git.soup.land/soup/shelves/internal/forms" + "git.soup.land/soup/shelves/internal/httpx" + "git.soup.land/soup/shelves/internal/templates/components" ) type loginForm struct { @@ -21,26 +22,32 @@ type loginFormErrors struct { password error } -func loginRenderView(f loginForm, e loginFormErrors) template.HTML { - body := templates.Form{ +func loginRenderView(f loginForm, e loginFormErrors, ctx httpx.Ctx) template.HTML { + formHtml := components.Form{ Action: "/login", - Fields: []templates.Field{ - templates.Field{ + Fields: []components.Field{ + components.Field{ Label: "Password", Type: "password", Placeholder: "Password", Name: "password", Error: errorsx.String(e.password), }, - templates.Field{ + components.Field{ Type: "hidden", Name: "redirectTo", Value: f.redirectTo, }, }, + }.HTML() + + page := components.Page{ + Title: "Login", + SessionInfo: ctx.SessionInfo, + Body: formHtml, } - return templates.Page{Title: "Login", Body: body.HTML()}.HTML() + return page.HTML() } func getRedirectTo(r *http.Request) string { @@ -66,7 +73,7 @@ func LoginGet(w http.ResponseWriter, r *http.Request) { return } - html(w, loginRenderView(loginForm{redirectTo: redirectTo}, loginFormErrors{})) + html(w, loginRenderView(loginForm{redirectTo: redirectTo}, loginFormErrors{}, ctx)) } func loginParseForm(f *loginForm, e *loginFormErrors, vs url.Values, v *forms.Validator) { @@ -84,7 +91,7 @@ func LoginPost(w http.ResponseWriter, r *http.Request) { }) if failed { httpx.BadRequest(w) - html(w, loginRenderView(form, errs)) + html(w, loginRenderView(form, errs, ctx)) return } @@ -102,7 +109,7 @@ func LoginPost(w http.ResponseWriter, r *http.Request) { httpx.BadRequest(w) errs.password = errors.New("Incorrect password") - html(w, loginRenderView(form, errs)) + html(w, loginRenderView(form, errs, ctx)) return } diff --git a/routes/routes.go b/internal/routes/routes.go similarity index 95% rename from routes/routes.go rename to internal/routes/routes.go index c824b6e..41cc9fd 100644 --- a/routes/routes.go +++ b/internal/routes/routes.go @@ -1,13 +1,12 @@ package routes import ( + "git.soup.land/soup/shelves" + "git.soup.land/soup/shelves/internal/httpx" "html/template" "net/http" - "shelves/httpx" "strings" "time" - - "shelves" ) func html(w http.ResponseWriter, s template.HTML) { diff --git a/routes/settings.go b/internal/routes/settings.go similarity index 87% rename from routes/settings.go rename to internal/routes/settings.go index a53f3a7..cf2c1e1 100644 --- a/routes/settings.go +++ b/internal/routes/settings.go @@ -6,41 +6,42 @@ import ( "html/template" "net/http" "net/url" - "shelves/auth" - "shelves/errorsx" - "shelves/forms" - "shelves/httpx" - "shelves/templates" + + "git.soup.land/soup/shelves/internal/auth" + "git.soup.land/soup/shelves/internal/errorsx" + "git.soup.land/soup/shelves/internal/forms" + "git.soup.land/soup/shelves/internal/httpx" + "git.soup.land/soup/shelves/internal/templates/components" ) func settingsRenderView(f settingsForm, e settingsFormErrors) template.HTML { - body := templates.Form{ + body := components.Form{ Action: "/settings", - Fields: []templates.Field{ - templates.Field{ + Fields: []components.Field{ + components.Field{ Label: "Display name", Name: "displayName", Placeholder: "Jane Doe", Value: f.displayName, Error: errorsx.String(e.displayName), }, - templates.Field{ + components.Field{ Label: "Password", Type: "password", Placeholder: "Password", Name: "password", Error: errorsx.String(e.password), }, - templates.Field{ + components.Field{ Label: "Confirm password", Placeholder: "Confirm Password", Type: "password", Name: "passwordConfirmation", }, }, - } + }.HTML() - return templates.PageBase{Title: "Set up", Body: body.HTML()}.HTML() + return components.Page{Title: "Set up", Body: body}.HTML() } func queryGetOwnerSettings(db *sql.DB) (settingsForm, error) { diff --git a/internal/templates/components/component.go b/internal/templates/components/component.go new file mode 100644 index 0000000..bc820f5 --- /dev/null +++ b/internal/templates/components/component.go @@ -0,0 +1 @@ +package components diff --git a/templates/form.go b/internal/templates/components/form.go similarity index 73% rename from templates/form.go rename to internal/templates/components/form.go index 34c47ed..41b9a7b 100644 --- a/templates/form.go +++ b/internal/templates/components/form.go @@ -1,6 +1,7 @@ -package templates +package components import ( + "git.soup.land/soup/shelves/internal/templates" "html/template" ) @@ -28,6 +29,8 @@ type Form struct { Fields []Field } +var formTmpl = templates.MustParseEmbed("components/form.tmpl.html") + func (f Form) HTML() template.HTML { if f.Method == "" { f.Method = "POST" @@ -37,5 +40,5 @@ func (f Form) HTML() template.HTML { f.Fields[i].init() } - return Tmpls.HTML("form.tmpl.html", f) + return templates.HTML(formTmpl, "form", f) } diff --git a/internal/templates/components/form.tmpl.html b/internal/templates/components/form.tmpl.html new file mode 100644 index 0000000..2576d30 --- /dev/null +++ b/internal/templates/components/form.tmpl.html @@ -0,0 +1,5 @@ +{{define "field"}} +{{end}} + +{{define "form"}} +{{end}} diff --git a/internal/templates/components/page.go b/internal/templates/components/page.go new file mode 100644 index 0000000..423152c --- /dev/null +++ b/internal/templates/components/page.go @@ -0,0 +1,23 @@ +package components + +import ( + "git.soup.land/soup/shelves/internal/auth" + "git.soup.land/soup/shelves/internal/templates" + "html/template" +) + +type Page struct { + SessionInfo auth.SessionInfo + + Title string + Head template.HTML + Body template.HTML + BodyBefore template.HTML + BodyAfter template.HTML +} + +var pageTmpl = templates.MustParseEmbed("components/page.tmpl.html") + +func (p Page) HTML() template.HTML { + return templates.HTML(pageTmpl, "page", p) +} diff --git a/templates/tmpls/page.tmpl.html b/internal/templates/components/page.tmpl.html similarity index 100% rename from templates/tmpls/page.tmpl.html rename to internal/templates/components/page.tmpl.html diff --git a/internal/templates/templates.go b/internal/templates/templates.go new file mode 100644 index 0000000..a74b8a8 --- /dev/null +++ b/internal/templates/templates.go @@ -0,0 +1,22 @@ +package templates + +import ( + "git.soup.land/soup/shelves" + "git.soup.land/soup/shelves/internal/errorsx" + "html/template" + "strings" +) + +var files = shelves.Templates + +func MustParseEmbed(path string) *template.Template { + return template.Must(template.ParseFS(files, path)) +} + +func HTML(t *template.Template, name string, data any) template.HTML { + out := strings.Builder{} + err := t.ExecuteTemplate(&out, name, data) + out.WriteString(errorsx.String(err)) + + return template.HTML(out.String()) +} diff --git a/templates/tmpls/form.tmpl.html b/internal/templates/tmpls/form.tmpl.html similarity index 100% rename from templates/tmpls/form.tmpl.html rename to internal/templates/tmpls/form.tmpl.html diff --git a/internal/templates/views/home.go b/internal/templates/views/home.go new file mode 100644 index 0000000..e29e57d --- /dev/null +++ b/internal/templates/views/home.go @@ -0,0 +1 @@ +package views diff --git a/internal/templates/views/home.tmpl.html b/internal/templates/views/home.tmpl.html new file mode 100644 index 0000000..3bf6544 --- /dev/null +++ b/internal/templates/views/home.tmpl.html @@ -0,0 +1,15 @@ +{{define "Title"}}Home{{end}} + +{{define "Body"}} +
+

Featured Shelves

+
+
+

Featured Items

+
+
+

Recent Activity

+
+{{end}} + +{{template "page.tmpl.html" .}} diff --git a/internal/templates/views/login.tmpl.html b/internal/templates/views/login.tmpl.html new file mode 100644 index 0000000..00a0edd --- /dev/null +++ b/internal/templates/views/login.tmpl.html @@ -0,0 +1,6 @@ +{{template "page.tmpl.html" .}} + +{{define "Title"}}Login{{end}} + +{{define "Body"}} +{{end}} diff --git a/urls/urls.go b/internal/urls/urls.go similarity index 100% rename from urls/urls.go rename to internal/urls/urls.go diff --git a/routes/home.go b/routes/home.go deleted file mode 100644 index 5cd01ac..0000000 --- a/routes/home.go +++ /dev/null @@ -1,20 +0,0 @@ -package routes - -import ( - "net/http" - "shelves/httpx" - "shelves/templates" -) - -type homeTemplate struct { - templates.Page -} - -func HomeGet(w http.ResponseWriter, req *http.Request) { - ctx := httpx.GetCtx(req) - tmpl := homeTemplate{ - Page: templates.Page{SessionInfo: ctx.SessionInfo}, - } - - html(w, templates.Tmpls.HTML("home.tmpl.html", tmpl)) -} diff --git a/templates/page.go b/templates/page.go deleted file mode 100644 index 72a0f05..0000000 --- a/templates/page.go +++ /dev/null @@ -1,32 +0,0 @@ -package templates - -import ( - "html/template" - "shelves/auth" -) - -type PageBase struct { - Title string - Head template.HTML - Body template.HTML - BodyBefore template.HTML - BodyAfter template.HTML -} - -func (pb PageBase) HTML() template.HTML { - return Tmpls.HTML("page_base.tmpl.html", pb) -} - -type Page struct { - SessionInfo auth.SessionInfo - - Title string - Head template.HTML - Body template.HTML - BodyBefore template.HTML - BodyAfter template.HTML -} - -func (p Page) HTML() template.HTML { - return Tmpls.HTML("page.tmpl.html", p) -} diff --git a/templates/templates.go b/templates/templates.go deleted file mode 100644 index c909a69..0000000 --- a/templates/templates.go +++ /dev/null @@ -1,28 +0,0 @@ -package templates - -import ( - "embed" - "fmt" - "html/template" - "strings" -) - -//go:embed tmpls/* -var files embed.FS - -type Template struct { - *template.Template -} - -var Tmpls = Template{template.Must(template.ParseFS(files, "tmpls/*"))} - -func (tmpl Template) HTML(name string, data any) template.HTML { - writer := &strings.Builder{} - err := tmpl.ExecuteTemplate(writer, name, data) - - if err != nil { - fmt.Fprint(writer, err) - } - - return template.HTML(writer.String()) -} diff --git a/templates/tmpls/home.tmpl.html b/templates/tmpls/home.tmpl.html deleted file mode 100644 index 39014e4..0000000 --- a/templates/tmpls/home.tmpl.html +++ /dev/null @@ -1,3 +0,0 @@ -{{define "Title"}}Home{{end}} - -{{template "page.tmpl.html" .}} diff --git a/templates/tmpls/page_base.tmpl.html b/templates/tmpls/page_base.tmpl.html deleted file mode 100644 index e69de29..0000000