From e0571a8ae32ced85d9dce06ef2a18a0cc33d6018 Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Mon, 14 Oct 2019 14:01:09 +0000 Subject: [PATCH 1/6] avis: improve layout and wording --- app/assets/stylesheets/new_design/avis.scss | 4 +++- .../instructeurs/shared/avis/_form.html.haml | 16 ++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/assets/stylesheets/new_design/avis.scss b/app/assets/stylesheets/new_design/avis.scss index 42e7c354d..fa8876b1d 100644 --- a/app/assets/stylesheets/new_design/avis.scss +++ b/app/assets/stylesheets/new_design/avis.scss @@ -33,6 +33,8 @@ } .ask-avis { + margin-bottom: 2 * $default-padding; + .avis-notice { font-size: 14px; color: $grey; @@ -67,7 +69,7 @@ .confidentiel-explanation { font-size: 14px; color: $grey; - margin-top: -$default-padding; + margin-top: - $default-padding; margin-bottom: 2 * $default-padding; } } diff --git a/app/views/instructeurs/shared/avis/_form.html.haml b/app/views/instructeurs/shared/avis/_form.html.haml index 15f317f8f..a23a30ae2 100644 --- a/app/views/instructeurs/shared/avis/_form.html.haml +++ b/app/views/instructeurs/shared/avis/_form.html.haml @@ -1,23 +1,23 @@ %section.ask-avis %h1.tab-title Inviter des personnes à donner leur avis - %p.avis-notice Les invités pourront consulter, donner un avis sur le dossier et contribuer au fil de messagerie, mais ils ne pourront pas le modifier. + %p.avis-notice Les invités pourront consulter le dossier, donner un avis et contribuer au fil de messagerie. Ils ne pourront pas modifier le dossier. = form_for avis, url: url, html: { class: 'form' } do |f| = f.email_field :emails, placeholder: 'Adresses email, séparées par des virgules', required: true, multiple: true, onchange: "javascript:DS.replaceSemicolonByComma(event);" = f.text_area :introduction, rows: 3, value: avis.introduction || 'Bonjour, merci de me donner votre avis sur ce dossier.', required: true + .flex.justify-between.align-baseline - if must_be_confidentiel %p.confidentiel.flex %span.icon.lock %span - Cet avis est confidentiel et n'est pas affiché aux autres experts consultés mais est visible par tous les instructeurs - .send-wrapper - = f.submit 'Demander un avis', class: 'button send' + Cet avis sera confidentiel : il ne sera pas affiché aux autres experts consultés, mais sera visible par les instructeurs. + - else .confidentiel-wrapper - = f.label :confidentiel, 'Cet avis est' + = f.label :confidentiel, 'Cet avis sera ' = f.select :confidentiel, [['partagé avec les autres experts', false], ['confidentiel', true]], {}, onchange: "javascript:DS.toggleCondidentielExplanation(event);" .confidentiel-explanation.hidden - Il ne sera pas affiché aux autres experts consultés mais sera visible par les instructeurs - .send-wrapper - = f.submit 'Demander un avis', class: 'button send' + Il ne sera pas affiché aux autres experts consultés, mais sera visible par les instructeurs. + + = f.submit 'Demander un avis', class: 'button primary send' From 0064c2c61037bbe54a53835d79a2b2fc18e429ff Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Mon, 14 Oct 2019 15:34:04 +0200 Subject: [PATCH 2/6] views: tell an attestation will be sent only if it is true Previously the message stating "an attestation will be sent" was displayed even when the attestation was disabled. --- .../instructeurs/dossiers/_state_button_motivation.html.haml | 5 +++-- .../dossiers/_state_button_motivation.html.haml_spec.rb | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/views/instructeurs/dossiers/_state_button_motivation.html.haml b/app/views/instructeurs/dossiers/_state_button_motivation.html.haml index d071c05b2..447054a0d 100644 --- a/app/views/instructeurs/dossiers/_state_button_motivation.html.haml +++ b/app/views/instructeurs/dossiers/_state_button_motivation.html.haml @@ -6,8 +6,9 @@ = form_tag(terminer_instructeur_dossier_path(dossier.procedure, dossier), remote: true, method: :post, class: 'form') do - if title == 'Accepter' = text_area :dossier, :motivation, class: 'motivation-text-area', placeholder: placeholder, required: false - %p.help - L'acceptation du dossier envoie automatiquement une attestation à l'usager. + - if dossier.procedure.attestation_template&.activated? + %p.help + L'acceptation du dossier envoie automatiquement une attestation à l'usager. - unspecified_attestation_champs = dossier.unspecified_attestation_champs - if unspecified_attestation_champs.present? diff --git a/spec/views/instructeur/dossiers/_state_button_motivation.html.haml_spec.rb b/spec/views/instructeur/dossiers/_state_button_motivation.html.haml_spec.rb index 368cf13cc..4f9d21937 100644 --- a/spec/views/instructeur/dossiers/_state_button_motivation.html.haml_spec.rb +++ b/spec/views/instructeur/dossiers/_state_button_motivation.html.haml_spec.rb @@ -20,6 +20,7 @@ describe 'instructeurs/dossiers/state_button_motivation.html.haml', type: :view end context 'without an attestation preview' do + it { expect(rendered).not_to have_text("envoie automatiquement une attestation") } it { expect(rendered).not_to have_text("Voir l'attestation") } end end From 0e5f66c5ba6bbfb25130a74207e9c0da6bca6dda Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Mon, 14 Oct 2019 15:38:04 +0200 Subject: [PATCH 3/6] views: make the "Voir l'attestation" UI simpler Instead of adding a button, just turn the "attestation" text into a link --- .../dossiers/_state_button_motivation.html.haml | 6 +++--- .../dossiers/_state_button_motivation.html.haml_spec.rb | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/views/instructeurs/dossiers/_state_button_motivation.html.haml b/app/views/instructeurs/dossiers/_state_button_motivation.html.haml index 447054a0d..7376dceca 100644 --- a/app/views/instructeurs/dossiers/_state_button_motivation.html.haml +++ b/app/views/instructeurs/dossiers/_state_button_motivation.html.haml @@ -8,7 +8,9 @@ = text_area :dossier, :motivation, class: 'motivation-text-area', placeholder: placeholder, required: false - if dossier.procedure.attestation_template&.activated? %p.help - L'acceptation du dossier envoie automatiquement une attestation à l'usager. + L'acceptation du dossier envoie automatiquement + = link_to 'une attestation', apercu_attestation_instructeur_dossier_path(dossier.procedure, dossier), target: '_blank', rel: 'noopener', title: "Voir l'attestation qui sera envoyée à l'usager" + à l'usager. - unspecified_attestation_champs = dossier.unspecified_attestation_champs - if unspecified_attestation_champs.present? @@ -34,7 +36,5 @@ .hidden{ id: "justificatif_motivation_import_#{popup_class}" } = file_field :dossier, :justificatif_motivation, direct_upload: true .text-right - - if title == 'Accepter' && dossier.procedure.attestation_template&.activated? - = link_to "Voir l'attestation", apercu_attestation_instructeur_dossier_path(dossier.procedure, dossier), target: '_blank', rel: 'noopener', class: 'button', title: "Voir l'attestation qui sera envoyée au demandeur" %span.button{ onclick: 'DS.motivationCancel();' } Annuler = button_tag 'Valider la décision', name: :process_action, value: process_action, class: 'button primary', title: title, data: { confirm: confirm } diff --git a/spec/views/instructeur/dossiers/_state_button_motivation.html.haml_spec.rb b/spec/views/instructeur/dossiers/_state_button_motivation.html.haml_spec.rb index 4f9d21937..e02e37d14 100644 --- a/spec/views/instructeur/dossiers/_state_button_motivation.html.haml_spec.rb +++ b/spec/views/instructeur/dossiers/_state_button_motivation.html.haml_spec.rb @@ -16,11 +16,10 @@ describe 'instructeurs/dossiers/state_button_motivation.html.haml', type: :view context 'with an attestation preview' do let(:dossier) { create :dossier, :accepte, :with_attestation } - it { expect(rendered).to have_text("Voir l'attestation") } + it { expect(rendered).to have_link(href: apercu_attestation_instructeur_dossier_path(dossier.procedure, dossier)) } end context 'without an attestation preview' do - it { expect(rendered).not_to have_text("envoie automatiquement une attestation") } - it { expect(rendered).not_to have_text("Voir l'attestation") } + it { expect(rendered).not_to have_link(href: apercu_attestation_instructeur_dossier_path(dossier.procedure, dossier)) } end end From 07f75ff20ee76c686c12a0d30cb6d310d9e707d9 Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Mon, 14 Oct 2019 10:57:19 +0000 Subject: [PATCH 4/6] views: fix missing attestation link - Fix the missing link to see attestations (see #4400) - Fix the "Repasser en instruction" wording being confusing for accepted state - Add lot of tests --- .../dossiers/_state_button.html.haml | 25 ++-- .../dossiers/_state_button.html.haml_spec.rb | 127 ++++++++++++++++++ 2 files changed, 142 insertions(+), 10 deletions(-) create mode 100644 spec/views/instructeur/dossiers/_state_button.html.haml_spec.rb diff --git a/app/views/instructeurs/dossiers/_state_button.html.haml b/app/views/instructeurs/dossiers/_state_button.html.haml index 9574d6987..84e39f9f8 100644 --- a/app/views/instructeurs/dossiers/_state_button.html.haml +++ b/app/views/instructeurs/dossiers/_state_button.html.haml @@ -1,4 +1,9 @@ -- if dossier.en_construction? || dossier.en_instruction? || dossier.accepte? +- if dossier.en_construction? || dossier.en_instruction? + + -# ----------------------------------------- + -# Dossier EN CONSTRUCTION ou EN INSTRUCTION + -# ----------------------------------------- + %span.dropdown %button.button.primary.dropdown-button = dossier_display_state dossier @@ -17,13 +22,6 @@ %h4 Passer en instruction L'usager ne pourra plus modifier le formulaire - - if dossier.accepte? - %li - = link_to repasser_en_instruction_instructeur_dossier_path(dossier.procedure, dossier), method: :post, data: { remote: true, confirm: "Confirmez-vous le passage en instruction de ce dossier ?" } do - %span.icon.in-progress - .dropdown-description - %h4 Passer en instruction - L'usager ne pourra plus modifier le formulaire - if dossier.en_instruction? %li = link_to repasser_en_construction_instructeur_dossier_path(dossier.procedure, dossier), method: :post, data: { remote:true, confirm: "Confirmez-vous le passage en construction de ce dossier ?" } do @@ -59,6 +57,11 @@ = render partial: 'instructeurs/dossiers/state_button_motivation', locals: { dossier: dossier, popup_title: 'Refuser le dossier', placeholder: 'Expliquez au demandeur pourquoi ce dossier est refusé (obligatoire)', popup_class: 'refuse', process_action: 'refuser', title: 'Refuser', confirm: 'Confirmez-vous le refus de ce dossier ?' } - else + + -# --------------------------------------------------- + -# Dossier TERMINÉ + -# --------------------------------------------------- + - if dossier.motivation.present? || dossier.attestation.present? %span.dropdown %button.button.dropdown-button{ class: button_or_label_class(dossier) } @@ -74,8 +77,7 @@ %p.attestation L'acceptation du dossier a envoyé automatiquement une attestation au demandeur = link_to "Voir l'attestation", attestation_instructeur_dossier_path(dossier.procedure, dossier), target: '_blank', rel: 'noopener', class: 'button' - - - if dossier.refuse? || dossier.sans_suite? + - if dossier.termine? %ul.dropdown-items.with-top-border %li = link_to repasser_en_instruction_instructeur_dossier_path(dossier.procedure, dossier), method: :post, data: { remote:true, confirm: "Voulez vous remettre le dossier #{dossier.id} en instruction ?" } do @@ -83,6 +85,9 @@ .dropdown-description %h4 Repasser en instruction L’usager sera notifié que son dossier est réexaminé. + - else + -# No actions to perform: only display a label with the dossier state + -# FIXME: we still should be able to move back the dossier to instruction %span.label{ class: button_or_label_class(dossier) } = dossier_display_state(dossier, lower: true) diff --git a/spec/views/instructeur/dossiers/_state_button.html.haml_spec.rb b/spec/views/instructeur/dossiers/_state_button.html.haml_spec.rb new file mode 100644 index 000000000..49599613e --- /dev/null +++ b/spec/views/instructeur/dossiers/_state_button.html.haml_spec.rb @@ -0,0 +1,127 @@ +require 'spec_helper' + +describe 'instructeurs/dossiers/state_button.html.haml', type: :view do + include DossierHelper + + subject! do + render('instructeurs/dossiers/state_button.html.haml', dossier: dossier) + end + + matcher :have_state_label do |expected_title| + match do |rendered| + expect(rendered).to have_selector('.label', text: expected_title) + expect(rendered).not_to have_selector('.dropdown') + end + end + + matcher :have_dropdown_title do |expected_title| + match do |rendered| + expect(rendered).to have_selector('.dropdown .dropdown-button', text: expected_title) + end + end + + matcher :have_dropdown_items do |options| + match do |rendered| + expected_count = options[:count] || 1 + expect(rendered).to have_selector('ul.dropdown-items li', count: expected_count) + end + end + + matcher :have_dropdown_item do |expected_title, options = {}| + match do |rendered| + expected_href = options[:href] + if (expected_href.present?) + expect(rendered).to have_selector("ul.dropdown-items li a[href='#{expected_href}']", text: expected_title) + else + expect(rendered).to have_selector('ul.dropdown-items li', text: expected_title) + end + end + end + + context 'brouillon' do + let(:dossier) { create(:dossier) } + + # Currently the state button is not supposed to be displayed for brouillons. + # But better have a sane fallback than crashing. + + it 'renders a label' do + expect(rendered).to have_state_label('brouillon') + end + end + + context 'en_contruction' do + let(:dossier) { create(:dossier, :en_construction) } + + it 'renders a dropdown' do + expect(rendered).to have_dropdown_title('En construction') + expect(rendered).to have_dropdown_items(count: 2) + expect(rendered).to have_dropdown_item('En construction') + expect(rendered).to have_dropdown_item('Passer en instruction', href: passer_en_instruction_instructeur_dossier_path(dossier.procedure, dossier)) + end + end + + context 'en_instruction' do + let(:dossier) { create(:dossier, :en_instruction) } + + it 'renders a dropdown' do + expect(rendered).to have_dropdown_title('En instruction') + expect(rendered).to have_dropdown_items(count: 5) + expect(rendered).to have_dropdown_item('Repasser en construction', href: repasser_en_construction_instructeur_dossier_path(dossier.procedure, dossier)) + expect(rendered).to have_dropdown_item('En instruction') + expect(rendered).to have_dropdown_item('Accepter') + expect(rendered).to have_dropdown_item('Classer sans suite') + expect(rendered).to have_dropdown_item('Refuser') + end + end + + shared_examples 'a dropdown for a closed state' do |state| + let(:dossier) { create :dossier, state } + + # FIXME: it should also render the link to move back to instruction + it 'renders a simple label' do + expect(rendered).to have_state_label(dossier_display_state(dossier, lower: true)) + end + + context 'with a motivation' do + let(:dossier) { create :dossier, state, motivation: 'Correspond au programme' } + + it 'renders a dropdown' do + expect(rendered).to have_dropdown_title(dossier_display_state(dossier, lower: true)) + expect(rendered).to have_dropdown_items(count: 1) + expect(rendered).to have_dropdown_item('Repasser en instruction', href: repasser_en_instruction_instructeur_dossier_path(dossier.procedure, dossier)) + end + + it 'displays the motivation text' do + expect(rendered).to have_content('Motivation') + expect(rendered).to have_content(dossier.motivation) + end + end + + context 'with an attestation' do + let(:dossier) { create :dossier, state, :with_attestation } + + it 'renders a dropdown' do + expect(rendered).to have_dropdown_title(dossier_display_state(dossier, lower: true)) + expect(rendered).to have_dropdown_items(count: 1) + expect(rendered).to have_dropdown_item('Repasser en instruction', href: repasser_en_instruction_instructeur_dossier_path(dossier.procedure, dossier)) + end + + it 'provides a link to the attestation' do + expect(rendered).to have_content('Attestation') + expect(rendered).to have_link(href: attestation_instructeur_dossier_path(dossier.procedure, dossier)) + end + end + end + + context 'accepte' do + it_behaves_like 'a dropdown for a closed state', :accepte + end + + context 'refuse' do + it_behaves_like 'a dropdown for a closed state', :refuse + end + + context 'sans_suite' do + it_behaves_like 'a dropdown for a closed state', :sans_suite + end +end From dd57953b76232652d05ee7fb2d0ec21f12d82a91 Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Mon, 14 Oct 2019 11:18:59 +0000 Subject: [PATCH 5/6] views: refactor the state button Now that all states have a dropdown, we can simplify the code. This also brings the "Repasser en instruction" action for all states (including when no attestation or motivation is present). --- .../dossiers/_state_button.html.haml | 164 +++++++++--------- .../dossiers/_state_button.html.haml_spec.rb | 34 +--- 2 files changed, 91 insertions(+), 107 deletions(-) diff --git a/app/views/instructeurs/dossiers/_state_button.html.haml b/app/views/instructeurs/dossiers/_state_button.html.haml index 84e39f9f8..def2c8496 100644 --- a/app/views/instructeurs/dossiers/_state_button.html.haml +++ b/app/views/instructeurs/dossiers/_state_button.html.haml @@ -1,93 +1,95 @@ -- if dossier.en_construction? || dossier.en_instruction? +%span.dropdown + -# Dropdown button title + %button.button.primary.dropdown-button{ class: button_or_label_class(dossier) } + = dossier_display_state dossier - -# ----------------------------------------- - -# Dossier EN CONSTRUCTION ou EN INSTRUCTION - -# ----------------------------------------- + -# Dropdown content + .dropdown-content.fade-in-down{ class: ('terminated' if dossier.termine?) } - %span.dropdown - %button.button.primary.dropdown-button - = dossier_display_state dossier - .dropdown-content.fade-in-down + - if dossier.en_construction? + -# ------------------------------------------------------ + -# EN CONSTRUCTION + -# ------------------------------------------------------ %ul.dropdown-items - - if dossier.en_construction? - %li.selected - %span.icon.edit - .dropdown-description - %h4 En construction - Vous permettez à l'usager de modifier ses réponses au formulaire - %li - = link_to passer_en_instruction_instructeur_dossier_path(dossier.procedure, dossier), method: :post, data: { remote: true, confirm: "Confirmez-vous le passage en instruction de ce dossier ?" } do - %span.icon.in-progress - .dropdown-description - %h4 Passer en instruction - L'usager ne pourra plus modifier le formulaire - - if dossier.en_instruction? - %li - = link_to repasser_en_construction_instructeur_dossier_path(dossier.procedure, dossier), method: :post, data: { remote:true, confirm: "Confirmez-vous le passage en construction de ce dossier ?" } do - %span.icon.edit - .dropdown-description - %h4 Repasser en construction - Vous permettrez à l'usager de modifier ses réponses au formulaire - %li.selected + %li.selected + %span.icon.edit + .dropdown-description + %h4 En construction + Vous permettez à l'usager de modifier ses réponses au formulaire + + %li + = link_to passer_en_instruction_instructeur_dossier_path(dossier.procedure, dossier), method: :post, data: { remote: true, confirm: "Confirmez-vous le passage en instruction de ce dossier ?" } do %span.icon.in-progress .dropdown-description - %h4 En instruction - L'usager ne peut modifier son dossier pendant l'instruction - %li - %a{ href: '#', onclick: "DS.showMotivation(event, 'accept');" } - %span.icon.accept - .dropdown-description - %h4 Accepter - L'usager sera notifié que son dossier a été accepté - %li - %a{ href: '#', onclick: "DS.showMotivation(event, 'without-continuation');" } - %span.icon.without-continuation - .dropdown-description - %h4 Classer sans suite - L'usager sera notifié que son dossier a été classé sans suite - %li - %a{ href: '#', onclick: "DS.showMotivation(event, 'refuse');" } - %span.icon.refuse - .dropdown-description - %h4 Refuser - L'usager sera notifié que son dossier a été refusé - = render partial: 'instructeurs/dossiers/state_button_motivation', locals: { dossier: dossier, popup_title: 'Accepter le dossier', placeholder: 'Expliquez au demandeur pourquoi ce dossier est accepté (facultatif)', popup_class: 'accept', process_action: 'accepter', title: 'Accepter', confirm: "Confirmez-vous l'acceptation ce dossier ?" } - = render partial: 'instructeurs/dossiers/state_button_motivation', locals: { dossier: dossier, popup_title: 'Classer le dossier sans suite', placeholder: 'Expliquez au demandeur pourquoi ce dossier est classé sans suite (obligatoire)', popup_class: 'without-continuation', process_action: 'classer_sans_suite', title: 'Classer sans suite', confirm: 'Confirmez-vous le classement sans suite de ce dossier ?' } - = render partial: 'instructeurs/dossiers/state_button_motivation', locals: { dossier: dossier, popup_title: 'Refuser le dossier', placeholder: 'Expliquez au demandeur pourquoi ce dossier est refusé (obligatoire)', popup_class: 'refuse', process_action: 'refuser', title: 'Refuser', confirm: 'Confirmez-vous le refus de ce dossier ?' } + %h4 Passer en instruction + L'usager ne pourra plus modifier le formulaire -- else + - elsif dossier.en_instruction? + -# ------------------------------------------------------ + -# EN INSTRUCTION + -# ------------------------------------------------------ + %ul.dropdown-items - -# --------------------------------------------------- - -# Dossier TERMINÉ - -# --------------------------------------------------- + %li + = link_to repasser_en_construction_instructeur_dossier_path(dossier.procedure, dossier), method: :post, data: { remote:true, confirm: "Confirmez-vous le passage en construction de ce dossier ?" } do + %span.icon.edit + .dropdown-description + %h4 Repasser en construction + Vous permettrez à l'usager de modifier ses réponses au formulaire - - if dossier.motivation.present? || dossier.attestation.present? - %span.dropdown - %button.button.dropdown-button{ class: button_or_label_class(dossier) } - = dossier_display_state(dossier, lower: true) - .dropdown-content.fade-in-down.terminated - - if dossier.motivation.present? - %h4.title Motivation - %p.dossier-motivation= dossier.motivation - = render partial: 'users/dossiers/show/download_justificatif', locals: { dossier: dossier } + %li.selected + %span.icon.in-progress + .dropdown-description + %h4 En instruction + L'usager ne peut modifier son dossier pendant l'instruction - - if dossier.attestation.present? - %h4.title Attestation - %p.attestation L'acceptation du dossier a envoyé automatiquement une attestation au demandeur - = link_to "Voir l'attestation", attestation_instructeur_dossier_path(dossier.procedure, dossier), target: '_blank', rel: 'noopener', class: 'button' + %li + %a{ href: '#', onclick: "DS.showMotivation(event, 'accept');" } + %span.icon.accept + .dropdown-description + %h4 Accepter + L'usager sera notifié que son dossier a été accepté - - if dossier.termine? - %ul.dropdown-items.with-top-border - %li - = link_to repasser_en_instruction_instructeur_dossier_path(dossier.procedure, dossier), method: :post, data: { remote:true, confirm: "Voulez vous remettre le dossier #{dossier.id} en instruction ?" } do - %span.icon.in-progress - .dropdown-description - %h4 Repasser en instruction - L’usager sera notifié que son dossier est réexaminé. + %li + %a{ href: '#', onclick: "DS.showMotivation(event, 'without-continuation');" } + %span.icon.without-continuation + .dropdown-description + %h4 Classer sans suite + L'usager sera notifié que son dossier a été classé sans suite - - else - -# No actions to perform: only display a label with the dossier state - -# FIXME: we still should be able to move back the dossier to instruction - %span.label{ class: button_or_label_class(dossier) } - = dossier_display_state(dossier, lower: true) + %li + %a{ href: '#', onclick: "DS.showMotivation(event, 'refuse');" } + %span.icon.refuse + .dropdown-description + %h4 Refuser + L'usager sera notifié que son dossier a été refusé + + = render partial: 'instructeurs/dossiers/state_button_motivation', locals: { dossier: dossier, popup_title: 'Accepter le dossier', placeholder: 'Expliquez au demandeur pourquoi ce dossier est accepté (facultatif)', popup_class: 'accept', process_action: 'accepter', title: 'Accepter', confirm: "Confirmez-vous l'acceptation ce dossier ?" } + + = render partial: 'instructeurs/dossiers/state_button_motivation', locals: { dossier: dossier, popup_title: 'Classer le dossier sans suite', placeholder: 'Expliquez au demandeur pourquoi ce dossier est classé sans suite (obligatoire)', popup_class: 'without-continuation', process_action: 'classer_sans_suite', title: 'Classer sans suite', confirm: 'Confirmez-vous le classement sans suite de ce dossier ?' } + + = render partial: 'instructeurs/dossiers/state_button_motivation', locals: { dossier: dossier, popup_title: 'Refuser le dossier', placeholder: 'Expliquez au demandeur pourquoi ce dossier est refusé (obligatoire)', popup_class: 'refuse', process_action: 'refuser', title: 'Refuser', confirm: 'Confirmez-vous le refus de ce dossier ?' } + + - elsif dossier.termine? + -# --------------------------------------------------- + -# TERMINÉ + -# --------------------------------------------------- + -# TODO: turn the motivation and attestation into regular dropdown items + - if dossier.motivation.present? + %h4.title Motivation + %p.dossier-motivation= dossier.motivation + = render partial: 'users/dossiers/show/download_justificatif', locals: { dossier: dossier } + + - if dossier.attestation.present? + %h4.title Attestation + %p.attestation L'acceptation du dossier a envoyé automatiquement une attestation au demandeur + = link_to "Voir l'attestation", attestation_instructeur_dossier_path(dossier.procedure, dossier), target: '_blank', rel: 'noopener', class: 'button' + + %ul.dropdown-items.with-top-border + %li + = link_to repasser_en_instruction_instructeur_dossier_path(dossier.procedure, dossier), method: :post, data: { remote:true, confirm: "Voulez vous remettre le dossier #{dossier.id} en instruction ?" } do + %span.icon.in-progress + .dropdown-description + %h4 Repasser en instruction + L’usager sera notifié que son dossier est réexaminé. diff --git a/spec/views/instructeur/dossiers/_state_button.html.haml_spec.rb b/spec/views/instructeur/dossiers/_state_button.html.haml_spec.rb index 49599613e..32030a098 100644 --- a/spec/views/instructeur/dossiers/_state_button.html.haml_spec.rb +++ b/spec/views/instructeur/dossiers/_state_button.html.haml_spec.rb @@ -7,13 +7,6 @@ describe 'instructeurs/dossiers/state_button.html.haml', type: :view do render('instructeurs/dossiers/state_button.html.haml', dossier: dossier) end - matcher :have_state_label do |expected_title| - match do |rendered| - expect(rendered).to have_selector('.label', text: expected_title) - expect(rendered).not_to have_selector('.dropdown') - end - end - matcher :have_dropdown_title do |expected_title| match do |rendered| expect(rendered).to have_selector('.dropdown .dropdown-button', text: expected_title) @@ -39,13 +32,13 @@ describe 'instructeurs/dossiers/state_button.html.haml', type: :view do end context 'brouillon' do - let(:dossier) { create(:dossier) } - # Currently the state button is not supposed to be displayed for brouillons. # But better have a sane fallback than crashing. + let(:dossier) { create(:dossier) } - it 'renders a label' do - expect(rendered).to have_state_label('brouillon') + it 'renders a dropdown' do + expect(rendered).to have_dropdown_title('Brouillon') + expect(rendered).to have_dropdown_items(count: 0) end end @@ -77,20 +70,15 @@ describe 'instructeurs/dossiers/state_button.html.haml', type: :view do shared_examples 'a dropdown for a closed state' do |state| let(:dossier) { create :dossier, state } - # FIXME: it should also render the link to move back to instruction - it 'renders a simple label' do - expect(rendered).to have_state_label(dossier_display_state(dossier, lower: true)) + it 'renders a dropdown' do + expect(rendered).to have_dropdown_title(dossier_display_state(dossier)) + expect(rendered).to have_dropdown_items(count: 1) + expect(rendered).to have_dropdown_item('Repasser en instruction', href: repasser_en_instruction_instructeur_dossier_path(dossier.procedure, dossier)) end context 'with a motivation' do let(:dossier) { create :dossier, state, motivation: 'Correspond au programme' } - it 'renders a dropdown' do - expect(rendered).to have_dropdown_title(dossier_display_state(dossier, lower: true)) - expect(rendered).to have_dropdown_items(count: 1) - expect(rendered).to have_dropdown_item('Repasser en instruction', href: repasser_en_instruction_instructeur_dossier_path(dossier.procedure, dossier)) - end - it 'displays the motivation text' do expect(rendered).to have_content('Motivation') expect(rendered).to have_content(dossier.motivation) @@ -100,12 +88,6 @@ describe 'instructeurs/dossiers/state_button.html.haml', type: :view do context 'with an attestation' do let(:dossier) { create :dossier, state, :with_attestation } - it 'renders a dropdown' do - expect(rendered).to have_dropdown_title(dossier_display_state(dossier, lower: true)) - expect(rendered).to have_dropdown_items(count: 1) - expect(rendered).to have_dropdown_item('Repasser en instruction', href: repasser_en_instruction_instructeur_dossier_path(dossier.procedure, dossier)) - end - it 'provides a link to the attestation' do expect(rendered).to have_content('Attestation') expect(rendered).to have_link(href: attestation_instructeur_dossier_path(dossier.procedure, dossier)) From db0fede5214a136a03dcf21298d92ae6b96fd9b4 Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Tue, 15 Oct 2019 10:42:51 +0000 Subject: [PATCH 6/6] views: improve the state button - Turn the "accepted" infos into standard dropdown sections - Display the justificatif even if there is no motivation --- app/assets/images/icons/download.svg | 1 + app/assets/images/icons/justificatif.svg | 1 + app/assets/images/icons/preview.svg | 1 + .../stylesheets/new_design/buttons.scss | 9 ++--- app/assets/stylesheets/new_design/icons.scss | 13 +++++++ app/assets/stylesheets/new_design/patron.scss | 2 +- .../dossiers/_state_button.html.haml | 34 +++++++++++++------ app/views/root/patron.html.haml | 3 ++ .../dossiers/show/_status_overview.html.haml | 2 +- spec/factories/dossier.rb | 9 +++++ .../dossiers/_state_button.html.haml_spec.rb | 19 +++++++++-- 11 files changed, 74 insertions(+), 20 deletions(-) create mode 100644 app/assets/images/icons/download.svg create mode 100644 app/assets/images/icons/justificatif.svg create mode 100644 app/assets/images/icons/preview.svg diff --git a/app/assets/images/icons/download.svg b/app/assets/images/icons/download.svg new file mode 100644 index 000000000..70b8ac752 --- /dev/null +++ b/app/assets/images/icons/download.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/icons/justificatif.svg b/app/assets/images/icons/justificatif.svg new file mode 100644 index 000000000..3569c189a --- /dev/null +++ b/app/assets/images/icons/justificatif.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/icons/preview.svg b/app/assets/images/icons/preview.svg new file mode 100644 index 000000000..4eb692353 --- /dev/null +++ b/app/assets/images/icons/preview.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/stylesheets/new_design/buttons.scss b/app/assets/stylesheets/new_design/buttons.scss index 6fe9cb876..a36b7a719 100644 --- a/app/assets/stylesheets/new_design/buttons.scss +++ b/app/assets/stylesheets/new_design/buttons.scss @@ -206,7 +206,6 @@ border-bottom: 1px solid $border-grey; font-size: 12px; min-width: 300px; - cursor: pointer; &.selected { cursor: default; @@ -217,8 +216,9 @@ } &.selected, - &:hover { + &:hover:not(.inactive) { background: $light-grey; + cursor: pointer; } &.danger { @@ -267,8 +267,9 @@ margin-bottom: $default-spacer; } - &.with-top-border { - border-top: 1px solid $grey; + p + h4, + p + p, { + margin-top: $default-spacer; } } diff --git a/app/assets/stylesheets/new_design/icons.scss b/app/assets/stylesheets/new_design/icons.scss index 20a290c7d..5155ee6d8 100644 --- a/app/assets/stylesheets/new_design/icons.scss +++ b/app/assets/stylesheets/new_design/icons.scss @@ -63,7 +63,15 @@ background-image: image-url("icons/attachment.svg"); } + &.preview { + background-image: image-url("icons/preview.svg"); + } + &.download { + background-image: image-url("icons/download.svg"); + } + + &.download-white { background-image: image-url("icons/download-white.svg"); } @@ -71,6 +79,11 @@ background-image: image-url("icons/lock.svg"); } + &.justificatif { + background-image: image-url("icons/justificatif.svg"); + } + + &.printer { background-image: image-url("icons/printer.svg"); } diff --git a/app/assets/stylesheets/new_design/patron.scss b/app/assets/stylesheets/new_design/patron.scss index ae160adab..cb337bce2 100644 --- a/app/assets/stylesheets/new_design/patron.scss +++ b/app/assets/stylesheets/new_design/patron.scss @@ -5,7 +5,7 @@ margin-bottom: 20px; } - .icon.download { + .icon.download-white { background-color: $blue; box-shadow: 0px 0px 1px 2px $blue; } diff --git a/app/views/instructeurs/dossiers/_state_button.html.haml b/app/views/instructeurs/dossiers/_state_button.html.haml index def2c8496..cbf3c2251 100644 --- a/app/views/instructeurs/dossiers/_state_button.html.haml +++ b/app/views/instructeurs/dossiers/_state_button.html.haml @@ -4,7 +4,7 @@ = dossier_display_state dossier -# Dropdown content - .dropdown-content.fade-in-down{ class: ('terminated' if dossier.termine?) } + .dropdown-content.fade-in-down - if dossier.en_construction? -# ------------------------------------------------------ @@ -75,18 +75,30 @@ -# --------------------------------------------------- -# TERMINÉ -# --------------------------------------------------- - -# TODO: turn the motivation and attestation into regular dropdown items - - if dossier.motivation.present? - %h4.title Motivation - %p.dossier-motivation= dossier.motivation - = render partial: 'users/dossiers/show/download_justificatif', locals: { dossier: dossier } + %ul.dropdown-items + - if dossier.motivation.present? + %li.inactive + %span.icon.info + .dropdown-description + %h4 Motivation + %p « #{dossier.motivation} » - - if dossier.attestation.present? - %h4.title Attestation - %p.attestation L'acceptation du dossier a envoyé automatiquement une attestation au demandeur - = link_to "Voir l'attestation", attestation_instructeur_dossier_path(dossier.procedure, dossier), target: '_blank', rel: 'noopener', class: 'button' + - if dossier.justificatif_motivation.attached? + %li.inactive + %span.icon.justificatif + .dropdown-description + %h4 Justificatif + %p Ce justificatif joint par l’instructeur a été envoyé au demandeur. + = render partial: 'users/dossiers/show/download_justificatif', locals: { dossier: dossier } + + - if dossier.attestation.present? + %li + = link_to attestation_instructeur_dossier_path(dossier.procedure, dossier), target: '_blank', rel: 'noopener' do + %span.icon.preview + .dropdown-description + %h4 Voir l’attestation + %p Cette attestation a été envoyée automatiquement au demandeur. - %ul.dropdown-items.with-top-border %li = link_to repasser_en_instruction_instructeur_dossier_path(dossier.procedure, dossier), method: :post, data: { remote:true, confirm: "Voulez vous remettre le dossier #{dossier.id} en instruction ?" } do %span.icon.in-progress diff --git a/app/views/root/patron.html.haml b/app/views/root/patron.html.haml index 1e297d8cc..a55189955 100644 --- a/app/views/root/patron.html.haml +++ b/app/views/root/patron.html.haml @@ -16,6 +16,7 @@ %span.icon.bubble %span.icon.attachment %span.icon.lock + %span.icon.justificatif %span.icon.printer %span.icon.account %span.icon.person @@ -29,7 +30,9 @@ %span.icon.help %span.icon.phone %span.icon.clock + %span.icon.preview %span.icon.download + %span.icon.download-white %span.icon.move-handle %span.icon.frown %span.icon.meh diff --git a/app/views/users/dossiers/show/_status_overview.html.haml b/app/views/users/dossiers/show/_status_overview.html.haml index 945b18e63..50de64eda 100644 --- a/app/views/users/dossiers/show/_status_overview.html.haml +++ b/app/views/users/dossiers/show/_status_overview.html.haml @@ -62,7 +62,7 @@ - if dossier.attestation.present? .action = link_to attestation_dossier_path(dossier), target: '_blank', rel: 'noopener', class: 'button primary' do - %span.icon.download + %span.icon.download-white Télécharger l’attestation diff --git a/spec/factories/dossier.rb b/spec/factories/dossier.rb index 98cf72929..163109eac 100644 --- a/spec/factories/dossier.rb +++ b/spec/factories/dossier.rb @@ -145,6 +145,15 @@ FactoryBot.define do end end + trait :with_justificatif do + after(:create) do |dossier, _evaluator| + dossier.justificatif_motivation.attach( + io: StringIO.new('Hello World'), + filename: 'hello.txt' + ) + end + end + trait :with_all_champs do after(:create) do |dossier, _evaluator| dossier.champs = dossier.procedure.types_de_champ.map do |type_de_champ| diff --git a/spec/views/instructeur/dossiers/_state_button.html.haml_spec.rb b/spec/views/instructeur/dossiers/_state_button.html.haml_spec.rb index 32030a098..048b8b7bb 100644 --- a/spec/views/instructeur/dossiers/_state_button.html.haml_spec.rb +++ b/spec/views/instructeur/dossiers/_state_button.html.haml_spec.rb @@ -77,10 +77,10 @@ describe 'instructeurs/dossiers/state_button.html.haml', type: :view do end context 'with a motivation' do - let(:dossier) { create :dossier, state, motivation: 'Correspond au programme' } + let(:dossier) { create :dossier, state, :with_motivation } it 'displays the motivation text' do - expect(rendered).to have_content('Motivation') + expect(rendered).to have_dropdown_item('Motivation') expect(rendered).to have_content(dossier.motivation) end end @@ -89,10 +89,23 @@ describe 'instructeurs/dossiers/state_button.html.haml', type: :view do let(:dossier) { create :dossier, state, :with_attestation } it 'provides a link to the attestation' do - expect(rendered).to have_content('Attestation') + expect(rendered).to have_dropdown_item('Voir l’attestation') expect(rendered).to have_link(href: attestation_instructeur_dossier_path(dossier.procedure, dossier)) end end + + context 'with a justificatif' do + let(:dossier) do + dossier = create(:dossier, state, :with_justificatif) + dossier.justificatif_motivation.blob.update(metadata: dossier.justificatif_motivation.blob.metadata.merge(virus_scan_result: ActiveStorage::VirusScanner::SAFE)) + dossier + end + + it 'allows to download the justificatif' do + expect(rendered).to have_dropdown_item('Justificatif') + expect(rendered).to have_link(href: url_for(dossier.justificatif_motivation.attachment.blob)) + end + end end context 'accepte' do