From d31f4d4e25f9ad3e33633a25de8a02e4e60b5e83 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Fri, 18 Dec 2020 12:03:55 +0100 Subject: [PATCH 1/5] GraphQL: render api errors as json --- app/controllers/api/v2/graphql_controller.rb | 43 ++++++++++++++++---- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/v2/graphql_controller.rb b/app/controllers/api/v2/graphql_controller.rb index f25bf041d..34b564012 100644 --- a/app/controllers/api/v2/graphql_controller.rb +++ b/app/controllers/api/v2/graphql_controller.rb @@ -8,11 +8,11 @@ class API::V2::GraphqlController < API::V2::BaseController operation_name: params[:operationName]) render json: result - rescue => e + rescue => exception if Rails.env.development? - handle_error_in_development e + handle_error_in_development(exception) else - raise e + handle_error_in_production(exception) end end @@ -21,7 +21,12 @@ class API::V2::GraphqlController < API::V2::BaseController def process_action(*args) super rescue ActionDispatch::Http::Parameters::ParseError => exception - render status: 400, json: { errors: [{ message: exception.cause.message }] } + render json: { + errors: [ + { message: exception.cause.message } + ], + data: nil + }, status: 400 end # Handle form data, JSON body, or a blank value @@ -42,10 +47,32 @@ class API::V2::GraphqlController < API::V2::BaseController end end - def handle_error_in_development(e) - logger.error e.message - logger.error e.backtrace.join("\n") + def handle_error_in_development(exception) + logger.error exception.message + logger.error exception.backtrace.join("\n") - render json: { error: { message: e.message, backtrace: e.backtrace }, data: {} }, status: 500 + render json: { + errors: [ + { message: exception.message, backtrace: exception.backtrace } + ], + data: nil + }, status: 500 + end + + def handle_error_in_production(exception) + id = SecureRandom.uuid + Raven.capture_exception(exception, extra: { exception_id: id }) + + render json: { + errors: [ + { + message: "Internal Server Error", + extensions: { + exception: { id: id } + } + } + ], + data: nil + }, status: 500 end end From 7a8b1fa6390a38c2fd87d627d3b807d890521ab2 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 17 Dec 2020 18:03:35 +0100 Subject: [PATCH 2/5] [GraphQL] hide dossiers brouillon from api --- app/graphql/types/query_type.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index 4ed32c7ab..34ba29f5b 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -19,7 +19,7 @@ module Types end def dossier(number:) - Dossier.for_api_v2.find(number) + Dossier.state_not_brouillon.for_api_v2.find(number) rescue => e raise GraphQL::ExecutionError.new(e.message, extensions: { code: :not_found }) end From 2b06ee95e11e137ba0a7c62a6a9f3a789d25eaf5 Mon Sep 17 00:00:00 2001 From: kara Diaby Date: Thu, 17 Dec 2020 14:28:21 +0100 Subject: [PATCH 3/5] Add a method to retrieve all invited experts for all procedure dossiers --- app/models/avis.rb | 10 ++++++++++ spec/models/avis_spec.rb | 42 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/app/models/avis.rb b/app/models/avis.rb index ca532fefd..51da59ce1 100644 --- a/app/models/avis.rb +++ b/app/models/avis.rb @@ -56,6 +56,16 @@ class Avis < ApplicationRecord Avis.find_by(id: avis_id)&.email == email end + def self.invited_expert_emails(procedure) + Avis + .joins(dossier: :revision) + .left_joins(instructeur: :user) + .where(procedure_revisions: { procedure_id: procedure }) + .map(&:email_to_display) + .uniq + .sort + end + def spreadsheet_columns [ ['Dossier ID', dossier_id.to_s], diff --git a/spec/models/avis_spec.rb b/spec/models/avis_spec.rb index 7f04bcf58..37c156cc5 100644 --- a/spec/models/avis_spec.rb +++ b/spec/models/avis_spec.rb @@ -200,4 +200,46 @@ RSpec.describe Avis, type: :model do end end end + + describe '#invited_expert_emails' do + let!(:procedure) { create(:procedure, :published) } + + subject { Avis.invited_expert_emails(procedure) } + + context 'when there is one dossier' do + let!(:dossier) { create(:dossier, procedure: procedure) } + + context 'when a procedure has one avis and unknown instructeur' do + let!(:avis) { create(:avis, dossier: dossier, email: 'expert@expert.com') } + + it { is_expected.to eq(['expert@expert.com']) } + end + + context 'when a procedure has one avis and known instructeur' do + let!(:avis) { create(:avis, dossier: dossier, instructeur: create(:instructeur, email: 'expert@expert.com')) } + + it { is_expected.to eq(['expert@expert.com']) } + end + + context 'when a dossier has 2 avis from the same expert' do + let!(:avis) { create(:avis, dossier: dossier, email: 'expert@expert.com') } + let!(:avis2) { create(:avis, dossier: dossier, email: 'expert@expert.com') } + + it { is_expected.to eq(['expert@expert.com']) } + end + end + + context 'when there are two dossiers' do + let!(:dossier) { create(:dossier, procedure: procedure) } + let!(:dossier2) { create(:dossier, procedure: procedure) } + + context 'and each one has an avis from 3 different experts' do + let!(:avis) { create(:avis, dossier: dossier, instructeur: create(:instructeur, email: '2_expert@expert.com')) } + let!(:unaffected_avis) { create(:avis, dossier: dossier2, email: '3_expert@expert.com') } + let!(:unaffected_avis2) { create(:avis, dossier: dossier2, email: '1_expert@expert.com') } + + it { is_expected.to eq(['1_expert@expert.com', '2_expert@expert.com', '3_expert@expert.com']) } + end + end + end end From 8f6440f61570c3e5fd47de22a150d6634dda5217 Mon Sep 17 00:00:00 2001 From: kara Diaby Date: Fri, 18 Dec 2020 09:16:41 +0100 Subject: [PATCH 4/5] Admins can see the list of invited experts --- .../procedures_controller.rb | 7 +++- .../procedures/invited_expert_list.html.haml | 10 +++++ .../procedures/show.html.haml | 14 +++++++ config/routes.rb | 1 + .../invited_expert_list.html.haml_spec.rb | 41 +++++++++++++++++++ .../procedures/show.html.haml_spec.rb | 24 ++++++++++- 6 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 app/views/new_administrateur/procedures/invited_expert_list.html.haml create mode 100644 spec/views/new_administrateur/procedures/invited_expert_list.html.haml_spec.rb diff --git a/app/controllers/new_administrateur/procedures_controller.rb b/app/controllers/new_administrateur/procedures_controller.rb index 29cf33abc..728d2895b 100644 --- a/app/controllers/new_administrateur/procedures_controller.rb +++ b/app/controllers/new_administrateur/procedures_controller.rb @@ -1,6 +1,6 @@ module NewAdministrateur class ProceduresController < AdministrateurController - before_action :retrieve_procedure, only: [:champs, :annotations, :edit, :monavis, :update_monavis, :jeton, :update_jeton, :publication, :publish, :transfert, :allow_expert_review] + before_action :retrieve_procedure, only: [:champs, :annotations, :edit, :monavis, :update_monavis, :jeton, :update_jeton, :publication, :publish, :transfert, :allow_expert_review, :invited_expert_list] before_action :procedure_locked?, only: [:champs, :annotations] ITEMS_PER_PAGE = 25 @@ -185,6 +185,11 @@ module NewAdministrateur end end + def invited_expert_list + @invited_expert_emails = Avis.invited_expert_emails(@procedure) + redirect_to admin_procedure_path(@procedure) if @invited_expert_emails.blank? + end + private def apercu_tab diff --git a/app/views/new_administrateur/procedures/invited_expert_list.html.haml b/app/views/new_administrateur/procedures/invited_expert_list.html.haml new file mode 100644 index 000000000..4ce8cb52b --- /dev/null +++ b/app/views/new_administrateur/procedures/invited_expert_list.html.haml @@ -0,0 +1,10 @@ +.container + %h1.mt-2 Experts invités sur #{@procedure.libelle} + %table.table.mt-2 + %thead + %tr + %th Liste des experts + %tbody + - @invited_expert_emails.each do |expert| + %tr + %td= expert diff --git a/app/views/new_administrateur/procedures/show.html.haml b/app/views/new_administrateur/procedures/show.html.haml index 21ae54a9d..834fe6adf 100644 --- a/app/views/new_administrateur/procedures/show.html.haml +++ b/app/views/new_administrateur/procedures/show.html.haml @@ -156,6 +156,20 @@ .card-admin-action = link_to "#{@procedure.allow_expert_review? ? 'Désactiver' : 'Activer'}", allow_expert_review_admin_procedure_path(@procedure), method: :put, class: 'button' + - if @procedure.allow_expert_review? + .card-admin + %div + %span.icon.preview + %p.card-admin-status-todo À voir + + %div + %p.card-admin-title Liste des experts + %p.card-admin-subtitle Liste des experts invités par les instructeurs + + .card-admin-action + = link_to "Voir", invited_expert_list_admin_procedure_path(@procedure), class: 'button' + + .card-admin %div %span.icon.clock diff --git a/config/routes.rb b/config/routes.rb index cfa066dc7..f9a9f8131 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -379,6 +379,7 @@ Rails.application.routes.draw do get 'jeton' patch 'update_jeton' put :allow_expert_review + get 'invited_expert_list' end get 'publication' => 'procedures#publication', as: :publication diff --git a/spec/views/new_administrateur/procedures/invited_expert_list.html.haml_spec.rb b/spec/views/new_administrateur/procedures/invited_expert_list.html.haml_spec.rb new file mode 100644 index 000000000..ff575ed94 --- /dev/null +++ b/spec/views/new_administrateur/procedures/invited_expert_list.html.haml_spec.rb @@ -0,0 +1,41 @@ +describe 'new_administrateur/procedures/invited_expert_list.html.haml', type: :view do + let!(:procedure) { create(:procedure, :published) } + + before do + assign(:procedure, procedure) + assign(:procedure_lien, commencer_url(path: procedure.path)) + allow(view).to receive(:current_administrateur).and_return(procedure.administrateurs.first) + end + + subject { render } + + context 'when the procedure has 0 avis' do + let!(:dossier) { create(:dossier, procedure: procedure) } + before do + @invited_expert_emails = Avis.invited_expert_emails(procedure) + subject + end + + it 'has 0 experts into the page' do + expect(@invited_expert_emails.count).to eq(0) + expect(@invited_expert_emails).to eq([]) + end + end + + context 'when the procedure has 3 avis from 2 experts and 1 unasigned' do + let!(:dossier) { create(:dossier, procedure: procedure) } + let!(:avis) { create(:avis, dossier: dossier, instructeur: create(:instructeur, email: '1_expert@expert.com')) } + let!(:avis2) { create(:avis, dossier: dossier, instructeur: create(:instructeur, email: '2_expert@expert.com')) } + let!(:unasigned_avis) { create(:avis, dossier: dossier, email: 'expert@expert.com') } + + before do + @invited_expert_emails = Avis.invited_expert_emails(procedure) + subject + end + + it 'has 3 experts and match array' do + expect(@invited_expert_emails.count).to eq(3) + expect(@invited_expert_emails).to eq(['1_expert@expert.com', '2_expert@expert.com', 'expert@expert.com']) + end + end +end diff --git a/spec/views/new_administrateur/procedures/show.html.haml_spec.rb b/spec/views/new_administrateur/procedures/show.html.haml_spec.rb index f321f6e3b..2f8dd2c8e 100644 --- a/spec/views/new_administrateur/procedures/show.html.haml_spec.rb +++ b/spec/views/new_administrateur/procedures/show.html.haml_spec.rb @@ -44,13 +44,35 @@ describe 'new_administrateur/procedures/show.html.haml', type: :view do procedure.publish! procedure.close! procedure.reload - render end describe 'Re-enable button is visible' do + before do + render + end + it { expect(rendered).not_to have_css('#close-procedure-link') } it { expect(rendered).to have_css('#publish-procedure-link') } it { expect(rendered).to have_content('Réactiver') } end + + describe 'When procedure.allow_expert_review is true, the expert list card must be visible' do + before do + render + end + it { expect(procedure.allow_expert_review).to be_truthy } + it { expect(rendered).to have_content('Liste des experts invités par les instructeurs') } + end + + describe 'When procedure.allow_expert_review is false, the expert list card must not be visible' do + before do + procedure.update!(allow_expert_review: false) + procedure.reload + render + end + + it { expect(procedure.allow_expert_review).to be_falsy } + it { expect(rendered).not_to have_content('Liste des experts invités par les instructeurs') } + end end end From 0bd0fef8d5ddc0fa82d6f3bbea9b6d280674d260 Mon Sep 17 00:00:00 2001 From: kara Diaby Date: Mon, 4 Jan 2021 11:26:33 +0100 Subject: [PATCH 5/5] fixes regarding invited expert list --- .../procedures_controller.rb | 1 - .../procedures/invited_expert_list.html.haml | 22 +++++++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/app/controllers/new_administrateur/procedures_controller.rb b/app/controllers/new_administrateur/procedures_controller.rb index 728d2895b..2f250ae2e 100644 --- a/app/controllers/new_administrateur/procedures_controller.rb +++ b/app/controllers/new_administrateur/procedures_controller.rb @@ -187,7 +187,6 @@ module NewAdministrateur def invited_expert_list @invited_expert_emails = Avis.invited_expert_emails(@procedure) - redirect_to admin_procedure_path(@procedure) if @invited_expert_emails.blank? end private diff --git a/app/views/new_administrateur/procedures/invited_expert_list.html.haml b/app/views/new_administrateur/procedures/invited_expert_list.html.haml index 4ce8cb52b..6c1b82e64 100644 --- a/app/views/new_administrateur/procedures/invited_expert_list.html.haml +++ b/app/views/new_administrateur/procedures/invited_expert_list.html.haml @@ -1,10 +1,18 @@ .container %h1.mt-2 Experts invités sur #{@procedure.libelle} - %table.table.mt-2 - %thead - %tr - %th Liste des experts - %tbody - - @invited_expert_emails.each do |expert| + - if @invited_expert_emails.present? + %table.table.mt-2 + %thead %tr - %td= expert + %th Liste des experts + %tbody + - @invited_expert_emails.each do |expert| + %tr + %td + %span.icon.person + = expert + - else + .blank-tab + %h2.empty-text Aucun expert invité pour le moment. + %p.empty-text-details Les instructeurs de cette démarche n'ont pas encore fait appel aux experts. +