diff options
| -rw-r--r-- | assets/js/list.js | 8 | ||||
| -rw-r--r-- | frontend/renderer.go | 15 | ||||
| -rw-r--r-- | modules/lists/lists.go | 44 | ||||
| -rw-r--r-- | views/list.html | 39 | ||||
| -rw-r--r-- | views/list_gril.html | 38 |
5 files changed, 104 insertions, 40 deletions
diff --git a/assets/js/list.js b/assets/js/list.js index 3a58971..25ff80d 100644 --- a/assets/js/list.js +++ b/assets/js/list.js | |||
| @@ -2,7 +2,13 @@ function clickSearchResult(resId) { | |||
| 2 | var xhr = new XMLHttpRequest(); | 2 | var xhr = new XMLHttpRequest(); |
| 3 | xhr.onreadystatechange = function() { | 3 | xhr.onreadystatechange = function() { |
| 4 | if (xhr.readyState == XMLHttpRequest.DONE) { | 4 | if (xhr.readyState == XMLHttpRequest.DONE) { |
| 5 | alert(xhr.status + ": " + xhr.response); | 5 | if (xhr.status !== 200) { |
| 6 | alert(xhr.status + ": " + xhr.response); | ||
| 7 | return; | ||
| 8 | } | ||
| 9 | |||
| 10 | data = xhr.responseText; | ||
| 11 | document.getElementById("gril-list").innerHTML += data; | ||
| 6 | } | 12 | } |
| 7 | } | 13 | } |
| 8 | xhr.open('POST', window.location, true); | 14 | xhr.open('POST', window.location, true); |
diff --git a/frontend/renderer.go b/frontend/renderer.go index 524c2c8..f311462 100644 --- a/frontend/renderer.go +++ b/frontend/renderer.go | |||
| @@ -26,6 +26,12 @@ type Renderer struct { | |||
| 26 | defaultData map[string]interface{} | 26 | defaultData map[string]interface{} |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | // RangePair für Range-Dingens. Damit man die ID weiterhin accessen kann. | ||
| 30 | type RangePair struct { | ||
| 31 | Index int | ||
| 32 | Value interface{} | ||
| 33 | } | ||
| 34 | |||
| 29 | // DefaultData gibt die Standard-Daten für die Views zurück. Das ist immer eine Kopie weil Reasons. | 35 | // DefaultData gibt die Standard-Daten für die Views zurück. Das ist immer eine Kopie weil Reasons. |
| 30 | func (r *Renderer) DefaultData() map[string]interface{} { | 36 | func (r *Renderer) DefaultData() map[string]interface{} { |
| 31 | d := make(map[string]interface{}) | 37 | d := make(map[string]interface{}) |
| @@ -53,6 +59,15 @@ func New(path string) *Renderer { | |||
| 53 | "sub": func(a, b int) int { | 59 | "sub": func(a, b int) int { |
| 54 | return a - b | 60 | return a - b |
| 55 | }, | 61 | }, |
| 62 | "makeRangePair": func(idx int, value interface{}) RangePair { | ||
| 63 | return RangePair{idx, value} | ||
| 64 | }, | ||
| 65 | "makeObject": func(name string, existing interface{}, newKey string, newData interface{}) map[string]interface{} { | ||
| 66 | d := make(map[string]interface{}) | ||
| 67 | d[name] = existing | ||
| 68 | d[newKey] = newData | ||
| 69 | return d | ||
| 70 | }, | ||
| 56 | } | 71 | } |
| 57 | 72 | ||
| 58 | r := &Renderer{ | 73 | r := &Renderer{ |
diff --git a/modules/lists/lists.go b/modules/lists/lists.go index 8957c5f..85e6ce5 100644 --- a/modules/lists/lists.go +++ b/modules/lists/lists.go | |||
| @@ -15,6 +15,7 @@ import ( | |||
| 15 | "net/http" | 15 | "net/http" |
| 16 | "net/url" | 16 | "net/url" |
| 17 | "strconv" | 17 | "strconv" |
| 18 | "sort" | ||
| 18 | ) | 19 | ) |
| 19 | 20 | ||
| 20 | // Module und so. | 21 | // Module und so. |
| @@ -40,6 +41,12 @@ type ListGril struct { | |||
| 40 | Order int | 41 | Order int |
| 41 | } | 42 | } |
| 42 | 43 | ||
| 44 | // ListGrils ist die Sort-Interface Implementation für Grils einer Liste. | ||
| 45 | type ListGrils []*ListGril | ||
| 46 | func (l ListGrils) Len() int { return len(l) } | ||
| 47 | func (l ListGrils) Swap(i, j int) { l[i], l[j] = l[j], l[i] } | ||
| 48 | func (l ListGrils) Less(i, j int) bool { return l[i].Order < l[j].Order } | ||
| 49 | |||
| 43 | // Name gibt den Namen des Moduls zurück | 50 | // Name gibt den Namen des Moduls zurück |
| 44 | func (m *Module) Name() string { | 51 | func (m *Module) Name() string { |
| 45 | return "Lists" | 52 | return "Lists" |
| @@ -90,6 +97,7 @@ func (m *Module) getListGrils(list *List) error { | |||
| 90 | 97 | ||
| 91 | list.Grils = append(list.Grils, lg) | 98 | list.Grils = append(list.Grils, lg) |
| 92 | } | 99 | } |
| 100 | sort.Sort(ListGrils(list.Grils)) | ||
| 93 | return nil | 101 | return nil |
| 94 | } | 102 | } |
| 95 | 103 | ||
| @@ -258,8 +266,40 @@ func (m *Module) addGrilToList(w http.ResponseWriter, r *http.Request, p httprou | |||
| 258 | return | 266 | return |
| 259 | } | 267 | } |
| 260 | 268 | ||
| 261 | log.Println("implement: add gril", grilID, "to list", listID) | 269 | list, err := m.FromID(listID) |
| 262 | http.Error(w, "not implemented", 500) | 270 | if err != nil { |
| 271 | http.Error(w, "invalid list", 404) | ||
| 272 | return | ||
| 273 | } | ||
| 274 | |||
| 275 | rank := 0 | ||
| 276 | if len(list.Grils) > 0 { | ||
| 277 | rank = list.Grils[len(list.Grils) - 1].Order + 1 | ||
| 278 | } | ||
| 279 | |||
| 280 | // rein in die DB damit | ||
| 281 | _, err = m.g.DB.Query(`INSERT INTO grilist.lists_grils(list_id, gril_id, "order") VALUES($1, $2, $3)`, listID, grilID, rank) | ||
| 282 | if err != nil { | ||
| 283 | log.Println("error inserting gril into list:", err) | ||
| 284 | http.Error(w, "could not insert gril", 500) | ||
| 285 | return | ||
| 286 | } | ||
| 287 | |||
| 288 | gril, err := m.grils.FromID(grilID) | ||
| 289 | if err != nil { | ||
| 290 | log.Println("inserted gril into list but couldnt get gril afterwards:", err) | ||
| 291 | http.Error(w, "error after insert", 500) | ||
| 292 | return | ||
| 293 | } | ||
| 294 | |||
| 295 | data := m.g.Renderer.DefaultData() | ||
| 296 | data["Index"] = len(list.Grils) | ||
| 297 | value := make(map[string]interface{}) | ||
| 298 | value["IsListOwner"] = true | ||
| 299 | value["Gril"] = ListGril{ gril, rank } | ||
| 300 | data["Value"] = value | ||
| 301 | m.g.Renderer.RenderPage("list_gril", w, data) | ||
| 302 | return | ||
| 263 | } | 303 | } |
| 264 | 304 | ||
| 265 | func (m *Module) displayCreateList(w http.ResponseWriter, r *http.Request, p httprouter.Params) { | 305 | func (m *Module) displayCreateList(w http.ResponseWriter, r *http.Request, p httprouter.Params) { |
diff --git a/views/list.html b/views/list.html index fa58f91..b9ef7c8 100644 --- a/views/list.html +++ b/views/list.html | |||
| @@ -18,44 +18,9 @@ | |||
| 18 | <blockquote>{{ $list.Description }}</blockquote><br /> | 18 | <blockquote>{{ $list.Description }}</blockquote><br /> |
| 19 | <div class="row"> | 19 | <div class="row"> |
| 20 | <div class="col s12 {{ if ($user) and eq $user.ID $list.Owner.ID }}l8{{ end }}"> | 20 | <div class="col s12 {{ if ($user) and eq $user.ID $list.Owner.ID }}l8{{ end }}"> |
| 21 | <ul class="gril-list"> | 21 | <ul id="gril-list" class="gril-list"> |
| 22 | {{ range $index, $lg := $list.Grils }} | 22 | {{ range $index, $lg := $list.Grils }} |
| 23 | <li id="{{ $index }}"> | 23 | {{ template "list_gril" makeRangePair $index (makeObject "Gril" $lg "IsListOwner" (and ($user) (eq $user.ID $list.Owner.ID) )) }} |
| 24 | <div class="card-panel hoverable list-entry"> | ||
| 25 | <div class="row valign-wrapper"> | ||
| 26 | <div class="col s3 m2"> | ||
| 27 | <div class="circle gril-img" style="background-image: url(/{{ $lg.Gril.ImagePath true }})"> </div> | ||
| 28 | </div> | ||
| 29 | <div class="col s6 m6"> | ||
| 30 | <span><a href="/gril/{{ $lg.Gril.Slug }}">{{ $lg.Gril.RomajiName }}</a><br /> | ||
| 31 | <span class="jap-name">{{ $lg.Gril.KanjiName }}</span> | ||
| 32 | </span> | ||
| 33 | </div> | ||
| 34 | {{ if ($user) and eq $user.ID $list.Owner.ID }} | ||
| 35 | <div class="col s3 m5"> | ||
| 36 | <div class="hide-on-med-and-up"> | ||
| 37 | <div class="row list-controls valign-wrapper"> | ||
| 38 | <div class="col s6 left-align"> | ||
| 39 | <i class="material-icons grey-text" onClick="">keyboard_arrow_up</i> | ||
| 40 | <i class="material-icons grey-text" onClick="">keyboard_arrow_down</i> | ||
| 41 | </div> | ||
| 42 | <div class="col s4 left-align"> | ||
| 43 | <i class="hide-on-med-and-up material-icons delete-icon grey-text" onClick="">delete</i> | ||
| 44 | </div> | ||
| 45 | </div> | ||
| 46 | </div> | ||
| 47 | <div class="hide-on-small-only"> | ||
| 48 | <div class="valign-wrapper"> | ||
| 49 | <i class="medium material-icons grey-text" onClick="">keyboard_arrow_up</i> | ||
| 50 | <i class="medium material-icons grey-text" onClick="">keyboard_arrow_down</i> | ||
| 51 | <i class="material-icons grey-text" onClick="">delete</i> | ||
| 52 | </div> | ||
| 53 | </div> | ||
| 54 | </div> | ||
| 55 | {{ end }} | ||
| 56 | </div> | ||
| 57 | </div> | ||
| 58 | </li> | ||
| 59 | {{ end }} | 24 | {{ end }} |
| 60 | </ul> | 25 | </ul> |
| 61 | </div> | 26 | </div> |
diff --git a/views/list_gril.html b/views/list_gril.html new file mode 100644 index 0000000..5cfd0df --- /dev/null +++ b/views/list_gril.html | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | {{ define "list_gril" }} | ||
| 2 | <li id="{{ .Index }}"> | ||
| 3 | <div class="card-panel hoverable list-entry"> | ||
| 4 | <div class="row valign-wrapper"> | ||
| 5 | <div class="col s3 m2"> | ||
| 6 | <div class="circle gril-img" style="background-image: url(/{{ .Value.Gril.Gril.ImagePath true }})"> </div> | ||
| 7 | </div> | ||
| 8 | <div class="col s6 m6"> | ||
| 9 | <span><a href="/gril/{{ .Value.Gril.Gril.Slug }}">{{ .Value.Gril.Gril.RomajiName }}</a><br /> | ||
| 10 | <span class="jap-name">{{ .Value.Gril.Gril.KanjiName }}</span> | ||
| 11 | </span> | ||
| 12 | </div> | ||
| 13 | {{ if (.Value.IsListOwner) }} | ||
| 14 | <div class="col s3 m5"> | ||
| 15 | <div class="hide-on-med-and-up"> | ||
| 16 | <div class="row list-controls valign-wrapper"> | ||
| 17 | <div class="col s6 left-align"> | ||
| 18 | <i class="material-icons grey-text" onClick="">keyboard_arrow_up</i> | ||
| 19 | <i class="material-icons grey-text" onClick="">keyboard_arrow_down</i> | ||
| 20 | </div> | ||
| 21 | <div class="col s4 left-align"> | ||
| 22 | <i class="hide-on-med-and-up material-icons delete-icon grey-text" onClick="">delete</i> | ||
| 23 | </div> | ||
| 24 | </div> | ||
| 25 | </div> | ||
| 26 | <div class="hide-on-small-only"> | ||
| 27 | <div class="valign-wrapper"> | ||
| 28 | <i class="medium material-icons grey-text" onClick="">keyboard_arrow_up</i> | ||
| 29 | <i class="medium material-icons grey-text" onClick="">keyboard_arrow_down</i> | ||
| 30 | <i class="material-icons grey-text" onClick="">delete</i> | ||
| 31 | </div> | ||
| 32 | </div> | ||
| 33 | </div> | ||
| 34 | {{ end }} | ||
| 35 | </div> | ||
| 36 | </div> | ||
| 37 | </li> | ||
| 38 | {{ end }} \ No newline at end of file | ||
