From 07db227557f0cb29e87c90fdc3d1c433ca14188f Mon Sep 17 00:00:00 2001 From: Gregor Best <gbe@unobtanium.de> Date: Sun, 16 May 2021 19:34:45 +0200 Subject: [PATCH] Store ISO3 country codes --- handler-details.go | 13 +++++++++--- templates/details.tpl | 10 ++++----- templates/index.tpl | 10 ++++++--- vino.go | 48 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 11 deletions(-) diff --git a/handler-details.go b/handler-details.go index b048d7d..e7f6434 100644 --- a/handler-details.go +++ b/handler-details.go @@ -84,6 +84,12 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) { return } + v, err := LoadVino(r.Context(), h.db, id) + if err != nil { + // Only log error here, just create a new entry. + log.Println("can't load vino with id", id, ":", err) + } + name := r.FormValue("name") if name == "" { httpError(w, "name can't be empty", nil, http.StatusBadRequest) @@ -96,14 +102,15 @@ func (h Handler) detailsPost(w http.ResponseWriter, r *http.Request) { return } - v, err := LoadVino(r.Context(), h.db, id) + country, err := ISO3CountryFromString(r.FormValue("country")) if err != nil { - // Only log error here, just create a new entry. - log.Println("can't load vino with id", id, ":", err) + httpError(w, "can't parse country", nil, http.StatusBadRequest) + return } v.Name = name v.Rating = rating + v.Country = country comment := strings.TrimSpace(r.FormValue("comment")) if comment != "" { diff --git a/templates/details.tpl b/templates/details.tpl index 6f58e94..353041a 100644 --- a/templates/details.tpl +++ b/templates/details.tpl @@ -15,11 +15,6 @@ <input type="hidden" name="id" value="{{ .Wine.ID }}"> <fieldset> - <div class="pure-control-group"> - <label for="form-id">ID</label> - <input type="text" id="form-id" value="{{ .Wine.ID }}" disabled> - </div> - <div class="pure-control-group"> <label for="form-name">Name</label> <input id="form-name" type="text" name="name" value="{{ .Wine.Name }}" placeholder="Name"> @@ -30,6 +25,11 @@ <input id="form-rating" type="number" name="rating" value="{{ .Wine.Rating }}" placeholder="Rating"> </div> + <div class="pure-control-group"> + <label for="form-country">Country (ISO3)</label> + <input id="form-country" type="text" name="country" value="{{ .Wine.Country }}" placeholder="XXX" pattern="[A-Z]{3}"> + </div> + <div class="pure-control-group"> <label for="form-new-picture">New picture</label> <input id="form-new-picture" type="file" name="picture" accept="image/png, image/jpeg"> diff --git a/templates/index.tpl b/templates/index.tpl index 2660329..3c82e49 100644 --- a/templates/index.tpl +++ b/templates/index.tpl @@ -8,13 +8,17 @@ <div class="content withfooter pure-u-1"> <div class="maxwidth box"> <table class="pure-table"> - <thead><tr><th>#</th><th>Rating</th><th class="fill">Name</th></tr></thead> + <thead><tr> + <th class="fill">Name</th> + <th>Rating</th> + <th>Country</th> + </tr></thead> <tbody> {{ range .Wines }} <tr> - <td><a href="/details?id={{ .ID }}">{{ .ID }}</a></td> - <td>{{ .Rating }}</td> <td><a href="/details?id={{ .ID }}">{{ .Name }}</a></td> + <td>{{ .Rating }}</td> + <td>{{ .Country }}</td> </tr> {{ end }} </tbody> diff --git a/vino.go b/vino.go index ad69328..f4dfb4c 100644 --- a/vino.go +++ b/vino.go @@ -28,10 +28,46 @@ type Comment struct { Content string } +type ISO3CountryCode [3]byte + +var UnknownCountry = ISO3CountryCode{'X', 'X', 'X'} + +func ISO3CountryFromString(s string) (ISO3CountryCode, error) { + if len(s) == 0 { + return UnknownCountry, nil + } + + if len(s) != 3 { + return UnknownCountry, errors.New("unexpected length") + } + + return ISO3CountryCode{s[0], s[1], s[2]}, nil +} + +func (i ISO3CountryCode) String() string { + return fmt.Sprintf("%c%c%c", i[0], i[1], i[2]) +} + +func (i *ISO3CountryCode) UnmarshalBinary(d []byte) error { + if len(d) == 0 { + *i = [3]byte{'X', 'X', 'X'} + return nil + } + + if len(d) != 3 { + return errors.New("invalid length") + } + + *i = [3]byte{d[0], d[1], d[2]} + + return nil +} + type Vino struct { ID uuid.UUID Name string Rating int + Country ISO3CountryCode Picture image.Image HasPicture bool // Set to true if there's picture data for this vino Comments []Comment @@ -74,6 +110,11 @@ func loadVino(tx *bolt.Tx, id uuid.UUID) (Vino, error) { return v, err } + err = v.Country.UnmarshalBinary(data.Get([]byte("country"))) + if err != nil { + return v, err + } + comments := data.Bucket([]byte("comments")) if comments != nil { err := comments.ForEach(func(k, txt []byte) error { @@ -283,6 +324,13 @@ func (v *Vino) Store(ctx context.Context, db *bolt.DB) error { } } + if v.Country != UnknownCountry { + err = wine.Put([]byte("country"), v.Country[:]) + if err != nil { + return err + } + } + return nil }) } -- GitLab