Authors list
This commit is contained in:
parent
2f1e2a70fd
commit
6c11b38f2b
@ -33,6 +33,10 @@ Vue.component('result-cell', {
|
|||||||
},
|
},
|
||||||
cellContent: function(h) {
|
cellContent: function(h) {
|
||||||
switch (this.col.id) {
|
switch (this.col.id) {
|
||||||
|
case 'name':
|
||||||
|
return this.link(h, 'user', this.item.name, this.authorUrl(this.item.id));
|
||||||
|
case 'count':
|
||||||
|
return this.item.count;
|
||||||
case 'title':
|
case 'title':
|
||||||
return this.link(h, 'book', this.item.title, this.bookUrl(this.item.id));
|
return this.link(h, 'book', this.item.title, this.bookUrl(this.item.id));
|
||||||
case 'authors':
|
case 'authors':
|
||||||
@ -52,6 +56,7 @@ Vue.component('result-cell', {
|
|||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
default:
|
default:
|
||||||
|
console.log('ERROR unknown col: ' + this.col.id)
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,7 +87,7 @@ var index = new Vue({
|
|||||||
console.log("Series");
|
console.log("Series");
|
||||||
},
|
},
|
||||||
showAuthors: function() {
|
showAuthors: function() {
|
||||||
console.log("Authors");
|
this.sendQuery('/authors/', this.stdError, this.loadResults);
|
||||||
},
|
},
|
||||||
showBooks: function() {
|
showBooks: function() {
|
||||||
this.sendQuery('/books/', this.stdError, this.loadResults);
|
this.sendQuery('/books/', this.stdError, this.loadResults);
|
||||||
@ -105,8 +110,8 @@ var index = new Vue({
|
|||||||
break;
|
break;
|
||||||
case 'authors':
|
case 'authors':
|
||||||
this.cols = [
|
this.cols = [
|
||||||
{ name: 'Nom', sortId: 'name' },
|
{ id: 'name', name: 'Nom', sortable: true },
|
||||||
{ name: 'Livre(s)' }
|
{ id:'count', name: 'Livre(s)' }
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package bouquins
|
|||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"log"
|
"log"
|
||||||
@ -158,21 +159,35 @@ func NewIndexModel(title, js string, count int64) *IndexModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ResultsModel struct {
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
}
|
||||||
type BooksResultsModel struct {
|
type BooksResultsModel struct {
|
||||||
|
ResultsModel
|
||||||
Results []*BookAdv `json:"results,omitempty"`
|
Results []*BookAdv `json:"results,omitempty"`
|
||||||
Type string `json:"type,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBooksResultsModel(books []*BookAdv) *BooksResultsModel {
|
func NewBooksResultsModel(books []*BookAdv) *BooksResultsModel {
|
||||||
return &BooksResultsModel{
|
return &BooksResultsModel{ResultsModel{"books"}, books}
|
||||||
books,
|
|
||||||
"books",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Books []*BookAdv `json:"books,omitempty"`
|
type AuthorsResultsModel struct {
|
||||||
// Series []*SeriesAdv `json:"series,omitempty"`
|
ResultsModel
|
||||||
// Authors []*AuthorAdv `json:"authors,omitempty"`
|
Results []*AuthorAdv `json:"results,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAuthorsResultsModel(authors []*AuthorAdv) *AuthorsResultsModel {
|
||||||
|
return &AuthorsResultsModel{ResultsModel{"authors"}, authors}
|
||||||
|
}
|
||||||
|
|
||||||
|
type SerieResultsModel struct {
|
||||||
|
ResultsModel
|
||||||
|
Results []*SeriesAdv `json:"results,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSerieResultsModel(series []*SeriesAdv) *SerieResultsModel {
|
||||||
|
return &SerieResultsModel{ResultsModel{"series"}, series}
|
||||||
|
}
|
||||||
|
|
||||||
type BookModel struct {
|
type BookModel struct {
|
||||||
BouquinsModel
|
BouquinsModel
|
||||||
@ -189,11 +204,8 @@ type AuthorModel struct {
|
|||||||
*AuthorFull
|
*AuthorFull
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *Bouquins) render(res http.ResponseWriter, tpl string, model interface{}) {
|
func (app *Bouquins) render(res http.ResponseWriter, tpl string, model interface{}) error {
|
||||||
err := app.Template.ExecuteTemplate(res, tpl, model)
|
return app.Template.ExecuteTemplate(res, tpl, model)
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
func TemplatesFunc() *template.Template {
|
func TemplatesFunc() *template.Template {
|
||||||
tpl := template.New("")
|
tpl := template.New("")
|
||||||
@ -212,6 +224,14 @@ func TemplatesFunc() *template.Template {
|
|||||||
return tpl
|
return tpl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func writeJson(res http.ResponseWriter, model interface{}) error {
|
||||||
|
res.Header().Set("Content-Type", "application/json")
|
||||||
|
enc := json.NewEncoder(res)
|
||||||
|
return enc.Encode(model)
|
||||||
|
}
|
||||||
|
func isJson(req *http.Request) bool {
|
||||||
|
return req.Header.Get("Accept") == "application/json"
|
||||||
|
}
|
||||||
func paramInt(name string, req *http.Request) int {
|
func paramInt(name string, req *http.Request) int {
|
||||||
val := req.URL.Query().Get(name)
|
val := req.URL.Query().Get(name)
|
||||||
valInt, err := strconv.Atoi(val)
|
valInt, err := strconv.Atoi(val)
|
||||||
@ -254,10 +274,8 @@ func (app *Bouquins) IndexPage(res http.ResponseWriter, req *http.Request) {
|
|||||||
log.Print(err)
|
log.Print(err)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if req.Header.Get("Accept") == "application/json" {
|
if isJson(req) {
|
||||||
res.Header().Set("Content-Type", "application/json")
|
err := writeJson(res, model)
|
||||||
enc := json.NewEncoder(res)
|
|
||||||
err := enc.Encode(model)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
http.Error(res, err.Error(), 500)
|
http.Error(res, err.Error(), 500)
|
||||||
@ -266,68 +284,83 @@ func (app *Bouquins) IndexPage(res http.ResponseWriter, req *http.Request) {
|
|||||||
app.render(res, TPL_INDEX, model)
|
app.render(res, TPL_INDEX, model)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (app *Bouquins) BooksPage(res http.ResponseWriter, req *http.Request) {
|
func (app *Bouquins) BooksListPage(res http.ResponseWriter, req *http.Request) error {
|
||||||
if !strings.HasPrefix(req.URL.Path, URL_BOOKS) {
|
if isJson(req) {
|
||||||
// FIXME 404
|
books, err := app.BooksAdv(10, 0, "", "")
|
||||||
log.Fatalln("Invalid URL")
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return writeJson(res, NewBooksResultsModel(books))
|
||||||
}
|
}
|
||||||
idParam := req.URL.Path[len(URL_BOOKS):]
|
return errors.New("Invalid mime")
|
||||||
if len(idParam) == 0 {
|
}
|
||||||
// books list
|
func (app *Bouquins) BookPage(idParam string, res http.ResponseWriter, req *http.Request) error {
|
||||||
if req.Header.Get("Accept") == "application/json" {
|
id, err := strconv.Atoi(idParam)
|
||||||
books, err := app.BooksAdv(10, 0, "", "")
|
if err != nil {
|
||||||
if err != nil {
|
return nil
|
||||||
log.Println(err)
|
}
|
||||||
http.Error(res, err.Error(), 500)
|
book, err := app.BookFull(int64(id))
|
||||||
}
|
if err != nil {
|
||||||
model := NewBooksResultsModel(books)
|
return nil
|
||||||
// FIXME params
|
}
|
||||||
res.Header().Set("Content-Type", "application/json")
|
return app.render(res, TPL_BOOKS, &BookModel{*NewBouquinsModel(book.Title), book})
|
||||||
enc := json.NewEncoder(res)
|
}
|
||||||
err = enc.Encode(model)
|
func (app *Bouquins) BooksPage(res http.ResponseWriter, req *http.Request) {
|
||||||
if err != nil {
|
var err error
|
||||||
log.Println(err)
|
var idParam = ""
|
||||||
http.Error(res, err.Error(), 500)
|
if strings.HasPrefix(req.URL.Path, URL_BOOKS) {
|
||||||
}
|
idParam = req.URL.Path[len(URL_BOOKS):]
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// book page
|
err = errors.New("Invalid URL") // FIXME 404
|
||||||
id, err := strconv.Atoi(idParam)
|
}
|
||||||
if err != nil {
|
if len(idParam) == 0 {
|
||||||
// FIXME 404
|
err = app.BooksListPage(res, req)
|
||||||
log.Fatalln(err)
|
} else {
|
||||||
}
|
err = app.BookPage(idParam, res, req)
|
||||||
book, err := app.BookFull(int64(id))
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// FIXME 500
|
log.Println(err)
|
||||||
log.Fatalln(err)
|
http.Error(res, err.Error(), 500)
|
||||||
}
|
|
||||||
model := &BookModel{
|
|
||||||
*NewBouquinsModel(book.Title),
|
|
||||||
book,
|
|
||||||
}
|
|
||||||
app.render(res, TPL_BOOKS, model)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (app *Bouquins) AuthorsPage(res http.ResponseWriter, req *http.Request) {
|
func (app *Bouquins) AuthorsListPage(res http.ResponseWriter, req *http.Request) error {
|
||||||
if !strings.HasPrefix(req.URL.Path, URL_AUTHORS) {
|
if isJson(req) {
|
||||||
// FIXME 404
|
authors, err := app.AuthorsAdv(10, 0, "", "")
|
||||||
log.Fatalln("Invalid URL")
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return writeJson(res, NewAuthorsResultsModel(authors))
|
||||||
}
|
}
|
||||||
id, err := strconv.Atoi(req.URL.Path[len(URL_AUTHORS):])
|
return errors.New("Invalid mime")
|
||||||
|
}
|
||||||
|
func (app *Bouquins) AuthorPage(idParam string, res http.ResponseWriter, req *http.Request) error {
|
||||||
|
id, err := strconv.Atoi(idParam)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// FIXME 404
|
return err
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
}
|
||||||
author, err := app.AuthorFull(int64(id))
|
author, err := app.AuthorFull(int64(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// FIXME 500
|
return err
|
||||||
log.Fatalln(err)
|
}
|
||||||
|
return app.render(res, TPL_AUTHORS, &AuthorModel{*NewBouquinsModelJs(author.Name, "author.js"), author})
|
||||||
|
}
|
||||||
|
func (app *Bouquins) AuthorsPage(res http.ResponseWriter, req *http.Request) {
|
||||||
|
var err error
|
||||||
|
var idParam = ""
|
||||||
|
if strings.HasPrefix(req.URL.Path, URL_AUTHORS) {
|
||||||
|
idParam = req.URL.Path[len(URL_AUTHORS):]
|
||||||
|
} else {
|
||||||
|
err = errors.New("Invalid URL") // FIXME 404
|
||||||
|
}
|
||||||
|
if len(idParam) == 0 {
|
||||||
|
err = app.AuthorsListPage(res, req)
|
||||||
|
} else {
|
||||||
|
err = app.AuthorPage(idParam, res, req)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
http.Error(res, err.Error(), 500)
|
||||||
}
|
}
|
||||||
app.render(res, TPL_AUTHORS, &AuthorModel{
|
|
||||||
*NewBouquinsModelJs(author.Name, "author.js"),
|
|
||||||
author,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
func (app *Bouquins) SeriesPage(res http.ResponseWriter, req *http.Request) {
|
func (app *Bouquins) SeriesPage(res http.ResponseWriter, req *http.Request) {
|
||||||
if !strings.HasPrefix(req.URL.Path, URL_SERIES) {
|
if !strings.HasPrefix(req.URL.Path, URL_SERIES) {
|
||||||
|
@ -29,7 +29,7 @@ const (
|
|||||||
STMT_SEARCH_TERM_SERIES = " series.sort like ? "
|
STMT_SEARCH_TERM_SERIES = " series.sort like ? "
|
||||||
|
|
||||||
STMT_AUTHORS0 = `SELECT authors.id, authors.name, count(book) as count FROM authors, books_authors_link
|
STMT_AUTHORS0 = `SELECT authors.id, authors.name, count(book) as count FROM authors, books_authors_link
|
||||||
WHERE authors.id = books_authors_link.author GROUP BY author`
|
WHERE authors.id = books_authors_link.author GROUP BY author `
|
||||||
STMT_AUTHORS_SEARCH = "SELECT id, name FROM authors WHERE "
|
STMT_AUTHORS_SEARCH = "SELECT id, name FROM authors WHERE "
|
||||||
STMT_SEARCH_TERM_AUTHOR = " sort like ? "
|
STMT_SEARCH_TERM_AUTHOR = " sort like ? "
|
||||||
|
|
||||||
@ -115,6 +115,7 @@ const (
|
|||||||
SERIES QueryType = iota
|
SERIES QueryType = iota
|
||||||
SERIES_AUTHORS QueryType = iota
|
SERIES_AUTHORS QueryType = iota
|
||||||
SERIES_BOOKS QueryType = iota
|
SERIES_BOOKS QueryType = iota
|
||||||
|
AUTHORS QueryType = iota
|
||||||
AUTHOR QueryType = iota
|
AUTHOR QueryType = iota
|
||||||
AUTHOR_BOOKS QueryType = iota
|
AUTHOR_BOOKS QueryType = iota
|
||||||
AUTHOR_COAUTHORS QueryType = iota
|
AUTHOR_COAUTHORS QueryType = iota
|
||||||
@ -141,6 +142,10 @@ var QUERIES = map[Query]string{
|
|||||||
Query{SERIES, false, false}: STMT_SERIE,
|
Query{SERIES, false, false}: STMT_SERIE,
|
||||||
Query{SERIES_AUTHORS, false, false}: STMT_SERIE_AUTHORS,
|
Query{SERIES_AUTHORS, false, false}: STMT_SERIE_AUTHORS,
|
||||||
Query{SERIES_BOOKS, false, false}: STMT_SERIE_BOOKS,
|
Query{SERIES_BOOKS, false, false}: STMT_SERIE_BOOKS,
|
||||||
|
Query{AUTHORS, true, true}: STMT_AUTHORS_NAME_DESC,
|
||||||
|
Query{AUTHORS, true, false}: STMT_AUTHORS_NAME_ASC,
|
||||||
|
Query{AUTHORS, false, true}: STMT_AUTHORS_ID_DESC,
|
||||||
|
Query{AUTHORS, false, false}: STMT_AUTHORS_ID_ASC,
|
||||||
Query{AUTHOR, false, false}: STMT_AUTHOR,
|
Query{AUTHOR, false, false}: STMT_AUTHOR,
|
||||||
Query{AUTHOR_BOOKS, false, false}: STMT_AUTHOR_BOOKS,
|
Query{AUTHOR_BOOKS, false, false}: STMT_AUTHOR_BOOKS,
|
||||||
Query{AUTHOR_COAUTHORS, false, false}: STMT_AUTHOR_AUTHORS,
|
Query{AUTHOR_COAUTHORS, false, false}: STMT_AUTHOR_AUTHORS,
|
||||||
@ -149,9 +154,9 @@ var STMTS = make(map[Query]*sql.Stmt)
|
|||||||
|
|
||||||
type QueryType uint
|
type QueryType uint
|
||||||
type Query struct {
|
type Query struct {
|
||||||
Type QueryType
|
Type QueryType
|
||||||
Title bool
|
SortField bool // sort by name or title
|
||||||
Desc bool
|
Desc bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// PREPARED STATEMENTS //
|
// PREPARED STATEMENTS //
|
||||||
@ -173,7 +178,13 @@ func (app *Bouquins) PrepareAll() error {
|
|||||||
|
|
||||||
// prepared statement with sort on books
|
// prepared statement with sort on books
|
||||||
func (app *Bouquins) psSortBooks(qt QueryType, sort, order string) (*sql.Stmt, error) {
|
func (app *Bouquins) psSortBooks(qt QueryType, sort, order string) (*sql.Stmt, error) {
|
||||||
q := Query{qt, sort == "title", order == "desc"}
|
return app.psSort("title", qt, sort, order)
|
||||||
|
}
|
||||||
|
func (app *Bouquins) psSortAuthors(qt QueryType, sort, order string) (*sql.Stmt, error) {
|
||||||
|
return app.psSort("name", qt, sort, order)
|
||||||
|
}
|
||||||
|
func (app *Bouquins) psSort(sortNameField string, qt QueryType, sort, order string) (*sql.Stmt, error) {
|
||||||
|
q := Query{qt, sort == sortNameField, order == "desc"}
|
||||||
query := QUERIES[q]
|
query := QUERIES[q]
|
||||||
log.Println(query)
|
log.Println(query)
|
||||||
stmt := STMTS[q]
|
stmt := STMTS[q]
|
||||||
|
@ -6,6 +6,30 @@ import (
|
|||||||
|
|
||||||
// SUB QUERIES //
|
// SUB QUERIES //
|
||||||
|
|
||||||
|
func (app *Bouquins) queryAuthors(limit, offset int, sort, order string) ([]*AuthorAdv, error) {
|
||||||
|
authors := make([]*AuthorAdv, 0, limit)
|
||||||
|
stmt, err := app.psSortAuthors(AUTHORS, sort, order)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rows, err := stmt.Query(limit, offset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
for rows.Next() {
|
||||||
|
author := new(AuthorAdv)
|
||||||
|
if err := rows.Scan(&author.Id, &author.Name, &author.Count); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
authors = append(authors, author)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return authors, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (app *Bouquins) queryAuthorBooks(author *AuthorFull) error {
|
func (app *Bouquins) queryAuthorBooks(author *AuthorFull) error {
|
||||||
stmt, err := app.ps(AUTHOR_BOOKS)
|
stmt, err := app.ps(AUTHOR_BOOKS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -81,6 +105,17 @@ func (app *Bouquins) queryAuthor(id int64) (*AuthorFull, error) {
|
|||||||
|
|
||||||
// DB LOADS //
|
// DB LOADS //
|
||||||
|
|
||||||
|
func (app *Bouquins) AuthorsAdv(limit, offset int, sort, order string) ([]*AuthorAdv, error) {
|
||||||
|
if limit == 0 {
|
||||||
|
limit = DEF_LIM
|
||||||
|
}
|
||||||
|
authors, err := app.queryAuthors(limit, offset, sort, order)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return authors, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (app *Bouquins) AuthorFull(id int64) (*AuthorFull, error) {
|
func (app *Bouquins) AuthorFull(id int64) (*AuthorFull, error) {
|
||||||
author, err := app.queryAuthor(id)
|
author, err := app.queryAuthor(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -228,12 +228,6 @@ func (app *Bouquins) BookCount() (int64, error) {
|
|||||||
err = row.Scan(&count)
|
err = row.Scan(&count)
|
||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
func (app *Bouquins) SeriesAdv(limit, offset int, sort, order string) ([]*SeriesAdv, error) {
|
|
||||||
panic("not implemented")
|
|
||||||
}
|
|
||||||
func (app *Bouquins) AuthorsAdv(limit, offset int, sort, order string) ([]*AuthorAdv, error) {
|
|
||||||
panic("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (app *Bouquins) BookFull(id int64) (*BookFull, error) {
|
func (app *Bouquins) BookFull(id int64) (*BookFull, error) {
|
||||||
book, err := app.queryBook(id)
|
book, err := app.queryBook(id)
|
||||||
|
@ -73,3 +73,7 @@ func (app *Bouquins) SeriesFull(id int64) (*SeriesFull, error) {
|
|||||||
}
|
}
|
||||||
return series, nil
|
return series, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (app *Bouquins) SeriesAdv(limit, offset int, sort, order string) ([]*SeriesAdv, error) {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user