From ae5f87f8fb47abcad374a0ed1a16ac3879926349 Mon Sep 17 00:00:00 2001 From: Pete Matsyburka Date: Sun, 13 Sep 2026 13:13:21 +0300 Subject: [PATCH] add search --- app/controllers/api/submissions_controller.rb | 1 - app/controllers/search_controller.rb | 132 ++++++++++++++++++ app/javascript/elements/native_search.js | 50 ++++--- app/javascript/lib/turbo_instant_click.js | 2 +- app/views/search/_folder.html.erb | 1 + app/views/search/_folders.html.erb | 9 ++ app/views/search/_results.html.erb | 28 ++++ app/views/search/_row.html.erb | 18 +++ app/views/search/_submission.html.erb | 4 + app/views/search/_submissions.html.erb | 9 ++ app/views/search/_template.html.erb | 2 + app/views/search/_templates.html.erb | 9 ++ app/views/search/index.html.erb | 10 ++ app/views/shared/_infinite_scroll.html.erb | 2 +- app/views/shared/_native_navbar.html.erb | 2 +- app/views/shared/_search_input.html.erb | 6 +- app/views/submissions_archived/index.html.erb | 3 + .../submissions_dashboard/index.html.erb | 3 + .../_applied_filters.html.erb | 26 +++- .../_filter_button.html.erb | 2 +- .../_filter_modal.html.erb | 4 +- app/views/template_folders/show.html.erb | 3 + app/views/templates/show.html.erb | 2 +- app/views/templates_archived/index.html.erb | 3 + .../index.html.erb | 3 + config/locales/i18n.yml | 14 ++ config/routes.rb | 1 + lib/submissions/filter.rb | 8 ++ 28 files changed, 323 insertions(+), 34 deletions(-) create mode 100644 app/controllers/search_controller.rb create mode 100644 app/views/search/_folder.html.erb create mode 100644 app/views/search/_folders.html.erb create mode 100644 app/views/search/_results.html.erb create mode 100644 app/views/search/_row.html.erb create mode 100644 app/views/search/_submission.html.erb create mode 100644 app/views/search/_submissions.html.erb create mode 100644 app/views/search/_template.html.erb create mode 100644 app/views/search/_templates.html.erb create mode 100644 app/views/search/index.html.erb diff --git a/app/controllers/api/submissions_controller.rb b/app/controllers/api/submissions_controller.rb index 9c7e6911b..e55cbe03d 100644 --- a/app/controllers/api/submissions_controller.rb +++ b/app/controllers/api/submissions_controller.rb @@ -173,7 +173,6 @@ module Api end def filter_submissions(submissions, params) - submissions = submissions.where(template_id: params[:template_id]) if params[:template_id].present? submissions = submissions.where(slug: params[:slug]) if params[:slug].present? if params[:template_folder].present? diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb new file mode 100644 index 000000000..1b8b1a261 --- /dev/null +++ b/app/controllers/search_controller.rb @@ -0,0 +1,132 @@ +# frozen_string_literal: true + +class SearchController < ApplicationController + load_and_authorize_resource :template_folder, parent: false + load_and_authorize_resource :template, parent: false + load_and_authorize_resource :submission, parent: false + load_and_authorize_resource :template, instance_name: :filter_template, id_param: :template_id, parent: true + + FOLDERS_LIMIT = 4 + LIMIT = 12 + + def index + @query = params[:q].to_s.squish + + return render_infinite_scroll(@template_folders, @templates, @submissions, @query) if turbo_infinite_scroll? + + if @query.blank? + @template_folders = @templates = @submissions = [] + elsif params[:scope] == 'folders' + @folders_pagy, @template_folders = + pagy(:countless, filter_folders(@template_folders, @templates, @query), limit: LIMIT) + + @templates = @submissions = [] + else + folders = filter_folders(@template_folders, @templates, @query) + + @pagy, @template_folders, @templates, @submissions = + if params[:scope] == 'submissions' + load_submissions_page(folders, @templates, @submissions, @query) + else + load_templates_page(folders, @templates, @submissions, @query) + end + + if @templates.blank? && @submissions.blank? && params[:template_id].blank? + @folders_pagy, @template_folders = pagy(:countless, folders, limit: LIMIT) + end + end + end + + private + + def load_submissions_page(folders, templates, submissions, query) + pagy, submissions = pagy(:countless, filter_submissions(submissions, query), limit: LIMIT) + + return [pagy, [], [], submissions] if pagy.next || params[:template_id].present? + + [pagy, folders.limit(FOLDERS_LIMIT).to_a, filter_templates(templates, query).limit(LIMIT).to_a, submissions] + end + + def load_templates_page(folders, templates, submissions, query) + pagy, templates = pagy(:countless, filter_templates(templates, query), limit: LIMIT) + + submissions = pagy.next ? [] : filter_submissions(submissions, query).limit(LIMIT).to_a + + [pagy, folders.limit(FOLDERS_LIMIT).to_a, templates, submissions] + end + + def render_infinite_scroll(folders, templates, submissions, query) + target, partial, collection = + case params[:scope] + when 'folders' + ['search_folders', 'search/folder', filter_folders(folders, templates, query)] + when 'submissions' + ['search_submissions', 'search/submission', filter_submissions(submissions, query)] + else + ['search_templates', 'search/template', filter_templates(templates, query)] + end + + pagy, records = pagy(:countless, collection, limit: LIMIT) + + render turbo_stream: [ + turbo_stream.append(target, partial:, collection: records), + turbo_stream.replace('infinite_scroll', partial: 'shared/infinite_scroll', locals: { pagy: }) + ] + end + + def filter_folders(folders, templates, query) + return folders.none if params[:archived] == 'true' + + folders = folders.where.not(id: current_account.default_template_folder.id) + + folders = folders.where(parent_folder_id: filter_folder_ids(params[:folder])) if params[:folder].present? + folders = folders.where(author_id: filter_author_id(params[:author])) if params[:author].present? + folders = TemplateFolders.filter_active_folders(folders, templates) + folders = TemplateFolders.search(folders, query) + + folders.preload(:parent_folder).order(:name) + end + + def filter_templates(templates, query) + templates = params[:archived] == 'true' ? templates.where.not(archived_at: nil) : templates.active + templates = templates.select_for_list.preload(:author, :template_accesses, folder: :parent_folder) + + templates = templates.where(folder_id: filter_folder_ids(params[:folder])) if params[:folder].present? + templates = templates.where(author_id: filter_author_id(params[:author])) if params[:author].present? + + Templates.search(current_user, templates, query).order(id: :desc) + end + + def filter_folder_ids(folder_name) + TemplateFolders.filter_by_full_name(current_account.template_folders, folder_name) + .preload(:subfolders) + .flat_map { |folder| [folder.id, *folder.subfolders.map(&:id)] } + end + + def filter_author_id(email) + current_account.users.find_by(email:)&.id || -1 + end + + def filter_submissions(submissions, query) + submissions = submissions.left_joins(:template) + + submissions = + if params[:archived] == 'true' + submissions.where.not(archived_at: nil).or(submissions.where.not(templates: { archived_at: nil })) + else + submissions.where(archived_at: nil).where(templates: { archived_at: nil }) + end + + submissions = Submissions.search(current_user, submissions, query, search_template: true) + submissions = Submissions::Filter.call(submissions, current_user, params) + + submissions = + if params[:status] == 'completed' || params[:completed_at_from].present? || params[:completed_at_to].present? + submissions.order(completed_at: :desc) + else + submissions.order(id: :desc) + end + + submissions.select_for_list.preload(:submitters, :template) + end +end diff --git a/app/javascript/elements/native_search.js b/app/javascript/elements/native_search.js index ecff58ebd..37bfe7bc1 100644 --- a/app/javascript/elements/native_search.js +++ b/app/javascript/elements/native_search.js @@ -1,27 +1,33 @@ -import { target, targetable } from '@github/catalyst/lib/targetable' - -export default targetable(class extends HTMLElement { - static [target.static] = ['form'] - +export default class extends HTMLElement { connectedCallback () { - const bridge = window.webkit?.messageHandlers?.native - - if (!bridge || !this.form) return - - const url = new URL(this.form.action) - - new FormData(this.form).forEach((value, key) => { - if (key !== 'q' && value) url.searchParams.set(key, value) - }) - - this.declared = true - - bridge.postMessage({ type: 'search', op: 'add', url: url.pathname + url.search }) + document.addEventListener('native:search', this.onSearch) } disconnectedCallback () { - if (this.declared) { - window.webkit?.messageHandlers?.native?.postMessage({ type: 'search', op: 'remove' }) - } + document.removeEventListener('native:search', this.onSearch) } -}) + + onSearch = (event) => { + const query = (event.detail?.q || '').trim() + + if (query === (this.dataset.q || '')) return + + this.dataset.q = query + + const url = new URL(this.frame.src || this.dataset.src, window.location.href) + + url.searchParams.delete('page') + + if (query) { + url.searchParams.set('q', query) + } else { + url.searchParams.delete('q') + } + + this.frame.src = url.toString() + } + + get frame () { + return this.querySelector('turbo-frame') + } +} diff --git a/app/javascript/lib/turbo_instant_click.js b/app/javascript/lib/turbo_instant_click.js index d72d4ce84..2a021e644 100644 --- a/app/javascript/lib/turbo_instant_click.js +++ b/app/javascript/lib/turbo_instant_click.js @@ -66,7 +66,7 @@ function mouseoverListener (event) { } else if (linkElement.dataset.turboFrame !== '_top') { const turboFrame = linkElement.closest('turbo-frame') - if (turboFrame) { + if (turboFrame && turboFrame.getAttribute('target') !== '_top') { requestOptions.headers['Turbo-Frame'] = turboFrame.id } } diff --git a/app/views/search/_folder.html.erb b/app/views/search/_folder.html.erb new file mode 100644 index 000000000..b8a99cb3d --- /dev/null +++ b/app/views/search/_folder.html.erb @@ -0,0 +1 @@ +<%= render 'search/row', href: folder_path(folder), icon: 'folder', title: folder.name, subtitle: folder.parent_folder&.name %> diff --git a/app/views/search/_folders.html.erb b/app/views/search/_folders.html.erb new file mode 100644 index 000000000..edcb537cd --- /dev/null +++ b/app/views/search/_folders.html.erb @@ -0,0 +1,9 @@ +<% if folders.present? %> +
+
<%= t('folders') %>
+
+ <%= render partial: 'search/folder', collection: folders %> +
+ <%= render 'shared/infinite_scroll', pagy:, query_params: { 'scope' => 'folders' } if pagy %> +
+<% end %> diff --git a/app/views/search/_results.html.erb b/app/views/search/_results.html.erb new file mode 100644 index 000000000..346894646 --- /dev/null +++ b/app/views/search/_results.html.erb @@ -0,0 +1,28 @@ +<% with_filters = params[:scope] == 'submissions' || params[:archived] == 'true' || Submissions::Filter::ALLOWED_PARAMS.any? { |key| params[key].present? } %> + + <% if with_filters %> + <% filter_params = params.permit(Submissions::Filter::ALLOWED_PARAMS).compact_blank %> + +
+ <%= render 'submissions_filters/applied_filters', filter_params:, with_status: true, with_archived: true, filter_template: @filter_template %> + <%= render 'submissions_filters/filter_button', filter_params: %> +
+ <% end %> +
+ <% if @query.present? %> + <% if @template_folders.blank? && @templates.blank? && @submissions.blank? %> +
+ <%= t('no_results') %> +
+ <% end %> + <% if params[:scope] == 'submissions' %> + <%= render 'search/submissions', submissions: @submissions, pagy: @pagy %> + <% end %> + <%= render 'search/folders', folders: @template_folders, pagy: @folders_pagy %> + <%= render 'search/templates', templates: @templates, pagy: (@pagy unless params[:scope] == 'submissions') %> + <% unless params[:scope] == 'submissions' %> + <%= render 'search/submissions', submissions: @submissions, pagy: nil %> + <% end %> + <% end %> +
+
diff --git a/app/views/search/_row.html.erb b/app/views/search/_row.html.erb new file mode 100644 index 000000000..4c596ad8a --- /dev/null +++ b/app/views/search/_row.html.erb @@ -0,0 +1,18 @@ +<% subtitle = local_assigns[:subtitle].presence %> +<% badge = local_assigns[:badge].presence %> +<% date = local_assigns[:date] %> + + <%= svg_icon(icon, class: 'w-6 h-6 shrink-0') %> +
+
<%= title %>
+ <% if subtitle %> +
<%= subtitle %>
+ <% end %> + <% if badge %> + <%= badge %> + <% end %> + <% if date %> + <%= l(date.in_time_zone(current_account.timezone).to_date, format: :short, locale: current_account.locale) %> + <% end %> +
+
diff --git a/app/views/search/_submission.html.erb b/app/views/search/_submission.html.erb new file mode 100644 index 000000000..fc85eac75 --- /dev/null +++ b/app/views/search/_submission.html.erb @@ -0,0 +1,4 @@ +<% status = submission.completed_at? ? 'completed' : (submission.expired? ? 'expired' : 'pending') %> +<% name = submission.name.presence || submission.template&.name %> +<% submitters = submission.submitters.filter_map { |s| s.name.presence || s.email.presence || s.phone.presence }.join(', ') %> +<%= render 'search/row', href: submission_path(submission), icon: 'file_text', title: submitters, subtitle: (name if params[:template_id].blank?), date: (params[:status] == 'completed' && submission.completed_at) || submission.created_at, badge: t(status), badge_class: { 'completed' => 'badge-success', 'expired' => 'badge-error', 'pending' => 'badge-info' }[status] %> diff --git a/app/views/search/_submissions.html.erb b/app/views/search/_submissions.html.erb new file mode 100644 index 000000000..d5a54e5b4 --- /dev/null +++ b/app/views/search/_submissions.html.erb @@ -0,0 +1,9 @@ +<% if submissions.present? %> +
+
<%= t('submissions') %>
+
+ <%= render partial: 'search/submission', collection: submissions %> +
+ <%= render 'shared/infinite_scroll', pagy: pagy if pagy %> +
+<% end %> diff --git a/app/views/search/_template.html.erb b/app/views/search/_template.html.erb new file mode 100644 index 000000000..5b32ef4bf --- /dev/null +++ b/app/views/search/_template.html.erb @@ -0,0 +1,2 @@ +<% author = template.author.full_name.presence || template.author.email.to_s.sub(/\+\w+@/, '@') %> +<%= render 'search/row', href: template_path(template), icon: 'layout_grid', title: template.name, subtitle: template.folder.default? || params[:folder].present? ? author : template.folder.full_name, date: template.created_at, native_actions: ('pencil,menu' if turbo_native_app? && !template.archived_at? && can?(:update, template)) %> diff --git a/app/views/search/_templates.html.erb b/app/views/search/_templates.html.erb new file mode 100644 index 000000000..c0a42ba97 --- /dev/null +++ b/app/views/search/_templates.html.erb @@ -0,0 +1,9 @@ +<% if templates.present? %> +
+
<%= t('templates') %>
+
+ <%= render partial: 'search/template', collection: templates %> +
+ <%= render 'shared/infinite_scroll', pagy: pagy if pagy %> +
+<% end %> diff --git a/app/views/search/index.html.erb b/app/views/search/index.html.erb new file mode 100644 index 000000000..f2009b0e7 --- /dev/null +++ b/app/views/search/index.html.erb @@ -0,0 +1,10 @@ +<% content_for(:native_title, t('search')) if turbo_native_app? %> +<% unless turbo_native_app? %> +
+

<%= t('search') %>

+ <%= render 'shared/search_input', placeholder: t('search') %> +
+<% end %> + + <%= render 'search/results' %> + diff --git a/app/views/shared/_infinite_scroll.html.erb b/app/views/shared/_infinite_scroll.html.erb index 09b7fbe7a..4161f5e7a 100644 --- a/app/views/shared/_infinite_scroll.html.erb +++ b/app/views/shared/_infinite_scroll.html.erb @@ -1,5 +1,5 @@ <% if pagy.next || pagy.page > 1 %> - + <%= svg_icon('loader', class: 'w-6 h-6 animate-spin') %> <% end %> diff --git a/app/views/shared/_native_navbar.html.erb b/app/views/shared/_native_navbar.html.erb index cdeb8a791..878315910 100644 --- a/app/views/shared/_native_navbar.html.erb +++ b/app/views/shared/_native_navbar.html.erb @@ -11,7 +11,7 @@ <% end %> - <% if can?(:create, ::Template) && controller_name.in?(%w[templates_dashboard submissions_dashboard template_folders]) %> + <% if can?(:create, ::Template) && controller_name.in?(%w[templates_dashboard submissions_dashboard template_folders templates_archived submissions_archived]) %> <% folder_name = @template_folder&.full_name %> "> diff --git a/app/views/shared/_search_input.html.erb b/app/views/shared/_search_input.html.erb index 501d6eea6..900f77728 100644 --- a/app/views/shared/_search_input.html.erb +++ b/app/views/shared/_search_input.html.erb @@ -1,5 +1,5 @@ - -
+<% unless turbo_native_app? %> + <% Submissions::Filter::ALLOWED_PARAMS.each do |key| %> <% if params[key].present? %> @@ -27,4 +27,4 @@
-
+<% end %> diff --git a/app/views/submissions_archived/index.html.erb b/app/views/submissions_archived/index.html.erb index e7c5a9e67..96651a2a6 100644 --- a/app/views/submissions_archived/index.html.erb +++ b/app/views/submissions_archived/index.html.erb @@ -1,5 +1,8 @@ <% content_for(:native_title, t('archived')) if turbo_native_app? %> <% filter_params = params.permit(Submissions::Filter::ALLOWED_PARAMS).compact_blank %> +<% if turbo_native_app? %> + +<% end %> <% unless turbo_native_app? %>
<%= link_to root_path, class: 'flex items-center mb-1 md:mb-0' do %> diff --git a/app/views/submissions_dashboard/index.html.erb b/app/views/submissions_dashboard/index.html.erb index 06da53ef3..92742603e 100644 --- a/app/views/submissions_dashboard/index.html.erb +++ b/app/views/submissions_dashboard/index.html.erb @@ -1,4 +1,7 @@ <% filter_params = params.permit(Submissions::Filter::ALLOWED_PARAMS).compact_blank %> +<% if turbo_native_app? %> + +<% end %> <% is_show_tabs = (@pagy.count.nil? || @pagy.count >= 5) || params[:status].present? || filter_params.present? %> <% if Docuseal.demo? %><%= render 'shared/demo_alert' %><% end %>
diff --git a/app/views/submissions_filters/_applied_filters.html.erb b/app/views/submissions_filters/_applied_filters.html.erb index d36093619..45de54e23 100644 --- a/app/views/submissions_filters/_applied_filters.html.erb +++ b/app/views/submissions_filters/_applied_filters.html.erb @@ -1,5 +1,5 @@ -<% query_params = params.permit(:q).merge(filter_params) %> -<% filter_names = %w[status folder author completed_at created_at] %> +<% query_params = params.permit(:q, :scope, :archived).merge(filter_params) %> +<% filter_names = %w[status archived template folder author completed_at created_at] %> <% ordered_filters = request.query_parameters.keys.filter_map { |key| filter_names.find { |name| key.start_with?(name) } }.uniq %> <% chip_order = ordered_filters.reverse.each_with_index.to_h { |name, index| [name, index + 1] } %> <% chip_order.default = ordered_filters.size + 1 %> @@ -22,6 +22,28 @@ <% end %> <% end %> <% chips_html = capture do %> + <% if local_assigns[:with_archived] && params[:archived] == 'true' %> +
+ + <%= svg_icon('archive', class: 'w-5 h-5 shrink-0') %> + <%= t('archived') %> + + <%= link_to url_for(params: request.query_parameters.except('archived')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %> + <%= svg_icon('x', class: 'w-5 h-5') %> + <% end %> +
+ <% end %> + <% if params[:template_id].present? %> +
+ + <%= svg_icon('layout_grid', class: 'w-5 h-5 shrink-0') %> + <%= local_assigns[:filter_template]&.name || 'NA' %> + + <%= link_to url_for(params: request.query_parameters.except('template_id')), class: 'rounded-lg ml-1 shrink-0 hover:bg-base-content hover:text-white' do %> + <%= svg_icon('x', class: 'w-5 h-5') %> + <% end %> +
+ <% end %> <% if params[:folder].present? %>
<%= link_to submissions_filter_path('folder', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 flex-1 min-w-0 pr-1' do %> diff --git a/app/views/submissions_filters/_filter_button.html.erb b/app/views/submissions_filters/_filter_button.html.erb index ab79aa7d7..3b76d8484 100644 --- a/app/views/submissions_filters/_filter_button.html.erb +++ b/app/views/submissions_filters/_filter_button.html.erb @@ -1,4 +1,4 @@ -<% query_params = params.permit(:q).merge(filter_params) %> +<% query_params = params.permit(:q, :scope, :archived).merge(filter_params) %> <% advanced_filters = filter_params.then { |f| f[:status].in?(%w[pending completed]) ? f.except(:status) : f } %> <% if params[:with_remove] %>
- <%= link_to t('remove_filter'), "#{path}?#{request.query_parameters.slice('q').merge(local_assigns[:default_params]).to_query}", class: 'link', data: { turbo_frame: :_top } %> + <%= link_to t('remove_filter'), "#{path}?#{request.query_parameters.slice('q', 'scope', 'archived').merge(local_assigns[:default_params]).to_query}", class: 'link', data: { turbo_frame: :_top } %>
<% end %> <% end %> diff --git a/app/views/template_folders/show.html.erb b/app/views/template_folders/show.html.erb index 39abe3cc7..56bda567c 100644 --- a/app/views/template_folders/show.html.erb +++ b/app/views/template_folders/show.html.erb @@ -1,4 +1,7 @@ <% content_for(:native_title, @template_folder.name) if turbo_native_app? %> +<% if turbo_native_app? %> + +<% end %> <% if turbo_native_app? && (can?(:manage, :countless) || current_account.templates.where.not(archived_at: nil).exists?) %> <%= t('view_archived') %> diff --git a/app/views/templates/show.html.erb b/app/views/templates/show.html.erb index c83ce8ebe..62c875da4 100644 --- a/app/views/templates/show.html.erb +++ b/app/views/templates/show.html.erb @@ -5,7 +5,7 @@ <% is_show_header = submissions_count != 0 || params[:q].present? || params[:status].present? || filter_params.present? %> <%= render 'title', template: @template, with_export: is_show_header %> <% if turbo_native_app? %> - <%= render 'shared/search_input' %> + <% if !@template.archived_at? && can?(:create, Submission) %> diff --git a/app/views/templates_archived/index.html.erb b/app/views/templates_archived/index.html.erb index f02389eaf..7dae6c474 100644 --- a/app/views/templates_archived/index.html.erb +++ b/app/views/templates_archived/index.html.erb @@ -1,4 +1,7 @@ <% content_for(:native_title, t('archived')) if turbo_native_app? %> +<% if turbo_native_app? %> + +<% end %> <% unless turbo_native_app? %>
<%= link_to root_path, class: 'flex items-center mb-1 md:mb-0' do %> diff --git a/app/views/templates_archived_submissions/index.html.erb b/app/views/templates_archived_submissions/index.html.erb index a3c504f17..4fd0efa90 100644 --- a/app/views/templates_archived_submissions/index.html.erb +++ b/app/views/templates_archived_submissions/index.html.erb @@ -1,5 +1,8 @@ <% content_for(:native_title, t('archived')) if turbo_native_app? %> <% filter_params = params.permit(Submissions::Filter::ALLOWED_PARAMS).compact_blank %> +<% if turbo_native_app? %> + +<% end %> <% with_filters = @pagy.pages > 1 || params[:q].present? || filter_params.present? %> <% unless turbo_native_app? %> <%= render 'templates/title', template: @template %> diff --git a/config/locales/i18n.yml b/config/locales/i18n.yml index 7c5fc4427..513b70320 100644 --- a/config/locales/i18n.yml +++ b/config/locales/i18n.yml @@ -483,6 +483,8 @@ en: &en document_templates_html: Templates archived: Archived search: Search + no_results: No Results + folders: Folders submissions_not_found: Submissions not Found create: Create view_archived: View Archived @@ -1624,6 +1626,8 @@ es: &es document_templates_html: Plantillas archived: Archivado search: Buscar + no_results: Sin resultados + folders: Carpetas submissions_not_found: Envíos no encontrados create: Crear view_archived: Ver Archivados @@ -2769,6 +2773,8 @@ it: &it document_templates_html: Modelli archived: Archiviato search: Cerca + no_results: Nessun risultato + folders: Cartelle submissions_not_found: Invii non trovati create: Crea view_archived: Visualizza Archiviati @@ -3900,6 +3906,8 @@ fr: &fr document_templates_html: Modèles archived: Archivé search: Rechercher + no_results: Aucun résultat + folders: Dossiers submissions_not_found: Soumissions introuvables create: Créer view_archived: Voir les archivés @@ -5041,6 +5049,8 @@ pt: &pt document_templates_html: Modelos archived: Arquivado search: Buscar + no_results: Sem resultados + folders: Pastas submissions_not_found: Submissões não encontradas create: Criar view_archived: Ver arquivados @@ -6185,6 +6195,8 @@ de: &de document_templates_html: Vorlagen archived: Archiviert search: Suchen + no_results: Keine Ergebnisse + folders: Ordner submissions_not_found: Einreichungen nicht gefunden create: Erstellen view_archived: Archivierte anzeigen @@ -7857,6 +7869,8 @@ nl: &nl document_templates_html: Sjablonen archived: Gearchiveerd search: Zoeken + no_results: Geen resultaten + folders: Mappen submissions_not_found: Geen inzendingen gevonden create: Aanmaken view_archived: Archief bekijken diff --git a/config/routes.rb b/config/routes.rb index a4c09d05c..234be4db1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -58,6 +58,7 @@ Rails.application.routes.draw do resources :encrypted_user_configs, only: %i[destroy] resources :timestamp_server, only: %i[create] unless Docuseal.multitenant? resources :dashboard, only: %i[index] + resources :search, only: %i[index] resources :setup, only: %i[index create] resource :newsletter, only: %i[show update] resources :enquiries, only: %i[create] diff --git a/lib/submissions/filter.rb b/lib/submissions/filter.rb index f338a877b..e9163db0d 100644 --- a/lib/submissions/filter.rb +++ b/lib/submissions/filter.rb @@ -5,6 +5,7 @@ module Submissions ALLOWED_PARAMS = %w[ author status + template_id folder completed_at_from completed_at_to @@ -27,6 +28,7 @@ module Submissions filters = normalize_filter_params(params, current_user) submissions = filter_by_author(submissions, filters, current_user) + submissions = filter_by_template(submissions, filters) submissions = filter_by_folder(submissions, filters, current_user) submissions = filter_by_status(submissions, filters) submissions = filter_by_created_at(submissions, filters) @@ -42,6 +44,12 @@ module Submissions submissions.where(created_by_user_id: user&.id || -1) end + def filter_by_template(submissions, filters) + return submissions if filters[:template_id].blank? + + submissions.where(template_id: filters[:template_id]) + end + def filter_by_status(submissions, filters) case filters[:status] when 'pending'