mirror of
https://github.com/janeczku/calibre-web
synced 2024-11-15 14:24:57 +00:00
progressbar during upload thanks to jim3ma
This commit is contained in:
parent
0fa45f5800
commit
56826f67fc
8
cps/static/css/upload.css
Normal file
8
cps/static/css/upload.css
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
@media (min-device-width: 768px) {
|
||||||
|
.modal-dialog {
|
||||||
|
position: absolute;
|
||||||
|
top: 45%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%) !important;
|
||||||
|
}
|
||||||
|
}
|
198
cps/static/js/uploadprogress.js
Normal file
198
cps/static/js/uploadprogress.js
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
* bootstrap-uploadprogress
|
||||||
|
* github: https://github.com/jakobadam/bootstrap-uploadprogress
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Jakob Aarøe Dam
|
||||||
|
* Version 1.0.0
|
||||||
|
* Licensed under the MIT license.
|
||||||
|
*/
|
||||||
|
(function($){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
$.support.xhrFileUpload = !!(window.FileReader && window.ProgressEvent);
|
||||||
|
$.support.xhrFormData = !!window.FormData;
|
||||||
|
|
||||||
|
if(!$.support.xhrFileUpload || !$.support.xhrFormData){
|
||||||
|
// skip decorating form
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var template = '<div class="modal fade" id="file-progress-modal">\
|
||||||
|
<div class="modal-dialog">\
|
||||||
|
<div class="modal-content">\
|
||||||
|
<div class="modal-header">\
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>\
|
||||||
|
<h4 class="modal-title">Uploading</h4>\
|
||||||
|
</div>\
|
||||||
|
<div class="modal-body">\
|
||||||
|
<div class="modal-message"></div>\
|
||||||
|
<div class="progress">\
|
||||||
|
<div class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="0" aria-valuemin="0"\
|
||||||
|
aria-valuemax="100" style="width: 0%;min-width: 2em;">\
|
||||||
|
0%\
|
||||||
|
</div>\
|
||||||
|
</div>\
|
||||||
|
</div>\
|
||||||
|
<div class="modal-footer" style="display:none">\
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>\
|
||||||
|
</div>\
|
||||||
|
</div>\
|
||||||
|
</div>\
|
||||||
|
</div>';
|
||||||
|
|
||||||
|
var UploadProgress = function(element, options){
|
||||||
|
this.options = options;
|
||||||
|
this.$element = $(element);
|
||||||
|
};
|
||||||
|
|
||||||
|
UploadProgress.prototype = {
|
||||||
|
|
||||||
|
constructor: function() {
|
||||||
|
this.$form = this.$element;
|
||||||
|
this.$form.on('submit', $.proxy(this.submit, this));
|
||||||
|
this.$modal = $(this.options.template);
|
||||||
|
this.$modal_message = this.$modal.find('.modal-message');
|
||||||
|
this.$modal_title = this.$modal.find('.modal-title');
|
||||||
|
this.$modal_footer = this.$modal.find('.modal-footer');
|
||||||
|
this.$modal_bar = this.$modal.find('.progress-bar');
|
||||||
|
|
||||||
|
this.$modal.on('hidden.bs.modal', $.proxy(this.reset, this));
|
||||||
|
},
|
||||||
|
|
||||||
|
reset: function(){
|
||||||
|
this.$modal_title = this.$modal_title.text('Uploading');
|
||||||
|
this.$modal_footer.hide();
|
||||||
|
this.$modal_bar.addClass('progress-bar-success');
|
||||||
|
this.$modal_bar.removeClass('progress-bar-danger');
|
||||||
|
if(this.xhr){
|
||||||
|
this.xhr.abort();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
submit: function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
this.$modal.modal({
|
||||||
|
backdrop: 'static',
|
||||||
|
keyboard: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// We need the native XMLHttpRequest for the progress event
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
this.xhr = xhr;
|
||||||
|
|
||||||
|
xhr.addEventListener('load', $.proxy(this.success, this, xhr));
|
||||||
|
xhr.addEventListener('error', $.proxy(this.error, this, xhr));
|
||||||
|
//xhr.addEventListener('abort', function(){});
|
||||||
|
|
||||||
|
xhr.upload.addEventListener('progress', $.proxy(this.progress, this));
|
||||||
|
|
||||||
|
var form = this.$form;
|
||||||
|
|
||||||
|
xhr.open(form.attr('method'), form.attr("action"));
|
||||||
|
xhr.setRequestHeader('X-REQUESTED-WITH', 'XMLHttpRequest');
|
||||||
|
|
||||||
|
var data = new FormData(form.get(0));
|
||||||
|
xhr.send(data);
|
||||||
|
},
|
||||||
|
|
||||||
|
success: function(xhr) {
|
||||||
|
if(xhr.status == 0 || xhr.status >= 400){
|
||||||
|
// HTTP 500 ends up here!?!
|
||||||
|
return this.error(xhr);
|
||||||
|
}
|
||||||
|
this.set_progress(100);
|
||||||
|
var url;
|
||||||
|
var content_type = xhr.getResponseHeader('Content-Type');
|
||||||
|
|
||||||
|
// make it possible to return the redirect URL in
|
||||||
|
// a JSON response
|
||||||
|
if(content_type.indexOf('application/json') !== -1){
|
||||||
|
var response = $.parseJSON(xhr.responseText);
|
||||||
|
console.log(response);
|
||||||
|
url = response.location;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
url = this.options.redirect_url;
|
||||||
|
}
|
||||||
|
window.location.href = url;
|
||||||
|
},
|
||||||
|
|
||||||
|
// handle form error
|
||||||
|
// we replace the form with the returned one
|
||||||
|
error: function(xhr){
|
||||||
|
this.$modal_title.text('Upload failed');
|
||||||
|
|
||||||
|
this.$modal_bar.removeClass('progress-bar-success');
|
||||||
|
this.$modal_bar.addClass('progress-bar-danger');
|
||||||
|
this.$modal_footer.show();
|
||||||
|
|
||||||
|
var content_type = xhr.getResponseHeader('Content-Type');
|
||||||
|
|
||||||
|
// Replace the contents of the form, with the returned html
|
||||||
|
if(xhr.status === 422){
|
||||||
|
var new_html = $.parseHTML(xhr.responseText);
|
||||||
|
this.replace_form(new_html);
|
||||||
|
this.$modal.modal('hide');
|
||||||
|
}
|
||||||
|
// Write the error response to the document.
|
||||||
|
else{
|
||||||
|
var response_text = xhr.responseText;
|
||||||
|
if(content_type.indexOf('text/plain') !== -1){
|
||||||
|
response_text = '<pre>' + response_text + '</pre>';
|
||||||
|
}
|
||||||
|
document.write(xhr.responseText);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
set_progress: function(percent){
|
||||||
|
var txt = percent + '%';
|
||||||
|
if (percent == 100) {
|
||||||
|
txt = this.options.uploaded_msg;
|
||||||
|
}
|
||||||
|
this.$modal_bar.attr('aria-valuenow', percent);
|
||||||
|
this.$modal_bar.text(txt);
|
||||||
|
this.$modal_bar.css('width', percent + '%');
|
||||||
|
},
|
||||||
|
|
||||||
|
progress: function(/*ProgressEvent*/e){
|
||||||
|
var percent = Math.round((e.loaded / e.total) * 100);
|
||||||
|
this.set_progress(percent);
|
||||||
|
},
|
||||||
|
|
||||||
|
// replace_form replaces the contents of the current form
|
||||||
|
// with the form in the html argument.
|
||||||
|
// We use the id of the current form to find the new form in the html
|
||||||
|
replace_form: function(html){
|
||||||
|
var new_form;
|
||||||
|
var form_id = this.$form.attr('id');
|
||||||
|
if(form_id !== undefined){
|
||||||
|
new_form = $(html).find('#' + form_id);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
new_form = $(html).find('form');
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the filestyle again
|
||||||
|
new_form.find(':file').filestyle({buttonBefore: true});
|
||||||
|
this.$form.html(new_form.children());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.uploadprogress = function(options, value){
|
||||||
|
return this.each(function(){
|
||||||
|
var _options = $.extend({}, $.fn.uploadprogress.defaults, options);
|
||||||
|
var file_progress = new UploadProgress(this, _options);
|
||||||
|
file_progress.constructor();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fn.uploadprogress.defaults = {
|
||||||
|
template: template,
|
||||||
|
uploaded_msg: "Upload done, processing, please wait..."
|
||||||
|
//redirect_url: ...
|
||||||
|
|
||||||
|
// need to customize stuff? Add here, and change code accordingly.
|
||||||
|
};
|
||||||
|
|
||||||
|
})(window.jQuery);
|
@ -12,6 +12,7 @@
|
|||||||
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||||
<link href="{{ url_for('static', filename='css/libs/bootstrap.min.css') }}" rel="stylesheet" media="screen">
|
<link href="{{ url_for('static', filename='css/libs/bootstrap.min.css') }}" rel="stylesheet" media="screen">
|
||||||
<link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet" media="screen">
|
<link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet" media="screen">
|
||||||
|
<link href="{{ url_for('static', filename='css/upload.css') }}" rel="stylesheet" media="screen">
|
||||||
{% if g.current_theme == 1 %}
|
{% if g.current_theme == 1 %}
|
||||||
<link href="{{ url_for('static', filename='css/caliBlur.min.css') }}" rel="stylesheet" media="screen">
|
<link href="{{ url_for('static', filename='css/caliBlur.min.css') }}" rel="stylesheet" media="screen">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -103,14 +104,6 @@
|
|||||||
</div>
|
</div>
|
||||||
{%endif%}
|
{%endif%}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<div id="loader" hidden="true">
|
|
||||||
<center>
|
|
||||||
<h3>{{_('Uploading...')}}</h3>
|
|
||||||
<span>{{_("please don't refresh the page")}}</span>.
|
|
||||||
<br />
|
|
||||||
<img src="{{ url_for('static', filename='img/loader.gif') }}">
|
|
||||||
</center>
|
|
||||||
</div>
|
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row-fluid">
|
<div class="row-fluid">
|
||||||
{% if g.user.is_authenticated or g.user.is_anonymous %}
|
{% if g.user.is_authenticated or g.user.is_anonymous %}
|
||||||
@ -240,6 +233,7 @@
|
|||||||
<script src="{{ url_for('static', filename='js/libs/plugins.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/libs/plugins.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/libs/jquery.form.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/libs/jquery.form.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/uploadprogress.js') }}"> </script>
|
||||||
{% if g.current_theme == 1 %}
|
{% if g.current_theme == 1 %}
|
||||||
<script src="{{ url_for('static', filename='js/libs/jquery.visible.min.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/libs/jquery.visible.min.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/libs/compromise.min.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/libs/compromise.min.js') }}"></script>
|
||||||
@ -247,9 +241,9 @@
|
|||||||
<script src="{{ url_for('static', filename='js/caliBlur.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/caliBlur.js') }}"></script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(function () {
|
$(function() {
|
||||||
$("#btn-upload").change(function () {
|
$("#form-upload").uploadprogress({redirect_url: '{{ url_for('index')}}'});
|
||||||
$("#loader").show();
|
$("#btn-upload").change(function() {
|
||||||
$("#form-upload").submit();
|
$("#form-upload").submit();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -568,6 +568,8 @@ class Config:
|
|||||||
# everywhere to curent should work. Migration is done by checking if relevant coloums are existing, and than adding
|
# everywhere to curent should work. Migration is done by checking if relevant coloums are existing, and than adding
|
||||||
# rows with SQL commands
|
# rows with SQL commands
|
||||||
def migrate_Database():
|
def migrate_Database():
|
||||||
|
if not engine.dialect.has_table(engine.connect(), "book_read_link"):
|
||||||
|
ReadBook.__table__.create(bind=engine)
|
||||||
if not engine.dialect.has_table(engine.connect(), "bookmark"):
|
if not engine.dialect.has_table(engine.connect(), "bookmark"):
|
||||||
Bookmark.__table__.create(bind=engine)
|
Bookmark.__table__.create(bind=engine)
|
||||||
if not engine.dialect.has_table(engine.connect(), "registration"):
|
if not engine.dialect.has_table(engine.connect(), "registration"):
|
||||||
|
18
cps/web.py
18
cps/web.py
@ -3862,19 +3862,13 @@ def upload():
|
|||||||
for author in db_book.authors:
|
for author in db_book.authors:
|
||||||
author_names.append(author.name)
|
author_names.append(author.name)
|
||||||
if len(request.files.getlist("btn-upload")) < 2:
|
if len(request.files.getlist("btn-upload")) < 2:
|
||||||
cc = db.session.query(db.Custom_Columns).filter(db.Custom_Columns.
|
|
||||||
datatype.notin_(db.cc_exceptions)).all()
|
|
||||||
if current_user.role_edit() or current_user.role_admin():
|
if current_user.role_edit() or current_user.role_admin():
|
||||||
return render_title_template('book_edit.html', book=book, authors=author_names,
|
resp = {"location": url_for('edit_book', book_id=db_book.id)}
|
||||||
cc=cc, title=_(u"edit metadata"), page="upload")
|
return Response(json.dumps(resp), mimetype='application/json')
|
||||||
book_in_shelfs = []
|
else:
|
||||||
kindle_list = helper.check_send_to_kindle(book)
|
resp = {"location": url_for('show_book', book_id=db_book.id)}
|
||||||
reader_list = helper.check_read_formats(book)
|
return Response(json.dumps(resp), mimetype='application/json')
|
||||||
|
return Response(json.dumps({"location": url_for("index")}), mimetype='application/json')
|
||||||
return render_title_template('detail.html', entry=book, cc=cc,
|
|
||||||
title=book.title, books_shelfs=book_in_shelfs, kindle_list=kindle_list,
|
|
||||||
reader_list=reader_list, page="upload")
|
|
||||||
return redirect(url_for("index"))
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/admin/book/convert/<int:book_id>", methods=['POST'])
|
@app.route("/admin/book/convert/<int:book_id>", methods=['POST'])
|
||||||
|
Loading…
Reference in New Issue
Block a user