From 15d06f4fb04573296541e1444da7cd9e7ff3640c Mon Sep 17 00:00:00 2001 From: Pete Matsyburka Date: Fri, 13 Dec 2024 19:45:37 +0200 Subject: [PATCH] add status filters --- .../submissions_dashboard_controller.rb | 3 - .../submissions_filters_controller.rb | 1 + app/controllers/templates_controller.rb | 5 +- app/models/submission.rb | 2 + app/views/icons/_clock_cancel.html.erb | 3 + app/views/icons/_clock_edit.html.erb | 3 + .../_applied_filters.html.erb | 35 ++++++---- .../_filter_button.html.erb | 10 ++- .../_filter_modal.html.erb | 3 +- app/views/submissions_filters/status.html.erb | 17 +++++ config/locales/i18n.yml | 11 ++++ lib/submissions/filter.rb | 64 +++++++++++++++---- 12 files changed, 122 insertions(+), 35 deletions(-) create mode 100644 app/views/icons/_clock_cancel.html.erb create mode 100644 app/views/icons/_clock_edit.html.erb create mode 100644 app/views/submissions_filters/status.html.erb diff --git a/app/controllers/submissions_dashboard_controller.rb b/app/controllers/submissions_dashboard_controller.rb index f71e10b5..3403d22c 100644 --- a/app/controllers/submissions_dashboard_controller.rb +++ b/app/controllers/submissions_dashboard_controller.rb @@ -15,9 +15,6 @@ class SubmissionsDashboardController < ApplicationController @submissions = Submissions.search(@submissions, params[:q], search_template: true) @submissions = Submissions::Filter.call(@submissions, current_user, params) - @submissions = @submissions.pending if params[:status] == 'pending' - @submissions = @submissions.completed if params[:status] == 'completed' - @submissions = if params[:completed_at_from].present? || params[:completed_at_to].present? @submissions.order(Submitter.arel_table[:completed_at].maximum.desc) else diff --git a/app/controllers/submissions_filters_controller.rb b/app/controllers/submissions_filters_controller.rb index bd5eae1e..b0298d4c 100644 --- a/app/controllers/submissions_filters_controller.rb +++ b/app/controllers/submissions_filters_controller.rb @@ -4,6 +4,7 @@ class SubmissionsFiltersController < ApplicationController ALLOWED_NAMES = %w[ author completed_at + status created_at ].freeze diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb index b11812ab..c023a5e7 100644 --- a/app/controllers/templates_controller.rb +++ b/app/controllers/templates_controller.rb @@ -9,12 +9,11 @@ class TemplatesController < ApplicationController submissions = @template.submissions.accessible_by(current_ability) submissions = submissions.active if @template.archived_at.blank? submissions = Submissions.search(submissions, params[:q], search_values: true) - submissions = Submissions::Filter.call(submissions, current_user, params) + submissions = Submissions::Filter.call(submissions, current_user, params.except(:status)) @base_submissions = submissions - submissions = submissions.pending if params[:status] == 'pending' - submissions = submissions.completed if params[:status] == 'completed' + submissions = Submissions::Filter.filter_by_status(submissions, params) submissions = if params[:completed_at_from].present? || params[:completed_at_to].present? submissions.order(Submitter.arel_table[:completed_at].maximum.desc) diff --git a/app/models/submission.rb b/app/models/submission.rb index 8567aaa1..c0f1c92c 100644 --- a/app/models/submission.rb +++ b/app/models/submission.rb @@ -69,6 +69,8 @@ class Submission < ApplicationRecord where.not(Submitter.where(Submitter.arel_table[:submission_id].eq(Submission.arel_table[:id]) .and(Submitter.arel_table[:completed_at].eq(nil))).select(1).arel.exists) } + scope :declined, -> { joins(:submitters).where.not(submitters: { declined_at: nil }).group(:id) } + scope :expired, -> { where(expire_at: ..Time.current) } enum :source, { invite: 'invite', diff --git a/app/views/icons/_clock_cancel.html.erb b/app/views/icons/_clock_cancel.html.erb new file mode 100644 index 00000000..d114f04a --- /dev/null +++ b/app/views/icons/_clock_cancel.html.erb @@ -0,0 +1,3 @@ + + + diff --git a/app/views/icons/_clock_edit.html.erb b/app/views/icons/_clock_edit.html.erb new file mode 100644 index 00000000..ccd629d2 --- /dev/null +++ b/app/views/icons/_clock_edit.html.erb @@ -0,0 +1,3 @@ + + + diff --git a/app/views/submissions_filters/_applied_filters.html.erb b/app/views/submissions_filters/_applied_filters.html.erb index ad988d71..f1cdb070 100644 --- a/app/views/submissions_filters/_applied_filters.html.erb +++ b/app/views/submissions_filters/_applied_filters.html.erb @@ -1,4 +1,26 @@ -<% query_params = params.permit(:q, :status).merge(filter_params) %> +<% query_params = params.permit(:q).merge(filter_params) %> +<% if icon = { 'declined' => 'x_circle', 'expired' => 'clock_cancel', 'partially_completed' => 'clock_edit' }[params[:status]] %> +
+ <%= link_to submissions_filter_path('status', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 w-full pr-1 md:max-w-[140px]' do %> + <%= svg_icon(icon, class: 'w-5 h-5 shrink-0') %> + <%= t(params[:status]) %> + <% end %> + <%= link_to url_for(params.to_unsafe_h.except(:status)), class: 'rounded-lg ml-1 hover:bg-base-content hover:text-white' do %> + <%= svg_icon('x', class: 'w-5 h-5') %> + <% end %> +
+<% end %> +<% if params[:author].present? %> +
+ <%= link_to submissions_filter_path('author', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 w-full pr-1 md:max-w-[140px]' do %> + <%= svg_icon('user', class: 'w-5 h-5 shrink-0') %> + <%= current_account.users.accessible_by(current_ability).where(account: current_account).find_by(email: params[:author])&.full_name || 'NA' %> + <% end %> + <%= link_to url_for(params.to_unsafe_h.except(:author)), class: 'rounded-lg ml-1 hover:bg-base-content hover:text-white' do %> + <%= svg_icon('x', class: 'w-5 h-5') %> + <% end %> +
+<% end %> <% if query_params[:completed_at_from].present? || query_params[:completed_at_to].present? %>
<%= link_to submissions_filter_path('completed_at', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 w-full pr-1 md:max-w-[140px]' do %> @@ -37,14 +59,3 @@ <% end %>
<% end %> -<% if params[:author].present? %> -
- <%= link_to submissions_filter_path('author', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 w-full pr-1 md:max-w-[140px]' do %> - <%= svg_icon('user', class: 'w-5 h-5 shrink-0') %> - <%= current_account.users.accessible_by(current_ability).where(account: current_account).find_by(email: params[:author])&.full_name || 'NA' %> - <% end %> - <%= link_to url_for(params.to_unsafe_h.except(:author)), class: 'rounded-lg ml-1 hover:bg-base-content hover:text-white' do %> - <%= svg_icon('x', class: 'w-5 h-5') %> - <% end %> -
-<% end %> diff --git a/app/views/submissions_filters/_filter_button.html.erb b/app/views/submissions_filters/_filter_button.html.erb index b840729d..3f24aaf6 100644 --- a/app/views/submissions_filters/_filter_button.html.erb +++ b/app/views/submissions_filters/_filter_button.html.erb @@ -1,8 +1,8 @@ -<% query_params = params.permit(:q, :status).merge(filter_params) %> +<% query_params = params.permit(:q).merge(filter_params) %> <% if params[:with_remove] %>
- <%= link_to t('remove_filter'), "#{params[:path]}?#{params.to_unsafe_h.slice(:q, :status).merge(local_assigns[:default_params]).to_query}", class: 'link', data: { turbo_frame: :_top } %> + <%= link_to t('remove_filter'), "#{params[:path]}?#{params.to_unsafe_h.slice(:q).merge(local_assigns[:default_params]).to_query}", class: 'link', data: { turbo_frame: :_top } %>
<% end %> <% end %> diff --git a/app/views/submissions_filters/status.html.erb b/app/views/submissions_filters/status.html.erb new file mode 100644 index 00000000..72541571 --- /dev/null +++ b/app/views/submissions_filters/status.html.erb @@ -0,0 +1,17 @@ +<%= render 'filter_modal', title: t('status'), default_params: params.permit(*(Submissions::Filter::ALLOWED_PARAMS - %w[status])) do %> +
+
+
+ <%= label_tag 'status', t('status'), class: 'label text-sm' %> +
+ <% ['', 'pending', 'completed', 'declined', 'expired', 'partially_completed'].each do |status| %> + + <% end %> +
+
+
+
+<% end %> diff --git a/config/locales/i18n.yml b/config/locales/i18n.yml index 3e142f59..92ee1d8e 100644 --- a/config/locales/i18n.yml +++ b/config/locales/i18n.yml @@ -20,6 +20,8 @@ en: &en language_ko: 한국어 hi_there: Hi there thanks: Thanks + pending_by_me: Pending by me + partially_completed: Partially completed unarchive: Unarchive first_party: 'First Party' remove_filter: Remove filter @@ -699,6 +701,8 @@ en: &en read: Read your data es: &es + partially_completed: Parcialmente completado + pending_by_me: Pendiente por mi add: Agregar adding: Agregando owner: Propietario @@ -1380,6 +1384,7 @@ es: &es read: Leer tus datos it: &it + pending_by_me: In sospeso da me add: Aggiungi adding: Aggiungendo owner: Proprietario @@ -2061,6 +2066,8 @@ it: &it read: Leggi i tuoi dati fr: &fr + partially_completed: Partiellement complété + pending_by_me: En attente par moi add: Ajouter adding: Ajout owner: Propriétaire @@ -2743,6 +2750,8 @@ fr: &fr read: Lire vos données pt: &pt + partially_completed: Parcialmente concluído + pending_by_me: Pendente por mim add: Adicionar adding: Adicionando owner: Proprietário @@ -3424,6 +3433,8 @@ pt: &pt read: Ler seus dados de: &de + partially_completed: Teilweise abgeschlossen + pending_by_me: Ausstehend von mir add: Hinzufügen adding: Hinzufügen owner: Eigentümer diff --git a/lib/submissions/filter.rb b/lib/submissions/filter.rb index f4a2271a..11d40a17 100644 --- a/lib/submissions/filter.rb +++ b/lib/submissions/filter.rb @@ -4,6 +4,7 @@ module Submissions module Filter ALLOWED_PARAMS = %w[ author + status completed_at_from completed_at_to created_at_from @@ -22,31 +23,68 @@ module Submissions def call(submissions, current_user, params) filters = normalize_filter_params(params, current_user) - if filters[:author].present? - user = current_user.account.users.find_by(email: filters[:author]) - submissions = submissions.where(created_by_user_id: user&.id || -1) + submissions = filter_by_author(submissions, filters, current_user) + submissions = filter_by_status(submissions, filters) + submissions = filter_by_created_at(submissions, filters) + + filter_by_completed_at(submissions, filters) + end + + def filter_by_author(submissions, filters, current_user) + return submissions if filters[:author].blank? + + user = current_user.account.users.find_by(email: filters[:author]) + submissions.where(created_by_user_id: user&.id || -1) + end + + def filter_by_status(submissions, filters) + submissions = submissions.pending if filters[:status] == 'pending' + submissions = submissions.completed if filters[:status] == 'completed' + submissions = submissions.declined if filters[:status] == 'declined' + submissions = submissions.expired if filters[:status] == 'expired' + + if filters[:status] == 'partially_completed' + submissions = + submissions.joins(:submitters) + .group(:id) + .having(Arel::Nodes::NamedFunction.new( + 'COUNT', [Arel::Nodes::NamedFunction.new('NULLIF', + [Submitter.arel_table[:completed_at].eq(nil), + Arel::Nodes.build_quoted(false)])] + ).gt(0)) + .having(Arel::Nodes::NamedFunction.new( + 'COUNT', [Arel::Nodes::NamedFunction.new('NULLIF', + [Submitter.arel_table[:completed_at].not_eq(nil), + Arel::Nodes.build_quoted(false)])] + ).gt(0)) end + submissions + end + + def filter_by_created_at(submissions, filters) submissions = submissions.where(created_at: filters[:created_at_from]..) if filters[:created_at_from].present? if filters[:created_at_to].present? submissions = submissions.where(created_at: ..filters[:created_at_to].end_of_day) end - if filters[:completed_at_from].present? || filters[:completed_at_to].present? - completed_arel = Submitter.arel_table[:completed_at].maximum - submissions = submissions.completed.joins(:submitters).group(:id) + submissions + end - if filters[:completed_at_from].present? - submissions = submissions.having(completed_arel.gteq(filters[:completed_at_from])) - end + def filter_by_completed_at(submissions, filters) + return submissions unless filters[:completed_at_from].present? || filters[:completed_at_to].present? - if filters[:completed_at_to].present? - submissions = submissions.having(completed_arel.lteq(filters[:completed_at_to].end_of_day)) - end + completed_arel = Submitter.arel_table[:completed_at].maximum + submissions = submissions.completed.joins(:submitters).group(:id) + + if filters[:completed_at_from].present? + submissions = submissions.having(completed_arel.gteq(filters[:completed_at_from])) end - submissions + return submissions if filters[:completed_at_to].blank? + + submissions.having(completed_arel.lteq(filters[:completed_at_to].end_of_day)) end def normalize_filter_params(params, current_user)