From 46762ea17b24da6b24ce85385a4292b0f1fb1e0f Mon Sep 17 00:00:00 2001 From: Las Zenow Date: Mon, 9 Apr 2018 09:47:44 +0000 Subject: [PATCH] Add basic html/rss support for book lists --- lib/database/list.go | 9 ++--- lib/list.go | 86 ++++++++++++++++++++++++++++++++++++++++ lib/template.go | 72 +++++++++++++++++++-------------- lib/trantor.go | 20 ++++++++++ templates/book.html | 27 +++++++++++++ templates/book_list.html | 25 ++++++++++++ templates/book_list.rss | 17 ++++++++ templates/list.html | 16 ++++++++ templates/list.rss | 14 +++++++ templates/search.html | 28 +------------ templates/search.rss | 18 +-------- 11 files changed, 254 insertions(+), 78 deletions(-) create mode 100644 lib/list.go create mode 100644 templates/book_list.html create mode 100644 templates/book_list.rss create mode 100644 templates/list.html create mode 100644 templates/list.rss diff --git a/lib/database/list.go b/lib/database/list.go index 25c5f13..99cb1a3 100644 --- a/lib/database/list.go +++ b/lib/database/list.go @@ -80,7 +80,7 @@ func (db *pgDB) UpdateBookList(listID, title string, description []string) error func (db *pgDB) GetBookList(listID string) (*BookList, error) { var bookList BookList err := db.sql.Model(&bookList). - Column("Books"). + Column("Books", "User"). Where("list_id = ?", listID). Select() return &bookList, err @@ -95,7 +95,7 @@ func (db *pgDB) GetListsByUser(username string) ([]BookList, error) { } err = db.sql.Model(&bookLists). - Column("Books"). + Column("Books", "User"). Where("user_id = ?", user.ID). Select() return bookLists, err @@ -108,7 +108,7 @@ func (db *pgDB) GetListsByBook(bookID string) ([]BookList, error) { err := db.sql.Model(&bookListEntries). Where("book_id = ?", bookID). Select() - if err != nil { + if err != nil || len(bookListEntries) == 0 { return bookLists, err } @@ -118,11 +118,10 @@ func (db *pgDB) GetListsByBook(bookID string) ([]BookList, error) { whereQuery += "?" if i < len(bookListEntries)-1 { whereQuery += ", " - } else { - whereQuery += ")" } listIDs[i] = entry.ID } + whereQuery += ")" err = db.sql.Model(&bookLists). Column("Books"). diff --git a/lib/list.go b/lib/list.go new file mode 100644 index 0000000..6c2af99 --- /dev/null +++ b/lib/list.go @@ -0,0 +1,86 @@ +package trantor + +import ( + "net/http" + "strings" + + "gitlab.com/trantor/trantor/lib/database" + + log "github.com/cihub/seelog" + "github.com/gorilla/mux" +) + +func listHandler(h handler) { + listID := mux.Vars(h.r)["listID"] + list, err := h.db.GetBookList(listID) + if err != nil { + log.Error("Error loading list ", listID, ": ", err) + h.sess.Notify("Something went wrong!", "Could not load the list list", "error") + http.Redirect(h.w, h.r, h.r.Referer(), http.StatusFound) + return + } + if list == nil { + notFound(h) + return + } + + var data listData + data.S = GetStatus(h) + data.S.Title = list.Title + " -- " + data.S.Title + data.List = list + h.load("list", data) +} + +type listData struct { + S Status + List *database.BookList +} + +func listPostHandler(h handler) { + if h.sess.User == "" { + notFound(h) + return + } + + listTitle := h.r.FormValue("list") + bookID := h.r.FormValue("book_id") + userLists, err := h.db.GetListsByUser(h.sess.User) + if err != nil { + log.Error("Error loading user (", h.sess.User, ") lists: ", err) + h.sess.Notify("Something went wrong!", "Could not add book to the list", "error") + http.Redirect(h.w, h.r, h.r.Referer(), http.StatusFound) + return + } + + var list *database.BookList + for _, l := range userLists { + if strings.ToLower(l.Title) == strings.ToLower(listTitle) { + list = &l + break + } + } + + var listID string + if list == nil { + listID = genID() + err = h.db.NewBookList(listID, listTitle, h.sess.User, []string{}) + if err != nil { + log.Error("Error creating list ", listTitle, " by user ", h.sess.User, ": ", err) + h.sess.Notify("Something went wrong!", "Could not add book to the list", "error") + http.Redirect(h.w, h.r, h.r.Referer(), http.StatusFound) + return + } + } else { + listID = list.ListID + } + + err = h.db.AddBookToList(listID, bookID) + if err != nil { + log.Error("Error adding book ", bookID, " to list ", listTitle, "(", listID, "): ", err) + h.sess.Notify("Something went wrong!", "Could not add book to the list", "error") + http.Redirect(h.w, h.r, h.r.Referer(), http.StatusFound) + return + } + + http.Redirect(h.w, h.r, "/list/"+listID, http.StatusFound) +} diff --git a/lib/template.go b/lib/template.go index 7f4f452..16a837a 100644 --- a/lib/template.go +++ b/lib/template.go @@ -4,6 +4,8 @@ import ( html_tmpl "html/template" txt_tmpl "text/template" + log "github.com/cihub/seelog" + "encoding/json" "errors" "net/http" @@ -51,40 +53,31 @@ type Template struct { } func InitTemplate(assetsPath string) *Template { + var err error var t Template templatePath := path.Join(assetsPath, "templates") - t.html = html_tmpl.Must(html_tmpl.ParseFiles( - path.Join(templatePath, "header.html"), - path.Join(templatePath, "footer.html"), - path.Join(templatePath, "404.html"), - path.Join(templatePath, "index.html"), - path.Join(templatePath, "about.html"), - path.Join(templatePath, "news.html"), - path.Join(templatePath, "edit_news.html"), - path.Join(templatePath, "book.html"), - path.Join(templatePath, "search.html"), - path.Join(templatePath, "upload.html"), - path.Join(templatePath, "submission.html"), - path.Join(templatePath, "login.html"), - path.Join(templatePath, "new.html"), - path.Join(templatePath, "read.html"), - path.Join(templatePath, "edit.html"), - path.Join(templatePath, "dashboard.html"), - path.Join(templatePath, "settings.html"), - path.Join(templatePath, "help.html"), - path.Join(templatePath, "user_admin.html"), - )) + t.html, err = html_tmpl.ParseGlob(path.Join(templatePath, "*.html")) + if err != nil { + log.Critical("Error loading html templates: ", err) + } - t.rss = txt_tmpl.Must(txt_tmpl.ParseFiles( - path.Join(templatePath, "search.rss"), - path.Join(templatePath, "news.rss"), - )) + t.rss, err = txt_tmpl.New("rss").Funcs(txt_tmpl.FuncMap{ + "book_list": func(books, baseURL interface{}) (map[string]interface{}, error) { + data := make(map[string]interface{}, 2) + data["Books"] = books + data["BaseURL"] = baseURL + return data, nil + }, + }).ParseGlob(path.Join(templatePath, "*.rss")) + if err != nil { + log.Critical("Error loading rss templates: ", err) + } - t.opds = txt_tmpl.Must(txt_tmpl.ParseFiles( - path.Join(templatePath, "index.opds"), - path.Join(templatePath, "search.opds"), - )) + t.opds, err = txt_tmpl.ParseGlob(path.Join(templatePath, "*.opds")) + if err != nil { + log.Critical("Error loading opds templates: ", err) + } return &t } @@ -101,6 +94,8 @@ func loadJson(w http.ResponseWriter, tmpl string, data interface{}) error { res, err = newsJson(data) case "search": res, err = searchJson(data) + case "list": + res, err = listJson(data) } if err != nil { return err @@ -178,6 +173,25 @@ func searchJson(data interface{}) ([]byte, error) { }) } +func listJson(data interface{}) ([]byte, error) { + list, ok := data.(listData) + if !ok { + return nil, errors.New("Data is not valid") + } + + books := make([]map[string]interface{}, len(list.List.Books)) + for i, book := range list.List.Books { + books[i] = bookJsonRaw(book) + } + return json.Marshal(map[string]interface{}{ + "ID": list.List.ListID, + "title": list.List.Title, + "description": list.List.Description, + "user ": list.List.User.Username, + "books": books, + }) +} + func bookJsonRaw(book database.Book) map[string]interface{} { cover := "" coverSmall := "" diff --git a/lib/trantor.go b/lib/trantor.go index 6d4ab2f..a0e6b7e 100644 --- a/lib/trantor.go +++ b/lib/trantor.go @@ -52,6 +52,8 @@ type bookData struct { S Status Book database.Book Description []string + Lists []database.BookList + UserLists []string } func bookHandler(h handler) { @@ -71,6 +73,21 @@ func bookHandler(h handler) { } data.S.Title = book.Title + author + " -- " + data.S.Title + data.Lists, err = h.db.GetListsByBook(id) + if err != nil { + log.Error("Error getting lists: ", err) + } + if h.sess.User != "" { + userLists, err := h.db.GetListsByUser(h.sess.User) + if err != nil { + log.Error("Error getting lists: ", err) + } else { + data.UserLists = make([]string, len(userLists)) + for i, l := range userLists { + data.UserLists[i] = l.Title + } + } + } data.Description = strings.Split(data.Book.Description, "\n") h.load("book", data) } @@ -191,6 +208,9 @@ func InitRouter(db database.DB, sg *StatsGatherer, assetsPath string) http.Handl r.HandleFunc("/dashboard/", sg.Gather(dashboardHandler)) r.HandleFunc("/settings/", sg.Gather(settingsHandler)) + r.HandleFunc("/list/{listID:"+idPattern+"}", sg.Gather(listHandler)).Methods("GET") + r.HandleFunc("/list/", sg.Gather(listPostHandler)).Methods("POST") + r.HandleFunc("/new/", sg.Gather(newHandler)) r.HandleFunc("/save/{id:"+idPattern+"}", sg.Gather(saveHandler)).Methods("POST") r.HandleFunc("/edit/{id:"+idPattern+"}", sg.Gather(editHandler)) diff --git a/templates/book.html b/templates/book.html index c788b8a..7d0e7ed 100644 --- a/templates/book.html +++ b/templates/book.html @@ -76,4 +76,31 @@ function delBook(){ +{{if .Lists}} +
+
+

Book in lists:

+ +
+{{end}} + +{{if .S.User}} +
+
+ + + +
+ + +{{end}} + {{template "footer.html"}} diff --git a/templates/book_list.html b/templates/book_list.html new file mode 100644 index 0000000..37a0511 --- /dev/null +++ b/templates/book_list.html @@ -0,0 +1,25 @@ +{{range .}} +
+ +
+
+
+

+ [{{if .Lang}}{{.Lang}}{{end}}] + {{.Title}} + {{if .Publisher}}{{.Publisher}}{{end}}
+ {{range .Authors}}{{.}}, {{end}} +

+
+ +
+
+
+{{end}} diff --git a/templates/book_list.rss b/templates/book_list.rss new file mode 100644 index 0000000..89ab859 --- /dev/null +++ b/templates/book_list.rss @@ -0,0 +1,17 @@ +{{$baseURL := .BaseURL}} +{{range .Books}} + + {{.Title}} - {{index .Authors 0}} + {{.Description}} + {{$baseURL}}/book/{{.ID}} +{{if .Isbn}} + ISBN: {{.Isbn}} +{{end}} + +{{range .Authors}} + {{if .}} + {{.}} + {{end}} +{{end}} + +{{end}} diff --git a/templates/list.html b/templates/list.html new file mode 100644 index 0000000..de75a1c --- /dev/null +++ b/templates/list.html @@ -0,0 +1,16 @@ +{{template "header.html" .S}} + +
+

{{.List.Title}}

+

By {{.List.User.Username}}

+
+
+ +{{range .List.Description}} +

{{.}}

+{{end}} + + +{{template "book_list.html" .List.Books}} + +{{template "footer.html"}} diff --git a/templates/list.rss b/templates/list.rss new file mode 100644 index 0000000..73a7dab --- /dev/null +++ b/templates/list.rss @@ -0,0 +1,14 @@ + + + + {{.S.Title}} + {{range .List.Description}} + {{.}} +{{end}} + {{.S.BaseURL}}/list/{{.List.ListID}} + {{.List.User.Username}} + +{{template "book_list.rss" book_list .List.Books .S.BaseURL}} + + + diff --git a/templates/search.html b/templates/search.html index 6798d6c..2487811 100644 --- a/templates/search.html +++ b/templates/search.html @@ -17,33 +17,7 @@ {{end}} -{{with .Books}} - {{range .}} -
- -
-
-
-

- [{{if .Lang}}{{.Lang}}{{end}}] - {{.Title}} - {{if .Publisher}}{{.Publisher}}{{end}}
- {{range .Authors}}{{.}}, {{end}} -

-
- -
-
-
- {{end}} -{{end}} +{{template "book_list.html" .Books}}