aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/css/gril.css20
-rw-r--r--main.go2
-rw-r--r--modules/grils/gril.go15
-rw-r--r--modules/grils/grils.go29
-rw-r--r--modules/tags/tags.go96
-rw-r--r--tools/importer/main.go47
-rw-r--r--views/card.html20
-rw-r--r--views/dashboard.html20
-rw-r--r--views/gril.html26
-rw-r--r--views/list.html4
-rw-r--r--views/login.html8
-rw-r--r--views/tag.html22
12 files changed, 251 insertions, 58 deletions
diff --git a/assets/css/gril.css b/assets/css/gril.css
index 5b5bd84..b82e2c7 100644
--- a/assets/css/gril.css
+++ b/assets/css/gril.css
@@ -1,3 +1,21 @@
1#gril-title {
2 margin-bottom: 0rem;
3}
4
5#gril-alias {
6 margin-top: 0rem;
7 margin-bottom: 1rem;
8}
9
10.gril-tag {
11 transition: background-color .2s, color .2s;
12}
13
14.gril-tag:hover {
15 background-color: #BA68C8;
16 color: #FFF;
17}
18
1h1 > small { 19h1 > small {
2 padding-left: 8px; 20 padding-left: 8px;
3 font-size: 50%; 21 font-size: 50%;
@@ -10,4 +28,4 @@ h1 > small {
10.card-content.center-big { 28.card-content.center-big {
11 padding-top: 9px; 29 padding-top: 9px;
12 padding-bottom: 9px; 30 padding-bottom: 9px;
13} \ No newline at end of file 31}
diff --git a/main.go b/main.go
index 6dec94c..04db8d6 100644
--- a/main.go
+++ b/main.go
@@ -11,6 +11,7 @@ import (
11 "fagott.pw/grilist/grilist" 11 "fagott.pw/grilist/grilist"
12 "fagott.pw/grilist/modules/grils" 12 "fagott.pw/grilist/modules/grils"
13 "fagott.pw/grilist/modules/lists" 13 "fagott.pw/grilist/modules/lists"
14 "fagott.pw/grilist/modules/tags"
14 15
15 "github.com/julienschmidt/httprouter" 16 "github.com/julienschmidt/httprouter"
16 _ "github.com/lib/pq" 17 _ "github.com/lib/pq"
@@ -73,6 +74,7 @@ func main() {
73 // Module laden 74 // Module laden
74 loadModule(grils.New()) 75 loadModule(grils.New())
75 loadModule(lists.New()) 76 loadModule(lists.New())
77 loadModule(tags.New())
76 78
77 log.Fatal(http.ListenAndServe(":8080", nil)) 79 log.Fatal(http.ListenAndServe(":8080", nil))
78} 80}
diff --git a/modules/grils/gril.go b/modules/grils/gril.go
index fe316cd..89dd7c4 100644
--- a/modules/grils/gril.go
+++ b/modules/grils/gril.go
@@ -3,9 +3,12 @@ package grils
3import ( 3import (
4 "database/sql" 4 "database/sql"
5 "fmt" 5 "fmt"
6 "github.com/lib/pq"
7 "os" 6 "os"
7 "strconv"
8 "strings"
8 "time" 9 "time"
10
11 "github.com/lib/pq"
9) 12)
10 13
11type DataSource int 14type DataSource int
@@ -28,6 +31,16 @@ type Gril struct {
28 Lists []int 31 Lists []int
29} 32}
30 33
34func (g *Gril) Slug() string {
35 if g.RomajiName == "" {
36 return strconv.Itoa(g.ID)
37 }
38 return fmt.Sprintf(
39 "%d/%s",
40 g.ID,
41 strings.Replace(g.RomajiName, " ", "", -1))
42}
43
31func (g *Gril) ImagePath(prioritizeThumbnail bool) string { 44func (g *Gril) ImagePath(prioritizeThumbnail bool) string {
32 var big string 45 var big string
33 exts := []string{"png", "jpg", "gif", "jpeg"} 46 exts := []string{"png", "jpg", "gif", "jpeg"}
diff --git a/modules/grils/grils.go b/modules/grils/grils.go
index a1c84c7..0df93a0 100644
--- a/modules/grils/grils.go
+++ b/modules/grils/grils.go
@@ -1,16 +1,18 @@
1package grils 1package grils
2 2
3import ( 3import (
4 "fagott.pw/charakterin"
5 "fagott.pw/grilist/frontend"
6 "fagott.pw/grilist/grilist"
7 "fmt" 4 "fmt"
8 "github.com/julienschmidt/httprouter"
9 "log" 5 "log"
10 "net/http" 6 "net/http"
11 "regexp" 7 "regexp"
12 "strconv" 8 "strconv"
13 "strings" 9 "strings"
10
11 "fagott.pw/charakterin"
12 "fagott.pw/grilist/frontend"
13 "fagott.pw/grilist/grilist"
14
15 "github.com/julienschmidt/httprouter"
14) 16)
15 17
16var ( 18var (
@@ -39,6 +41,7 @@ func (m *GrilsModule) Init(g *grilist.Grilist) {
39 findIdx() 41 findIdx()
40 m.g = g 42 m.g = g
41 m.g.Router.GET("/gril/:id", m.viewGril) 43 m.g.Router.GET("/gril/:id", m.viewGril)
44 m.g.Router.GET("/gril/:id/*rest", m.viewGril)
42} 45}
43 46
44func (m *GrilsModule) getGrils(whereClause string, params ...interface{}) ([]*Gril, error) { 47func (m *GrilsModule) getGrils(whereClause string, params ...interface{}) ([]*Gril, error) {
@@ -124,7 +127,7 @@ func (m *GrilsModule) ProvideDashboardData(user *charakterin.User) []grilist.Das
124 Actions: []frontend.Action{ 127 Actions: []frontend.Action{
125 frontend.Action{ 128 frontend.Action{
126 Name: "anguckieren", 129 Name: "anguckieren",
127 Link: fmt.Sprintf("/gril/%d", gril.ID), 130 Link: "/gril/" + gril.Slug(),
128 }, 131 },
129 }, 132 },
130 }) 133 })
@@ -149,6 +152,22 @@ func (m *GrilsModule) FromID(id int) (*Gril, error) {
149 return gril, nil 152 return gril, nil
150} 153}
151 154
155func (m *GrilsModule) FromIDs(ids []int) ([]*Gril, error) {
156 idList := "("
157 first := true
158 for _, v := range ids {
159 if first {
160 first = false
161 } else {
162 idList += ","
163 }
164 idList += strconv.Itoa(v)
165 }
166 idList += ")"
167 grils, err := m.getGrils("id IN " + idList)
168 return grils, err
169}
170
152func (m *GrilsModule) viewGril(w http.ResponseWriter, r *http.Request, p httprouter.Params) { 171func (m *GrilsModule) viewGril(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
153 user, _ := m.g.Charakterin.GetUserFromRequest(r) 172 user, _ := m.g.Charakterin.GetUserFromRequest(r)
154 sid := p.ByName("id") 173 sid := p.ByName("id")
diff --git a/modules/tags/tags.go b/modules/tags/tags.go
new file mode 100644
index 0000000..9412e24
--- /dev/null
+++ b/modules/tags/tags.go
@@ -0,0 +1,96 @@
1package tags
2
3import (
4 "log"
5 "net/http"
6
7 "fagott.pw/charakterin"
8 "fagott.pw/grilist/frontend"
9 "fagott.pw/grilist/grilist"
10 "fagott.pw/grilist/modules/grils"
11
12 "github.com/julienschmidt/httprouter"
13)
14
15type Module struct {
16 g *grilist.Grilist
17 grils *grils.GrilsModule
18}
19
20func New() *Module {
21 return &Module{}
22}
23
24func (m *Module) Name() string {
25 return "Tags"
26}
27
28func (m *Module) Init(g *grilist.Grilist) {
29 m.g = g
30 gm, ok := g.Modules["Grils"]
31 if !ok {
32 log.Fatal("tags: grils module not found")
33 }
34 m.grils = gm.(*grils.GrilsModule)
35 m.g.Router.GET("/tag/:tag", m.viewTag)
36}
37
38func (m *Module) Interface() interface{} {
39 return m
40}
41
42func (m *Module) ProvideDashboardData(user *charakterin.User) []grilist.DashboardCategory {
43 return make([]grilist.DashboardCategory, 0)
44}
45
46func (m *Module) viewTag(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
47 user, _ := m.g.Charakterin.GetUserFromRequest(r)
48 tag := p.ByName("tag")
49 var tagID int
50 row := m.g.DB.QueryRow("SELECT id FROM grilist.tags WHERE name = $1;", tag)
51 if err := row.Scan(&tagID); err != nil {
52 log.Println(err)
53 http.Redirect(w, r, "/", 302)
54 return
55 }
56 idList := make([]int, 0)
57 rows, err := m.g.DB.Query(
58 "SELECT gril_id FROM grilist.grils_tags WHERE tag_id = $1",
59 tagID)
60 if err != nil {
61 log.Println(err)
62 http.Redirect(w, r, "/", 302)
63 return
64 }
65 defer rows.Close()
66 for rows.Next() {
67 var grilID int
68 rows.Scan(&grilID)
69 idList = append(idList, grilID)
70 }
71 grils, err := m.grils.FromIDs(idList)
72 if err != nil {
73 log.Println(err)
74 http.Redirect(w, r, "/", 302)
75 return
76 }
77 cards := make([]frontend.Card, 0)
78 for _, v := range grils {
79 cards = append(cards, frontend.Card{
80 Title: v.RomajiName,
81 Description: v.KanjiName,
82 Size: "medium",
83 Actions: []frontend.Action{
84 frontend.Action{
85 Name: "anguckieren",
86 Link: "/gril/" + v.Slug(),
87 },
88 },
89 })
90 }
91 data := m.g.Renderer.DefaultData()
92 data["user"] = user
93 data["tag"] = tag
94 data["cards"] = cards
95 m.g.Renderer.RenderPage("tag", w, data)
96}
diff --git a/tools/importer/main.go b/tools/importer/main.go
index 7f12d78..9caf287 100644
--- a/tools/importer/main.go
+++ b/tools/importer/main.go
@@ -81,8 +81,7 @@ func main() {
81 for rows.Next() { 81 for rows.Next() {
82 var id int 82 var id int
83 var name string 83 var name string
84 rows.Scan(&id) 84 rows.Scan(&id, &name)
85 rows.Scan(&name)
86 taglist[name] = id 85 taglist[name] = id
87 } 86 }
88 idmap := make(map[int]int) 87 idmap := make(map[int]int)
@@ -90,8 +89,7 @@ func main() {
90 for rows.Next() { 89 for rows.Next() {
91 var sourceID int 90 var sourceID int
92 var grilID int 91 var grilID int
93 rows.Scan(&sourceID) 92 rows.Scan(&sourceID, &grilID)
94 rows.Scan(&grilID)
95 idmap[sourceID] = grilID 93 idmap[sourceID] = grilID
96 } 94 }
97 filepath.Walk(path, func(path string, info os.FileInfo, err error) error { 95 filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
@@ -99,23 +97,16 @@ func main() {
99 return nil 97 return nil
100 } 98 }
101 g := r.Read(path) 99 g := r.Read(path)
102 for _, v := range g.Gril.Tags { 100 var dbID int
103 if _, ok := taglist[v]; ok { 101 var ok bool
104 continue 102 if dbID, ok = idmap[g.Gril.ID]; !ok {
105 }
106 var id int
107 row := db.QueryRow("INSERT INTO grilist.tags (name) VALUES ($1) RETURNING id;", v)
108 row.Scan(&id)
109 taglist[v] = id
110 }
111 if _, ok := idmap[g.Gril.ID]; !ok {
112 row := db.QueryRow("INSERT INTO grilist.grils (age) VALUES (NULL) RETURNING id;") 103 row := db.QueryRow("INSERT INTO grilist.grils (age) VALUES (NULL) RETURNING id;")
113 var dbID int
114 row.Scan(&dbID) 104 row.Scan(&dbID)
115 for _, v := range g.Gril.Tags { 105 fmt.Printf(
116 tagID := taglist[v] 106 "Assigned %d from %s to %d\n",
117 db.Exec("INSERT INTO grilist.grils_tags (gril_id, tag_id) VALUES ($1, $2);", dbID, tagID) 107 g.Gril.ID,
118 } 108 sourceType,
109 dbID)
119 db.Exec(`INSERT INTO grilist.grils_id_mappings (gril_id, 110 db.Exec(`INSERT INTO grilist.grils_id_mappings (gril_id,
120 source, source_id) VALUES ($1, $2, $3);`, 111 source, source_id) VALUES ($1, $2, $3);`,
121 dbID, r.ID(), g.Gril.ID) 112 dbID, r.ID(), g.Gril.ID)
@@ -159,6 +150,24 @@ func main() {
159 } 150 }
160 fmt.Printf("Inserted %s\n", g.Gril.RomajiName) 151 fmt.Printf("Inserted %s\n", g.Gril.RomajiName)
161 } 152 }
153 for _, v := range g.Gril.Tags {
154 if _, ok := taglist[v]; ok {
155 continue
156 }
157 var id int
158 row := db.QueryRow("INSERT INTO grilist.tags (name) VALUES ($1) RETURNING id;", v)
159 row.Scan(&id)
160 taglist[v] = id
161 }
162 _, err = db.Exec(`DELETE FROM grilist.grils_tags WHERE gril_id
163 = $1`, dbID)
164 LogErr(err)
165 for _, v := range g.Gril.Tags {
166 tagID := taglist[v]
167 _, err := db.Exec(`INSERT INTO grilist.grils_tags
168 (gril_id, tag_id) VALUES ($1, $2);`, dbID, tagID)
169 LogErr(err)
170 }
162 return nil 171 return nil
163 }) 172 })
164} 173}
diff --git a/views/card.html b/views/card.html
new file mode 100644
index 0000000..be28272
--- /dev/null
+++ b/views/card.html
@@ -0,0 +1,20 @@
1{{ define "card" }}
2{{ $card := . }}
3<div class="col s12 m6 l4">
4 <div class="card white">
5 <div class="card-content black-text">
6 <span class="card-title">{{ $card.Title | html }}</span>
7 <p>{{ $card.Description | html }}</p>
8 </div>
9 <div class="card-action">
10 {{ range $action := $card.Actions }}
11 {{ if $action.Disabled }}
12 <span>{{ $action.Name | html }}</span>
13 {{ else }}
14 <a href="{{ $action.Link }}">{{ $action.Name | html }}</a>
15 {{ end }}
16 {{ end }}
17 </div>
18 </div>
19</div>
20{{ end }}
diff --git a/views/dashboard.html b/views/dashboard.html
index 0551285..56be42b 100644
--- a/views/dashboard.html
+++ b/views/dashboard.html
@@ -13,23 +13,7 @@
13 <h2>{{ $category.Title }}</h2> 13 <h2>{{ $category.Title }}</h2>
14 <div class="row"> 14 <div class="row">
15 {{ range $card := $category.Cards }} 15 {{ range $card := $category.Cards }}
16 <div class="col s12 m6 l4"> 16 {{ template "card" $card }}
17 <div class="card white">
18 <div class="card-content black-text">
19 <span class="card-title">{{ $card.Title | html }}</span>
20 <p>{{ $card.Description | html }}</p>
21 </div>
22 <div class="card-action">
23 {{ range $action := $card.Actions }}
24 {{ if $action.Disabled }}
25 <span>{{ $action.Name | html }}</span>
26 {{ else }}
27 <a href="{{ $action.Link }}">{{ $action.Name | html }}</a>
28 {{ end }}
29 {{ end }}
30 </div>
31 </div>
32 </div>
33 {{ end }} 17 {{ end }}
34 </div> 18 </div>
35 {{ end }} 19 {{ end }}
@@ -37,4 +21,4 @@
37 </div> 21 </div>
38 </body> 22 </body>
39</html> 23</html>
40{{ end }} \ No newline at end of file 24{{ end }}
diff --git a/views/gril.html b/views/gril.html
index 2dea399..776f14f 100644
--- a/views/gril.html
+++ b/views/gril.html
@@ -10,14 +10,24 @@
10 <body> 10 <body>
11 {{ template "navbar" . }} 11 {{ template "navbar" . }}
12 <div class="container"> 12 <div class="container">
13 <h1>{{ $gril.RomajiName }}<small>{{ $gril.KanjiName }}</small></h1> 13 <h1 id="gril-title">{{ $gril.RomajiName }}<small>{{ $gril.KanjiName }}</small></h1>
14 {{ if $gril.OtherNames }}
15 <p id="gril-alias">Auch bekannt als:
16 {{ range $i, $alias := $gril.OtherNames }}{{ if $i }},{{ end }}
17 {{ $alias }}{{ end }}
18 </p>
19 {{ end }}
14 <div class="row center-align"> 20 <div class="row center-align">
15 <img src="/{{ $gril.ImagePath false }}" /> 21 <img src="/{{ $gril.ImagePath false }}" />
16 </div> 22 </div>
17 {{ range $tag := $gril.Tags }} 23 {{ range $tag := $gril.Tags }}
18 <div class="chip"> 24 <a href="/tag/{{ $tag }}"
19 {{ $tag }} 25 alt="Mit &quot;{{ $tag }}&quot; getaggte Grils einsehen"
20 </div> 26 title="Mit &quot;{{ $tag }}&quot; getaggte Grils einsehen">
27 <div class="chip gril-tag">
28 {{ $tag }}
29 </div>
30 </a>
21 {{ end }} 31 {{ end }}
22 <br /> 32 <br />
23 <br /> 33 <br />
@@ -27,7 +37,7 @@
27 <div class="card"> 37 <div class="card">
28 <div class="card-content purple-text text-lighten-2 center-align"> 38 <div class="card-content purple-text text-lighten-2 center-align">
29 <span class="card-title big">{{ $gril.Birthday.Value}}</span> 39 <span class="card-title big">{{ $gril.Birthday.Value}}</span>
30 <p>geburtstag</p> 40 <p>Geburtstag</p>
31 </div> 41 </div>
32 </div> 42 </div>
33 </div> 43 </div>
@@ -36,7 +46,7 @@
36 <div class="card"> 46 <div class="card">
37 <div class="card-content purple-text text-lighten-2 center-align"> 47 <div class="card-content purple-text text-lighten-2 center-align">
38 <span class="card-title big">{{ $gril.Age.Value }}</span> 48 <span class="card-title big">{{ $gril.Age.Value }}</span>
39 <p>jahre alt</p> 49 <p>Jahre alt</p>
40 </div> 50 </div>
41 </div> 51 </div>
42 </div> 52 </div>
@@ -47,7 +57,7 @@
47 <div class="card-content center-big purple-text text-lighten-2 center-align"> 57 <div class="card-content center-big purple-text text-lighten-2 center-align">
48 <p>in</p> 58 <p>in</p>
49 <span class="card-title big">{{ len $gril.Lists}}</span> 59 <span class="card-title big">{{ len $gril.Lists}}</span>
50 <p>liste{{ if ne (len $gril.Lists) 1 }}n{{ end }}</p> 60 <p>Liste{{ if ne (len $gril.Lists) 1 }}n{{ end }}</p>
51 </div> 61 </div>
52 </div> 62 </div>
53 </div> 63 </div>
@@ -64,4 +74,4 @@
64 </div> 74 </div>
65 </body> 75 </body>
66</html> 76</html>
67{{ end }} \ No newline at end of file 77{{ end }}
diff --git a/views/list.html b/views/list.html
index ddec59f..0393d19 100644
--- a/views/list.html
+++ b/views/list.html
@@ -25,7 +25,7 @@
25 <div class="circle gril-img" style="background-image: url(/{{ $lg.Gril.ImagePath true }})"> </div> 25 <div class="circle gril-img" style="background-image: url(/{{ $lg.Gril.ImagePath true }})"> </div>
26 </div> 26 </div>
27 <div class="col s6 m6"> 27 <div class="col s6 m6">
28 <span><a href="/gril/{{ $lg.Gril.ID }}">{{ $lg.Gril.RomajiName }}</a><br /> 28 <span><a href="/gril/{{ $lg.Gril.Slug }}">{{ $lg.Gril.RomajiName }}</a><br />
29 <span class="jap-name">{{ $lg.Gril.KanjiName }}</span> 29 <span class="jap-name">{{ $lg.Gril.KanjiName }}</span>
30 </span> 30 </span>
31 </div> 31 </div>
@@ -59,4 +59,4 @@
59 </div> 59 </div>
60 </body> 60 </body>
61</html> 61</html>
62{{ end }} \ No newline at end of file 62{{ end }}
diff --git a/views/login.html b/views/login.html
index d671d50..6014d4d 100644
--- a/views/login.html
+++ b/views/login.html
@@ -24,15 +24,15 @@
24 <form method="POST" name="login" action="#"> 24 <form method="POST" name="login" action="#">
25 <div class="input-field col s12"> 25 <div class="input-field col s12">
26 <i class="material-icons prefix">perm_identity</i> 26 <i class="material-icons prefix">perm_identity</i>
27 <input name="username" type="text" placeholder="Username" class="validate" value="{{ .previous_user }}"/> 27 <input name="username" type="text" placeholder="Benutzername" class="validate" value="{{ .previous_user }}"/>
28 </div> 28 </div>
29 <div class="input-field col s12"> 29 <div class="input-field col s12">
30 <i class="material-icons prefix">lock_outline</i> 30 <i class="material-icons prefix">lock_outline</i>
31 <input name="password" type="password" placeholder="Password" class="validate" /> 31 <input name="password" type="password" placeholder="Passwort" class="validate" />
32 </div> 32 </div>
33 <div class="row col s12"> 33 <div class="row col s12">
34 <div class="col s4"> 34 <div class="col s4">
35 <a class="waves-effect waves-teal btn-flat" href="/register">Register</a> 35 <a class="waves-effect waves-teal btn-flat" href="/register">Registrieren</a>
36 </div> 36 </div>
37 <div class="right-align"> 37 <div class="right-align">
38 <button class="btn waves-effect waves-light purple lighten-2" type="submit" name="action"> 38 <button class="btn waves-effect waves-light purple lighten-2" type="submit" name="action">
@@ -46,4 +46,4 @@
46 </div> 46 </div>
47 </body> 47 </body>
48</html> 48</html>
49{{ end }} \ No newline at end of file 49{{ end }}
diff --git a/views/tag.html b/views/tag.html
new file mode 100644
index 0000000..788083f
--- /dev/null
+++ b/views/tag.html
@@ -0,0 +1,22 @@
1{{ define "tag" }}
2<html>
3 <head>
4 {{ template "materialize" }}
5 <title>grilist</title>
6 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
7 </head>
8 <body>
9 {{ template "navbar" . }}
10 <div class="container">
11 <div class="row">
12 <h2>Grils mit dem Tag &quot;{{ .tag }}&quot;:</h2>
13 <div class="row">
14 {{ range .cards }}
15 {{ template "card" . }}
16 {{ end }}
17 </div>
18 </div>
19 </div>
20 </body>
21</html>
22{{ end }}