commit
611d56d918
23 changed files with 270 additions and 55 deletions
|
@ -100,6 +100,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
&.small {
|
||||
line-height: 14px;
|
||||
padding: 5px 10px 6px 10px;
|
||||
}
|
||||
|
||||
&.large {
|
||||
font-size: 18px;
|
||||
line-height: 26px;
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
@import "../constants";
|
||||
|
||||
.piece-justificative-actions {
|
||||
display: flex;
|
||||
margin-bottom: $default-spacer;
|
||||
}
|
||||
|
||||
.piece-justificative-action {
|
||||
margin-right: $default-spacer;
|
||||
|
||||
.button {
|
||||
text-transform: lowercase;
|
||||
}
|
||||
}
|
||||
|
||||
.piece-justificative-input.hidden {
|
||||
display: none;
|
||||
}
|
|
@ -100,9 +100,9 @@
|
|||
input[type=date],
|
||||
input[type=number],
|
||||
input[type=tel],
|
||||
input[type=file],
|
||||
textarea,
|
||||
select {
|
||||
select,
|
||||
.piece-justificative {
|
||||
display: block;
|
||||
margin-bottom: 2 * $default-padding;
|
||||
|
||||
|
@ -111,10 +111,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.direct-upload {
|
||||
margin-bottom: 2 * $default-padding;
|
||||
}
|
||||
|
||||
.add-row {
|
||||
margin-bottom: 2 * $default-padding;
|
||||
}
|
||||
|
|
|
@ -13,19 +13,16 @@ class Champs::CarteController < ApplicationController
|
|||
coordinates = params[:dossier][:champs_private_attributes][params[:position]][:value]
|
||||
end
|
||||
|
||||
if params[:champ_id].present?
|
||||
@champ = Champ
|
||||
@champ = if params[:champ_id].present?
|
||||
Champ
|
||||
.joins(:dossier)
|
||||
.where(dossiers: { user_id: logged_user_ids })
|
||||
.find(params[:champ_id])
|
||||
else
|
||||
@champ = Champs::CarteChamp.new(type_de_champ: TypeDeChamp.new(
|
||||
type_champ: TypeDeChamp.type_champs.fetch(:carte),
|
||||
options: {
|
||||
quartiers_prioritaires: true,
|
||||
cadastres: true
|
||||
}
|
||||
))
|
||||
TypeDeChamp
|
||||
.joins(:procedure)
|
||||
.where(procedures: { administrateur_id: logged_user_ids })
|
||||
.find(params[:type_de_champ_id]).champ.build
|
||||
end
|
||||
|
||||
geo_areas = []
|
||||
|
|
|
@ -16,7 +16,7 @@ class DossierDashboard < Administrate::BaseDashboard
|
|||
created_at: Field::DateTime,
|
||||
updated_at: Field::DateTime,
|
||||
hidden_at: Field::DateTime,
|
||||
types_de_champ: TypesDeChampCollectionField
|
||||
champs: ChampCollectionField
|
||||
}.freeze
|
||||
|
||||
# COLLECTION_ATTRIBUTES
|
||||
|
@ -38,7 +38,7 @@ class DossierDashboard < Administrate::BaseDashboard
|
|||
:state,
|
||||
:procedure,
|
||||
:user,
|
||||
:types_de_champ,
|
||||
:champs,
|
||||
:created_at,
|
||||
:updated_at,
|
||||
:hidden_at
|
||||
|
|
7
app/fields/champ_collection_field.rb
Normal file
7
app/fields/champ_collection_field.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
require "administrate/field/base"
|
||||
|
||||
class ChampCollectionField < Administrate::Field::Base
|
||||
def to_s
|
||||
data
|
||||
end
|
||||
end
|
|
@ -9,4 +9,12 @@ module ChampHelper
|
|||
raw(champ.to_render_data.to_json)
|
||||
# rubocop:enable Rails/OutputSafety
|
||||
end
|
||||
|
||||
def champ_carte_params(champ)
|
||||
if champ.persisted?
|
||||
{ champ_id: champ.id }
|
||||
else
|
||||
{ type_de_champ_id: champ.type_de_champ_id }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,6 +12,7 @@ import '../shared/safari-11-file-xhr-workaround';
|
|||
import '../shared/autocomplete';
|
||||
import '../shared/remote-input';
|
||||
import '../shared/franceconnect';
|
||||
import '../shared/toggle-target';
|
||||
|
||||
import '../new_design/spinner';
|
||||
import '../new_design/dropdown';
|
||||
|
|
20
app/javascript/shared/toggle-target.js
Normal file
20
app/javascript/shared/toggle-target.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { delegate, toggle } from '@utils';
|
||||
|
||||
// Unobtrusive Javascript for allowing an element to toggle
|
||||
// the visibility of another element.
|
||||
//
|
||||
// Usage:
|
||||
// <button data-toggle-target="#target">Toggle</button>
|
||||
// <div id="target">Content</div>
|
||||
|
||||
const TOGGLE_SOURCE_SELECTOR = '[data-toggle-target]';
|
||||
|
||||
delegate('click', TOGGLE_SOURCE_SELECTOR, evt => {
|
||||
evt.preventDefault();
|
||||
|
||||
const targetSelector = evt.target.dataset.toggleTarget;
|
||||
const targetElements = document.querySelectorAll(targetSelector);
|
||||
for (let target of targetElements) {
|
||||
toggle(target);
|
||||
}
|
||||
});
|
|
@ -23,15 +23,15 @@ class Champ < ApplicationRecord
|
|||
end
|
||||
|
||||
def mandatory_and_blank?
|
||||
if mandatory?
|
||||
case type_de_champ.type_champ
|
||||
when TypeDeChamp.type_champs.fetch(:carte)
|
||||
value.blank? || value == '[]'
|
||||
else
|
||||
value.blank?
|
||||
end
|
||||
mandatory? && blank?
|
||||
end
|
||||
|
||||
def blank?
|
||||
case type_de_champ.type_champ
|
||||
when TypeDeChamp.type_champs.fetch(:carte)
|
||||
value.blank? || value == '[]'
|
||||
else
|
||||
false
|
||||
value.blank?
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
pour y accéder vous pouvez utiliser le lien :
|
||||
= link_to procedure_lien(@procedure), sanitize_url(procedure_lien(@procedure)), target: :blank
|
||||
%p
|
||||
Tout personne ayant la connaissance de ce lien pourra ainsi remplir des dossiers sur votre démarche.
|
||||
Tout personne ayant la connaissance de ce lien pourra ainsi remplir des dossiers de test sur votre démarche.
|
||||
%br
|
||||
|
||||
%h4 Ce que vous pouvez faire lorsque vous êtes en test
|
||||
|
|
24
app/views/fields/champ_collection_field/_show.html.haml
Normal file
24
app/views/fields/champ_collection_field/_show.html.haml
Normal file
|
@ -0,0 +1,24 @@
|
|||
- if field.data.any?
|
||||
%table.collection-data{ "aria-labelledby": "page-title" }
|
||||
%thead
|
||||
%tr
|
||||
%td.cell-label Libelle
|
||||
%td.cell-label Type de champ
|
||||
%td.cell-label Rempli
|
||||
%tbody
|
||||
- field.data.each do |f|
|
||||
%tr
|
||||
%td.cell-data
|
||||
= f.libelle
|
||||
- if f.mandatory?
|
||||
%span.mandatory{ style: 'color: #A10005;' } *
|
||||
%td.cell-data
|
||||
= I18n.t("activerecord.attributes.type_de_champ.type_champs.#{f.type_champ}")
|
||||
|
||||
%td.cell-data
|
||||
- if f.blank?
|
||||
vide
|
||||
- else
|
||||
rempli
|
||||
- else
|
||||
Aucun
|
|
@ -4,12 +4,21 @@
|
|||
%tr
|
||||
%td.cell-label Libelle
|
||||
%td.cell-label Type de champ
|
||||
%td.cell-label Rempli
|
||||
%tbody
|
||||
- field.data.order(:order_place).each do |f|
|
||||
%tr
|
||||
%td.cell-data
|
||||
= f.libelle
|
||||
- if f.mandatory?
|
||||
%span.mandatory{ style: 'color: #A10005;' } *
|
||||
%td.cell-data
|
||||
= I18n.t("activerecord.attributes.type_de_champ.type_champs.#{f.type_champ}")
|
||||
|
||||
%td.cell-data
|
||||
- if f.blank?
|
||||
vide
|
||||
- else
|
||||
rempli
|
||||
- else
|
||||
Aucun
|
||||
|
|
|
@ -10,3 +10,7 @@
|
|||
= link_to 'CGU / Mentions légales', CGU_URL
|
||||
\-
|
||||
= contact_link 'Contact'
|
||||
\-
|
||||
= link_to 'FAQ', "https://faq.demarches-simplifiees.fr"
|
||||
\-
|
||||
= link_to 'Documentation', "http://doc.demarches-simplifiees.fr"
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
<%= render_flash(timeout: 5000, sticky: true) %>
|
||||
<%= remove_element("#piece_justificative_#{@champ.id}") %>
|
||||
|
||||
let fileInputSelector = '<%= "#champs_#{@champ.id}" %>';
|
||||
document.querySelector(fileInputSelector).classList.remove('hidden');
|
||||
|
|
|
@ -78,6 +78,11 @@
|
|||
|
||||
= link_to ".button.without-continuation", "#", class: "button without-continuation"
|
||||
|
||||
%p
|
||||
= link_to ".button.small", "#", class: "button small"
|
||||
|
||||
= link_to ".button.small.primary", "#", class: "button small primary"
|
||||
|
||||
%p
|
||||
= link_to ".button.large", "#", class: "button large"
|
||||
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
- pj = champ.piece_justificative_file
|
||||
- if champ.virus_scan.present?
|
||||
- if champ.virus_scan.safe?
|
||||
= link_to pj.filename.to_s, url_for(pj), target: '_blank'
|
||||
|
||||
.pj-link
|
||||
- if champ.virus_scan.safe? || champ.virus_scan.blank?
|
||||
= 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)
|
||||
|
||||
- else
|
||||
= pj.filename.to_s
|
||||
- if champ.virus_scan.pending?
|
||||
|
@ -13,6 +19,3 @@
|
|||
(virus détecté, merci d'envoyer un autre fichier)
|
||||
- else
|
||||
(virus détecté, le téléchargement de ce fichier est bloqué)
|
||||
- else
|
||||
= link_to pj.filename.to_s, url_for(pj), target: '_blank'
|
||||
(ce fichier n'a pas été analysé par notre antivirus, téléchargez-le avec précaution)
|
||||
|
|
|
@ -8,4 +8,4 @@
|
|||
= render partial: 'shared/champs/carte/geo_areas', locals: { champ: champ, error: false }
|
||||
|
||||
= form.hidden_field :value,
|
||||
data: { remote: true, url: champs_carte_path(form.index), params: { champ_id: champ&.id }.to_query, method: 'post' }
|
||||
data: { remote: true, url: champs_carte_path(form.index), params: champ_carte_params(champ).to_query, method: 'post' }
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
- pj = champ.piece_justificative_file
|
||||
|
||||
- if champ.type_de_champ.piece_justificative_template.attached?
|
||||
%p.edit-pj-template.mb-1
|
||||
Veuillez télécharger, remplir et joindre
|
||||
= link_to('le modèle suivant', url_for(champ.type_de_champ.piece_justificative_template), target: '_blank')
|
||||
.piece-justificative
|
||||
- if champ.type_de_champ.piece_justificative_template.attached?
|
||||
%p.edit-pj-template.mb-1
|
||||
Veuillez télécharger, remplir et joindre
|
||||
= link_to('le modèle suivant', url_for(champ.type_de_champ.piece_justificative_template), target: '_blank')
|
||||
|
||||
- if pj.attached?
|
||||
.piece-justificative-actions{ id: "piece_justificative_#{champ.id}" }
|
||||
.piece-justificative-action
|
||||
= render partial: "shared/champs/piece_justificative/pj_link", locals: { champ: champ, user_can_upload: true }
|
||||
.piece-justificative-action
|
||||
- if champ.private?
|
||||
= link_to 'Supprimer', gestionnaire_champ_purge_champ_piece_justificative_path(procedure_id: champ.dossier.procedure_id, dossier_id: champ.dossier_id, champ_id: champ.id), remote: true, method: :delete, class: 'button small danger'
|
||||
- else
|
||||
= link_to 'Supprimer', champ_purge_champ_piece_justificative_path(id: champ.dossier_id, champ_id: champ.id), remote: true, method: :delete, class: 'button small danger'
|
||||
.piece-justificative-action
|
||||
= button_tag 'Remplacer', type: 'button', class: 'button small', data: { 'toggle-target': "#champs_#{champ.id}" }
|
||||
|
||||
- if !pj.attached?
|
||||
= form.file_field :piece_justificative_file,
|
||||
id: "champs_#{champ.id}",
|
||||
direct_upload: true
|
||||
- else
|
||||
%div{ id: "piece_justificative_#{champ.id}" }
|
||||
= render partial: "shared/champs/piece_justificative/pj_link", locals: { champ: champ, user_can_upload: true }
|
||||
%br
|
||||
- if champ.private?
|
||||
= link_to 'supprimer', gestionnaire_champ_purge_champ_piece_justificative_path(procedure_id: champ.dossier.procedure_id, dossier_id: champ.dossier_id, champ_id: champ.id), remote: true, method: :delete
|
||||
- else
|
||||
= link_to 'supprimer', champ_purge_champ_piece_justificative_path(id: champ.dossier_id, champ_id: champ.id), remote: true, method: :delete
|
||||
%br
|
||||
Modifier :
|
||||
= form.file_field :piece_justificative_file,
|
||||
id: "champs_#{champ.id}",
|
||||
class: "piece-justificative-input #{'hidden' if pj.attached?}",
|
||||
direct_upload: true
|
||||
|
|
|
@ -130,4 +130,28 @@ namespace :support do
|
|||
|
||||
user.update(email: new_email)
|
||||
end
|
||||
|
||||
desc <<~EOD
|
||||
Activate feature publish draft
|
||||
EOD
|
||||
task activate_publish_draft: :environment do
|
||||
start_with = ENV['START_WITH']
|
||||
|
||||
administrateurs = Administrateur.where("email like ?", "#{start_with}%")
|
||||
|
||||
rake_puts("Activating publish draft for #{administrateurs.count} administrateurs...")
|
||||
|
||||
administrateurs.each do |a|
|
||||
rake_puts("Activating publish draft for #{a.email}")
|
||||
a.features["publish_draft"] = true
|
||||
a.save
|
||||
|
||||
a.procedures.brouillon.each do |p|
|
||||
if p.path.nil?
|
||||
p.path = SecureRandom.uuid
|
||||
p.save
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -117,4 +117,19 @@ feature 'As an administrateur I can edit types de champ', js: true do
|
|||
|
||||
expect(page).to have_content('Supprimer', count: 3)
|
||||
end
|
||||
|
||||
it "Add carte champ" do
|
||||
select('Carte', from: 'procedure_types_de_champ_attributes_0_type_champ')
|
||||
fill_in 'procedure_types_de_champ_attributes_0_libelle', with: 'libellé de champ carte'
|
||||
blur
|
||||
check 'Quartiers prioritaires'
|
||||
expect(page).to have_content('Formulaire enregistré')
|
||||
|
||||
preview_window = window_opened_by { click_on 'Prévisualiser le formulaire' }
|
||||
within_window(preview_window) do
|
||||
expect(page).to have_content('libellé de champ carte')
|
||||
expect(page).to have_content('Quartiers prioritaires')
|
||||
expect(page).not_to have_content('Cadastres')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require 'spec_helper'
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'The user' do
|
||||
let(:password) { 'secret_password' }
|
||||
|
@ -10,7 +10,6 @@ feature 'The user' do
|
|||
# TODO: check
|
||||
# the order
|
||||
# there are no extraneous input
|
||||
# attached file works
|
||||
scenario 'fill a dossier', js: true do
|
||||
allow(Champs::RegionChamp).to receive(:regions).and_return(['region1', 'region2']).at_least(:once)
|
||||
allow(Champs::DepartementChamp).to receive(:departements).and_return(['dep1', 'dep2']).at_least(:once)
|
||||
|
@ -38,10 +37,10 @@ feature 'The user' do
|
|||
select('dep2', from: 'departements')
|
||||
check('engagement')
|
||||
fill_in('dossier_link', with: '123')
|
||||
# do not know how to make it work...
|
||||
# find('form input[type="file"]').set(Rails.root.join('spec/fixtures/files/white.png'))
|
||||
find('.editable-champ-piece_justificative input[type=file]').attach_file(Rails.root + 'spec/fixtures/files/file.pdf')
|
||||
|
||||
click_on 'Enregistrer le brouillon'
|
||||
expect(page).to have_content('Votre brouillon a bien été sauvegardé')
|
||||
|
||||
# check data on the dossier
|
||||
expect(user_dossier.brouillon?).to be true
|
||||
|
@ -62,8 +61,10 @@ feature 'The user' do
|
|||
expect(champ_value_for('departements')).to eq('dep2')
|
||||
expect(champ_value_for('engagement')).to eq('on')
|
||||
expect(champ_value_for('dossier_link')).to eq('123')
|
||||
expect(champ_value_for('piece_justificative')).to be_nil # antivirus hasn't approved the file yet
|
||||
|
||||
## check data on the gui
|
||||
|
||||
expect(page).to have_field('text', with: 'super texte')
|
||||
expect(page).to have_field('textarea', with: 'super textarea')
|
||||
expect(page).to have_field('date', with: '2012-12-12')
|
||||
|
@ -81,6 +82,8 @@ feature 'The user' do
|
|||
expect(page).to have_select('departement', selected: 'dep2')
|
||||
expect(page).to have_checked_field('engagement')
|
||||
expect(page).to have_field('dossier_link', with: '123')
|
||||
expect(page).to have_text('file.pdf')
|
||||
expect(page).to have_text('analyse antivirus en cours')
|
||||
end
|
||||
|
||||
let(:procedure_with_repetition) do
|
||||
|
@ -147,6 +150,48 @@ feature 'The user' do
|
|||
expect(page).to have_current_path(merci_dossier_path(user_dossier))
|
||||
end
|
||||
|
||||
let(:procedure_with_pj) do
|
||||
tdcs = [create(:type_de_champ_piece_justificative, mandatory: true, libelle: 'Pièce justificative')]
|
||||
create(:procedure, :published, :for_individual, types_de_champ: tdcs)
|
||||
end
|
||||
|
||||
scenario 'adding, replacing and removing attachments', js: true do
|
||||
log_in(user.email, password, procedure_with_pj)
|
||||
fill_individual
|
||||
|
||||
# Add an attachment
|
||||
find('.editable-champ-piece_justificative input[type=file]').attach_file(Rails.root + 'spec/fixtures/files/file.pdf')
|
||||
click_on 'Enregistrer le brouillon'
|
||||
expect(page).to have_content('Votre brouillon a bien été sauvegardé')
|
||||
expect(page).to have_text('file.pdf')
|
||||
expect(page).to have_text('analyse antivirus en cours')
|
||||
|
||||
# Mark file as scanned and clean
|
||||
virus_scan = VirusScan.last
|
||||
virus_scan.update(scanned_at: Time.zone.now, status: VirusScan.statuses.fetch(:safe))
|
||||
within '.piece-justificative' do
|
||||
click_on 'rafraichir'
|
||||
end
|
||||
expect(page).to have_link('file.pdf')
|
||||
expect(page).to have_no_content('analyse antivirus en cours')
|
||||
|
||||
# Replace the attachment
|
||||
within '.piece-justificative' do
|
||||
click_on 'Remplacer'
|
||||
end
|
||||
find('.editable-champ-piece_justificative input[type=file]').attach_file(Rails.root + 'spec/fixtures/files/RIB.pdf')
|
||||
click_on 'Enregistrer le brouillon'
|
||||
expect(page).to have_no_text('file.pdf')
|
||||
expect(page).to have_text('RIB.pdf')
|
||||
|
||||
# Remove the attachment
|
||||
within '.piece-justificative' do
|
||||
click_on 'Supprimer'
|
||||
end
|
||||
expect(page).to have_content('La pièce jointe a bien été supprimée')
|
||||
expect(page).to have_no_text('RIB.pdf')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def log_in(email, password, procedure)
|
||||
|
|
31
spec/lib/tasks/activate_publish_draft_spec.rb
Normal file
31
spec/lib/tasks/activate_publish_draft_spec.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'activate_publish_draft#clean' do
|
||||
let(:rake_task) { Rake::Task['support:activate_publish_draft'] }
|
||||
|
||||
let(:administrateur) { create(:administrateur) }
|
||||
let!(:procedure) { create(:procedure, administrateur: administrateur) }
|
||||
let!(:procedure2) { create(:simple_procedure, administrateur: administrateur) }
|
||||
|
||||
before do
|
||||
ENV['START_WITH'] = administrateur.email
|
||||
rake_task.invoke
|
||||
administrateur.reload
|
||||
end
|
||||
|
||||
after { rake_task.reenable }
|
||||
|
||||
it 'activate feature for administrateur' do
|
||||
expect(administrateur.features["publish_draft"]).to eq(true)
|
||||
end
|
||||
|
||||
it 'create a path for his brouillon procedure' do
|
||||
expect(administrateur.procedures.brouillon.count).to eq(1)
|
||||
expect(administrateur.procedures.brouillon.first.path).not_to eq(nil)
|
||||
end
|
||||
|
||||
it 'does not change the path of his published procedure' do
|
||||
expect(administrateur.procedures.publiee.count).to eq(1)
|
||||
expect(administrateur.procedures.publiee.first.path).to eq(procedure2.path)
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue