Merge pull request #5034 from betagouv/dev

2020-04-09-04
This commit is contained in:
Pierre de La Morinerie 2020-04-09 17:59:43 +02:00 committed by GitHub
commit 2550dce8b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 142 additions and 47 deletions

View file

@ -254,7 +254,8 @@ module Instructeurs
private private
def assign_to_params def assign_to_params
params.require(:assign_to).permit(:instant_email_message_notifications_enabled, :daily_email_notifications_enabled, :weekly_email_notifications_enabled) params.require(:assign_to)
.permit(:instant_email_dossier_notifications_enabled, :instant_email_message_notifications_enabled, :daily_email_notifications_enabled, :weekly_email_notifications_enabled)
end end
def assign_exports def assign_exports

View file

@ -153,6 +153,9 @@ module Users
if passage_en_construction? && errors.blank? if passage_en_construction? && errors.blank?
@dossier.en_construction! @dossier.en_construction!
NotificationMailer.send_initiated_notification(@dossier).deliver_later NotificationMailer.send_initiated_notification(@dossier).deliver_later
@dossier.procedure.instructeurs.with_instant_email_dossier_notifications.each do |instructeur|
DossierMailer.notify_new_dossier_depose_to_instructeur(@dossier, instructeur.email).deliver_later
end
return redirect_to(merci_dossier_path(@dossier)) return redirect_to(merci_dossier_path(@dossier))
elsif errors.present? elsif errors.present?
flash.now.alert = errors flash.now.alert = errors

View file

@ -0,0 +1,22 @@
// Convert an error message returned by DirectUpload to a proper error object.
//
// This function has two goals:
// 1. Remove the file name from the DirectUpload error message
// (because the filename confuses Sentry error grouping)
// 2. Create each kind of error on a different line
// (so that Sentry knows they are different kind of errors, from
// the line they were created.)
export default function errorFromDirectUploadMessage(message) {
let matches = message.match(/ Status: [0-9]{1,3}/);
let status = (matches && matches[0]) || '';
if (message.includes('Error creating')) {
return new Error('Error creating file.' + status);
} else if (message.includes('Error storing')) {
return new Error('Error storing file.' + status);
} else if (message.includes('Error reading')) {
return new Error('Error reading file.' + status);
} else {
return new Error(message);
}
}

View file

@ -1,4 +1,5 @@
import ProgressBar from './progress-bar'; import ProgressBar from './progress-bar';
import errorFromDirectUploadMessage from './errors';
import { fire } from '@utils'; import { fire } from '@utils';
const INITIALIZE_EVENT = 'direct-upload:initialize'; const INITIALIZE_EVENT = 'direct-upload:initialize';
@ -40,17 +41,22 @@ addUploadEventListener(PROGRESS_EVENT, ({ detail: { id, progress } }) => {
}); });
addUploadEventListener(ERROR_EVENT, event => { addUploadEventListener(ERROR_EVENT, event => {
let id = event.detail.id;
let errorMsg = event.detail.error;
// Display an error message // Display an error message
alert( alert(
`Nous sommes désolés, une erreur sest produite lors de lenvoi du fichier. `Nous sommes désolés, une erreur sest produite lors de lenvoi du fichier.
(${event.detail.error})` (${errorMsg})`
); );
// Prevent ActiveStorage from displaying its own error message // Prevent ActiveStorage from displaying its own error message
event.preventDefault(); event.preventDefault();
ProgressBar.error(event.detail.id, event.detail.error); ProgressBar.error(id, errorMsg);
fire(document, 'sentry:capture-exception', new Error(event.detail.error));
let error = errorFromDirectUploadMessage(errorMsg);
fire(document, 'sentry:capture-exception', error);
}); });
addUploadEventListener(END_EVENT, ({ detail: { id } }) => { addUploadEventListener(END_EVENT, ({ detail: { id } }) => {

View file

@ -1,5 +1,6 @@
import { DirectUpload } from '@rails/activestorage'; import { DirectUpload } from '@rails/activestorage';
import ProgressBar from './progress-bar'; import ProgressBar from './progress-bar';
import errorFromDirectUploadMessage from './errors';
/** /**
Uploader class is a delegate for DirectUpload instance Uploader class is a delegate for DirectUpload instance
@ -18,7 +19,8 @@ export default class Uploader {
this.directUpload.create((errorMsg, attributes) => { this.directUpload.create((errorMsg, attributes) => {
if (errorMsg) { if (errorMsg) {
this.progressBar.error(errorMsg); this.progressBar.error(errorMsg);
reject(new Error(errorMsg)); let error = errorFromDirectUploadMessage(errorMsg);
reject(error);
} else { } else {
resolve(attributes.signed_id); resolve(attributes.signed_id);
} }

View file

@ -35,6 +35,12 @@ class DossierMailer < ApplicationMailer
mail(from: NO_REPLY_EMAIL, to: instructeur_email, subject: @subject) mail(from: NO_REPLY_EMAIL, to: instructeur_email, subject: @subject)
end end
def notify_new_dossier_depose_to_instructeur(dossier, instructeur_email)
@dossier = dossier
@subject = default_i18n_subject(dossier_id: dossier.id, libelle_demarche: dossier.procedure.libelle)
mail(from: NO_REPLY_EMAIL, to: instructeur_email, subject: @subject)
end
def notify_revert_to_instruction(dossier) def notify_revert_to_instruction(dossier)
@dossier = dossier @dossier = dossier
@service = dossier.procedure.service @service = dossier.procedure.service

View file

@ -23,6 +23,10 @@ class Instructeur < ApplicationRecord
includes(:assign_to).where(assign_tos: { instant_email_message_notifications_enabled: true }) includes(:assign_to).where(assign_tos: { instant_email_message_notifications_enabled: true })
} }
scope :with_instant_email_dossier_notifications, -> {
includes(:assign_to).where(assign_tos: { instant_email_dossier_notifications_enabled: true })
}
default_scope { eager_load(:user) } default_scope { eager_load(:user) }
def self.by_email(email) def self.by_email(email)

View file

@ -26,6 +26,7 @@ class Procedure < ApplicationRecord
has_many :administrateurs_procedures has_many :administrateurs_procedures
has_many :administrateurs, through: :administrateurs_procedures, after_remove: -> (procedure, _admin) { procedure.validate! } has_many :administrateurs, through: :administrateurs_procedures, after_remove: -> (procedure, _admin) { procedure.validate! }
has_many :groupe_instructeurs, dependent: :destroy has_many :groupe_instructeurs, dependent: :destroy
has_many :instructeurs, through: :groupe_instructeurs
has_many :dossiers, through: :groupe_instructeurs, dependent: :restrict_with_exception has_many :dossiers, through: :groupe_instructeurs, dependent: :restrict_with_exception

View file

@ -0,0 +1,10 @@
- content_for(:title, "#{@subject}")
%p
Bonjour,
%p
= t('.body', dossier_id: @dossier.id, libelle_demarche: @dossier.procedure.libelle)
%p= link_to("Consulter le dossier n°#{@dossier.id}", instructeur_dossier_url(procedure_id: @dossier.procedure.id, dossier_id: @dossier.id))
= render partial: "layouts/mailers/signature"

View file

@ -11,6 +11,22 @@
.explication .explication
Configurez sur cette page les notifications que vous souhaitez recevoir par email pour cette démarche. Configurez sur cette page les notifications que vous souhaitez recevoir par email pour cette démarche.
= form.label :email_notification, "Recevoir une notification à chaque dossier déposé"
%p.notice
Cet email vous signale le dépôt d'un nouveau dossier.
%p.notice
Il est envoyé à chaque fois qu'un usager dépose un dossier.
.radios
%label
= form.radio_button :instant_email_dossier_notifications_enabled, true
Oui
%label
= form.radio_button :instant_email_dossier_notifications_enabled, false
Non
= form.label :email_notification, "Recevoir une notification à chaque message déposé" = form.label :email_notification, "Recevoir une notification à chaque message déposé"
%p.notice %p.notice

View file

@ -0,0 +1,5 @@
fr:
dossier_mailer:
notify_new_dossier_depose_to_instructeur:
subject: Nouveau dossier déposé pour la démarche %{libelle_demarche}
body: Un nouveau dossier a été déposé (n° %{dossier_id}) pour la démarche %{libelle_demarche}

View file

@ -0,0 +1,5 @@
class AddInstantEmailDossierNotificationsToAssignTos < ActiveRecord::Migration[5.2]
def change
add_column :assign_tos, :instant_email_dossier_notifications_enabled, :boolean, default: false, null: false
end
end

View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2020_04_07_135256) do ActiveRecord::Schema.define(version: 2020_04_09_075320) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -104,6 +104,7 @@ ActiveRecord::Schema.define(version: 2020_04_07_135256) do
t.boolean "weekly_email_notifications_enabled", default: true, null: false t.boolean "weekly_email_notifications_enabled", default: true, null: false
t.boolean "daily_email_notifications_enabled", default: false, null: false t.boolean "daily_email_notifications_enabled", default: false, null: false
t.boolean "instant_email_message_notifications_enabled", default: false, null: false t.boolean "instant_email_message_notifications_enabled", default: false, null: false
t.boolean "instant_email_dossier_notifications_enabled", default: false, null: false
t.index ["groupe_instructeur_id", "instructeur_id"], name: "unique_couple_groupe_instructeur_instructeur", unique: true t.index ["groupe_instructeur_id", "instructeur_id"], name: "unique_couple_groupe_instructeur_instructeur", unique: true
t.index ["groupe_instructeur_id"], name: "index_assign_tos_on_groupe_instructeur_id" t.index ["groupe_instructeur_id"], name: "index_assign_tos_on_groupe_instructeur_id"
t.index ["instructeur_id", "procedure_id"], name: "index_assign_tos_on_instructeur_id_and_procedure_id", unique: true t.index ["instructeur_id", "procedure_id"], name: "index_assign_tos_on_instructeur_id_and_procedure_id", unique: true

View file

@ -421,6 +421,24 @@ describe Users::DossiersController, type: :controller do
expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction)) expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction))
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) }
before do
allow(DossierMailer).to receive(:notify_new_dossier_depose_to_instructeur).and_return(double(deliver_later: nil))
create(:assign_to, instructeur: instructeur_with_instant_email_dossier, procedure: dossier.procedure, instant_email_dossier_notifications_enabled: true, groupe_instructeur: dossier.procedure.defaut_groupe_instructeur)
create(:assign_to, instructeur: instructeur_without_instant_email_dossier, procedure: dossier.procedure, instant_email_dossier_notifications_enabled: false, groupe_instructeur: dossier.procedure.defaut_groupe_instructeur)
end
it "sends notification mail to instructeurs" do
subject
expect(DossierMailer).to have_received(:notify_new_dossier_depose_to_instructeur).once.with(dossier, instructeur_with_instant_email_dossier.email)
expect(DossierMailer).not_to have_received(:notify_new_dossier_depose_to_instructeur).with(dossier, instructeur_without_instant_email_dossier.email)
end
end
context "on an closed procedure" do context "on an closed procedure" do
before { dossier.procedure.close! } before { dossier.procedure.close! }

View file

@ -1087,55 +1087,55 @@
webpack-sources "^1.4.3" webpack-sources "^1.4.3"
"@sentry/browser@^5.11.2": "@sentry/browser@^5.11.2":
version "5.11.2" version "5.15.4"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.11.2.tgz#f0b19bd97e9f09a20e9f93a9835339ed9ab1f5a4" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.15.4.tgz#5a7e7bad088556665ed8e69bceb0e18784e4f6c7"
integrity sha512-ls6ARX5m+23ld8OsuoPnR+kehjR5ketYWRcDYlmJDX2VOq5K4EzprujAo8waDB0o5a92yLXQ0ZSoK/zzAV2VoA== integrity sha512-l/auT1HtZM3KxjCGQHYO/K51ygnlcuOrM+7Ga8gUUbU9ZXDYw6jRi0+Af9aqXKmdDw1naNxr7OCSy6NBrLWVZw==
dependencies: dependencies:
"@sentry/core" "5.11.2" "@sentry/core" "5.15.4"
"@sentry/types" "5.11.0" "@sentry/types" "5.15.4"
"@sentry/utils" "5.11.1" "@sentry/utils" "5.15.4"
tslib "^1.9.3" tslib "^1.9.3"
"@sentry/core@5.11.2": "@sentry/core@5.15.4":
version "5.11.2" version "5.15.4"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.11.2.tgz#f2d9d37940d291dbcb9a9e4a012f76919474bdf6" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.15.4.tgz#08b617e093a636168be5aebad141d1f744217085"
integrity sha512-IFCXGy7ebqIq/Kb8RVryCo/SjwhPcrfBmOjkicr4+DxN1UybLre2N3p9bejQMPIteOfDVHlySLYeipjTf+mxZw== integrity sha512-9KP4NM4SqfV5NixpvAymC7Nvp36Zj4dU2fowmxiq7OIbzTxGXDhwuN/t0Uh8xiqlkpkQqSECZ1OjSFXrBldetQ==
dependencies: dependencies:
"@sentry/hub" "5.11.2" "@sentry/hub" "5.15.4"
"@sentry/minimal" "5.11.2" "@sentry/minimal" "5.15.4"
"@sentry/types" "5.11.0" "@sentry/types" "5.15.4"
"@sentry/utils" "5.11.1" "@sentry/utils" "5.15.4"
tslib "^1.9.3" tslib "^1.9.3"
"@sentry/hub@5.11.2": "@sentry/hub@5.15.4":
version "5.11.2" version "5.15.4"
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.11.2.tgz#a3b7ec27cd4cea2cddd75c372fbf1b4bc04c6aae" resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.15.4.tgz#cb64473725a60eec63b0be58ed1143eaaf894bee"
integrity sha512-5BiDin6ZPsaiTm29rCC41MAjP1vOaKniqfjtXHVPm7FeOBA2bpHm95ncjLkshKGJTPfPZHXTpX/1IZsHrfGVEA== integrity sha512-1XJ1SVqadkbUT4zLS0TVIVl99si7oHizLmghR8LMFl5wOkGEgehHSoOydQkIAX2C7sJmaF5TZ47ORBHgkqclUg==
dependencies: dependencies:
"@sentry/types" "5.11.0" "@sentry/types" "5.15.4"
"@sentry/utils" "5.11.1" "@sentry/utils" "5.15.4"
tslib "^1.9.3" tslib "^1.9.3"
"@sentry/minimal@5.11.2": "@sentry/minimal@5.15.4":
version "5.11.2" version "5.15.4"
resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.11.2.tgz#ae417699342266ecd109a97e53cd9519c0893b21" resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.15.4.tgz#113f01fefb86b7830994c3dfa7ad4889ba7b2003"
integrity sha512-oNuJuz3EZhVtamzABmPdr6lcYo06XHLWb2LvgnoNaYcMD1ExUSvhepOSyZ2h5STCMbmVgGVfXBNPV9RUTp8GZg== integrity sha512-GL4GZ3drS9ge+wmxkHBAMEwulaE7DMvAEfKQPDAjg2p3MfcCMhAYfuY4jJByAC9rg9OwBGGehz7UmhWMFjE0tw==
dependencies: dependencies:
"@sentry/hub" "5.11.2" "@sentry/hub" "5.15.4"
"@sentry/types" "5.11.0" "@sentry/types" "5.15.4"
tslib "^1.9.3" tslib "^1.9.3"
"@sentry/types@5.11.0": "@sentry/types@5.15.4":
version "5.11.0" version "5.15.4"
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.11.0.tgz#40f0f3174362928e033ddd9725d55e7c5cb7c5b6" resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.15.4.tgz#37f30e35b06e8e12ad1101f1beec3e9b88ca1aab"
integrity sha512-1Uhycpmeo1ZK2GLvrtwZhTwIodJHcyIS6bn+t4IMkN9MFoo6ktbAfhvexBDW/IDtdLlCGJbfm8nIZerxy0QUpg== integrity sha512-quPHPpeAuwID48HLPmqBiyXE3xEiZLZ5D3CEbU3c3YuvvAg8qmfOOTI6z4Z3Eedi7flvYpnx3n7N3dXIEz30Eg==
"@sentry/utils@5.11.1": "@sentry/utils@5.15.4":
version "5.11.1" version "5.15.4"
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.11.1.tgz#aa19fcc234cf632257b2281261651d2fac967607" resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.15.4.tgz#02865ab3c9b745656cea0ab183767ec26c96f6e6"
integrity sha512-O0Zl4R2JJh8cTkQ8ZL2cDqGCmQdpA5VeXpuBbEl1v78LQPkBDISi35wH4mKmLwMsLBtTVpx2UeUHBj0KO5aLlA== integrity sha512-lO8SLBjrUDGADl0LOkd55R5oL510d/1SaI08/IBHZCxCUwI4TiYo5EPECq8mrj3XGfgCyq9osw33bymRlIDuSQ==
dependencies: dependencies:
"@sentry/types" "5.11.0" "@sentry/types" "5.15.4"
tslib "^1.9.3" tslib "^1.9.3"
"@turf/area@^6.0.1": "@turf/area@^6.0.1":
@ -9105,16 +9105,11 @@ ts-pnp@^1.1.6:
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
tslib@^1.9.0: tslib@^1.9.0, tslib@^1.9.3:
version "1.11.1" version "1.11.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"
integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==
tslib@^1.9.3:
version "1.9.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==
tty-browserify@0.0.0: tty-browserify@0.0.0:
version "0.0.0" version "0.0.0"
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"