From 7fee82ded2fdc8c251bb41910d93bbb8f84b91c5 Mon Sep 17 00:00:00 2001 From: Pete Matsyburka Date: Tue, 22 Apr 2025 16:32:09 +0300 Subject: [PATCH] fix order queries --- .../template_folders_controller.rb | 3 +- .../templates_dashboard_controller.rb | 63 ++++++++----------- app/views/shared/_pagination.html.erb | 4 +- .../shared/_templates_order_select.html.erb | 36 +++++------ app/views/template_folders/show.html.erb | 7 ++- config/locales/i18n.yml | 18 +++--- lib/templates/order.rb | 34 ++++++++++ 7 files changed, 97 insertions(+), 68 deletions(-) create mode 100644 lib/templates/order.rb diff --git a/app/controllers/template_folders_controller.rb b/app/controllers/template_folders_controller.rb index a3418015..05b19814 100644 --- a/app/controllers/template_folders_controller.rb +++ b/app/controllers/template_folders_controller.rb @@ -5,8 +5,9 @@ class TemplateFoldersController < ApplicationController def show @templates = @template_folder.templates.active.accessible_by(current_ability) - .preload(:author, :template_accesses).order(id: :desc) + .preload(:author, :template_accesses) @templates = Templates.search(@templates, params[:q]) + @templates = Templates::Order.call(@templates, cookies.permanent[:dashboard_templates_order]) @pagy, @templates = pagy(@templates, limit: 12) end diff --git a/app/controllers/templates_dashboard_controller.rb b/app/controllers/templates_dashboard_controller.rb index ad8d049a..f6964432 100644 --- a/app/controllers/templates_dashboard_controller.rb +++ b/app/controllers/templates_dashboard_controller.rb @@ -7,18 +7,12 @@ class TemplatesDashboardController < ApplicationController SHOW_TEMPLATES_FOLDERS_THRESHOLD = 9 TEMPLATES_PER_PAGE = 12 FOLDERS_PER_PAGE = 18 - LAST_USED_SQL = <<~SQL.squish - GREATEST( - COALESCE(MAX(templates.updated_at), '1970-01-01'), - COALESCE(MAX(submissions.created_at), '1970-01-01') - ) - SQL def index @template_folders = @template_folders.where(id: @templates.active.select(:folder_id)) @template_folders = TemplateFolders.search(@template_folders, params[:q]) - @template_folders = sort_template_folders(@template_folders) + @template_folders = sort_template_folders(@template_folders, cookies.permanent[:dashboard_templates_order]) @pagy, @template_folders = pagy( @template_folders, @@ -31,7 +25,7 @@ class TemplatesDashboardController < ApplicationController else @template_folders = @template_folders.reject { |e| e.name == TemplateFolder::DEFAULT_NAME } @templates = filter_templates(@templates) - @templates = sort_templates(@templates) + @templates = Templates::Order.call(@templates, cookies.permanent[:dashboard_templates_order]) limit = if @template_folders.size < 4 @@ -63,41 +57,36 @@ class TemplatesDashboardController < ApplicationController Templates.search(rel, params[:q]) end - def sort_template_folders(template_folders) - return template_folders.order(id: :desc) if params[:q].present? + def sort_template_folders(template_folders, order) + case order + when 'used_at' + subquery = + Template.left_joins(:submissions) + .group(:folder_id) + .select( + :folder_id, + Template.arel_table[:updated_at].maximum.as('updated_at_max'), + Submission.arel_table[:created_at].maximum.as('submission_created_at_max') + ) - case cookies.permanent[:dashboard_templates_order] - when 'recently_used' - sorted_folders = - template_folders.left_joins(templates: :submissions) - .select("template_folders.*, #{LAST_USED_SQL} AS last_used_at") - .group('template_folders.id') - .order(Arel.sql("#{LAST_USED_SQL} DESC NULLS LAST")) + template_folders = template_folders.joins( + Template.arel_table + .join(subquery.arel.as('templates'), Arel::Nodes::OuterJoin) + .on(TemplateFolder.arel_table[:id].eq(Template.arel_table[:folder_id])) + .join_sources + ) - TemplateFolder.from(sorted_folders, :template_folders) + template_folders.order( + Arel::Nodes::Case.new + .when(Template.arel_table[:submission_created_at_max].gt(Template.arel_table[:updated_at_max])) + .then(Template.arel_table[:submission_created_at_max]) + .else(Template.arel_table[:updated_at_max]) + .desc + ) when 'name' template_folders.order(name: :asc) else template_folders.order(id: :desc) end end - - def sort_templates(templates) - return templates.order(id: :desc) if params[:q].present? - - case cookies.permanent[:dashboard_templates_order] - when 'recently_used' - sorted_templates = - templates.left_joins(:submissions) - .select("templates.*, #{LAST_USED_SQL} AS last_used_at") - .group('templates.id') - .order(Arel.sql("#{LAST_USED_SQL} DESC NULLS LAST")) - - Template.from(sorted_templates, :templates) - when 'name' - templates.order(name: :asc) - else - templates.order(id: :desc) - end - end end diff --git a/app/views/shared/_pagination.html.erb b/app/views/shared/_pagination.html.erb index 2c365542..8eecc313 100644 --- a/app/views/shared/_pagination.html.erb +++ b/app/views/shared/_pagination.html.erb @@ -5,7 +5,7 @@ <%= @pagy.from %>-<%= local_assigns.fetch(:to, @pagy.to) %> of <%= local_assigns.fetch(:count, @pagy.count) %> <%= local_assigns[:items_name] || 'items' %> <%= local_assigns[:left_additional_html] %> -
+
<%= local_assigns[:right_additional_html] %>
<% if @pagy.prev %> @@ -13,7 +13,7 @@ <% else %> « <% end %> - + <%= t('page_number', number: @pagy.page) %> <% if @pagy.next %> diff --git a/app/views/shared/_templates_order_select.html.erb b/app/views/shared/_templates_order_select.html.erb index 62c63803..520ecae1 100644 --- a/app/views/shared/_templates_order_select.html.erb +++ b/app/views/shared/_templates_order_select.html.erb @@ -1,9 +1,25 @@ -<% dashboard_templates_order = cookies.permanent[:dashboard_templates_order] || 'creation_date' %> - diff --git a/app/views/template_folders/show.html.erb b/app/views/template_folders/show.html.erb index 65acdcd5..1793c993 100644 --- a/app/views/template_folders/show.html.erb +++ b/app/views/template_folders/show.html.erb @@ -35,7 +35,12 @@
<%= render partial: 'templates/template', collection: @templates %>
- <%= render 'shared/pagination', pagy: @pagy, items_name: 'templates' %> + <% templates_order_select_html = capture do %> + <% if params[:q].blank? && @pagy.pages > 1 %> + <%= render('shared/templates_order_select') %> + <% end %> + <% end %> + <%= render 'shared/pagination', pagy: @pagy, items_name: 'templates', right_additional_html: templates_order_select_html %> <% elsif params[:q].present? %>
diff --git a/config/locales/i18n.yml b/config/locales/i18n.yml index e5a35380..2fbf8328 100644 --- a/config/locales/i18n.yml +++ b/config/locales/i18n.yml @@ -713,8 +713,8 @@ en: &en start_a_quick_tour_to_learn_how_to_create_an_send_your_first_document: Start a quick tour to learn how to create an send your first document start_tour: Start Tour name_a_z: Name A-Z - recently_used: Recently Used - creation_date: Creation Date + recently_used: Recently used + newest_first: Newest first submission_sources: api: API bulk: Bulk Send @@ -1495,7 +1495,7 @@ es: &es start_tour: Iniciar guía name_a_z: Nombre A-Z recently_used: Usado recientemente - creation_date: Fecha de creación + newest_first: Más reciente primero submission_sources: api: API bulk: Envío masivo @@ -2274,8 +2274,8 @@ it: &it start_a_quick_tour_to_learn_how_to_create_an_send_your_first_document: Inizia un tour rapido per imparare a creare e inviare il tuo primo documento. start_tour: Inizia il tour name_a_z: Nome A-Z - recently_used: Usato di recente - creation_date: Data di creazione + recently_used: Recentemente usato + newest_first: Più recenti prima submission_sources: api: API bulk: Invio massivo @@ -3057,7 +3057,7 @@ fr: &fr start_tour: Démarrer name_a_z: Nom A-Z recently_used: Récemment utilisé - creation_date: Date de création + newest_first: Le plus récent d'abord submission_sources: api: API bulk: Envoi en masse @@ -3837,8 +3837,8 @@ pt: &pt start_a_quick_tour_to_learn_how_to_create_an_send_your_first_document: Comece um tour rápido para aprender a criar e enviar seu primeiro documento. start_tour: Iniciar tour name_a_z: Nome A-Z - recently_used: Usado recentemente - creation_date: Data de criação + recently_used: Recentemente usado + newest_first: Mais recente primeiro submission_sources: api: API bulk: Envio em massa @@ -4620,7 +4620,7 @@ de: &de start_tour: Starten name_a_z: Name A-Z recently_used: Kürzlich verwendet - creation_date: Erstellungsdatum + newest_first: Neueste zuerst submission_sources: api: API bulk: Massenversand diff --git a/lib/templates/order.rb b/lib/templates/order.rb new file mode 100644 index 00000000..726120ca --- /dev/null +++ b/lib/templates/order.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Templates + module Order + module_function + + def call(templates, order) + case order + when 'used_at' + subquery = Submission.select(:template_id, Submission.arel_table[:created_at].maximum.as('created_at')) + .group(:template_id) + + templates = templates.joins( + Template.arel_table + .join(subquery.arel.as('submissions'), Arel::Nodes::OuterJoin) + .on(Template.arel_table[:id].eq(Submission.arel_table[:template_id])) + .join_sources + ) + + templates.order( + Arel::Nodes::Case.new + .when(Submission.arel_table[:created_at].gt(Template.arel_table[:updated_at])) + .then(Submission.arel_table[:created_at]) + .else(Template.arel_table[:updated_at]) + .desc + ) + when 'name' + templates.order(name: :asc) + else + templates.order(id: :desc) + end + end + end +end