Paginate
This commit is contained in:
parent
c8fc680331
commit
e724ac4e5a
@ -68,33 +68,63 @@ Vue.component('result-cell', {
|
||||
});
|
||||
Vue.component('paginate', {
|
||||
template: '#paginate-template',
|
||||
props: ['page'],
|
||||
props: ['page','more'],
|
||||
methods: {
|
||||
prevPage: function() {
|
||||
if (this.page > 1) this.$emit('prev');
|
||||
},
|
||||
nextPage: function() {
|
||||
if (this.more) this.$emit('next');
|
||||
}
|
||||
}
|
||||
});
|
||||
var index = new Vue({
|
||||
el: '#index',
|
||||
data: {
|
||||
url: '',
|
||||
page: 0,
|
||||
perpage: 20,
|
||||
more: false,
|
||||
sort_by: null,
|
||||
order_desc: false,
|
||||
cols: [],
|
||||
results: []
|
||||
},
|
||||
methods: {
|
||||
updatePage: function(p) {
|
||||
this.page += p;
|
||||
this.updateResults();
|
||||
},
|
||||
order: function(query) {
|
||||
if (this.order_desc)
|
||||
return query + '&order=desc';
|
||||
return query;
|
||||
},
|
||||
sort: function(query) {
|
||||
if (this.sort_by)
|
||||
return query + '&sort=' + this.sort_by;
|
||||
return query;
|
||||
},
|
||||
paginate: function(query) {
|
||||
return query + '?page=' + this.page + '&perpage=' + this.perpage;
|
||||
},
|
||||
params: function(url) {
|
||||
return this.order(this.sort(this.paginate(url)));
|
||||
},
|
||||
updateResults: function() {
|
||||
this.sendQuery(this.params(this.url), this.stdError, this.loadResults);
|
||||
},
|
||||
showSeries: function() {
|
||||
this.sendQuery('/series/', this.stdError, this.loadResults);
|
||||
this.url = '/series/';
|
||||
this.updateResults();
|
||||
},
|
||||
showAuthors: function() {
|
||||
this.sendQuery('/authors/', this.stdError, this.loadResults);
|
||||
this.url = '/authors/';
|
||||
this.updateResults();
|
||||
},
|
||||
showBooks: function() {
|
||||
this.sendQuery('/books/', this.stdError, this.loadResults);
|
||||
this.url = '/books/';
|
||||
this.updateResults();
|
||||
},
|
||||
loadCols: function(type) {
|
||||
switch (type) {
|
||||
@ -122,10 +152,14 @@ var index = new Vue({
|
||||
},
|
||||
loadResults(resp) {
|
||||
this.results = [];
|
||||
this.page = 1;
|
||||
this.more = resp.more;
|
||||
this.loadCols(resp.type);
|
||||
if (resp.results)
|
||||
if (resp.results) {
|
||||
this.results = resp.results;
|
||||
if (this.page == 0) this.page = 1;
|
||||
} else {
|
||||
this.page = 0;
|
||||
}
|
||||
},
|
||||
sendQuery: function(url, error, success) {
|
||||
var xmh = new XMLHttpRequest();
|
||||
|
@ -21,11 +21,11 @@ const (
|
||||
TPL_SERIES = "series.html"
|
||||
TPL_INDEX = "index.html"
|
||||
|
||||
PARAM_LIST = "list"
|
||||
PARAM_ORDER = "order"
|
||||
PARAM_SORT = "sort"
|
||||
PARAM_LIMIT = "limit"
|
||||
PARAM_OFFSET = "offset"
|
||||
PARAM_LIST = "list"
|
||||
PARAM_ORDER = "order"
|
||||
PARAM_SORT = "sort"
|
||||
PARAM_PAGE = "page"
|
||||
PARAM_PERPAGE = "perpage"
|
||||
|
||||
LIST_AUTHORS = "authors"
|
||||
LIST_SERIES = "series"
|
||||
@ -161,14 +161,15 @@ func NewIndexModel(title, js string, count int64) *IndexModel {
|
||||
|
||||
type ResultsModel struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
More bool `json:"more"`
|
||||
}
|
||||
type BooksResultsModel struct {
|
||||
ResultsModel
|
||||
Results []*BookAdv `json:"results,omitempty"`
|
||||
}
|
||||
|
||||
func NewBooksResultsModel(books []*BookAdv) *BooksResultsModel {
|
||||
return &BooksResultsModel{ResultsModel{"books"}, books}
|
||||
func NewBooksResultsModel(books []*BookAdv, more bool) *BooksResultsModel {
|
||||
return &BooksResultsModel{ResultsModel{"books", more}, books}
|
||||
}
|
||||
|
||||
type AuthorsResultsModel struct {
|
||||
@ -176,8 +177,8 @@ type AuthorsResultsModel struct {
|
||||
Results []*AuthorAdv `json:"results,omitempty"`
|
||||
}
|
||||
|
||||
func NewAuthorsResultsModel(authors []*AuthorAdv) *AuthorsResultsModel {
|
||||
return &AuthorsResultsModel{ResultsModel{"authors"}, authors}
|
||||
func NewAuthorsResultsModel(authors []*AuthorAdv, more bool) *AuthorsResultsModel {
|
||||
return &AuthorsResultsModel{ResultsModel{"authors", more}, authors}
|
||||
}
|
||||
|
||||
type SeriesResultsModel struct {
|
||||
@ -185,8 +186,8 @@ type SeriesResultsModel struct {
|
||||
Results []*SeriesAdv `json:"results,omitempty"`
|
||||
}
|
||||
|
||||
func NewSeriesResultsModel(series []*SeriesAdv) *SeriesResultsModel {
|
||||
return &SeriesResultsModel{ResultsModel{"series"}, series}
|
||||
func NewSeriesResultsModel(series []*SeriesAdv, more bool) *SeriesResultsModel {
|
||||
return &SeriesResultsModel{ResultsModel{"series", more}, series}
|
||||
}
|
||||
|
||||
type BookModel struct {
|
||||
@ -249,6 +250,22 @@ func paramOrder(req *http.Request) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// return limit, offset, sort, order
|
||||
func paramPaginate(req *http.Request) (int, int, string, string) {
|
||||
page, perpage := paramInt(PARAM_PAGE, req), paramInt(PARAM_PERPAGE, req)
|
||||
limit := perpage
|
||||
if perpage == 0 {
|
||||
limit = DEF_LIM
|
||||
}
|
||||
offset := perpage * (page - 1)
|
||||
if offset < 0 {
|
||||
offset = 0
|
||||
}
|
||||
sort := req.URL.Query().Get(PARAM_SORT)
|
||||
order := paramOrder(req)
|
||||
return limit, offset, sort, order
|
||||
}
|
||||
|
||||
// ROUTES //
|
||||
|
||||
func (app *Bouquins) IndexPage(res http.ResponseWriter, req *http.Request) {
|
||||
@ -257,23 +274,6 @@ func (app *Bouquins) IndexPage(res http.ResponseWriter, req *http.Request) {
|
||||
log.Print(err)
|
||||
}
|
||||
model := NewIndexModel("", "index.js", count)
|
||||
/*
|
||||
order, sort := paramOrder(req), req.URL.Query().Get(PARAM_SORT)
|
||||
limit, offset := paramInt(PARAM_LIMIT, req), paramInt(PARAM_OFFSET, req)
|
||||
switch req.URL.Query().Get(PARAM_LIST) {
|
||||
case LIST_AUTHORS:
|
||||
model.Authors, err = app.AuthorsAdv(limit, offset, sort, order)
|
||||
case LIST_SERIES:
|
||||
model.Series, err = app.SeriesAdv(limit, offset, sort, order)
|
||||
case LIST_BOOKS:
|
||||
fallthrough
|
||||
default:
|
||||
model.Books, err = app.BooksAdv(limit, offset, sort, order)
|
||||
}
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
*/
|
||||
if isJson(req) {
|
||||
err := writeJson(res, model)
|
||||
if err != nil {
|
||||
@ -286,11 +286,11 @@ func (app *Bouquins) IndexPage(res http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
func (app *Bouquins) BooksListPage(res http.ResponseWriter, req *http.Request) error {
|
||||
if isJson(req) {
|
||||
books, err := app.BooksAdv(10, 0, "", "")
|
||||
books, more, err := app.BooksAdv(paramPaginate(req))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeJson(res, NewBooksResultsModel(books))
|
||||
return writeJson(res, NewBooksResultsModel(books, more))
|
||||
}
|
||||
return errors.New("Invalid mime")
|
||||
}
|
||||
@ -325,11 +325,11 @@ func (app *Bouquins) BooksPage(res http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
func (app *Bouquins) AuthorsListPage(res http.ResponseWriter, req *http.Request) error {
|
||||
if isJson(req) {
|
||||
authors, err := app.AuthorsAdv(10, 0, "", "")
|
||||
authors, more, err := app.AuthorsAdv(paramPaginate(req))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeJson(res, NewAuthorsResultsModel(authors))
|
||||
return writeJson(res, NewAuthorsResultsModel(authors, more))
|
||||
}
|
||||
return errors.New("Invalid mime")
|
||||
}
|
||||
@ -364,11 +364,11 @@ func (app *Bouquins) AuthorsPage(res http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
func (app *Bouquins) SeriesListPage(res http.ResponseWriter, req *http.Request) error {
|
||||
if isJson(req) {
|
||||
series, err := app.SeriesAdv(10, 0, "", "")
|
||||
series, more, err := app.SeriesAdv(paramPaginate(req))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeJson(res, NewSeriesResultsModel(series))
|
||||
return writeJson(res, NewSeriesResultsModel(series, more))
|
||||
}
|
||||
return errors.New("Invalid mime")
|
||||
}
|
||||
|
@ -6,28 +6,33 @@ import (
|
||||
|
||||
// SUB QUERIES //
|
||||
|
||||
func (app *Bouquins) queryAuthors(limit, offset int, sort, order string) ([]*AuthorAdv, error) {
|
||||
func (app *Bouquins) queryAuthors(limit, offset int, sort, order string) ([]*AuthorAdv, bool, error) {
|
||||
authors := make([]*AuthorAdv, 0, limit)
|
||||
stmt, err := app.psSortAuthors(AUTHORS, sort, order)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
rows, err := stmt.Query(limit, offset)
|
||||
rows, err := stmt.Query(limit+1, offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
defer rows.Close()
|
||||
more := false
|
||||
for rows.Next() {
|
||||
author := new(AuthorAdv)
|
||||
if err := rows.Scan(&author.Id, &author.Name, &author.Count); err != nil {
|
||||
return nil, err
|
||||
if len(authors) == limit {
|
||||
more = true
|
||||
} else {
|
||||
author := new(AuthorAdv)
|
||||
if err := rows.Scan(&author.Id, &author.Name, &author.Count); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
authors = append(authors, author)
|
||||
}
|
||||
authors = append(authors, author)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
return authors, nil
|
||||
return authors, more, nil
|
||||
}
|
||||
|
||||
func (app *Bouquins) queryAuthorBooks(author *AuthorFull) error {
|
||||
@ -105,15 +110,12 @@ func (app *Bouquins) queryAuthor(id int64) (*AuthorFull, error) {
|
||||
|
||||
// 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)
|
||||
func (app *Bouquins) AuthorsAdv(limit, offset int, sort, order string) ([]*AuthorAdv, bool, error) {
|
||||
authors, more, err := app.queryAuthors(limit, offset, sort, order)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
return authors, nil
|
||||
return authors, more, nil
|
||||
}
|
||||
|
||||
func (app *Bouquins) AuthorFull(id int64) (*AuthorFull, error) {
|
||||
|
@ -12,36 +12,41 @@ func assignAuthorsTagsBooks(books []*BookAdv, authors map[int64][]*Author, tags
|
||||
|
||||
// SUB QUERIES //
|
||||
|
||||
func (app *Bouquins) queryBooks(limit, offset int, sort, order string) ([]*BookAdv, error) {
|
||||
func (app *Bouquins) queryBooks(limit, offset int, sort, order string) ([]*BookAdv, bool, error) {
|
||||
books := make([]*BookAdv, 0, limit)
|
||||
stmt, err := app.psSortBooks(BOOKS, sort, order)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
rows, err := stmt.Query(limit, offset)
|
||||
rows, err := stmt.Query(limit+1, offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
defer rows.Close()
|
||||
more := false
|
||||
for rows.Next() {
|
||||
book := new(BookAdv)
|
||||
var series_name sql.NullString
|
||||
var series_id sql.NullInt64
|
||||
if err := rows.Scan(&book.Id, &book.Title, &book.SeriesIndex, &series_name, &series_id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if series_name.Valid && series_id.Valid {
|
||||
book.Series = &Series{
|
||||
series_id.Int64,
|
||||
series_name.String,
|
||||
if len(books) == limit {
|
||||
more = true
|
||||
} else {
|
||||
book := new(BookAdv)
|
||||
var series_name sql.NullString
|
||||
var series_id sql.NullInt64
|
||||
if err := rows.Scan(&book.Id, &book.Title, &book.SeriesIndex, &series_name, &series_id); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if series_name.Valid && series_id.Valid {
|
||||
book.Series = &Series{
|
||||
series_id.Int64,
|
||||
series_name.String,
|
||||
}
|
||||
}
|
||||
books = append(books, book)
|
||||
}
|
||||
books = append(books, book)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
return books, nil
|
||||
return books, more, nil
|
||||
}
|
||||
|
||||
func (app *Bouquins) queryBooksAuthors(limit, offset int, sort, order string) (map[int64][]*Author, error) {
|
||||
@ -249,22 +254,19 @@ func (app *Bouquins) BookFull(id int64) (*BookFull, error) {
|
||||
return book, nil
|
||||
}
|
||||
|
||||
func (app *Bouquins) BooksAdv(limit, offset int, sort, order string) ([]*BookAdv, error) {
|
||||
if limit == 0 {
|
||||
limit = DEF_LIM
|
||||
}
|
||||
books, err := app.queryBooks(limit, offset, sort, order)
|
||||
func (app *Bouquins) BooksAdv(limit, offset int, sort, order string) ([]*BookAdv, bool, error) {
|
||||
books, more, err := app.queryBooks(limit, offset, sort, order)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
authors, err := app.queryBooksAuthors(limit, offset, sort, order)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
tags, err := app.queryBooksTags(limit, offset, sort, order)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
assignAuthorsTagsBooks(books, authors, tags)
|
||||
return books, nil
|
||||
return books, more, nil
|
||||
}
|
||||
|
@ -10,28 +10,33 @@ func assignAuthorsSeries(series []*SeriesAdv, authors map[int64][]*Author) {
|
||||
|
||||
// SUB QUERIES //
|
||||
|
||||
func (app *Bouquins) querySeriesList(limit, offset int, sort, order string) ([]*SeriesAdv, error) {
|
||||
func (app *Bouquins) querySeriesList(limit, offset int, sort, order string) ([]*SeriesAdv, bool, error) {
|
||||
series := make([]*SeriesAdv, 0, limit)
|
||||
stmt, err := app.psSortSeries(SERIES, sort, order)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
rows, err := stmt.Query(limit, offset)
|
||||
rows, err := stmt.Query(limit+1, offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
defer rows.Close()
|
||||
more := false
|
||||
for rows.Next() {
|
||||
serie := new(SeriesAdv)
|
||||
if err := rows.Scan(&serie.Id, &serie.Name, &serie.Count); err != nil {
|
||||
return nil, err
|
||||
if len(series) == limit {
|
||||
more = true
|
||||
} else {
|
||||
serie := new(SeriesAdv)
|
||||
if err := rows.Scan(&serie.Id, &serie.Name, &serie.Count); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
series = append(series, serie)
|
||||
}
|
||||
series = append(series, serie)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
return series, nil
|
||||
return series, more, nil
|
||||
}
|
||||
func (app *Bouquins) querySeriesListAuthors(limit, offset int, sort, order string) (map[int64][]*Author, error) {
|
||||
authors := make(map[int64][]*Author)
|
||||
@ -134,18 +139,15 @@ func (app *Bouquins) SeriesFull(id int64) (*SeriesFull, error) {
|
||||
return series, nil
|
||||
}
|
||||
|
||||
func (app *Bouquins) SeriesAdv(limit, offset int, sort, order string) ([]*SeriesAdv, error) {
|
||||
if limit == 0 {
|
||||
limit = DEF_LIM
|
||||
}
|
||||
series, err := app.querySeriesList(limit, offset, sort, order)
|
||||
func (app *Bouquins) SeriesAdv(limit, offset int, sort, order string) ([]*SeriesAdv, bool, error) {
|
||||
series, more, err := app.querySeriesList(limit, offset, sort, order)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
authors, err := app.querySeriesListAuthors(limit, offset, sort, order)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
assignAuthorsSeries(series, authors)
|
||||
return series, nil
|
||||
return series, more, nil
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
<button class="btn btn-primary" type="button" @click="showSeries">Series</button>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<paginate :page="page"></paginate>
|
||||
<paginate v-on:next="updatePage(1)" v-on:prev="updatePage(-1)" :page="page" :more="more"></paginate>
|
||||
<results :results="results" :cols="cols" :sort_by="sort_by" :order_desc="order_desc"></results>
|
||||
<paginate :page="page"></paginate>
|
||||
</div>
|
||||
@ -35,7 +35,7 @@
|
||||
<nav aria-label="Pages" v-if="page > 0">
|
||||
<ul class="pager">
|
||||
<li class="previous" v-bind:class="{ disabled: page <= 1 }"><a href="#" @click="prevPage"><span aria-hidden="true">←</span> Précédents</a></li>
|
||||
<li class="next"><a href="#" @click="nextPage">Suivants <span aria-hidden="true">→</span></a></li>
|
||||
<li class="next" v-bind:class="{ disabled: !more }"><a href="#" @click="nextPage">Suivants <span aria-hidden="true">→</span></a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue
Block a user