aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/js/list.js8
-rw-r--r--frontend/renderer.go15
-rw-r--r--modules/lists/lists.go44
-rw-r--r--views/list.html39
-rw-r--r--views/list_gril.html38
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.
30type 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.
30func (r *Renderer) DefaultData() map[string]interface{} { 36func (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.
45type ListGrils []*ListGril
46func (l ListGrils) Len() int { return len(l) }
47func (l ListGrils) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
48func (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
44func (m *Module) Name() string { 51func (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
265func (m *Module) displayCreateList(w http.ResponseWriter, r *http.Request, p httprouter.Params) { 305func (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