Merge remote-tracking branch 'adv/get-meta-data'

pull/289/head
OzzieIsaacs 7 years ago
commit bd02c92162

@ -55,6 +55,27 @@ span.glyphicon.glyphicon-tags {padding-right: 5px;color: #999;vertical-align: te
.block-label {display: block;} .block-label {display: block;}
.fake-input {position: absolute; pointer-events: none; top: 0;} .fake-input {position: absolute; pointer-events: none; top: 0;}
input.pill { position: absolute; opacity: 0; }
input.pill + label {
border: 2px solid #45b29d;
border-radius: 15px;
color: #45b29d;
cursor: pointer;
display: inline-block;
padding: 3px 15px;
user-select: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
input.pill:checked + label {
background-color: #45b29d;
border-color: #fff;
color: #fff;
}
input.pill:not(:checked) + label .glyphicon {
display: none;
}
.author-bio img {margin: 0 1em 1em 0;} .author-bio img {margin: 0 1em 1em 0;}
.author-link img {display: inline-block;max-width: 100px;} .author-link img {display: inline-block;max-width: 100px;}
@ -64,3 +85,7 @@ span.glyphicon.glyphicon-tags {padding-right: 5px;color: #999;vertical-align: te
} }
.tags_click, .serie_click, .language_click {margin-right: 5px;} .tags_click, .serie_click, .language_click {margin-right: 5px;}
#meta-info img { max-height: 150px; max-width: 100px; cursor: pointer; }
.padded-bottom { margin-bottom: 15px; }

@ -4,7 +4,7 @@
* Google Books api document: https://developers.google.com/books/docs/v1/using * Google Books api document: https://developers.google.com/books/docs/v1/using
* Douban Books api document: https://developers.douban.com/wiki/?title=book_v2 (Chinese Only) * Douban Books api document: https://developers.douban.com/wiki/?title=book_v2 (Chinese Only)
*/ */
/* global i18nMsg, tinymce */ /* global _, i18nMsg, tinymce */
var dbResults = []; var dbResults = [];
var ggResults = []; var ggResults = [];
@ -23,64 +23,93 @@ $(function () {
var showFlag = 0; var showFlag = 0;
var templates = {
bookResult: _.template(
$("#template-book-result").html()
)
};
function populateForm (book) {
tinymce.get("description").setContent(book.description);
$("#bookAuthor").val(book.authors);
$("#book_title").val(book.title);
$("#tags").val(book.tags.join(","));
$("#rating").data("rating").setValue(Math.round(book.rating));
$(".cover img").attr("src", book.cover);
$("#cover_url").val(book.cover);
}
function showResult () { function showResult () {
var book;
var i;
var bookHtml;
showFlag++; showFlag++;
if (showFlag === 1) { if (showFlag === 1) {
$("#meta-info").html("<ul id=\"book-list\" class=\"media-list\"></ul>"); $("#meta-info").html("<ul id=\"book-list\" class=\"media-list\"></ul>");
} }
if (ggDone && dbDone) { if (ggDone && dbDone) {
if (!ggResults && !dbResults) { if (!ggResults && !dbResults) {
$("#meta-info").html("<p class=\"text-danger\">"+ msg.no_result +"</p>"); $("#meta-info").html("<p class=\"text-danger\">" + msg.no_result + "</p>");
return; return;
} }
} }
if (ggDone && ggResults.length > 0) { if (ggDone && ggResults.length > 0) {
for (i = 0; i < ggResults.length; i++) { ggResults.forEach(function(result) {
book = ggResults[i]; var book = {
var bookCover; id: result.id,
if (book.volumeInfo.imageLinks) { title: result.volumeInfo.title,
bookCover = book.volumeInfo.imageLinks.thumbnail; authors: result.volumeInfo.authors || [],
} else { description: result.volumeInfo.description || "",
bookCover = "/static/generic_cover.jpg"; publisher: result.volumeInfo.publisher || "",
} publishedDate: result.volumeInfo.publishedDate || "",
bookHtml = "<li class=\"media\">" + tags: result.volumeInfo.categories || [],
"<img class=\"pull-left img-responsive\" data-toggle=\"modal\" data-target=\"#metaModal\" src=\"" + rating: result.volumeInfo.averageRating || 0,
bookCover + "\" alt=\"Cover\" style=\"width:100px;height:150px\" onclick='getMeta(\"google\"," + cover: result.volumeInfo.imageLinks ?
i + ")'>" + result.volumeInfo.imageLinks.thumbnail :
"<div class=\"media-body\">" + "/static/generic_cover.jpg",
"<h4 class=\"media-heading\"><a href=\"https://books.google.com/books?id=" + url: "https://books.google.com/books?id=" + result.id,
book.id + "\" target=\"_blank\">" + book.volumeInfo.title + "</a></h4>" + source: {
"<p>"+ msg.author +"" + book.volumeInfo.authors + "</p>" + id: "google",
"<p>"+ msg.publisher + "" + book.volumeInfo.publisher + "</p>" + description: "Google Books",
"<p>"+ msg.description + ":" + book.volumeInfo.description + "</p>" + url: "https://books.google.com/"
"<p>"+ msg.source + ":<a href=\"https://books.google.com\" target=\"_blank\">Google Books</a></p>" + }
"</div>" + };
"</li>";
$("#book-list").append(bookHtml); var $book = $(templates.bookResult(book));
} $book.find("img").on("click", function () {
populateForm(book);
});
$("#book-list").append($book);
});
ggDone = false; ggDone = false;
} }
if (dbDone && dbResults.length > 0) { if (dbDone && dbResults.length > 0) {
for (i = 0; i < dbResults.length; i++) { dbResults.forEach(function(result) {
book = dbResults[i]; var book = {
bookHtml = "<li class=\"media\">" + id: result.id,
"<img class=\"pull-left img-responsive\" data-toggle=\"modal\" data-target=\"#metaModal\" src=\"" + title: result.title,
book.image + "\" alt=\"Cover\" style=\"width:100px;height: 150px\" onclick='getMeta(\"douban\"," + authors: result.author || [],
i + ")'>" + description: result.summary,
"<div class=\"media-body\">" + publisher: result.publisher || "",
"<h4 class=\"media-heading\"><a href=\"https://book.douban.com/subject/" + publishedDate: result.pubdate || "",
book.id + "\" target=\"_blank\">" + book.title + "</a></h4>" + tags: result.tags.map(function(tag) {
"<p>" + msg.author + "" + book.author + "</p>" + return tag.title;
"<p>" + msg.publisher + "" + book.publisher + "</p>" + }),
"<p>" + msg.description + ":" + book.summary + "</p>" + rating: result.rating.average || 0,
"<p>" + msg.source + ":<a href=\"https://book.douban.com\" target=\"_blank\">Douban Books</a></p>" + cover: result.image,
"</div>" + url: "https://book.douban.com/subject/" + result.id,
"</li>"; source: {
$("#book-list").append(bookHtml); id: "douban",
} description: "Douban Books",
url: "https://book.douban.com/"
}
};
var $book = $(templates.bookResult(book));
$book.find("img").on("click", function () {
populateForm(book);
});
$("#book-list").append($book);
});
dbDone = false; dbDone = false;
} }
} }
@ -97,6 +126,7 @@ $(function () {
complete: function complete() { complete: function complete() {
ggDone = true; ggDone = true;
showResult(); showResult();
$("#show-google").trigger("change");
} }
}); });
} }
@ -111,11 +141,12 @@ $(function () {
dbResults = data.books; dbResults = data.books;
}, },
error: function error() { error: function error() {
$("#meta-info").html("<p class=\"text-danger\">"+ msg.search_error+"!</p>"); $("#meta-info").html("<p class=\"text-danger\">" + msg.search_error + "!</p>");
}, },
complete: function complete() { complete: function complete() {
dbDone = true; dbDone = true;
showResult(); showResult();
$("#show-douban").trigger("change");
} }
}); });
} }
@ -130,7 +161,8 @@ $(function () {
} }
} }
$("#do-search").click(function () { $("#meta-search").on("submit", function (e) {
e.preventDefault();
var keyword = $("#keyword").val(); var keyword = $("#keyword").val();
if (keyword) { if (keyword) {
doSearch(keyword); doSearch(keyword);
@ -146,35 +178,3 @@ $(function () {
}); });
}); });
// eslint-disable-next-line no-unused-vars
function getMeta (source, id) {
var meta;
var tags;
if (source === "google") {
meta = ggResults[id];
tinymce.get("description").setContent(meta.volumeInfo.description);
$("#bookAuthor").val(meta.volumeInfo.authors.join(" & "));
$("#book_title").val(meta.volumeInfo.title);
if (meta.volumeInfo.categories) {
tags = meta.volumeInfo.categories.join(",");
$("#tags").val(tags);
}
if (meta.volumeInfo.averageRating) {
$("#rating").val(Math.round(meta.volumeInfo.averageRating));
}
return;
}
if (source === "douban") {
meta = dbResults[id];
tinymce.get("description").setContent(meta.summary);
$("#bookAuthor").val(meta.author.join(" & "));
$("#book_title").val(meta.title);
tags = "";
for (var i = 0; i < meta.tags.length; i++) {
tags = tags + meta.tags[i].title + ",";
}
$("#tags").val(tags);
$("#rating").val(Math.round(meta.rating.average / 2));
}
}

@ -1 +1,2 @@
!function(a){"use strict";function b(a){return"[data-value"+(a?"="+a:"")+"]"}function c(a,b,c){var d=c.activeIcon,e=c.inactiveIcon;a.removeClass(b?e:d).addClass(b?d:e)}function d(b,c){var d=a.extend({},i,b.data(),c);return d.inline=""===d.inline||d.inline,d.readonly=""===d.readonly||d.readonly,d.clearable===!1?d.clearableLabel="":d.clearableLabel=d.clearable,d.clearable=""===d.clearable||d.clearable,d}function e(b,c){if(c.inline)var d=a('<span class="rating-input"></span>');else var d=a('<div class="rating-input"></div>');d.addClass(b.attr("class")),d.removeClass("rating");for(var e=c.min;e<=c.max;e++)d.append('<i class="'+c.iconLib+'" data-value="'+e+'"></i>');return c.clearable&&!c.readonly&&d.append("&nbsp;").append('<a class="'+f+'"><i class="'+c.iconLib+" "+c.clearableIcon+'"/>'+c.clearableLabel+"</a>"),d}var f="rating-clear",g="."+f,h="hidden",i={min:1,max:5,"empty-value":0,iconLib:"glyphicon",activeIcon:"glyphicon-star",inactiveIcon:"glyphicon-star-empty",clearable:!1,clearableIcon:"glyphicon-remove",clearableRemain:!1,inline:!1,readonly:!1},j=function(a,b){var c=this.$input=a;this.options=d(c,b);var f=this.$el=e(c,this.options);c.addClass(h).before(f),c.attr("type","hidden"),this.highlight(c.val())};j.VERSION="0.4.0",j.DEFAULTS=i,j.prototype={clear:function(){this.setValue(this.options["empty-value"])},setValue:function(a){this.highlight(a),this.updateInput(a)},highlight:function(a,d){var e=this.options,f=this.$el;if(a>=this.options.min&&a<=this.options.max){var i=f.find(b(a));c(i.prevAll("i").andSelf(),!0,e),c(i.nextAll("i"),!1,e)}else c(f.find(b()),!1,e);d||(this.options.clearableRemain?f.find(g).removeClass(h):a&&a!=this.options["empty-value"]?f.find(g).removeClass(h):f.find(g).addClass(h))},updateInput:function(a){var b=this.$input;b.val()!=a&&b.val(a).change()}};var k=a.fn.rating=function(c){return this.filter("input[type=number]").each(function(){var d=a(this),e="object"==typeof c&&c||{},f=new j(d,e);f.options.readonly||f.$el.on("mouseenter",b(),function(){f.highlight(a(this).data("value"),!0)}).on("mouseleave",b(),function(){f.highlight(d.val(),!0)}).on("click",b(),function(){f.setValue(a(this).data("value"))}).on("click",g,function(){f.clear()})})};k.Constructor=j,a(function(){a("input.rating[type=number]").each(function(){a(this).rating()})})}(jQuery); /** @link https://github.com/javiertoledo/bootstrap-rating-input */
!function(a){"use strict";function n(a){return"[data-value"+(a?"="+a:"")+"]"}function e(a,n,e){var i=e.activeIcon,t=e.inactiveIcon;a.removeClass(n?t:i).addClass(n?i:t)}function i(n,e){var i=a.extend({},s,n.data(),e);return i.inline=""===i.inline||i.inline,i.readonly=""===i.readonly||i.readonly,!1===i.clearable?i.clearableLabel="":i.clearableLabel=i.clearable,i.clearable=""===i.clearable||i.clearable,i}function t(n,e){if(e.inline)i=a('<span class="rating-input"></span>');else var i=a('<div class="rating-input"></div>');i.addClass(n.attr("class")),i.removeClass("rating");for(var t=e.min;t<=e.max;t++)i.append('<i class="'+e.iconLib+'" data-value="'+t+'"></i>');return e.clearable&&!e.readonly&&i.append("&nbsp;").append('<a class="'+l+'"><i class="'+e.iconLib+" "+e.clearableIcon+'"/>'+e.clearableLabel+"</a>"),i}var l="rating-clear",o="."+l,s={min:1,max:5,"empty-value":0,iconLib:"glyphicon",activeIcon:"glyphicon-star",inactiveIcon:"glyphicon-star-empty",clearable:!1,clearableIcon:"glyphicon-remove",clearableRemain:!1,inline:!1,readonly:!1},r=function(a,n){var e=this.$input=a;this.options=i(e,n);var l=this.$el=t(e,this.options);e.addClass("hidden").before(l),e.attr("type","hidden"),this.highlight(e.val())};r.VERSION="0.4.0",r.DEFAULTS=s,r.prototype={clear:function(){this.setValue(this.options["empty-value"])},setValue:function(a){this.highlight(a),this.updateInput(a)},highlight:function(a,i){var t=this.options,l=this.$el;if(a>=this.options.min&&a<=this.options.max){var s=l.find(n(a));e(s.prevAll("i").addBack(),!0,t),e(s.nextAll("i"),!1,t)}else e(l.find(n()),!1,t);i||(this.options.clearableRemain?l.find(o).removeClass("hidden"):a&&a!=this.options["empty-value"]?l.find(o).removeClass("hidden"):l.find(o).addClass("hidden"))},updateInput:function(a){var n=this.$input;n.val()!=a&&n.val(a).change()}},(a.fn.rating=function(e){return this.filter("input[type=number]").each(function(){var i=a(this),t=new r(i,"object"==typeof e&&e||{});t.options.readonly||(t.$el.on("mouseenter",n(),function(){t.highlight(a(this).data("value"),!0)}).on("mouseleave",n(),function(){t.highlight(i.val(),!0)}).on("click",n(),function(){t.setValue(a(this).data("value"))}).on("click",o,function(){t.clear()}),i.data("rating",t))})}).Constructor=r,a(function(){a("input.rating[type=number]").each(function(){a(this).rating()})})}(jQuery);

@ -154,23 +154,36 @@
{% endif %} {% endif %}
<div class="modal fade" id="metaModal" tabindex="-1" role="dialog" aria-labelledby="metaModalLabel"> <div class="modal fade" id="metaModal" tabindex="-1" role="dialog" aria-labelledby="metaModalLabel">
<div class="modal-dialog" role="document"> <div class="modal-dialog modal-lg" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="metaModalLabel">{{_('Get metadata')}}</h4> <h4 class="modal-title" id="metaModalLabel">{{_('Get metadata')}}</h4>
<form class="form-inline"> <form class="padded-bottom" id="meta-search">
<div class="form-group"> <div class="input-group">
<label class="sr-only" for="keyword">{{_('Keyword')}}</label> <label class="sr-only" for="keyword">{{_('Keyword')}}</label>
<input type="text" class="form-control" id="keyword" placeholder="{{_(" Search keyword ")}}"> <input type="text" class="form-control" id="keyword" name="keyword" placeholder="{{_(" Search keyword ")}}">
<span class="input-group-btn">
<button type="submit" class="btn btn-primary" id="do-search">{{_("Go!")}}</button>
</span>
</div> </div>
<button type="button" class="btn btn-default" id="do-search">{{_("Go!")}}</button>
<span>{{_('Click the cover to load metadata to the form')}}</span>
</form> </form>
<div>{{_('Click the cover to load metadata to the form')}}</div>
</div>
<div class="modal-body">
<div class="text-center padded-bottom">
<input type="checkbox" id="show-douban" class="pill" data-control="douban" checked>
<label for="show-douban">Douban <span class="glyphicon glyphicon-ok"></span></label>
<input type="checkbox" id="show-google" class="pill" data-control="google" checked>
<label for="show-google">Google <span class="glyphicon glyphicon-ok"></span></label>
</div> </div>
<div class="modal-body" id="meta-info">
<div id="meta-info">
{{_("Loading...")}} {{_("Loading...")}}
</div> </div>
<ul id="book-list" class="media-list"></ul>
</div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{_('Close')}}</button> <button type="button" class="btn btn-default" data-dismiss="modal">{{_('Close')}}</button>
</div> </div>
@ -180,6 +193,31 @@
{% endblock %} {% endblock %}
{% block js %} {% block js %}
<script type="text/template" id="template-book-result">
<li class="media" data-related="<%= source.id %>">
<img class="pull-left img-responsive"
data-toggle="modal"
data-target="#metaModal"
src="<%= cover %>"
alt="Cover"
>
<div class="media-body">
<h4 class="media-heading">
<a href="<%= url %>" target="_blank" rel="noopener"><%= title %></a>
</h4>
<p>{{_('Author')}}<%= authors.join(" & ") %></p>
<% if (publisher) { %>
<p>{{_('Publisher')}}<%= publisher %></p>
<% } %>
<% if (description) { %>
<p>{{_('Description')}}: <%= description %></p>
<% } %>
<p>{{_('Source')}}:
<a href="<%= source.url %>" target="_blank" rel="noopener"><%= source.description %></a>
</p>
</div>
</li>
</script>
<script> <script>
var i18nMsg = { var i18nMsg = {
'loading': {{_('Loading...')|safe|tojson}}, 'loading': {{_('Loading...')|safe|tojson}},

Loading…
Cancel
Save