diff --git a/app/components/dossiers/batch_alert_component.rb b/app/components/dossiers/batch_alert_component.rb new file mode 100644 index 000000000..e52ee87e2 --- /dev/null +++ b/app/components/dossiers/batch_alert_component.rb @@ -0,0 +1,8 @@ +class Dossiers::BatchAlertComponent < ApplicationComponent + attr_reader :batch + + def initialize(batch:, procedure:) + @batch = batch + @procedure = procedure + end +end diff --git a/app/components/dossiers/batch_alert_component/batch_alert_component.en.yml b/app/components/dossiers/batch_alert_component/batch_alert_component.en.yml new file mode 100644 index 000000000..8d384fd29 --- /dev/null +++ b/app/components/dossiers/batch_alert_component/batch_alert_component.en.yml @@ -0,0 +1,20 @@ +en: + finish: + title: The bulk action is finished + text_success: + one: 1 file has been archived + other: "%{count} files have been archived" + text_fail: + one: 1 file has not been archived + other: "%{count} have not been archived" + in_progress: + title: A bulk action is processing + text_beginning: "0/ %{count} file archived" + text_success: + one: 1 file has been archived + other: "%{count} files have been archived" + text_fail: + one: 1 file has not been archived + other: "%{count} have not been archived" + link_text: Refresh this webpage + after_link_text: to check if the process is over. diff --git a/app/components/dossiers/batch_alert_component/batch_alert_component.fr.yml b/app/components/dossiers/batch_alert_component/batch_alert_component.fr.yml new file mode 100644 index 000000000..4e4528f13 --- /dev/null +++ b/app/components/dossiers/batch_alert_component/batch_alert_component.fr.yml @@ -0,0 +1,20 @@ +fr: + finish: + title: L'action de masse est terminée + text_success: + one: 1 dossier a été archivé + other: "%{count} dossiers ont été archivés" + text_fail: + one: 1 dossier n'a pas été archivé + other: "%{count} dossiers n'ont pas été archivés" + in_progress: + title: Une action de masse est en cours + text_beginning: "0/ %{count} dossier archivé" + text_success: + one: 1 dossier a été archivé + other: "%{count} dossiers ont été archivés" + text_fail: + one: 1 dossier n'a pas été archivé + other: "%{count} dossiers n'ont pas été archivés" + link_text: Recharger la page + after_link_text: pour voir si l'opération est finie. diff --git a/app/components/dossiers/batch_alert_component/batch_alert_component.html.haml b/app/components/dossiers/batch_alert_component/batch_alert_component.html.haml new file mode 100644 index 000000000..c698247d0 --- /dev/null +++ b/app/components/dossiers/batch_alert_component/batch_alert_component.html.haml @@ -0,0 +1,38 @@ +.fr-mb-5v + - if @batch.finished_and_success? + = render Dsfr::AlertComponent.new(title: t('.finish.title'), state: :success) do |c| + - c.body do + %p + = t('.finish.text_success', count: @batch.success_dossier_ids.count) + + - if @batch.finished_and_fails? + = render Dsfr::AlertComponent.new(title: t('.finish.title'), state: :warning) do |c| + - c.body do + %p + = t('.finish.text_fail', count: @batch.failed_dossier_ids.count) + + - if @batch.beginning? + = render Dsfr::AlertComponent.new(title: t('.in_progress.title'), state: :info) do |c| + - c.body do + %p + = t('.in_progress.text_beginning', count: @batch.dossiers.count) + + %p + = link_to t('.link_text'), instructeur_procedure_path(@procedure, statut: params["statut"]), data: { action: 'turbo-poll#refresh' } + = t('.after_link_text') + + - if @batch.in_progress? + = render Dsfr::AlertComponent.new(title: t('.in_progress.title'), state: :info) do |c| + - c.body do + + - if @batch.failed_dossier_ids.present? + %p + = t('.in_progress.text_fail', count: @batch.failed_dossier_ids.count) + + - if @batch.success_dossier_ids.present? + %p + = t('.in_progress.text_success', count: @batch.success_dossier_ids.count) + + %p + = link_to t('.link_text'), instructeur_procedure_path(@procedure, statut: params["statut"]), data: { action: 'turbo-poll#refresh' } + = t('.after_link_text') diff --git a/app/controllers/instructeurs/procedures_controller.rb b/app/controllers/instructeurs/procedures_controller.rb index 90fd54944..16ff8717a 100644 --- a/app/controllers/instructeurs/procedures_controller.rb +++ b/app/controllers/instructeurs/procedures_controller.rb @@ -90,6 +90,18 @@ module Instructeurs @projected_dossiers = DossierProjectionService.project(@filtered_sorted_paginated_ids, procedure_presentation.displayed_fields) assign_exports + + # Set procedure_batchs to display alerts in view + # TO DO // récupérer les batchs du groupe d'instructeurs au lieu de l'instructeur + return if current_instructeur.batch_operations.blank? + # extraire un dossier de chaque batch pour voir quel procedure est rattaché -> et les ajouter à un tableau + @procedure_batchs = [] + current_instructeur.batch_operations.each do |batch| + random_batch_dossier_id = (batch.failed_dossier_ids + batch.success_dossier_ids + batch.dossiers.ids).sample + if Dossier.find(random_batch_dossier_id).procedure.id == @procedure.id + @procedure_batchs << batch + end + end end def deleted_dossiers diff --git a/app/models/batch_operation.rb b/app/models/batch_operation.rb index 0a5068ade..c644b1e8c 100644 --- a/app/models/batch_operation.rb +++ b/app/models/batch_operation.rb @@ -78,7 +78,7 @@ class BatchOperation < ApplicationRecord transaction do instance = new(params) instance.dossiers = instance.dossiers_safe_scope(params[:dossier_ids]) - .not_having_batch_operation + .not_having_batch_operation instance.save! BatchOperationEnqueueAllJob.perform_later(instance) instance @@ -94,6 +94,22 @@ class BatchOperation < ApplicationRecord dossiers.count.zero? end + def finished_and_success? + called_for_last_time? && failed_dossier_ids.empty? + end + + def finished_and_fails? + called_for_last_time? && failed_dossier_ids.present? + end + + def in_progress? + !called_for_last_time? && (failed_dossier_ids + success_dossier_ids).present? + end + + def beginning? + !called_for_last_time? && (failed_dossier_ids + success_dossier_ids).empty? + end + private def arel_table diff --git a/app/views/instructeurs/procedures/show.html.haml b/app/views/instructeurs/procedures/show.html.haml index 914fa4a21..91de40501 100644 --- a/app/views/instructeurs/procedures/show.html.haml +++ b/app/views/instructeurs/procedures/show.html.haml @@ -71,6 +71,10 @@ %div{ data: { controller: 'batch-operation' } } - batch_operation_component = Dossiers::BatchOperationComponent.new(statut: @statut, procedure: @procedure) + - if @procedure_batchs.present? + - @procedure_batchs.each do |batch| + = render Dossiers::BatchAlertComponent.new(batch: batch, procedure: @procedure) + .flex .flex-grow= render batch_operation_component .fr-table.fr-table--bordered @@ -116,8 +120,7 @@ %td.folder-col - if batch_operation_component.render? - if p.batch_operation_id.present? - %span.cell-link - %span.fr-icon-lock-line{ aria_hidden: "true" } + = check_box_tag :"batch_operation[dossier_ids][]", p.dossier_id, true, disabled: true - else = check_box_tag :"batch_operation[dossier_ids][]", p.dossier_id, false, data: { "batch-operation-target" => "input", "action" => "batch-operation#onCheckOne"}, form: dom_id(BatchOperation.new) - else diff --git a/spec/components/dossiers/batch_alert_component_spec.rb b/spec/components/dossiers/batch_alert_component_spec.rb new file mode 100644 index 000000000..ed579e0aa --- /dev/null +++ b/spec/components/dossiers/batch_alert_component_spec.rb @@ -0,0 +1,55 @@ +RSpec.describe Dossiers::BatchAlertComponent, type: :component do + let(:component) do + described_class.new( + batch: batch_operation, + procedure: procedure + ) + end + let(:instructeur) { create(:instructeur) } + let(:procedure) { create(:procedure) } + let!(:dossier) { create(:dossier, :accepte, procedure: procedure) } + let!(:dossier_2) { create(:dossier, :accepte, procedure: procedure) } + let!(:batch_operation) { create(:batch_operation, operation: :archiver, dossiers: [dossier, dossier_2], instructeur: instructeur) } + + subject { render_inline(component).to_html } + + context 'beginning' do + it { is_expected.to have_selector('.fr-alert--info') } + it { is_expected.to have_text("Une action de masse est en cours") } + it { is_expected.to have_text("0/ 2 dossier archivé") } + end + + context 'in_progress' do + before { + batch_operation.track_processed_dossier(true, dossier) + batch_operation.reload + } + it { is_expected.to have_selector('.fr-alert--info') } + it { is_expected.to have_text("Une action de masse est en cours") } + it { is_expected.to have_text("1 dossier a été archivé") } + end + + context 'finished and success' do + before { + batch_operation.track_processed_dossier(true, dossier) + batch_operation.track_processed_dossier(true, dossier_2) + batch_operation.reload + } + + it { is_expected.to have_selector('.fr-alert--success') } + it { is_expected.to have_text("L'action de masse est terminée") } + it { is_expected.to have_text("2 dossiers ont été archivés") } + end + + context 'finished and fail' do + before { + batch_operation.track_processed_dossier(false, dossier) + batch_operation.track_processed_dossier(true, dossier_2) + batch_operation.reload + } + + it { is_expected.to have_selector('.fr-alert--warning') } + it { is_expected.to have_text("L'action de masse est terminée") } + it { is_expected.to have_text("1 dossier n'a pas été archivé") } + end +end diff --git a/spec/controllers/instructeurs/procedures_controller_spec.rb b/spec/controllers/instructeurs/procedures_controller_spec.rb index cb39bd9f2..1244a7c1e 100644 --- a/spec/controllers/instructeurs/procedures_controller_spec.rb +++ b/spec/controllers/instructeurs/procedures_controller_spec.rb @@ -341,6 +341,24 @@ describe Instructeurs::ProceduresController, type: :controller do it { expect(assigns(:filtered_sorted_paginated_ids)).to match_array([termine_dossier, termine_dossier_on_gi_2].map(&:id)) } end + + context 'with batch operations' do + let!(:batch_operation) { create(:batch_operation, operation: :archiver, dossiers: [termine_dossier], instructeur: instructeur) } + let!(:termine_dossier_2) { create(:dossier, :accepte, procedure: procedure) } + let!(:batch_operation_2) { create(:batch_operation, operation: :archiver, dossiers: [termine_dossier_2], instructeur: instructeur) } + + before { subject } + + it { expect(assigns(:procedure_batchs)).to match_array([batch_operation, batch_operation_2]) } + end + + context 'with a batch operation not attached to the instructeur' do + let(:instructeur_2) { create(:instructeur) } + let!(:batch_operation) { create(:batch_operation, operation: :archiver, dossiers: [termine_dossier], instructeur: instructeur_2) } + before { subject } + + it { expect(assigns(:procedure_batchs)).to eq(nil) } + end end context 'with an archived dossier' do