Commit 709fa88c authored by OzzieIsaacs's avatar OzzieIsaacs

Navbar reduced to icons on smaller screens

Feedback updater improved (#81)
parent 3cadde65
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
import os import os
import sys import sys
import time
base_path = os.path.dirname(os.path.abspath(__file__)) base_path = os.path.dirname(os.path.abspath(__file__))
# Insert local directories into path # Insert local directories into path
...@@ -22,7 +21,7 @@ if __name__ == '__main__': ...@@ -22,7 +21,7 @@ if __name__ == '__main__':
http_server.listen(web.ub.config.config_port) http_server.listen(web.ub.config.config_port)
IOLoop.instance().start() IOLoop.instance().start()
if web.global_task == 0: if web.helper.global_task == 0:
print("Performing restart of Calibre-web") print("Performing restart of Calibre-web")
os.execl(sys.executable, sys.executable, *sys.argv) os.execl(sys.executable, sys.executable, *sys.argv)
else: else:
......
This diff is collapsed.
...@@ -47,3 +47,7 @@ span.glyphicon.glyphicon-tags {padding-right: 5px;color: #999;vertical-align: te ...@@ -47,3 +47,7 @@ span.glyphicon.glyphicon-tags {padding-right: 5px;color: #999;vertical-align: te
.btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary{ background-color: #1C5484; } .btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary{ background-color: #1C5484; }
.btn-primary.disabled, .btn-primary[disabled], fieldset[disabled] .btn-primary, .btn-primary.disabled:hover, .btn-primary[disabled]:hover, fieldset[disabled] .btn-primary:hover, .btn-primary.disabled:focus, .btn-primary[disabled]:focus, fieldset[disabled] .btn-primary:focus, .btn-primary.disabled:active, .btn-primary[disabled]:active, fieldset[disabled] .btn-primary:active, .btn-primary.disabled.active, .btn-primary[disabled].active, fieldset[disabled] .btn-primary.active { background-color: #89B9E2; } .btn-primary.disabled, .btn-primary[disabled], fieldset[disabled] .btn-primary, .btn-primary.disabled:hover, .btn-primary[disabled]:hover, fieldset[disabled] .btn-primary:hover, .btn-primary.disabled:focus, .btn-primary[disabled]:focus, fieldset[disabled] .btn-primary:focus, .btn-primary.disabled:active, .btn-primary[disabled]:active, fieldset[disabled] .btn-primary:active, .btn-primary.disabled.active, .btn-primary[disabled].active, fieldset[disabled] .btn-primary.active { background-color: #89B9E2; }
.btn-toolbar>.btn+.btn, .btn-toolbar>.btn-group+.btn, .btn-toolbar>.btn+.btn-group, .btn-toolbar>.btn-group+.btn-group { margin-left:0px; } .btn-toolbar>.btn+.btn, .btn-toolbar>.btn-group+.btn, .btn-toolbar>.btn+.btn-group, .btn-toolbar>.btn-group+.btn-group { margin-left:0px; }
.spinner {margin:0 41%;}
.spinner2 {margin:0 41%;}
var displaytext;
var updateTimerID;
var updateText;
$(function() { $(function() {
$('.discover .row').isotope({ $('.discover .row').isotope({
...@@ -31,7 +34,9 @@ $(function() { ...@@ -31,7 +34,9 @@ $(function() {
url: window.location.pathname+"/../../shutdown", url: window.location.pathname+"/../../shutdown",
data: {"parameter":0}, data: {"parameter":0},
success: function(data) { success: function(data) {
return alert(data.text);} $('#spinner').show();
displaytext=data.text;
window.setTimeout(restartTimer, 3000);}
}); });
}); });
$("#shutdown").click(function() { $("#shutdown").click(function() {
...@@ -50,17 +55,66 @@ $(function() { ...@@ -50,17 +55,66 @@ $(function() {
dataType: 'json', dataType: 'json',
url: window.location.pathname+"/../../get_update_status", url: window.location.pathname+"/../../get_update_status",
success: function(data) { success: function(data) {
if (data.status == true) {
$("#check_for_update").addClass('hidden');
$("#perform_update").removeClass('hidden');
}else{
$("#check_for_update").html(button_text); $("#check_for_update").html(button_text);
};} if (data.status == true) {
$("#check_for_update").addClass('hidden');
$("#perform_update").removeClass('hidden');
$("#update_info").removeClass('hidden');
$("#update_info").find('span').html(data.commit);
}
}
});
});
$("#perform_update").click(function() {
$('#spinner2').show();
$.ajax({
type: "POST",
dataType: 'json',
data: { start: "True"},
url: window.location.pathname+"/../../get_updater_status",
success: function(data) {
updateText=data.text
$("#UpdateprogressDialog #Updatecontent").html(updateText[data.status]);
console.log(data.status);
updateTimerID=setInterval(updateTimer, 2000);}
}); });
}); });
}); });
function restartTimer() {
$('#spinner').hide();
$('#RestartDialog').modal('hide');
}
function updateTimer() {
$.ajax({
dataType: 'json',
url: window.location.pathname+"/../../get_updater_status",
success: function(data) {
console.log(data.status);
$("#UpdateprogressDialog #Updatecontent").html(updateText[data.status]);
if (data.status >6){
clearInterval(updateTimerID);
$('#spinner2').hide();
$('#UpdateprogressDialog #updateFinished').removeClass('hidden');
$("#check_for_update").removeClass('hidden');
$("#perform_update").addClass('hidden');
}
},
error: function() {
console.log('Done');
clearInterval(updateTimerID);
$('#spinner2').hide();
$("#UpdateprogressDialog #Updatecontent").html(updateText[7]);
$('#UpdateprogressDialog #updateFinished').removeClass('hidden');
$("#check_for_update").removeClass('hidden');
$("#perform_update").addClass('hidden');
}
});
}
$(window).resize(function(event) { $(window).resize(function(event) {
$('.discover .row').isotope('reLayout'); $('.discover .row').isotope('reLayout');
}); });
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
{% block body %} {% block body %}
<div class="discover"> <div class="discover">
<h2>{{_('User list')}}</h2> <h2>{{_('User list')}}</h2>
<div id="divLoading"></div>
<table class="table table-striped" id="table_user"> <table class="table table-striped" id="table_user">
<tr> <tr>
<th>{{_('Nickname')}}</th> <th>{{_('Nickname')}}</th>
...@@ -76,11 +77,13 @@ ...@@ -76,11 +77,13 @@
<div class="btn btn-default"><a href="{{url_for('configuration')}}">{{_('Configuration')}}</a></div> <div class="btn btn-default"><a href="{{url_for('configuration')}}">{{_('Configuration')}}</a></div>
<h2>{{_('Administration')}}</h2> <h2>{{_('Administration')}}</h2>
{% if not development %} {% if not development %}
<p>{{_('Current commit timestamp')}}: {{commit}} </p> <div>{{_('Current commit timestamp')}}: <span>{{commit}} </span></div>
<div class="btn btn-default" data-toggle="modal" data-target="#RestartDialog">{{_('Restart Calibre-web')}}</a></div> <div class="hidden" id="update_info">{{_('Newest commit timestamp')}}: <span></span></div>
<div class="btn btn-default" data-toggle="modal" data-target="#ShutdownDialog">{{_('Stop Calibre-web')}}</a></div> <p></p>
<div class="btn btn-default" id="check_for_update">{{_('Check for update')}}</a></div> <div class="btn btn-default" data-toggle="modal" data-target="#RestartDialog">{{_('Restart Calibre-web')}}</div>
<a href="{{url_for('update')}}" class="btn btn-default hidden" id="perform_update">{{_('Perform Update')}}</a> <div class="btn btn-default" data-toggle="modal" data-target="#ShutdownDialog">{{_('Stop Calibre-web')}}</div>
<div class="btn btn-default" id="check_for_update">{{_('Check for update')}}</div>
<div class="btn btn-default hidden" id="perform_update" data-toggle="modal" data-target="#UpdateprogressDialog">{{_('Perform Update')}}</div>
{% endif %} {% endif %}
</div> </div>
<!-- Modal --> <!-- Modal -->
...@@ -88,15 +91,17 @@ ...@@ -88,15 +91,17 @@
<div class="modal-dialog modal-sm"> <div class="modal-dialog modal-sm">
<!-- Modal content--> <!-- Modal content-->
<div class="modal-content"> <div class="modal-content">
<div class="modal-header bg-info"> <div class="modal-header bg-info"></div>
</div>
<div class="modal-body text-center"> <div class="modal-body text-center">
<p>{{_('Do you really want to restart Calibre-web?')}}</p> <p>{{_('Do you really want to restart Calibre-web?')}}</p>
<button type="button" class="btn btn-default" id="restart" data-dismiss="modal">{{_('Ok')}}</button> <div id="spinner" class="spinner" style="display:none;">
<img id="img-spinner" src="/static/css/images/loading-icon.gif"/>
</div>
<p></p>
<button type="button" class="btn btn-default" id="restart" >{{_('Ok')}}</button>
<button type="button" class="btn btn-default" data-dismiss="modal">{{_('Back')}}</button> <button type="button" class="btn btn-default" data-dismiss="modal">{{_('Back')}}</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div id="ShutdownDialog" class="modal fade" role="dialog"> <div id="ShutdownDialog" class="modal fade" role="dialog">
...@@ -114,5 +119,23 @@ ...@@ -114,5 +119,23 @@
</div> </div>
</div> </div>
<div id="UpdateprogressDialog" class="modal fade" role="dialog">
<div class="modal-dialog modal-sm">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header bg-info text-center">
<span>{{_('Updating, please do not reload page')}}</span>
</div>
<div class="modal-body text-center">
<div id="spinner2" class="spinner2" style="display:none;">
<img id="img-spinner" src="/static/css/images/loading-icon.gif"/>
</div>
<p></p>
<div id="Updatecontent"></div>
<p></p>
<button type="button" class="btn btn-default hidden" id="updateFinished" data-dismiss="modal">{{_('Ok')}}</button>
</div>
</div>
</div>
</div>
{% endblock %} {% endblock %}
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
<div class="navbar-collapse collapse"> <div class="navbar-collapse collapse">
{% if g.user.is_authenticated or g.user.is_anonymous() %} {% if g.user.is_authenticated or g.user.is_anonymous() %}
<ul class="nav navbar-nav "> <ul class="nav navbar-nav ">
<li><a href="{{url_for('advanced_search')}}"><span class="glyphicon glyphicon-search"></span> {{_('Advanced Search')}}</a></li> <li><a href="{{url_for('advanced_search')}}"><span class="glyphicon glyphicon-search"></span><span class="hidden-sm"> {{_('Advanced Search')}}</span></a></li>
</ul> </ul>
{% endif %} {% endif %}
<ul class="nav navbar-nav navbar-right" id="main-nav"> <ul class="nav navbar-nav navbar-right" id="main-nav">
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
import mimetypes import mimetypes
import logging import logging
from logging.handlers import RotatingFileHandler from logging.handlers import RotatingFileHandler
from tempfile import gettempdir
import textwrap import textwrap
from flask import Flask, render_template, session, request, Response, redirect, url_for, send_from_directory, \ from flask import Flask, render_template, session, request, Response, redirect, url_for, send_from_directory, \
make_response, g, flash, abort make_response, g, flash, abort
...@@ -39,9 +38,10 @@ import sys ...@@ -39,9 +38,10 @@ import sys
import subprocess import subprocess
import re import re
import db import db
import thread
from shutil import move, copyfile from shutil import move, copyfile
from tornado.ioloop import IOLoop from tornado.ioloop import IOLoop
import StringIO
try: try:
from wand.image import Image from wand.image import Image
...@@ -51,9 +51,6 @@ except ImportError, e: ...@@ -51,9 +51,6 @@ except ImportError, e:
use_generic_pdf_cover = True use_generic_pdf_cover = True
from cgi import escape from cgi import escape
# Global variables
global_task = None
# Proxy Helper class # Proxy Helper class
class ReverseProxied(object): class ReverseProxied(object):
...@@ -668,7 +665,7 @@ def get_opds_download_link(book_id, format): ...@@ -668,7 +665,7 @@ def get_opds_download_link(book_id, format):
file_name = book.title file_name = book.title
if len(book.authors) > 0: if len(book.authors) > 0:
file_name = book.authors[0].name + '-' + file_name file_name = book.authors[0].name + '-' + file_name
file_name = helper.get_valid_filename(file_name) # file_name = helper.get_valid_filename(file_name)
response = make_response(send_from_directory(os.path.join(config.config_calibre_dir, book.path), data.name + "." + format)) response = make_response(send_from_directory(os.path.join(config.config_calibre_dir, book.path), data.name + "." + format))
response.headers["Content-Disposition"] = "attachment; filename=\"%s.%s\"" % (data.name, format) response.headers["Content-Disposition"] = "attachment; filename=\"%s.%s\"" % (data.name, format)
return response return response
...@@ -716,10 +713,39 @@ def get_update_status(): ...@@ -716,10 +713,39 @@ def get_update_status():
commit = requests.get('https://api.github.com/repos/janeczku/calibre-web/git/refs/heads/master').json() commit = requests.get('https://api.github.com/repos/janeczku/calibre-web/git/refs/heads/master').json()
if "object" in commit and commit['object']['sha'] != commit_id: if "object" in commit and commit['object']['sha'] != commit_id:
status['status'] = True status['status'] = True
commitdate = requests.get('https://api.github.com/repos/janeczku/calibre-web/git/commits/'+commit['object']['sha']).json()
if "committer" in commitdate:
status['commit'] = commitdate['committer']['date']
else:
status['commit'] = u'Unknown'
else: else:
status['status'] = False status['status'] = False
return json.dumps(status) return json.dumps(status)
@app.route("/get_updater_status", methods=['GET','POST'])
@login_required
@admin_required
def get_updater_status():
status = {}
if request.method == "POST":
commit = request.form.to_dict()
if "start" in commit and commit['start'] == 'True':
text={
"1": _(u'Requesting update package'),
"2": _(u'Downloading update package'),
"3": _(u'Unzipping update package'),
"4": _(u'Files are replaced'),
"5": _(u'Database connections are closed'),
"6": _(u'Server is stopped'),
"7": _(u'Update finished, please press okay and reload page')
}
status['text']=text
helper.updater_thread = helper.Updater()
helper.updater_thread.start()
status['status']=helper.updater_thread.get_update_status()
elif request.method == "GET":
status['status']=helper.updater_thread.get_update_status()
return json.dumps(status)
@app.route("/get_languages_json", methods=['GET', 'POST']) @app.route("/get_languages_json", methods=['GET', 'POST'])
...@@ -1032,7 +1058,7 @@ def shutdown(): ...@@ -1032,7 +1058,7 @@ def shutdown():
server.add_callback(server.stop) server.add_callback(server.stop)
showtext = {} showtext = {}
if task == 0: if task == 0:
showtext['text'] = _(u'Performing Restart, please reload page') showtext['text'] = _(u'Server restarted, please reload page')
else: else:
showtext['text'] = _(u'Performing shutdown of server, please close window') showtext['text'] = _(u'Performing shutdown of server, please close window')
return json.dumps(showtext) return json.dumps(showtext)
...@@ -1043,23 +1069,10 @@ def shutdown(): ...@@ -1043,23 +1069,10 @@ def shutdown():
@login_required @login_required
@admin_required @admin_required
def update(): def update():
global global_task helper.updater_thread = helper.Updater()
r = requests.get('https://api.github.com/repos/janeczku/calibre-web/zipball/master', stream=True)
fname = re.findall("filename=(.+)", r.headers['content-disposition'])[0]
z = zipfile.ZipFile(StringIO.StringIO(r.content))
tmp_dir = gettempdir()
z.extractall(tmp_dir)
helper.update_source(os.path.join(tmp_dir,os.path.splitext(fname)[0]),config.get_main_dir)
global_task = 0
db.session.close()
db.engine.dispose()
ub.session.close()
ub.engine.dispose()
# stop tornado server
server = IOLoop.instance()
server.add_callback(server.stop)
flash(_(u"Update done"), category="info") flash(_(u"Update done"), category="info")
return logout() return ""
@app.route("/search", methods=["GET"]) @app.route("/search", methods=["GET"])
@login_required_if_no_ano @login_required_if_no_ano
...@@ -1605,7 +1618,6 @@ def configuration_helper(origin): ...@@ -1605,7 +1618,6 @@ def configuration_helper(origin):
if request.method == "POST": if request.method == "POST":
to_save = request.form.to_dict() to_save = request.form.to_dict()
content = ub.session.query(ub.Settings).first() content = ub.session.query(ub.Settings).first()
# ToDo: check lib vaild, and change without restart
if "config_calibre_dir" in to_save: if "config_calibre_dir" in to_save:
if content.config_calibre_dir != to_save["config_calibre_dir"]: if content.config_calibre_dir != to_save["config_calibre_dir"]:
content.config_calibre_dir = to_save["config_calibre_dir"] content.config_calibre_dir = to_save["config_calibre_dir"]
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment