Merge pull request #5562 from betagouv/dev

2020-09-11-01
This commit is contained in:
LeSim 2020-09-11 15:26:56 +02:00 committed by GitHub
commit 408124d61c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 4206 additions and 184 deletions

4
.gitignore vendored
View file

@ -34,3 +34,7 @@ vendor/*
/yarn-error.log
yarn-debug.log*
.yarn-integrity
/docs
# Local Netlify folder
.netlify

View file

@ -454,7 +454,7 @@ GEM
ast (~> 2.4.1)
pdf-core (0.7.0)
pg (1.2.3)
phonelib (0.6.43)
phonelib (0.6.45)
prawn (2.2.2)
pdf-core (~> 0.7.0)
ttfunk (~> 1.5)

View file

@ -30,17 +30,16 @@ module Instructeurs
.reorder(nil)
.count
@all_dossiers_counts = {}
@all_dossiers_counts['à suivre'] = dossiers.without_followers.en_cours.count
@all_dossiers_counts['suivis'] = current_instructeur
.followed_dossiers
.joins(:groupe_instructeur)
.en_cours
.where(groupe_instructeur_id: groupe_ids)
.count
@all_dossiers_counts['traités'] = dossiers.termine.count
@all_dossiers_counts['dossiers'] = dossiers.all_state.count
@all_dossiers_counts['archivés'] = dossiers.archived.count
@all_dossiers_counts = {
'à suivre' => @dossiers_a_suivre_count_per_procedure.sum { |_, v| v },
'suivis' => @followed_dossiers_count_per_procedure.sum { |_, v| v },
'traités' => @dossiers_termines_count_per_procedure.sum { |_, v| v },
'dossiers' => @dossiers_count_per_procedure.sum { |_, v| v },
'archivés' => @dossiers_archived_count_per_procedure.sum { |_, v| v }
}
@procedure_ids_en_cours_with_notifications = current_instructeur.procedure_ids_with_notifications(:en_cours)
@procedure_ids_termines_with_notifications = current_instructeur.procedure_ids_with_notifications(:termine)
end
def show

View file

@ -20,5 +20,5 @@ class Champs::PhoneChamp < Champs::TextChamp
possible: true,
allow_blank: true,
message: I18n.t(:not_a_phone, scope: 'activerecord.errors.messages')
}
}, unless: -> { Phonelib.valid_for_country?(value, :pf) }
end

View file

@ -144,17 +144,14 @@ class Instructeur < ApplicationRecord
.with_notifications(self)
end
def procedures_with_notifications(scope)
dossiers = Dossier
def procedure_ids_with_notifications(scope)
groupe_instructeur_ids = Dossier
.send(scope) # :en_cours or :termine (or any other Dossier scope)
.merge(followed_dossiers)
.with_notifications(self)
.select(:groupe_instructeur_id)
Procedure
.where(id: dossiers.joins(:groupe_instructeur)
.select('groupe_instructeurs.procedure_id')
.distinct)
.distinct
GroupeInstructeur.where(id: groupe_instructeur_ids).pluck(:procedure_id)
end
def mark_tab_as_seen(dossier, tab)

View file

@ -1,63 +1,61 @@
%ul.procedure-list
- procedures.each do |p|
%li.procedure-item.flex.align-start
= link_to(instructeur_procedure_path(p)) do
.flex
%li.procedure-item.flex.align-start
= link_to(instructeur_procedure_path(p)) do
.flex
.procedure-logo{ style: "background-image: url(#{p.logo_url})" }
.procedure-logo{ style: "background-image: url(#{p.logo_url})" }
.procedure-details
%p.procedure-title
= procedure_libelle p
%ul.procedure-stats.flex
%li
%object
= link_to(instructeur_procedure_path(p, statut: 'a-suivre')) do
- a_suivre_count = dossiers_a_suivre_count_per_procedure[p.id] || 0
.stats-number
= number_with_html_delimiter(a_suivre_count)
.stats-legend
à suivre
%li
%object
= link_to(instructeur_procedure_path(p, statut: 'suivis')) do
- if current_instructeur.procedures_with_notifications(:en_cours).include?(p)
%span.notifications{ 'aria-label': "notifications" }
- followed_count = followed_dossiers_count_per_procedure[p.id] || 0
.stats-number
= number_with_html_delimiter(followed_count)
.stats-legend
= t('pluralize.followed', count: followed_count)
%li
%object
= link_to(instructeur_procedure_path(p, statut: 'traites')) do
- if current_instructeur.procedures_with_notifications(:termine).include?(p)
%span.notifications{ 'aria-label': "notifications" }
- termines_count = dossiers_termines_count_per_procedure[p.id] || 0
.stats-number
= number_with_html_delimiter(termines_count)
.stats-legend
= t('pluralize.processed', count: termines_count)
%li
%object
= link_to(instructeur_procedure_path(p, statut: 'tous')) do
- dossier_count = dossiers_count_per_procedure[p.id] || 0
.stats-number
= number_with_html_delimiter(dossier_count)
.stats-legend
= t('pluralize.case', count: dossier_count)
%li
%object
= link_to(instructeur_procedure_path(p, statut: 'archives')) do
- archived_count = dossiers_archived_count_per_procedure[p.id] || 0
.stats-number
= number_with_html_delimiter(archived_count)
.stats-legend
= t('pluralize.archived', count: archived_count)
.procedure-details
%p.procedure-title
= procedure_libelle p
%ul.procedure-stats.flex
%li
%object
= link_to(instructeur_procedure_path(p, statut: 'a-suivre')) do
- a_suivre_count = dossiers_a_suivre_count_per_procedure[p.id] || 0
.stats-number
= number_with_html_delimiter(a_suivre_count)
.stats-legend
à suivre
%li
%object
= link_to(instructeur_procedure_path(p, statut: 'suivis')) do
- if procedure_ids_en_cours_with_notifications.include?(p.id)
%span.notifications{ 'aria-label': "notifications" }
- followed_count = followed_dossiers_count_per_procedure[p.id] || 0
.stats-number
= number_with_html_delimiter(followed_count)
.stats-legend
= t('pluralize.followed', count: followed_count)
%li
%object
= link_to(instructeur_procedure_path(p, statut: 'traites')) do
- if procedure_ids_termines_with_notifications.include?(p.id)
%span.notifications{ 'aria-label': "notifications" }
- termines_count = dossiers_termines_count_per_procedure[p.id] || 0
.stats-number
= number_with_html_delimiter(termines_count)
.stats-legend
= t('pluralize.processed', count: termines_count)
%li
%object
= link_to(instructeur_procedure_path(p, statut: 'tous')) do
- dossier_count = dossiers_count_per_procedure[p.id] || 0
.stats-number
= number_with_html_delimiter(dossier_count)
.stats-legend
= t('pluralize.case', count: dossier_count)
%li
%object
= link_to(instructeur_procedure_path(p, statut: 'archives')) do
- archived_count = dossiers_archived_count_per_procedure[p.id] || 0
.stats-number
= number_with_html_delimiter(archived_count)
.stats-legend
= t('pluralize.archived', count: archived_count)
- if p.close?
.procedure-status
%span.label Close
- elsif p.depubliee?
.procedure-status
%span.label Dépubliée
- if p.close?
.procedure-status
%span.label Close
- elsif p.depubliee?
.procedure-status
%span.label Dépubliée

View file

@ -4,9 +4,14 @@
%h1.page-title Démarches
= render partial: 'instructeurs/procedures/synthese', locals: { procedures: @procedures, all_dossiers_counts: @all_dossiers_counts }
= render partial: 'instructeurs/procedures/list', locals: { procedures: @procedures,
dossiers_count_per_procedure: @dossiers_count_per_procedure,
dossiers_a_suivre_count_per_procedure: @dossiers_a_suivre_count_per_procedure,
dossiers_archived_count_per_procedure: @dossiers_archived_count_per_procedure,
dossiers_termines_count_per_procedure: @dossiers_termines_count_per_procedure,
followed_dossiers_count_per_procedure: @followed_dossiers_count_per_procedure }
%ul.procedure-list
= render partial: 'instructeurs/procedures/list',
collection: @procedures,
as: :p,
locals: { dossiers_count_per_procedure: @dossiers_count_per_procedure,
dossiers_a_suivre_count_per_procedure: @dossiers_a_suivre_count_per_procedure,
dossiers_archived_count_per_procedure: @dossiers_archived_count_per_procedure,
dossiers_termines_count_per_procedure: @dossiers_termines_count_per_procedure,
followed_dossiers_count_per_procedure: @followed_dossiers_count_per_procedure,
procedure_ids_en_cours_with_notifications: @procedure_ids_en_cours_with_notifications,
procedure_ids_termines_with_notifications: @procedure_ids_termines_with_notifications }

View file

@ -19,9 +19,13 @@ max_logo_width = body_width
max_logo_height = 50.mm
max_signature_size = 50.mm
title = @attestation.fetch(:title)
body = @attestation.fetch(:body)
footer = @attestation.fetch(:footer)
def normalize_pdf_text(text)
text&.tr("\t", ' ')
end
title = normalize_pdf_text(@attestation.fetch(:title))
body = normalize_pdf_text(@attestation.fetch(:body))
footer = normalize_pdf_text(@attestation.fetch(:footer))
created_at = @attestation.fetch(:created_at)
logo = @attestation[:logo]

View file

@ -225,7 +225,7 @@
.cta-panel-wrapper
%div
%h1.cta-panel-title Une question, un problème ?
%p.cta-panel-explanation Notre équipe est disponible pour vous renseigner et vous aider
%p.cta-panel-explanation Consultez notre FAQ
%div
%a.cta-panel-button-white{ rel: 'noopener noreferrer', href:'/contact-admin' }
Contactez-nous
%a.cta-panel-button-white{ rel: 'noopener noreferrer', href:"#{ FAQ_URL }" }
Voir la FAQ

View file

@ -43,7 +43,7 @@
%ul.numbers
%li.number
.number-value
= number_with_delimiter(Procedure.includes(:administrateurs).publiees_ou_closes.flat_map(&:administrateurs).uniq.count, :locale => :fr)
= number_with_delimiter(AdministrateursProcedure.joins(:procedure).merge(Procedure.publiees_ou_closes).select('distinct administrateur_id').count, :locale => :fr)
.number-label<
administrations
%br<>

View file

@ -38,6 +38,7 @@
"whatwg-fetch": "^3.0.0"
},
"devDependencies": {
"@2fd/graphdoc": "^2.4.0",
"babel-eslint": "^10.1.0",
"eclint": "^2.8.1",
"eslint": "^7.0.0",
@ -45,6 +46,7 @@
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-react": "^7.20.0",
"eslint-plugin-react-hooks": "^4.0.2",
"netlify-cli": "^2.61.2",
"prettier": "^2.0.5",
"webpack-bundle-analyzer": "^3.7.0",
"webpack-dev-server": "^3.11.0"
@ -52,9 +54,16 @@
"scripts": {
"lint:ec": "eclint check $({ git ls-files | grep -v app/graphql/schema.graphql ; find vendor -type f ; echo 'db/schema.rb' ; } | sort | uniq -u)",
"lint:js": "eslint ./app/javascript ./app/assets/javascripts ./config/webpack",
"webpack:build": "NODE_ENV=production bin/webpack"
"webpack:build": "NODE_ENV=production bin/webpack",
"graphql:docs:build": "graphdoc --force",
"graphql:docs:deploy": "netlify deploy -d ./docs/graphql --prod",
"graphql:docs:publish": "yarn graphql:docs:build && yarn graphql:docs:deploy"
},
"engines": {
"node": ">= 12.*"
},
"graphdoc": {
"endpoint": "https://www.demarches-simplifiees.fr/api/v2/graphql",
"output": "./docs/graphql"
}
}

View file

@ -698,6 +698,43 @@ describe Users::DossiersController, type: :controller do
expect(instructeur.reload.followed_dossiers.with_notifications(instructeur)).to eq([dossier.reload])
end
end
context 'when the champ is a phone number' do
let(:procedure) { create(:procedure, :published, :with_phone) }
let!(:dossier) { create(:dossier, :en_construction, user: user, procedure: procedure) }
let(:first_champ) { dossier.champs.first }
let(:now) { Time.zone.parse('01/01/2100') }
let(:submit_payload) do
{
id: dossier.id,
dossier: {
champs_attributes: [
{
id: first_champ.id,
value: value
}
]
}
}
end
context 'with a valid value sent as string' do
let(:value) { '0612345678' }
it 'updates the value' do
subject
expect(first_champ.reload.value).to eq('0612345678')
end
end
context 'with a valid value sent as number' do
let(:value) { '45187272'.to_i }
it 'updates the value' do
subject
expect(first_champ.reload.value).to eq('45187272')
end
end
end
end
describe '#index' do

View file

@ -182,6 +182,12 @@ FactoryBot.define do
end
end
trait :with_phone do
after(:build) do |procedure, _evaluator|
build(:type_de_champ_phone, procedure: procedure)
end
end
trait :published do
after(:build) do |procedure, _evaluator|
procedure.path = generate(:published_path)

View file

@ -13,7 +13,23 @@ RSpec.describe ApplicationJob, type: :job do
end
end
context 'when ::Excon::Error::BadRequest is raised' do
# https://api.rubyonrails.org/classes/ActiveJob/Exceptions/ClassMethods.html#method-i-retry_on
# retry on will try 5 times and then bubble up the error
it 'makes 5 attempts' do
assert_performed_jobs 5 do
ExconErrJob.perform_later rescue ::Excon::Error::BadRequest
end
end
end
class ChildJob < ApplicationJob
def perform; end
end
class ExconErrJob < ApplicationJob
def perform
raise ::Excon::Error::BadRequest.new('bad request')
end
end
end

View file

@ -20,6 +20,19 @@ describe Champs::PhoneChamp do
expect(build(:champ_phone, value: "+1(0) - 123456789")).to be_valid
expect(build(:champ_phone, value: "+49 2109 87654321")).to be_valid
expect(build(:champ_phone, value: "012345678")).to be_valid
# polynesian numbers should not return errors in any way
## landline numbers start with 40 or 45
expect(build(:champ_phone, value: "45187272")).to be_valid
expect(build(:champ_phone, value: "40 473 500")).to be_valid
expect(build(:champ_phone, value: "40473500")).to be_valid
expect(build(:champ_phone, value: "45473500")).to be_valid
## +689 is the international indicator
expect(build(:champ_phone, value: "+689 45473500")).to be_valid
expect(build(:champ_phone, value: "0145473500")).to be_valid
## polynesian mobile numbers start with 87, 88, 89
expect(build(:champ_phone, value: "87473500")).to be_valid
expect(build(:champ_phone, value: "88473500")).to be_valid
expect(build(:champ_phone, value: "89473500")).to be_valid
end
end
end

View file

@ -352,17 +352,17 @@ describe Instructeur, type: :model do
end
end
describe '#notifications_per_procedure' do
describe '#procedure_ids_with_notifications' do
let!(:dossier) { create(:dossier, :followed, state: Dossier.states.fetch(:en_construction)) }
let(:instructeur) { dossier.follows.first.instructeur }
let(:procedure) { dossier.procedure }
subject { instructeur.procedures_with_notifications(:en_cours) }
subject { instructeur.procedure_ids_with_notifications(:en_cours) }
context 'when there is a modification on public champs' do
before { dossier.update!(last_champ_updated_at: Time.zone.now) }
it { is_expected.to match([procedure]) }
it { is_expected.to match([procedure.id]) }
end
end

4108
yarn.lock

File diff suppressed because it is too large Load diff