hivedav

A curlable free/busy scheduler with CalDAV integration
git clone https://git.in0rdr.ch/hivedav.git
Log | Files | Refs | Pull requests |Archive | README | LICENSE

commit 0380cb2454291d6121d87650ba4a8354c69678d2
parent 27f6020924c3cf57e180dad757c69975dab6efb4
Author: Andreas Gruhler <andreas.gruhler@adfinis.com>
Date:   Thu, 28 Sep 2023 01:11:58 +0200

feat: improve html templates

Diffstat:
Mserver.go | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Mtemplates/index.html | 19+++++++++++++------
Mtemplates/listcubicles.html | 12+++++++++++-
3 files changed, 86 insertions(+), 34 deletions(-)

diff --git a/server.go b/server.go @@ -166,6 +166,11 @@ func (s *Server) available(start string, end string) (bool, error) { return false, nil } +var funcMap = template.FuncMap{ + "next": func(i int) int { return i + 1 }, + "prev": func(i int) int { return i - 1 }, +} + func (s *Server) Week(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { userAgent := req.Header.Get("user-agent") @@ -189,9 +194,13 @@ func (s *Server) Week(w http.ResponseWriter, req *http.Request, ps httprouter.Pa sqlDateFmt := "2006-01-02 15:04" - rows := make([][]string, 9) - for i := range rows { - rows[i] = make([]string, 6) + termRows := make([][]string, 9) + for i := range termRows { + termRows[i] = make([]string, 6) + } + htmlRows := make([][]string, 9) + for i := range htmlRows { + htmlRows[i] = make([]string, 6) } // Define the table header @@ -205,9 +214,17 @@ func (s *Server) Week(w http.ResponseWriter, req *http.Request, ps httprouter.Pa fmt.Sprintf("Fri %s", monday.Add(time.Hour*24*4).Format("02.01.")), } - tableData := TableData{ + termTableData := TableData{ TableHead: tableHead, - Rows: rows, + Rows: termRows, + Week: week, + Year: year, + Version: hivedavVersion, + HiveDavHost: s.config.HiveDavHost, + } + htmlTableData := TableData{ + TableHead: tableHead, + Rows: htmlRows, Week: week, Year: year, Version: hivedavVersion, @@ -223,33 +240,48 @@ func (s *Server) Week(w http.ResponseWriter, req *http.Request, ps httprouter.Pa // Working hours - Eight to Five //for h := 8; h < 17; h++ { for _, h := range []int{8, 9, 10, 11, 12, 13, 14, 15, 16} { - var availability [5]string + var htmlAvailability [5]string + var termAvailability [5]string // Working days - Monday through Friday //for d := 0; d < 5; d++ { for _, d := range []int{1, 2, 3, 4, 5} { // add/remove 1 minute to make the sql time query in available() below behave correctly // convert to read/compare in UTC from db - start := timeIt.Add(time.Hour * time.Duration((d-1)*24+h)).Add(1 * time.Minute).UTC().Format(sqlDateFmt) - end := timeIt.Add(time.Hour * time.Duration((d-1)*24+h+1)).Add(-1 * time.Minute).UTC().Format(sqlDateFmt) + startTime := timeIt.Add(time.Hour * time.Duration((d-1)*24+h)).Add(1 * time.Minute) + start := startTime.UTC().Format(sqlDateFmt) + endTime := timeIt.Add(time.Hour * time.Duration((d-1)*24+h+1)).Add(-1 * time.Minute) + end := endTime.UTC().Format(sqlDateFmt) avi, err := s.available(start, end) if err != nil { log.Printf("Error getting availability on day '%d' hour '%d'\n", d, h) return } if avi { - availability[d-1] = "" + // terminal shows free slots as empty + termAvailability[d-1] = "" + // web UI shows a booking link for free slots + htmlAvailability[d-1] = fmt.Sprintf("%s", startTime.Format("2006-01-02-15")) } else { - availability[d-1] = "X" + termAvailability[d-1] = "X" + htmlAvailability[d-1] = "" } //timeIt = timeIt.Add(time.Hour * 24) } - tableData.Rows[h-8] = []string{ + termTableData.Rows[h-8] = []string{ fmt.Sprintf("%02d:00 - %02d:00", h, h+1), - availability[0], - availability[1], - availability[2], - availability[3], - availability[4], + termAvailability[0], + termAvailability[1], + termAvailability[2], + termAvailability[3], + termAvailability[4], + } + htmlTableData.Rows[h-8] = []string{ + fmt.Sprintf("%02d:00 - %02d:00", h, h+1), + htmlAvailability[0], + htmlAvailability[1], + htmlAvailability[2], + htmlAvailability[3], + htmlAvailability[4], } //timeIt = timeIt.Add(time.Hour) } @@ -259,8 +291,8 @@ func (s *Server) Week(w http.ResponseWriter, req *http.Request, ps httprouter.Pa io.WriteString(w, fmt.Sprintf("Serving week %d of year %d\n", week, year)) io.WriteString(w, fmt.Sprintf("Use 'curl %s/list/%d' to list cubicle booking commands\n", s.config.HiveDavHost, week)) - pt := prettytable.New(tableData.TableHead) - for _, r := range tableData.Rows { + pt := prettytable.New(termTableData.TableHead) + for _, r := range termTableData.Rows { // convert to slice of interface // https://go.dev/doc/faq#convert_slice_of_interface s := make([]interface{}, len(r)) @@ -276,7 +308,7 @@ func (s *Server) Week(w http.ResponseWriter, req *http.Request, ps httprouter.Pa } else { w.Header().Set("Content-Type", "text/html") - tmpl, err := template.ParseFiles("./templates/index.html") + tmpl, err := template.New("index.html").Funcs(funcMap).ParseFiles("./templates/index.html") if err != nil { log.Printf("Error parsing html template: %v\n", err) w.WriteHeader(http.StatusInternalServerError) @@ -284,7 +316,7 @@ func (s *Server) Week(w http.ResponseWriter, req *http.Request, ps httprouter.Pa fmt.Fprintf(w, "Error parsing html template: %v\n", err) return } - err = tmpl.Execute(w, tableData) + err = tmpl.Execute(w, htmlTableData) if err != nil { w.WriteHeader(http.StatusInternalServerError) log.Printf("Error executing html template: %v\n", err) @@ -533,7 +565,7 @@ func (s *Server) ListCubiclesInWeek(w http.ResponseWriter, req *http.Request, ps // Make two columns, for the date/time and the command tableData.Rows = append(tableData.Rows, []string{ fmt.Sprintf("%s - %s", startTime.Format("Mon 02.01. 15:04"), endTime.Format("15:04")), - fmt.Sprintf("curl %s/book/%s -F 'mail=' -F 'msg='", s.config.HiveDavHost, startTime.Format("2006-01-02-15")), + fmt.Sprintf("%s", startTime.Format("2006-01-02-15")), }) } } @@ -548,12 +580,15 @@ func (s *Server) ListCubiclesInWeek(w http.ResponseWriter, req *http.Request, ps for _, r := range tableData.Rows { // convert to slice of interface // https://go.dev/doc/faq#convert_slice_of_interface - s := make([]interface{}, len(r)) - for i, v := range r { - s[i] = v - } + row := make([]interface{}, len(r)) + + // use the date/time column as is + row[0] = r[0] + // create the booking cmd + row[1] = fmt.Sprintf("curl %s/book/%s -F 'mail=' -F 'msg='", s.config.HiveDavHost, r[1]) + // unpack the string array into row arguments - pt.AddRow(s...) + pt.AddRow(row...) } io.WriteString(w, fmt.Sprint(pt)) @@ -561,7 +596,7 @@ func (s *Server) ListCubiclesInWeek(w http.ResponseWriter, req *http.Request, ps } else { w.Header().Set("Content-Type", "text/html") - tmpl, err := template.ParseFiles("./templates/listcubicles.html") + tmpl, err := template.New("listcubicles.html").Funcs(funcMap).ParseFiles("./templates/listcubicles.html") if err != nil { w.WriteHeader(http.StatusInternalServerError) log.Printf("Error parsing html template: %v\n", err) diff --git a/templates/index.html b/templates/index.html @@ -9,8 +9,15 @@ Serving week <i>{{ .Week }}</i> of year <i>{{ .Year }}</i> </p> <p> - This site is curlable, try <code>`curl {{ .HiveDavHost }}`</code> + This site is curlable, try <code>`curl {{ .HiveDavHost }}/week/{{ .Week }}`</code> </p> + <nav> + <ul> + <li><a href="/list/{{ .Week }}">List cubicles</a></li> + <li><a href="/week/{{ prev .Week }}">Prev week</a></li> + <li><a href="/week/{{ next .Week }}">Next week</a></li> + </ul> + </nav> <table> <tr> {{ range $i, $h := .TableHead }} @@ -20,11 +27,11 @@ {{ range $i, $r := .Rows }} <tr> <td>{{ index $r 0 }}</td> - <td>{{ index $r 1 }}</td> - <td>{{ index $r 2 }}</td> - <td>{{ index $r 3 }}</td> - <td>{{ index $r 4 }}</td> - <td>{{ index $r 5 }}</td> + <td>{{with index $r 1}}<a href="/book/{{ index $r 1 }}">book</a>{{else}}X{{end}}</td> + <td>{{with index $r 2}}<a href="/book/{{ index $r 2 }}">book</a>{{else}}X{{end}}</td> + <td>{{with index $r 3}}<a href="/book/{{ index $r 3 }}">book</a>{{else}}X{{end}}</td> + <td>{{with index $r 5}}<a href="/book/{{ index $r 4 }}">book</a>{{else}}X{{end}}</td> + <td>{{with index $r 1}}<a href="/book/{{ index $r 5 }}">book</a>{{else}}X{{end}}</td> </tr> {{ end }} </table> diff --git a/templates/listcubicles.html b/templates/listcubicles.html @@ -8,6 +8,16 @@ <p> Serving week <i>{{ .Week }}</i> of year <i>{{ .Year }}</i> </p> + <p> + This site is curlable, try <code>`curl {{ .HiveDavHost }}/list/{{ .Week }}`</code> + </p> + <nav> + <ul> + <li><a href="/week/{{ .Week }}">Show calendar</a></li> + <li><a href="/list/{{ prev .Week }}">Prev week</a></li> + <li><a href="/list/{{ next .Week }}">Next week</a></li> + </ul> + </nav> <table> <tr> {{ range $i, $h := .TableHead }} @@ -17,7 +27,7 @@ {{ range $i, $r := .Rows }} <tr> <td>{{ index $r 0 }}</td> - <td>{{ index $r 1 }}</td> + <td><a href="/book/{{ index $r 1 }}">book </a></td> </tr> {{ end }} </table>