diff --git a/app/controllers/templates_dashboard_controller.rb b/app/controllers/templates_dashboard_controller.rb index 7c806fa9..ad8d049a 100644 --- a/app/controllers/templates_dashboard_controller.rb +++ b/app/controllers/templates_dashboard_controller.rb @@ -7,11 +7,18 @@ 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)).order(id: :desc) + @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) @pagy, @template_folders = pagy( @template_folders, @@ -24,6 +31,7 @@ class TemplatesDashboardController < ApplicationController else @template_folders = @template_folders.reject { |e| e.name == TemplateFolder::DEFAULT_NAME } @templates = filter_templates(@templates) + @templates = sort_templates(@templates) limit = if @template_folders.size < 4 @@ -39,7 +47,7 @@ class TemplatesDashboardController < ApplicationController private def filter_templates(templates) - rel = templates.active.preload(:author, :template_accesses).order(id: :desc) + rel = templates.active.preload(:author, :template_accesses) if params[:q].blank? if Docuseal.multitenant? && !current_account.testing? @@ -54,4 +62,42 @@ 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? + + 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")) + + TemplateFolder.from(sorted_folders, :template_folders) + 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/icons/_arrow_sort.html.erb b/app/views/icons/_arrow_sort.html.erb new file mode 100644 index 00000000..9298a506 --- /dev/null +++ b/app/views/icons/_arrow_sort.html.erb @@ -0,0 +1,5 @@ + + + + + diff --git a/app/views/icons/_sort_ascending_letters.html.erb b/app/views/icons/_sort_ascending_letters.html.erb new file mode 100644 index 00000000..4afd82d5 --- /dev/null +++ b/app/views/icons/_sort_ascending_letters.html.erb @@ -0,0 +1,5 @@ + + + + + diff --git a/app/views/icons/_sort_descending_numbers.html.erb b/app/views/icons/_sort_descending_numbers.html.erb new file mode 100644 index 00000000..85feb2fd --- /dev/null +++ b/app/views/icons/_sort_descending_numbers.html.erb @@ -0,0 +1,7 @@ + + + + + + + diff --git a/app/views/icons/_sort_descending_small_big.html.erb b/app/views/icons/_sort_descending_small_big.html.erb new file mode 100644 index 00000000..d3796644 --- /dev/null +++ b/app/views/icons/_sort_descending_small_big.html.erb @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/views/shared/_pagination.html.erb b/app/views/shared/_pagination.html.erb index e53128e1..2c365542 100644 --- a/app/views/shared/_pagination.html.erb +++ b/app/views/shared/_pagination.html.erb @@ -5,20 +5,23 @@ <%= @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] %> -
- <% if @pagy.prev %> - <%== link.call(@pagy.prev, '«', classes: 'join-item btn min-h-full h-10') %> - <% else %> - « - <% end %> - - <%= t('page_number', number: @pagy.page) %> - - <% if @pagy.next %> - <%== link.call(@pagy.next, '»', classes: 'join-item btn min-h-full h-10') %> - <% else %> - » - <% end %> +
+ <%= local_assigns[:right_additional_html] %> +
+ <% if @pagy.prev %> + <%== link.call(@pagy.prev, '«', classes: 'join-item btn min-h-full h-10') %> + <% else %> + « + <% end %> + + <%= t('page_number', number: @pagy.page) %> + + <% if @pagy.next %> + <%== link.call(@pagy.next, '»', classes: 'join-item btn min-h-full h-10') %> + <% else %> + » + <% end %> +
<% end %> diff --git a/app/views/shared/_templates_order_select.html.erb b/app/views/shared/_templates_order_select.html.erb new file mode 100644 index 00000000..62c63803 --- /dev/null +++ b/app/views/shared/_templates_order_select.html.erb @@ -0,0 +1,32 @@ +<% dashboard_templates_order = cookies.permanent[:dashboard_templates_order] || 'creation_date' %> + diff --git a/app/views/templates_dashboard/index.html.erb b/app/views/templates_dashboard/index.html.erb index c6f42c94..056b3cc4 100644 --- a/app/views/templates_dashboard/index.html.erb +++ b/app/views/templates_dashboard/index.html.erb @@ -34,6 +34,11 @@ <% end %> <% end %> +<% templates_order_select_html = capture do %> + <% if params[:q].blank? && @pagy.pages > 1 %> + <%= render('shared/templates_order_select') %> + <% end %> +<% end %> <% if @template_folders.present? %>
<%= render partial: 'template_folders/folder', collection: @template_folders, as: :folder %> @@ -71,7 +76,7 @@ <% end %> <% if @templates.present? || params[:q].blank? %> <% if @pagy.pages > 1 %> - <%= render 'shared/pagination', pagy: @pagy, items_name: 'templates', left_additional_html: view_archived_html %> + <%= render 'shared/pagination', pagy: @pagy, items_name: 'templates', left_additional_html: view_archived_html, right_additional_html: templates_order_select_html %> <% else %>
<%= view_archived_html %> diff --git a/config/locales/i18n.yml b/config/locales/i18n.yml index f15660ba..e5a35380 100644 --- a/config/locales/i18n.yml +++ b/config/locales/i18n.yml @@ -712,6 +712,9 @@ en: &en welcome_to_docuseal: Welcome to DocuSeal 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 submission_sources: api: API bulk: Bulk Send @@ -1490,6 +1493,9 @@ es: &es welcome_to_docuseal: Bienvenido a DocuSeal start_a_quick_tour_to_learn_how_to_create_an_send_your_first_document: Inicia una guía rápida para aprender a crear y enviar tu primer documento. start_tour: Iniciar guía + name_a_z: Nombre A-Z + recently_used: Usado recientemente + creation_date: Fecha de creación submission_sources: api: API bulk: Envío masivo @@ -2267,6 +2273,9 @@ it: &it welcome_to_docuseal: Benvenuto in DocuSeal 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 submission_sources: api: API bulk: Invio massivo @@ -3046,6 +3055,9 @@ fr: &fr welcome_to_docuseal: Bienvenue sur DocuSeal start_a_quick_tour_to_learn_how_to_create_an_send_your_first_document: Lancez une visite rapide pour apprendre à créer et envoyer votre premier document. start_tour: Démarrer + name_a_z: Nom A-Z + recently_used: Récemment utilisé + creation_date: Date de création submission_sources: api: API bulk: Envoi en masse @@ -3824,6 +3836,9 @@ pt: &pt welcome_to_docuseal: Bem-vindo ao DocuSeal 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 submission_sources: api: API bulk: Envio em massa @@ -4603,6 +4618,9 @@ de: &de welcome_to_docuseal: Willkommen bei DocuSeal start_a_quick_tour_to_learn_how_to_create_an_send_your_first_document: Starte eine kurze Tour, um zu lernen, wie du dein erstes Dokument erstellst und versendest. start_tour: Starten + name_a_z: Name A-Z + recently_used: Kürzlich verwendet + creation_date: Erstellungsdatum submission_sources: api: API bulk: Massenversand