account page stubbed: link to etsy sign up
This commit is contained in:
+127
-9
@@ -7,16 +7,61 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/angelbeltran/templater"
|
||||
|
||||
"ruben/inventory2/internal/domains/accounts"
|
||||
etsy_platform "ruben/inventory2/internal/domains/platforms/etsy"
|
||||
"ruben/inventory2/internal/domains/raw_events"
|
||||
)
|
||||
|
||||
func NewSiteHandler(dir string, db *raw_events.Store) http.Handler {
|
||||
func NewSiteHandler(
|
||||
dir string,
|
||||
rawEvents *raw_events.Store,
|
||||
accts *accounts.Store,
|
||||
etsy *etsy_platform.Platform,
|
||||
) http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
// api routes
|
||||
|
||||
mux.HandleFunc("POST /accounts", func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
email := r.FormValue("email")
|
||||
if email == "" {
|
||||
http.Error(w, "no email provided", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
acct, err := accts.CreateAccount(ctx, email)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to create account: %w", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, fmt.Sprintf("/site/accounts/%d", acct.ID), http.StatusSeeOther)
|
||||
})
|
||||
|
||||
mux.HandleFunc("POST /log-in", func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
email := r.FormValue("email")
|
||||
if email == "" {
|
||||
http.Error(w, "no email provided", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
acct, err := accts.GetAccountByEmail(ctx, email)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to create account: %w", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, fmt.Sprintf("/site/accounts/%d", acct.ID), http.StatusSeeOther)
|
||||
})
|
||||
|
||||
// non-html routes
|
||||
|
||||
scfs := http.FileServer(http.Dir(dir + "/scripts"))
|
||||
@@ -44,6 +89,12 @@ func NewSiteHandler(dir string, db *raw_events.Store) http.Handler {
|
||||
// TODO: make "/site" dynamic somehow
|
||||
return path.Join(append([]string{"/site"}, strParts...)...)
|
||||
},
|
||||
"splitPath": func(p string) []string {
|
||||
if p == "" {
|
||||
return nil
|
||||
}
|
||||
return strings.Split(strings.TrimSuffix(strings.TrimPrefix(p, "/"), "/"), "/")
|
||||
},
|
||||
|
||||
"prettyPrintJSON": func(j json.RawMessage) string {
|
||||
b, err := json.MarshalIndent(j, " ", "")
|
||||
@@ -53,6 +104,10 @@ func NewSiteHandler(dir string, db *raw_events.Store) http.Handler {
|
||||
return string(b)
|
||||
},
|
||||
|
||||
"parseInt64": func(s string) (int64, error) {
|
||||
return strconv.ParseInt(s, 10, 64)
|
||||
},
|
||||
|
||||
"addInt": func(a, b int) int {
|
||||
return a + b
|
||||
},
|
||||
@@ -66,15 +121,23 @@ func NewSiteHandler(dir string, db *raw_events.Store) http.Handler {
|
||||
},
|
||||
)
|
||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
name, pathParams := getPageTemplateNameForURL(r.URL)
|
||||
b, err := tmplr.ExecutePage(
|
||||
getPageTemplateNameForURL(r.URL),
|
||||
name,
|
||||
"Request",
|
||||
r,
|
||||
// add services here
|
||||
"RawEvents",
|
||||
db.WithContext(r.Context()),
|
||||
rawEvents.WithContext(ctx),
|
||||
"URLCalc",
|
||||
newURLCalculator(r.URL),
|
||||
"PathParams",
|
||||
pathParams,
|
||||
"Accounts",
|
||||
accts.WithContext(ctx),
|
||||
"Etsy",
|
||||
etsy.WithContext(ctx),
|
||||
)
|
||||
if err != nil {
|
||||
// TODO: handle 'not found' as a 404?
|
||||
@@ -89,14 +152,69 @@ func NewSiteHandler(dir string, db *raw_events.Store) http.Handler {
|
||||
return mux
|
||||
}
|
||||
|
||||
func getPageTemplateNameForURL(u *url.URL) string {
|
||||
filepath := strings.TrimPrefix(strings.TrimSuffix(u.Path, ".html"), "/")
|
||||
if filepath == "" {
|
||||
// "/" maps to "/home"
|
||||
filepath = "home"
|
||||
// TODO: clean this up...
|
||||
// TODO: somehow tell what the path params are and pass them up.
|
||||
// - then consider pushing this functionality into the template library.
|
||||
//
|
||||
// getPageTemplateNameForURL eliminate any trailing .html or /, and checks for any
|
||||
// file with path parameters in the name, eg '{abc}.html.tmpl', prefering exact filename matches.
|
||||
func getPageTemplateNameForURL(u *url.URL) (name string, params map[string]string) {
|
||||
fp := strings.TrimPrefix(strings.TrimSuffix(strings.TrimSuffix(u.Path, ".html"), "/"), "/")
|
||||
if fp == "" {
|
||||
// "/" maps to "/index"
|
||||
fp = "index"
|
||||
}
|
||||
|
||||
return filepath
|
||||
fpParts := strings.Split(fp, "/")
|
||||
res := getMatchingGlobPatternsCapturingFilepathIncludingParametrizedFilepaths(fpParts)
|
||||
for _, combs := range res {
|
||||
const pageBodiesPrefix = "internal/site/templates/page_bodies"
|
||||
pattern := path.Join(pageBodiesPrefix, path.Join(combs...)) + ".html.tmpl"
|
||||
|
||||
matches, _ := filepath.Glob(pattern)
|
||||
if len(matches) == 0 {
|
||||
pattern := path.Join(pageBodiesPrefix, path.Join(combs...), "index") + ".html.tmpl"
|
||||
matches, _ = filepath.Glob(pattern)
|
||||
}
|
||||
if len(matches) > 0 {
|
||||
match := matches[0]
|
||||
name = strings.TrimPrefix(strings.TrimSuffix(match, ".html.tmpl"), pageBodiesPrefix+"/")
|
||||
|
||||
patternParts := strings.Split(name, "/")
|
||||
params = make(map[string]string)
|
||||
for i, pp := range patternParts {
|
||||
if strings.HasPrefix(pp, "{") && strings.HasSuffix(pp, "}") {
|
||||
params[pp[1:len(pp)-1]] = fpParts[i]
|
||||
}
|
||||
}
|
||||
|
||||
return name, params
|
||||
}
|
||||
}
|
||||
|
||||
return fp, nil
|
||||
}
|
||||
|
||||
func getMatchingGlobPatternsCapturingFilepathIncludingParametrizedFilepaths(filepathParts []string) [][]string {
|
||||
switch len(filepathParts) {
|
||||
case 0:
|
||||
return nil
|
||||
case 1:
|
||||
return [][]string{
|
||||
[]string{filepathParts[0]},
|
||||
[]string{"{*}"},
|
||||
}
|
||||
default:
|
||||
tailCombs := getMatchingGlobPatternsCapturingFilepathIncludingParametrizedFilepaths(filepathParts[1:])
|
||||
|
||||
combs := make([][]string, 2*len(tailCombs))
|
||||
for i, c := range tailCombs {
|
||||
combs[i*2] = append([]string{filepathParts[0]}, c...)
|
||||
combs[i*2+1] = append([]string{"{*}"}, c...)
|
||||
}
|
||||
|
||||
return combs
|
||||
}
|
||||
}
|
||||
|
||||
type URLCalculator struct {
|
||||
|
||||
Reference in New Issue
Block a user