Content server: Show custom column data in the book listing

This commit is contained in:
Kovid Goyal 2010-09-03 11:37:51 -06:00
commit 2d85288855
5 changed files with 105 additions and 12 deletions

View File

@ -50,7 +50,7 @@ function render_book(book) {
var comments = $.trim(book.text()).replace(/\n\n/, '<br/>'); var comments = $.trim(book.text()).replace(/\n\n/, '<br/>');
var formats = new Array(); var formats = new Array();
var size = (parseFloat(book.attr('size'))/(1024*1024)).toFixed(1); var size = (parseFloat(book.attr('size'))/(1024*1024)).toFixed(1);
var tags = book.attr('tags').replace(/,/g, ', '); var tags = book.attr('tags')
formats = book.attr("formats").split(","); formats = book.attr("formats").split(",");
if (formats.length > 0) { if (formats.length > 0) {
for (i=0; i < formats.length; i++) { for (i=0; i < formats.length; i++) {
@ -59,7 +59,14 @@ function render_book(book) {
title = title.slice(0, title.length-2); title = title.slice(0, title.length-2);
title += '&nbsp;({0}&nbsp;MB)&nbsp;'.format(size); title += '&nbsp;({0}&nbsp;MB)&nbsp;'.format(size);
} }
if (tags) title += '[{0}]'.format(tags); if (tags) title += 'Tags=[{0}] '.format(tags);
custcols = book.attr("custcols").split(',')
for ( i = 0; i < custcols.length; i++) {
if (custcols[i].length > 0) {
vals = book.attr(custcols[i]).split(':#:', 2);
title += '{0}=[{1}] '.format(vals[0], vals[1]);
}
}
title += '<img style="display:none" alt="" src="get/cover/{0}" /></span>'.format(id); title += '<img style="display:none" alt="" src="get/cover/{0}" /></span>'.format(id);
title += '<div class="comments">{0}</div>'.format(comments) title += '<div class="comments">{0}</div>'.format(comments)
// Render authors cell // Render authors cell
@ -290,7 +297,7 @@ function layout() {
} }
$(function() { $(function() {
// document is ready // document is ready
create_table_headers(); create_table_headers();
// Setup widgets // Setup widgets

View File

@ -110,3 +110,7 @@ grouped_search_terms = {}
# a book' are added when copying books to another library # a book' are added when copying books to another library
add_new_book_tags_when_importing_books = False add_new_book_tags_when_importing_books = False
# Set the maximum number of tags to show per book in the content server
max_content_server_tags_shown=5

View File

@ -13,11 +13,11 @@ from lxml import html
from lxml.html.builder import HTML, HEAD, TITLE, LINK, DIV, IMG, BODY, \ from lxml.html.builder import HTML, HEAD, TITLE, LINK, DIV, IMG, BODY, \
OPTION, SELECT, INPUT, FORM, SPAN, TABLE, TR, TD, A, HR OPTION, SELECT, INPUT, FORM, SPAN, TABLE, TR, TD, A, HR
from calibre.library.server.utils import strftime from calibre.library.server.utils import strftime, format_tag_string
from calibre.ebooks.metadata import fmt_sidx from calibre.ebooks.metadata import fmt_sidx
from calibre.constants import __appname__ from calibre.constants import __appname__
from calibre import human_readable from calibre import human_readable
from calibre.utils.date import utcfromtimestamp from calibre.utils.date import utcfromtimestamp, format_date
def CLASS(*args, **kwargs): # class is a reserved word in Python def CLASS(*args, **kwargs): # class is a reserved word in Python
kwargs['class'] = ' '.join(args) kwargs['class'] = ' '.join(args)
@ -85,7 +85,7 @@ def build_navigation(start, num, total, url_base): # {{{
# }}} # }}}
def build_index(books, num, search, sort, order, start, total, url_base): def build_index(books, num, search, sort, order, start, total, url_base, CKEYS):
logo = DIV(IMG(src='/static/calibre.png', alt=__appname__), id='logo') logo = DIV(IMG(src='/static/calibre.png', alt=__appname__), id='logo')
search_box = build_search_box(num, search, sort, order) search_box = build_search_box(num, search, sort, order)
@ -123,10 +123,16 @@ def build_index(books, num, search, sort, order, start, total, url_base):
series = u'[%s - %s]'%(book['series'], book['series_index']) \ series = u'[%s - %s]'%(book['series'], book['series_index']) \
if book['series'] else '' if book['series'] else ''
tags = u'[%s]'%book['tags'] if book['tags'] else '' tags = u'Tags=[%s]'%book['tags'] if book['tags'] else ''
text = u'\u202f%s %s by %s - %s - %s %s' % (book['title'], series, ctext = ''
book['authors'], book['size'], book['timestamp'], tags) for key in CKEYS:
val = book.get(key, None)
if val:
ctext += '%s=[%s] '%tuple(val.split(':#:'))
text = u'\u202f%s %s by %s - %s - %s %s %s' % (book['title'], series,
book['authors'], book['size'], book['timestamp'], tags, ctext)
if last is None: if last is None:
data.text = text data.text = text
@ -189,6 +195,10 @@ class MobileServer(object):
if sort is not None: if sort is not None:
self.sort(items, sort, (order.lower().strip() == 'ascending')) self.sort(items, sort, (order.lower().strip() == 'ascending'))
CFM = self.db.field_metadata
CKEYS = [key for key in sorted(CFM.get_custom_fields(),
cmp=lambda x,y: cmp(CFM[x]['name'].lower(),
CFM[y]['name'].lower()))]
books = [] books = []
for record in items[(start-1):(start-1)+num]: for record in items[(start-1):(start-1)+num]:
book = {'formats':record[FM['formats']], 'size':record[FM['size']]} book = {'formats':record[FM['formats']], 'size':record[FM['size']]}
@ -203,12 +213,37 @@ class MobileServer(object):
book['authors'] = authors book['authors'] = authors
book['series_index'] = fmt_sidx(float(record[FM['series_index']])) book['series_index'] = fmt_sidx(float(record[FM['series_index']]))
book['series'] = record[FM['series']] book['series'] = record[FM['series']]
book['tags'] = record[FM['tags']] book['tags'] = format_tag_string(record[FM['tags']], ',')
book['title'] = record[FM['title']] book['title'] = record[FM['title']]
for x in ('timestamp', 'pubdate'): for x in ('timestamp', 'pubdate'):
book[x] = strftime('%Y/%m/%d %H:%M:%S', record[FM[x]]) book[x] = strftime('%Y/%m/%d %H:%M:%S', record[FM[x]])
book['id'] = record[FM['id']] book['id'] = record[FM['id']]
books.append(book) books.append(book)
for key in CKEYS:
def concat(name, val):
return '%s:#:%s'%(name, unicode(val))
val = record[CFM[key]['rec_index']]
if val:
datatype = CFM[key]['datatype']
if datatype in ['comments']:
continue
name = CFM[key]['name']
if datatype == 'text' and CFM[key]['is_multiple']:
book[key] = concat(name, format_tag_string(val, '|'))
elif datatype == 'series':
book[key] = concat(name, '%s [%s]'%(val,
fmt_sidx(record[CFM.cc_series_index_column_for(key)])))
elif datatype == 'datetime':
book[key] = concat(name,
format_date(val, CFM[key]['display'].get('date_format','dd MMM yyyy')))
elif datatype == 'bool':
if val:
book[key] = concat(name, __builtin__._('Yes'))
else:
book[key] = concat(name, __builtin__._('No'))
else:
book[key] = concat(name, val)
updated = self.db.last_modified() updated = self.db.last_modified()
cherrypy.response.headers['Content-Type'] = 'text/html; charset=utf-8' cherrypy.response.headers['Content-Type'] = 'text/html; charset=utf-8'
@ -218,7 +253,7 @@ class MobileServer(object):
url_base = "/mobile?search=" + search+";order="+order+";sort="+sort+";num="+str(num) url_base = "/mobile?search=" + search+";order="+order+";sort="+sort+";num="+str(num)
return html.tostring(build_index(books, num, search, sort, order, return html.tostring(build_index(books, num, search, sort, order,
start, len(ids), url_base), start, len(ids), url_base, CKEYS),
encoding='utf-8', include_meta_content_type=True, encoding='utf-8', include_meta_content_type=True,
pretty_print=True) pretty_print=True)

View File

@ -11,6 +11,7 @@ import cherrypy
from calibre import strftime as _strftime, prints from calibre import strftime as _strftime, prints
from calibre.utils.date import now as nowf from calibre.utils.date import now as nowf
from calibre.utils.config import tweaks
def expose(func): def expose(func):
@ -43,4 +44,14 @@ def strftime(fmt='%Y/%m/%d %H:%M:%S', dt=None):
except: except:
return _strftime(fmt, nowf().timetuple()) return _strftime(fmt, nowf().timetuple())
def format_tag_string(tags, sep):
MAX = tweaks['max_content_server_tags_shown']
if tags:
tlist = [t.strip() for t in tags.split(sep)]
else:
tlist = []
tlist.sort(cmp=lambda x,y:cmp(x.lower(), y.lower()))
if len(tlist) > MAX:
tlist = tlist[:MAX]+['...']
return u'%s'%(', '.join(tlist)) if tlist else ''

View File

@ -11,10 +11,11 @@ import cherrypy
from lxml.builder import ElementMaker from lxml.builder import ElementMaker
from lxml import etree from lxml import etree
from calibre.library.server.utils import strftime from calibre.library.server.utils import strftime, format_tag_string
from calibre.ebooks.metadata import fmt_sidx from calibre.ebooks.metadata import fmt_sidx
from calibre.constants import preferred_encoding from calibre.constants import preferred_encoding
from calibre import isbytestring from calibre import isbytestring
from calibre.utils.date import format_date
E = ElementMaker() E = ElementMaker()
@ -83,9 +84,44 @@ class XMLServer(object):
for x in ('isbn', 'formats', 'series', 'tags', 'publisher', for x in ('isbn', 'formats', 'series', 'tags', 'publisher',
'comments'): 'comments'):
y = record[FM[x]] y = record[FM[x]]
if x == 'tags':
y = format_tag_string(y, ',')
kwargs[x] = serialize(y) if y else '' kwargs[x] = serialize(y) if y else ''
c = kwargs.pop('comments') c = kwargs.pop('comments')
CFM = self.db.field_metadata
CKEYS = [key for key in sorted(CFM.get_custom_fields(),
cmp=lambda x,y: cmp(CFM[x]['name'].lower(),
CFM[y]['name'].lower()))]
custcols = []
for key in CKEYS:
def concat(name, val):
return '%s:#:%s'%(name, unicode(val))
val = record[CFM[key]['rec_index']]
if val:
datatype = CFM[key]['datatype']
if datatype in ['comments']:
continue
k = str('CF_'+key[1:])
name = CFM[key]['name']
custcols.append(k)
if datatype == 'text' and CFM[key]['is_multiple']:
kwargs[k] = concat(name, format_tag_string(val,'|'))
elif datatype == 'series':
kwargs[k] = concat(name, '%s [%s]'%(val,
fmt_sidx(record[CFM.cc_series_index_column_for(key)])))
elif datatype == 'datetime':
kwargs[k] = concat(name,
format_date(val, CFM[key]['display'].get('date_format','dd MMM yyyy')))
elif datatype == 'bool':
if val:
kwargs[k] = concat(name, __builtin__._('Yes'))
else:
kwargs[k] = concat(name, __builtin__._('No'))
else:
kwargs[k] = concat(name, val)
kwargs['custcols'] = ','.join(custcols)
books.append(E.book(c, **kwargs)) books.append(E.book(c, **kwargs))
updated = self.db.last_modified() updated = self.db.last_modified()