From 57683d1cfbea75bb3f95da3653ca40ea5bea5edb Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Fri, 24 Dec 2021 16:29:55 +0900 Subject: [PATCH 01/20] Add sort option "Name" for title --- src/util/util.cr | 2 ++ src/views/library.html.ecr | 1 + 2 files changed, 3 insertions(+) diff --git a/src/util/util.cr b/src/util/util.cr index 9f5ffee..7278bb2 100644 --- a/src/util/util.cr +++ b/src/util/util.cr @@ -98,6 +98,8 @@ def sort_titles(titles : Array(Title), opt : SortOptions, username : String) (a.load_percentage(username) <=> b.load_percentage(username)).or \ compare_numerically a.title, b.title end + when .title? + ary.sort! { |a, b| compare_numerically a.title, b.title } else unless opt.method.auto? Logger.warn "Unknown sorting method #{opt.not_nil!.method}. Using " \ diff --git a/src/views/library.html.ecr b/src/views/library.html.ecr index 39e9856..a5e8b59 100644 --- a/src/views/library.html.ecr +++ b/src/views/library.html.ecr @@ -10,6 +10,7 @@
<% hash = { "auto" => "Auto", + "title" => "Name", "time_modified" => "Date Modified", "progress" => "Progress" } %> From 3a932d7b0a1e3213cb009c3abfde38bc25593b8a Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Fri, 24 Dec 2021 22:57:11 +0900 Subject: [PATCH 02/20] Add column 'sort_title' to titles, ids table --- migration/sort_title.12.cr | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 migration/sort_title.12.cr diff --git a/migration/sort_title.12.cr b/migration/sort_title.12.cr new file mode 100644 index 0000000..8da828f --- /dev/null +++ b/migration/sort_title.12.cr @@ -0,0 +1,17 @@ +class SortTitle < MG::Base + def up : String + <<-SQL + -- add sort_title column to ids and titles + ALTER TABLE ids ADD COLUMN sort_title TEXT; + ALTER TABLE titles ADD COLUMN sort_title TEXT; + SQL + end + + def down : String + <<-SQL + -- drop sort_title column to ids and titles + ALTER TABLE ids DROP COLUMN sort_title; + ALTER TABLE titles DROP COLUMN sort_title; + SQL + end +end From ab799af866ad6ed80664e6bdabaf64ad41e29b71 Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Fri, 24 Dec 2021 23:48:52 +0900 Subject: [PATCH 03/20] Implement sort_title getter, setter --- src/library/entry.cr | 24 ++++++++++++++++++++++++ src/library/title.cr | 23 +++++++++++++++++++++++ src/storage.cr | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+) diff --git a/src/library/entry.cr b/src/library/entry.cr index 43fbb23..9e676c8 100644 --- a/src/library/entry.cr +++ b/src/library/entry.cr @@ -8,6 +8,9 @@ class Entry size : String, pages : Int32, id : String, encoded_path : String, encoded_title : String, mtime : Time, err_msg : String? + @[YAML::Field(ignore: true)] + @sort_title : String? + def initialize(@zip_path, @book) storage = Storage.default @encoded_path = URI.encode @zip_path @@ -66,6 +69,27 @@ class Entry end end + def sort_title + sort_title_cached = @sort_title + return sort_title_cached if sort_title_cached + sort_title = Storage.default.get_entry_sort_title id + if sort_title + @sort_title = sort_title + return sort_title + end + @sort_title = @title + @title + end + + def sort_title=(sort_title : String | Nil) + Storage.default.set_entry_sort_title id, sort_title + @sort_title = sort_title + end + + def sort_title_db + Storage.default.get_entry_sort_title id + end + def display_name @book.display_name @title end diff --git a/src/library/title.cr b/src/library/title.cr index 4886f3d..d2e34a2 100644 --- a/src/library/title.cr +++ b/src/library/title.cr @@ -10,6 +10,8 @@ class Title entry_cover_url_cache : Hash(String, String)? setter entry_cover_url_cache : Hash(String, String)? + @[YAML::Field(ignore: true)] + @sort_title : String? @[YAML::Field(ignore: true)] @entry_display_name_cache : Hash(String, String)? @[YAML::Field(ignore: true)] @@ -286,6 +288,27 @@ class Title ary.join " and " end + def sort_title + sort_title_cached = @sort_title + return sort_title_cached if sort_title_cached + sort_title = Storage.default.get_title_sort_title id + if sort_title + @sort_title = sort_title + return sort_title + end + @sort_title = @title + @title + end + + def sort_title=(sort_title : String | Nil) + Storage.default.set_title_sort_title id, sort_title + @sort_title = sort_title + end + + def sort_title_db + Storage.default.get_title_sort_title id + end + def tags Storage.default.get_title_tags @id end diff --git a/src/storage.cr b/src/storage.cr index 32f446a..edf71ff 100644 --- a/src/storage.cr +++ b/src/storage.cr @@ -342,6 +342,44 @@ class Storage end end + def get_title_sort_title(title_id : String) + sort_title = nil + MainFiber.run do + get_db do |db| + sort_title = db.query_one? "Select sort_title from titles where id = (?)", title_id, as: String | Nil + end + end + sort_title + end + + def set_title_sort_title(title_id : String, sort_title : String | Nil) + sort_title = nil if sort_title == "" + MainFiber.run do + get_db do |db| + db.exec "update titles set sort_title = (?) where id = (?)", sort_title, title_id + end + end + end + + def get_entry_sort_title(entry_id : String) + sort_title = nil + MainFiber.run do + get_db do |db| + sort_title = db.query_one? "Select sort_title from ids where id = (?)", entry_id, as: String | Nil + end + end + sort_title + end + + def set_entry_sort_title(entry_id : String, sort_title : String | Nil) + sort_title = nil if sort_title == "" + MainFiber.run do + get_db do |db| + db.exec "update ids set sort_title = (?) where id = (?)", sort_title, entry_id + end + end + end + def save_thumbnail(id : String, img : Image) MainFiber.run do get_db do |db| From 546bd0138cbacb31a32a51509efbded46d535aae Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Sat, 25 Dec 2021 16:50:00 +0900 Subject: [PATCH 04/20] Use sort_title instead of title --- src/library/library.cr | 2 +- src/library/title.cr | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/library/library.cr b/src/library/library.cr index 2a5de7d..a2dc28d 100644 --- a/src/library/library.cr +++ b/src/library/library.cr @@ -161,7 +161,7 @@ class Library .select { |path| File.directory? path } .map { |path| Title.new path, "", cache } .select { |title| !(title.entries.empty? && title.titles.empty?) } - .sort! { |a, b| a.title <=> b.title } + .sort! { |a, b| a.sort_title <=> b.sort_title } .each do |title| @title_hash[title.id] = title @title_ids << title.id diff --git a/src/library/title.cr b/src/library/title.cr index d2e34a2..e264ae9 100644 --- a/src/library/title.cr +++ b/src/library/title.cr @@ -68,7 +68,7 @@ class Title end sorter = ChapterSorter.new @entries.map &.title @entries.sort! do |a, b| - sorter.compare a.title, b.title + sorter.compare a.sort_title, b.sort_title end end @@ -182,9 +182,9 @@ class Title end end if is_entries_added || previous_entries_size != @entries.size - sorter = ChapterSorter.new @entries.map &.title + sorter = ChapterSorter.new @entries.map &.sort_title @entries.sort! do |a, b| - sorter.compare a.title, b.title + sorter.compare a.sort_title, b.sort_title end end @@ -495,28 +495,28 @@ class Title case opt.not_nil!.method when .title? - ary = @entries.sort { |a, b| compare_numerically a.title, b.title } + ary = @entries.sort { |a, b| compare_numerically a.sort_title, b.sort_title } when .time_modified? ary = @entries.sort { |a, b| (a.mtime <=> b.mtime).or \ - compare_numerically a.title, b.title } + compare_numerically a.sort_title, b.sort_title } when .time_added? ary = @entries.sort { |a, b| (a.date_added <=> b.date_added).or \ - compare_numerically a.title, b.title } + compare_numerically a.sort_title, b.sort_title } when .progress? percentage_ary = load_percentage_for_all_entries username, opt, true ary = @entries.zip(percentage_ary) .sort { |a_tp, b_tp| (a_tp[1] <=> b_tp[1]).or \ - compare_numerically a_tp[0].title, b_tp[0].title } + compare_numerically a_tp[0].sort_title, b_tp[0].sort_title } .map &.[0] else unless opt.method.auto? Logger.warn "Unknown sorting method #{opt.not_nil!.method}. Using " \ "Auto instead" end - sorter = ChapterSorter.new @entries.map &.title + sorter = ChapterSorter.new @entries.map &.sort_title ary = @entries.sort do |a, b| - sorter.compare(a.title, b.title).or \ - compare_numerically a.title, b.title + sorter.compare(a.sort_title, b.sort_title).or \ + compare_numerically a.sort_title, b.sort_title end end From d4b58e91d10a171744e0ab41a19d12705a2f0a52 Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Sat, 25 Dec 2021 16:45:32 +0900 Subject: [PATCH 05/20] Implement sort title api --- src/routes/api.cr | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/routes/api.cr b/src/routes/api.cr index 1fea598..95d29ee 100644 --- a/src/routes/api.cr +++ b/src/routes/api.cr @@ -371,6 +371,37 @@ struct APIRouter end end + Koa.describe "Sets the sort title of a title or an entry", <<-MD + When `eid` is provided, apply the sort title to the entry. Otherwise, apply the sort title to the title identified by `tid`. + MD + Koa.tags ["admin", "library"] + Koa.path "tid", desc: "Title ID" + Koa.query "eid", desc: "Entry ID", required: false + Koa.query "name", desc: "The new sort title" + Koa.response 200, schema: "result" + put "/api/admin/sort_title/:tid" do |env| + begin + title = (Library.default.get_title env.params.url["tid"]) + .not_nil! + name = env.params.query["name"]? + entry = env.params.query["eid"]? + if entry.nil? + title.sort_title = name + else + eobj = title.get_entry entry + eobj.sort_title = name unless eobj.nil? + end + rescue e + Logger.error e + send_json env, { + "success" => false, + "error" => e.message, + }.to_json + else + send_json env, {"success" => true}.to_json + end + end + ws "/api/admin/mangadex/queue" do |socket, env| interval_raw = env.params.query["interval"]? interval = (interval_raw.to_i? if interval_raw) || 5 From 162318cf4a34e9598f98e666aa2785700d221542 Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Sat, 25 Dec 2021 20:58:09 +0900 Subject: [PATCH 06/20] Add Api call --- public/js/title.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/public/js/title.js b/public/js/title.js index 1aca6d6..32ab7bf 100644 --- a/public/js/title.js +++ b/public/js/title.js @@ -122,6 +122,34 @@ const renameSubmit = (name, eid) => { }); }; +const renameSortNameSubmit = (name, eid) => { + const upload = $('.upload-field'); + const titleId = upload.attr('data-title-id'); + + const params = {}; + if (eid) params.eid = eid; + if (name) params.name = name; + const query = $.param(params); + let url = `${base_url}api/admin/sort_title/${titleId}?${query}`; + + $.ajax({ + type: 'PUT', + url, + contentType: 'application/json', + dataType: 'json' + }) + .done(data => { + if (data.error) { + alert('danger', `Failed to update sort title. Error: ${data.error}`); + return; + } + location.reload(); + }) + .fail((jqXHR, status) => { + alert('danger', `Failed to update sort title. Error: [${jqXHR.status}] ${jqXHR.statusText}`); + }); +}; + const edit = (eid) => { const cover = $('#edit-modal #cover'); let url = cover.attr('data-title-cover'); From 45ffa3d428b6ef9a9571a776a0a37471400a5bb5 Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Sat, 25 Dec 2021 21:02:57 +0900 Subject: [PATCH 07/20] Implement UI to edit sort title --- public/js/title.js | 17 +++++++++++++++++ src/views/components/card.html.ecr | 4 +++- src/views/title.html.ecr | 10 +++++++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/public/js/title.js b/public/js/title.js index 32ab7bf..5a2da33 100644 --- a/public/js/title.js +++ b/public/js/title.js @@ -154,11 +154,15 @@ const edit = (eid) => { const cover = $('#edit-modal #cover'); let url = cover.attr('data-title-cover'); let displayName = $('h2.uk-title > span').text(); + let fileTitle = $('h2.uk-title').attr('data-file-title'); + let sortTitle = $('h2.uk-title').attr('data-sort-title'); if (eid) { const item = $(`#${eid}`); url = item.find('img').attr('data-src'); displayName = item.find('.uk-card-title').attr('data-title'); + fileTitle = item.find('.uk-card-title').attr('data-file-title'); + sortTitle = item.find('.uk-card-title').attr('data-sort-title'); $('#title-progress-control').attr('hidden', ''); } else { $('#title-progress-control').removeAttr('hidden'); @@ -178,6 +182,19 @@ const edit = (eid) => { renameSubmit(displayNameField.val(), eid); }); + const sortTitleField = $('#sort-title-field'); + sortTitleField.attr('value', sortTitle); + sortTitleField.attr('placeholder', fileTitle); + console.log(sortTitle); + sortTitleField.keyup(event => { + if (event.keyCode === 13) { + renameSortNameSubmit(sortTitleField.val(), eid); + } + }); + sortTitleField.siblings('a.uk-form-icon').click(() => { + renameSortNameSubmit(sortTitleField.val(), eid); + }); + setupUpload(eid); UIkit.modal($('#edit-modal')).show(); diff --git a/src/views/components/card.html.ecr b/src/views/components/card.html.ecr index b85d39e..5549499 100644 --- a/src/views/components/card.html.ecr +++ b/src/views/components/card.html.ecr @@ -61,7 +61,9 @@ <% if page == "home" && item.is_a? Entry %> <%= "uk-margin-remove-bottom" %> <% end %> - " data-title="<%= HTML.escape(item.display_name) %>"><%= HTML.escape(item.display_name) %> + " data-title="<%= HTML.escape(item.display_name) %>" + data-file-title="<%= HTML.escape(item.title || "") %>" + data-sort-title="<%= HTML.escape(item.sort_title_db || "") %>"><%= HTML.escape(item.display_name) %> <% if page == "home" && item.is_a? Entry %> <%= HTML.escape(item.book.display_name) %> diff --git a/src/views/title.html.ecr b/src/views/title.html.ecr index 78edf98..99b9380 100644 --- a/src/views/title.html.ecr +++ b/src/views/title.html.ecr @@ -18,7 +18,8 @@
-

<%= title.display_name %> +

"> + <%= title.display_name %>   <% if is_admin %> @@ -89,6 +90,13 @@ +
+ +
+ + +
+
From edfef80e5c11418c8a7310337a365519ade77de4 Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Sat, 25 Dec 2021 22:12:09 +0900 Subject: [PATCH 08/20] Invalidate sort result cache after change sort_title --- src/library/entry.cr | 10 +++++++++- src/library/title.cr | 11 ++++++++++- src/routes/api.cr | 5 +++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/library/entry.cr b/src/library/entry.cr index 9e676c8..0d508f1 100644 --- a/src/library/entry.cr +++ b/src/library/entry.cr @@ -81,9 +81,17 @@ class Entry @title end - def sort_title=(sort_title : String | Nil) + def set_sort_title(sort_title : String | Nil, username : String) Storage.default.set_entry_sort_title id, sort_title @sort_title = sort_title + + [false, true].each do |ascend| + [SortMethod::Auto, SortMethod::Title].each do |sort_method| + sorted_entries_cache_key = SortedEntriesCacheEntry.gen_key @book.id, + username, @book.entries, SortOptions.new(sort_method, ascend) + LRUCache.invalidate sorted_entries_cache_key + end + end end def sort_title_db diff --git a/src/library/title.cr b/src/library/title.cr index e264ae9..1c89731 100644 --- a/src/library/title.cr +++ b/src/library/title.cr @@ -300,9 +300,18 @@ class Title @title end - def sort_title=(sort_title : String | Nil) + def set_sort_title(sort_title : String | Nil, username : String) Storage.default.set_title_sort_title id, sort_title @sort_title = sort_title + + [false, true].each do |ascend| + [SortMethod::Auto, SortMethod::Title].each do |sort_method| + sorted_entries_cache_key = + SortedEntriesCacheEntry.gen_key @id, username, @entries, + SortOptions.new(sort_method, ascend) + LRUCache.invalidate sorted_entries_cache_key + end + end end def sort_title_db diff --git a/src/routes/api.cr b/src/routes/api.cr index 95d29ee..28ec314 100644 --- a/src/routes/api.cr +++ b/src/routes/api.cr @@ -380,16 +380,17 @@ struct APIRouter Koa.query "name", desc: "The new sort title" Koa.response 200, schema: "result" put "/api/admin/sort_title/:tid" do |env| + username = get_username env begin title = (Library.default.get_title env.params.url["tid"]) .not_nil! name = env.params.query["name"]? entry = env.params.query["eid"]? if entry.nil? - title.sort_title = name + title.set_sort_title name, username else eobj = title.get_entry entry - eobj.sort_title = name unless eobj.nil? + eobj.set_sort_title name, username unless eobj.nil? end rescue e Logger.error e From 234b29bbdd38a42cbd462c1c275d1ec3575f1382 Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Sat, 25 Dec 2021 22:40:10 +0900 Subject: [PATCH 09/20] Fix save --- src/library/entry.cr | 6 +++++- src/library/title.cr | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/library/entry.cr b/src/library/entry.cr index 0d508f1..ec11cb1 100644 --- a/src/library/entry.cr +++ b/src/library/entry.cr @@ -83,7 +83,11 @@ class Entry def set_sort_title(sort_title : String | Nil, username : String) Storage.default.set_entry_sort_title id, sort_title - @sort_title = sort_title + if sort_title == "" || sort_title.nil? + @sort_title = nil + else + @sort_title = sort_title + end [false, true].each do |ascend| [SortMethod::Auto, SortMethod::Title].each do |sort_method| diff --git a/src/library/title.cr b/src/library/title.cr index 1c89731..883f36c 100644 --- a/src/library/title.cr +++ b/src/library/title.cr @@ -302,7 +302,11 @@ class Title def set_sort_title(sort_title : String | Nil, username : String) Storage.default.set_title_sort_title id, sort_title - @sort_title = sort_title + if sort_title == "" || sort_title.nil? + @sort_title = nil + else + @sort_title = sort_title + end [false, true].each do |ascend| [SortMethod::Auto, SortMethod::Title].each do |sort_method| From 8fea35fa510cc3210318046d65fc72670e3cc5cd Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Sun, 26 Dec 2021 00:27:00 +0900 Subject: [PATCH 10/20] Use sorted_titles --- src/library/title.cr | 4 ++++ src/routes/main.cr | 6 ++++++ src/views/title.html.ecr | 4 ++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/library/title.cr b/src/library/title.cr index 883f36c..d1520be 100644 --- a/src/library/title.cr +++ b/src/library/title.cr @@ -252,6 +252,10 @@ class Title @title_ids.map { |tid| Library.default.get_title! tid } end + def sorted_titles(username, opt : SortOptions? = nil) + titles + end + # Get all entries, including entries in nested titles def deep_entries return @entries if title_ids.empty? diff --git a/src/routes/main.cr b/src/routes/main.cr index 4aa7da6..87a7c3b 100644 --- a/src/routes/main.cr +++ b/src/routes/main.cr @@ -61,9 +61,15 @@ struct MainRouter sort_opt = SortOptions.from_info_json title.dir, username get_and_save_sort_opt title.dir + sorted_titles = title.sorted_titles username, sort_opt entries = title.sorted_entries username, sort_opt percentage = title.load_percentage_for_all_entries username, sort_opt title_percentage = title.titles.map &.load_percentage username + title_percentage_map = {} of String => Float64 + title_percentage.each_with_index do |percentage, i| + t = title.titles[i] + title_percentage_map[t.id] = percentage + end layout "title" rescue e diff --git a/src/views/title.html.ecr b/src/views/title.html.ecr index 99b9380..6880347 100644 --- a/src/views/title.html.ecr +++ b/src/views/title.html.ecr @@ -60,8 +60,8 @@
- <% title.titles.each_with_index do |item, i| %> - <% progress = title_percentage[i] %> + <% sorted_titles.each do |item| %> + <% progress = title_percentage_map[item.id] %> <%= render_component "card" %> <% end %>
From 1ec8dcbfdab19c8bf88d9781e9e22ca03b0ac242 Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Sun, 26 Dec 2021 01:50:55 +0900 Subject: [PATCH 11/20] Use sort_title, sort_titles in title page --- src/library/title.cr | 7 ++++++- src/util/util.cr | 12 ++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/library/title.cr b/src/library/title.cr index d1520be..9eacf4e 100644 --- a/src/library/title.cr +++ b/src/library/title.cr @@ -253,7 +253,12 @@ class Title end def sorted_titles(username, opt : SortOptions? = nil) - titles + if opt.nil? + opt = SortOptions.from_info_json @dir, username + end + + # Helper function from src/util/util.cr + sort_titles titles, opt.not_nil!, username end # Get all entries, including entries in nested titles diff --git a/src/util/util.cr b/src/util/util.cr index 7278bb2..2814c6c 100644 --- a/src/util/util.cr +++ b/src/util/util.cr @@ -91,21 +91,21 @@ def sort_titles(titles : Array(Title), opt : SortOptions, username : String) case opt.method when .time_modified? - ary.sort! { |a, b| (a.mtime <=> b.mtime).or \ - compare_numerically a.title, b.title } + ary.sort { |a, b| (a.mtime <=> b.mtime).or \ + compare_numerically a.sort_title, b.sort_title } when .progress? - ary.sort! do |a, b| + ary.sort do |a, b| (a.load_percentage(username) <=> b.load_percentage(username)).or \ - compare_numerically a.title, b.title + compare_numerically a.sort_title, b.sort_title end when .title? - ary.sort! { |a, b| compare_numerically a.title, b.title } + ary.sort { |a, b| compare_numerically a.sort_title, b.sort_title } else unless opt.method.auto? Logger.warn "Unknown sorting method #{opt.not_nil!.method}. Using " \ "Auto instead" end - ary.sort! { |a, b| compare_numerically a.title, b.title } + ary.sort { |a, b| compare_numerically a.sort_title, b.sort_title } end ary.reverse! unless opt.not_nil!.ascend From 1cd777d27d08b5bbc8c7d5fa99e46c59e6240bd7 Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Sun, 26 Dec 2021 02:56:57 +0900 Subject: [PATCH 12/20] Cache sorted titles --- src/library/cache.cr | 31 ++++++++++++++++++++++++++++++- src/library/entry.cr | 14 ++------------ src/library/title.cr | 36 ++++++++++++++++++++++-------------- src/util/util.cr | 7 ++++++- 4 files changed, 60 insertions(+), 28 deletions(-) diff --git a/src/library/cache.cr b/src/library/cache.cr index d0d3f01..686ae1f 100644 --- a/src/library/cache.cr +++ b/src/library/cache.cr @@ -1,6 +1,7 @@ require "digest" require "./entry" +require "./title" require "./types" # Base class for an entry in the LRU cache. @@ -81,6 +82,31 @@ class SortedEntriesCacheEntry < CacheEntry(Array(String), Array(Entry)) end end +class SortedTitlesCacheEntry < CacheEntry(Array(String), Array(Title)) + def self.to_save_t(value : Array(Title)) + value.map &.id + end + + def self.to_return_t(value : Array(String)) + value.map { |title_id| Library.default.title_hash[title_id].not_nil! } + end + + def instance_size + instance_sizeof(SortedTitlesCacheEntry) + # sizeof itself + instance_sizeof(String) + @key.bytesize + # allocated memory for @key + @value.size * (instance_sizeof(String) + sizeof(String)) + + @value.sum(&.bytesize) # elements in Array(String) + end + + def self.gen_key(username : String, titles : Array(Title), opt : SortOptions?) + titles_sig = Digest::SHA1.hexdigest (titles.map &.id).to_s + user_context = opt && opt.method == SortMethod::Progress ? username : "" + sig = Digest::SHA1.hexdigest (titles_sig + user_context + + (opt ? opt.to_tuple.to_s : "nil")) + "#{sig}:sorted_titles" + end +end + class String def instance_size instance_sizeof(String) + bytesize @@ -101,14 +127,17 @@ struct Tuple(*T) end end -alias CacheableType = Array(Entry) | String | Tuple(String, Int32) +alias CacheableType = Array(Entry) | Array(Title) | String | Tuple(String, Int32) alias CacheEntryType = SortedEntriesCacheEntry | + SortedTitlesCacheEntry | CacheEntry(String, String) | CacheEntry(Tuple(String, Int32), Tuple(String, Int32)) def generate_cache_entry(key : String, value : CacheableType) if value.is_a? Array(Entry) SortedEntriesCacheEntry.new key, value + elsif value.is_a? Array(Title) + SortedTitlesCacheEntry.new key, value else CacheEntry(typeof(value), typeof(value)).new key, value end diff --git a/src/library/entry.cr b/src/library/entry.cr index ec11cb1..4c9c96f 100644 --- a/src/library/entry.cr +++ b/src/library/entry.cr @@ -89,13 +89,7 @@ class Entry @sort_title = sort_title end - [false, true].each do |ascend| - [SortMethod::Auto, SortMethod::Title].each do |sort_method| - sorted_entries_cache_key = SortedEntriesCacheEntry.gen_key @book.id, - username, @book.entries, SortOptions.new(sort_method, ascend) - LRUCache.invalidate sorted_entries_cache_key - end - end + @book.remove_sorted_caches [SortMethod::Auto, SortMethod::Title], username end def sort_title_db @@ -213,11 +207,7 @@ class Entry @book.parents.each do |parent| LRUCache.invalidate "#{parent.id}:#{username}:progress_sum" end - [false, true].each do |ascend| - sorted_entries_cache_key = SortedEntriesCacheEntry.gen_key @book.id, - username, @book.entries, SortOptions.new(SortMethod::Progress, ascend) - LRUCache.invalidate sorted_entries_cache_key - end + @book.remove_sorted_caches [SortMethod::Progress], username TitleInfo.new @book.dir do |info| if info.progress[username]?.nil? diff --git a/src/library/title.cr b/src/library/title.cr index 9eacf4e..f61f01d 100644 --- a/src/library/title.cr +++ b/src/library/title.cr @@ -317,14 +317,7 @@ class Title @sort_title = sort_title end - [false, true].each do |ascend| - [SortMethod::Auto, SortMethod::Title].each do |sort_method| - sorted_entries_cache_key = - SortedEntriesCacheEntry.gen_key @id, username, @entries, - SortOptions.new(sort_method, ascend) - LRUCache.invalidate sorted_entries_cache_key - end - end + remove_sorted_caches [SortMethod::Auto, SortMethod::Title], username end def sort_title_db @@ -605,17 +598,32 @@ class Title zip + titles.flat_map &.deep_entries_with_date_added end + def remove_sorted_caches(sort_methods : Array(SortMethod), username : String) + [false, true].each do |ascend| + sort_methods.each do |sort_method| + sorted_entries_cache_key = + SortedEntriesCacheEntry.gen_key @id, username, @entries, + SortOptions.new(sort_method, ascend) + LRUCache.invalidate sorted_entries_cache_key + end + end + parents.each do |parent| + [false, true].each do |ascend| + sort_methods.each do |sort_method| + sorted_titles_cache_key = SortedTitlesCacheEntry.gen_key username, + parent.titles, SortOptions.new(sort_method, ascend) + LRUCache.invalidate sorted_titles_cache_key + end + end + end + end + def bulk_progress(action, ids : Array(String), username) LRUCache.invalidate "#{@id}:#{username}:progress_sum" parents.each do |parent| LRUCache.invalidate "#{parent.id}:#{username}:progress_sum" end - [false, true].each do |ascend| - sorted_entries_cache_key = - SortedEntriesCacheEntry.gen_key @id, username, @entries, - SortOptions.new(SortMethod::Progress, ascend) - LRUCache.invalidate sorted_entries_cache_key - end + remove_sorted_caches [SortMethod::Progress], username selected_entries = ids .map { |id| diff --git a/src/util/util.cr b/src/util/util.cr index 2814c6c..74738b7 100644 --- a/src/util/util.cr +++ b/src/util/util.cr @@ -86,7 +86,11 @@ def env_is_true?(key : String) : Bool val.downcase.in? "1", "true" end -def sort_titles(titles : Array(Title), opt : SortOptions, username : String) +def sort_titles(titles : Array(Title), opt : SortOptions, username : String) : Array(Title) + cache_key = SortedTitlesCacheEntry.gen_key username, titles, opt + cached_titles = LRUCache.get cache_key + return cached_titles if cached_titles.is_a? Array(Title) + ary = titles case opt.method @@ -110,6 +114,7 @@ def sort_titles(titles : Array(Title), opt : SortOptions, username : String) ary.reverse! unless opt.not_nil!.ascend + LRUCache.set generate_cache_entry cache_key, ary ary end From bd2ed1b338214911c806be30cf82b28cf8413617 Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Sun, 26 Dec 2021 03:01:51 +0900 Subject: [PATCH 13/20] Implement to restore a display name with an empty input Add a placeholder for the default display name Remove some console.log() callings --- public/js/title.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/public/js/title.js b/public/js/title.js index 5a2da33..d6cde9a 100644 --- a/public/js/title.js +++ b/public/js/title.js @@ -90,8 +90,6 @@ const renameSubmit = (name, eid) => { const upload = $('.upload-field'); const titleId = upload.attr('data-title-id'); - console.log(name); - if (name.length === 0) { alert('danger', 'The display name should not be empty'); return; @@ -172,20 +170,19 @@ const edit = (eid) => { const displayNameField = $('#display-name-field'); displayNameField.attr('value', displayName); - console.log(displayNameField); + displayNameField.attr('placeholder', fileTitle); displayNameField.keyup(event => { if (event.keyCode === 13) { - renameSubmit(displayNameField.val(), eid); + renameSubmit(displayNameField.val() || fileTitle, eid); } }); displayNameField.siblings('a.uk-form-icon').click(() => { - renameSubmit(displayNameField.val(), eid); + renameSubmit(displayNameField.val() || fileTitle, eid); }); const sortTitleField = $('#sort-title-field'); sortTitleField.attr('value', sortTitle); sortTitleField.attr('placeholder', fileTitle); - console.log(sortTitle); sortTitleField.keyup(event => { if (event.keyCode === 13) { renameSortNameSubmit(sortTitleField.val(), eid); @@ -211,7 +208,6 @@ const setupUpload = (eid) => { queryObj['eid'] = eid; const query = $.param(queryObj); const url = `${base_url}api/admin/upload/cover?${query}`; - console.log(url); UIkit.upload('.upload-field', { url: url, name: 'file', From 0f94288bab36d88b905d7c7cd8d402f3e62cf2c4 Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Sun, 26 Dec 2021 03:29:41 +0900 Subject: [PATCH 14/20] Avoid N+1 queries problem --- src/library/entry.cr | 5 +++-- src/library/title.cr | 14 +++++++++++++- src/storage.cr | 16 ++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/library/entry.cr b/src/library/entry.cr index 4c9c96f..067acce 100644 --- a/src/library/entry.cr +++ b/src/library/entry.cr @@ -72,7 +72,7 @@ class Entry def sort_title sort_title_cached = @sort_title return sort_title_cached if sort_title_cached - sort_title = Storage.default.get_entry_sort_title id + sort_title = @book.entry_sort_title_db id if sort_title @sort_title = sort_title return sort_title @@ -89,11 +89,12 @@ class Entry @sort_title = sort_title end + @book.entry_sort_title_cache = nil @book.remove_sorted_caches [SortMethod::Auto, SortMethod::Title], username end def sort_title_db - Storage.default.get_entry_sort_title id + @book.entry_sort_title_db @id end def display_name diff --git a/src/library/title.cr b/src/library/title.cr index f61f01d..8465d56 100644 --- a/src/library/title.cr +++ b/src/library/title.cr @@ -8,11 +8,14 @@ class Title entries : Array(Entry), title : String, id : String, encoded_title : String, mtime : Time, signature : UInt64, entry_cover_url_cache : Hash(String, String)? - setter entry_cover_url_cache : Hash(String, String)? + setter entry_cover_url_cache : Hash(String, String)?, + entry_sort_title_cache : Hash(String, String | Nil)? @[YAML::Field(ignore: true)] @sort_title : String? @[YAML::Field(ignore: true)] + @entry_sort_title_cache : Hash(String, String | Nil)? + @[YAML::Field(ignore: true)] @entry_display_name_cache : Hash(String, String)? @[YAML::Field(ignore: true)] @entry_cover_url_cache : Hash(String, String)? @@ -324,6 +327,15 @@ class Title Storage.default.get_title_sort_title id end + def entry_sort_title_db(entry_id) + unless @entry_sort_title_cache + @entry_sort_title_cache = + Storage.default.get_entries_sort_title @entries.map &.id + end + + @entry_sort_title_cache.not_nil![entry_id]? + end + def tags Storage.default.get_title_tags @id end diff --git a/src/storage.cr b/src/storage.cr index edf71ff..cd3e3c0 100644 --- a/src/storage.cr +++ b/src/storage.cr @@ -371,6 +371,22 @@ class Storage sort_title end + def get_entries_sort_title(ids : Array(String)) + results = Hash(String, String | Nil).new + MainFiber.run do + get_db do |db| + db.query "select id, sort_title from ids where id in (#{ids.join "," { |id| "'#{id}'" }})" do |rs| + rs.each do + id = rs.read String + sort_title = rs.read String | Nil + results[id] = sort_title + end + end + end + end + results + end + def set_entry_sort_title(entry_id : String, sort_title : String | Nil) sort_title = nil if sort_title == "" MainFiber.run do From b711072492bcc527e06d8679150a9c785813caa6 Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Sun, 26 Dec 2021 04:10:03 +0900 Subject: [PATCH 15/20] Fix lint --- src/library/cache.cr | 3 ++- src/library/title.cr | 4 +++- src/routes/main.cr | 4 ++-- src/storage.cr | 17 ++++++++++++----- src/util/util.cr | 2 +- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/library/cache.cr b/src/library/cache.cr index 686ae1f..10e4f60 100644 --- a/src/library/cache.cr +++ b/src/library/cache.cr @@ -127,7 +127,8 @@ struct Tuple(*T) end end -alias CacheableType = Array(Entry) | Array(Title) | String | Tuple(String, Int32) +alias CacheableType = Array(Entry) | Array(Title) | String | + Tuple(String, Int32) alias CacheEntryType = SortedEntriesCacheEntry | SortedTitlesCacheEntry | CacheEntry(String, String) | diff --git a/src/library/title.cr b/src/library/title.cr index 8465d56..d5d8692 100644 --- a/src/library/title.cr +++ b/src/library/title.cr @@ -522,7 +522,9 @@ class Title case opt.not_nil!.method when .title? - ary = @entries.sort { |a, b| compare_numerically a.sort_title, b.sort_title } + ary = @entries.sort do |a, b| + compare_numerically a.sort_title, b.sort_title + end when .time_modified? ary = @entries.sort { |a, b| (a.mtime <=> b.mtime).or \ compare_numerically a.sort_title, b.sort_title } diff --git a/src/routes/main.cr b/src/routes/main.cr index 87a7c3b..ea2f0d8 100644 --- a/src/routes/main.cr +++ b/src/routes/main.cr @@ -66,9 +66,9 @@ struct MainRouter percentage = title.load_percentage_for_all_entries username, sort_opt title_percentage = title.titles.map &.load_percentage username title_percentage_map = {} of String => Float64 - title_percentage.each_with_index do |percentage, i| + title_percentage.each_with_index do |tp, i| t = title.titles[i] - title_percentage_map[t.id] = percentage + title_percentage_map[t.id] = tp end layout "title" diff --git a/src/storage.cr b/src/storage.cr index cd3e3c0..4c8cfe7 100644 --- a/src/storage.cr +++ b/src/storage.cr @@ -346,7 +346,9 @@ class Storage sort_title = nil MainFiber.run do get_db do |db| - sort_title = db.query_one? "Select sort_title from titles where id = (?)", title_id, as: String | Nil + sort_title = + db.query_one? "Select sort_title from titles where id = (?)", + title_id, as: String | Nil end end sort_title @@ -356,7 +358,8 @@ class Storage sort_title = nil if sort_title == "" MainFiber.run do get_db do |db| - db.exec "update titles set sort_title = (?) where id = (?)", sort_title, title_id + db.exec "update titles set sort_title = (?) where id = (?)", + sort_title, title_id end end end @@ -365,7 +368,9 @@ class Storage sort_title = nil MainFiber.run do get_db do |db| - sort_title = db.query_one? "Select sort_title from ids where id = (?)", entry_id, as: String | Nil + sort_title = + db.query_one? "Select sort_title from ids where id = (?)", + entry_id, as: String | Nil end end sort_title @@ -375,7 +380,8 @@ class Storage results = Hash(String, String | Nil).new MainFiber.run do get_db do |db| - db.query "select id, sort_title from ids where id in (#{ids.join "," { |id| "'#{id}'" }})" do |rs| + db.query "select id, sort_title from ids where id in " \ + "(#{ids.join "," { |id| "'#{id}'" }})" do |rs| rs.each do id = rs.read String sort_title = rs.read String | Nil @@ -391,7 +397,8 @@ class Storage sort_title = nil if sort_title == "" MainFiber.run do get_db do |db| - db.exec "update ids set sort_title = (?) where id = (?)", sort_title, entry_id + db.exec "update ids set sort_title = (?) where id = (?)", + sort_title, entry_id end end end diff --git a/src/util/util.cr b/src/util/util.cr index 74738b7..82edb6a 100644 --- a/src/util/util.cr +++ b/src/util/util.cr @@ -86,7 +86,7 @@ def env_is_true?(key : String) : Bool val.downcase.in? "1", "true" end -def sort_titles(titles : Array(Title), opt : SortOptions, username : String) : Array(Title) +def sort_titles(titles : Array(Title), opt : SortOptions, username : String) cache_key = SortedTitlesCacheEntry.gen_key username, titles, opt cached_titles = LRUCache.get cache_key return cached_titles if cached_titles.is_a? Array(Title) From ecaec307d6549c03e84ea333bd973087d31d5ace Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Sun, 26 Dec 2021 04:27:27 +0900 Subject: [PATCH 16/20] Fix title sort bug, invalidate titles of the Library Refactor remove cache --- src/library/entry.cr | 3 ++- src/library/title.cr | 24 +++++++++++++++--------- src/util/util.cr | 24 ++++++++++++++++++------ 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/library/entry.cr b/src/library/entry.cr index 067acce..8b80d46 100644 --- a/src/library/entry.cr +++ b/src/library/entry.cr @@ -90,7 +90,8 @@ class Entry end @book.entry_sort_title_cache = nil - @book.remove_sorted_caches [SortMethod::Auto, SortMethod::Title], username + @book.remove_sorted_entries_cache [SortMethod::Auto, SortMethod::Title], + username end def sort_title_db diff --git a/src/library/title.cr b/src/library/title.cr index d5d8692..6fa78a5 100644 --- a/src/library/title.cr +++ b/src/library/title.cr @@ -320,7 +320,13 @@ class Title @sort_title = sort_title end - remove_sorted_caches [SortMethod::Auto, SortMethod::Title], username + if parents.size > 0 + target = parents[-1].titles + else + target = Library.default.titles + end + remove_sorted_titles_cache target, + [SortMethod::Auto, SortMethod::Title], username end def sort_title_db @@ -612,7 +618,8 @@ class Title zip + titles.flat_map &.deep_entries_with_date_added end - def remove_sorted_caches(sort_methods : Array(SortMethod), username : String) + def remove_sorted_entries_cache(sort_methods : Array(SortMethod), + username : String) [false, true].each do |ascend| sort_methods.each do |sort_method| sorted_entries_cache_key = @@ -621,15 +628,14 @@ class Title LRUCache.invalidate sorted_entries_cache_key end end + end + + def remove_sorted_caches(sort_methods : Array(SortMethod), username : String) + remove_sorted_entries_cache sort_methods, username parents.each do |parent| - [false, true].each do |ascend| - sort_methods.each do |sort_method| - sorted_titles_cache_key = SortedTitlesCacheEntry.gen_key username, - parent.titles, SortOptions.new(sort_method, ascend) - LRUCache.invalidate sorted_titles_cache_key - end - end + remove_sorted_titles_cache parent.titles, sort_methods, username end + remove_sorted_titles_cache Library.default.titles, sort_methods, username end def bulk_progress(action, ids : Array(String), username) diff --git a/src/util/util.cr b/src/util/util.cr index 82edb6a..11d1a13 100644 --- a/src/util/util.cr +++ b/src/util/util.cr @@ -91,25 +91,25 @@ def sort_titles(titles : Array(Title), opt : SortOptions, username : String) cached_titles = LRUCache.get cache_key return cached_titles if cached_titles.is_a? Array(Title) - ary = titles - case opt.method when .time_modified? - ary.sort { |a, b| (a.mtime <=> b.mtime).or \ + ary = titles.sort { |a, b| (a.mtime <=> b.mtime).or \ compare_numerically a.sort_title, b.sort_title } when .progress? - ary.sort do |a, b| + ary = titles.sort do |a, b| (a.load_percentage(username) <=> b.load_percentage(username)).or \ compare_numerically a.sort_title, b.sort_title end when .title? - ary.sort { |a, b| compare_numerically a.sort_title, b.sort_title } + ary = titles.sort do |a, b| + compare_numerically a.sort_title, b.sort_title + end else unless opt.method.auto? Logger.warn "Unknown sorting method #{opt.not_nil!.method}. Using " \ "Auto instead" end - ary.sort { |a, b| compare_numerically a.sort_title, b.sort_title } + ary = titles.sort { |a, b| compare_numerically a.sort_title, b.sort_title } end ary.reverse! unless opt.not_nil!.ascend @@ -118,6 +118,18 @@ def sort_titles(titles : Array(Title), opt : SortOptions, username : String) ary end +def remove_sorted_titles_cache(titles : Array(Title), + sort_methods : Array(SortMethod), + username : String) + [false, true].each do |ascend| + sort_methods.each do |sort_method| + sorted_titles_cache_key = SortedTitlesCacheEntry.gen_key username, + titles, SortOptions.new(sort_method, ascend) + LRUCache.invalidate sorted_titles_cache_key + end + end +end + class String # Returns the similarity (in [0, 1]) of two paths. # For the two paths, separate them into arrays of components, count the From e7538bb7f20a791840d45471a2dd97fea8658ae7 Mon Sep 17 00:00:00 2001 From: Leeingnyo Date: Sun, 26 Dec 2021 05:56:45 +0900 Subject: [PATCH 17/20] Use val(), Remove callbacks after modal hidden --- public/js/title.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/public/js/title.js b/public/js/title.js index d6cde9a..5d0e49f 100644 --- a/public/js/title.js +++ b/public/js/title.js @@ -60,6 +60,11 @@ function showModal(encodedPath, pages, percentage, encodedeTitle, encodedEntryTi UIkit.modal($('#modal')).show(); } +UIkit.util.on(document, 'hidden', '#modal', () => { + $('#read-btn').off('click'); + $('#unread-btn').off('click'); +}); + const updateProgress = (tid, eid, page) => { let url = `${base_url}api/progress/${tid}/${page}` const query = $.param({ @@ -181,7 +186,7 @@ const edit = (eid) => { }); const sortTitleField = $('#sort-title-field'); - sortTitleField.attr('value', sortTitle); + sortTitleField.val(sortTitle); sortTitleField.attr('placeholder', fileTitle); sortTitleField.keyup(event => { if (event.keyCode === 13) { @@ -197,6 +202,16 @@ const edit = (eid) => { UIkit.modal($('#edit-modal')).show(); }; +UIkit.util.on(document, 'hidden', '#edit-modal', () => { + const displayNameField = $('#display-name-field'); + displayNameField.off('keyup'); + displayNameField.off('click'); + + const sortTitleField = $('#sort-title-field'); + sortTitleField.off('keyup'); + sortTitleField.off('click'); +}); + const setupUpload = (eid) => { const upload = $('.upload-field'); const bar = $('#upload-progress').get(0); From ab29a9eb80daf729960f0fcc3dbc96b34f4fb8ef Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Fri, 31 Dec 2021 14:33:49 +0000 Subject: [PATCH 18/20] Fix down SQL for removing columns --- migration/sort_title.12.cr | 83 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/migration/sort_title.12.cr b/migration/sort_title.12.cr index 8da828f..a62f244 100644 --- a/migration/sort_title.12.cr +++ b/migration/sort_title.12.cr @@ -9,9 +9,86 @@ class SortTitle < MG::Base def down : String <<-SQL - -- drop sort_title column to ids and titles - ALTER TABLE ids DROP COLUMN sort_title; - ALTER TABLE titles DROP COLUMN sort_title; + -- remove sort_title column from ids + ALTER TABLE ids RENAME TO tmp; + + CREATE TABLE ids ( + path TEXT NOT NULL, + id TEXT NOT NULL, + signature TEXT, + unavailable INTEGER NOT NULL DEFAULT 0 + ); + + INSERT INTO ids + SELECT path, id, signature, unavailable + FROM tmp; + + DROP TABLE tmp; + + -- recreate the indices + CREATE UNIQUE INDEX path_idx ON ids (path); + CREATE UNIQUE INDEX id_idx ON ids (id); + + -- recreate the foreign key constraint on thumbnails + ALTER TABLE thumbnails RENAME TO tmp; + + CREATE TABLE thumbnails ( + id TEXT NOT NULL, + data BLOB NOT NULL, + filename TEXT NOT NULL, + mime TEXT NOT NULL, + size INTEGER NOT NULL, + FOREIGN KEY (id) REFERENCES ids (id) + ON UPDATE CASCADE + ON DELETE CASCADE + ); + + INSERT INTO thumbnails + SELECT * FROM tmp; + + DROP TABLE tmp; + + CREATE UNIQUE INDEX tn_index ON thumbnails (id); + + -- remove sort_title column from titles + ALTER TABLE titles RENAME TO tmp; + + CREATE TABLE titles ( + id TEXT NOT NULL, + path TEXT NOT NULL, + signature TEXT, + unavailable INTEGER NOT NULL DEFAULT 0 + ); + + INSERT INTO titles + SELECT path, id, signature, unavailable + FROM tmp; + + DROP TABLE tmp; + + -- recreate the indices + CREATE UNIQUE INDEX titles_id_idx on titles (id); + CREATE UNIQUE INDEX titles_path_idx on titles (path); + + -- recreate the foreign key constraint on tags + ALTER TABLE tags RENAME TO tmp; + + CREATE TABLE tags ( + id TEXT NOT NULL, + tag TEXT NOT NULL, + UNIQUE (id, tag), + FOREIGN KEY (id) REFERENCES titles (id) + ON UPDATE CASCADE + ON DELETE CASCADE + ); + + INSERT INTO tags + SELECT * FROM tmp; + + DROP TABLE tmp; + + CREATE INDEX tags_id_idx ON tags (id); + CREATE INDEX tags_tag_idx ON tags (tag); SQL end end From b83ccf1ccce354352d847531cfb005a10443b8ab Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Sat, 15 Jan 2022 12:08:23 +0000 Subject: [PATCH 19/20] Fix down SQL --- migration/sort_title.12.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migration/sort_title.12.cr b/migration/sort_title.12.cr index a62f244..9853182 100644 --- a/migration/sort_title.12.cr +++ b/migration/sort_title.12.cr @@ -61,7 +61,7 @@ class SortTitle < MG::Base ); INSERT INTO titles - SELECT path, id, signature, unavailable + SELECT id, path, signature, unavailable FROM tmp; DROP TABLE tmp; From 1b32dc3de9d024295023c13052fe7cba75882434 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Sat, 15 Jan 2022 12:09:03 +0000 Subject: [PATCH 20/20] Add sort title to API response --- src/library/entry.cr | 1 + src/library/title.cr | 1 + 2 files changed, 2 insertions(+) diff --git a/src/library/entry.cr b/src/library/entry.cr index 8b80d46..ceaa531 100644 --- a/src/library/entry.cr +++ b/src/library/entry.cr @@ -59,6 +59,7 @@ class Entry json.field {{str}}, @{{str.id}} {% end %} json.field "title_id", @book.id + json.field "sort_title", sort_title json.field "pages" { json.number @pages } unless slim json.field "display_name", @book.display_name @title diff --git a/src/library/title.cr b/src/library/title.cr index 6fa78a5..539f114 100644 --- a/src/library/title.cr +++ b/src/library/title.cr @@ -209,6 +209,7 @@ class Title json.field {{str}}, @{{str.id}} {% end %} json.field "signature" { json.number @signature } + json.field "sort_title", sort_title unless slim json.field "display_name", display_name json.field "cover_url", cover_url