invite: add button for invite someone to collaborate on a draft
This commit is contained in:
parent
9541e781bb
commit
1cac0b80af
10 changed files with 239 additions and 6 deletions
|
@ -316,6 +316,15 @@
|
|||
}
|
||||
}
|
||||
|
||||
.send-notice {
|
||||
@include notice-text-style;
|
||||
margin-bottom: $default-padding;
|
||||
}
|
||||
|
||||
.send-wrapper + .send-notice {
|
||||
margin-top: - $default-padding;
|
||||
}
|
||||
|
||||
.inline-champ {
|
||||
margin-left: $default-spacer;
|
||||
margin-right: $default-spacer;
|
||||
|
|
35
app/assets/stylesheets/new_design/invites_form.scss
Normal file
35
app/assets/stylesheets/new_design/invites_form.scss
Normal file
|
@ -0,0 +1,35 @@
|
|||
@import "constants";
|
||||
|
||||
#invites-form {
|
||||
padding: $default-padding;
|
||||
text-align: left;
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
margin-top: $default-padding;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-weight: bold;
|
||||
margin-bottom: $default-spacer;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: $default-spacer;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-position: inside;
|
||||
list-style-type: disc;
|
||||
margin-bottom: $default-padding;
|
||||
}
|
||||
|
||||
input[type=email] {
|
||||
width: auto;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.button {
|
||||
margin-left: $default-spacer;
|
||||
}
|
||||
}
|
|
@ -3,9 +3,10 @@ class InvitesController < ApplicationController
|
|||
|
||||
def create
|
||||
email = params[:invite_email].downcase
|
||||
dossier = current_user.dossiers.find(params[:dossier_id])
|
||||
|
||||
invite = InviteUser.create(
|
||||
dossier: current_user.dossiers.find(params[:dossier_id]),
|
||||
dossier: dossier,
|
||||
user: User.find_by(email: email),
|
||||
email: email,
|
||||
email_sender: current_user.email
|
||||
|
@ -18,12 +19,12 @@ class InvitesController < ApplicationController
|
|||
InviteMailer.invite_guest(invite).deliver_later
|
||||
end
|
||||
|
||||
flash.notice = "Invitation envoyée (#{invite.email})"
|
||||
flash.notice = "Une invitation a été envoyée à #{invite.email}."
|
||||
else
|
||||
flash.alert = invite.errors.full_messages
|
||||
end
|
||||
|
||||
redirect_to url_for(controller: 'users/recapitulatif', action: :show, dossier_id: params['dossier_id'])
|
||||
redirect_back(fallback_location: helpers.url_for_dossier(dossier))
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -9,7 +9,11 @@ class Users::Dossiers::InvitesController < UsersController
|
|||
def show
|
||||
@facade = InviteDossierFacades.new params[:id].to_i, current_user.email
|
||||
|
||||
render 'users/recapitulatif/show'
|
||||
if @facade.dossier.brouillon?
|
||||
redirect_to modifier_dossier_path(@facade.dossier)
|
||||
else
|
||||
render 'users/recapitulatif/show'
|
||||
end
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
flash.alert = t('errors.messages.dossier_not_found')
|
||||
redirect_to url_for dossiers_path
|
||||
|
|
17
app/views/invites/_form.html.haml
Normal file
17
app/views/invites/_form.html.haml
Normal file
|
@ -0,0 +1,17 @@
|
|||
#invites-form
|
||||
- if dossier.invites.present?
|
||||
%h4 Personnes invitées à participer à ce dossier
|
||||
%ul
|
||||
- dossier.invites.each do |invite|
|
||||
%li= invite.email
|
||||
%p Ces personnes peuvent modifier ce dossier.
|
||||
- if dossier.brouillon?
|
||||
%p Une fois le dossier complet, vous devez le soumettre vous-même.
|
||||
|
||||
- else
|
||||
%p Vous pouvez inviter quelqu’un à remplir ce dossier avec vous.
|
||||
%p Cette personne aura le droit de modifier votre dossier.
|
||||
|
||||
= form_tag invites_dossier_path(dossier_id: dossier.id), method: :post, class: 'form' do
|
||||
= email_field_tag :invite_email, '', class: 'small', placeholder: 'adresse email', required: true
|
||||
= submit_tag 'Envoyer une invitation', class: 'button accepted'
|
|
@ -74,9 +74,10 @@
|
|||
class: 'button send secondary',
|
||||
data: { action: 'draft', disable_with: 'Envoi...' }
|
||||
|
||||
- if current_user.owns?(dossier) && dossier.can_transition_to_en_construction?
|
||||
- if dossier.can_transition_to_en_construction?
|
||||
= f.button 'Soumettre le dossier',
|
||||
class: 'button send primary',
|
||||
disabled: !current_user.owns?(dossier),
|
||||
data: { action: 'submit', disable_with: 'Envoi...' }
|
||||
|
||||
- else
|
||||
|
@ -84,4 +85,8 @@
|
|||
class: 'button send primary',
|
||||
data: { action: 'submit', disable_with: 'Envoi...' }
|
||||
|
||||
- if dossier.brouillon? && !current_user.owns?(dossier)
|
||||
.send-notice.invite-cannot-submit
|
||||
En tant qu’invité, vous pouvez remplir ce formulaire – mais le titulaire du dossier doit le soumettre lui-même.
|
||||
|
||||
= render partial: "shared/dossiers/submit_is_over", locals: { dossier: dossier }
|
||||
|
|
|
@ -1,3 +1,16 @@
|
|||
%h1
|
||||
%span.icon.folder
|
||||
= dossier.procedure.libelle
|
||||
|
||||
.dossier-form-actions
|
||||
- if current_user.owns?(dossier)
|
||||
%span.button.dropdown.invite-user-action
|
||||
%span.icon.person
|
||||
- if dossier.invites.count > 0
|
||||
Voir les personnes invitées
|
||||
%span.badge= dossier.invites.count
|
||||
- else
|
||||
Inviter une personne à modifier ce dossier
|
||||
|
||||
.dropdown-content.fade-in-down
|
||||
= render partial: "invites/form", locals: { dossier: dossier }
|
||||
|
|
|
@ -69,11 +69,16 @@ describe InvitesController, type: :controller do
|
|||
|
||||
context 'when user has access to dossier' do
|
||||
before do
|
||||
request.env["HTTP_REFERER"] = "/dossiers/#{dossier.id}/modifier"
|
||||
dossier.update(user: signed_in_profile)
|
||||
end
|
||||
|
||||
it { expect { subject }.to change(InviteUser, :count).by(1) }
|
||||
|
||||
it "redirects to the previous URL" do
|
||||
expect(subject).to redirect_to("/dossiers/#{dossier.id}/modifier")
|
||||
end
|
||||
|
||||
context 'when email is assign to an user' do
|
||||
let! (:user_invite) { create(:user, email: email) }
|
||||
|
||||
|
|
|
@ -51,7 +51,20 @@ describe Users::Dossiers::InvitesController, type: :controller do
|
|||
|
||||
context 'when invitation ID is attached at the user email account' do
|
||||
let(:email) { user.email }
|
||||
it { is_expected.to have_http_status(:ok) }
|
||||
|
||||
context 'and dossier is a brouillon' do
|
||||
let(:dossier) { create :dossier, state: 'brouillon' }
|
||||
|
||||
it { is_expected.to have_http_status(302) }
|
||||
it { is_expected.to redirect_to modifier_dossier_path(dossier) }
|
||||
end
|
||||
|
||||
context 'and dossier is not a brouillon' do
|
||||
let(:dossier) { create :dossier, :en_construction }
|
||||
|
||||
it { is_expected.to have_http_status(:ok) }
|
||||
it { is_expected.to render_template('users/recapitulatif/show') }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when invitation ID is not attached at the user email account' do
|
||||
|
|
131
spec/features/new_user/invite_spec.rb
Normal file
131
spec/features/new_user/invite_spec.rb
Normal file
|
@ -0,0 +1,131 @@
|
|||
require 'spec_helper'
|
||||
|
||||
feature 'Invitations' do
|
||||
let(:user) { create(:user) }
|
||||
let(:invited_user) { create(:user, email: 'user_invite@exemple.fr') }
|
||||
let(:procedure) { create(:procedure, :published, :with_type_de_champ) }
|
||||
let(:invite) { create(:invite_user, user: invited_user, dossier: dossier) }
|
||||
|
||||
context 'when the dossier is a brouillon' do
|
||||
let!(:dossier) { create(:dossier, :for_individual, state: 'brouillon', user: user, procedure: procedure) }
|
||||
|
||||
scenario 'on the form, a user can invite another user to collaborate on the dossier', js: true do
|
||||
log_in(user)
|
||||
navigate_to_brouillon(dossier)
|
||||
|
||||
send_invite_to "user_invite@exemple.fr"
|
||||
|
||||
expect(page).to have_current_path(modifier_dossier_path(dossier))
|
||||
expect(page).to have_text("Une invitation a été envoyée à user_invite@exemple.fr.")
|
||||
expect(page).to have_text("user_invite@exemple.fr")
|
||||
end
|
||||
|
||||
scenario 'an invited user can see and edit the draft', js: true do
|
||||
visit users_dossiers_invite_path(invite)
|
||||
expect(page).to have_current_path(new_user_session_path)
|
||||
|
||||
submit_login_form(invited_user)
|
||||
expect(page).to have_current_path(modifier_dossier_path(dossier))
|
||||
expect(page).to have_no_selector('.button.invite-user-action')
|
||||
|
||||
fill_in 'Libelle du champ', with: 'Some edited value'
|
||||
click_button 'Enregistrer le brouillon'
|
||||
expect(page).to have_text('Votre brouillon a bien été sauvegardé')
|
||||
expect(page).to have_field('Libelle du champ', with: 'Some edited value')
|
||||
end
|
||||
|
||||
scenario 'an invited user cannot submit the draft' do
|
||||
visit users_dossiers_invite_path(invite)
|
||||
expect(page).to have_current_path(new_user_session_path)
|
||||
|
||||
submit_login_form(invited_user)
|
||||
expect(page).to have_current_path(modifier_dossier_path(dossier))
|
||||
|
||||
expect(page).to have_button('Soumettre le dossier', disabled: true)
|
||||
expect(page).to have_selector('.invite-cannot-submit')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the dossier is en_construction' do
|
||||
let!(:dossier) { create(:dossier, :for_individual, :en_construction, user: user, procedure: procedure) }
|
||||
|
||||
scenario 'on dossier details, a user can invite another user to collaborate on the dossier', js: true do
|
||||
log_in(user)
|
||||
navigate_to_recapitulatif(dossier)
|
||||
|
||||
legacy_send_invite_to "user_invite@exemple.fr"
|
||||
|
||||
expect(page).to have_current_path(users_dossier_recapitulatif_path(dossier))
|
||||
expect(page).to have_text("Une invitation a été envoyée à user_invite@exemple.fr.")
|
||||
expect(page).to have_text("user_invite@exemple.fr")
|
||||
end
|
||||
|
||||
scenario 'an invited user can see and edit the dossier', js: true do
|
||||
visit users_dossiers_invite_path(invite)
|
||||
expect(page).to have_current_path(new_user_session_path)
|
||||
|
||||
submit_login_form(invited_user)
|
||||
expect(page).to have_current_path(users_dossiers_invite_path(invite))
|
||||
expect(page).to have_no_selector('.button.invite-user-action')
|
||||
expect(page).to have_text("Dossier nº #{dossier.id}")
|
||||
|
||||
# We should be able to just click() the link, but Capybara detects that the
|
||||
# enclosing div would be clicked instead.
|
||||
expect(page).to have_link("MODIFIER", href: modifier_dossier_path(dossier))
|
||||
visit modifier_dossier_path(dossier)
|
||||
|
||||
expect(page).to have_current_path(modifier_dossier_path(dossier))
|
||||
fill_in "Libelle du champ", with: "Some edited value"
|
||||
click_button "Enregistrer les modifications du dossier"
|
||||
|
||||
expect(page).to have_current_path(users_dossiers_invite_path(invite))
|
||||
expect(page).to have_text("Some edited value")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def log_in(user)
|
||||
visit '/'
|
||||
click_on 'Connexion'
|
||||
submit_login_form(user)
|
||||
expect(page).to have_current_path(dossiers_path)
|
||||
end
|
||||
|
||||
def submit_login_form(user)
|
||||
fill_in 'user_email', with: user.email
|
||||
fill_in 'user_password', with: user.password
|
||||
click_on 'Se connecter'
|
||||
end
|
||||
|
||||
def navigate_to_brouillon(dossier)
|
||||
expect(page).to have_current_path(dossiers_path)
|
||||
click_on(dossier.id)
|
||||
expect(page).to have_current_path(modifier_dossier_path(dossier))
|
||||
end
|
||||
|
||||
def navigate_to_recapitulatif(dossier)
|
||||
expect(page).to have_current_path(dossiers_path)
|
||||
click_on(dossier.id)
|
||||
expect(page).to have_current_path(users_dossier_recapitulatif_path(dossier))
|
||||
end
|
||||
|
||||
def send_invite_to(invited_email)
|
||||
find('.button.invite-user-action').click()
|
||||
expect(page).to have_button("Envoyer une invitation", visible: true)
|
||||
|
||||
fill_in 'invite_email', with: invited_email
|
||||
click_on "Envoyer une invitation"
|
||||
end
|
||||
|
||||
def legacy_send_invite_to(invited_email)
|
||||
find('.dropdown-toggle', text: "Voir les personnes impliquées").click()
|
||||
expect(page).to have_button("Ajouter", visible: true)
|
||||
|
||||
fill_in 'invite_email', with: invited_email
|
||||
|
||||
page.accept_alert "Envoyer l'invitation ?" do
|
||||
click_on "Ajouter"
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue