add folders/templates sorting

pull/475/head
Alex Turchyn 9 months ago committed by Pete Matsyburka
parent b498291b62
commit e1cd62ff40

@ -7,11 +7,18 @@ class TemplatesDashboardController < ApplicationController
SHOW_TEMPLATES_FOLDERS_THRESHOLD = 9 SHOW_TEMPLATES_FOLDERS_THRESHOLD = 9
TEMPLATES_PER_PAGE = 12 TEMPLATES_PER_PAGE = 12
FOLDERS_PER_PAGE = 18 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 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 = TemplateFolders.search(@template_folders, params[:q])
@template_folders = sort_template_folders(@template_folders)
@pagy, @template_folders = pagy( @pagy, @template_folders = pagy(
@template_folders, @template_folders,
@ -24,6 +31,7 @@ class TemplatesDashboardController < ApplicationController
else else
@template_folders = @template_folders.reject { |e| e.name == TemplateFolder::DEFAULT_NAME } @template_folders = @template_folders.reject { |e| e.name == TemplateFolder::DEFAULT_NAME }
@templates = filter_templates(@templates) @templates = filter_templates(@templates)
@templates = sort_templates(@templates)
limit = limit =
if @template_folders.size < 4 if @template_folders.size < 4
@ -39,7 +47,7 @@ class TemplatesDashboardController < ApplicationController
private private
def filter_templates(templates) 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 params[:q].blank?
if Docuseal.multitenant? && !current_account.testing? if Docuseal.multitenant? && !current_account.testing?
@ -54,4 +62,42 @@ class TemplatesDashboardController < ApplicationController
Templates.search(rel, params[:q]) Templates.search(rel, params[:q])
end 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 end

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="#2c3e50" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M3 9l4 -4l4 4m-4 -4v14" />
<path d="M21 15l-4 4l-4 -4m4 4v-14" />
</svg>

After

Width:  |  Height:  |  Size: 357 B

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" width="24" height="24" stroke-width="2">
<path d="M15 10v-5c0 -1.38 .62 -2 2 -2s2 .62 2 2v5m0 -3h-4"></path>
<path d="M19 21h-4l4 -7h-4"></path> <path d="M4 15l3 3l3 -3"></path>
<path d="M7 6v12"></path>
</svg>

After

Width:  |  Height:  |  Size: 395 B

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" width="24" height="24" stroke-width="2">
<path d="M4 15l3 3l3 -3"></path>
<path d="M7 6v12"></path>
<path d="M17 14a2 2 0 0 1 2 2v3a2 2 0 1 1 -4 0v-3a2 2 0 0 1 2 -2z"></path>
<path d="M17 5m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0"></path>
<path d="M19 5v3a2 2 0 0 1 -2 2h-1.5"></path>
</svg>

After

Width:  |  Height:  |  Size: 474 B

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" width="24" height="24" stroke-width="2">
<path d="M10 15l-3 3l-3 -3"></path>
<path d="M7 6v12"></path>
<path d="M14 18.333c0 .369 .298 .667 .667 .667h2.666a.667 .667 0 0 0 .667 -.667v-2.666a.667 .667 0 0 0 -.667 -.667h-2.666a.667 .667 0 0 0 -.667 .667v2.666z"></path>
<path d="M14 10.833c0 .645 .522 1.167 1.167 1.167h4.666c.645 0 1.167 -.522 1.167 -1.167v-4.666c0 -.645 -.522 -1.167 -1.167 -1.167h-4.666c-.645 0 -1.167 .522 -1.167 1.167v4.666z"></path>
</svg>

After

Width:  |  Height:  |  Size: 647 B

@ -5,20 +5,23 @@
<%= @pagy.from %>-<%= local_assigns.fetch(:to, @pagy.to) %> of <%= local_assigns.fetch(:count, @pagy.count) %> <%= local_assigns[:items_name] || 'items' %> <%= @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[:left_additional_html] %>
</div> </div>
<div class="join"> <div class="flex items-center gap-1">
<% if @pagy.prev %> <%= local_assigns[:right_additional_html] %>
<%== link.call(@pagy.prev, '«', classes: 'join-item btn min-h-full h-10') %> <div class="join">
<% else %> <% if @pagy.prev %>
<span class="join-item btn btn-disabled !bg-base-200 min-h-full h-10">«</span> <%== link.call(@pagy.prev, '«', classes: 'join-item btn min-h-full h-10') %>
<% end %> <% else %>
<span class="join-item btn uppercase min-h-full h-10"> <span class="join-item btn btn-disabled !bg-base-200 min-h-full h-10">«</span>
<%= t('page_number', number: @pagy.page) %> <% end %>
</span> <span class="join-item btn uppercase min-h-full h-10">
<% if @pagy.next %> <%= t('page_number', number: @pagy.page) %>
<%== link.call(@pagy.next, '»', classes: 'join-item btn min-h-full h-10') %> </span>
<% else %> <% if @pagy.next %>
<span class="join-item btn btn-disabled !bg-base-200 min-h-full h-10">»</span> <%== link.call(@pagy.next, '»', classes: 'join-item btn min-h-full h-10') %>
<% end %> <% else %>
<span class="join-item btn btn-disabled !bg-base-200 min-h-full h-10">»</span>
<% end %>
</div>
</div> </div>
</div> </div>
<% end %> <% end %>

@ -0,0 +1,32 @@
<% dashboard_templates_order = cookies.permanent[:dashboard_templates_order] || 'creation_date' %>
<form action="<%= root_path %>" method="get" class="dropdown dropdown-top">
<label tabindex="0" class="btn btn-sm h-10">
<%= svg_icon('arrow_sort', class: 'w-5 h-5') %>
</label>
<ul tabindex="0" class="dropdown-content z-[10] menu p-2 shadow bg-base-100 rounded-box mb-1 min-w-48">
<toggle-cookies data-value="name" data-key="dashboard_templates_order">
<li>
<button class="<%= 'bg-base-200' if dashboard_templates_order == 'name' %>">
<%= svg_icon('sort_ascending_letters', class: 'w-4 h-4') %>
<span class="whitespace-nowrap"><%= t('name_a_z') %></span>
</button>
</li>
</toggle-cookies>
<toggle-cookies data-value="recently_used" data-key="dashboard_templates_order">
<li>
<button class="<%= 'bg-base-200' if dashboard_templates_order == 'recently_used' %>">
<%= svg_icon('sort_descending_small_big', class: 'w-4 h-4') %>
<span class="whitespace-nowrap"><%= t('recently_used') %></span>
</button>
</li>
</toggle-cookies>
<toggle-cookies data-value="creation_date" data-key="dashboard_templates_order">
<li>
<button class="<%= 'bg-base-200' if dashboard_templates_order == 'creation_date' %>">
<%= svg_icon('sort_descending_numbers', class: 'w-4 h-4') %>
<span class="whitespace-nowrap"><%= t('creation_date') %></span>
</button>
</li>
</toggle-cookies>
</ul>
</form>

@ -34,6 +34,11 @@
</div> </div>
<% end %> <% end %>
<% 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? %> <% if @template_folders.present? %>
<div class="grid gap-4 md:grid-cols-3 <%= 'mb-6' if @templates.present? %>"> <div class="grid gap-4 md:grid-cols-3 <%= 'mb-6' if @templates.present? %>">
<%= render partial: 'template_folders/folder', collection: @template_folders, as: :folder %> <%= render partial: 'template_folders/folder', collection: @template_folders, as: :folder %>
@ -71,7 +76,7 @@
<% end %> <% end %>
<% if @templates.present? || params[:q].blank? %> <% if @templates.present? || params[:q].blank? %>
<% if @pagy.pages > 1 %> <% 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 %> <% else %>
<div class="mt-2"> <div class="mt-2">
<%= view_archived_html %> <%= view_archived_html %>

@ -712,6 +712,9 @@ en: &en
welcome_to_docuseal: Welcome to DocuSeal 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_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 start_tour: Start Tour
name_a_z: Name A-Z
recently_used: Recently Used
creation_date: Creation Date
submission_sources: submission_sources:
api: API api: API
bulk: Bulk Send bulk: Bulk Send
@ -1490,6 +1493,9 @@ es: &es
welcome_to_docuseal: Bienvenido a DocuSeal 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_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 start_tour: Iniciar guía
name_a_z: Nombre A-Z
recently_used: Usado recientemente
creation_date: Fecha de creación
submission_sources: submission_sources:
api: API api: API
bulk: Envío masivo bulk: Envío masivo
@ -2267,6 +2273,9 @@ it: &it
welcome_to_docuseal: Benvenuto in DocuSeal 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_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 start_tour: Inizia il tour
name_a_z: Nome A-Z
recently_used: Usato di recente
creation_date: Data di creazione
submission_sources: submission_sources:
api: API api: API
bulk: Invio massivo bulk: Invio massivo
@ -3046,6 +3055,9 @@ fr: &fr
welcome_to_docuseal: Bienvenue sur DocuSeal 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_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 start_tour: Démarrer
name_a_z: Nom A-Z
recently_used: Récemment utilisé
creation_date: Date de création
submission_sources: submission_sources:
api: API api: API
bulk: Envoi en masse bulk: Envoi en masse
@ -3824,6 +3836,9 @@ pt: &pt
welcome_to_docuseal: Bem-vindo ao DocuSeal 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_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 start_tour: Iniciar tour
name_a_z: Nome A-Z
recently_used: Usado recentemente
creation_date: Data de criação
submission_sources: submission_sources:
api: API api: API
bulk: Envio em massa bulk: Envio em massa
@ -4603,6 +4618,9 @@ de: &de
welcome_to_docuseal: Willkommen bei DocuSeal 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_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 start_tour: Starten
name_a_z: Name A-Z
recently_used: Kürzlich verwendet
creation_date: Erstellungsdatum
submission_sources: submission_sources:
api: API api: API
bulk: Massenversand bulk: Massenversand

Loading…
Cancel
Save