package main import ( "bytes" "context" "crypto/rand" "fmt" "io" "log" "math/big" "net/http" "net/url" "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" pathAdmin = "/admin" ) 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 pageAdmin() h.Term { return h.Text("check the log") } const keyEventID = "event_id" const keyAdminCode = "admin_code" func pageDoCreate(name string, earliest, latest time.Time) h.Term { event, err := store.CreateEvent(context.Background(), henwen.CreateEventCommand{ Name: name, EarliestDate: earliest, LatestDate: latest, Duration: 1, }) if err != nil { return h.Text(err.Error()) } var adminQuery = make(url.Values) adminQuery.Add(keyEventID, event.AlphaID) adminQuery.Add(keyAdminCode, event.AdminCode) adminURL := baseURL + pathAdmin + "?" + adminQuery.Encode() 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() { var err error store, err = henwen.NewStore(dbFileName, genString) if err != nil { log.Fatal(err) } 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)) }) mux.HandleFunc(pathAdmin, func(w http.ResponseWriter, r *http.Request) { query := r.URL.Query() err := store.GetEvent(context.Background(), henwen.GetEventQuery{ AlphaID: query.Get(keyEventID), AdminCode: query.Get(keyAdminCode), }) if err != nil { fmt.Fprint(w, err.Error()) return } _ = writePage(w, pageAdmin()) }) srv := http.Server{ Addr: Addr, Handler: mux, } log.Println(srv.ListenAndServe()) }