mirror of
				https://github.com/janeczku/calibre-web
				synced 2025-10-31 07:13:02 +00:00 
			
		
		
		
	Merge with branch develop
Release version
This commit is contained in:
		
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -21,14 +21,12 @@ vendor/ | ||||
| # calibre-web | ||||
| *.db | ||||
| *.log | ||||
| config.ini | ||||
| cps/static/[0-9]* | ||||
|  | ||||
| .idea/ | ||||
| *.bak | ||||
| *.log.* | ||||
| tags | ||||
|  | ||||
| settings.yaml | ||||
| gdrive_credentials | ||||
| client_secrets.json | ||||
|  | ||||
|   | ||||
| @@ -43,7 +43,7 @@ parser.add_argument('-k', metavar='path', | ||||
|                     help='path and name to SSL keyfile, e.g. /opt/test.key, works only in combination with certfile') | ||||
| parser.add_argument('-v', '--version', action='version', help='Shows version number and exits Calibre-web', | ||||
|                     version=version_info()) | ||||
| parser.add_argument('-i', metavar='ip-adress', help='Server IP-Adress to listen') | ||||
| parser.add_argument('-i', metavar='ip-address', help='Server IP-Address to listen') | ||||
| parser.add_argument('-s', metavar='user:pass', help='Sets specific username to new password') | ||||
| args = parser.parse_args() | ||||
|  | ||||
|   | ||||
| @@ -106,7 +106,6 @@ except ValueError: | ||||
| del env_CALIBRE_PORT | ||||
|  | ||||
|  | ||||
|  | ||||
| EXTENSIONS_AUDIO    = {'mp3', 'm4a', 'm4b'} | ||||
| EXTENSIONS_CONVERT  = {'pdf', 'epub', 'mobi', 'azw3', 'docx', 'rtf', 'fb2', 'lit', 'lrf', 'txt', 'htmlz', 'rtf', 'odt'} | ||||
| EXTENSIONS_UPLOAD   = {'txt', 'pdf', 'epub', 'mobi', 'azw', 'azw3', 'cbr', 'cbz', 'cbt', 'djvu', 'prc', 'doc', 'docx', | ||||
| @@ -126,7 +125,7 @@ def selected_roles(dictionary): | ||||
| BookMeta = namedtuple('BookMeta', 'file_path, extension, title, author, cover, description, tags, series, ' | ||||
|                                   'series_id, languages') | ||||
|  | ||||
| STABLE_VERSION = {'version': '0.6.6 Beta'} | ||||
| STABLE_VERSION = {'version': '0.6.6'} | ||||
|  | ||||
| NIGHTLY_VERSION = {} | ||||
| NIGHTLY_VERSION[0] = '$Format:%H$' | ||||
|   | ||||
							
								
								
									
										11
									
								
								cps/db.py
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								cps/db.py
									
									
									
									
									
								
							| @@ -25,13 +25,13 @@ import ast | ||||
|  | ||||
| from sqlalchemy import create_engine | ||||
| from sqlalchemy import Table, Column, ForeignKey | ||||
| from sqlalchemy import String, Integer, Boolean | ||||
| from sqlalchemy import String, Integer, Boolean, Float | ||||
| from sqlalchemy.orm import relationship, sessionmaker, scoped_session | ||||
| from sqlalchemy.ext.declarative import declarative_base | ||||
|  | ||||
|  | ||||
| session = None | ||||
| cc_exceptions = ['datetime', 'comments', 'float', 'composite', 'series'] | ||||
| cc_exceptions = ['datetime', 'comments', 'composite', 'series'] | ||||
| cc_classes = {} | ||||
| engine = None | ||||
|  | ||||
| @@ -378,6 +378,11 @@ def setup_db(config): | ||||
|                               'id': Column(Integer, primary_key=True), | ||||
|                               'book': Column(Integer, ForeignKey('books.id')), | ||||
|                               'value': Column(Integer)} | ||||
|                 elif row.datatype == 'float': | ||||
|                     ccdict = {'__tablename__': 'custom_column_' + str(row.id), | ||||
|                               'id': Column(Integer, primary_key=True), | ||||
|                               'book': Column(Integer, ForeignKey('books.id')), | ||||
|                               'value': Column(Float)} | ||||
|                 else: | ||||
|                     ccdict = {'__tablename__': 'custom_column_' + str(row.id), | ||||
|                               'id': Column(Integer, primary_key=True), | ||||
| @@ -385,7 +390,7 @@ def setup_db(config): | ||||
|                 cc_classes[row.id] = type(str('Custom_Column_' + str(row.id)), (Base,), ccdict) | ||||
|  | ||||
|         for cc_id in cc_ids: | ||||
|             if (cc_id[1] == 'bool') or (cc_id[1] == 'int'): | ||||
|             if (cc_id[1] == 'bool') or (cc_id[1] == 'int') or (cc_id[1] == 'float'): | ||||
|                 setattr(Books, 'custom_column_' + str(cc_id[0]), relationship(cc_classes[cc_id[0]], | ||||
|                                                                            primaryjoin=( | ||||
|                                                                            Books.id == cc_classes[cc_id[0]].book), | ||||
|   | ||||
| @@ -175,7 +175,7 @@ def delete_book(book_id, book_format): | ||||
|                     cc_string = "custom_column_" + str(c.id) | ||||
|                     if not c.is_multiple: | ||||
|                         if len(getattr(book, cc_string)) > 0: | ||||
|                             if c.datatype == 'bool' or c.datatype == 'integer': | ||||
|                             if c.datatype == 'bool' or c.datatype == 'integer' or c.datatype == 'float': | ||||
|                                 del_cc = getattr(book, cc_string)[0] | ||||
|                                 getattr(book, cc_string).remove(del_cc) | ||||
|                                 db.session.delete(del_cc) | ||||
| @@ -254,7 +254,7 @@ def edit_cc_data(book_id, book, to_save): | ||||
|             else: | ||||
|                 cc_db_value = None | ||||
|             if to_save[cc_string].strip(): | ||||
|                 if c.datatype == 'int' or c.datatype == 'bool': | ||||
|                 if c.datatype == 'int' or c.datatype == 'bool' or c.datatype == 'float': | ||||
|                     if to_save[cc_string] == 'None': | ||||
|                         to_save[cc_string] = None | ||||
|                     elif c.datatype == 'bool': | ||||
| @@ -697,7 +697,6 @@ def upload(): | ||||
|             # Reread book. It's important not to filter the result, as it could have language which hide it from | ||||
|             # current users view (tags are not stored/extracted from metadata and could also be limited) | ||||
|             book = db.session.query(db.Books).filter(db.Books.id == book_id).first() | ||||
|  | ||||
|             # upload book to gdrive if nesseccary and add "(bookid)" to folder name | ||||
|             if config.config_use_google_drive: | ||||
|                 gdriveutils.updateGdriveCalibreFromLocal() | ||||
|   | ||||
| @@ -156,7 +156,7 @@ class WebServer(object): | ||||
|                                  max_buffer_size=209700000, | ||||
|                                  ssl_options=self.ssl_args) | ||||
|         http_server.listen(self.listen_port, self.listen_address) | ||||
|         self.wsgiserver = IOLoop.instance() | ||||
|         self.wsgiserver = IOLoop.current() | ||||
|         self.wsgiserver.start() | ||||
|         # wait for stop signal | ||||
|         self.wsgiserver.close(True) | ||||
| @@ -177,6 +177,8 @@ class WebServer(object): | ||||
|  | ||||
|         if not self.restart: | ||||
|             log.info("Performing shutdown of Calibre-Web") | ||||
|             # prevent irritiating log of pending tasks message from asyncio | ||||
|             logger.get('asyncio').setLevel(logger.logging.CRITICAL) | ||||
|             return True | ||||
|  | ||||
|         log.info("Performing restart of Calibre-Web") | ||||
| @@ -197,4 +199,4 @@ class WebServer(object): | ||||
|             if _GEVENT: | ||||
|                 self.wsgiserver.close() | ||||
|             else: | ||||
|                 self.wsgiserver.add_callback(self.wsgiserver.stop) | ||||
|                 self.wsgiserver.add_callback_from_signal(self.wsgiserver.stop) | ||||
|   | ||||
| @@ -159,10 +159,12 @@ if ( $( 'body.book' ).length > 0 ) { | ||||
|   real_custom_column = $( '.real_custom_columns' ); | ||||
|     // $( '.real_custom_columns' ).remove(); | ||||
|     $.each(real_custom_column, function(i, val) { | ||||
|         real_cc = $(this).text().split( ':' ); | ||||
|         var split = $(this).text().split( ':' ); | ||||
|         real_cc_key = split.shift(); | ||||
|         real_cc_value = split.join(':'); | ||||
|         $( this ).text(""); | ||||
|         if (real_cc.length > 1) { | ||||
|             $( this ).append( '<span>' + real_cc[0] + '</span><span>' + real_cc[1] + '</span>' ); | ||||
|         if (real_cc_value != "") { | ||||
|             $( this ).append( '<span>' + real_cc_key + '</span><span>' + real_cc_value + '</span>' ); | ||||
|         } | ||||
|     }); | ||||
|   //$( '.real_custom_columns:nth-child(3)' ).text(function() { | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| {% extends "layout.html" %} | ||||
| {% block body %} | ||||
| {% if book %} | ||||
|  | ||||
|  | ||||
|   <div class="col-sm-3 col-lg-3 col-xs-12"> | ||||
|     <div class="cover"> | ||||
|         <img src="{{ url_for('web.get_cover', book_id=book.id) }}" alt="{{ book.title }}"/> | ||||
| @@ -115,8 +113,8 @@ | ||||
|               </select> | ||||
|             {% endif %} | ||||
|  | ||||
|             {% if c.datatype == 'int' %} | ||||
|               <input type="number" step="1" class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}" value="{% if book['custom_column_' ~ c.id]|length > 0 %}{{ book['custom_column_' ~ c.id][0].value }}{% endif %}"> | ||||
|             {% if c.datatype == 'int' or c.datatype == 'float' %} | ||||
| 	    <input type="number" step="{% if c.datatype == 'float' %}0.01{% else %}1{% endif %}" class="form-control" name="{{ 'custom_column_' ~ c.id }}" id="{{ 'custom_column_' ~ c.id }}" value="{% if book['custom_column_' ~ c.id]|length > 0 %}{{ book['custom_column_' ~ c.id][0].value }}{% endif %}"> | ||||
|             {% endif %} | ||||
|  | ||||
|             {% if c.datatype in ['text', 'series'] and not c.is_multiple %} | ||||
|   | ||||
| @@ -44,7 +44,7 @@ | ||||
|               <label for="query" class="sr-only">{{_('Search')}}</label> | ||||
|               <input type="text" class="form-control" id="query" name="query" placeholder="{{_('Search')}}"> | ||||
|               <span class="input-group-btn"> | ||||
|                 <button type="submit" class="btn btn-default">{{_('Go!')}}</button> | ||||
|                 <button type="submit" id="query_submit" class="btn btn-default">{{_('Go!')}}</button> | ||||
|               </span> | ||||
|             </div> | ||||
|           </form> | ||||
| @@ -52,7 +52,7 @@ | ||||
|         <div class="navbar-collapse collapse"> | ||||
|           {% if g.user.is_authenticated or g.allow_anonymous %} | ||||
|           <ul class="nav navbar-nav "> | ||||
|             <li><a href="{{url_for('web.advanced_search')}}"><span class="glyphicon glyphicon-search"></span><span class="hidden-sm">{{_('Advanced Search')}}</span></a></li> | ||||
|             <li><a href="{{url_for('web.advanced_search')}}" id="advanced_search"><span class="glyphicon glyphicon-search"></span><span class="hidden-sm">{{_('Advanced Search')}}</span></a></li> | ||||
|           </ul> | ||||
|           {% endif %} | ||||
|           <ul class="nav navbar-nav navbar-right" id="main-nav"> | ||||
| @@ -229,7 +229,6 @@ | ||||
|             }); | ||||
|         }); | ||||
|     </script> | ||||
|  | ||||
|     {% block js %}{% endblock %} | ||||
|   </body> | ||||
| </html> | ||||
|   | ||||
| @@ -167,7 +167,7 @@ | ||||
|       {% endfor %} | ||||
|     {% endif %} | ||||
|  | ||||
|     <button type="submit" class="btn btn-default">{{_('Submit')}}</button> | ||||
|     <button type="submit" id="adv_submit" class="btn btn-default">{{_('Submit')}}</button> | ||||
|   </form> | ||||
| </div> | ||||
| {% endblock %} | ||||
|   | ||||
| @@ -5,19 +5,19 @@ | ||||
|     <div>{{_('Drag \'n drop to rearrange order')}}</div> | ||||
|       <div id="sortTrue" class="list-group"> | ||||
|         {% for entry in entries %} | ||||
|           <div id="{{entry.id}}" class="list-group-item"> | ||||
|           <div id="{{entry['id']}}" class="list-group-item"> | ||||
|             <div class="row"> | ||||
|               <div class="col-lg-2 col-sm-4 hidden-xs"> | ||||
|                   <img class="cover-height" src="{{ url_for('web.get_cover', book_id=entry.id) }}"> | ||||
|                   <img class="cover-height" src="{{ url_for('web.get_cover', book_id=entry['id']) }}"> | ||||
|               </div> | ||||
|               <div class="col-lg-10 col-sm-8 col-xs-12"> | ||||
|                   {{entry.title}} | ||||
|                   {% if entry.series|length > 0 %} | ||||
|                   {{entry['title']}} | ||||
|                   {% if entry['series']|length > 0 %} | ||||
|                     <br> | ||||
|                     {{entry.series_index}} - {{entry.series[0].name}} | ||||
|                     {{entry['series_index']}} - {{entry['series'][0].name}} | ||||
|                   {% endif %} | ||||
|                   <br> | ||||
|                   {% for author in entry.authors %} | ||||
|                   {% for author in entry['authors'] %} | ||||
|                     {{author.name.replace('|',',')}} | ||||
|                     {% if not loop.last %} | ||||
|                       & | ||||
|   | ||||
| @@ -46,7 +46,6 @@ | ||||
|             {% endfor %} | ||||
|         </select> | ||||
|     </div> | ||||
|  | ||||
|     {% if registered_oauth.keys()| length > 0 %} | ||||
|       {% for id, name in registered_oauth.items() %} | ||||
|     <div class="form-group"> | ||||
| @@ -60,7 +59,6 @@ | ||||
|     </div> | ||||
|  | ||||
|     {% endif %} | ||||
|  | ||||
|     <div class="col-sm-6"> | ||||
|         {% for element in sidebar %} | ||||
|           {% if element['config_show'] %} | ||||
|   | ||||
| @@ -307,7 +307,7 @@ class RemoteAuthToken(Base): | ||||
|     __tablename__ = 'remote_auth_token' | ||||
|  | ||||
|     id = Column(Integer, primary_key=True) | ||||
|     auth_token = Column(String(8), unique=True) | ||||
|     auth_token = Column(String, unique=True) | ||||
|     user_id = Column(Integer, ForeignKey('user.id')) | ||||
|     verified = Column(Boolean, default=False) | ||||
|     expiration = Column(DateTime) | ||||
|   | ||||
| @@ -198,7 +198,7 @@ class Updater(threading.Thread): | ||||
|         ) | ||||
|         additional_path = self.is_venv() | ||||
|         if additional_path: | ||||
|             exclude = exclude + (additional_path) | ||||
|             exclude = exclude + (additional_path,) | ||||
|         for root, dirs, files in os.walk(destination, topdown=True): | ||||
|             for name in files: | ||||
|                 old_list.append(os.path.join(root, name).replace(destination, '')) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Ozzieisaacs
					Ozzieisaacs