Skip to content
Snippets Groups Projects
Commit b2db89fc authored by gbe's avatar gbe
Browse files

Add comments

parent 3d8d3f61
No related branches found
No related tags found
No related merge requests found
......@@ -9,6 +9,7 @@ import (
"log"
"net/http"
"strconv"
"strings"
)
var detailsTemplate = template.Must(template.ParseFS(templateFS, "templates/base.tpl", "templates/details.tpl"))
......@@ -102,6 +103,19 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) {
v.Name = name
v.Rating = rating
comment := strings.TrimSpace(r.FormValue("comment"))
if comment != "" {
if len(comment) > 1024 {
comment = comment[:1024] + "..."
}
err = v.StoreComment(r.Context(), h.db, comment)
if err != nil {
httpError(w, "can't add comment", err, http.StatusInternalServerError)
return
}
}
err = r.ParseMultipartForm(16 * 1024 * 1024)
if err != nil {
httpError(w, "can't parse multipart form data", err, http.StatusInternalServerError)
......
CREATE TABLE comments (
content TEXT,
wine INTEGER,
FOREIGN KEY (wine) REFERENCES wines(rowid)
);
\ No newline at end of file
......@@ -35,14 +35,27 @@
<input id="form-new-picture" type="file" name="picture" accept="image/png, image/jpeg">
<!-- TODO: add a button to remove the image -->
</div>
<div class="pure-control-group">
<label for="form-new-comment">Add comment</label>
<textarea id="form-new-comment" name="comment" placeholder="Etaoin Shrdlu">
</textarea>
</div>
</fieldset>
<details>
Etaoin Shrdlu, here be metadata
{{ if .Wine.Comments }}
<details open>
<summary>Comments</summary>
<ul>
{{ range .Wine.Comments }}
<li>{{ .Content }}</li>
{{ end }}
</ul>
</details>
{{ end }}
{{ if .Wine.HasPicture }}
<p>And here's a picture:<br/>
<p>Here's a picture:<br/>
<img class="foto pure-img" src="/details/img?id={{ .Wine.ID }}"/>
{{ end }}
......
......@@ -26,12 +26,17 @@ const (
Update
)
type Comment struct {
Content string `db:"content"`
}
type Vino struct {
ID int `db:"rowid"`
Name string `db:"name"`
Rating int `db:"rating"`
Picture image.Image `db:"-"`
HasPicture bool `db:"has_picture"` // Set to true if there's picture data for this vino
Comments []Comment `db:"-"`
}
func DeleteVino(ctx context.Context, db *sqlx.DB, id int) error {
......@@ -51,7 +56,10 @@ func DeleteVino(ctx context.Context, db *sqlx.DB, id int) error {
}
func LoadVino(ctx context.Context, db *sqlx.DB, id int) (Vino, error) {
cols := []string{"rowid", "name", "rating", "case when picture is not null then true else false end as has_picture"}
cols := []string{
"rowid", "name", "rating",
"CASE WHEN picture IS NOT NULL THEN true ELSE false END AS has_picture",
}
query, args, err := squirrel.Select(cols...).
From("wines").
......@@ -61,8 +69,28 @@ func LoadVino(ctx context.Context, db *sqlx.DB, id int) (Vino, error) {
return Vino{}, err
}
tx, err := db.Beginx()
if err != nil {
return Vino{}, err
}
defer tx.Rollback() // The tx is readonly anyway, no need to commit anything
var v Vino
err = db.GetContext(ctx, &v, query, args...)
err = tx.GetContext(ctx, &v, query, args...)
if err != nil {
return v, err
}
query, args, err = squirrel.Select("content").
From("comments").
Where(squirrel.Eq{"wine": id}).
OrderBy("rowid ASC").
ToSql()
if err != nil {
return v, err
}
err = tx.SelectContext(ctx, &v.Comments, query, args...)
if err != nil {
return v, err
}
......@@ -85,7 +113,7 @@ func LoadPictureData(ctx context.Context, db *sqlx.DB, id int) ([]byte, error) {
// AddPicture loads picture data (PNG or JPEG) from fh and sets v's picture to it.
// If something goes wrong during loading, or the image is neither PNG nor JPEG, an error
// is returned. If contentType is not the empty string, it is validated to be either
// image/png or image/jpeg
// image/png or image/jpeg.
func (v *Vino) AddPicture(fh io.Reader, contentType string) error {
switch contentType {
case "", "image/jpeg", "image/png":
......@@ -196,6 +224,17 @@ func (v *Vino) Store(ctx context.Context, db *sqlx.DB, op storeOperation) (err e
return nil
}
func (v *Vino) StoreComment(ctx context.Context, db *sqlx.DB, comment string) error {
query := `INSERT INTO comments (content, wine) VALUES (?, ?)`
_, err := db.ExecContext(ctx, query, comment, v.ID)
if err != nil {
return err
}
return nil
}
func ListWines(ctx context.Context, db *sqlx.DB) ([]Vino, error) {
query := `SELECT rowid, name, rating FROM wines ORDER BY rating DESC;`
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment