Vue components books list
This commit is contained in:
parent
a76dd7275e
commit
2f1e2a70fd
@ -1,11 +1,62 @@
|
|||||||
Vue.component('results', {
|
Vue.component('results', {
|
||||||
template: '#results-template',
|
template: '#results-template',
|
||||||
props: ['results', 'cols'],
|
props: ['results', 'cols','sort_by','order_desc'],
|
||||||
methods: {
|
methods: {
|
||||||
sortBy: function(col) {
|
sortBy: function(col) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Vue.component('result-cell', {
|
||||||
|
render: function(h) {
|
||||||
|
return h('td', this.cellContent(h));
|
||||||
|
},
|
||||||
|
props: ['item', 'col'],
|
||||||
|
methods: {
|
||||||
|
bookUrl: function(id) {
|
||||||
|
return '/books/' + id;
|
||||||
|
},
|
||||||
|
authorUrl: function(id) {
|
||||||
|
return '/authors/' + id;
|
||||||
|
},
|
||||||
|
seriesUrl: function(id) {
|
||||||
|
return '/series/' + id;
|
||||||
|
},
|
||||||
|
link: function(h, icon, text, url) {
|
||||||
|
return [
|
||||||
|
h('span',{ attrs: { class: 'glyphicon glyphicon-'+icon } },''),
|
||||||
|
' ',
|
||||||
|
h('a', { attrs: { href: url } }, text)
|
||||||
|
];
|
||||||
|
},
|
||||||
|
badge: function(h, num) {
|
||||||
|
return h('span', { attrs: { class: 'badge' } }, num);
|
||||||
|
},
|
||||||
|
cellContent: function(h) {
|
||||||
|
switch (this.col.id) {
|
||||||
|
case 'title':
|
||||||
|
return this.link(h, 'book', this.item.title, this.bookUrl(this.item.id));
|
||||||
|
case 'authors':
|
||||||
|
var elts = [];
|
||||||
|
var authors = this.item.authors;
|
||||||
|
for (i=0;i<authors.length;i++) {
|
||||||
|
elts[i] = this.link(h, 'user', authors[i].name, this.authorUrl(authors[i].id));
|
||||||
|
}
|
||||||
|
return elts;
|
||||||
|
case 'series':
|
||||||
|
var series = this.item.series;
|
||||||
|
if (series) {
|
||||||
|
return [
|
||||||
|
this.link(h, 'list', series.name, this.seriesUrl(series.id)),
|
||||||
|
h('span', { attrs: { class: 'badge' } }, this.item.series_idx)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
Vue.component('paginate', {
|
Vue.component('paginate', {
|
||||||
template: '#paginate-template',
|
template: '#paginate-template',
|
||||||
props: ['page'],
|
props: ['page'],
|
||||||
@ -19,12 +70,12 @@ Vue.component('paginate', {
|
|||||||
var index = new Vue({
|
var index = new Vue({
|
||||||
el: '#index',
|
el: '#index',
|
||||||
data: {
|
data: {
|
||||||
page: 1,
|
page: 0,
|
||||||
perpage: 20,
|
perpage: 20,
|
||||||
sort_by: null,
|
sort_by: null,
|
||||||
order_desc: false,
|
order_desc: false,
|
||||||
cols: [{name:'test'}, {name:'test2'}],
|
cols: [],
|
||||||
results: [{}]
|
results: []
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
showSeries: function() {
|
showSeries: function() {
|
||||||
@ -34,7 +85,65 @@ var index = new Vue({
|
|||||||
console.log("Authors");
|
console.log("Authors");
|
||||||
},
|
},
|
||||||
showBooks: function() {
|
showBooks: function() {
|
||||||
console.log("Books");
|
this.sendQuery('/books/', this.stdError, this.loadResults);
|
||||||
|
},
|
||||||
|
loadCols: function(type) {
|
||||||
|
switch (type) {
|
||||||
|
case 'books':
|
||||||
|
this.cols = [
|
||||||
|
{ id: 'title', name: 'Titre', sortable: true },
|
||||||
|
{ id: 'authors', name: 'Auteur(s)' },
|
||||||
|
{ id: 'series', name: 'Serie' }
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case 'series':
|
||||||
|
this.cols = [
|
||||||
|
{ name: 'Nom', sortId: 'name' },
|
||||||
|
{ name: 'Livre(s)' },
|
||||||
|
{ name: 'Auteur(s)' }
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case 'authors':
|
||||||
|
this.cols = [
|
||||||
|
{ name: 'Nom', sortId: 'name' },
|
||||||
|
{ name: 'Livre(s)' }
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
loadResults(resp) {
|
||||||
|
this.results = [];
|
||||||
|
this.page = 1;
|
||||||
|
this.loadCols(resp.type);
|
||||||
|
if (resp.results)
|
||||||
|
this.results = resp.results;
|
||||||
|
},
|
||||||
|
sendQuery: function(url, error, success) {
|
||||||
|
var xmh = new XMLHttpRequest();
|
||||||
|
var v;
|
||||||
|
xmh.onreadystatechange = function() {
|
||||||
|
v = xmh.responseText;
|
||||||
|
if (xmh.readyState === 4 && xmh.status === 200) {
|
||||||
|
var res;
|
||||||
|
try {
|
||||||
|
res = JSON.parse(v);
|
||||||
|
} catch (err) {
|
||||||
|
if (null !== error)
|
||||||
|
error(err.name, err.message);
|
||||||
|
}
|
||||||
|
if (null !== success)
|
||||||
|
success(res);
|
||||||
|
} else if (xmh.readyState === 4) {
|
||||||
|
if (null !== error)
|
||||||
|
error(xmh.status, v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xmh.open('GET', url, true);
|
||||||
|
xmh.setRequestHeader('Accept','application/json');
|
||||||
|
xmh.send(null);
|
||||||
|
},
|
||||||
|
stdError: function(code, resp) {
|
||||||
|
console.log('ERROR ' + code + ': ' + resp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -147,10 +147,7 @@ func NewBouquinsModelJs(title, js string) *BouquinsModel {
|
|||||||
|
|
||||||
type IndexModel struct {
|
type IndexModel struct {
|
||||||
BouquinsModel
|
BouquinsModel
|
||||||
BooksCount int64 `json:"count"`
|
BooksCount int64 `json:"count"`
|
||||||
Books []*BookAdv `json:"books,omitempty"`
|
|
||||||
Series []*SeriesAdv `json:"series,omitempty"`
|
|
||||||
Authors []*AuthorAdv `json:"authors,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor IndexModel
|
// Constructor IndexModel
|
||||||
@ -158,12 +155,25 @@ func NewIndexModel(title, js string, count int64) *IndexModel {
|
|||||||
return &IndexModel{
|
return &IndexModel{
|
||||||
*NewBouquinsModelJs(title, js),
|
*NewBouquinsModelJs(title, js),
|
||||||
count,
|
count,
|
||||||
nil,
|
|
||||||
nil,
|
|
||||||
nil,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BooksResultsModel struct {
|
||||||
|
Results []*BookAdv `json:"results,omitempty"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBooksResultsModel(books []*BookAdv) *BooksResultsModel {
|
||||||
|
return &BooksResultsModel{
|
||||||
|
books,
|
||||||
|
"books",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Books []*BookAdv `json:"books,omitempty"`
|
||||||
|
// Series []*SeriesAdv `json:"series,omitempty"`
|
||||||
|
// Authors []*AuthorAdv `json:"authors,omitempty"`
|
||||||
|
|
||||||
type BookModel struct {
|
type BookModel struct {
|
||||||
BouquinsModel
|
BouquinsModel
|
||||||
*BookFull
|
*BookFull
|
||||||
@ -227,21 +237,23 @@ func (app *Bouquins) IndexPage(res http.ResponseWriter, req *http.Request) {
|
|||||||
log.Print(err)
|
log.Print(err)
|
||||||
}
|
}
|
||||||
model := NewIndexModel("", "index.js", count)
|
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)
|
order, sort := paramOrder(req), req.URL.Query().Get(PARAM_SORT)
|
||||||
switch req.URL.Query().Get(PARAM_LIST) {
|
limit, offset := paramInt(PARAM_LIMIT, req), paramInt(PARAM_OFFSET, req)
|
||||||
case LIST_AUTHORS:
|
switch req.URL.Query().Get(PARAM_LIST) {
|
||||||
model.Authors, err = app.AuthorsAdv(limit, offset, sort, order)
|
case LIST_AUTHORS:
|
||||||
case LIST_SERIES:
|
model.Authors, err = app.AuthorsAdv(limit, offset, sort, order)
|
||||||
model.Series, err = app.SeriesAdv(limit, offset, sort, order)
|
case LIST_SERIES:
|
||||||
case LIST_BOOKS:
|
model.Series, err = app.SeriesAdv(limit, offset, sort, order)
|
||||||
fallthrough
|
case LIST_BOOKS:
|
||||||
default:
|
fallthrough
|
||||||
model.Books, err = app.BooksAdv(limit, offset, sort, order)
|
default:
|
||||||
}
|
model.Books, err = app.BooksAdv(limit, offset, sort, order)
|
||||||
if err != nil {
|
}
|
||||||
log.Print(err)
|
if err != nil {
|
||||||
}
|
log.Print(err)
|
||||||
|
}
|
||||||
|
*/
|
||||||
if req.Header.Get("Accept") == "application/json" {
|
if req.Header.Get("Accept") == "application/json" {
|
||||||
res.Header().Set("Content-Type", "application/json")
|
res.Header().Set("Content-Type", "application/json")
|
||||||
enc := json.NewEncoder(res)
|
enc := json.NewEncoder(res)
|
||||||
@ -263,9 +275,13 @@ func (app *Bouquins) BooksPage(res http.ResponseWriter, req *http.Request) {
|
|||||||
if len(idParam) == 0 {
|
if len(idParam) == 0 {
|
||||||
// books list
|
// books list
|
||||||
if req.Header.Get("Accept") == "application/json" {
|
if req.Header.Get("Accept") == "application/json" {
|
||||||
model := NewIndexModel("", "", 0) // FIXME model books/paginate
|
books, err := app.BooksAdv(10, 0, "", "")
|
||||||
var err error
|
if err != nil {
|
||||||
model.Books, err = app.BooksAdv(10, 0, "", "") // FIXME params
|
log.Println(err)
|
||||||
|
http.Error(res, err.Error(), 500)
|
||||||
|
}
|
||||||
|
model := NewBooksResultsModel(books)
|
||||||
|
// FIXME params
|
||||||
res.Header().Set("Content-Type", "application/json")
|
res.Header().Set("Content-Type", "application/json")
|
||||||
enc := json.NewEncoder(res)
|
enc := json.NewEncoder(res)
|
||||||
err = enc.Encode(model)
|
err = enc.Encode(model)
|
||||||
|
@ -9,28 +9,30 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<paginate :page="page"></paginate>
|
<paginate :page="page"></paginate>
|
||||||
<results :results="results" :cols="cols"></results>
|
<results :results="results" :cols="cols" :sort_by="sort_by" :order_desc="order_desc"></results>
|
||||||
<paginate :page="page"></paginate>
|
<paginate :page="page"></paginate>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/x-template" id="results-template">
|
<script type="text/x-template" id="results-template">
|
||||||
<table class="table table-striped" v-if="results.length > 0">
|
<table class="table table-striped" v-if="results.length > 0">
|
||||||
<tr>
|
<tbody>
|
||||||
<th v-for="col in cols">
|
<tr>
|
||||||
<template v-if="col.sortable">
|
<th v-for="col in cols">
|
||||||
<a href="#" @click="sortBy(col.id)">{{ "{{" }}col.name{{ "}}" }}</a>
|
<template v-if="col.sortable">
|
||||||
<span v-if="sort_by == col.id" :class="['glyphicon', { 'glyphicon-chevron-up': order_desc , 'glyphicon-chevron-down': !order_desc}]"></span>
|
<a href="#" @click="sortBy(col.sortId)">{{ "{{" }}col.name{{ "}}" }}</a>
|
||||||
</template>
|
<span v-if="sort_by == col.id" :class="['glyphicon', { 'glyphicon-chevron-up': order_desc , 'glyphicon-chevron-down': !order_desc}]"></span>
|
||||||
<template v-else>{{ "{{" }}col.name{{ "}}" }}</template>
|
</template>
|
||||||
</th>
|
<template v-else>{{ "{{" }}col.name{{ "}}" }}</template>
|
||||||
</tr>
|
</th>
|
||||||
<tr v-for="item in results">
|
</tr>
|
||||||
<td v-for="col in cols">test</td>
|
<tr v-for="item in results">
|
||||||
</tr>
|
<td is="result-cell" :col="col" :item="item" v-for="col in cols"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</script>
|
</script>
|
||||||
<script type="text/x-template" id="paginate-template">
|
<script type="text/x-template" id="paginate-template">
|
||||||
<nav aria-label="Pages">
|
<nav aria-label="Pages" v-if="page > 0">
|
||||||
<ul class="pager">
|
<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="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"><a href="#" @click="nextPage">Suivants <span aria-hidden="true">→</span></a></li>
|
||||||
|
Loading…
Reference in New Issue
Block a user