aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjan <jan@ruken.pw>2016-01-16 18:39:21 (UTC)
committerjan <jan@ruken.pw>2016-01-16 18:39:21 (UTC)
commitb16c4ef8e1ef3458f186139172362a511f925043 (patch)
treeb965638fccbbddee16206c88ba61b76a9656cefc
parent928ab739e2b4b40077610a7913adb0cf086f2ee1 (diff)
grils können nun zu listen hinzugefügt werden, da lukas zu faul war. javascript wird vorausgesetzt. grils werden direkt hinzugefügt beim klicken ohne ladezeit. musste dafür ein paar hacks im templating verwenden, da ein gewisser jemand kein frontend framework verwenden will.
-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