Add basic html/rss support for book lists

This commit is contained in:
Las Zenow 2018-04-09 09:47:44 +00:00
parent c0a70a18e1
commit 46762ea17b
11 changed files with 254 additions and 78 deletions

View file

@ -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").

86
lib/list.go Normal file
View file

@ -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)
}

View file

@ -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 := ""

View file

@ -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))