From c07ce374a8cf8490e7623874094c221bcbc0b690 Mon Sep 17 00:00:00 2001 From: clemkeirua Date: Mon, 27 Jul 2020 16:35:05 +0200 Subject: [PATCH 01/10] france connect avant les boutons de login/signup --- .../new_design/france-connect-login.scss | 37 +++++++++++++++++-- app/views/commencer/show.html.haml | 2 +- .../shared/_france_connect_login.html.haml | 8 +++- app/views/users/registrations/new.html.haml | 4 +- app/views/users/sessions/new.html.haml | 4 +- 5 files changed, 46 insertions(+), 9 deletions(-) diff --git a/app/assets/stylesheets/new_design/france-connect-login.scss b/app/assets/stylesheets/new_design/france-connect-login.scss index 779b800fc..f54289631 100644 --- a/app/assets/stylesheets/new_design/france-connect-login.scss +++ b/app/assets/stylesheets/new_design/france-connect-login.scss @@ -1,6 +1,15 @@ @import "colors"; +@import "constants"; .france-connect-login { + h2 { + color: $black; + font-size: 24px; + } +} + +.france-connect-login-buttons, +.france-connect-help-link { text-align: center; } @@ -22,7 +31,29 @@ } .france-connect-login-separator { - margin: 24px 0; - font-size: 14px; - color: $dark-grey; + display: flex; + flex-basis: 100%; + align-items: center; + color: $black; + text-transform: uppercase; + padding-bottom: $default-padding; + padding-top: $default-padding; + + &::before, + &::after { + content: ""; + flex-grow: 1; + background: $dark-grey; + height: 1px; + font-size: 0; + line-height: 0; + } + + &::before { + margin-right: $default-spacer; + } + + &::after { + margin-left: $default-spacer; + } } diff --git a/app/views/commencer/show.html.haml b/app/views/commencer/show.html.haml index 75e2b9470..c08c940ea 100644 --- a/app/views/commencer/show.html.haml +++ b/app/views/commencer/show.html.haml @@ -3,12 +3,12 @@ .commencer.form - if !user_signed_in? %h2.huge-title Commencer la démarche + = render partial: 'shared/france_connect_login', locals: { url: commencer_france_connect_path(path: @procedure.path) } = link_to commencer_sign_up_path(path: @procedure.path), class: ['button large expand primary'] do Créer un compte %span.optional-on-small-screens #{APPLICATION_NAME} = link_to 'J’ai déjà un compte', commencer_sign_in_path(path: @procedure.path), class: ['button large expand'] - = render partial: 'shared/france_connect_login', locals: { url: commencer_france_connect_path(path: @procedure.path) } - else - dossiers = current_user.dossiers.where(groupe_instructeur: @procedure.groupe_instructeurs) diff --git a/app/views/shared/_france_connect_login.html.haml b/app/views/shared/_france_connect_login.html.haml index 4bd33221c..0e752ceee 100644 --- a/app/views/shared/_france_connect_login.html.haml +++ b/app/views/shared/_france_connect_login.html.haml @@ -1,7 +1,11 @@ .france-connect-login - .france-connect-login-separator - ou + %h2 + Avec FranceConnect + %p + France connect est la solution proposée par l'État pour sécuriser et simplifier la connexion aux services en ligne. .france-connect-login-buttons = link_to "S’identifier avec FranceConnect", url, class: "france-connect-login-button" .france-connect-help-link = link_to "Qu’est-ce que FranceConnect ?", "https://franceconnect.gouv.fr/", target: "_blank", rel: "noopener", class: "link" + .france-connect-login-separator + ou diff --git a/app/views/users/registrations/new.html.haml b/app/views/users/registrations/new.html.haml index c7755ad54..ec7b91c30 100644 --- a/app/views/users/registrations/new.html.haml +++ b/app/views/users/registrations/new.html.haml @@ -5,6 +5,8 @@ = form_for resource, url: user_registration_path, html: { class: "form" } do |f| %h1 Créez-vous un compte #{APPLICATION_NAME} + = render partial: 'shared/france_connect_login', locals: { url: france_connect_particulier_path } + = f.label :email, "Email (nom@site.com)", id: :user_email_label = f.text_field :email, type: :email, autocomplete: 'email', autofocus: true, placeholder: "Votre adresse email", 'aria-describedby': :user_email_label @@ -24,4 +26,4 @@ = f.submit "Créer un compte", class: "button large primary expand" - = render partial: 'shared/france_connect_login', locals: { url: france_connect_particulier_path } + diff --git a/app/views/users/sessions/new.html.haml b/app/views/users/sessions/new.html.haml index a00021620..fe57eb71f 100644 --- a/app/views/users/sessions/new.html.haml +++ b/app/views/users/sessions/new.html.haml @@ -5,6 +5,8 @@ = form_for User.new, url: user_session_path, html: { class: "form" } do |f| %h1.huge-title Connectez-vous + = render partial: 'shared/france_connect_login', locals: { url: france_connect_particulier_path } + = f.label :email, "Email (nom@site.com)" = f.text_field :email, type: :email, autocomplete: 'username', autofocus: true @@ -21,8 +23,6 @@ = f.submit "Se connecter", class: "button large primary expand" - = render partial: 'shared/france_connect_login', locals: { url: france_connect_particulier_path } - %hr %p.center %span Vous êtes nouveau sur demarches‑simplifiees.fr ? From b8eea0516374e1c185332285127195bd1b9ce467 Mon Sep 17 00:00:00 2001 From: clemkeirua Date: Wed, 29 Jul 2020 09:27:16 +0200 Subject: [PATCH 02/10] ajout de traductions --- app/views/shared/_france_connect_login.html.haml | 10 +++++----- config/locales/views/shared/fr.yml | 6 ++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/views/shared/_france_connect_login.html.haml b/app/views/shared/_france_connect_login.html.haml index 0e752ceee..9f4a33646 100644 --- a/app/views/shared/_france_connect_login.html.haml +++ b/app/views/shared/_france_connect_login.html.haml @@ -1,11 +1,11 @@ .france-connect-login %h2 - Avec FranceConnect + = t('views.shared.france_connect_login.title') %p - France connect est la solution proposée par l'État pour sécuriser et simplifier la connexion aux services en ligne. + = t('views.shared.france_connect_login.description') .france-connect-login-buttons - = link_to "S’identifier avec FranceConnect", url, class: "france-connect-login-button" + = link_to t('views.shared.france_connect_login.login_button'), url, class: "france-connect-login-button" .france-connect-help-link - = link_to "Qu’est-ce que FranceConnect ?", "https://franceconnect.gouv.fr/", target: "_blank", rel: "noopener", class: "link" + = link_to t('views.shared.france_connect_login.help_link'), "https://franceconnect.gouv.fr/", target: "_blank", rel: "noopener", class: "link" .france-connect-login-separator - ou + = t('views.shared.france_connect_login.separator') diff --git a/config/locales/views/shared/fr.yml b/config/locales/views/shared/fr.yml index d1c7e15ea..963f7f1ba 100644 --- a/config/locales/views/shared/fr.yml +++ b/config/locales/views/shared/fr.yml @@ -9,3 +9,9 @@ fr: demande_revoquee_le: "Demande d'avis révoquée le %{date}" reponse_donnee_le: "Réponse donnée le %{date}" en_attente: "En attente de réponse" + france_connect_login: + title: 'Avec FranceConnect' + description: "France connect est la solution proposée par l’État pour sécuriser et simplifier la connexion aux services en ligne." + login_button: "S’identifier avec FranceConnect" + help_link: "Qu’est-ce que FranceConnect ?" + separator: 'ou' From 667b7d98763c6c46e1c14e883b38a7fce4726a5c Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Wed, 22 Jul 2020 15:52:39 +0200 Subject: [PATCH 03/10] add migration Co-authored-by: clemkeirua --- ...00722135121_add_dossiers_latest_updates_to_dossiers.rb | 8 ++++++++ db/schema.rb | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20200722135121_add_dossiers_latest_updates_to_dossiers.rb diff --git a/db/migrate/20200722135121_add_dossiers_latest_updates_to_dossiers.rb b/db/migrate/20200722135121_add_dossiers_latest_updates_to_dossiers.rb new file mode 100644 index 000000000..a857bd6ae --- /dev/null +++ b/db/migrate/20200722135121_add_dossiers_latest_updates_to_dossiers.rb @@ -0,0 +1,8 @@ +class AddDossiersLatestUpdatesToDossiers < ActiveRecord::Migration[6.0] + def change + add_column :dossiers, :last_champ_updated_at, :datetime + add_column :dossiers, :last_champ_private_updated_at, :datetime + add_column :dossiers, :last_avis_updated_at, :datetime + add_column :dossiers, :last_commentaire_updated_at, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index 040346832..733d1c852 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_07_15_143010) do +ActiveRecord::Schema.define(version: 2020_07_22_135121) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -260,6 +260,10 @@ ActiveRecord::Schema.define(version: 2020_07_15_143010) do t.bigint "revision_id" t.index "to_tsvector('french'::regconfig, (search_terms || private_search_terms))", name: "index_dossiers_on_search_terms_private_search_terms", using: :gin t.index "to_tsvector('french'::regconfig, search_terms)", name: "index_dossiers_on_search_terms", using: :gin + t.datetime "last_champ_updated_at" + t.datetime "last_champ_private_updated_at" + t.datetime "last_avis_updated_at" + t.datetime "last_commentaire_updated_at" t.index ["archived"], name: "index_dossiers_on_archived" t.index ["groupe_instructeur_id"], name: "index_dossiers_on_groupe_instructeur_id" t.index ["hidden_at"], name: "index_dossiers_on_hidden_at" From f3a675c3bcbfbe447277bb0356cccaea4231e00c Mon Sep 17 00:00:00 2001 From: clemkeirua Date: Wed, 22 Jul 2020 16:34:33 +0200 Subject: [PATCH 04/10] update dossier after saving commentaire update last_commentaire_updated_at without hook Co-authored-by: Christophe Robillard --- app/controllers/instructeurs/avis_controller.rb | 1 + app/controllers/instructeurs/dossiers_controller.rb | 1 + app/controllers/users/dossiers_controller.rb | 1 + spec/controllers/instructeurs/avis_controller_spec.rb | 5 +++++ spec/controllers/instructeurs/dossiers_controller_spec.rb | 5 +++++ spec/controllers/users/dossiers_controller_spec.rb | 5 +++++ 6 files changed, 18 insertions(+) diff --git a/app/controllers/instructeurs/avis_controller.rb b/app/controllers/instructeurs/avis_controller.rb index 933aa64a7..ba8997448 100644 --- a/app/controllers/instructeurs/avis_controller.rb +++ b/app/controllers/instructeurs/avis_controller.rb @@ -60,6 +60,7 @@ module Instructeurs @commentaire = CommentaireService.build(current_instructeur, avis.dossier, commentaire_params) if @commentaire.save + @commentaire.dossier.update!(last_commentaire_updated_at: Time.zone.now) flash.notice = "Message envoyé" redirect_to messagerie_instructeur_avis_path(avis.procedure, avis) else diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index 85b21678d..4ad0cbe88 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -169,6 +169,7 @@ module Instructeurs @commentaire = CommentaireService.build(current_instructeur, dossier, commentaire_params) if @commentaire.save + @commentaire.dossier.update!(last_commentaire_updated_at: Time.zone.now) current_instructeur.follow(dossier) flash.notice = "Message envoyé" redirect_to messagerie_instructeur_dossier_path(procedure, dossier) diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index 93a62ad67..0fe661950 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -198,6 +198,7 @@ module Users @commentaire = CommentaireService.build(current_user, dossier, commentaire_params) if @commentaire.save + @commentaire.dossier.update!(last_commentaire_updated_at: Time.zone.now) dossier.followers_instructeurs .with_instant_email_message_notifications .each do |instructeur| diff --git a/spec/controllers/instructeurs/avis_controller_spec.rb b/spec/controllers/instructeurs/avis_controller_spec.rb index 1d805df7d..b220573cc 100644 --- a/spec/controllers/instructeurs/avis_controller_spec.rb +++ b/spec/controllers/instructeurs/avis_controller_spec.rb @@ -117,18 +117,23 @@ describe Instructeurs::AvisController, type: :controller do describe '#create_commentaire' do let(:file) { nil } let(:scan_result) { true } + let(:now) { Time.zone.parse("14/07/1789") } subject { post :create_commentaire, params: { id: avis_without_answer.id, procedure_id: procedure.id, commentaire: { body: 'commentaire body', piece_jointe: file } } } before do allow(ClamavService).to receive(:safe_file?).and_return(scan_result) + Timecop.freeze(now) end + after { Timecop.return } + it do subject expect(response).to redirect_to(messagerie_instructeur_avis_path(avis_without_answer.procedure, avis_without_answer)) expect(dossier.commentaires.map(&:body)).to match(['commentaire body']) + expect(dossier.reload.last_commentaire_updated_at).to eq(now) end context "with a file" do diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index ec2d68386..28e8e4798 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -390,6 +390,7 @@ describe Instructeurs::DossiersController, type: :controller do let(:body) { "avant\napres" } let(:file) { fixture_file_upload('spec/fixtures/files/piece_justificative_0.pdf', 'application/pdf') } let(:scan_result) { true } + let(:now) { Timecop.freeze("09/11/1989") } subject { post :create_commentaire, params: { @@ -404,14 +405,18 @@ describe Instructeurs::DossiersController, type: :controller do before do allow(ClamavService).to receive(:safe_file?).and_return(scan_result) + Timecop.freeze(now) end + after { Timecop.return } + it "creates a commentaire" do expect { subject }.to change(Commentaire, :count).by(1) expect(instructeur.followed_dossiers).to include(dossier) expect(response).to redirect_to(messagerie_instructeur_dossier_path(dossier.procedure, dossier)) expect(flash.notice).to be_present + expect(dossier.reload.last_commentaire_updated_at).to eq(now) end context "when the commentaire created with virus file" do diff --git a/spec/controllers/users/dossiers_controller_spec.rb b/spec/controllers/users/dossiers_controller_spec.rb index 9dd0cdfd5..b7a949643 100644 --- a/spec/controllers/users/dossiers_controller_spec.rb +++ b/spec/controllers/users/dossiers_controller_spec.rb @@ -802,6 +802,7 @@ describe Users::DossiersController, type: :controller do let(:body) { "avant\napres" } let(:file) { fixture_file_upload('spec/fixtures/files/piece_justificative_0.pdf', 'application/pdf') } let(:scan_result) { true } + let(:now) { Time.zone.parse("18/09/1981") } subject { post :create_commentaire, params: { @@ -814,6 +815,7 @@ describe Users::DossiersController, type: :controller do } before do + Timecop.freeze(now) sign_in(user) allow(ClamavService).to receive(:safe_file?).and_return(scan_result) allow(DossierMailer).to receive(:notify_new_commentaire_to_instructeur).and_return(double(deliver_later: nil)) @@ -823,6 +825,8 @@ describe Users::DossiersController, type: :controller do create(:assign_to, instructeur: instructeur_without_instant_message, procedure: procedure, instant_email_message_notifications_enabled: false, groupe_instructeur: procedure.defaut_groupe_instructeur) end + after { Timecop.return } + it "creates a commentaire" do expect { subject }.to change(Commentaire, :count).by(1) @@ -830,6 +834,7 @@ describe Users::DossiersController, type: :controller do expect(DossierMailer).to have_received(:notify_new_commentaire_to_instructeur).with(dossier, instructeur_with_instant_message.email) expect(DossierMailer).not_to have_received(:notify_new_commentaire_to_instructeur).with(dossier, instructeur_without_instant_message.email) expect(flash.notice).to be_present + expect(dossier.reload.last_commentaire_updated_at).to eq(now) end end From b940d2e1b083973817fb0d5054b7bf95caaab561 Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Wed, 22 Jul 2020 16:57:00 +0200 Subject: [PATCH 05/10] update dossier after saving avis update last_avis_updated_at without hook Co-authored-by: clemkeirua --- app/controllers/concerns/create_avis_concern.rb | 1 + app/controllers/instructeurs/avis_controller.rb | 1 + .../controllers/instructeurs/avis_controller_spec.rb | 12 ++++++++++-- .../instructeurs/dossiers_controller_spec.rb | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/app/controllers/concerns/create_avis_concern.rb b/app/controllers/concerns/create_avis_concern.rb index ecc0d412a..a88c2768b 100644 --- a/app/controllers/concerns/create_avis_concern.rb +++ b/app/controllers/concerns/create_avis_concern.rb @@ -35,6 +35,7 @@ module CreateAvisConcern persisted, failed = create_results.partition(&:persisted?) if persisted.any? + dossier.update!(last_avis_updated_at: Time.zone.now) sent_emails_addresses = [] persisted.each do |avis| avis.dossier.demander_un_avis!(avis) diff --git a/app/controllers/instructeurs/avis_controller.rb b/app/controllers/instructeurs/avis_controller.rb index ba8997448..0b392fa13 100644 --- a/app/controllers/instructeurs/avis_controller.rb +++ b/app/controllers/instructeurs/avis_controller.rb @@ -44,6 +44,7 @@ module Instructeurs def update if @avis.update(avis_params) flash.notice = 'Votre réponse est enregistrée.' + @avis.dossier.update!(last_avis_updated_at: Time.zone.now) redirect_to instruction_instructeur_avis_path(@avis.procedure, @avis) else flash.now.alert = @avis.errors.full_messages diff --git a/spec/controllers/instructeurs/avis_controller_spec.rb b/spec/controllers/instructeurs/avis_controller_spec.rb index b220573cc..497ac2e56 100644 --- a/spec/controllers/instructeurs/avis_controller_spec.rb +++ b/spec/controllers/instructeurs/avis_controller_spec.rb @@ -2,6 +2,7 @@ describe Instructeurs::AvisController, type: :controller do context 'with a instructeur signed in' do render_views + let(:now) { Time.zone.parse('01/02/2345') } let(:claimant) { create(:instructeur) } let(:instructeur) { create(:instructeur) } let(:procedure) { create(:procedure, :published, instructeurs: [claimant]) } @@ -79,21 +80,24 @@ describe Instructeurs::AvisController, type: :controller do end describe '#update' do - describe 'without attachment' do + context 'without attachment' do before do + Timecop.freeze(now) patch :update, params: { id: avis_without_answer.id, procedure_id: procedure.id, avis: { answer: 'answer' } } avis_without_answer.reload end + after { Timecop.return } it 'should be ok' do expect(response).to redirect_to(instruction_instructeur_avis_path(avis_without_answer.procedure, avis_without_answer)) expect(avis_without_answer.answer).to eq('answer') expect(avis_without_answer.piece_justificative_file).to_not be_attached + expect(dossier.reload.last_avis_updated_at).to eq(now) expect(flash.notice).to eq('Votre réponse est enregistrée.') end end - describe 'with attachment' do + context 'with attachment' do include ActiveJob::TestHelper let(:file) { fixture_file_upload('spec/fixtures/files/piece_justificative_0.pdf', 'application/pdf') } @@ -157,10 +161,12 @@ describe Instructeurs::AvisController, type: :controller do let(:invite_linked_dossiers) { nil } before do + Timecop.freeze(now) @introduction_file = fixture_file_upload('spec/fixtures/files/piece_justificative_0.pdf', 'application/pdf') post :create_avis, params: { id: previous_avis.id, procedure_id: procedure.id, avis: { emails: emails, introduction: intro, confidentiel: asked_confidentiel, invite_linked_dossiers: invite_linked_dossiers, introduction_file: @introduction_file } } created_avis.reload end + after { Timecop.return } context 'when an invalid email' do let(:previous_avis_confidentiel) { false } @@ -170,6 +176,7 @@ describe Instructeurs::AvisController, type: :controller do it { expect(response).to render_template :instruction } it { expect(flash.alert).to eq(["toto.fr : Email n'est pas valide"]) } it { expect(Avis.last).to eq(previous_avis) } + it { expect(dossier.last_avis_updated_at).to eq(nil) } end context 'ask review with attachment' do @@ -179,6 +186,7 @@ describe Instructeurs::AvisController, type: :controller do it { expect(created_avis.introduction_file).to be_attached } it { expect(created_avis.introduction_file.filename).to eq("piece_justificative_0.pdf") } + it { expect(created_avis.dossier.reload.last_avis_updated_at).to eq(now) } it { expect(flash.notice).to eq("Une demande d'avis a été envoyée à toto@totomail.com") } end diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index 28e8e4798..5550518b1 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -464,6 +464,7 @@ describe Instructeurs::DossiersController, type: :controller do it { expect(response).to render_template :avis } it { expect(flash.alert).to eq(["emaila.com : Email n'est pas valide"]) } it { expect { subject }.not_to change(Avis, :count) } + it { expect(dossier.last_avis_updated_at).to eq(nil) } end context 'with multiple emails' do From c772c3454cfb365e1fb517aea44e414c2de489c6 Mon Sep 17 00:00:00 2001 From: clemkeirua Date: Wed, 22 Jul 2020 17:11:33 +0200 Subject: [PATCH 06/10] update dossier after saving champ update last_champ_updated_at without hook update last_champ_private_updated_at without hook Co-authored-by: Christophe Robillard --- .../instructeurs/dossiers_controller.rb | 6 +- app/controllers/users/dossiers_controller.rb | 6 +- .../instructeurs/dossiers_controller_spec.rb | 61 ++++++++++++++----- .../users/dossiers_controller_spec.rb | 17 ++++++ 4 files changed, 74 insertions(+), 16 deletions(-) diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index 4ad0cbe88..f03f6e1ac 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -192,7 +192,11 @@ module Instructeurs def update_annotations dossier = current_instructeur.dossiers.includes(champs_private: :type_de_champ).find(params[:dossier_id]) - dossier.update(champs_private_params) + dossier.assign_attributes(champs_private_params) + if dossier.champs_private.any?(&:changed?) + dossier.last_champ_private_updated_at = Time.zone.now + end + dossier.save dossier.modifier_annotations!(current_instructeur) redirect_to annotations_privees_instructeur_dossier_path(procedure, dossier) end diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index 0fe661950..4d65e3e05 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -345,7 +345,11 @@ module Users errors = [] if champs_params[:dossier] - if !@dossier.update(champs_params[:dossier]) + @dossier.assign_attributes(champs_params[:dossier]) + if @dossier.champs.any?(&:changed?) + @dossier.last_champ_updated_at = Time.zone.now + end + if !@dossier.save errors += @dossier.errors.full_messages elsif change_groupe_instructeur? groupe_instructeur = @dossier.procedure.groupe_instructeurs.find(params[:dossier][:groupe_instructeur_id]) diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index 5550518b1..2213f501b 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -584,9 +584,26 @@ describe Instructeurs::DossiersController, type: :controller do create(:dossier, :en_construction, procedure: procedure, champs_private: [champ_multiple_drop_down_list, champ_linked_drop_down_list, champ_datetime, champ_repetition]) end + let(:now) { Time.zone.parse('01/01/2100') } + before do - patch :update_annotations, params: { - procedure_id: procedure.id, + Timecop.freeze(now) + patch :update_annotations, params: params + + champ_multiple_drop_down_list.reload + champ_linked_drop_down_list.reload + champ_datetime.reload + champ_repetition.reload + end + + after do + Timecop.return + end + + context "with new values for champs_private" do + let(:params) do + { + procedure_id: procedure.id, dossier_id: dossier.id, dossier: { champs_private_attributes: { @@ -616,20 +633,36 @@ describe Instructeurs::DossiersController, type: :controller do } } } - } - - champ_multiple_drop_down_list.reload - champ_linked_drop_down_list.reload - champ_datetime.reload - champ_repetition.reload + } + end + it { expect(champ_multiple_drop_down_list.value).to eq('["un", "deux"]') } + it { expect(champ_linked_drop_down_list.primary_value).to eq('primary') } + it { expect(champ_linked_drop_down_list.secondary_value).to eq('secondary') } + it { expect(champ_datetime.value).to eq('21/12/2019 13:17') } + it { expect(champ_repetition.champs.first.value).to eq('text') } + it { expect(dossier.reload.last_champ_private_updated_at).to eq(now) } + it { expect(response).to redirect_to(annotations_privees_instructeur_dossier_path(dossier.procedure, dossier)) } end - it { expect(champ_multiple_drop_down_list.value).to eq('["un", "deux"]') } - it { expect(champ_linked_drop_down_list.primary_value).to eq('primary') } - it { expect(champ_linked_drop_down_list.secondary_value).to eq('secondary') } - it { expect(champ_datetime.value).to eq('21/12/2019 13:17') } - it { expect(champ_repetition.champs.first.value).to eq('text') } - it { expect(response).to redirect_to(annotations_privees_instructeur_dossier_path(dossier.procedure, dossier)) } + context "without new values for champs_private" do + let(:params) do + { + procedure_id: procedure.id, + dossier_id: dossier.id, + dossier: { + champs_private_attributes: {}, + champs_attributes: { + '0': { + id: champ_multiple_drop_down_list.id, + value: ['', 'un', 'deux'] + } + } + } + } + end + it { expect(dossier.reload.last_champ_private_updated_at).to eq(nil) } + it { expect(response).to redirect_to(annotations_privees_instructeur_dossier_path(dossier.procedure, dossier)) } + end end describe "#telecharger_pjs" do diff --git a/spec/controllers/users/dossiers_controller_spec.rb b/spec/controllers/users/dossiers_controller_spec.rb index b7a949643..29d8fbeb7 100644 --- a/spec/controllers/users/dossiers_controller_spec.rb +++ b/spec/controllers/users/dossiers_controller_spec.rb @@ -378,6 +378,22 @@ describe Users::DossiersController, type: :controller do expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction)) end + context 'without new values for champs' do + let(:submit_payload) do + { + id: dossier.id, + dossier: { + champs_attributes: {} + } + } + end + + it "doesn't set last_champ_updated_at" do + subject + expect(dossier.reload.last_champ_updated_at).to eq(nil) + end + end + context 'with instructeurs ok to be notified instantly' do let!(:instructeur_with_instant_email_dossier) { create(:instructeur) } let!(:instructeur_without_instant_email_dossier) { create(:instructeur) } @@ -576,6 +592,7 @@ describe Users::DossiersController, type: :controller do it 'updates the champs' do subject expect(first_champ.reload.value).to eq('beautiful value') + expect(first_champ.dossier.reload.last_champ_updated_at).to eq(now) expect(piece_justificative_champ.reload.piece_justificative_file).to be_attached end From 03e3e8fb1c0bfcedebf89a3c41558369f62fa676 Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Tue, 28 Jul 2020 14:22:56 +0200 Subject: [PATCH 07/10] rename Dossier#modifier_annotations! give a more accurate name to the method Co-authored-by: clemkeirua --- app/controllers/instructeurs/dossiers_controller.rb | 2 +- app/models/dossier.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index f03f6e1ac..7f24aafe4 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -197,7 +197,7 @@ module Instructeurs dossier.last_champ_private_updated_at = Time.zone.now end dossier.save - dossier.modifier_annotations!(current_instructeur) + dossier.log_modifier_annotations!(current_instructeur) redirect_to annotations_privees_instructeur_dossier_path(procedure, dossier) end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 1317c26ab..b51801936 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -615,7 +615,7 @@ class Dossier < ApplicationRecord end end - def modifier_annotations!(instructeur) + def log_modifier_annotations!(instructeur) champs_private.filter(&:value_previously_changed?).each do |champ| log_dossier_operation(instructeur, :modifier_annotation, champ) end From 153c6aebd7c7a89fbd68ee7315f1db90d9389e43 Mon Sep 17 00:00:00 2001 From: clemkeirua Date: Tue, 28 Jul 2020 17:15:43 +0200 Subject: [PATCH 08/10] add temp job to set last_updated_at_* values for dossier Co-authored-by: Christophe Robillard --- .../tmp_set_dossiers_last_updated_at_job.rb | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 app/jobs/tmp_set_dossiers_last_updated_at_job.rb diff --git a/app/jobs/tmp_set_dossiers_last_updated_at_job.rb b/app/jobs/tmp_set_dossiers_last_updated_at_job.rb new file mode 100644 index 000000000..ca0b69997 --- /dev/null +++ b/app/jobs/tmp_set_dossiers_last_updated_at_job.rb @@ -0,0 +1,27 @@ +class TmpSetDossiersLastUpdatedAtJob < ApplicationJob + def perform(except) + dossiers = Dossier.where + .not(id: except) + .where(last_champ_updated_at: nil) + .includes(:champs, :avis, :commentaires) + .limit(100) + + dossiers.find_each do |dossier| + last_commentaire_updated_at = dossier.commentaires.maximum(:updated_at) + last_avis_updated_at = dossier.avis.maximum(:updated_at) + last_champ_updated_at = dossier.champs.maximum(:updated_at) + last_champ_private_updated_at = dossier.champs_private.maximum(:updated_at) + dossier.update_columns( + last_commentaire_updated_at: last_commentaire_updated_at, + last_avis_updated_at: last_avis_updated_at, + last_champ_updated_at: last_champ_updated_at, + last_champ_private_updated_at: last_champ_private_updated_at + ) + except << dossier.id + end + + if dossiers.where.not(id: except).exists? + TmpSetDossiersLastUpdatedAtJob.perform_later(except) + end + end +end From 952a43058fbcb6ddb0261617d6cb6fcecd9dde70 Mon Sep 17 00:00:00 2001 From: clemkeirua Date: Thu, 30 Jul 2020 11:16:21 +0200 Subject: [PATCH 09/10] last_commentaire_updated_at does not take system email into account --- app/jobs/tmp_set_dossiers_last_updated_at_job.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/jobs/tmp_set_dossiers_last_updated_at_job.rb b/app/jobs/tmp_set_dossiers_last_updated_at_job.rb index ca0b69997..80c15e043 100644 --- a/app/jobs/tmp_set_dossiers_last_updated_at_job.rb +++ b/app/jobs/tmp_set_dossiers_last_updated_at_job.rb @@ -7,7 +7,10 @@ class TmpSetDossiersLastUpdatedAtJob < ApplicationJob .limit(100) dossiers.find_each do |dossier| - last_commentaire_updated_at = dossier.commentaires.maximum(:updated_at) + last_commentaire_updated_at = dossier.commentaires + .where.not(email: OLD_CONTACT_EMAIL) + .where.not(email: CONTACT_EMAIL) + .maximum(:updated_at) last_avis_updated_at = dossier.avis.maximum(:updated_at) last_champ_updated_at = dossier.champs.maximum(:updated_at) last_champ_private_updated_at = dossier.champs_private.maximum(:updated_at) From db3e40ebf885a687607624873f04afaf878f40b9 Mon Sep 17 00:00:00 2001 From: kara Diaby Date: Thu, 30 Jul 2020 11:33:53 +0200 Subject: [PATCH 10/10] =?UTF-8?q?Fixe=20la=20non=20possibilit=C3=A9=20de?= =?UTF-8?q?=20cloner=20une=20d=C3=A9marche=20pour=20une=20proc=C3=A9dure?= =?UTF-8?q?=20archiv=C3=A9e=20(nouvelle=20interface=20administrateur)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../procedures/_procedures_list.html.haml | 35 ++++++++++--------- .../procedures/index.html.haml | 2 +- db/schema.rb | 4 +-- .../features/admin/procedure_creation_spec.rb | 6 ++-- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/app/views/new_administrateur/procedures/_procedures_list.html.haml b/app/views/new_administrateur/procedures/_procedures_list.html.haml index cfbfaad03..8923f657e 100644 --- a/app/views/new_administrateur/procedures/_procedures_list.html.haml +++ b/app/views/new_administrateur/procedures/_procedures_list.html.haml @@ -44,27 +44,28 @@ %span.icon.in-progress .dropdown-description %h4 Tester + + %li + = link_to admin_procedure_clone_path(procedure.id), class: 'clone-btn', data: { method: :put } do + %span.icon.new-folder + .dropdown-description + %h4 Cloner + + - if procedure.publiee? %li - = link_to admin_procedure_clone_path(procedure.id), class: 'clone-btn', data: { method: :put } do - %span.icon.new-folder + = link_to admin_procedure_archive_path(procedure_id: procedure.id), method: :put, data: { confirm: "Voulez-vous vraiment clore la démarche ? \nLes dossiers en cours pourront être instruits, mais aucun nouveau dossier ne pourra plus être déposé.", disable_with: "Archivage..."} do + %span.icon.archive .dropdown-description - %h4 Cloner + %h4 Clore - - if procedure.publiee? - %li - = link_to admin_procedure_archive_path(procedure_id: procedure.id), method: :put, data: { confirm: "Voulez-vous vraiment clore la démarche ? \nLes dossiers en cours pourront être instruits, mais aucun nouveau dossier ne pourra plus être déposé.", disable_with: "Archivage..."} do - %span.icon.archive - .dropdown-description - %h4 Clore + - if procedure.brouillon? + %li + = link_to admin_procedure_path(procedure), method: :delete, data: { confirm: "Voulez-vous vraiment supprimer la démarche ? \nToute suppression est définitive et s'appliquera aux éventuels autres administrateurs de cette démarche !" } do + %span.icon.refuse + .dropdown-description + %h4 Supprimer - - if procedure.brouillon? - %li - = link_to admin_procedure_path(procedure), method: :delete, data: { confirm: "Voulez-vous vraiment supprimer la démarche ? \nToute suppression est définitive et s'appliquera aux éventuels autres administrateurs de cette démarche !" } do - %span.icon.refuse - .dropdown-description - %h4 Supprimer - - - else + - if procedure.close? %li = link_to admin_procedure_publication_path(procedure) do %span.icon.unarchive diff --git a/app/views/new_administrateur/procedures/index.html.haml b/app/views/new_administrateur/procedures/index.html.haml index 0f68be127..2a30ee766 100644 --- a/app/views/new_administrateur/procedures/index.html.haml +++ b/app/views/new_administrateur/procedures/index.html.haml @@ -1,6 +1,6 @@ .sub-header .procedure-admin-listing-container - = link_to "Nouvelle Démarche", new_admin_procedure_path, id: 'new-procedure', class: 'button primary' + = link_to "Nouvelle Démarche", new_from_existing_admin_procedures_path, id: 'new-procedure', class: 'button primary' .container %ul.tabs diff --git a/db/schema.rb b/db/schema.rb index 733d1c852..92ca3e485 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -258,12 +258,12 @@ ActiveRecord::Schema.define(version: 2020_07_22_135121) do t.interval "en_construction_conservation_extension", default: "PT0S" t.datetime "termine_close_to_expiration_notice_sent_at" t.bigint "revision_id" - t.index "to_tsvector('french'::regconfig, (search_terms || private_search_terms))", name: "index_dossiers_on_search_terms_private_search_terms", using: :gin - t.index "to_tsvector('french'::regconfig, search_terms)", name: "index_dossiers_on_search_terms", using: :gin t.datetime "last_champ_updated_at" t.datetime "last_champ_private_updated_at" t.datetime "last_avis_updated_at" t.datetime "last_commentaire_updated_at" + t.index "to_tsvector('french'::regconfig, (search_terms || private_search_terms))", name: "index_dossiers_on_search_terms_private_search_terms", using: :gin + t.index "to_tsvector('french'::regconfig, search_terms)", name: "index_dossiers_on_search_terms", using: :gin t.index ["archived"], name: "index_dossiers_on_archived" t.index ["groupe_instructeur_id"], name: "index_dossiers_on_groupe_instructeur_id" t.index ["hidden_at"], name: "index_dossiers_on_hidden_at" diff --git a/spec/features/admin/procedure_creation_spec.rb b/spec/features/admin/procedure_creation_spec.rb index a2b2f0faa..943aa622d 100644 --- a/spec/features/admin/procedure_creation_spec.rb +++ b/spec/features/admin/procedure_creation_spec.rb @@ -33,7 +33,8 @@ feature 'As an administrateur I wanna create a new procedure', js: true do expect(page).to have_selector('#new-procedure') find('#new-procedure').click - expect(page).to have_current_path(new_admin_procedure_path) + expect(page).to have_current_path(new_from_existing_admin_procedures_path) + click_on 'Créer une nouvelle démarche de zéro' expect(find('#procedure_for_individual_true')).to be_checked expect(find('#procedure_for_individual_false')).not_to be_checked fill_in 'procedure_duree_conservation_dossiers_dans_ds', with: '3' @@ -54,7 +55,8 @@ feature 'As an administrateur I wanna create a new procedure', js: true do expect(page).to have_selector('#new-procedure') find('#new-procedure').click - expect(page).to have_current_path(new_admin_procedure_path) + expect(page).to have_current_path(new_from_existing_admin_procedures_path) + click_on 'Créer une nouvelle démarche de zéro' fill_in_dummy_procedure_details click_on 'Créer la démarche'