mirror of
				https://github.com/janeczku/calibre-web
				synced 2025-10-31 07:13:02 +00:00 
			
		
		
		
	Added option to save books with no nenglish characters
Imporvements on metadata search
This commit is contained in:
		| @@ -1208,6 +1208,7 @@ def _configuration_update_helper(): | |||||||
|             return _configuration_result(_('Certfile Location is not Valid, Please Enter Correct Path')) |             return _configuration_result(_('Certfile Location is not Valid, Please Enter Correct Path')) | ||||||
|  |  | ||||||
|         _config_checkbox_int(to_save, "config_uploading") |         _config_checkbox_int(to_save, "config_uploading") | ||||||
|  |         _config_checkbox_int(to_save, "config_unicode_filename") | ||||||
|         # Reboot on config_anonbrowse with enabled ldap, as decoraters are changed in this case |         # Reboot on config_anonbrowse with enabled ldap, as decoraters are changed in this case | ||||||
|         reboot_required |= (_config_checkbox_int(to_save, "config_anonbrowse") |         reboot_required |= (_config_checkbox_int(to_save, "config_anonbrowse") | ||||||
|                              and config.config_login_type == constants.LOGIN_LDAP) |                              and config.config_login_type == constants.LOGIN_LDAP) | ||||||
|   | |||||||
| @@ -133,6 +133,7 @@ class _Settings(_Base): | |||||||
|     config_calibre = Column(String) |     config_calibre = Column(String) | ||||||
|     config_rarfile_location = Column(String, default=None) |     config_rarfile_location = Column(String, default=None) | ||||||
|     config_upload_formats = Column(String, default=','.join(constants.EXTENSIONS_UPLOAD)) |     config_upload_formats = Column(String, default=','.join(constants.EXTENSIONS_UPLOAD)) | ||||||
|  |     config_unicode_filename =Column(Boolean, default=False) | ||||||
|  |  | ||||||
|     config_updatechannel = Column(Integer, default=constants.UPDATE_STABLE) |     config_updatechannel = Column(Integer, default=constants.UPDATE_STABLE) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -230,16 +230,14 @@ def get_valid_filename(value, replace_whitespace=True): | |||||||
|         value = value[:-1]+u'_' |         value = value[:-1]+u'_' | ||||||
|     value = value.replace("/", "_").replace(":", "_").strip('\0') |     value = value.replace("/", "_").replace(":", "_").strip('\0') | ||||||
|     if use_unidecode: |     if use_unidecode: | ||||||
|  |         if config.config_unicode_filename: | ||||||
|             value = (unidecode.unidecode(value)) |             value = (unidecode.unidecode(value)) | ||||||
|     else: |     else: | ||||||
|         value = value.replace(u'§', u'SS') |         value = value.replace(u'§', u'SS') | ||||||
|         value = value.replace(u'ß', u'ss') |         value = value.replace(u'ß', u'ss') | ||||||
|         value = unicodedata.normalize('NFKD', value) |         value = unicodedata.normalize('NFKD', value) | ||||||
|         re_slugify = re.compile(r'[\W\s-]', re.UNICODE) |         re_slugify = re.compile(r'[\W\s-]', re.UNICODE) | ||||||
|         if isinstance(value, str):  # Python3 str, Python2 unicode |  | ||||||
|         value = re_slugify.sub('', value) |         value = re_slugify.sub('', value) | ||||||
|         else: |  | ||||||
|             value = unicode(re_slugify.sub('', value)) |  | ||||||
|     if replace_whitespace: |     if replace_whitespace: | ||||||
|         #  *+:\"/<>? are replaced by _ |         #  *+:\"/<>? are replaced by _ | ||||||
|         value = re.sub(r'[*+:\\\"/<>?]+', u'_', value, flags=re.U) |         value = re.sub(r'[*+:\\\"/<>?]+', u'_', value, flags=re.U) | ||||||
| @@ -248,10 +246,7 @@ def get_valid_filename(value, replace_whitespace=True): | |||||||
|     value = value[:128].strip() |     value = value[:128].strip() | ||||||
|     if not value: |     if not value: | ||||||
|         raise ValueError("Filename cannot be empty") |         raise ValueError("Filename cannot be empty") | ||||||
|     if sys.version_info.major == 3: |  | ||||||
|     return value |     return value | ||||||
|     else: |  | ||||||
|         return value.decode('utf-8') |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def split_authors(values): | def split_authors(values): | ||||||
| @@ -838,8 +833,8 @@ def get_download_link(book_id, book_format, client): | |||||||
|             ub.update_download(book_id, int(current_user.id)) |             ub.update_download(book_id, int(current_user.id)) | ||||||
|         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 = file_name + ' - ' + book.authors[0].name | ||||||
|         file_name = get_valid_filename(file_name) |         file_name = get_valid_filename(file_name, replace_whitespace=False) | ||||||
|         headers = Headers() |         headers = Headers() | ||||||
|         headers["Content-Type"] = mimetypes.types_map.get('.' + book_format, "application/octet-stream") |         headers["Content-Type"] = mimetypes.types_map.get('.' + book_format, "application/octet-stream") | ||||||
|         headers["Content-Disposition"] = "attachment; filename=%s.%s; filename*=UTF-8''%s.%s" % ( |         headers["Content-Disposition"] = "attachment; filename=%s.%s; filename*=UTF-8''%s.%s" % ( | ||||||
|   | |||||||
| @@ -41,7 +41,7 @@ class Google(Metadata): | |||||||
|                 v['tags'] = r['volumeInfo'].get('categories', []) |                 v['tags'] = r['volumeInfo'].get('categories', []) | ||||||
|                 v['rating'] = r['volumeInfo'].get('averageRating', 0) |                 v['rating'] = r['volumeInfo'].get('averageRating', 0) | ||||||
|                 if r['volumeInfo'].get('imageLinks'): |                 if r['volumeInfo'].get('imageLinks'): | ||||||
|                     v['cover'] = r['volumeInfo']['imageLinks']['thumbnail'] |                     v['cover'] = r['volumeInfo']['imageLinks']['thumbnail'].replace("http://", "https://") | ||||||
|                 else: |                 else: | ||||||
|                     v['cover'] = "/../../../static/generic_cover.jpg" |                     v['cover'] = "/../../../static/generic_cover.jpg" | ||||||
|                 v['source'] = { |                 v['source'] = { | ||||||
|   | |||||||
| @@ -26,8 +26,10 @@ import inspect | |||||||
| from flask import Blueprint, request, Response | from flask import Blueprint, request, Response | ||||||
| from flask_login import current_user | from flask_login import current_user | ||||||
| from flask_login import login_required | from flask_login import login_required | ||||||
|  | from sqlalchemy.orm.attributes import flag_modified | ||||||
|  | from sqlalchemy.exc import OperationalError, InvalidRequestError | ||||||
|  |  | ||||||
| from . import constants, logger | from . import constants, logger, ub | ||||||
| from cps.services.Metadata import Metadata | from cps.services.Metadata import Metadata | ||||||
|  |  | ||||||
| meta = Blueprint('metadata', __name__) | meta = Blueprint('metadata', __name__) | ||||||
| @@ -63,17 +65,29 @@ def metadata_provider(): | |||||||
|     active = current_user.view_settings.get('metadata', {}) |     active = current_user.view_settings.get('metadata', {}) | ||||||
|     provider = list() |     provider = list() | ||||||
|     for c in cl: |     for c in cl: | ||||||
|         provider.append({"name": c.__name__, "active": active.get(c.__name__, True), "id": c.__id__}) |         provider.append({"name": c.__name__, "active": active.get(c.__id__, True), "id": c.__id__}) | ||||||
|     return Response(json.dumps(provider), mimetype='application/json') |     return Response(json.dumps(provider), mimetype='application/json') | ||||||
|  |  | ||||||
| @meta.route("/metadata/provider", methods=['POST']) | @meta.route("/metadata/provider", methods=['POST']) | ||||||
| @login_required | @login_required | ||||||
| def metadata_change_active_provider(): | def metadata_change_active_provider(): | ||||||
|  |     new_state = request.get_json() | ||||||
|     active = current_user.view_settings.get('metadata', {}) |     active = current_user.view_settings.get('metadata', {}) | ||||||
|  |     active[new_state['id']] = new_state['value'] | ||||||
|  |     current_user.view_settings['metadata'] = active | ||||||
|  |     try: | ||||||
|  |         try: | ||||||
|  |             flag_modified(current_user, "view_settings") | ||||||
|  |         except AttributeError: | ||||||
|  |             pass | ||||||
|  |         ub.session.commit() | ||||||
|  |     except (InvalidRequestError, OperationalError): | ||||||
|  |         log.error("Invalid request received: {}".format(request)) | ||||||
|  |         return "Invalid request", 400 | ||||||
|     provider = list() |     provider = list() | ||||||
|     for c in cl: |     for c in cl: | ||||||
|         provider.append({"name": c.__name__, "active": active.get(c.__name__, True), "id": c.__id__}) |         provider.append({"name": c.__name__, "active": active.get(c.__id__, True), "id": c.__id__}) | ||||||
|     return Response(json.dumps(provider), mimetype='application/json') |     return "" # Response(json.dumps(provider), mimetype='application/json') | ||||||
|  |  | ||||||
| @meta.route("/metadata/search", methods=['POST']) | @meta.route("/metadata/search", methods=['POST']) | ||||||
| @login_required | @login_required | ||||||
| @@ -83,6 +97,6 @@ def metadata_search(): | |||||||
|     active = current_user.view_settings.get('metadata', {}) |     active = current_user.view_settings.get('metadata', {}) | ||||||
|     if query: |     if query: | ||||||
|         for c in cl: |         for c in cl: | ||||||
|             if active.get(c.__name__, True): |             if active.get(c.__id__, True): | ||||||
|                 data.extend(c.search(query)) |                 data.extend(c.search(query)) | ||||||
|     return Response(json.dumps(data), mimetype='application/json') |     return Response(json.dumps(data), mimetype='application/json') | ||||||
|   | |||||||
| @@ -123,6 +123,10 @@ table .bg-dark-danger a { color: #fff; } | |||||||
|   flex-wrap: wrap; |   flex-wrap: wrap; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .row-fluid.text-center { | ||||||
|  |     margin-top: -20px; | ||||||
|  | } | ||||||
|  |  | ||||||
| .container-fluid img { | .container-fluid img { | ||||||
|   display: block; |   display: block; | ||||||
|   max-width: 100%; |   max-width: 100%; | ||||||
| @@ -166,6 +170,10 @@ table .bg-dark-danger a { color: #fff; } | |||||||
|   box-shadow: 0 5px 8px -6px #777; |   box-shadow: 0 5px 8px -6px #777; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .datepicker.form-control { | ||||||
|  |     position: static; | ||||||
|  | } | ||||||
|  |  | ||||||
| .container-fluid .book .cover span img { | .container-fluid .book .cover span img { | ||||||
|   position: relative; |   position: relative; | ||||||
|   top: 0; |   top: 0; | ||||||
| @@ -322,7 +330,7 @@ table .bg-dark-danger:hover { background-color: #c9302c; } | |||||||
| table .bg-primary:hover { background-color: #1c5484; } | table .bg-primary:hover { background-color: #1c5484; } | ||||||
| .block-label { display: block; } | .block-label { display: block; } | ||||||
|  |  | ||||||
| .fake-input { | .form-control.fake-input { | ||||||
|   position: absolute; |   position: absolute; | ||||||
|   pointer-events: none; |   pointer-events: none; | ||||||
|   top: 0; |   top: 0; | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ $("#have_read_cb").on("change", function() { | |||||||
|             $("#flash_danger").remove(); |             $("#flash_danger").remove(); | ||||||
|             if (!jQuery.isEmptyObject(data)) { |             if (!jQuery.isEmptyObject(data)) { | ||||||
|                 data.forEach(function (item) { |                 data.forEach(function (item) { | ||||||
|                     $(".navbar").after('<div class="row-fluid text-center" style="margin-top: -20px;">' + |                     $(".navbar").after('<div class="row-fluid text-center" >' + | ||||||
|                         '<div id="flash_' + item.type + '" class="alert alert-' + item.type + '">' + item.message + '</div>' + |                         '<div id="flash_' + item.type + '" class="alert alert-' + item.type + '">' + item.message + '</div>' + | ||||||
|                         '</div>'); |                         '</div>'); | ||||||
|                 }); |                 }); | ||||||
|   | |||||||
| @@ -82,7 +82,6 @@ $(function () { | |||||||
|             success: function success(data) { |             success: function success(data) { | ||||||
|                 // console.log(data); |                 // console.log(data); | ||||||
|                 data.forEach(function(provider) { |                 data.forEach(function(provider) { | ||||||
|                     //$("#metadata_provider").html("<ul id=\"book-list\" class=\"media-list\"></ul>"); |  | ||||||
|                     var checked = ""; |                     var checked = ""; | ||||||
|                     if (provider.active) { |                     if (provider.active) { | ||||||
|                         checked = "checked"; |                         checked = "checked"; | ||||||
| @@ -94,6 +93,17 @@ $(function () { | |||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     $(document).on("change", ".pill", function () { | ||||||
|  |         var id = $(this).data("control"); | ||||||
|  |         var val = $(this).prop('checked'); | ||||||
|  |         $.ajax({ | ||||||
|  |             method:"post", | ||||||
|  |             contentType: "application/json; charset=utf-8", | ||||||
|  |             dataType: "json", | ||||||
|  |             url: getPath() + "/metadata/provider", | ||||||
|  |             data: JSON.stringify({id : id, value: val}), | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|     $("#meta-search").on("submit", function (e) { |     $("#meta-search").on("submit", function (e) { | ||||||
|         e.preventDefault(); |         e.preventDefault(); | ||||||
|   | |||||||
| @@ -172,7 +172,7 @@ $("#delete_confirm").click(function() { | |||||||
|                             if (item.format != "") { |                             if (item.format != "") { | ||||||
|                                 $("button[data-delete-format='"+item.format+"']").addClass('hidden'); |                                 $("button[data-delete-format='"+item.format+"']").addClass('hidden'); | ||||||
|                             } |                             } | ||||||
|                             $( ".navbar" ).after( '<div class="row-fluid text-center" style="margin-top: -20px;">' + |                             $( ".navbar" ).after( '<div class="row-fluid text-center" >' + | ||||||
|                                 '<div id="flash_'+item.type+'" class="alert alert-'+item.type+'">'+item.message+'</div>' + |                                 '<div id="flash_'+item.type+'" class="alert alert-'+item.type+'">'+item.message+'</div>' + | ||||||
|                                 '</div>'); |                                 '</div>'); | ||||||
|  |  | ||||||
| @@ -543,7 +543,7 @@ $(function() { | |||||||
|     function handle_response(data) { |     function handle_response(data) { | ||||||
|         if (!jQuery.isEmptyObject(data)) { |         if (!jQuery.isEmptyObject(data)) { | ||||||
|             data.forEach(function (item) { |             data.forEach(function (item) { | ||||||
|                 $(".navbar").after('<div class="row-fluid text-center" style="margin-top: -20px;">' + |                 $(".navbar").after('<div class="row-fluid text-center">' + | ||||||
|                     '<div id="flash_' + item.type + '" class="alert alert-' + item.type + '">' + item.message + '</div>' + |                     '<div id="flash_' + item.type + '" class="alert alert-' + item.type + '">' + item.message + '</div>' + | ||||||
|                     '</div>'); |                     '</div>'); | ||||||
|             }); |             }); | ||||||
|   | |||||||
| @@ -744,7 +744,7 @@ function handleListServerResponse (data) { | |||||||
|     $("#flash_danger").remove(); |     $("#flash_danger").remove(); | ||||||
|     if (!jQuery.isEmptyObject(data)) { |     if (!jQuery.isEmptyObject(data)) { | ||||||
|         data.forEach(function(item) { |         data.forEach(function(item) { | ||||||
|             $(".navbar").after('<div class="row-fluid text-center" style="margin-top: -20px;">' + |             $(".navbar").after('<div class="row-fluid text-center">' + | ||||||
|                 '<div id="flash_' + item.type + '" class="alert alert-' + item.type + '">' + item.message + '</div>' + |                 '<div id="flash_' + item.type + '" class="alert alert-' + item.type + '">' + item.message + '</div>' + | ||||||
|                 '</div>'); |                 '</div>'); | ||||||
|         }); |         }); | ||||||
|   | |||||||
| @@ -111,8 +111,8 @@ | |||||||
|     {% endif %} |     {% endif %} | ||||||
|     <label for="pubdate">{{_('Published Date')}}</label> |     <label for="pubdate">{{_('Published Date')}}</label> | ||||||
|     <div class="form-group input-group"> |     <div class="form-group input-group"> | ||||||
|        <input type="text" style="position: static;"  class="datepicker form-control" name="pubdate" id="pubdate" value="{% if book.pubdate %}{{book.pubdate|formatdateinput}}{% endif %}"> |        <input type="text" class="datepicker form-control" name="pubdate" id="pubdate" value="{% if book.pubdate %}{{book.pubdate|formatdateinput}}{% endif %}"> | ||||||
|        <input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_pubdate" value="{% if book.pubdate %}{{book.pubdate|formatdate}}{% endif %}"> |        <input type="text" class="form-control fake-input hidden" id="fake_pubdate" value="{% if book.pubdate %}{{book.pubdate|formatdate}}{% endif %}"> | ||||||
|       <span class="input-group-btn"> |       <span class="input-group-btn"> | ||||||
|         <button type="button" id="pubdate_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button> |         <button type="button" id="pubdate_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button> | ||||||
|       </span> |       </span> | ||||||
| @@ -156,11 +156,11 @@ | |||||||
|  |  | ||||||
|             {% if c.datatype == 'datetime' %} |             {% if c.datatype == 'datetime' %} | ||||||
|               <div class="input-group"> |               <div class="input-group"> | ||||||
|                 <input type="text" style="position: static;"  class="datepicker form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}" |                 <input type="text" class="datepicker form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}" | ||||||
|                   {% if book['custom_column_' ~ c.id]|length > 0 %} |                   {% if book['custom_column_' ~ c.id]|length > 0 %} | ||||||
|                     value="{% if book['custom_column_' ~ c.id][0].value  %}{{ book['custom_column_' ~ c.id][0].value|formatdateinput}}{% endif %}" |                     value="{% if book['custom_column_' ~ c.id][0].value  %}{{ book['custom_column_' ~ c.id][0].value|formatdateinput}}{% endif %}" | ||||||
|                   {% endif %}> |                   {% endif %}> | ||||||
|                 <input type="text" style="position: absolute;" class="fake_custom_column_{{ c.id }} form-control fake-input hidden" id="fake_pubdate" |                 <input type="text" class="fake_custom_column_{{ c.id }} form-control fake-input hidden" id="fake_pubdate_{{ c.id }}" | ||||||
|                   {% if book['custom_column_' ~ c.id]|length > 0 %} |                   {% if book['custom_column_' ~ c.id]|length > 0 %} | ||||||
|                     value="{% if book['custom_column_' ~ c.id][0].value %}{{book['custom_column_' ~ c.id][0].value|formatdate}}{% endif %}" |                     value="{% if book['custom_column_' ~ c.id][0].value %}{{book['custom_column_' ~ c.id][0].value|formatdate}}{% endif %}" | ||||||
|                   {% endif %}> |                   {% endif %}> | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| {% extends "layout.html" %} | {% extends "layout.html" %} | ||||||
| {% block flash %} | {% block flash %} | ||||||
| <div id="spinning_success" class="row-fluid text-center" style="margin-top: -20px; display:none;"> | <div id="spinning_success" class="row-fluid text-center" style="display:none;"> | ||||||
|     <div class="alert alert-info"><img id="img-spinner" src="{{ url_for('static', filename='css/libs/images/loading-icon.gif') }}"/></div> |     <div class="alert alert-info"><img id="img-spinner" src="{{ url_for('static', filename='css/libs/images/loading-icon.gif') }}"/></div> | ||||||
| </div> | </div> | ||||||
| {% endblock %} | {% endblock %} | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| {% extends "layout.html" %} | {% extends "layout.html" %} | ||||||
| {% block flash %} | {% block flash %} | ||||||
| <div id="spinning_success" class="row-fluid text-center" style="margin-top: -20px; display:none;"> | <div id="spinning_success" class="row-fluid text-center" style="display:none;"> | ||||||
|     <div class="alert alert-info"><img id="img-spinner" src="{{ url_for('static', filename='css/libs/images/loading-icon.gif') }}"/></div> |     <div class="alert alert-info"><img id="img-spinner" src="{{ url_for('static', filename='css/libs/images/loading-icon.gif') }}"/></div> | ||||||
| </div> | </div> | ||||||
| {% endblock %} | {% endblock %} | ||||||
| @@ -94,6 +94,10 @@ | |||||||
|     </div> |     </div> | ||||||
|     <div id="collapsefour" class="panel-collapse collapse"> |     <div id="collapsefour" class="panel-collapse collapse"> | ||||||
|       <div class="panel-body"> |       <div class="panel-body"> | ||||||
|  |     <div class="form-group"> | ||||||
|  |       <input type="checkbox" id="config_unicode_filename" name="config_unicode_filename" {% if config.config_unicode_filename %}checked{% endif %}> | ||||||
|  |       <label for="config_unicode_filename">{{_('Convert non-English characters in title and author while saving to disk')}}</label> | ||||||
|  |     </div> | ||||||
|     <div class="form-group"> |     <div class="form-group"> | ||||||
|         <input type="checkbox" id="config_uploading" data-control="upload_settings" name="config_uploading" {% if config.config_uploading %}checked{% endif %}> |         <input type="checkbox" id="config_uploading" data-control="upload_settings" name="config_uploading" {% if config.config_uploading %}checked{% endif %}> | ||||||
|         <label for="config_uploading">{{_('Enable Uploads')}}</label> |         <label for="config_uploading">{{_('Enable Uploads')}}</label> | ||||||
|   | |||||||
| @@ -91,22 +91,22 @@ | |||||||
|     </div> |     </div> | ||||||
|     {% for message in get_flashed_messages(with_categories=True) %} |     {% for message in get_flashed_messages(with_categories=True) %} | ||||||
|       {%if message[0] == "error" %} |       {%if message[0] == "error" %} | ||||||
|       <div class="row-fluid text-center" style="margin-top: -20px;"> |       <div class="row-fluid text-center" > | ||||||
|         <div id="flash_danger" class="alert alert-danger">{{ message[1] }}</div> |         <div id="flash_danger" class="alert alert-danger">{{ message[1] }}</div> | ||||||
|       </div> |       </div> | ||||||
|       {%endif%} |       {%endif%} | ||||||
|       {%if message[0] == "info" %} |       {%if message[0] == "info" %} | ||||||
|       <div class="row-fluid text-center" style="margin-top: -20px;"> |       <div class="row-fluid text-center"> | ||||||
|         <div id="flash_info" class="alert alert-info">{{ message[1] }}</div> |         <div id="flash_info" class="alert alert-info">{{ message[1] }}</div> | ||||||
|       </div> |       </div> | ||||||
|       {%endif%} |       {%endif%} | ||||||
|       {%if message[0] == "warning" %} |       {%if message[0] == "warning" %} | ||||||
|       <div class="row-fluid text-center" style="margin-top: -20px;"> |       <div class="row-fluid text-center"> | ||||||
|         <div id="flash_warning" class="alert alert-warning">{{ message[1] }}</div> |         <div id="flash_warning" class="alert alert-warning">{{ message[1] }}</div> | ||||||
|       </div> |       </div> | ||||||
|       {%endif%} |       {%endif%} | ||||||
|       {%if message[0] == "success" %} |       {%if message[0] == "success" %} | ||||||
|       <div class="row-fluid text-center" style="margin-top: -20px;"> |       <div class="row-fluid text-center"> | ||||||
|         <div id="flash_success" class="alert alert-success">{{ message[1] }}</div> |         <div id="flash_success" class="alert alert-success">{{ message[1] }}</div> | ||||||
|       </div> |       </div> | ||||||
|       {%endif%} |       {%endif%} | ||||||
|   | |||||||
| @@ -19,8 +19,8 @@ | |||||||
|       <div class="form-group col-sm-6"> |       <div class="form-group col-sm-6"> | ||||||
|         <label for="publishstart">{{_('Published Date From')}}</label> |         <label for="publishstart">{{_('Published Date From')}}</label> | ||||||
|         <div class="input-group"> |         <div class="input-group"> | ||||||
|           <input type="text" style="position: static;"  class="datepicker form-control" name="publish_start" id="publishstart" value=""> |           <input type="text" class="datepicker form-control" name="publish_start" id="publishstart" value=""> | ||||||
|           <input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_publishstart" value=""> |           <input type="text" class="form-control fake-input hidden" id="fake_publishstart" value=""> | ||||||
|           <span class="input-group-btn"> |           <span class="input-group-btn"> | ||||||
|             <button type="button" id="publishstart_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button> |             <button type="button" id="publishstart_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button> | ||||||
|           </span> |           </span> | ||||||
| @@ -29,8 +29,8 @@ | |||||||
|       <div class="form-group col-sm-6"> |       <div class="form-group col-sm-6"> | ||||||
|         <label for="publishend">{{_('Published Date To')}}</label> |         <label for="publishend">{{_('Published Date To')}}</label> | ||||||
|         <div class="input-group "> |         <div class="input-group "> | ||||||
|           <input type="text" style="position: static;"  class="datepicker form-control" name="publishend" id="publishend" value=""> |           <input type="text" class="datepicker form-control" name="publishend" id="publishend" value=""> | ||||||
|           <input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_publishend" value=""> |           <input type="text" class="form-control fake-input hidden" id="fake_publishend" value=""> | ||||||
|           <span class="input-group-btn"> |           <span class="input-group-btn"> | ||||||
|             <button type="button" id="publishend_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button> |             <button type="button" id="publishend_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button> | ||||||
|           </span> |           </span> | ||||||
| @@ -178,8 +178,8 @@ | |||||||
|         <div class="form-group col-sm-6"> |         <div class="form-group col-sm-6"> | ||||||
|           <label for="{{ 'custom_column_' ~ c.id }}">{{_('From:')}}</label> |           <label for="{{ 'custom_column_' ~ c.id }}">{{_('From:')}}</label> | ||||||
|           <div class="input-group"> |           <div class="input-group"> | ||||||
|             <input type="text" style="position: static;"  class="datepicker form-control" name="{{ 'custom_column_' ~ c.id }}_start" id="{{ 'custom_column_' ~ c.id }}_start" value=""> |             <input type="text" class="datepicker form-control" name="{{ 'custom_column_' ~ c.id }}_start" id="{{ 'custom_column_' ~ c.id }}_start" value=""> | ||||||
|             <input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_{{ 'custom_column_' ~ c.id }}_start" value=""> |             <input type="text" class="form-control fake-input hidden" id="fake_{{ 'custom_column_' ~ c.id }}_start" value=""> | ||||||
|             <span class="input-group-btn"> |             <span class="input-group-btn"> | ||||||
|               <button type="button" id="{{ 'custom_column_' ~ c.id }}_start_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button> |               <button type="button" id="{{ 'custom_column_' ~ c.id }}_start_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button> | ||||||
|             </span> |             </span> | ||||||
| @@ -188,8 +188,8 @@ | |||||||
|         <div class="form-group col-sm-6"> |         <div class="form-group col-sm-6"> | ||||||
|           <label for="{{ 'custom_column_' ~ c.id }}">{{_('To:')}}</label> |           <label for="{{ 'custom_column_' ~ c.id }}">{{_('To:')}}</label> | ||||||
|           <div class="input-group "> |           <div class="input-group "> | ||||||
|             <input type="text" style="position: static;"  class="datepicker form-control" name="{{ 'custom_column_' ~ c.id }}_end" id="{{ 'custom_column_' ~ c.id }}_end" value=""> |             <input type="text" class="datepicker form-control" name="{{ 'custom_column_' ~ c.id }}_end" id="{{ 'custom_column_' ~ c.id }}_end" value=""> | ||||||
|             <input type="text" style="position: absolute;" class="form-control fake-input hidden" id="fake_{{ 'custom_column_' ~ c.id }}_end" value=""> |             <input type="text" class="form-control fake-input hidden" id="fake_{{ 'custom_column_' ~ c.id }}_end" value=""> | ||||||
|             <span class="input-group-btn"> |             <span class="input-group-btn"> | ||||||
|               <button type="button" id="{{ 'custom_column_' ~ c.id }}_end_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button> |               <button type="button" id="{{ 'custom_column_' ~ c.id }}_end_delete" class="datepicker_delete btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></button> | ||||||
|             </span> |             </span> | ||||||
|   | |||||||
| @@ -178,7 +178,7 @@ | |||||||
| {{ restrict_modal() }} | {{ restrict_modal() }} | ||||||
| {% endblock %} | {% endblock %} | ||||||
| {% block js %} | {% block js %} | ||||||
| <script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-table.min.js') }}"></script> | <script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-table.js') }}"></script> | ||||||
| <script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-table-editable.min.js') }}"></script> | <script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-table-editable.min.js') }}"></script> | ||||||
| <script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-editable.min.js') }}"></script> | <script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-editable.min.js') }}"></script> | ||||||
| <script src="{{ url_for('static', filename='js/libs/bootstrap-select.min.js')}}"></script> | <script src="{{ url_for('static', filename='js/libs/bootstrap-select.min.js')}}"></script> | ||||||
|   | |||||||
| @@ -84,7 +84,7 @@ except ImportError: | |||||||
|  |  | ||||||
| @app.after_request | @app.after_request | ||||||
| def add_security_headers(resp): | def add_security_headers(resp): | ||||||
|     resp.headers['Content-Security-Policy']= "script-src 'self'" |     resp.headers['Content-Security-Policy']= "default-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src * data:" | ||||||
|     resp.headers['X-Content-Type-Options'] = 'nosniff' |     resp.headers['X-Content-Type-Options'] = 'nosniff' | ||||||
|     resp.headers['X-Frame-Options'] = 'SAMEORIGIN' |     resp.headers['X-Frame-Options'] = 'SAMEORIGIN' | ||||||
|     resp.headers['X-XSS-Protection'] = '1; mode=block' |     resp.headers['X-XSS-Protection'] = '1; mode=block' | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Ozzie Isaacs
					Ozzie Isaacs