mirror of
https://github.com/janeczku/calibre-web
synced 2024-11-24 10:37:23 +00:00
Improvements for books table editor
This commit is contained in:
parent
94b5ec91cc
commit
1c681ee378
@ -240,7 +240,10 @@ class Languages(Base):
|
||||
self.lang_code = lang_code
|
||||
|
||||
def get(self):
|
||||
return self.lang_code
|
||||
if self.language_name:
|
||||
return self.language_name
|
||||
else:
|
||||
return self.lang_code
|
||||
|
||||
def __repr__(self):
|
||||
return u"<Languages('{0}')>".format(self.lang_code)
|
||||
|
@ -27,6 +27,7 @@ import json
|
||||
from shutil import copyfile
|
||||
from uuid import uuid4
|
||||
|
||||
from babel import Locale as LC
|
||||
from flask import Blueprint, request, flash, redirect, url_for, abort, Markup, Response
|
||||
from flask_babel import gettext as _
|
||||
from flask_login import current_user, login_required
|
||||
@ -892,7 +893,7 @@ def convert_bookformat(book_id):
|
||||
@login_required_if_no_ano
|
||||
def edit_list_book(param):
|
||||
vals = request.form.to_dict()
|
||||
#calibre_db.update_title_sort(config)
|
||||
# calibre_db.update_title_sort(config)
|
||||
#calibre_db.session.connection().connection.connection.create_function('uuid4', 0, lambda: str(uuid4()))
|
||||
book = calibre_db.get_book(vals['pk'])
|
||||
if param =='series_index':
|
||||
@ -902,16 +903,17 @@ def edit_list_book(param):
|
||||
elif param =='series':
|
||||
edit_book_series(vals['value'], book)
|
||||
elif param =='publishers':
|
||||
edit_book_publisher(vals['value'], book)
|
||||
# ToDo: edit books
|
||||
vals['publisher'] = vals['value']
|
||||
edit_book_publisher(vals, book)
|
||||
elif param =='languages':
|
||||
edit_book_languages(vals['value'], book)
|
||||
elif param =='title':
|
||||
edit_book_languages(vals['value'], book)
|
||||
elif param =='sort':
|
||||
edit_book_languages(vals['value'], book)
|
||||
elif param =='author_sort':
|
||||
edit_book_languages(vals['value'], book)
|
||||
book.author_sort = vals['value']
|
||||
elif param =='title':
|
||||
book.title = vals['value']
|
||||
elif param =='sort':
|
||||
book.sort = vals['value']
|
||||
# ToDo: edit books
|
||||
elif param =='authors':
|
||||
edit_book_languages(vals['value'], book)
|
||||
|
||||
@ -919,7 +921,18 @@ def edit_list_book(param):
|
||||
calibre_db.session.commit()
|
||||
return ""
|
||||
|
||||
@editbook.route("/ajax/sort_value")
|
||||
@login_required
|
||||
def get_sorted_entry():
|
||||
pass
|
||||
|
||||
@editbook.route("/ajax/deletebooks")
|
||||
@login_required_if_no_ano
|
||||
@login_required
|
||||
def delete_list_book():
|
||||
pass
|
||||
|
||||
@editbook.route("/ajax/mergebooks", methods=['POST'])
|
||||
@login_required
|
||||
def merge_list_book():
|
||||
vals = request.get_json()
|
||||
return ""
|
||||
|
@ -51,9 +51,9 @@ body h2 {
|
||||
color:#444;
|
||||
}
|
||||
|
||||
a, .danger, .editable-empty, .editable-empty:hover { color: #45b29d; }
|
||||
a, .danger,.book-remove, .editable-empty, .editable-empty:hover { color: #45b29d; }
|
||||
|
||||
.danger:hover { color: #23527c; }
|
||||
.book-remove:hover { color: #23527c; }
|
||||
|
||||
.btn-default a { color: #444; }
|
||||
|
||||
|
@ -15,15 +15,149 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* exported TableActions, RestrictionActions, EbookActions*/
|
||||
/* exported TableActions, RestrictionActions, EbookActions, responseHandler */
|
||||
|
||||
var selections = [];
|
||||
|
||||
$(function() {
|
||||
|
||||
$("#books-table").bootstrapTable({
|
||||
formatNoMatches: function () {
|
||||
return "";
|
||||
$("#books-table").on("check.bs.table check-all.bs.table uncheck.bs.table uncheck-all.bs.table",
|
||||
function (e, rowsAfter, rowsBefore) {
|
||||
var rows = rowsAfter;
|
||||
|
||||
if (e.type === "uncheck-all") {
|
||||
rows = rowsBefore;
|
||||
}
|
||||
|
||||
var ids = $.map(!$.isArray(rows) ? [rows] : rows, function (row) {
|
||||
return row.id;
|
||||
});
|
||||
|
||||
var func = $.inArray(e.type, ["check", "check-all"]) > -1 ? "union" : "difference";
|
||||
selections = window._[func](selections, ids);
|
||||
if (selections.length >= 2) {
|
||||
$("#merge_books").removeClass("disabled");
|
||||
$("#merge_books").attr("aria-disabled", false);
|
||||
} else {
|
||||
$("#merge_books").addClass("disabled");
|
||||
$("#merge_books").attr("aria-disabled", true);
|
||||
}
|
||||
});
|
||||
|
||||
$("#merge_books").click(function() {
|
||||
$.ajax({
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../../ajax/mergebooks",
|
||||
data: JSON.stringify({"Merge_books":selections}),
|
||||
success: function success() {
|
||||
// ToDo:
|
||||
}
|
||||
});
|
||||
});
|
||||
/*$("#books-table").bootstrapTable({
|
||||
});
|
||||
test = $("#books-table").bootstrapTable('getOptions');
|
||||
var column = test.columns[0]
|
||||
column.forEach(function(item){
|
||||
if ('editableValidate' in item) {
|
||||
item.editable = {
|
||||
mode: 'inline',
|
||||
validate: function (value) { if($.trim(value) == '') return 'This field is required'; },
|
||||
}
|
||||
}
|
||||
});
|
||||
$("#books-table").bootstrapTable('refreshOptions', {columns: [column]});*/
|
||||
|
||||
var column = [];
|
||||
$('#table1 > thead > tr > th').each(function(){
|
||||
if ($(this).attr('data-edit')) {
|
||||
if ($(this).attr('data-edit-validate')) {
|
||||
column.push({
|
||||
editable: {
|
||||
mode: 'inline',
|
||||
emptytext: "<span class='glyphicon glyphicon-plus'></span>",
|
||||
validate: function (value) { if($.trim(value) == '') return 'This field is required'; },
|
||||
}
|
||||
});
|
||||
} else {
|
||||
column.push({
|
||||
editable: {
|
||||
mode: 'inline',
|
||||
emptytext: "<span class='glyphicon glyphicon-plus'></span>",
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
column.push({});
|
||||
}
|
||||
});
|
||||
$("#table1").bootstrapTable({
|
||||
sidePagination: "server",
|
||||
pagination: true,
|
||||
paginationDetailHAlign: " hidden",
|
||||
paginationHAlign: "left",
|
||||
/*url: window.location.pathname + "/../../ajax/listbooks",*/
|
||||
idField: "id",
|
||||
search: true,
|
||||
showColumns: true,
|
||||
searchAlign: "left",
|
||||
showSearchButton : false,
|
||||
searchOnEnterKey: true,
|
||||
checkboxHeader: false,
|
||||
maintainMetaData: true,
|
||||
responseHandler: responseHandler,
|
||||
columns: column,
|
||||
/*editable-mode="inline"
|
||||
editable-emptytext="<span class='glyphicon glyphicon-plus'></span>">*/
|
||||
/*columns: [
|
||||
{},
|
||||
{}, {
|
||||
editable: {
|
||||
mode: 'inline',
|
||||
emptytext: "<span class='glyphicon glyphicon-plus'></span>",
|
||||
validate: function (value) { if($.trim(value) == '') return 'This field is required'; },
|
||||
},
|
||||
}, {
|
||||
editable: {
|
||||
mode: 'inline',
|
||||
validate: function (value) { if($.trim(value) == '') return 'This field is required'; },
|
||||
},
|
||||
}, {
|
||||
editable: {
|
||||
mode: 'inline',
|
||||
validate: function (value) { if($.trim(value) == '') return 'This field is required'; },
|
||||
}
|
||||
}, {
|
||||
editable: {
|
||||
mode: 'inline',
|
||||
emptytext: "<span class='glyphicon glyphicon-plus'></span>",
|
||||
validate: function (value) { if($.trim(value) == '') return 'This field is required'; },
|
||||
},
|
||||
}, {
|
||||
editable: {
|
||||
mode: 'inline',
|
||||
emptytext: "<span class='glyphicon glyphicon-plus'></span>",
|
||||
validate: function (value) { if($.trim(value) == '') return 'This field is required'; },
|
||||
},
|
||||
}, {
|
||||
editable: {
|
||||
mode: 'inline',
|
||||
emptytext: "<span class='glyphicon glyphicon-plus'></span>",
|
||||
validate: function (value) { if($.trim(value) == '') return 'This field is required'; },
|
||||
},
|
||||
}],*/
|
||||
formatNoMatches: function () {
|
||||
return "";
|
||||
},
|
||||
});
|
||||
|
||||
/*var $table = $('#books-table');
|
||||
$('#books-table').bootstrapTable('getOptions')*/
|
||||
/*$('#books-table').bootstrapTable('editable')*/
|
||||
/*{ field: 'aimValue', title: 'Aim<br>Value', class: 'danger',editable: { mode: 'inline', validate: function (v) { return validateData(this, v); }, }, },*/
|
||||
|
||||
|
||||
$("#domain_allow_submit").click(function(event) {
|
||||
event.preventDefault();
|
||||
@ -105,7 +239,7 @@ $(function() {
|
||||
var deleteId = $(this).data("deleteid");
|
||||
$.ajax({
|
||||
method:"get",
|
||||
url: window.location.pathname + "/../../delete"/+deleteId,
|
||||
url: window.location.pathname + "/../../delete/" + deleteId,
|
||||
});
|
||||
});
|
||||
|
||||
@ -238,6 +372,7 @@ function TableActions (value, row) {
|
||||
].join("");
|
||||
}
|
||||
|
||||
|
||||
/* Function for deleting domain restrictions */
|
||||
function RestrictionActions (value, row) {
|
||||
return [
|
||||
@ -250,8 +385,22 @@ function RestrictionActions (value, row) {
|
||||
/* Function for deleting books */
|
||||
function EbookActions (value, row) {
|
||||
return [
|
||||
"<div class=\"danger remove\" data-toggle=\"modal\" data-target=\"#deleteModal\" data-delete-id=\"" + row.id + "\" title=\"Remove\">",
|
||||
"<div class=\"book-remove\" data-toggle=\"modal\" data-target=\"#deleteModal\" data-delete-id=\"" + row.id + "\" title=\"Remove\">",
|
||||
"<i class=\"glyphicon glyphicon-trash\"></i>",
|
||||
"</div>"
|
||||
].join("");
|
||||
}
|
||||
|
||||
/* Function for keeping checked rows */
|
||||
function responseHandler(res) {
|
||||
$.each(res.rows, function (i, row) {
|
||||
row.state = $.inArray(row.id, selections) !== -1;
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
function validato(value) {
|
||||
if($.trim(value) == '') return 'This field is required';
|
||||
}
|
||||
|
||||
/*function validateVal(value) { if($.trim(value) == '') return 'This field is required'; }*/
|
||||
|
@ -1,6 +1,14 @@
|
||||
{% extends "layout.html" %}
|
||||
{% macro text_table_row(parameter, edit_text, show_text) -%}
|
||||
<th data-field="{{ parameter }}" id="{{ parameter }}" data-sortable="true" {% if g.user.role_edit() %}data-editable-type="text" data-editable-url="{{ url_for('editbook.edit_list_book', param=parameter)}}" data-editable="true" data-editable-title="{{ edit_text}}"{% endif %}>{{ show_text }}</th>
|
||||
{% macro text_table_row(parameter, edit_text, show_text, validate) -%}
|
||||
<th data-field="{{ parameter }}" id="{{ parameter }}" data-sortable="true"
|
||||
{% if g.user.role_edit() %}
|
||||
data-editable-type="text"
|
||||
data-editable-url="{{ url_for('editbook.edit_list_book', param=parameter)}}"
|
||||
data-editable-title="{{ edit_text}}"
|
||||
data-edit="true"
|
||||
{% if validate %}data-edit-validate="true" {% endif %}
|
||||
{% endif %}
|
||||
>{{ show_text }}</th>
|
||||
{%- endmacro %}
|
||||
|
||||
{% block header %}
|
||||
@ -9,13 +17,14 @@
|
||||
{% endblock %}
|
||||
{% block body %}
|
||||
<h2 class="{{page}}">{{_(title)}}</h2>
|
||||
<table class="table table-no-bordered table-striped"
|
||||
<!--table id="table1"></table-->
|
||||
<!--a href="{{url_for('editbook.merge_list_book')}}" class="btn btn-default disabled" id="merge_book" role="button" aria-disabled="true">{{_('Merge selected books')}}
|
||||
data-side-pagination="server"
|
||||
data-pagination="true"
|
||||
data-pagination-detail-h-align=" hidden"
|
||||
data-pagination-h-align="left"
|
||||
id="books-table"
|
||||
data-url="{{url_for('web.list_books')}}"
|
||||
|
||||
data-id-field="id"
|
||||
data-editable-mode="inline"
|
||||
data-show-columns="true"
|
||||
@ -26,24 +35,27 @@
|
||||
data-checkbox-header="false"
|
||||
data-maintain-meta-data="true"
|
||||
data-response-handler="responseHandler"
|
||||
data-editable-emptytext="<span class='glyphicon glyphicon-plus'></span>">
|
||||
|
||||
data-editable-emptytext="<span class='glyphicon glyphicon-plus'></span>"
|
||||
</a-->
|
||||
<div class="btn btn-default disabled" id="merge_books" aria-disabled="true">{{_('Merge selected books')}}</div>
|
||||
<table id="table1" class="table table-no-bordered table-striped"
|
||||
data-url="{{url_for('web.list_books')}}">
|
||||
<thead>
|
||||
<tr>
|
||||
{% if g.user.role_edit() %}
|
||||
<th data-field="state" data-checkbox="true" data-sortable="true"></th>
|
||||
{% endif %}
|
||||
<th data-field="id" id="id" data-visible="false" data-switchable="false"></th>
|
||||
{{ text_table_row('title', _('Enter Title'),_('Title')) }}
|
||||
{{ text_table_row('sort', _('Enter Titlesort'),_('Sort')) }}
|
||||
{{ text_table_row('author_sort', _('Enter Authorsort'),_('Authors Sort')) }}
|
||||
{{ text_table_row('authors', _('Enter Authors'),_('Authors')) }}
|
||||
{{ text_table_row('tags', _('Enter Tags'),_('Tags')) }}
|
||||
{{ text_table_row('series', _('Enter Series'),_('Series')) }}
|
||||
{{ text_table_row('title', _('Enter Title'),_('Title'), true) }}
|
||||
{{ text_table_row('sort', _('Enter Titlesort'),_('Sort'), false) }}
|
||||
{{ text_table_row('author_sort', _('Enter Authorsort'),_('Authors Sort'), false) }}
|
||||
{{ text_table_row('authors', _('Enter Authors'),_('Authors'), false) }}
|
||||
{{ text_table_row('tags', _('Enter Tags'),_('Tags'), false) }}
|
||||
{{ text_table_row('series', _('Enter Series'),_('Series'), false) }}
|
||||
<th data-field="series_index" id="series_index" data-sortable="true" {% if g.user.role_edit() %} data-editable-type="number" data-editable-placeholder="1" data-editable-step="0.01" data-editable-min="0" data-editable-url="{{ url_for('editbook.edit_list_book', param='series_index')}}" data-editable="true" data-editable-title="{{_('Enter title')}}"{% endif %}>{{_('Series Index')}}</th>
|
||||
{{ text_table_row('languages', _('Enter Languages'),_('Languages')) }}
|
||||
<th data-field="pubdate" id="pubdate" data-sortable="true">Publishing Date</th>
|
||||
{{ text_table_row('publishers', _('Enter Publishers'),_('Publishers')) }}
|
||||
{{ text_table_row('languages', _('Enter Languages'),_('Languages'), false) }}
|
||||
<th data-field="pubdate" data-type="date" data-viewformat="dd.mm.yyyy" id="pubdate" data-sortable="true">Publishing Date</th>
|
||||
{{ text_table_row('publishers', _('Enter Publishers'),_('Publishers'), false) }}
|
||||
{% if g.user.role_edit() %}
|
||||
<th data-align="right" data-formatter="EbookActions" data-switchable="false"></th>
|
||||
{% endif %}
|
||||
@ -60,32 +72,5 @@
|
||||
<script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-editable.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/table.js') }}"></script>
|
||||
<script>
|
||||
var $table = $('#books-table')
|
||||
var selections = []
|
||||
|
||||
function responseHandler(res) {
|
||||
$.each(res.rows, function (i, row) {
|
||||
row.state = $.inArray(row.id, selections) !== -1
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
$(function() {
|
||||
$table.on('check.bs.table check-all.bs.table uncheck.bs.table uncheck-all.bs.table',
|
||||
function (e, rowsAfter, rowsBefore) {
|
||||
var rows = rowsAfter
|
||||
|
||||
if (e.type === 'uncheck-all') {
|
||||
rows = rowsBefore
|
||||
}
|
||||
|
||||
var ids = $.map(!$.isArray(rows) ? [rows] : rows, function (row) {
|
||||
return row.id
|
||||
})
|
||||
|
||||
var func = $.inArray(e.type, ['check', 'check-all']) > -1 ? 'union' : 'difference'
|
||||
selections = window._[func](selections, ids)
|
||||
})
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
10
cps/web.py
10
cps/web.py
@ -30,8 +30,8 @@ import traceback
|
||||
import binascii
|
||||
import re
|
||||
|
||||
from babel import Locale as LC
|
||||
from babel.dates import format_date
|
||||
from babel import Locale as LC
|
||||
from babel.core import UnknownLocaleError
|
||||
from flask import Blueprint
|
||||
from flask import render_template, request, redirect, send_from_directory, make_response, g, flash, abort, url_for
|
||||
@ -849,6 +849,14 @@ def list_books():
|
||||
else:
|
||||
entries, __, __ = calibre_db.fill_indexpage((int(off) / (int(limit)) + 1), limit, db.Books, True, order)
|
||||
filtered_count = total_count
|
||||
for entry in entries:
|
||||
for index in range(0, len(entry.languages)):
|
||||
try:
|
||||
entry.languages[index].language_name = LC.parse(entry.languages[index].lang_code)\
|
||||
.get_language_name(get_locale())
|
||||
except UnknownLocaleError:
|
||||
entry.languages[index].language_name = _(
|
||||
isoLanguages.get(part3=entry.languages[index].lang_code).name)
|
||||
table_entries = {'totalNotFiltered': total_count, 'total': filtered_count, "rows": entries}
|
||||
js_list = json.dumps(table_entries, cls=db.AlchemyEncoder)
|
||||
#js_list = json.dumps(entries, cls=db.AlchemyEncoder)
|
||||
|
Loading…
Reference in New Issue
Block a user