Merge pull request #3501 from betagouv/dev

2019-02-25
This commit is contained in:
LeSim 2019-02-25 13:45:48 +01:00 committed by GitHub
commit b851d821e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 285 additions and 56 deletions

View file

@ -8,7 +8,7 @@ gem 'administrate'
gem 'after_party'
gem 'axlsx', '~> 3.0.0.pre' # https://github.com/randym/axlsx/issues/501#issuecomment-373640365
gem 'bcrypt'
gem 'bootstrap-sass', '~> 3.3.5'
gem 'bootstrap-sass', '>= 3.4.1'
gem 'bootstrap-wysihtml5-rails', '~> 0.3.3.8'
gem 'browser'
gem 'carrierwave'

View file

@ -101,9 +101,9 @@ GEM
axlsx (>= 2.0, < 4)
bcrypt (3.1.12)
bindata (2.4.4)
bootstrap-sass (3.3.7)
bootstrap-sass (3.4.1)
autoprefixer-rails (>= 5.2.1)
sass (>= 3.3.4)
sassc (>= 2.0.0)
bootstrap-wysihtml5-rails (0.3.3.8)
railties (>= 3.0)
brakeman (4.3.1)
@ -652,7 +652,7 @@ DEPENDENCIES
after_party
axlsx (~> 3.0.0.pre)
bcrypt
bootstrap-sass (~> 3.3.5)
bootstrap-sass (>= 3.4.1)
bootstrap-wysihtml5-rails (~> 0.3.3.8)
brakeman
browser

View file

@ -80,6 +80,8 @@ Pour mettre à jour votre environnement de développement, installer les nouvell
### Exécution des tests (RSpec)
Les tests ont besoin de leur propre base de données et certains d'entre eux utilisent Selenium pour s'exécuter dans un navigateur. N'oubliez pas de créer la base de test et d'installer chrome et chromedriver pour exécuter tous les tests.
Pour exécuter les tests de l'application, plusieurs possibilités :
- Lancer tous les tests

View file

@ -33,4 +33,8 @@
margin-bottom: $default-spacer;
}
}
p:not(:last-of-type) {
margin-bottom: $default-spacer;
}
}

View file

@ -1,7 +1,7 @@
@import "colors";
.patron {
p {
.patron-section {
margin-bottom: 20px;
}

View file

@ -1,6 +1,16 @@
#switch-menu {
position: fixed;
left: 10px;
bottom: 10px;
z-index: 300;
color: #FFFFFF;
list-style: none;
text-decoration: none;
padding-left: 20px;
}
#switch-menu a,
#switch-menu a:link,
#switch-menu a:visited,
#switch-menu a:hover {
text-decoration: none;
color: #FFFFFF;
}

View file

@ -67,7 +67,7 @@ class Admin::ProceduresController < AdminController
end
def create
@procedure = Procedure.new(procedure_params)
@procedure = current_administrateur.admin_procedures.build(procedure_params)
@path = @procedure.path
@availability = Procedure.path_availability(current_administrateur, @procedure.path)

View file

@ -53,7 +53,7 @@ class SupportController < ApplicationController
phone: params[:phone],
text: params[:text],
file: params[:file],
dossier_id: params[:dossier_id],
dossier_id: dossier&.id,
browser: browser_name,
tags: tags
).send_form

View file

@ -0,0 +1,18 @@
import { show, hide, delegate } from '@utils';
delegate('change', '#contact-form #type', event => {
const type = event.target.value;
const answer = document.querySelector(`[data-answer="${type}"]`);
const card = document.querySelector('.support.card');
for (let element of document.querySelectorAll('.card-content')) {
hide(element);
}
if (answer) {
show(card);
show(answer);
} else {
hide(card);
}
});

View file

@ -14,11 +14,12 @@ import '../shared/remote-input';
import '../shared/franceconnect';
import '../shared/toggle-target';
import '../new_design/spinner';
import '../new_design/carto';
import '../new_design/dropdown';
import '../new_design/form-validation';
import '../new_design/carto';
import '../new_design/select2';
import '../new_design/spinner';
import '../new_design/support';
import '../new_design/champs/carte';
import '../new_design/champs/linked-drop-down-list';

View file

@ -49,7 +49,7 @@ class Champs::PieceJustificativeChamp < Champ
end
def for_api
if piece_justificative_file.attached?
if piece_justificative_file.attached? && virus_scan&.safe?
Rails.application.routes.url_helpers.url_for(piece_justificative_file)
end
end

View file

@ -40,6 +40,12 @@ module TagsSubstitutionConcern
description: '',
target: :id,
available_for_states: Dossier::SOUMIS
},
{
libelle: 'nom du service',
description: 'Le nom du service instructeur qui traite le dossier',
lambda: -> (d) { d.procedure.organisation_name || '' },
available_for_states: Dossier::SOUMIS
}
]

View file

@ -189,7 +189,7 @@ class Procedure < ApplicationRecord
end
def clone(admin, from_library)
is_different_admin = self.administrateur_id != admin.id
is_different_admin = !admin.owns?(self)
populate_champ_stable_ids
procedure = self.deep_clone(include:
@ -214,6 +214,12 @@ class Procedure < ApplicationRecord
procedure.types_de_champ.each { |tdc| tdc.options&.delete(:old_pj) }
end
if is_different_admin
procedure.administrateurs = [admin]
else
procedure.administrateurs = administrateurs
end
procedure.administrateur = admin
procedure.initiated_mail = initiated_mail&.dup
procedure.received_mail = received_mail&.dup

View file

@ -6,9 +6,25 @@
.container.demande
%h1 Demande de compte administrateur
.card
.card-title
Vous souhaitez seulement compléter une démarche sur notre site ?
%p
Vous n'avez pas besoin de compte administrateur !
%p
Cliquez plutôt sur le
%strong lien direct
vers votre démarche que doit vous communiquer l'administration par exemple <strong>https://www.demarches-simplifiees.fr/commencer/NOM_DE_LA_DEMARCHE</strong>.
%p
Vous pouvez aussi consulter la
= succeed '.' do
= link_to "liste des démarches disponibles", "https://doc.demarches-simplifiees.fr/listes-des-demarches"
%p.intro Attention, la création de compte administrateur est réservée <b>uniquement aux organismes publics</b>. Elle ne concerne ni les particuliers, ni les entreprises, ni les associations (sauf celles reconnues d'utilité publique), ni les personnes souhaitant remplir un dossier ou faire une démarche en ligne. Ce compte vous permettra de créer des démarches sur demarches-simplifiees.fr, vous pourrez ensuite les diffuser en ligne auprès de vos usagers.
%p.intro Pour obtenir un compte administrateur sur demarches-simplifiees.fr, veuillez remplir le formulaire ci-dessous et un membre de notre équipe vous contactera dès que possible.
%p.intro Tous les champs sont obligatoires.
%p.intro <b>Si vous souhaitez seulement compléter une démarche sur notre site, vous n'avez pas besoin de compte administrateur!</b>
%hr

View file

@ -1,25 +1,14 @@
- if SwitchDeviseProfileService.new(warden).multiple_devise_profile_connect?
#switch-menu.dropdown.dropup
%button.btn.btn-default.dropdown-toggle{ type: :button, 'data-toggle' => 'dropdown', 'aria-haspopup' => true, 'aria-expanded' => false }
%i.fa.fa-toggle-on
%span.caret
%ul.dropdown-menu.dropdown-menu-left
- if user_signed_in?
%li
= link_to(dossiers_path, id: :menu_item_procedure) do
%i.fa.fa-user
&nbsp;
Usager
- if gestionnaire_signed_in?
%li
= link_to(gestionnaire_procedures_path) do
%i.fa.fa-user
&nbsp;
Instructeur
- if administrateur_signed_in?
%li
= link_to(admin_procedures_path) do
%i.fa.fa-user
&nbsp;
Administrateur
%ul#switch-menu
%li
Changer de rôle
- if user_signed_in?
%li
= link_to(dossiers_path, id: :menu_item_procedure, title: 'Aller dans votre espace usager. Vous pourrez revenir ici ensuite') do
%i.fa.fa-users
&nbsp; Usager
- if gestionnaire_signed_in?
%li
= link_to(gestionnaire_procedures_path, title: 'Aller dans votre espace instructeur. Vous pourrez revenir ici ensuite.') do
%i.fa.fa-user
&nbsp; Instructeur

View file

@ -48,6 +48,4 @@
%h1
%i.fa.fa-times{ style: 'position: fixed; top: 10; right: 30; color: white;' }
= render partial: 'layouts/switch_devise_profile_module'
= render partial: 'layouts/footer', locals: { main_container_size: main_container_size }

View file

@ -31,6 +31,7 @@
= current_administrateur.procedures.archivees.count
.split-hr-left
= render partial: 'layouts/switch_devise_profile_module'
#infos-block

View file

@ -46,7 +46,7 @@
%h1 Boutons
%p
.patron-section
= link_to ".button", "#", class: "button"
= link_to ".button.primary", "#", class: "button primary"
@ -62,7 +62,7 @@
= link_to "#", class: "button icon-only" do
%span.icon.follow
%p
.patron-section
%button.button{ disabled: true } .button.disabled
%button.button.primary{ disabled: true } .button.primary.disabled
@ -71,24 +71,24 @@
%button.button.danger{ disabled: true } .button.danger.disabled
%p
.patron-section
= link_to ".button.accepted", "#", class: "button accepted"
= link_to ".button.refused", "#", class: "button refused"
= link_to ".button.without-continuation", "#", class: "button without-continuation"
%p
.patron-section
= link_to ".button.small", "#", class: "button small"
= link_to ".button.small.primary", "#", class: "button small primary"
%p
.patron-section
= link_to ".button.large", "#", class: "button large"
= link_to ".button.large.primary", "#", class: "button large primary"
%p
.patron-section
= link_to ".button.primary.expand", "#", class: "button primary expand"
%h1 Labels
@ -111,17 +111,17 @@
.card
.card-title
Titre de la carte
Et voici le contenu de la carte
%p Et voici le contenu de la carte
.card.featured
.card-title
Titre de la carte mise en avant
Et voici le contenu de la carte
%p Et voici le contenu de la carte
.card.feedback
.card-title
Titre de la carte pour demander un avis
Utilisez cette carte pour informer dune nouveauté produit ou demander lavis des utilisateurs.
%p Utilisez cette carte pour informer dune nouveauté produit ou demander lavis des utilisateurs.
%h1 Table

View file

@ -1,12 +1,12 @@
- pj = champ.piece_justificative_file
.pj-link
- if champ.virus_scan.safe? || champ.virus_scan.blank?
- if champ.virus_scan.blank? || champ.virus_scan.safe?
= link_to url_for(pj), target: '_blank', title: "Télécharger la pièce jointe" do
%span.icon.attachment
= pj.filename.to_s
- if champ.virus_scan.blank?
(ce fichier n'a pas été analysé par notre antivirus, téléchargez-le avec précaution)
(ce fichier na pas été analysé par notre antivirus, téléchargez-le avec précaution)
- else
= pj.filename.to_s
@ -16,6 +16,6 @@
)
- elsif champ.virus_scan.infected?
- if user_can_upload
(virus détecté, merci d'envoyer un autre fichier)
(virus détecté, merci denvoyer un autre fichier)
- else
(virus détecté, le téléchargement de ce fichier est bloqué)

View file

@ -6,7 +6,7 @@
.description
Contactez-nous via ce formulaire et nous vous répondrons dans les plus brefs délais.
Pensez bien à nous donner le plus d'informations possible pour que nous puissions vous aider au mieux.
Pensez bien à nous donner le plus d'informations possible pour que nous puissions vous aider au mieux
= form_tag contact_path, method: :post, multipart: true, class: 'form' do |f|
- if !logged_in?
@ -20,7 +20,33 @@
= label_tag :type do
Votre problème
%span.mandatory *
= select_tag :type, options_for_select(@options, params[:type])
= select_tag :type, options_for_select(@options, params[:type]), include_blank: "Choisir un problème", required: true
.support.card.featured.hidden
.card-title
👉 Notre réponse
.card-content.hidden{ data: { answer: "info demarche" } }
%p Avez-vous bien vérifié que tous les champs obligatoires (*) sont bien remplis ?
%p Si vous avez des questions sur les informations à saisir, contactez les services en charge de la démarche.
%p
%a{ href: 'https://faq.demarches-simplifiees.fr/article/12-contacter-le-service-en-charge-de-ma-demarche' }
En savoir plus
.card-content.hidden{ data: { answer: "usager perdu" } }
%p Nous vous invitons à contacter ladministration en charge de votre démarche pour quelle vous indique le lien à suivre. Celui-ci devrait ressembler à cela : https://www.demarches-simplifiees.fr/commencer/NOM_DE_LA_DEMARCHE .
%br
%p Vous pouvez aussi consulter ici la liste de nos démarches les plus frequentes (permis, detr etc) :
%p
%a{ href: 'https://doc.demarches-simplifiees.fr/listes-des-demarches' }
https://doc.demarches-simplifiees.fr/listes-des-demarches
.card-content.hidden{ data: { answer: "info instruction" } }
%p Si vous avez des questions sur linstruction de votre dossier (par exemple sur les délais), nous vous invitons à contacter directement les services qui instruisent votre dossier par votre messagerie
%p
%a{ href: 'https://faq.demarches-simplifiees.fr/article/11-je-veux-savoir-ou-en-est-linstruction-de-ma-demarche' }
En savoir plus
%br
%p Si vous souhaitez poser une question pour un problème technique sur le site, utilisez le formulaire ci-dessous. Nous ne pourrons pas vous renseigner sur l'instruction de votre dossier.
.contact-champ
= label_tag :dossier_id, 'Numéro du dossier concerné'

View file

@ -0,0 +1,18 @@
namespace :after_party do
desc 'Deployment task: add_procedure_administrateur_to_administrateurs'
task add_procedure_administrateur_to_administrateurs: :environment do
rake_puts "Running deploy task: 'add_procedure_administrateur_to_administrateurs'"
procedures = Procedure.includes(:administrateurs)
progress = ProgressReport.new(procedures.count)
procedures.find_each do |procedure|
if !procedure.administrateurs.include?(procedure.administrateur)
procedure.administrateurs << procedure.administrateur
end
progress.inc
end
progress.finish
AfterParty::TaskRecord.create version: '20190214101524'
end
end

View file

@ -26,6 +26,8 @@ namespace :support do
procedure = Procedure.find(procedure_id)
rake_puts("Changing owner of procedure ##{procedure_id} from ##{procedure.administrateur_id} to ##{new_owner.id}")
procedure.administrateurs.delete(procedure.administrateur)
procedure.administrateurs << new_owner
procedure.update(administrateur: new_owner)
end
@ -68,6 +70,10 @@ namespace :support do
fail "Must specify a new owner"
end
procedures.each do |procedure|
procedure.administrateurs.delete(procedure.administrateur)
procedure.administrateurs << new_owner
end
procedures.update_all(administrateur_id: new_owner.id)
end

View file

@ -12,6 +12,10 @@ FactoryBot.define do
duree_conservation_dossiers_hors_ds { 6 }
ask_birthday { false }
after(:build) do |procedure|
procedure.administrateurs = [procedure.administrateur]
end
factory :procedure_with_dossiers do
transient do
dossiers_count { 1 }

View file

@ -1,4 +1,17 @@
FactoryBot.define do
factory :virus_scan do
add_attribute(:status) { VirusScan.statuses.fetch(:pending) }
trait :pending do
add_attribute(:status) { VirusScan.statuses.fetch(:pending) }
end
trait :safe do
add_attribute(:status) { VirusScan.statuses.fetch(:safe) }
end
trait :infected do
add_attribute(:status) { VirusScan.statuses.fetch(:infected) }
end
end
end

View file

@ -426,6 +426,10 @@ describe Champ do
expect(champ.champs.first.dossier).to eq(dossier)
# Make champs ordered
champ_integer_number.type_de_champ.update(order_place: 0)
champ_text.type_de_champ.update(order_place: 1)
champ.champs << champ_integer_number
row = champ.reload.rows.first
expect(row.size).to eq(1)

View file

@ -0,0 +1,24 @@
describe Champs::PieceJustificativeChamp do
describe '#for_api' do
let(:champ_pj) { create(:champ_piece_justificative) }
before { champ_pj.virus_scan.update(status: status) }
subject { champ_pj.for_api }
context 'when file is safe' do
let(:status) { 'safe' }
it { is_expected.to include("/rails/active_storage/blobs/") }
end
context 'when file is not scanned' do
let(:status) { 'pending' }
it { is_expected.to be_nil }
end
context 'when file is infected' do
let(:status) { 'infected' }
it { is_expected.to be_nil }
end
end
end

View file

@ -4,12 +4,16 @@ describe TagsSubstitutionConcern, type: :model do
let(:for_individual) { false }
let(:state) { Dossier.states.fetch(:accepte) }
let(:service) { create(:service, nom: 'Service instructeur') }
let(:procedure) do
create(:procedure,
libelle: 'Une magnifique démarche',
types_de_champ: types_de_champ,
types_de_champ_private: types_de_champ_private,
for_individual: for_individual)
for_individual: for_individual,
service: service,
organisation: nil)
end
let(:template_concern) do
@ -144,6 +148,19 @@ describe TagsSubstitutionConcern, type: :model do
end
end
context 'when the user requests the service' do
let(:template) { 'Dossier traité par --nom du service--' }
context 'and there is a service' do
it { is_expected.to eq("Dossier traité par #{service.nom}") }
end
context 'and there is no service yet' do
let(:service) { nil }
it { is_expected.to eq("Dossier traité par ") }
end
end
context 'when the dossier has a motivation' do
let(:dossier) { create(:dossier, motivation: 'motivation') }

View file

@ -404,7 +404,9 @@ describe Procedure do
context 'when the procedure is cloned from the library' do
let(:from_library) { true }
it { expect(subject.cloned_from_library).to be(true) }
it 'should set cloned_from_library to true' do
expect(subject.cloned_from_library).to be(true)
end
it 'should set service_id to nil' do
expect(subject.service).to eq(nil)
@ -415,6 +417,11 @@ describe Procedure do
expect(stc.old_pj).to be_nil
end
end
it 'should have one administrateur' do
expect(subject.administrateur).to eq(administrateur)
expect(subject.administrateurs).to eq([administrateur])
end
end
it 'should keep service_id' do
@ -435,6 +442,11 @@ describe Procedure do
expect(stc.old_pj).to be_nil
end
end
it 'should have one administrateur' do
expect(subject.administrateur).to eq(administrateur)
expect(subject.administrateurs).to eq([administrateur])
end
end
it 'should duplicate existing mail_templates' do

View file

@ -8,7 +8,10 @@ describe ChampSerializer do
let(:champ) { create(:champ_piece_justificative) }
before { champ.piece_justificative_file.attach({ filename: __FILE__, io: File.open(__FILE__) }) }
before do
champ.piece_justificative_file.attach({ filename: __FILE__, io: File.open(__FILE__) })
champ.reload.virus_scan.safe!
end
after { champ.piece_justificative_file.purge }
it { is_expected.to include(value: url_for(champ.piece_justificative_file)) }

View file

@ -0,0 +1,51 @@
require 'rails_helper'
describe 'shared/champs/piece_justificative/_pj_link.html.haml', type: :view do
let(:champ) { create(:champ, :piece_justificative, :with_piece_justificative_file) }
let(:virus_scan) { nil }
before do
if virus_scan
champ.update(virus_scan: virus_scan)
end
end
subject { render 'shared/champs/piece_justificative/pj_link', champ: champ, user_can_upload: false }
context 'when there is no anti-virus scan' do
let(:virus_scan) { nil }
it 'allows to download the file' do
expect(subject).to have_link(champ.piece_justificative_file.filename.to_s)
expect(subject).to have_text('ce fichier na pas été analysé par notre antivirus')
end
end
context 'when the anti-virus scan is pending' do
let(:virus_scan) { create(:virus_scan, :pending) }
it 'displays the filename, but doesnt allow to download the file' do
expect(subject).to have_text(champ.piece_justificative_file.filename.to_s)
expect(subject).not_to have_link(champ.piece_justificative_file.filename.to_s)
expect(subject).to have_text('analyse antivirus en cours')
end
end
context 'when the file is scanned and safe' do
let(:virus_scan) { create(:virus_scan, :safe) }
it 'allows to download the file' do
expect(subject).to have_link(champ.piece_justificative_file.filename.to_s)
end
end
context 'when the file is scanned and infected' do
let(:virus_scan) { create(:virus_scan, :infected) }
it 'displays the filename, but doesnt allow to download the file' do
expect(subject).to have_text(champ.piece_justificative_file.filename.to_s)
expect(subject).not_to have_link(champ.piece_justificative_file.filename.to_s)
expect(subject).to have_text('virus détecté')
end
end
end