diff --git a/handler-details.go b/handler-details.go index 7a097835c5ee64022515af055cf652361bebb58d..023380a9dd745c0532e39596e1d49046d19f3081 100644 --- a/handler-details.go +++ b/handler-details.go @@ -112,8 +112,9 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) { return } - rating, err := strconv.Atoi(r.FormValue("rating")) - if err != nil { + rawRating := r.FormValue("rating") + rating, err := strconv.Atoi(rawRating) + if rawRating != "" && err != nil { httpError(w, r, "can't parse rating", nil, http.StatusBadRequest) return } @@ -169,7 +170,7 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) { Name: name, Rating: sql.NullInt32{ Int32: int32(rating), - Valid: true, + Valid: rawRating != "", }, Country: sql.NullString{ String: country.String(), @@ -177,6 +178,8 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) { }, } + level.Debug(log.Get(r)).Log("update", fmt.Sprint(params)) + err = q.UpdateWine(r.Context(), params) if err != nil { httpError(w, r, "can't store update", err, http.StatusInternalServerError) @@ -199,8 +202,9 @@ func (h Handler) details() http.Handler { ) type templateData struct { - Wine query.LoadWineRow - User auth.User + Wine query.LoadWineRow + Comments []query.Comment + User auth.User } return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -232,9 +236,16 @@ func (h Handler) details() http.Handler { return } + comments, err := h.Q.ListComments(r.Context(), int32(id)) + if err != nil { + httpError(w, r, "can't load comments", err, http.StatusInternalServerError) + return + } + data := templateData{ - Wine: v, - User: auth.Get(r), + Wine: v, + Comments: comments, + User: auth.Get(r), } err = tpl.ExecuteTemplate(w, "details.tpl", data) diff --git a/handler-index.go b/handler-index.go index 9db654dd0233e1d9b2ee075daa206037fef71c5f..f7d5021c4b93c270af725a28e881e6811b760a96 100644 --- a/handler-index.go +++ b/handler-index.go @@ -3,7 +3,6 @@ package main import ( "database/sql" "errors" - "fmt" "html/template" "net/http" "strconv" @@ -71,7 +70,7 @@ func (h Handler) index() http.Handler { ratingVal := r.FormValue("rating") var ( - id int + id int64 rating int err error ) @@ -107,7 +106,14 @@ func (h Handler) index() http.Handler { return err } - level.Error(log.Get(r)).Log("msg", "got result", "res", fmt.Sprintf("%#v", res)) + id, err = res.LastInsertId() + if err != nil { + httpError(w, r, "can't store wine", err, http.StatusInternalServerError) + + return err + } + + level.Debug(log.Get(r)).Log("msg", "inserted new wine", "id", id) // See if there's an image file uploaded and persist it if that's the case. if r.MultipartForm == nil || len(r.MultipartForm.File["picture"]) == 0 { @@ -121,7 +127,7 @@ func (h Handler) index() http.Handler { } defer picFile.Close() - err = storage.AddPicture(r.Context(), q, id, picFile, picHdr.Header.Get("Content-Type")) + err = storage.AddPicture(r.Context(), q, int(id), picFile, picHdr.Header.Get("Content-Type")) if err != nil { httpError(w, r, "can't load picture", err, http.StatusBadRequest) return err @@ -133,6 +139,6 @@ func (h Handler) index() http.Handler { return } - http.Redirect(w, r, "/details?id="+strconv.Itoa(id), http.StatusSeeOther) // TODO: Is this the correct status? + http.Redirect(w, r, "/details?id="+strconv.Itoa(int(id)), http.StatusSeeOther) // TODO: Is this the correct status? }) } diff --git a/storage/query/query.sql b/storage/query/query.sql index e533a2780b2f2abd38792390b95275ee45f22ba4..9258a34dd4ed73485005e415ce40c69091759731 100644 --- a/storage/query/query.sql +++ b/storage/query/query.sql @@ -89,4 +89,7 @@ delete from wines where wine_id = @wine_id; insert into comments (wine_id, content) values (@wine_id, @comment); -- name: DeleteComment :exec -delete from comments where comment_id = @comment_id; \ No newline at end of file +delete from comments where comment_id = @comment_id; + +-- name: ListComments :many +select * from comments where wine_id = @wine_id; \ No newline at end of file diff --git a/storage/query/query.sql.go b/storage/query/query.sql.go index b044c2127189820a66b9361c8d7a57541839b42a..349c20fdf2bf45d9339d91cd1b0e3441f9ff1f24 100644 --- a/storage/query/query.sql.go +++ b/storage/query/query.sql.go @@ -196,6 +196,33 @@ func (q *Queries) IsValidSession(ctx context.Context, token string) (string, err return name, err } +const listComments = `-- name: ListComments :many +select comment_id, wine_id, content from comments where wine_id = $1 +` + +func (q *Queries) ListComments(ctx context.Context, wineID int32) ([]Comment, error) { + rows, err := q.db.QueryContext(ctx, listComments, wineID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Comment + for rows.Next() { + var i Comment + if err := rows.Scan(&i.CommentID, &i.WineID, &i.Content); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const listSessions = `-- name: ListSessions :many select users.name as name, sessions.created as created, sessions.remote as remote from users diff --git a/templates/details.tpl b/templates/details.tpl index 8e06ca6f6576e0db69c405cded7cb9eba32fbfc1..d9ebcb53eb6407f7e43ea33099c7fb414457c2c5 100644 --- a/templates/details.tpl +++ b/templates/details.tpl @@ -12,7 +12,7 @@ <div class="content withfooter details pure-u-1"> <div class="maxwidth box"> - <input type="hidden" name="id" value="{{ .Wine.ID }}"> + <input type="hidden" name="id" value="{{ .Wine.WineID }}"> <fieldset> <div class="pure-control-group"> @@ -27,9 +27,9 @@ <div class="pure-control-group"> <label for="form-rating">Rating</label> {{ if .User.CanWrite }} - <input id="form-rating" type="number" name="rating" value="{{ .Wine.Rating }}" placeholder="Rating"> + <input id="form-rating" type="number" name="rating" value="{{ .Wine.Rating.Int32 }}" placeholder="Rating"> {{ else }} - <span id="form-rating">{{ .Wine.Rating }}</span> + <span id="form-rating">{{ .Wine.Rating.Int32 }}</span> {{ end }} </div> @@ -38,14 +38,14 @@ Country (<a href="https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes#Current_ISO_3166_country_codes" target="_blank">ISO 3166 Alpha-2</a>) </label> {{ if .User.CanWrite }} - <input id="form-country" type="text" name="country" value="{{ .Wine.Country }}" placeholder="XXX" pattern="[A-Z]{2}"> + <input id="form-country" type="text" name="country" value="{{ .Wine.Country.String }}" placeholder="XX" pattern="[A-Z]{2}"> {{ else }} - <span id="form-country">{{ .Wine.Country }}</span> + <span id="form-country">{{ .Wine.Country.String }}</span> {{ end }} - {{ if ne .Wine.Country.String "XX" }} - <img src="/static/flags/{{ .Wine.Country }}.png" - alt="Country flag of {{ .Wine.Country }}"> + {{ if .Wine.Country.Valid }} + <img src="/static/flags/{{ .Wine.Country.String }}.png" + alt="Country flag of {{ .Wine.Country.String }}"> {{ end }} </div> @@ -63,16 +63,16 @@ {{ end }} </fieldset> - {{ if .Wine.Comments }} + {{ if .Comments }} <details open> <summary>Comments</summary> <ul> - {{ range .Wine.Comments }} + {{ range .Comments }} <li class="comment"> {{ if $.User.CanWrite }} <button type="submit" name="action" - value="delete-comment-{{ .ID }}" + value="delete-comment-{{ .CommentID }}" class="pure-button button-warning small"> <i class="fas fa-trash-alt"></i> </button> @@ -85,7 +85,7 @@ {{ end }} {{ if .Wine.HasPicture }} - <img class="foto pure-img" src="/details/img/{{ .Wine.ID }}" + <img class="foto pure-img" src="/details/img/{{ .Wine.WineID }}" alt="A photograph of a bottle of wine labelled '{{ .Wine.Name }}'"/> {{ end }} </div>