package main import ( "bytes" "crypto/rand" "fmt" "io" "log" "math/big" "net/http" "time" h "gitlab.codemonkeysoftware.net/b/hatmill" a "gitlab.codemonkeysoftware.net/b/hatmill/attribute" e "gitlab.codemonkeysoftware.net/b/hatmill/element" "gitlab.codemonkeysoftware.net/b/henwen" _ "gitlab.codemonkeysoftware.net/b/henwen" ) const Addr = ":8080" const Title = "Henwen" const baseURL = "http://localhost:8080" const dbFileName = "./henwen.db" const ( PathRoot = "/" PathCreate = "/create" PathDoCreate = "/create/do" ) var store *henwen.Store func writePage(w io.Writer, contents h.Term) error { page := e.Html()( e.Head()( e.Title()(h.Text(Title)), ), e.Body()( e.H1()(h.Text(Title)), e.Div()(contents), ), ) _, err := h.WriteDocument(w, page) return err } func pageRoot() h.Term { return h.Terms{ e.H2()(h.Text("Welcome!")), e.A(a.Href(PathCreate))( h.Text("Create event"), ), } } const ( fieldNameEarliest = "earliestDate" fieldNameLatest = "latestDate" fieldNameEventName = "eventName" ) func pageCreate() h.Term { return h.Terms{ e.H2()(h.Text("Create an event")), e.Form(a.Action(PathDoCreate), a.Method("POST"))( e.Label(a.For(fieldNameEventName))(h.Text("Event name")), e.Input(a.Name(fieldNameEventName)), e.Label(a.For(fieldNameEarliest))(h.Text("Earliest date")), e.Input(a.Name(fieldNameEarliest), a.Type("date")), e.Label(a.For(fieldNameLatest))(h.Text("Latest date")), e.Input(a.Name(fieldNameLatest), a.Type("date")), e.Input(a.Type("submit")), ), } } func makeAdminURL(eventID, adminCode string) string { return fmt.Sprintf("%s/%s/admin/%s", baseURL, eventID, adminCode) } func pageDoCreate(name string, earliest, latest time.Time) h.Term { id, err := genString() if err != nil { return h.Text(err.Error()) } adminCode, err := genString() if err != nil { return h.Text(err.Error()) } adminURL := makeAdminURL(id, adminCode) return h.Terms{ e.H2()(h.Text("Created event!")), e.P()( h.Text("You can find it again at "), e.A(a.Href(adminURL))(h.Text(adminURL)), h.Text("."), ), e.H3()(h.Text("Name")), h.Text(name), e.H3()(h.Text("Earliest date")), h.Text(earliest.Format(time.ANSIC)), e.H3()(h.Text("Latest date")), h.Text(latest.Format(time.ANSIC)), } } var chars = []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") func genString() (string, error) { const length = 10 charsLength := big.NewInt(int64(len(chars))) var maxN big.Int maxN.Exp(charsLength, big.NewInt(length), nil) n, err := rand.Int(rand.Reader, &maxN) if err != nil { return "", err } var buf bytes.Buffer for n.Cmp(&big.Int{}) == 1 { var charIdx big.Int n.DivMod(n, charsLength, &charIdx) _ = buf.WriteByte(chars[charIdx.Int64()]) } return buf.String(), nil } func main() { mux := http.NewServeMux() mux.HandleFunc(PathRoot, func(w http.ResponseWriter, r *http.Request) { _ = writePage(w, pageRoot()) }) mux.HandleFunc(PathCreate, func(w http.ResponseWriter, r *http.Request) { _ = writePage(w, pageCreate()) }) mux.HandleFunc(PathDoCreate, func(w http.ResponseWriter, r *http.Request) { const dateFmt = "2006-01-02" earliest, err := time.Parse(dateFmt, r.FormValue(fieldNameEarliest)) if err != nil { fmt.Fprint(w, "bad earliest date") return } latest, err := time.Parse(dateFmt, r.FormValue(fieldNameLatest)) if err != nil { fmt.Fprint(w, "bad latest date") return } eventName := r.FormValue(fieldNameEventName) if eventName == "" { fmt.Fprint(w, "event name is required") return } _ = writePage(w, pageDoCreate(eventName, earliest, latest)) }) srv := http.Server{ Addr: Addr, Handler: mux, } log.Println(srv.ListenAndServe()) }