Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
D
douban-api-proxy
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
captainwong
douban-api-proxy
Commits
665210e5
Commit
665210e5
authored
Apr 03, 2021
by
Ozzie Isaacs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixes for book edit with title sort and author sort
parent
91b9370a
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
88 additions
and
68 deletions
+88
-68
editbooks.py
cps/editbooks.py
+62
-50
helper.py
cps/helper.py
+1
-0
isoLanguages.py
cps/isoLanguages.py
+1
-1
table.js
cps/static/js/table.js
+19
-10
book_table.html
cps/templates/book_table.html
+3
-5
user_table.html
cps/templates/user_table.html
+1
-1
messages.po
cps/translations/de/LC_MESSAGES/messages.po
+1
-1
No files found.
cps/editbooks.py
View file @
665210e5
...
...
@@ -27,6 +27,8 @@ import json
from
shutil
import
copyfile
from
uuid
import
uuid4
from
babel
import
Locale
as
LC
from
babel.core
import
UnknownLocaleError
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
...
...
@@ -447,7 +449,7 @@ def edit_book_comments(comments, book):
return
modif_date
def
edit_book_languages
(
languages
,
book
,
upload
=
False
):
def
edit_book_languages
(
languages
,
book
,
upload
=
False
,
invalid
=
None
):
input_languages
=
languages
.
split
(
','
)
unknown_languages
=
[]
if
not
upload
:
...
...
@@ -456,7 +458,10 @@ def edit_book_languages(languages, book, upload=False):
input_l
=
isoLanguages
.
get_valid_language_codes
(
get_locale
(),
input_languages
,
unknown_languages
)
for
l
in
unknown_languages
:
log
.
error
(
'
%
s is not a valid language'
,
l
)
flash
(
_
(
u"
%(langname)
s is not a valid language"
,
langname
=
l
),
category
=
"warning"
)
if
isinstance
(
invalid
,
list
):
invalid
.
append
(
l
)
else
:
flash
(
_
(
u"
%(langname)
s is not a valid language"
,
langname
=
l
),
category
=
"warning"
)
# ToDo: Not working correct
if
upload
and
len
(
input_l
)
==
1
:
# If the language of the file is excluded from the users view, it's not imported, to allow the user to view
...
...
@@ -645,18 +650,21 @@ def upload_cover(request, book):
return
False
return
None
def
handle_title_on_edit
(
book
,
to_save
):
def
handle_title_on_edit
(
book
,
book_title
):
# handle book title
if
book
.
title
!=
to_save
[
"book_title"
]
.
rstrip
()
.
strip
():
if
to_save
[
"book_title"
]
==
''
:
to_save
[
"book_title"
]
=
_
(
u'Unknown'
)
book
.
title
=
to_save
[
"book_title"
]
.
rstrip
()
.
strip
()
book_title
=
book_title
.
rstrip
()
.
strip
()
if
book
.
title
!=
book_title
:
if
book_title
==
''
:
book_title
=
_
(
u'Unknown'
)
book
.
title
=
book_title
return
True
return
False
def
handle_author_on_edit
(
book
,
to_save
):
def
handle_author_on_edit
(
book
,
author_name
,
update_stored
=
True
):
# handle author(s)
input_authors
=
to_save
[
"author_name"
]
.
split
(
'&'
)
input_authors
=
author_name
.
split
(
'&'
)
input_authors
=
list
(
map
(
lambda
it
:
it
.
strip
()
.
replace
(
','
,
'|'
),
input_authors
))
# Remove duplicates in authors list
input_authors
=
helper
.
uniq
(
input_authors
)
...
...
@@ -666,7 +674,7 @@ def handle_author_on_edit(book, to_save):
change
=
modify_database_object
(
input_authors
,
book
.
authors
,
db
.
Authors
,
calibre_db
.
session
,
'author'
)
# Search for each author if author is in database, if not, author
name and sorted author
name is generated new
# Search for each author if author is in database, if not, author
name and sorted author
name is generated new
# everything then is assembled for sorted author field in database
sort_authors_list
=
list
()
for
inp
in
input_authors
:
...
...
@@ -677,7 +685,7 @@ def handle_author_on_edit(book, to_save):
stored_author
=
stored_author
.
sort
sort_authors_list
.
append
(
helper
.
get_sorted_author
(
stored_author
))
sort_authors
=
' & '
.
join
(
sort_authors_list
)
if
book
.
author_sort
!=
sort_authors
:
if
book
.
author_sort
!=
sort_authors
and
update_stored
:
book
.
author_sort
=
sort_authors
change
=
True
return
input_authors
,
change
...
...
@@ -718,14 +726,9 @@ def edit_book(book_id):
edited_books_id
=
None
# handle book title
if
book
.
title
!=
to_save
[
"book_title"
]
.
rstrip
()
.
strip
():
if
to_save
[
"book_title"
]
==
''
:
to_save
[
"book_title"
]
=
_
(
u'Unknown'
)
book
.
title
=
to_save
[
"book_title"
]
.
rstrip
()
.
strip
()
edited_books_id
=
book
.
id
modif_date
=
True
modif_date
|=
handle_title_on_edit
(
book
,
to_save
[
"book_title"
])
input_authors
,
change
=
handle_author_on_edit
(
book
,
to_save
)
input_authors
,
change
=
handle_author_on_edit
(
book
,
to_save
[
"author_name"
]
)
if
change
:
edited_books_id
=
book
.
id
modif_date
=
True
...
...
@@ -1039,6 +1042,7 @@ def convert_bookformat(book_id):
flash
(
_
(
u"There was an error converting this book:
%(res)
s"
,
res
=
rtn
),
category
=
"error"
)
return
redirect
(
url_for
(
'editbook.edit_book'
,
book_id
=
book_id
))
@
editbook
.
route
(
"/ajax/editbooks/<param>"
,
methods
=
[
'POST'
])
@
login_required_if_no_ano
@
edit_required
...
...
@@ -1048,71 +1052,79 @@ def edit_list_book(param):
ret
=
""
if
param
==
'series_index'
:
edit_book_series_index
(
vals
[
'value'
],
book
)
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
book
.
series_index
}),
mimetype
=
'application/json'
)
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
book
.
series_index
}),
mimetype
=
'application/json'
)
elif
param
==
'tags'
:
edit_book_tags
(
vals
[
'value'
],
book
)
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
', '
.
join
([
tag
.
name
for
tag
in
book
.
tags
])}),
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
', '
.
join
([
tag
.
name
for
tag
in
book
.
tags
])}),
mimetype
=
'application/json'
)
elif
param
==
'series'
:
edit_book_series
(
vals
[
'value'
],
book
)
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
', '
.
join
([
serie
.
name
for
serie
in
book
.
series
])}),
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
', '
.
join
([
serie
.
name
for
serie
in
book
.
series
])}),
mimetype
=
'application/json'
)
elif
param
==
'publishers'
:
vals
[
'publisher'
]
=
vals
[
'value'
]
edit_book_publisher
(
vals
,
book
)
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
book
.
publishers
}),
edit_book_publisher
(
vals
[
'value'
],
book
)
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
', '
.
join
([
publisher
.
name
for
publisher
in
book
.
publishers
])
}),
mimetype
=
'application/json'
)
elif
param
==
'languages'
:
edit_book_languages
(
vals
[
'value'
],
book
)
# ToDo: Not working
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
', '
.
join
([
lang
.
name
for
lang
in
book
.
languages
])}),
mimetype
=
'application/json'
)
invalid
=
list
()
edit_book_languages
(
vals
[
'value'
],
book
,
invalid
=
invalid
)
if
invalid
:
ret
=
Response
(
json
.
dumps
({
'success'
:
False
,
'msg'
:
'Invalid languages in request: {}'
.
format
(
','
.
join
(
invalid
))}),
mimetype
=
'application/json'
)
else
:
lang_names
=
list
()
for
lang
in
book
.
languages
:
try
:
lang_names
.
append
(
LC
.
parse
(
lang
.
lang_code
)
.
get_language_name
(
get_locale
()))
except
UnknownLocaleError
:
lang_names
.
append
(
_
(
isoLanguages
.
get
(
part3
=
lang
.
lang_code
)
.
name
))
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
', '
.
join
(
lang_names
)}),
mimetype
=
'application/json'
)
elif
param
==
'author_sort'
:
book
.
author_sort
=
vals
[
'value'
]
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
book
.
author_sort
}),
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
book
.
author_sort
}),
mimetype
=
'application/json'
)
elif
param
==
'title'
:
book
.
title
=
vals
[
'value'
]
elif
param
==
'title'
:
sort
=
book
.
sort
handle_title_on_edit
(
book
,
vals
.
get
(
'value'
,
""
))
helper
.
update_dir_stucture
(
book
.
id
,
config
.
config_calibre_dir
)
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
book
.
title
}),
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
book
.
title
}),
mimetype
=
'application/json'
)
elif
param
==
'sort'
:
book
.
sort
=
vals
[
'value'
]
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
book
.
sort
}),
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
book
.
sort
}),
mimetype
=
'application/json'
)
# ToDo: edit books
elif
param
==
'authors'
:
input_authors
=
vals
[
'value'
]
.
split
(
'&'
)
input_authors
=
list
(
map
(
lambda
it
:
it
.
strip
()
.
replace
(
','
,
'|'
),
input_authors
))
modify_database_object
(
input_authors
,
book
.
authors
,
db
.
Authors
,
calibre_db
.
session
,
'author'
)
sort_authors_list
=
list
()
for
inp
in
input_authors
:
stored_author
=
calibre_db
.
session
.
query
(
db
.
Authors
)
.
filter
(
db
.
Authors
.
name
==
inp
)
.
first
()
if
not
stored_author
:
stored_author
=
helper
.
get_sorted_author
(
inp
)
else
:
stored_author
=
stored_author
.
sort
sort_authors_list
.
append
(
helper
.
get_sorted_author
(
stored_author
))
sort_authors
=
' & '
.
join
(
sort_authors_list
)
if
book
.
author_sort
!=
sort_authors
:
book
.
author_sort
=
sort_authors
input_authors
,
__
=
handle_author_on_edit
(
book
,
vals
[
'value'
],
vals
.
get
(
'checkA'
,
None
)
==
"true"
)
helper
.
update_dir_stucture
(
book
.
id
,
config
.
config_calibre_dir
,
input_authors
[
0
])
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
', '
.
join
([
author
.
name
for
author
in
book
.
authors
])}),
ret
=
Response
(
json
.
dumps
({
'success'
:
True
,
'newValue'
:
' & '
.
join
([
author
.
replace
(
'|'
,
','
)
for
author
in
input_authors
])}),
mimetype
=
'application/json'
)
book
.
last_modified
=
datetime
.
utcnow
()
calibre_db
.
session
.
commit
()
# revert change for sort if automatic fields link is deactivated
if
param
==
'title'
and
vals
.
get
(
'checkT'
)
==
"false"
:
book
.
sort
=
sort
calibre_db
.
session
.
commit
()
return
ret
@
editbook
.
route
(
"/ajax/sort_value/<field>/<int:bookid>"
)
@
login_required
def
get_sorted_entry
(
field
,
bookid
):
if
field
==
'title'
or
field
==
'authors'
:
if
field
in
[
'title'
,
'authors'
,
'sort'
,
'author_sort'
]
:
book
=
calibre_db
.
get_filtered_book
(
bookid
)
if
book
:
if
field
==
'title'
:
return
json
.
dumps
({
'sort'
:
book
.
sort
})
elif
field
==
'authors'
:
return
json
.
dumps
({
'author_sort'
:
book
.
author_sort
})
if
field
==
'sort'
:
return
json
.
dumps
({
'sort'
:
book
.
title
})
if
field
==
'author_sort'
:
return
json
.
dumps
({
'author_sort'
:
book
.
author
})
return
""
...
...
cps/helper.py
View file @
665210e5
...
...
@@ -498,6 +498,7 @@ def generate_random_password():
def
uniq
(
inpt
):
output
=
[]
inpt
=
[
" "
.
join
(
inp
.
split
())
for
inp
in
inpt
]
for
x
in
inpt
:
if
x
not
in
output
:
output
.
append
(
x
)
...
...
cps/isoLanguages.py
View file @
665210e5
...
...
@@ -63,7 +63,7 @@ def get_language_codes(locale, language_names, remainder=None):
if
v
in
language_names
:
lang
.
append
(
k
)
language_names
.
remove
(
v
)
if
remainder
is
not
None
:
if
remainder
is
not
None
and
language_names
:
remainder
.
extend
(
language_names
)
return
lang
...
...
cps/static/js/table.js
View file @
665210e5
...
...
@@ -95,17 +95,22 @@ $(function() {
mode
:
"inline"
,
emptytext
:
"<span class='glyphicon glyphicon-plus'></span>"
,
success
:
function
(
response
,
__
)
{
if
(
!
response
.
success
)
return
response
.
msg
;
if
(
!
response
.
success
)
return
response
.
msg
;
return
{
newValue
:
response
.
newValue
};
},
params
:
function
(
params
)
{
params
.
checkA
=
$
(
'#autoupdate_authorsort'
).
prop
(
'checked'
);
params
.
checkT
=
$
(
'#autoupdate_titlesort'
).
prop
(
'checked'
);
return
params
}
}
};
}
var
validateText
=
$
(
this
).
attr
(
"data-edit-validate"
);
if
(
validateText
)
{
element
.
editable
.
validate
=
function
(
value
)
{
if
(
$
.
trim
(
value
)
===
""
)
return
validateText
;
}
;
var
validateText
=
$
(
this
).
attr
(
"data-edit-validate"
);
if
(
validateText
)
{
element
.
editable
.
validate
=
function
(
value
)
{
if
(
$
.
trim
(
value
)
===
""
)
return
validateText
;
}
;
}
}
column
.
push
(
element
);
});
...
...
@@ -132,7 +137,8 @@ $(function() {
},
// eslint-disable-next-line no-unused-vars
onEditableSave
:
function
(
field
,
row
,
oldvalue
,
$el
)
{
if
(
field
===
"title"
||
field
===
"authors"
)
{
if
(
$
.
inArray
(
field
,
[
"title"
,
"sort"
])
!==
-
1
&&
$
(
'#autoupdate_titlesort'
).
prop
(
'checked'
)
||
$
.
inArray
(
field
,
[
"authors"
,
"author_sort"
])
!==
-
1
&&
$
(
'#autoupdate_authorsort'
).
prop
(
'checked'
))
{
$
.
ajax
({
method
:
"get"
,
dataType
:
"json"
,
...
...
@@ -561,7 +567,10 @@ function TableActions (value, row) {
].
join
(
""
);
}
function
editEntry
(
param
)
{
console
.
log
(
param
);
}
/* Function for deleting domain restrictions */
function
RestrictionActions
(
value
,
row
)
{
return
[
...
...
@@ -598,7 +607,7 @@ function responseHandler(res) {
}
function
singleUserFormatter
(
value
,
row
)
{
return
'<
button type="button" className="btn btn-default"><a href="/admin/user/'
+
row
.
id
+
'">'
+
this
.
buttontext
+
'</a></button
>'
return
'<
a class="btn btn-default" href="/admin/user/'
+
row
.
id
+
'">'
+
this
.
buttontext
+
'</a
>'
}
function
checkboxFormatter
(
value
,
row
,
index
){
...
...
cps/templates/book_table.html
View file @
665210e5
...
...
@@ -30,8 +30,8 @@
<label
for=
"autoupdate_titlesort"
>
{{_('Update Title Sort automatically')}}
</label>
</div>
<div
class=
"row"
>
<input
type=
"checkbox"
id=
"autoupdate_aut
orsort"
name=
"autoupdate_aut
orsort"
checked
>
<label
for=
"autoupdate_autorsort"
>
{{_('Update Author Sort automatically')}}
</label>
<input
type=
"checkbox"
id=
"autoupdate_aut
horsort"
name=
"autoupdate_auth
orsort"
checked
>
<label
for=
"autoupdate_aut
h
orsort"
>
{{_('Update Author Sort automatically')}}
</label>
</div>
</div>
...
...
@@ -53,7 +53,7 @@
{{ text_table_row('languages', _('Enter Languages'),_('Languages'), false) }}
<!--th data-field="pubdate" data-type="date" data-visible="{{visiblility.get('pubdate')}}" 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()
%}
{% if g.user.role_
delete_books() and g.user.role_edit()
%}
<th
data-align=
"right"
data-formatter=
"EbookActions"
data-switchable=
"false"
>
{{_('Delete')}}
</th>
{% endif %}
</tr>
...
...
@@ -94,6 +94,4 @@
<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/table.js') }}"
></script>
<script>
</script>
{% endblock %}
cps/templates/user_table.html
View file @
665210e5
...
...
@@ -12,7 +12,7 @@
{%
endif
%}
{%
if
validate
%}
data-edit-validate=
"{{ _('This Field is Required') }}"
{%
endif
%}
>
{% if button %}
<
div><div
data-id=
"{{id}}"
data-toggle=
"modal"
data-target=
"#restrictModal"
class=
"btn btn-default button_head disabled"
aria-disabled=
"true"
>
{{edit_text}}
</div></div
><br>
<
!--div><button data-id="{{id}}" data-toggle="modal" data-target="#restrictModal" class="btn btn-default button_head disabled" aria-disabled="true">{{edit_text}}</button></div--
>
<br>
{% endif %}
{{ show_text }}
</th>
...
...
cps/translations/de/LC_MESSAGES/messages.po
View file @
665210e5
...
...
@@ -1693,7 +1693,7 @@ msgstr "Speicherort der Calibre-Datenbank"
#: cps/templates/config_edit.html:29
msgid "To activate serverside filepicker start Calibre-Web with -f option"
msgstr "Calibre-Web mit -f Option starten um die serverseitige Dateiauswahl zu aktivieren"
msgstr "Calibre-Web mit -f Option starten
,
um die serverseitige Dateiauswahl zu aktivieren"
#: cps/templates/config_edit.html:35
msgid "Use Google Drive?"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment