Merge pull request #4572 from betagouv/dev

2019-11-25-01
This commit is contained in:
Keirua 2019-11-25 16:59:40 +01:00 committed by GitHub
commit 7953bd423d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 181 additions and 161 deletions

View file

@ -35,16 +35,6 @@
display: block;
font-weight: bold;
.notice {
@include notice-text-style;
display: block;
margin-top: $default-spacer;
p {
margin-bottom: $default-spacer;
}
}
&.required {
&::after {
color: $dark-red;
@ -53,6 +43,17 @@
}
}
.notice {
@include notice-text-style;
font-weight: bold;
margin-top: - $default-spacer;
margin-bottom: $default-padding;
p {
margin-bottom: $default-spacer;
}
}
.editable-champ {
position: relative;
@ -73,6 +74,7 @@
&.editable-champ-checkbox,
&.editable-champ-radio.vertical,
&.editable-champ-engagement {
p,
label {
padding-left: 28px;
}

View file

@ -9,7 +9,7 @@ class AdministrateurDashboard < Administrate::BaseDashboard
# on pages throughout the dashboard.
ATTRIBUTE_TYPES = {
id: Field::Number,
email: Field::String,
user: Field::HasOne.with_options(searchable: true, searchable_field: 'email'),
created_at: Field::DateTime,
updated_at: Field::DateTime,
procedures: Field::HasMany.with_options(limit: 20),
@ -24,7 +24,7 @@ class AdministrateurDashboard < Administrate::BaseDashboard
# By default, it's limited to four items to reduce clutter on index pages.
# Feel free to add, remove, or rearrange items.
COLLECTION_ATTRIBUTES = [
:email,
:user,
:created_at,
:procedures,
:registration_state
@ -34,7 +34,7 @@ class AdministrateurDashboard < Administrate::BaseDashboard
# an array of attributes that will be displayed on the model's show page.
SHOW_PAGE_ATTRIBUTES = [
:id,
:email,
:user,
:created_at,
:updated_at,
:registration_state,
@ -46,9 +46,7 @@ class AdministrateurDashboard < Administrate::BaseDashboard
# FORM_ATTRIBUTES
# an array of attributes that will be displayed
# on the model's form (`new` and `edit`) pages.
FORM_ATTRIBUTES = [
:email
].freeze
FORM_ATTRIBUTES = [].freeze
# Overwrite this method to customize how procedures are displayed
# across all pages of the admin dashboard.

View file

@ -9,7 +9,7 @@ class InstructeurDashboard < Administrate::BaseDashboard
# on pages throughout the dashboard.
ATTRIBUTE_TYPES = {
id: Field::Number,
email: Field::String,
user: Field::HasOne.with_options(searchable: true, searchable_field: 'email'),
created_at: Field::DateTime,
updated_at: Field::DateTime,
current_sign_in_at: Field::DateTime,
@ -24,7 +24,7 @@ class InstructeurDashboard < Administrate::BaseDashboard
# By default, it's limited to four items to reduce clutter on index pages.
# Feel free to add, remove, or rearrange items.
COLLECTION_ATTRIBUTES = [
:email,
:user,
:created_at
].freeze
@ -34,7 +34,7 @@ class InstructeurDashboard < Administrate::BaseDashboard
:procedures,
:dossiers,
:id,
:email,
:user,
:current_sign_in_at,
:created_at,
:features

View file

@ -25,4 +25,10 @@ module ChampHelper
end
simple_format(auto_linked_text, {}, sanitize: false)
end
def describedby_id(champ)
if champ.description.present?
"desc-#{champ.type_de_champ.id}-#{champ.row}"
end
end
end

View file

@ -13,10 +13,10 @@ class ActiveStorage::DownloadableFile
def self.create_list_from_dossier(dossier)
pjs = PiecesJustificativesService.liste_pieces_justificatives(dossier)
pjs.map do |pj|
pjs.map do |piece_justificative|
[
ActiveStorage::DownloadableFile.new(pj.piece_justificative_file),
pj.piece_justificative_file.filename.to_s
ActiveStorage::DownloadableFile.new(piece_justificative),
piece_justificative.filename.to_s
]
end
end

View file

@ -30,4 +30,10 @@ class Service < ApplicationRecord
service_cloned.administrateur = administrateur
service_cloned
end
def telephone_url
if telephone.present?
"tel:#{telephone.gsub(/[[:blank:]]/, '')}"
end
end
end

View file

@ -1,17 +1,21 @@
class PiecesJustificativesService
def self.liste_pieces_justificatives(dossier)
pjs_commentaires = dossier.commentaires
.map(&:piece_jointe)
.filter(&:attached?)
champs_blocs_repetables = dossier.champs
.filter { |c| c.type_champ == TypeDeChamp.type_champs.fetch(:repetition) }
.flat_map(&:champs)
champs_pieces_justificatives_with_attachments(
pjs_commentaires + champs_pieces_justificatives_with_attachments(
champs_blocs_repetables + dossier.champs
)
end
def self.pieces_justificatives_total_size(dossier)
liste_pieces_justificatives(dossier)
.sum { |pj| pj.piece_justificative_file.byte_size }
.sum(&:byte_size)
end
def self.serialize_types_de_champ_as_type_pj(procedure)
@ -48,5 +52,6 @@ class PiecesJustificativesService
champs
.filter { |c| c.type_champ == TypeDeChamp.type_champs.fetch(:piece_justificative) }
.filter { |pj| pj.piece_justificative_file.attached? }
.map(&:piece_justificative_file)
end
end

View file

@ -41,8 +41,7 @@
%h2.header-section
Créer une nouvelle démarche à partir d'une démarche existante
%label
.notice
%p.notice
Pour rechercher dans cette liste, utilisez la fonction "Recherche" de votre navigateur (CTRL+F ou command+F)
%table.table.vertical.procedure-library-list

View file

@ -11,12 +11,11 @@
.explication
Configurez sur cette page les notifications que vous souhaitez recevoir par email pour cette démarche.
= form.label :email_notification do
Recevoir une notification quotidienne
= form.label :email_notification, "Recevoir une notification quotidienne"
%span.notice
%p.notice
Cet email vous signale le dépôt de nouveaux dossiers sur cette démarche, ou des changements sur vos dossiers suivis.
%span.notice
%p.notice
Il est envoyé une fois par jour, du lundi au samedi, vers 10 h du matin.
.radios
@ -28,11 +27,10 @@
= form.radio_button :email_notifications_enabled, false
Non
= form.label nil do
Recevoir un récapitulatif hebdomadaire
%span.notice
= form.label nil, "Recevoir un récapitulatif hebdomadaire"
%p.notice
Cet email récapitule lactivité de la semaine sur lensemble de vos démarches.
%span.notice
%p.notice
Il est envoyé chaque semaine le lundi matin, et nest pas désactivable.
.radios

View file

@ -1,6 +1,6 @@
.dropdown.header-menu-opener
%button.button.dropdown-button.header-menu-button
= image_tag "icons/account-circle.svg", title: "Mon compte"
%button.button.dropdown-button.header-menu-button{ title: "Mon compte" }
= image_tag "icons/account-circle.svg", alt: ''
%ul.header-menu.dropdown-content
%li
.menu-item{ title: current_email }

View file

@ -28,7 +28,7 @@
= link_to service.email, "mailto:#{service.email}"
%br
Par téléphone :
= link_to service.telephone, "tel:#{service.telephone}"
= link_to service.telephone, service.telephone_url
%br
Horaires : #{ formatted_horaires(service.horaires) }

View file

@ -11,7 +11,7 @@
= f.label :routing_criteria_name do
Libellé du routage
%span.notice Ce texte apparaitra sur le formulaire usager comme le libellé d'une liste
%p.notice Ce texte apparaitra sur le formulaire usager comme le libellé d'une liste
= f.text_field :routing_criteria_name, placeholder: 'ex. Votre ville', required: true
= f.submit 'Renommer', class: 'button primary send'
@ -21,7 +21,7 @@
= form_for :groupe_instructeur, html: { class: 'form' } do |f|
= f.label :label do
Ajouter un groupe
%span.notice Ce groupe sera un choix de la liste « #{@procedure.routing_criteria_name} » .
%p.notice Ce groupe sera un choix de la liste « #{@procedure.routing_criteria_name} » .
= f.text_field :label, placeholder: 'ex. Ville de Bordeaux', required: true
= f.submit 'Ajouter le groupe', class: 'button primary send'

View file

@ -4,6 +4,6 @@
remote: true do |f|
= f.label :email do
Ajouter un administrateur
%span.notice= "Renseignez lemail dun administrateur déjà enregistré sur demarches-simplifiees.fr pour lui permettre de modifier « #{procedure.libelle} »."
%p.notice Renseignez lemail dun administrateur déjà enregistré sur demarches-simplifiees.fr pour lui permettre de modifier « #{procedure.libelle} ».
= f.email_field :email, placeholder: 'marie.dupont@exemple.fr', required: true
= f.submit 'Ajouter comme administrateur', class: 'button primary send'

View file

@ -25,13 +25,13 @@
= f.label :duree_conservation_dossiers_dans_ds do
Sur demarches-simplifiees.fr
%span.mandatory *
.notice (durée en mois après le début de linstruction)
%p.notice (durée en mois après le début de linstruction)
= f.number_field :duree_conservation_dossiers_dans_ds, class: 'form-control', placeholder: '6', required: true
= f.label :duree_conservation_dossiers_hors_ds do
Hors demarches-simplifiees.fr
%span.mandatory *
.notice (durée en mois après la fin de l'instruction)
%p.notice (durée en mois après la fin de l'instruction)
= f.number_field :duree_conservation_dossiers_hors_ds, class: 'form-control', placeholder: '6', required: true
- if @procedure.created_at.present?
@ -43,9 +43,7 @@
Cadre juridique
%span.mandatory *
= f.label :cadre_juridique do
.notice
%p
%p.notice
Le cadre juridique justifie le droit de collecter les données demandées dans votre démarche auprès des usagers. Par exemple :
%br
 Texte de loi (loi, décret, circulaire, arrêté…)
@ -53,9 +51,11 @@
 Texte juridique (statuts, délibération, décision du conseil d'administration…)
%br
= link_to("En savoir plus avec cette vidéo de 5 minutes", CADRE_JURIDIQUE_URL, target: "_blank", rel: "noopener")
%p
%p.notice
Vous pouvez saisir un lien web vers ce texte, ou limporter depuis un fichier.
Lien vers le texte
= f.label :cadre_juridique, 'Lien vers le texte'
= f.text_field :cadre_juridique, class: 'form-control', placeholder: 'https://www.legifrance.gouv.fr/'
= f.label :deliberation, 'Importer le texte'
@ -64,14 +64,13 @@
attached_file: @procedure.deliberation,
user_can_destroy: true }
%h2.header-section
Notice explicative de la démarche
%h2.header-section Notice explicative de la démarche
- notice = @procedure.notice
= f.label :notice do
.notice
%p
%p.notice
Une notice explicative est un document destiné à guider lusager dans sa démarche. Cest un document que vous avez élaboré et qui peut prendre la forme dun fichier doc, dun pdf ou encore de diapositives. Le bouton pour télécharger cette notice apparaît en haut du formulaire pour lusager.
= f.label :notice, 'Notice'
- notice = @procedure.notice
= render 'shared/attachment/edit',
{ form: f,
attached_file: @procedure.notice,
@ -82,15 +81,14 @@
.editable-champ.editable-champ-radio.vertical
= f.label :for_individual, value: true do
Ma démarche sadresse à un particulier
%span.notice
%p En choisissant cette option, lusager devra renseigner son nom et prénom avant daccéder au formulaire
%p.notice En choisissant cette option, lusager devra renseigner son nom et prénom avant daccéder au formulaire
= f.radio_button :for_individual, true
.editable-champ.editable-champ-radio.vertical
= f.label :for_individual, value: false do
Ma démarche sadresse à une personne morale
%span.notice
%p En choisissant cette option, lusager devra renseigner son n° SIRET.<br>Grâce à lAPI Entreprise, les informations sur la personne morale (raison sociale, adresse du siège, etc.) seront automatiquement renseignées.
%p.notice
En choisissant cette option, lusager devra renseigner son n° SIRET.<br>Grâce à lAPI Entreprise, les informations sur la personne morale (raison sociale, adresse du siège, etc.) seront automatiquement renseignées.
= f.radio_button :for_individual, false
%p.explication
@ -103,8 +101,7 @@
- if feature_enabled?(:administrateur_web_hook)
= f.label :web_hook_url do
Lien de rappel HTTP (webhook)
.notice
%p
%p.notice
Vous pouvez définir un lien de rappel HTTP (aussi appelé webhook) pour notifier un service tiers du changement de l'état dun dossier de cette démarche sur demarches-simplifiees.fr.
= link_to("Consulter la documentation du webhook", WEBHOOK_DOC_URL, target: "_blank", rel: "noopener")
= f.text_field :web_hook_url, class: 'form-control', placeholder: 'https://callback.exemple.fr/'

View file

@ -54,16 +54,13 @@
%h2.header-section Bouton radio verticaux
.editable-champ.editable-champ-radio.vertical
= f.label :archived, value: true do
Option A
%span.notice
%p Une option tout à fait valable.
= f.label :archived, 'Option A', value: true
%p.notice Une option tout à fait valable.
= f.radio_button :archived, true
.editable-champ.editable-champ-radio.vertical
= f.label :archived, value: false do
Option B
%span.notice
%p Une autre option, pas mal non plus.
= f.label :archived, 'Option B', value: false
%p.notice Une autre option, pas mal non plus.
= f.radio_button :archived, false
.send-wrapper

View file

@ -1,4 +1,4 @@
= form.label champ.main_value_name, { class: champ.repetition? ? 'header-section' : '' } do
= form.label champ.main_value_name do
#{champ.libelle}
- if champ.mandatory?
%span.mandatory *
@ -8,4 +8,4 @@
= "modifié le #{try_format_datetime(champ.updated_at)}"
- if champ.description.present?
%span.notice= string_to_html(champ.description)
.notice{ id: describedby_id(champ) }= string_to_html(champ.description)

View file

@ -1,4 +1,3 @@
= form.date_field :value,
value: champ.value,
placeholder: 'JJ/MM/AAAA',
required: champ.mandatory?

View file

@ -1,5 +1,7 @@
.editable-champ{ class: "editable-champ-#{champ.type_champ}" }
- if has_label?(champ)
- if champ.repetition?
= render partial: 'shared/dossiers/editable_champs/header_section', locals: { champ: champ }
- elsif has_label?(champ)
= render partial: 'shared/dossiers/editable_champs/champ_label', locals: { form: form, champ: champ, seen_at: defined?(seen_at) ? seen_at : nil }
= render partial: "shared/dossiers/editable_champs/#{champ.type_champ}",

View file

@ -1,3 +1,4 @@
= form.text_field :value,
placeholder: champ.libelle,
required: champ.mandatory?
required: champ.mandatory?,
aria: { describedby: describedby_id(champ) }

View file

@ -5,10 +5,10 @@
= f.text_area :body, rows: 5, placeholder: placeholder, required: true, class: 'message-textarea'
.flex.justify-between.wrap
%div
= f.label :piece_jointe, for: :piece_jointe do
Joindre un document
%span.notice (taille max : 20 Mo)
= f.file_field :piece_jointe, id: 'piece_jointe', direct_upload: true
%label{ for: :piece_jointe }
%span.notice
(taille max : 20 Mo)
%div
= f.submit 'Envoyer le message', class: 'button primary send', data: { disable: true }

View file

@ -9,7 +9,7 @@
= link_to service.email, "mailto:#{service.email}"
%p.help-dropdown-service-item
%span.icon.small.phone
= link_to service.telephone, "tel:#{service.telephone}"
= link_to service.telephone, service.telephone_url
%p.help-dropdown-service-item
%span.icon.small.clock
= service.horaires

View file

@ -3,8 +3,9 @@
- service = procedure.service
- if service.present?
.footer-row.footer-columns
%ul.footer-column
.footer-column
%p.footer-header Cette démarche est gérée par :
%ul
%li
= service.nom
%br
@ -12,8 +13,9 @@
%br
= string_to_html(service.adresse, wrapper_tag = 'span')
%ul.footer-column
.footer-column
%p.footer-header Poser une question sur votre dossier :
%ul
%li
- if dossier.present? && dossier.messagerie_available?
Directement
@ -24,7 +26,7 @@
%li
Par téléphone :
%a{ href: "tel:#{service.telephone}" }= service.telephone
= link_to service.telephone, service.telephone_url
%li
- horaires = "Horaires : #{formatted_horaires(service.horaires)}"
@ -33,8 +35,9 @@
- politiques = politiques_conservation_de_donnees(procedure)
- if politiques.present?
%ul.footer-column
.footer-column
%p.footer-header Conservation des données :
%ul
- politiques.each do |politique|
%li= politique

View file

@ -9,7 +9,7 @@ FactoryBot.define do
end
trait :with_file do
file { Rack::Test::UploadedFile.new("./spec/fixtures/files/logo_test_procedure.png", 'image/png') }
piece_jointe { Rack::Test::UploadedFile.new("./spec/fixtures/files/logo_test_procedure.png", 'image/png') }
end
end
end

View file

@ -19,33 +19,36 @@ feature 'The routing', js: true do
click_on "Groupe d'instructeurs"
# rename routing criteria to spécialité
fill_in 'procedure_routing_criteria_name', with: 'spécialité'
fill_in 'Libellé du routage', with: 'spécialité'
click_on 'Renommer'
expect(procedure.reload.routing_criteria_name).to eq('spécialité')
expect(page).to have_text('Le libellé est maintenant « spécialité ».')
expect(page).to have_field('Libellé du routage', with: 'spécialité')
# rename defaut groupe to littéraire
click_on 'voir'
expect(page).to have_css('#groupe_instructeur_label')
2.times { find(:css, "#groupe_instructeur_label").set("littéraire") }
fill_in 'Nom du groupe', with: 'littéraire'
click_on 'Renommer'
expect(procedure.defaut_groupe_instructeur.reload.label).to eq('littéraire')
expect(page).to have_text('Le nom est à présent « littéraire ».')
expect(page).to have_field('Nom du groupe', with: 'littéraire')
# add victor to littéraire groupe
try_twice { find('input.select2-search__field').send_keys('victor@inst.com', :enter) }
find('input.select2-search__field').send_keys('victor@inst.com', :enter)
perform_enqueued_jobs { click_on 'Affecter' }
expect(page).to have_text("Linstructeur victor@inst.com a été affecté")
victor = User.find_by(email: 'victor@inst.com').instructeur
click_on "Groupes dinstructeurs"
# add scientifique groupe
fill_in 'groupe_instructeur_label', with: 'scientifique'
click_on 'Groupes dinstructeurs'
fill_in 'Ajouter un groupe', with: 'scientifique'
click_on 'Ajouter le groupe'
expect(page).to have_text('Le groupe dinstructeurs « scientifique » a été créé.')
# add marie to scientifique groupe
try_twice { find('input.select2-search__field').send_keys('marie@inst.com', :enter) }
find('input.select2-search__field').send_keys('marie@inst.com', :enter)
perform_enqueued_jobs { click_on 'Affecter' }
expect(page).to have_text("Linstructeur marie@inst.com a été affecté")
marie = User.find_by(email: 'marie@inst.com').instructeur
# publish
@ -93,11 +96,10 @@ feature 'The routing', js: true do
log_out
# litteraire_user change its dossier
visit root_path
click_on 'Connexion'
visit new_user_session_path
sign_in_with litteraire_user.email, password
click_on litteraire_user.dossiers.first.id
click_on litteraire_user.dossiers.first.id.to_s
click_on 'Modifier mon dossier'
fill_in 'dossier_champs_attributes_0_value', with: 'some value'
@ -105,29 +107,32 @@ feature 'The routing', js: true do
log_out
# the litteraires instructeurs should have a notification
visit root_path
click_on 'Connexion'
visit new_user_session_path
sign_in_with victor.user.email, password
## on the procedures list
visit instructeur_procedures_path
expect(page).to have_css("span.notifications")
expect(page).to have_current_path(instructeur_procedures_path)
expect(find('.procedure-stats')).to have_css('span.notifications')
## on the dossiers list
click_on procedure.libelle
expect(page).to have_css("span.notifications")
expect(page).to have_current_path(instructeur_procedure_path(procedure))
expect(find('.tabs')).to have_css('span.notifications')
## on the dossier itself
click_on 'suivi'
click_on litteraire_user.email
expect(page).to have_css("span.notifications")
expect(page).to have_current_path(instructeur_dossier_path(procedure, litteraire_user.dossiers.first))
expect(page).to have_text('Annotations privées') # ensure Turbolinks DID load the DOM content
expect(find('.tabs')).to have_css('span.notifications')
log_out
# the scientifiques instructeurs should not have a notification
login_as marie.user, scope: :user
visit instructeur_procedures_path
expect(page).not_to have_css("span.notifications")
visit new_user_session_path
sign_in_with marie.user.email, password
expect(page).to have_current_path(instructeur_procedures_path)
expect(find('.procedure-stats')).not_to have_css('span.notifications')
log_out
end
@ -136,7 +141,7 @@ feature 'The routing', js: true do
find('#publish-procedure').click
within '#publish-modal' do
fill_in 'lien_site_web', with: 'http://some.website'
click_on 'publish'
click_on 'Publier'
end
expect(page).to have_text('Démarche publiée')
@ -154,6 +159,7 @@ feature 'The routing', js: true do
select(groupe, from: 'dossier_groupe_instructeur_id')
click_on 'Déposer le dossier'
expect(page).to have_text('Merci')
log_out
end
@ -166,31 +172,18 @@ feature 'The routing', js: true do
visit "users/activate?#{token_params}"
fill_in :user_password, with: password
click_button 'Définir le mot de passe'
expect(page).to have_content 'Mot de passe enregistré'
expect(page).to have_text('Mot de passe enregistré')
end
def log_out(old_layout: false)
if old_layout
expect(page).to have_content('Se déconnecter')
click_on 'Se déconnecter'
else
try_twice do
expect(page).to have_css('[title="Mon compte"]')
find('[title="Mon compte"]').click
expect(page).to have_content('Se déconnecter')
click_button(title: 'Mon compte')
click_on 'Se déconnecter'
end
end
end
def try_twice
begin
yield
rescue Selenium::WebDriver::Error::ElementNotInteractableError, Capybara::ElementNotFound
yield
end
expect(page).to have_current_path(root_path)
end
end

View file

@ -24,5 +24,19 @@ describe ActiveStorage::DownloadableFile do
expect(list.size).to eq(4)
end
end
context 'when there is a message with no attachment' do
let(:commentaire) { create(:commentaire) }
let(:dossier) { commentaire.dossier }
it { expect(list.length).to be 0 }
end
context 'when there is a message with an attachment' do
let(:commentaire) { create(:commentaire, :with_file) }
let(:dossier) { commentaire.dossier }
it { expect(list.length).to be 1 }
end
end
end