Update to ES5 standards

Also fix ESLint issues
pull/255/head
Jonathan Rehm 7 years ago
parent 29e2658e53
commit 8171943b8e

@ -1,7 +1,6 @@
{ {
"env": { "env": {
"browser": true, "browser": true,
"es6": true,
"jquery": true "jquery": true
}, },
"globals": { "globals": {
@ -83,6 +82,8 @@
2, 2,
"always" "always"
], ],
"space-before-blocks": 2,
"space-infix-ops": 2,
"space-unary-ops": 2, "space-unary-ops": 2,
"use-isnan": 2, "use-isnan": 2,
"valid-typeof": 2, "valid-typeof": 2,

@ -1,4 +1,6 @@
$( document ).ready(function() { /* global _ */
$(function() {
$("#have_read_form").ajaxForm(); $("#have_read_form").ajaxForm();
}); });
@ -6,34 +8,51 @@ $("#have_read_cb").on("change", function() {
$(this).closest("form").submit(); $(this).closest("form").submit();
}); });
$("#shelf-actions").on("click", "[data-shelf-action]", function (e) { (function() {
var templates = {
add: _.template(
$("#template-shelf-add").html()
),
remove: _.template(
$("#template-shelf-remove").html()
)
};
$("#shelf-actions").on("click", "[data-shelf-action]", function (e) {
e.preventDefault(); e.preventDefault();
$.get(this.href) $.get(this.href)
.done(() => { .done(function() {
const $this = $(this); var $this = $(this);
switch ($this.data("shelf-action")) { switch ($this.data("shelf-action")) {
case "add": case "add":
$("#remove-from-shelves").append(`<a href="${$this.data("remove-href")}" $("#remove-from-shelves").append(
data-add-href="${this.href}" templates.remove({
class="btn btn-sm btn-default" data-shelf-action="remove" add: this.href,
><span class="glyphicon glyphicon-remove"></span> ${this.textContent}</a>`); remove: $this.data("remove-href"),
content: this.textContent
})
);
break; break;
case "remove": case "remove":
$("#add-to-shelves").append(`<li><a href="${$this.data("add-href")}" $("#add-to-shelves").append(
data-remove-href="${this.href}" templates.add({
data-shelf-action="add" add: $this.data("add-href"),
>${this.textContent}</a></li>`); remove: this.href,
content: this.textContent
})
);
break; break;
} }
this.parentNode.removeChild(this); this.parentNode.removeChild(this);
}) }.bind(this))
.fail((xhr) => { .fail(function(xhr) {
const $msg = $("<span/>", { "class": "text-danger"}).text(xhr.responseText); var $msg = $("<span/>", { "class": "text-danger"}).text(xhr.responseText);
$("#shelf-action-status").html($msg); $("#shelf-action-status").html($msg);
setTimeout(() => { setTimeout(function() {
$msg.remove(); $msg.remove();
}, 10000); }, 10000);
}); });
}); });
})();

@ -32,7 +32,7 @@ Takes a prefix, query typeahead callback, Bloodhound typeahead adapter
and returns the completions it gets from the bloodhound engine prefixed. and returns the completions it gets from the bloodhound engine prefixed.
*/ */
function prefixedSource(prefix, query, cb, bhAdapter) { function prefixedSource(prefix, query, cb, bhAdapter) {
bhAdapter(query, function(retArray){ bhAdapter(query, function(retArray) {
var matches = []; var matches = [];
for (var i = 0; i < retArray.length; i++) { for (var i = 0; i < retArray.length; i++) {
var obj = {name : prefix + retArray[i].name}; var obj = {name : prefix + retArray[i].name};
@ -41,7 +41,7 @@ function prefixedSource(prefix, query, cb, bhAdapter) {
cb(matches); cb(matches);
}); });
} }
function getPath(){ function getPath() {
var jsFileLocation = $("script[src*=edit_books]").attr("src"); // the js file path var jsFileLocation = $("script[src*=edit_books]").attr("src"); // the js file path
jsFileLocation = jsFileLocation.replace("/static/js/edit_books.js", ""); // the js folder path jsFileLocation = jsFileLocation.replace("/static/js/edit_books.js", ""); // the js folder path
return jsFileLocation; return jsFileLocation;
@ -49,7 +49,7 @@ function getPath(){
var authors = new Bloodhound({ var authors = new Bloodhound({
name: "authors", name: "authors",
datumTokenizer(datum) { datumTokenizer: function datumTokenizer(datum) {
return [datum.name]; return [datum.name];
}, },
queryTokenizer: Bloodhound.tokenizers.whitespace, queryTokenizer: Bloodhound.tokenizers.whitespace,
@ -60,15 +60,15 @@ var authors = new Bloodhound({
var series = new Bloodhound({ var series = new Bloodhound({
name: "series", name: "series",
datumTokenizer(datum) { datumTokenizer: function datumTokenizer(datum) {
return [datum.name]; return [datum.name];
}, },
queryTokenizer(query) { queryTokenizer: function queryTokenizer(query) {
return [query]; return [query];
}, },
remote: { remote: {
url: getPath()+"/get_series_json?q=", url: getPath()+"/get_series_json?q=",
replace(url, query) { replace: function replace(url, query) {
return url+encodeURIComponent(query); return url+encodeURIComponent(query);
} }
} }
@ -77,10 +77,10 @@ var series = new Bloodhound({
var tags = new Bloodhound({ var tags = new Bloodhound({
name: "tags", name: "tags",
datumTokenizer(datum) { datumTokenizer: function datumTokenizer(datum) {
return [datum.name]; return [datum.name];
}, },
queryTokenizer(query) { queryTokenizer: function queryTokenizer(query) {
var tokens = query.split(","); var tokens = query.split(",");
tokens = [tokens[tokens.length-1].trim()]; tokens = [tokens[tokens.length-1].trim()];
return tokens; return tokens;
@ -92,15 +92,15 @@ var tags = new Bloodhound({
var languages = new Bloodhound({ var languages = new Bloodhound({
name: "languages", name: "languages",
datumTokenizer(datum) { datumTokenizer: function datumTokenizer(datum) {
return [datum.name]; return [datum.name];
}, },
queryTokenizer(query) { queryTokenizer: function queryTokenizer(query) {
return [query]; return [query];
}, },
remote: { remote: {
url: getPath()+"/get_languages_json?q=", url: getPath()+"/get_languages_json?q=",
replace(url, query) { replace: function replace(url, query) {
return url+encodeURIComponent(query); return url+encodeURIComponent(query);
} }
} }
@ -115,9 +115,9 @@ function sourceSplit(query, cb, split, source) {
tokens.splice(tokens.length-1, 1); // remove last element tokens.splice(tokens.length-1, 1); // remove last element
var prefix = ""; var prefix = "";
var newSplit; var newSplit;
if (split === "&"){ if (split === "&") {
newSplit = " " + split + " "; newSplit = " " + split + " ";
}else{ } else {
newSplit = split + " "; newSplit = split + " ";
} }
for (var i = 0; i < tokens.length; i++) { for (var i = 0; i < tokens.length; i++) {
@ -127,7 +127,7 @@ function sourceSplit(query, cb, split, source) {
} }
var promiseAuthors = authors.initialize(); var promiseAuthors = authors.initialize();
promiseAuthors.done(function(){ promiseAuthors.done(function() {
$("#bookAuthor").typeahead( $("#bookAuthor").typeahead(
{ {
highlight: true, minLength: 1, highlight: true, minLength: 1,
@ -135,14 +135,15 @@ var promiseAuthors = authors.initialize();
}, { }, {
name: "authors", name: "authors",
displayKey: "name", displayKey: "name",
source(query, cb){ source: function source(query, cb) {
return sourceSplit(query, cb, "&", authors); //sourceSplit //("&") return sourceSplit(query, cb, "&", authors); //sourceSplit //("&")
} }
}); }
);
}); });
var promiseSeries = series.initialize(); var promiseSeries = series.initialize();
promiseSeries.done(function(){ promiseSeries.done(function() {
$("#series").typeahead( $("#series").typeahead(
{ {
highlight: true, minLength: 0, highlight: true, minLength: 0,
@ -156,7 +157,7 @@ var promiseSeries = series.initialize();
}); });
var promiseTags = tags.initialize(); var promiseTags = tags.initialize();
promiseTags.done(function(){ promiseTags.done(function() {
$("#tags").typeahead( $("#tags").typeahead(
{ {
highlight: true, minLength: 0, highlight: true, minLength: 0,
@ -164,14 +165,15 @@ var promiseTags = tags.initialize();
}, { }, {
name: "tags", name: "tags",
displayKey: "name", displayKey: "name",
source(query, cb){ source: function source(query, cb) {
return sourceSplit(query, cb, ",", tags); return sourceSplit(query, cb, ",", tags);
} }
}); }
}); );
});
var promiseLanguages = languages.initialize(); var promiseLanguages = languages.initialize();
promiseLanguages.done(function(){ promiseLanguages.done(function() {
$("#languages").typeahead( $("#languages").typeahead(
{ {
highlight: true, minLength: 0, highlight: true, minLength: 0,
@ -179,13 +181,14 @@ var promiseLanguages = languages.initialize();
}, { }, {
name: "languages", name: "languages",
displayKey: "name", displayKey: "name",
source(query, cb){ source: function source(query, cb) {
return sourceSplit(query, cb, ",", languages); //(",") return sourceSplit(query, cb, ",", languages); //(",")
} }
}); }
}); );
});
$("#search").on("change input.typeahead:selected", function(){ $("#search").on("change input.typeahead:selected", function() {
var form = $("form").serialize(); var form = $("form").serialize();
$.getJSON( getPath()+"/get_matching_tags", form, function( data ) { $.getJSON( getPath()+"/get_matching_tags", form, function( data ) {
$(".tags_click").each(function() { $(".tags_click").each(function() {
@ -193,8 +196,7 @@ $("#search").on("change input.typeahead:selected", function(){
if (!($(this).hasClass("active"))) { if (!($(this).hasClass("active"))) {
$(this).addClass("disabled"); $(this).addClass("disabled");
} }
} } else {
else {
$(this).removeClass("disabled"); $(this).removeClass("disabled");
} }
}); });

@ -8,7 +8,7 @@
var dbResults = []; var dbResults = [];
var ggResults = []; var ggResults = [];
$(document).ready(function () { $(function () {
var msg = i18nMsg; var msg = i18nMsg;
var douban = "https://api.douban.com"; var douban = "https://api.douban.com";
var dbSearch = "/v2/book/search"; var dbSearch = "/v2/book/search";
@ -22,9 +22,6 @@ $(document).ready(function () {
var ggDone = false; var ggDone = false;
var showFlag = 0; var showFlag = 0;
String.prototype.replaceAll = function (s1, s2) {
return this.replace(new RegExp(s1, "gm"), s2);
};
function showResult () { function showResult () {
var book; var book;
@ -32,11 +29,11 @@ $(document).ready(function () {
var bookHtml; var bookHtml;
showFlag++; showFlag++;
if (showFlag === 1) { if (showFlag === 1) {
$("#metaModal #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) {
$("#metaModal #meta-info").html("<p class=\"text-danger\">"+ msg.no_result +"</p>"); $("#meta-info").html("<p class=\"text-danger\">"+ msg.no_result +"</p>");
return; return;
} }
} }
@ -62,7 +59,7 @@ $(document).ready(function () {
"<p>"+ msg.source + ":<a href=\"https://books.google.com\" target=\"_blank\">Google Books</a></p>" + "<p>"+ msg.source + ":<a href=\"https://books.google.com\" target=\"_blank\">Google Books</a></p>" +
"</div>" + "</div>" +
"</li>"; "</li>";
$("#metaModal #book-list").append(bookHtml); $("#book-list").append(bookHtml);
} }
ggDone = false; ggDone = false;
} }
@ -82,24 +79,22 @@ $(document).ready(function () {
"<p>" + msg.source + ":<a href=\"https://book.douban.com\" target=\"_blank\">Douban Books</a></p>" + "<p>" + msg.source + ":<a href=\"https://book.douban.com\" target=\"_blank\">Douban Books</a></p>" +
"</div>" + "</div>" +
"</li>"; "</li>";
$("#metaModal #book-list").append(bookHtml); $("#book-list").append(bookHtml);
} }
dbDone = false; dbDone = false;
} }
} }
function ggSearchBook (title) { function ggSearchBook (title) {
title = title.replaceAll(/\s+/, "+");
var url = google + ggSearch + "?q=" + title;
$.ajax({ $.ajax({
url, url: google + ggSearch + "?q=" + title.replace(/\s+/gm, "+"),
type: "GET", type: "GET",
dataType: "jsonp", dataType: "jsonp",
jsonp: "callback", jsonp: "callback",
success (data) { success: function success(data) {
ggResults = data.items; ggResults = data.items;
}, },
complete () { complete: function complete() {
ggDone = true; ggDone = true;
showResult(); showResult();
} }
@ -107,19 +102,18 @@ $(document).ready(function () {
} }
function dbSearchBook (title) { function dbSearchBook (title) {
var url = douban + dbSearch + "?q=" + title + "&fields=all&count=10";
$.ajax({ $.ajax({
url, url: douban + dbSearch + "?q=" + title + "&fields=all&count=10",
type: "GET", type: "GET",
dataType: "jsonp", dataType: "jsonp",
jsonp: "callback", jsonp: "callback",
success (data) { success: function success(data) {
dbResults = data.books; dbResults = data.books;
}, },
error () { error: function error() {
$("#metaModal #meta-info").html("<p class=\"text-danger\">"+ msg.search_error+"!</p>"); $("#meta-info").html("<p class=\"text-danger\">"+ msg.search_error+"!</p>");
}, },
complete () { complete: function complete() {
dbDone = true; dbDone = true;
showResult(); showResult();
} }
@ -128,7 +122,7 @@ $(document).ready(function () {
function doSearch (keyword) { function doSearch (keyword) {
showFlag = 0; showFlag = 0;
$("#metaModal #meta-info").text(msg.loading); $("#meta-info").text(msg.loading);
// var keyword = $("#keyword").val(); // var keyword = $("#keyword").val();
if (keyword) { if (keyword) {
dbSearchBook(keyword); dbSearchBook(keyword);
@ -153,6 +147,7 @@ $(document).ready(function () {
}); });
// eslint-disable-next-line no-unused-vars
function getMeta (source, id) { function getMeta (source, id) {
var meta; var meta;
var tags; var tags;
@ -181,6 +176,5 @@ function getMeta (source, id) {
} }
$("#tags").val(tags); $("#tags").val(tags);
$("#rating").val(Math.round(meta.rating.average / 2)); $("#rating").val(Math.round(meta.rating.average / 2));
return;
} }
} }

@ -1,7 +1,3 @@
var displaytext;
var updateTimerID;
var updateText;
// Generic control/related handler to show/hide fields based on a checkbox' value // Generic control/related handler to show/hide fields based on a checkbox' value
// e.g. // e.g.
// <input type="checkbox" data-control="stuff-to-show"> // <input type="checkbox" data-control="stuff-to-show">
@ -11,16 +7,18 @@ $(document).on("change", "input[type=\"checkbox\"][data-control]", function () {
var name = $this.data("control"); var name = $this.data("control");
var showOrHide = $this.prop("checked"); var showOrHide = $this.prop("checked");
$("[data-related=\""+name+"\"]").each(function () { $("[data-related=\"" + name + "\"]").each(function () {
$(this).toggle(showOrHide); $(this).toggle(showOrHide);
}); });
}); });
$(function() { $(function() {
var updateTimerID;
var updateText;
// Allow ajax prefilters to be added/removed dynamically // Allow ajax prefilters to be added/removed dynamically
// eslint-disable-next-line new-cap // eslint-disable-next-line new-cap
const preFilters = $.Callbacks(); var preFilters = $.Callbacks();
$.ajaxPrefilter(preFilters.fire); $.ajaxPrefilter(preFilters.fire);
function restartTimer() { function restartTimer() {
@ -31,28 +29,28 @@ $(function() {
function updateTimer() { function updateTimer() {
$.ajax({ $.ajax({
dataType: "json", dataType: "json",
url: window.location.pathname+"/../../get_updater_status", url: window.location.pathname + "/../../get_updater_status",
success(data) { success: function success(data) {
// console.log(data.status); // console.log(data.status);
$("#UpdateprogressDialog #Updatecontent").html(updateText[data.status]); $("#Updatecontent").html(updateText[data.status]);
if (data.status >6){ if (data.status > 6) {
clearInterval(updateTimerID); clearInterval(updateTimerID);
$("#spinner2").hide(); $("#spinner2").hide();
$("#UpdateprogressDialog #updateFinished").removeClass("hidden"); $("#updateFinished").removeClass("hidden");
$("#check_for_update").removeClass("hidden"); $("#check_for_update").removeClass("hidden");
$("#perform_update").addClass("hidden"); $("#perform_update").addClass("hidden");
} }
}, },
error() { error: function error() {
// console.log('Done'); // console.log('Done');
clearInterval(updateTimerID); clearInterval(updateTimerID);
$("#spinner2").hide(); $("#spinner2").hide();
$("#UpdateprogressDialog #Updatecontent").html(updateText[7]); $("#Updatecontent").html(updateText[7]);
$("#UpdateprogressDialog #updateFinished").removeClass("hidden"); $("#updateFinished").removeClass("hidden");
$("#check_for_update").removeClass("hidden"); $("#check_for_update").removeClass("hidden");
$("#perform_update").addClass("hidden"); $("#perform_update").addClass("hidden");
}, },
timeout:2000 timeout: 2000
}); });
} }
@ -70,13 +68,13 @@ $(function() {
// selector for the NEXT link (to page 2) // selector for the NEXT link (to page 2)
itemSelector : ".load-more .book", itemSelector : ".load-more .book",
animate : true, animate : true,
extraScrollPx: 300, extraScrollPx: 300
// selector for all items you'll retrieve // selector for all items you'll retrieve
}, function(data){ }, function(data) {
$(".load-more .row").isotope( "appended", $(data), null ); $(".load-more .row").isotope( "appended", $(data), null );
}); });
$("#sendbtn").click(function(){ $("#sendbtn").click(function() {
var $this = $(this); var $this = $(this);
$this.text("Please wait..."); $this.text("Please wait...");
$this.addClass("disabled"); $this.addClass("disabled");
@ -84,36 +82,39 @@ $(function() {
$("#restart").click(function() { $("#restart").click(function() {
$.ajax({ $.ajax({
dataType: "json", dataType: "json",
url: window.location.pathname+"/../../shutdown", url: window.location.pathname + "/../../shutdown",
data: {"parameter":0}, data: {"parameter":0},
success(data) { success: function success() {
$("#spinner").show(); $("#spinner").show();
displaytext=data.text; setTimeout(restartTimer, 3000);
setTimeout(restartTimer, 3000);} }
}); });
}); });
$("#shutdown").click(function() { $("#shutdown").click(function() {
$.ajax({ $.ajax({
dataType: "json", dataType: "json",
url: window.location.pathname+"/../../shutdown", url: window.location.pathname + "/../../shutdown",
data: {"parameter":1}, data: {"parameter":1},
success(data) { success: function success(data) {
return alert(data.text);} return alert(data.text);
}
}); });
}); });
$("#check_for_update").click(function() { $("#check_for_update").click(function() {
var buttonText = $("#check_for_update").html(); var $this = $(this);
$("#check_for_update").html("..."); var buttonText = $this.html();
$this.html("...");
$.ajax({ $.ajax({
dataType: "json", dataType: "json",
url: window.location.pathname+"/../../get_update_status", url: window.location.pathname + "/../../get_update_status",
success(data) { success: function success(data) {
$("#check_for_update").html(buttonText); $this.html(buttonText);
if (data.status === true) { if (data.status === true) {
$("#check_for_update").addClass("hidden"); $("#check_for_update").addClass("hidden");
$("#perform_update").removeClass("hidden"); $("#perform_update").removeClass("hidden");
$("#update_info").removeClass("hidden"); $("#update_info")
$("#update_info").find("span").html(data.commit); .removeClass("hidden")
.find("span").html(data.commit);
} }
} }
}); });
@ -121,7 +122,7 @@ $(function() {
$("#restart_database").click(function() { $("#restart_database").click(function() {
$.ajax({ $.ajax({
dataType: "json", dataType: "json",
url: window.location.pathname+"/../../shutdown", url: window.location.pathname + "/../../shutdown",
data: {"parameter":2} data: {"parameter":2}
}); });
}); });
@ -131,12 +132,13 @@ $(function() {
type: "POST", type: "POST",
dataType: "json", dataType: "json",
data: { start: "True"}, data: { start: "True"},
url: window.location.pathname+"/../../get_updater_status", url: window.location.pathname + "/../../get_updater_status",
success(data) { success: function success(data) {
updateText=data.text; updateText = data.text;
$("#UpdateprogressDialog #Updatecontent").html(updateText[data.status]); $("#Updatecontent").html(updateText[data.status]);
// console.log(data.status); // console.log(data.status);
updateTimerID=setInterval(updateTimer, 2000);} updateTimerID = setInterval(updateTimer, 2000);
}
}); });
}); });
@ -144,10 +146,10 @@ $(function() {
$("#bookDetailsModal") $("#bookDetailsModal")
.on("show.bs.modal", function(e) { .on("show.bs.modal", function(e) {
const $modalBody = $(this).find(".modal-body"); var $modalBody = $(this).find(".modal-body");
// Prevent static assets from loading multiple times // Prevent static assets from loading multiple times
const useCache = (options) => { var useCache = function(options) {
options.async = true; options.async = true;
options.cache = true; options.cache = true;
}; };
@ -162,7 +164,7 @@ $(function() {
$(this).find(".modal-body").html("..."); $(this).find(".modal-body").html("...");
}); });
$(window).resize(function(event) { $(window).resize(function() {
$(".discover .row").isotope("reLayout"); $(".discover .row").isotope("reLayout");
}); });
}); });

@ -1,30 +1,30 @@
/* global Sortable,sortTrue */ /* global Sortable,sortTrue */
var sortable = Sortable.create(sortTrue, { Sortable.create(sortTrue, {
group: "sorting", group: "sorting",
sort: true sort: true
}); });
function sendData(path){ // eslint-disable-next-line no-unused-vars
function sendData(path) {
var elements; var elements;
var counter; var counter;
var maxElements; var maxElements;
var tmp=[]; var tmp = [];
elements=Sortable.utils.find(sortTrue,"div"); elements = Sortable.utils.find(sortTrue, "div");
maxElements=elements.length; maxElements = elements.length;
var form = document.createElement("form"); var form = document.createElement("form");
form.setAttribute("method", "post"); form.setAttribute("method", "post");
form.setAttribute("action", path); form.setAttribute("action", path);
for (counter = 0;counter < maxElements;counter++) {
for(counter=0;counter<maxElements;counter++){ tmp[counter] = elements[counter].getAttribute("id");
tmp[counter]=elements[counter].getAttribute("id");
var hiddenField = document.createElement("input"); var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden"); hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", elements[counter].getAttribute("id")); hiddenField.setAttribute("name", elements[counter].getAttribute("id"));
hiddenField.setAttribute("value", counter+1); hiddenField.setAttribute("value", String(counter + 1));
form.appendChild(hiddenField); form.appendChild(hiddenField);
} }
document.body.appendChild(form); document.body.appendChild(form);

@ -139,7 +139,7 @@
<div class="modal-header bg-danger text-center"> <div class="modal-header bg-danger text-center">
<span>{{_('Are really you sure?')}}</span> <span>{{_('Are really you sure?')}}</span>
</div> </div>
<div class="modal-body text-center" id="meta-info"> <div class="modal-body text-center">
<span>{{_('Book will be deleted from Calibre database')}}</span> <span>{{_('Book will be deleted from Calibre database')}}</span>
<span>{{_('and from hard disk')}}</span> <span>{{_('and from hard disk')}}</span>
</div> </div>

@ -259,5 +259,17 @@
{% endblock %} {% endblock %}
{% block js %} {% block js %}
<script type="text/template" id="template-shelf-add">
<li>
<a href="<%= add %>" data-remove-href="<%= remove %>" data-shelf-action="add">
<%= content %>
</a>
</li>
</script>
<script type="text/template" id="template-shelf-remove">
<a href="<%= remove %>" data-add-href="<%= add %>" class="btn btn-sm btn-default" data-shelf-action="remove">
<span class="glyphicon glyphicon-remove"></span> <%= content %>
</a>
</script>
<script src="{{ url_for('static', filename='js/details.js') }}"></script> <script src="{{ url_for('static', filename='js/details.js') }}"></script>
{% endblock %} {% endblock %}

Loading…
Cancel
Save