commit
a144da5718
94 changed files with 1790 additions and 346 deletions
|
@ -18,7 +18,7 @@ module.exports = {
|
|||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['config/webpack/*.js'],
|
||||
files: ['config/webpack/**/*.js'],
|
||||
env: {
|
||||
node: true
|
||||
}
|
||||
|
|
1
app/assets/images/icons/drag.svg
Normal file
1
app/assets/images/icons/drag.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M20 9H4v2h16V9zM4 15h16v-2H4v2z"/></svg>
|
After Width: | Height: | Size: 132 B |
|
@ -11,6 +11,7 @@
|
|||
|
||||
a {
|
||||
color: $black;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&::after {
|
||||
|
|
|
@ -110,7 +110,7 @@
|
|||
width: 18px;
|
||||
height: 18px;
|
||||
background-size: 18px 18px;
|
||||
vertical-align: middle;
|
||||
vertical-align: text-bottom;
|
||||
margin-right: $default-spacer;
|
||||
}
|
||||
|
||||
|
|
|
@ -107,6 +107,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
input[type=checkbox] {
|
||||
&.small-margin {
|
||||
margin-bottom: $default-padding / 2;
|
||||
}
|
||||
}
|
||||
|
||||
input[type=text]:not([data-address='true']),
|
||||
input[type=email],
|
||||
input[type=password],
|
||||
|
|
|
@ -20,3 +20,12 @@
|
|||
border-color: $light-green;
|
||||
color: $dark-green;
|
||||
}
|
||||
|
||||
.alert-fixed {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
margin-left: -100px;
|
||||
width: 200px;
|
||||
top: 10px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ footer {
|
|||
@include vertical-padding(72px);
|
||||
}
|
||||
|
||||
.dossier-footer {
|
||||
.procedure-footer {
|
||||
@include vertical-padding(30px);
|
||||
line-height: 24px;
|
||||
}
|
||||
|
|
137
app/assets/stylesheets/new_design/procedure_champs_editor.scss
Normal file
137
app/assets/stylesheets/new_design/procedure_champs_editor.scss
Normal file
|
@ -0,0 +1,137 @@
|
|||
@import "colors";
|
||||
|
||||
#champs-editor {
|
||||
.spinner {
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
margin-top: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
.draggable-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
border: 1px solid $border-grey;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
|
||||
.handle {
|
||||
cursor: ns-resize;
|
||||
margin-right: 10px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
text-align: center;
|
||||
flex-grow: 1;
|
||||
font-size: 14px;
|
||||
color: $light-grey;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
|
||||
.content {
|
||||
background-color: $medium-red;
|
||||
border-radius: 8px;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&.type-header-section {
|
||||
background-color: $blue;
|
||||
|
||||
label {
|
||||
color: $light-grey;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.type-header-section) {
|
||||
input.error {
|
||||
border: 1px solid $medium-red;
|
||||
}
|
||||
}
|
||||
|
||||
.column {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-direction: column;
|
||||
|
||||
&.shift-left {
|
||||
margin-left: 35px;
|
||||
}
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
|
||||
&.section {
|
||||
padding: 10px 10px 0 10px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
&.hr {
|
||||
border-bottom: 1px solid $border-grey;
|
||||
|
||||
&.head {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&.shift-left {
|
||||
margin-left: 35px;
|
||||
}
|
||||
|
||||
&.head {
|
||||
select {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
&.delete {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.cell {
|
||||
margin-right: 20px;
|
||||
|
||||
&.small {
|
||||
width: 90px;
|
||||
}
|
||||
|
||||
&.libelle {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-bottom: 8px;
|
||||
text-transform: uppercase;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.carte-options {
|
||||
label {
|
||||
font-weight: initial;
|
||||
}
|
||||
}
|
||||
|
||||
.inline {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
.header,
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 30px;
|
||||
}
|
|
@ -79,7 +79,12 @@ class Admin::ProceduresController < AdminController
|
|||
if gestionnaire
|
||||
gestionnaire.assign_to_procedure(@procedure)
|
||||
end
|
||||
redirect_to admin_procedure_types_de_champ_path(procedure_id: @procedure.id)
|
||||
|
||||
if Flipflop.new_champs_editor?
|
||||
redirect_to champs_procedure_path(@procedure)
|
||||
else
|
||||
redirect_to admin_procedure_types_de_champ_path(procedure_id: @procedure.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
34
app/controllers/concerns/procedure_context_concern.rb
Normal file
34
app/controllers/concerns/procedure_context_concern.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
module ProcedureContextConcern
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
include Devise::Controllers::StoreLocation
|
||||
include Devise::StoreLocationExtension
|
||||
|
||||
def restore_procedure_context
|
||||
if stored_procedure_id.present?
|
||||
@procedure = Procedure.publiees.find_by(id: stored_procedure_id)
|
||||
|
||||
if @procedure.blank?
|
||||
invalid_procedure_context
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def stored_procedure_id
|
||||
stored_location = get_stored_location_for(:user)
|
||||
|
||||
if stored_location.present? && stored_location.include?('procedure_id=')
|
||||
stored_location.split('procedure_id=').second
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def invalid_procedure_context
|
||||
clear_stored_location_for(:user)
|
||||
flash.alert = t('errors.messages.procedure_not_found')
|
||||
redirect_to root_path
|
||||
end
|
||||
end
|
19
app/controllers/devise/store_location_extension.rb
Normal file
19
app/controllers/devise/store_location_extension.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
module Devise
|
||||
# Useful helpers additions to Devise::Controllers::StoreLocation
|
||||
module StoreLocationExtension
|
||||
# A variant of `stored_location_key_for` which doesn't delete the stored path.
|
||||
def get_stored_location_for(resource_or_scope)
|
||||
location = stored_location_for(resource_or_scope)
|
||||
if location
|
||||
store_location_for(resource_or_scope, location)
|
||||
end
|
||||
location
|
||||
end
|
||||
|
||||
# Delete the url stored in the session for the given scope.
|
||||
def clear_stored_location_for(resource_or_scope)
|
||||
session_key = send(:stored_location_key_for, resource_or_scope)
|
||||
session.delete(session_key)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,5 +1,5 @@
|
|||
class InvitesController < ApplicationController
|
||||
SESSION_USER_RETURN_LOCATION = 'user_return_to'
|
||||
include Devise::StoreLocationExtension
|
||||
|
||||
before_action :authenticate_user!, only: [:create]
|
||||
before_action :store_user_location!, only: [:show]
|
||||
|
@ -62,6 +62,6 @@ class InvitesController < ApplicationController
|
|||
end
|
||||
|
||||
def erase_user_location!
|
||||
session.delete(SESSION_USER_RETURN_LOCATION)
|
||||
clear_stored_location_for(:user)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,28 @@
|
|||
module NewAdministrateur
|
||||
class AdministrateurController < ApplicationController
|
||||
before_action :authenticate_administrateur!
|
||||
|
||||
def retrieve_procedure
|
||||
id = params[:procedure_id] || params[:id]
|
||||
|
||||
@procedure = current_administrateur.procedures.find(id)
|
||||
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
flash.alert = 'Démarche inexistante'
|
||||
redirect_to admin_procedures_path
|
||||
end
|
||||
|
||||
def procedure_locked?
|
||||
if @procedure.locked?
|
||||
flash.alert = 'Démarche verrouillée'
|
||||
redirect_to admin_procedure_path(@procedure)
|
||||
end
|
||||
end
|
||||
|
||||
def reset_procedure
|
||||
if @procedure.brouillon_avec_lien?
|
||||
@procedure.reset!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,44 @@
|
|||
module NewAdministrateur
|
||||
class ProceduresController < AdministrateurController
|
||||
before_action :retrieve_procedure, only: [:champs, :annotations, :update]
|
||||
before_action :procedure_locked?, only: [:champs, :annotations, :update]
|
||||
|
||||
TYPE_DE_CHAMP_ATTRIBUTES = [
|
||||
:_destroy,
|
||||
:libelle,
|
||||
:description,
|
||||
:order_place,
|
||||
:type_champ,
|
||||
:id,
|
||||
:mandatory,
|
||||
:piece_justificative_template,
|
||||
:quartiers_prioritaires,
|
||||
:cadastres,
|
||||
:parcelles_agricoles,
|
||||
drop_down_list_attributes: [:value]
|
||||
]
|
||||
|
||||
def apercu
|
||||
@dossier = procedure_without_control.new_dossier
|
||||
@tab = apercu_tab
|
||||
end
|
||||
|
||||
def update
|
||||
if @procedure.update(procedure_params)
|
||||
flash.now.notice = if params[:procedure][:types_de_champ_attributes].present?
|
||||
'Champs enregistrés'
|
||||
elsif params[:procedure][:types_de_champ_private_attributes].present?
|
||||
'Annotations enregistrés'
|
||||
else
|
||||
'Démarche enregistrée.'
|
||||
end
|
||||
|
||||
reset_procedure
|
||||
else
|
||||
flash.now.alert = @procedure.errors.full_messages
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def apercu_tab
|
||||
|
@ -14,5 +48,12 @@ module NewAdministrateur
|
|||
def procedure_without_control
|
||||
Procedure.find(params[:id])
|
||||
end
|
||||
|
||||
def procedure_params
|
||||
params.required(:procedure).permit(
|
||||
types_de_champ_attributes: TYPE_DE_CHAMP_ATTRIBUTES,
|
||||
types_de_champ_private_attributes: TYPE_DE_CHAMP_ATTRIBUTES
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,7 +6,7 @@ module NewGestionnaire
|
|||
ITEMS_PER_PAGE = 25
|
||||
|
||||
def index
|
||||
@procedures = current_gestionnaire.visible_procedures.order(archived_at: :desc, published_at: :desc)
|
||||
@procedures = current_gestionnaire.visible_procedures.order(archived_at: :desc, published_at: :desc, created_at: :desc)
|
||||
|
||||
dossiers = current_gestionnaire.dossiers
|
||||
@dossiers_count_per_procedure = dossiers.all_state.group(:procedure_id).reorder(nil).count
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
module NewUser
|
||||
class DossiersController < UserController
|
||||
include Devise::StoreLocationExtension
|
||||
include DossierHelper
|
||||
|
||||
layout 'procedure_context', only: [:identite, :update_identite, :siret, :update_siret]
|
||||
|
||||
SESSION_USER_RETURN_LOCATION = 'user_return_to'
|
||||
ACTIONS_ALLOWED_TO_ANY_USER = [:index, :recherche, :new]
|
||||
ACTIONS_ALLOWED_TO_OWNER_OR_INVITE = [:show, :demande, :messagerie, :brouillon, :update_brouillon, :modifier, :update, :create_commentaire, :purge_champ_piece_justificative]
|
||||
|
||||
|
@ -247,7 +247,7 @@ module NewUser
|
|||
end
|
||||
|
||||
def erase_user_location!
|
||||
session.delete(SESSION_USER_RETURN_LOCATION)
|
||||
clear_stored_location_for(:user)
|
||||
end
|
||||
|
||||
def show_demarche_en_test_banner
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
class Sessions::SessionsController < Devise::SessionsController
|
||||
before_action :before_sign_in, only: [:create]
|
||||
|
||||
layout 'new_application'
|
||||
|
||||
def before_sign_in
|
||||
if user_signed_in?
|
||||
sign_out :user
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
class Users::RegistrationsController < Devise::RegistrationsController
|
||||
include ProcedureContextConcern
|
||||
|
||||
# before_action :configure_sign_up_params, only: [:create]
|
||||
# before_action :configure_account_update_params, only: [:update]
|
||||
before_action :restore_procedure_context, only: [:new, :create]
|
||||
|
||||
# def after_sign_up_path_for(resource_or_scope)
|
||||
# super
|
||||
# end
|
||||
layout 'procedure_context', only: [:new, :create]
|
||||
|
||||
# GET /resource/sign_up
|
||||
def new
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
class Users::SessionsController < Sessions::SessionsController
|
||||
include ProcedureContextConcern
|
||||
include TrustedDeviceConcern
|
||||
include ActionView::Helpers::DateHelper
|
||||
|
||||
layout 'procedure_context', only: [:new, :create]
|
||||
|
||||
before_action :restore_procedure_context, only: [:new, :create]
|
||||
|
||||
# GET /resource/sign_in
|
||||
def new
|
||||
if user_return_to_procedure_id.present? # WTF ?
|
||||
@dossier = Dossier.new(procedure: Procedure.active(user_return_to_procedure_id))
|
||||
end
|
||||
|
||||
@user = User.new
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
error_procedure
|
||||
end
|
||||
|
||||
# POST /resource/sign_in
|
||||
|
@ -78,7 +77,7 @@ class Users::SessionsController < Sessions::SessionsController
|
|||
end
|
||||
|
||||
def no_procedure
|
||||
session['user_return_to'] = nil
|
||||
clear_stored_location_for(:user)
|
||||
redirect_to new_user_session_path
|
||||
end
|
||||
|
||||
|
@ -110,20 +109,6 @@ class Users::SessionsController < Sessions::SessionsController
|
|||
end
|
||||
end
|
||||
|
||||
def error_procedure
|
||||
session["user_return_to"] = nil
|
||||
flash.alert = t('errors.messages.procedure_not_found')
|
||||
redirect_to url_for root_path
|
||||
end
|
||||
|
||||
def user_return_to_procedure_id
|
||||
if session["user_return_to"].nil?
|
||||
return nil
|
||||
end
|
||||
|
||||
NumberService.to_number session["user_return_to"].split("?procedure_id=").second
|
||||
end
|
||||
|
||||
def try_to_authenticate(klass, remember_me = false)
|
||||
resource = klass.find_for_database_authentication(email: params[:user][:email])
|
||||
|
||||
|
|
|
@ -7,11 +7,20 @@ module ApplicationHelper
|
|||
end
|
||||
end
|
||||
|
||||
def flash_class(level, sticky = false)
|
||||
case level
|
||||
when "notice" then "alert-success#{sticky ? ' sticky' : ''}"
|
||||
when "alert" then "alert-danger#{sticky ? ' sticky' : ''}"
|
||||
def flash_class(level, sticky: false, fixed: false)
|
||||
class_names = case level
|
||||
when 'notice'
|
||||
['alert-success']
|
||||
when 'alert'
|
||||
['alert-danger']
|
||||
end
|
||||
if sticky
|
||||
class_names << 'sticky'
|
||||
end
|
||||
if fixed
|
||||
class_names << 'alert-fixed'
|
||||
end
|
||||
class_names.join(' ')
|
||||
end
|
||||
|
||||
def render_to_element(selector, partial:, outer: false, locals: {})
|
||||
|
@ -22,9 +31,9 @@ module ApplicationHelper
|
|||
# rubocop:enable Rails/OutputSafety
|
||||
end
|
||||
|
||||
def render_flash(timeout: false, sticky: false)
|
||||
def render_flash(timeout: false, sticky: false, fixed: false)
|
||||
if flash.any?
|
||||
html = render_to_element('#flash_messages', partial: 'layouts/flash_messages', locals: { sticky: sticky }, outer: true)
|
||||
html = render_to_element('#flash_messages', partial: 'layouts/flash_messages', locals: { sticky: sticky, fixed: fixed }, outer: true)
|
||||
flash.clear
|
||||
if timeout
|
||||
html += remove_element('#flash_messages', timeout: timeout, inner: true)
|
||||
|
@ -56,6 +65,12 @@ module ApplicationHelper
|
|||
# rubocop:enable Rails/OutputSafety
|
||||
end
|
||||
|
||||
def fire_event(event_name, data)
|
||||
# rubocop:disable Rails/OutputSafety
|
||||
raw("DS.fire('#{event_name}', #{raw(data)});")
|
||||
# rubocop:enable Rails/OutputSafety
|
||||
end
|
||||
|
||||
def current_email
|
||||
current_user&.email ||
|
||||
current_gestionnaire&.email ||
|
||||
|
|
|
@ -10,7 +10,7 @@ module ProcedureHelper
|
|||
end
|
||||
|
||||
def procedure_libelle(procedure)
|
||||
parts = procedure.brouillon? ? [content_tag(:span, 'démarche non publiée', class: 'badge')] : []
|
||||
parts = procedure.brouillon? ? [content_tag(:span, 'démarche en test', class: 'badge')] : []
|
||||
parts << procedure.libelle
|
||||
safe_join(parts, ' ')
|
||||
end
|
||||
|
@ -33,4 +33,56 @@ module ProcedureHelper
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
def types_de_champ_data(procedure)
|
||||
{
|
||||
type: "champ",
|
||||
types_de_champ_options: types_de_champ_options.to_json,
|
||||
types_de_champ: types_de_champ_as_json(procedure.types_de_champ).to_json,
|
||||
direct_uploads_url: rails_direct_uploads_url,
|
||||
drag_icon_url: image_url("icons/drag.svg")
|
||||
}
|
||||
end
|
||||
|
||||
def types_de_champ_private_data(procedure)
|
||||
{
|
||||
type: "annotation",
|
||||
types_de_champ_options: types_de_champ_options.to_json,
|
||||
types_de_champ: types_de_champ_as_json(procedure.types_de_champ_private).to_json,
|
||||
direct_uploads_url: rails_direct_uploads_url,
|
||||
drag_icon_url: image_url("icons/drag.svg")
|
||||
}
|
||||
end
|
||||
|
||||
def procedure_data(procedure)
|
||||
{
|
||||
types_de_champ: types_de_champ_as_json(procedure.types_de_champ),
|
||||
types_de_champ_private: types_de_champ_as_json(procedure.types_de_champ_private)
|
||||
}.to_json
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
TOGGLES = {
|
||||
TypeDeChamp.type_champs.fetch(:siret) => :champ_siret?,
|
||||
TypeDeChamp.type_champs.fetch(:integer_number) => :champ_integer_number?,
|
||||
TypeDeChamp.type_champs.fetch(:repetition) => :champ_repetition?
|
||||
}
|
||||
|
||||
def types_de_champ_options
|
||||
types_de_champ = TypeDeChamp.type_de_champs_list_fr
|
||||
|
||||
types_de_champ.select! do |tdc|
|
||||
toggle = TOGGLES[tdc.last]
|
||||
toggle.blank? || Flipflop.send(toggle)
|
||||
end
|
||||
|
||||
types_de_champ
|
||||
end
|
||||
|
||||
def types_de_champ_as_json(types_de_champ)
|
||||
types_de_champ.as_json(except: [:created_at, :updated_at],
|
||||
methods: [:piece_justificative_template_filename, :piece_justificative_template_url],
|
||||
include: { drop_down_list: { only: :value } })
|
||||
end
|
||||
end
|
||||
|
|
131
app/javascript/new_design/administrateur/DraggableItem.js
Normal file
131
app/javascript/new_design/administrateur/DraggableItem.js
Normal file
|
@ -0,0 +1,131 @@
|
|||
export default {
|
||||
props: ['state', 'update', 'index', 'item', 'prefix'],
|
||||
computed: {
|
||||
isDirty() {
|
||||
return (
|
||||
this.state.version &&
|
||||
this.state.unsavedInvalidItems.size > 0 &&
|
||||
this.state.unsavedItems.has(this.itemId)
|
||||
);
|
||||
},
|
||||
isInvalid() {
|
||||
if (this.deleted) {
|
||||
return false;
|
||||
}
|
||||
if (this.libelle) {
|
||||
return !this.libelle.trim();
|
||||
}
|
||||
return true;
|
||||
},
|
||||
itemId() {
|
||||
return this.item.id || this.clientId;
|
||||
},
|
||||
changeLog() {
|
||||
return [this.itemId, !this.isInvalid];
|
||||
},
|
||||
itemClassName() {
|
||||
const classNames = [`draggable-item-${this.index}`];
|
||||
if (this.isHeaderSection) {
|
||||
classNames.push('type-header-section');
|
||||
}
|
||||
if (this.isDirty) {
|
||||
if (this.isInvalid) {
|
||||
classNames.push('invalid');
|
||||
} else {
|
||||
classNames.push('dirty');
|
||||
}
|
||||
}
|
||||
return classNames.join(' ');
|
||||
},
|
||||
isDropDown() {
|
||||
return [
|
||||
'drop_down_list',
|
||||
'multiple_drop_down_list',
|
||||
'linked_drop_down_list'
|
||||
].includes(this.typeChamp);
|
||||
},
|
||||
isFile() {
|
||||
return this.typeChamp === 'piece_justificative';
|
||||
},
|
||||
isCarte() {
|
||||
return this.typeChamp === 'carte';
|
||||
},
|
||||
isExplication() {
|
||||
return this.typeChamp === 'explication';
|
||||
},
|
||||
isHeaderSection() {
|
||||
return this.typeChamp === 'header_section';
|
||||
},
|
||||
options() {
|
||||
const options = this.item.options;
|
||||
for (let key of Object.keys(options)) {
|
||||
options[key] = castBoolean(options[key]);
|
||||
}
|
||||
return options;
|
||||
},
|
||||
attribute() {
|
||||
if (this.state.isAnnotation) {
|
||||
return 'types_de_champ_private_attributes';
|
||||
} else {
|
||||
return 'types_de_champ_attributes';
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
typeChamp: this.item.type_champ,
|
||||
libelle: this.item.libelle,
|
||||
mandatory: this.item.mandatory,
|
||||
description: this.item.description,
|
||||
dropDownList: this.item.drop_down_list.value,
|
||||
deleted: false,
|
||||
clientId: `id-${clientIds++}`
|
||||
};
|
||||
},
|
||||
created() {
|
||||
for (let path of PATHS_TO_WATCH) {
|
||||
this.$watch(path, () => this.update(this.changeLog));
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.isInvalid) {
|
||||
this.update(this.changeLog, false);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
removeChamp(item) {
|
||||
if (item.id) {
|
||||
this.deleted = true;
|
||||
} else {
|
||||
const index = this.state.typesDeChamp.indexOf(item);
|
||||
this.state.typesDeChamp.splice(index, 1);
|
||||
this.update([this.itemId, true]);
|
||||
}
|
||||
},
|
||||
nameFor(name) {
|
||||
return `${this.prefix}[${this.attribute}][${this.index}][${name}]`;
|
||||
},
|
||||
elementIdFor(name) {
|
||||
return `${this.prefix}_${this.attribute}_${this.index}_${name}`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const PATHS_TO_WATCH = [
|
||||
'typeChamp',
|
||||
'libelle',
|
||||
'mandatory',
|
||||
'description',
|
||||
'dropDownList',
|
||||
'options.quartiers_prioritaires',
|
||||
'options.cadastres',
|
||||
'options.parcelles_agricoles',
|
||||
'index',
|
||||
'deleted'
|
||||
];
|
||||
|
||||
function castBoolean(value) {
|
||||
return value && value != 0;
|
||||
}
|
||||
|
||||
let clientIds = 0;
|
165
app/javascript/new_design/administrateur/DraggableItem.vue
Normal file
165
app/javascript/new_design/administrateur/DraggableItem.vue
Normal file
|
@ -0,0 +1,165 @@
|
|||
<template>
|
||||
<div class="deleted" v-if="deleted">
|
||||
<input type="hidden" :name="nameFor('id')" :value="item.id">
|
||||
<input type="hidden" :name="nameFor('_destroy')" value="true">
|
||||
</div>
|
||||
|
||||
<div class="draggable-item" v-else :class="itemClassName">
|
||||
<div class="row section head" :class="{ hr: !isHeaderSection }">
|
||||
<div class="handle">
|
||||
<img :src="state.dragIconUrl" alt="">
|
||||
</div>
|
||||
<div class="cell">
|
||||
<select :name="nameFor('type_champ')" v-model="typeChamp" class="small-margin small inline">
|
||||
<option v-for="option in state.typesDeChampOptions" :key="option[1]" :value="option[1]">
|
||||
{{ option[0] }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="row delete">
|
||||
<div v-if="isDirty" class="error-message">
|
||||
<span v-if="isInvalid" class="content">
|
||||
Le libellé doit être rempli.
|
||||
</span>
|
||||
<span v-else class="content">
|
||||
<template v-if="state.isAnnotation">
|
||||
Modifications non sauvegardées. Le libellé doit être rempli sur tous les annotations.
|
||||
</template>
|
||||
<template v-else>
|
||||
Modifications non sauvegardées. Le libellé doit être rempli sur tous les champs.
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<button class="button danger" @click.prevent="removeChamp(item)">
|
||||
Supprimer
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row section" :class="{ hr: isDropDown || isFile || isCarte }">
|
||||
<div class="column shift-left">
|
||||
<div class="cell libelle">
|
||||
<label :for="elementIdFor('libelle')">
|
||||
Libellé
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
:id="elementIdFor('libelle')"
|
||||
:name="nameFor('libelle')"
|
||||
v-model="libelle"
|
||||
class="small-margin small"
|
||||
:class="{ error: isDirty && isInvalid }">
|
||||
</div>
|
||||
|
||||
<div class="cell" v-show="!isHeaderSection && !isExplication && !state.isAnnotation">
|
||||
<label :for="elementIdFor('mandatory')">
|
||||
Obligatoire
|
||||
</label>
|
||||
<input :name="nameFor('mandatory')" type="hidden" value="0">
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="elementIdFor('mandatory')"
|
||||
:name="nameFor('mandatory')"
|
||||
v-model="mandatory"
|
||||
class="small-margin small"
|
||||
value="1">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="cell" v-show="!isHeaderSection">
|
||||
<label :for="elementIdFor('description')">
|
||||
Description
|
||||
</label>
|
||||
<textarea
|
||||
:id="elementIdFor('description')"
|
||||
:name="nameFor('description')"
|
||||
v-model="description"
|
||||
rows=3
|
||||
cols=40
|
||||
class="small-margin small">
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row section shift-left" v-show="!isHeaderSection">
|
||||
<div class="cell" v-show="isDropDown">
|
||||
<label :for="elementIdFor('drop_down_list')">
|
||||
Liste déroulante
|
||||
</label>
|
||||
<textarea
|
||||
:id="elementIdFor('drop_down_list')"
|
||||
:name="nameFor('drop_down_list_attributes[value]')"
|
||||
v-model="dropDownList"
|
||||
rows=3
|
||||
cols=40
|
||||
placeholder="Ecrire une valeur par ligne et --valeur-- pour un séparateur."
|
||||
class="small-margin small">
|
||||
</textarea>
|
||||
</div>
|
||||
<div class="cell" v-show="isFile">
|
||||
<label :for="elementIdFor('piece_justificative_template')">
|
||||
Modèle
|
||||
</label>
|
||||
<template v-if="item.piece_justificative_template_url">
|
||||
<a :href="item.piece_justificative_template_url" target="_blank">
|
||||
{{item.piece_justificative_template_filename}}
|
||||
</a>
|
||||
<br> Modifier :
|
||||
</template>
|
||||
<input
|
||||
type="file"
|
||||
:id="elementIdFor('piece_justificative_template')"
|
||||
:name="nameFor('piece_justificative_template')"
|
||||
:data-direct-upload-url="state.directUploadsUrl"
|
||||
@change="update(changeLog)"
|
||||
class="small-margin small">
|
||||
</div>
|
||||
<div class="cell" v-show="isCarte">
|
||||
<label>
|
||||
Utilisation de la cartographie
|
||||
</label>
|
||||
<div class="carte-options">
|
||||
<label :for="elementIdFor('quartiers_prioritaires')">
|
||||
<input :name="nameFor('quartiers_prioritaires')" type="hidden" value="0">
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="elementIdFor('quartiers_prioritaires')"
|
||||
:name="nameFor('quartiers_prioritaires')"
|
||||
v-model="options.quartiers_prioritaires"
|
||||
class="small-margin small"
|
||||
value="1">
|
||||
Quartiers prioritaires
|
||||
</label>
|
||||
<label :for="elementIdFor('cadastres')">
|
||||
<input :name="nameFor('cadastres')" type="hidden" value="0">
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="elementIdFor('cadastres')"
|
||||
:name="nameFor('cadastres')"
|
||||
v-model="options.cadastres"
|
||||
class="small-margin small"
|
||||
value="1">
|
||||
Cadastres
|
||||
</label>
|
||||
<label :for="elementIdFor('parcelles_agricoles')">
|
||||
<input :name="nameFor('parcelles_agricoles')" type="hidden" value="0">
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="elementIdFor('parcelles_agricoles')"
|
||||
:name="nameFor('parcelles_agricoles')"
|
||||
v-model="options.parcelles_agricoles"
|
||||
class="small-margin small"
|
||||
value="1">
|
||||
Parcelles Agricoles
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="meta">
|
||||
<input type="hidden" :name="nameFor('order_place')" :value="index">
|
||||
<input type="hidden" :name="nameFor('id')" :value="item.id">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script src="./DraggableItem.js"></script>
|
12
app/javascript/new_design/administrateur/DraggableList.js
Normal file
12
app/javascript/new_design/administrateur/DraggableList.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
export default {
|
||||
props: ['state', 'version', 'update', 'updateAll'],
|
||||
methods: {
|
||||
addChamp() {
|
||||
this.state.typesDeChamp.push({
|
||||
type_champ: 'text',
|
||||
drop_down_list: {},
|
||||
options: {}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
42
app/javascript/new_design/administrateur/DraggableList.vue
Normal file
42
app/javascript/new_design/administrateur/DraggableList.vue
Normal file
|
@ -0,0 +1,42 @@
|
|||
<template>
|
||||
<div class="champs-editor">
|
||||
<div v-if="state.typesDeChamp.length > 3" class="header">
|
||||
<button class="button" @click.prevent="addChamp">
|
||||
<template v-if="state.isAnnotation">
|
||||
Ajouter une annotation
|
||||
</template>
|
||||
<template v-else>
|
||||
Ajouter un champ
|
||||
</template>
|
||||
</button>
|
||||
|
||||
<button class="button primary" @click.prevent="updateAll">Enregistrer</button>
|
||||
</div>
|
||||
|
||||
<Draggable :list="state.typesDeChamp" :options="{handle:'.handle'}">
|
||||
<DraggableItem
|
||||
v-for="(item, index) in state.typesDeChamp"
|
||||
prefix="procedure"
|
||||
:state="state"
|
||||
:update="update"
|
||||
:index="index"
|
||||
:item="item"
|
||||
:key="item.id" />
|
||||
</Draggable>
|
||||
|
||||
<div class="footer">
|
||||
<button class="button" @click.prevent="addChamp">
|
||||
<template v-if="state.isAnnotation">
|
||||
Ajouter une annotation
|
||||
</template>
|
||||
<template v-else>
|
||||
Ajouter un champ
|
||||
</template>
|
||||
</button>
|
||||
|
||||
<button class="button primary" @click.prevent="updateAll">Enregistrer</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script src="./DraggableList.js"></script>
|
109
app/javascript/new_design/administrateur/champs-editor.js
Normal file
109
app/javascript/new_design/administrateur/champs-editor.js
Normal file
|
@ -0,0 +1,109 @@
|
|||
import Vue from 'vue';
|
||||
import Draggable from 'vuedraggable';
|
||||
import { fire, debounce } from '@utils';
|
||||
|
||||
import DraggableItem from './DraggableItem';
|
||||
import DraggableList from './DraggableList';
|
||||
|
||||
Vue.component('Draggable', Draggable);
|
||||
Vue.component('DraggableItem', DraggableItem);
|
||||
|
||||
addEventListener('DOMContentLoaded', () => {
|
||||
const el = document.querySelector('#champs-editor');
|
||||
const { directUploadsUrl, dragIconUrl } = el.dataset;
|
||||
|
||||
const state = {
|
||||
typesDeChamp: JSON.parse(el.dataset.typesDeChamp),
|
||||
typesDeChampOptions: JSON.parse(el.dataset.typesDeChampOptions),
|
||||
directUploadsUrl,
|
||||
dragIconUrl,
|
||||
isAnnotation: el.dataset.type === 'annotation',
|
||||
unsavedItems: new Set(),
|
||||
unsavedInvalidItems: new Set(),
|
||||
version: 1
|
||||
};
|
||||
|
||||
new Vue({
|
||||
el,
|
||||
data: {
|
||||
state,
|
||||
update: null
|
||||
},
|
||||
render(h) {
|
||||
return h(DraggableList, {
|
||||
props: {
|
||||
state: this.state,
|
||||
update: this.update,
|
||||
updateAll: this.updateAll
|
||||
}
|
||||
});
|
||||
},
|
||||
mounted() {
|
||||
const [update, updateAll] = createUpdateFunctions(
|
||||
this,
|
||||
state.isAnnotation
|
||||
);
|
||||
|
||||
this.update = update;
|
||||
this.updateAll = updateAll;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function createUpdateFunctions(app, isAnnotation) {
|
||||
let isSaving = false;
|
||||
const form = app.$el.closest('form');
|
||||
|
||||
const update = ([id, isValid], refresh = true) => {
|
||||
app.state.unsavedItems.add(id);
|
||||
if (isValid) {
|
||||
app.state.unsavedInvalidItems.delete(id);
|
||||
} else {
|
||||
app.state.unsavedInvalidItems.add(id);
|
||||
}
|
||||
if (refresh) {
|
||||
app.state.version += 1;
|
||||
}
|
||||
updateAll();
|
||||
};
|
||||
|
||||
const updateAll = debounce(() => {
|
||||
if (isSaving) {
|
||||
updateAll();
|
||||
} else if (
|
||||
app.state.typesDeChamp.length > 0 &&
|
||||
app.state.unsavedInvalidItems.size === 0
|
||||
) {
|
||||
isSaving = true;
|
||||
app.state.unsavedItems.clear();
|
||||
app.state.version += 1;
|
||||
fire(form, 'submit');
|
||||
}
|
||||
}, 500);
|
||||
|
||||
addEventListener('ProcedureUpdated', event => {
|
||||
const { types_de_champ, types_de_champ_private } = event.detail;
|
||||
|
||||
app.state.typesDeChamp = isAnnotation
|
||||
? types_de_champ_private
|
||||
: types_de_champ;
|
||||
isSaving = false;
|
||||
updateFileInputs();
|
||||
});
|
||||
|
||||
return [update, updateAll];
|
||||
}
|
||||
|
||||
// This is needed du to the way ActiveStorage javascript integration works.
|
||||
// It is built to be used with traditional forms. Another way would be to not use
|
||||
// high level ActiveStorage abstractions (and maybe this is what we should do in the future).
|
||||
function updateFileInputs() {
|
||||
for (let element of document.querySelectorAll('.direct-upload')) {
|
||||
let hiddenInput = element.nextElementSibling;
|
||||
let fileInput = hiddenInput.nextElementSibling;
|
||||
element.remove();
|
||||
hiddenInput.remove();
|
||||
fileInput.value = '';
|
||||
fileInput.removeAttribute('disabled');
|
||||
}
|
||||
}
|
|
@ -22,6 +22,8 @@ import '../new_design/select2';
|
|||
import '../new_design/champs/carte';
|
||||
import '../new_design/champs/linked-drop-down-list';
|
||||
|
||||
import '../new_design/administrateur/champs-editor';
|
||||
|
||||
import { toggleCondidentielExplanation } from '../new_design/avis';
|
||||
import { scrollMessagerie } from '../new_design/messagerie';
|
||||
import { showMotivation, motivationCancel } from '../new_design/state-button';
|
||||
|
@ -30,6 +32,7 @@ import { replaceSemicolonByComma } from '../new_design/avis';
|
|||
|
||||
// This is the global application namespace where we expose helpers used from rails views
|
||||
const DS = {
|
||||
fire: (eventName, data) => Rails.fire(document, eventName, data),
|
||||
toggleCondidentielExplanation,
|
||||
scrollMessagerie,
|
||||
showMotivation,
|
||||
|
|
|
@ -3,11 +3,10 @@ class AutoArchiveProcedureJob < ApplicationJob
|
|||
|
||||
def perform(*args)
|
||||
Procedure.publiees.where("auto_archive_on <= ?", Date.today).each do |procedure|
|
||||
gestionnaire = procedure.gestionnaire_for_cron_job
|
||||
|
||||
procedure.dossiers.state_en_construction.find_each do |dossier|
|
||||
dossier.passer_en_instruction!(gestionnaire)
|
||||
end
|
||||
procedure
|
||||
.dossiers
|
||||
.state_en_construction
|
||||
.find_each(&:passer_automatiquement_en_instruction!)
|
||||
|
||||
procedure.archive!
|
||||
end
|
||||
|
|
|
@ -3,17 +3,18 @@ class AutoReceiveDossiersForProcedureJob < ApplicationJob
|
|||
|
||||
def perform(procedure_id, state)
|
||||
procedure = Procedure.find(procedure_id)
|
||||
gestionnaire = procedure.gestionnaire_for_cron_job
|
||||
|
||||
case state
|
||||
when Dossier.states.fetch(:en_instruction)
|
||||
procedure.dossiers.state_en_construction.find_each do |dossier|
|
||||
dossier.passer_en_instruction!(gestionnaire)
|
||||
end
|
||||
procedure
|
||||
.dossiers
|
||||
.state_en_construction
|
||||
.find_each(&:passer_automatiquement_en_instruction!)
|
||||
when Dossier.states.fetch(:accepte)
|
||||
procedure.dossiers.state_en_construction.find_each do |dossier|
|
||||
dossier.accepter!(gestionnaire, '')
|
||||
end
|
||||
procedure
|
||||
.dossiers
|
||||
.state_en_construction
|
||||
.find_each(&:accepter_automatiquement!)
|
||||
else
|
||||
raise "Receiving Procedure##{procedure_id} in invalid state \"#{state}\""
|
||||
end
|
||||
|
|
|
@ -274,6 +274,12 @@ class Dossier < ApplicationRecord
|
|||
log_dossier_operation(gestionnaire, :passer_en_instruction)
|
||||
end
|
||||
|
||||
def passer_automatiquement_en_instruction!
|
||||
en_instruction!
|
||||
|
||||
log_dossier_operation(nil, :passer_en_instruction, automatic_operation: true)
|
||||
end
|
||||
|
||||
def repasser_en_construction!(gestionnaire)
|
||||
self.en_instruction_at = nil
|
||||
en_construction!
|
||||
|
@ -295,6 +301,19 @@ class Dossier < ApplicationRecord
|
|||
log_dossier_operation(gestionnaire, :accepter)
|
||||
end
|
||||
|
||||
def accepter_automatiquement!
|
||||
self.en_instruction_at ||= Time.zone.now
|
||||
|
||||
accepte!
|
||||
|
||||
if attestation.nil?
|
||||
update(attestation: build_attestation)
|
||||
end
|
||||
|
||||
NotificationMailer.send_closed_notification(self).deliver_later
|
||||
log_dossier_operation(nil, :accepter, automatic_operation: true)
|
||||
end
|
||||
|
||||
def refuser!(gestionnaire, motivation)
|
||||
self.motivation = motivation
|
||||
self.en_instruction_at ||= Time.zone.now
|
||||
|
@ -317,10 +336,11 @@ class Dossier < ApplicationRecord
|
|||
|
||||
private
|
||||
|
||||
def log_dossier_operation(gestionnaire, operation)
|
||||
def log_dossier_operation(gestionnaire, operation, automatic_operation: false)
|
||||
dossier_operation_logs.create(
|
||||
gestionnaire: gestionnaire,
|
||||
operation: DossierOperationLog.operations.fetch(operation)
|
||||
operation: DossierOperationLog.operations.fetch(operation),
|
||||
automatic_operation: automatic_operation
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
class DropDownList < ApplicationRecord
|
||||
belongs_to :type_de_champ
|
||||
|
||||
before_validation :clean_value
|
||||
|
||||
def options
|
||||
result = value.split(/[\r\n]|[\r]|[\n]|[\n\r]/).reject(&:empty?)
|
||||
result.blank? ? [] : [''] + result
|
||||
|
@ -13,4 +15,12 @@ class DropDownList < ApplicationRecord
|
|||
def multiple
|
||||
type_de_champ.type_champ == TypeDeChamp.type_champs.fetch(:multiple_drop_down_list)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def clean_value
|
||||
value = read_attribute(:value)
|
||||
value = value ? value.split("\r\n").map(&:strip).join("\r\n") : ''
|
||||
write_attribute(:value, value)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -30,9 +30,9 @@ class Procedure < ApplicationRecord
|
|||
has_one_attached :notice
|
||||
has_one_attached :deliberation
|
||||
|
||||
accepts_nested_attributes_for :types_de_champ, :reject_if => proc { |attributes| attributes['libelle'].blank? }, :allow_destroy => true
|
||||
accepts_nested_attributes_for :types_de_piece_justificative, :reject_if => proc { |attributes| attributes['libelle'].blank? }, :allow_destroy => true
|
||||
accepts_nested_attributes_for :types_de_champ_private
|
||||
accepts_nested_attributes_for :types_de_champ, reject_if: proc { |attributes| attributes['libelle'].blank? }, allow_destroy: true
|
||||
accepts_nested_attributes_for :types_de_champ_private, reject_if: proc { |attributes| attributes['libelle'].blank? }, allow_destroy: true
|
||||
accepts_nested_attributes_for :types_de_piece_justificative, reject_if: proc { |attributes| attributes['libelle'].blank? }, allow_destroy: true
|
||||
|
||||
mount_uploader :logo, ProcedureLogoUploader
|
||||
|
||||
|
@ -68,6 +68,7 @@ class Procedure < ApplicationRecord
|
|||
|
||||
before_save :update_juridique_required
|
||||
before_save :update_durees_conservation_required
|
||||
before_create :ensure_path_exists
|
||||
|
||||
include AASM
|
||||
|
||||
|
@ -350,12 +351,6 @@ class Procedure < ApplicationRecord
|
|||
where.not(aasm_state: :archivee).where("path LIKE ?", "%#{path}%")
|
||||
end
|
||||
|
||||
def gestionnaire_for_cron_job
|
||||
administrateur_email = administrateur.email
|
||||
gestionnaire = Gestionnaire.find_by(email: administrateur_email)
|
||||
gestionnaire || gestionnaires.first
|
||||
end
|
||||
|
||||
def populate_champ_stable_ids
|
||||
TypeDeChamp.where(procedure: self, stable_id: nil).find_each do |type_de_champ|
|
||||
type_de_champ.update_column(:stable_id, type_de_champ.id)
|
||||
|
@ -458,4 +453,12 @@ class Procedure < ApplicationRecord
|
|||
times.percentile(p).ceil
|
||||
end
|
||||
end
|
||||
|
||||
def ensure_path_exists
|
||||
if Flipflop.publish_draft?
|
||||
if self.path.nil?
|
||||
self.path = SecureRandom.uuid
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -83,7 +83,7 @@ class TypeDeChamp < ApplicationRecord
|
|||
|
||||
has_one_attached :piece_justificative_template
|
||||
|
||||
accepts_nested_attributes_for :drop_down_list
|
||||
accepts_nested_attributes_for :drop_down_list, update_only: true
|
||||
accepts_nested_attributes_for :types_de_champ, allow_destroy: true
|
||||
|
||||
validates :libelle, presence: true, allow_blank: false, allow_nil: false
|
||||
|
@ -161,6 +161,18 @@ class TypeDeChamp < ApplicationRecord
|
|||
"TypesDeChamp::#{type_champ.classify}TypeDeChamp"
|
||||
end
|
||||
|
||||
def piece_justificative_template_url
|
||||
if piece_justificative_template.attached?
|
||||
Rails.application.routes.url_helpers.url_for(piece_justificative_template)
|
||||
end
|
||||
end
|
||||
|
||||
def piece_justificative_template_filename
|
||||
if piece_justificative_template.attached?
|
||||
piece_justificative_template.filename
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def setup_procedure
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
class NumberService
|
||||
def self.to_number(string)
|
||||
string.to_s
|
||||
end
|
||||
end
|
|
@ -1,9 +1,10 @@
|
|||
- champs_editor_path = Flipflop.new_champs_editor? ? champs_procedure_path(@procedure) : admin_procedure_types_de_champ_path(@procedure)
|
||||
.row.white-back
|
||||
.alert.alert-info
|
||||
.form-group
|
||||
%p
|
||||
Pour vos nouveaux besoins de pièces jointes, nous vous invitons à
|
||||
= link_to(admin_procedure_types_de_champ_path(@procedure)) do
|
||||
= link_to(champs_editor_path) do
|
||||
rajouter des champs
|
||||
\ <em>pièce justificative</em> à votre formulaire.
|
||||
|
||||
|
@ -17,7 +18,7 @@
|
|||
%li Support des pièces de grande taille (jusqu’à 200 Mo par pièce)
|
||||
%li Pas de limite de soumission simultanée de plusieurs pièces, pour une expérience usager plus confortable
|
||||
|
||||
= link_to(admin_procedure_types_de_champ_path(@procedure), class: 'btn btn-success') do
|
||||
= link_to(champs_editor_path, class: 'btn btn-success') do
|
||||
Ajouter un champ PJ
|
||||
|
||||
- if @procedure.has_old_pjs?
|
||||
|
|
|
@ -11,20 +11,6 @@
|
|||
= f.text_area :description, rows: '6', placeholder: 'Description du projet', class: 'form-control'
|
||||
|
||||
- if !@procedure.locked?
|
||||
- if Flipflop.publish_draft?
|
||||
.form-group
|
||||
%h4 Lien public*
|
||||
.procedure-lien
|
||||
%span.prefix
|
||||
= commencer_test_url(path: '')
|
||||
= f.text_field :path, value: @path, class: 'form-control', data: { remote: true, debounce: true, url: admin_procedures_available_path, params: { id: @procedure.id }.to_query(:procedure) }
|
||||
%p.unavailable-path-message.text-warning
|
||||
- if @availability != Procedure::PATH_AVAILABLE
|
||||
= render partial: 'unavailable', locals: { availability: @availability }
|
||||
%p.help-block
|
||||
%i.fa.fa-info-circle
|
||||
Afin de faciliter l’accès à la démarche, vous êtes invité à personnaliser l’adresse d'accès public. C'est ce lien qu'il va falloir communiquer aux usagers souhaitant faire la démarche.
|
||||
|
||||
.form-group
|
||||
%h4 Conservation des données
|
||||
= f.label :duree_conservation_dossiers_dans_ds, "Sur demarches-simplifiees.fr* (durée en mois après le début de l’instruction)"
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
%li{ class: @draft_class }
|
||||
%a{ :href => "#{url_for :admin_procedures_draft}" }
|
||||
%h5.text-primary
|
||||
Brouillons
|
||||
- if Flipflop.publish_draft?
|
||||
En test
|
||||
- else
|
||||
Brouillons
|
||||
|
||||
%li{ class: @active_class }
|
||||
%a{ :href => "#{url_for :admin_procedures}" }
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
%br
|
||||
Si vous voulez l’utiliser, l’ancienne démarche sera archivée lors de la publication de la démarche (plus accessible du public).
|
||||
- when Procedure::PATH_NOT_AVAILABLE_BROUILLON
|
||||
Un brouillon de démarche existe déjà avec ce lien.
|
||||
Une démarche en test existe déjà avec ce lien.
|
||||
- when Procedure::PATH_NOT_AVAILABLE
|
||||
Ce lien est déjà utilisé par une démarche.
|
||||
%br
|
||||
|
|
|
@ -42,25 +42,45 @@
|
|||
%i.fa.fa-remove
|
||||
Annuler
|
||||
|
||||
- if @procedure.locked?
|
||||
#procedure_locked
|
||||
.alert.alert-info
|
||||
Cette démarche a été publiée, certains éléments ne peuvent plus être modifiés.
|
||||
|
||||
.lien-demarche
|
||||
%h3 Lien démarche
|
||||
%h3
|
||||
- if @procedure.brouillon_avec_lien?
|
||||
Test et publication
|
||||
- else
|
||||
Publication
|
||||
%div{ style: 'margin-top: 30px;' }
|
||||
- if @procedure.archivee?
|
||||
.alert.alert-info
|
||||
Cette démarche est archivée et n’est donc pas accessible par le public.
|
||||
Cette démarche est <strong>archivée</strong> et n’est donc plus accessible par le public.
|
||||
- elsif @procedure.publiee?
|
||||
Cette démarche est <strong>publiée</strong>, certains éléments ne peuvent plus être modifiés.
|
||||
Pour y accéder vous pouvez utiliser le lien :
|
||||
= link_to procedure_lien(@procedure), sanitize_url(procedure_lien(@procedure)), target: :blank
|
||||
%br
|
||||
%br
|
||||
Attention, diffusez toujours le <strong>lien complet</strong> affiché ci-dessus, et non pas un lien générique vers demarches-simplifiees.fr. Ne dites pas non plus aux usagers de se rendre sur le site générique demarches-simplifiees.fr, donnez-leur toujours le lien complet.
|
||||
- elsif @procedure.brouillon_avec_lien?
|
||||
- if @procedure.gestionnaires.present? && @procedure.service.present?
|
||||
= link_to procedure_lien(@procedure), sanitize_url(procedure_lien(@procedure)), target: :blank
|
||||
%p
|
||||
Cette démarche est actuellement <strong>en test</strong>,
|
||||
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.
|
||||
%br
|
||||
|
||||
%h4 Ce que vous pouvez faire lorsque vous êtes en test
|
||||
%p
|
||||
Profitez de la phase de test pour tester la saisie de dossiers, ainsi que toutes les fonctionnalités associées (instruction, emails automatiques, attestations, etc.).
|
||||
%p
|
||||
Vous pouvez effectuer toutes les modifications que vous souhaitez sur votre démarche pendant cette phase de test.
|
||||
%p
|
||||
Les dossiers qui seront remplis pendant la phase de test seront automatiquement supprimés lors de la modification ou la publication de votre démarche.
|
||||
%br
|
||||
|
||||
%h4 Ce qui se passe lorsque vous passez en publication
|
||||
%p
|
||||
Une fois que vous êtes prêt à publier définitivement votre démarche, cliquez sur le bouton "Publier" pour choisir le lien définitif de votre démarche, les modifications sur la démarches ne seront alors plus possibles.
|
||||
|
||||
- else
|
||||
.alert.alert-info
|
||||
Pour pouvoir tester cette démarche, vous devez d’abord lui affecter
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
#flash_message.center
|
||||
- flash.each do |key, value|
|
||||
- sticky = defined?(sticky) ? sticky : false
|
||||
- fixed = defined?(fixed) ? fixed : false
|
||||
- if value.class == Array
|
||||
.alert{ class: flash_class(key, sticky) }
|
||||
.alert{ class: flash_class(key, sticky: sticky, fixed: fixed) }
|
||||
- value.each do |message|
|
||||
= sanitize(message)
|
||||
%br
|
||||
- else
|
||||
.alert{ class: flash_class(key, sticky) }
|
||||
.alert{ class: flash_class(key, sticky: sticky, fixed: fixed) }
|
||||
= sanitize(value)
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
})();
|
||||
|
||||
sendinblue.identify('#{current_administrateur.email}', {
|
||||
'nb_demarches_brouillons': '#{current_administrateur.procedures.brouillons.count}',
|
||||
'nb_demarches_actives': '#{current_administrateur.procedures.publiees.count}',
|
||||
'nb_demarches_archivees': '#{current_administrateur.procedures.archivees.count}',
|
||||
'sign_in_count' : '#{current_administrateur.sign_in_count}',
|
||||
'created_at' : '#{current_administrateur.created_at}',
|
||||
'active' : '#{current_administrateur.active}'
|
||||
'DS_NB_DEMARCHES_BROUILLONS': '#{current_administrateur.procedures.brouillons.count}',
|
||||
'DS_NB_DEMARCHES_ACTIVES': '#{current_administrateur.procedures.publiees.count}',
|
||||
'DS_NB_DEMARCHES_ARCHIVES': '#{current_administrateur.procedures.archivees.count}',
|
||||
'DS_SIGN_IN_COUNT' : '#{current_administrateur.sign_in_count}',
|
||||
'DS_CREATED_AT' : '#{current_administrateur.created_at}',
|
||||
'DS_ACTIVE' : '#{current_administrateur.active}',
|
||||
'DS_ID' : '#{current_administrateur.id}'
|
||||
// Dans l'ideal :
|
||||
// 'nom' : //pour personnaliser les emails
|
||||
// 'prenom' : //pour personnaliser les emails
|
||||
|
|
8
app/views/layouts/commencer/_no_procedure.html.haml
Normal file
8
app/views/layouts/commencer/_no_procedure.html.haml
Normal file
|
@ -0,0 +1,8 @@
|
|||
.no-procedure
|
||||
= image_tag "landing/hero/dematerialiser.svg", class: "paperless-logo"
|
||||
.baseline.center
|
||||
%h3 Un outil simple
|
||||
%p
|
||||
pour gérer les formulaires
|
||||
%br
|
||||
administratifs dématérialisés.
|
|
@ -0,0 +1,8 @@
|
|||
.procedure-logos
|
||||
= image_tag logo_img(procedure)
|
||||
- if procedure.euro_flag
|
||||
= image_tag "flag_of_europe.svg"
|
||||
%h2.procedure-title
|
||||
= procedure.libelle
|
||||
.procedure-description
|
||||
= h string_to_html(procedure.description)
|
|
@ -11,13 +11,16 @@
|
|||
#procedure-list
|
||||
%a#draft-procedures{ :href => "#{url_for :admin_procedures_draft}" }
|
||||
.procedure-list-element{ class: @draft_class }
|
||||
Brouillons
|
||||
- if Flipflop.publish_draft?
|
||||
En test
|
||||
- else
|
||||
Brouillons
|
||||
.badge.progress-bar-default
|
||||
= current_administrateur.procedures.brouillons.count
|
||||
|
||||
%a#active-procedures{ :href => "#{url_for :admin_procedures}" }
|
||||
.procedure-list-element{ class: @active_class }
|
||||
Actives
|
||||
Publiées
|
||||
.badge.progress-bar-success
|
||||
= current_administrateur.procedures.publiees.count
|
||||
|
||||
|
|
|
@ -12,7 +12,10 @@
|
|||
#procedure-list
|
||||
%a#onglet-infos{ href: url_for(admin_procedure_path(@procedure)) }
|
||||
.procedure-list-element{ class: ('active' if active == 'Informations') }
|
||||
Publication
|
||||
- if @procedure.brouillon_avec_lien?
|
||||
Test et publication
|
||||
- else
|
||||
Publication
|
||||
|
||||
%a#onglet-description{ href: url_for(edit_admin_procedure_path(@procedure)) }
|
||||
.procedure-list-element{ class: ('active' if active == 'Description') }
|
||||
|
@ -31,7 +34,8 @@
|
|||
%p.missing-steps (à compléter)
|
||||
|
||||
- if !@procedure.locked?
|
||||
%a#onglet-champs{ href: url_for(admin_procedure_types_de_champ_path(@procedure)) }
|
||||
- champs_editor_path = Flipflop.new_champs_editor? ? champs_procedure_path(@procedure) : admin_procedure_types_de_champ_path(@procedure)
|
||||
%a#onglet-champs{ href: champs_editor_path }
|
||||
.procedure-list-element{ class: ('active' if active == 'Champs') }
|
||||
Champs
|
||||
|
||||
|
@ -41,7 +45,8 @@
|
|||
Pièces jointes
|
||||
|
||||
- if !@procedure.locked?
|
||||
%a#onglet-private-champs{ href: url_for(admin_procedure_types_de_champ_private_path(@procedure)) }
|
||||
- annotations_editor_path = Flipflop.new_champs_editor? ? annotations_procedure_path(@procedure) : admin_procedure_types_de_champ_private_path(@procedure)
|
||||
%a#onglet-private-champs{ href: annotations_editor_path }
|
||||
.procedure-list-element{ class: ('active' if active == 'Annotations privées') }
|
||||
Annotations privées
|
||||
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
- procedure = @procedure || @dossier&.procedure || nil
|
||||
|
||||
- content_for :content do
|
||||
.two-columns.procedure-context
|
||||
.columns-container
|
||||
|
||||
.column.procedure-preview
|
||||
- procedure = @dossier.procedure
|
||||
.procedure-logos
|
||||
= image_tag logo_img(procedure)
|
||||
- if procedure.euro_flag
|
||||
= image_tag "flag_of_europe.svg"
|
||||
%h2.procedure-title
|
||||
= procedure.libelle
|
||||
.procedure-description
|
||||
= h string_to_html(procedure.description)
|
||||
- if procedure
|
||||
= render partial: 'layouts/commencer/procedure_description', locals: { procedure: procedure }
|
||||
- else
|
||||
= render partial: 'layouts/commencer/no_procedure'
|
||||
|
||||
.column.procedure-context-content
|
||||
= yield
|
||||
|
||||
- content_for :footer do
|
||||
= render partial: "new_user/dossiers/dossier_footer", locals: { dossier: @dossier }
|
||||
- if procedure
|
||||
= render partial: 'new_user/procedure_footer', locals: { procedure: procedure, dossier: @dossier }
|
||||
- else
|
||||
= render partial: 'new_user/dossiers/index_footer'
|
||||
|
||||
= render template: 'layouts/application'
|
||||
|
|
|
@ -38,7 +38,7 @@ as well as a link to its edit page.
|
|||
<% end %>
|
||||
|
||||
<% if procedure.publiee? && procedure.dossiers.empty? %>
|
||||
<%= link_to 'passer en brouillon', draft_manager_procedure_path(procedure), method: :post, class: 'button' %>
|
||||
<%= link_to 'repasser en test', draft_manager_procedure_path(procedure), method: :post, class: 'button' %>
|
||||
<% end %>
|
||||
|
||||
<%= link_to 'supprimer la démarche', hide_manager_procedure_path(procedure), method: :post, class: 'button', data: { confirm: "Confirmez-vous la suppression de la démarche ?" } %>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
.sub-header
|
||||
.container
|
||||
.container.flex.justify-between.align-baseline
|
||||
%ul.breadcrumbs
|
||||
- steps.each do |step|
|
||||
%li= step
|
||||
- if defined?(preview) && preview
|
||||
= link_to "Prévisualiser le formulaire", apercu_procedure_path(@procedure), target: "_blank", class: 'button'
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
= render partial: 'new_administrateur/breadcrumbs',
|
||||
locals: { steps: [link_to('Démarches', admin_procedures_path),
|
||||
link_to(@procedure.libelle, admin_procedure_path(@procedure)),
|
||||
'Configuration des annotations privées'], preview: true }
|
||||
|
||||
.container
|
||||
%h1 Configuration des annotations privées
|
||||
%br
|
||||
|
||||
= form_for @procedure, remote: true, html: { class: 'form' } do |form|
|
||||
#champs-editor{ data: types_de_champ_private_data(@procedure) }
|
||||
.spinner
|
12
app/views/new_administrateur/procedures/champs.html.haml
Normal file
12
app/views/new_administrateur/procedures/champs.html.haml
Normal file
|
@ -0,0 +1,12 @@
|
|||
= render partial: 'new_administrateur/breadcrumbs',
|
||||
locals: { steps: [link_to('Démarches', admin_procedures_path),
|
||||
link_to(@procedure.libelle, admin_procedure_path(@procedure)),
|
||||
'Configuration des champs'], preview: true }
|
||||
|
||||
.container
|
||||
%h1 Configuration des champs
|
||||
%br
|
||||
|
||||
= form_for @procedure, remote: true, html: { class: 'form' } do |form|
|
||||
#champs-editor{ data: types_de_champ_data(@procedure) }
|
||||
.spinner
|
3
app/views/new_administrateur/procedures/update.js.erb
Normal file
3
app/views/new_administrateur/procedures/update.js.erb
Normal file
|
@ -0,0 +1,3 @@
|
|||
<%= render_flash timeout: 6000, fixed: true %>
|
||||
|
||||
<%= fire_event(:ProcedureUpdated, procedure_data(@procedure)) %>
|
|
@ -3,7 +3,10 @@
|
|||
.flex.justify-between
|
||||
%ul.breadcrumbs
|
||||
%li
|
||||
= link_to dossier.procedure.libelle.truncate_words(10), gestionnaire_procedure_path(dossier.procedure), title: dossier.procedure.libelle
|
||||
= link_to gestionnaire_procedure_path(dossier.procedure), title: dossier.procedure.libelle do
|
||||
- if dossier.procedure.brouillon?
|
||||
%span.badge démarche en test
|
||||
= dossier.procedure.libelle.truncate_words(10)
|
||||
%li
|
||||
= "Dossier nº #{dossier.id}"
|
||||
.mixed-buttons-bar
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
%footer.dossier-footer
|
||||
%footer.procedure-footer
|
||||
.container
|
||||
- service = dossier.procedure.service
|
||||
- service = procedure.service
|
||||
- if service.present?
|
||||
%ul.footer-row.footer-columns
|
||||
%li.footer-column
|
||||
|
@ -15,12 +15,12 @@
|
|||
%li.footer-column
|
||||
%h3.footer-header Poser une question sur votre dossier :
|
||||
%p
|
||||
- if dossier.brouillon?
|
||||
Par email :
|
||||
= link_to service.email, "mailto:#{service.email}"
|
||||
- else
|
||||
- if dossier.present? && !dossier.brouillon?
|
||||
Directement
|
||||
= link_to "par la messagerie", messagerie_dossier_path(dossier)
|
||||
- else
|
||||
Par email :
|
||||
= link_to service.email, "mailto:#{service.email}"
|
||||
|
||||
%p
|
||||
Par téléphone :
|
||||
|
@ -29,7 +29,7 @@
|
|||
%p
|
||||
Horaires : #{ service.horaires.sub(/\S/, &:downcase) }
|
||||
|
||||
- politiques = politiques_conservation_de_donnees(dossier.procedure)
|
||||
- politiques = politiques_conservation_de_donnees(procedure)
|
||||
- if politiques.present?
|
||||
%li.footer-column
|
||||
%h3.footer-header Conservation des données :
|
||||
|
@ -37,4 +37,4 @@
|
|||
%p= politique
|
||||
|
||||
.footer-row.footer-bottom-line
|
||||
= render partial: "new_user/dossiers/general_footer_row", locals: { dossier: @dossier }
|
||||
= render partial: 'new_user/general_footer_row', locals: { dossier: dossier }
|
|
@ -1,4 +1,4 @@
|
|||
%footer.dossier-footer
|
||||
%footer.procedure-footer
|
||||
.container
|
||||
.footer-row.footer-bottom-line
|
||||
= render partial: "new_user/dossiers/general_footer_row", locals: { dossier: nil }
|
||||
= render partial: "new_user/general_footer_row", locals: { dossier: nil }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
- content_for(:title, "Modification du brouillon nº #{@dossier.id} (#{@dossier.procedure.libelle})")
|
||||
|
||||
- content_for :footer do
|
||||
= render partial: "new_user/dossiers/dossier_footer", locals: { dossier: @dossier }
|
||||
= render partial: "new_user/procedure_footer", locals: { procedure: @dossier.procedure, dossier: @dossier }
|
||||
|
||||
.dossier-header.sub-header
|
||||
.container
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
- content_for(:title, "Demande · Dossier nº #{@dossier.id} (#{@dossier.procedure.libelle})")
|
||||
|
||||
- content_for :footer do
|
||||
= render partial: "new_user/dossiers/dossier_footer", locals: { dossier: @dossier }
|
||||
= render partial: "new_user/procedure_footer", locals: { procedure: @dossier.procedure, dossier: @dossier }
|
||||
|
||||
#dossier-show
|
||||
= render partial: 'new_user/dossiers/show/header', locals: { dossier: @dossier }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
- content_for(:title, "Informations sur l’établissement")
|
||||
|
||||
- content_for :footer do
|
||||
= render partial: "new_user/dossiers/dossier_footer", locals: { dossier: @dossier }
|
||||
= render partial: "new_user/procedure_footer", locals: { procedure: @dossier.procedure, dossier: @dossier }
|
||||
|
||||
.etablissement
|
||||
.container
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
- content_for(:title, "Dossier bien envoyé (#{@dossier.procedure.libelle})")
|
||||
|
||||
- content_for :footer do
|
||||
= render partial: "new_user/dossiers/dossier_footer", locals: { dossier: @dossier }
|
||||
= render partial: "new_user/procedure_footer", locals: { procedure: @dossier.procedure, dossier: @dossier }
|
||||
|
||||
.merci
|
||||
.container
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
- content_for(:title, "Messagerie · Dossier nº #{@dossier.id} (#{@dossier.procedure.libelle})")
|
||||
|
||||
- content_for :footer do
|
||||
= render partial: "new_user/dossiers/dossier_footer", locals: { dossier: @dossier }
|
||||
= render partial: "new_user/procedure_footer", locals: { procedure: @dossier.procedure, dossier: @dossier }
|
||||
|
||||
#dossier-show
|
||||
= render partial: 'new_user/dossiers/show/header', locals: { dossier: @dossier }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
- content_for(:title, "Modifier · Dossier nº #{@dossier.id} (#{@dossier.procedure.libelle})")
|
||||
|
||||
- content_for :footer do
|
||||
= render partial: "new_user/dossiers/dossier_footer", locals: { dossier: @dossier }
|
||||
= render partial: "new_user/procedure_footer", locals: { procedure: @dossier.procedure, dossier: @dossier }
|
||||
|
||||
#dossier-show
|
||||
= render partial: 'new_user/dossiers/show/header', locals: { dossier: @dossier }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
- content_for(:title, "Résumé · Dossier nº #{@dossier.id} (#{@dossier.procedure.libelle})")
|
||||
|
||||
- content_for :footer do
|
||||
= render partial: "new_user/dossiers/dossier_footer", locals: { dossier: @dossier }
|
||||
= render partial: "new_user/procedure_footer", locals: { procedure: @dossier.procedure, dossier: @dossier }
|
||||
|
||||
#dossier-show
|
||||
= render partial: 'new_user/dossiers/show/header', locals: { dossier: @dossier }
|
||||
|
|
|
@ -1,33 +1,22 @@
|
|||
.two-columns.auth
|
||||
.columns-container
|
||||
.column.procedure-preview
|
||||
= image_tag "landing/hero/dematerialiser.svg", class: "paperless-logo"
|
||||
.baseline.center
|
||||
%h3 Un outil simple
|
||||
%p
|
||||
pour gérer les formulaires
|
||||
%br
|
||||
administratifs dématérialisés.
|
||||
.auth-form
|
||||
= devise_error_messages!
|
||||
= form_for resource, url: user_registration_path, html: { class: "form" } do |f|
|
||||
%h1 Créez-vous un compte demarches-simplifiees.fr
|
||||
|
||||
.column.procedure-context-content.auth-form
|
||||
= devise_error_messages!
|
||||
= form_for resource, url: user_registration_path, html: { class: "form" } do |f|
|
||||
%h1 Créez-vous un compte
|
||||
= f.label :email, "Email"
|
||||
= f.text_field :email, autofocus: true, placeholder: "Votre adresse email"
|
||||
|
||||
= f.label :email, "Email"
|
||||
= f.text_field :email, autofocus: true
|
||||
= f.label :password, "Mot de passe"
|
||||
= f.password_field :password, value: @user.password, placeholder: "8 caractères minimum"
|
||||
|
||||
= f.label :password, "Mot de passe"
|
||||
= f.password_field :password, value: @user.password, placeholder: "8 caractères minimum"
|
||||
= f.submit "Créer un compte", class: "button large primary expand"
|
||||
|
||||
= f.submit "Créer un compte", class: "button large primary expand"
|
||||
.separation.center
|
||||
ou
|
||||
|
||||
.separation.center
|
||||
ou
|
||||
.center
|
||||
= image_tag "login-with-fc-hover.svg", style: "display: none"
|
||||
= link_to "", france_connect_particulier_path, class: "login-with-fc"
|
||||
|
||||
.center
|
||||
= image_tag "login-with-fc-hover.svg", style: "display: none"
|
||||
= link_to "", france_connect_particulier_path, class: "login-with-fc"
|
||||
|
||||
.center
|
||||
= link_to "Qu’est-ce que FranceConnect ?", "https://franceconnect.gouv.fr/", target: "_blank", class: "link"
|
||||
.center
|
||||
= link_to "Qu’est-ce que FranceConnect ?", "https://franceconnect.gouv.fr/", target: "_blank", class: "link"
|
||||
|
|
|
@ -1,63 +1,39 @@
|
|||
.two-columns.auth
|
||||
.columns-container
|
||||
.column.procedure-preview
|
||||
- if !@dossier
|
||||
= image_tag "landing/hero/dematerialiser.svg", class: "paperless-logo"
|
||||
.baseline.center
|
||||
%h3 Un outil simple
|
||||
%p
|
||||
pour gérer les formulaires
|
||||
%br
|
||||
administratifs dématérialisés.
|
||||
- else
|
||||
.auth-form.sign-in-form
|
||||
- if resource_name == :user
|
||||
%p.register
|
||||
%span
|
||||
Nouveau sur demarches-simplifiees.fr ?
|
||||
= link_to "Créer un compte", new_registration_path(resource_name), class: "button primary auth-signup-button"
|
||||
|
||||
%hr
|
||||
|
||||
= form_for @user, url: user_session_path, html: { class: "form" } do |f|
|
||||
%h1 Connectez-vous
|
||||
|
||||
= f.label :email, "Email"
|
||||
= f.text_field :email, autofocus: true
|
||||
|
||||
= f.label :password, "Mot de passe"
|
||||
= f.password_field :password, value: @user.password, placeholder: "8 caractères minimum"
|
||||
|
||||
.auth-options
|
||||
- if devise_mapping.rememberable?
|
||||
%div
|
||||
= f.check_box :remember_me, as: :boolean
|
||||
= f.label :remember_me, "Se souvenir de moi", class: 'remember-me'
|
||||
|
||||
- if [:user, :gestionnaire].include?(resource_name)
|
||||
.text-right
|
||||
= link_to "Fermer", users_no_procedure_url, class: "link close-procedure"
|
||||
.procedure-logos
|
||||
= image_tag logo_img(@dossier.procedure)
|
||||
- if @dossier.procedure.euro_flag
|
||||
= image_tag "flag_of_europe.svg"
|
||||
= link_to "Mot de passe oublié ?", new_password_path(resource_name), class: "link"
|
||||
|
||||
%h2.procedure-title
|
||||
= @dossier.procedure.libelle
|
||||
.procedure-description
|
||||
= h simple_format(@dossier.procedure.description)
|
||||
= f.submit "Se connecter", class: "button large primary expand"
|
||||
|
||||
.column.procedure-context-content.auth-form.sign-in-form
|
||||
- if resource_name == :user
|
||||
%p.register
|
||||
%span
|
||||
Nouveau sur demarches-simplifiees.fr ?
|
||||
= link_to "Créer un compte", new_registration_path(resource_name), class: "button primary auth-signup-button"
|
||||
.separation.center
|
||||
ou
|
||||
|
||||
%hr
|
||||
.center
|
||||
= image_tag "login-with-fc-hover.svg", style: "display: none"
|
||||
= link_to "", france_connect_particulier_path, class: "login-with-fc"
|
||||
|
||||
= form_for @user, url: user_session_path, html: { class: "form" } do |f|
|
||||
%h1 Connectez-vous
|
||||
|
||||
= f.label :email, "Email"
|
||||
= f.text_field :email, autofocus: true
|
||||
|
||||
= f.label :password, "Mot de passe"
|
||||
= f.password_field :password, value: @user.password, placeholder: "8 caractères minimum"
|
||||
|
||||
.auth-options
|
||||
- if devise_mapping.rememberable?
|
||||
%div
|
||||
= f.check_box :remember_me, as: :boolean
|
||||
= f.label :remember_me, "Se souvenir de moi", class: 'remember-me'
|
||||
|
||||
- if [:user, :gestionnaire].include?(resource_name)
|
||||
.text-right
|
||||
= link_to "Mot de passe oublié ?", new_password_path(resource_name), class: "link"
|
||||
|
||||
= f.submit "Se connecter", class: "button large primary expand"
|
||||
|
||||
.separation.center
|
||||
ou
|
||||
|
||||
.center
|
||||
= image_tag "login-with-fc-hover.svg", style: "display: none"
|
||||
= link_to "", france_connect_particulier_path, class: "login-with-fc"
|
||||
|
||||
.center
|
||||
= link_to "Qu’est-ce que FranceConnect ?", "https://franceconnect.gouv.fr/", target: "_blank", class: "link"
|
||||
.center
|
||||
= link_to "Qu’est-ce que FranceConnect ?", "https://franceconnect.gouv.fr/", target: "_blank", class: "link"
|
||||
|
|
|
@ -19,6 +19,7 @@ Flipflop.configure do
|
|||
feature :publish_draft
|
||||
feature :support_form
|
||||
feature :enable_email_login_token
|
||||
feature :new_champs_editor
|
||||
|
||||
group :production do
|
||||
feature :remote_storage,
|
||||
|
|
|
@ -357,9 +357,11 @@ Rails.application.routes.draw do
|
|||
#
|
||||
|
||||
scope module: 'new_administrateur' do
|
||||
resources :procedures, only: [] do
|
||||
resources :procedures, only: [:update] do
|
||||
member do
|
||||
get 'apercu'
|
||||
get 'champs'
|
||||
get 'annotations'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
const path = require('path');
|
||||
const { environment } = require('@rails/webpacker');
|
||||
const { VueLoaderPlugin } = require('vue-loader');
|
||||
const vue = require('./loaders/vue');
|
||||
|
||||
const resolve = {
|
||||
alias: {
|
||||
|
@ -9,4 +11,6 @@ const resolve = {
|
|||
|
||||
environment.config.merge({ resolve });
|
||||
|
||||
environment.plugins.append('VueLoaderPlugin', new VueLoaderPlugin());
|
||||
environment.loaders.append('vue', vue);
|
||||
module.exports = environment;
|
||||
|
|
8
config/webpack/loaders/vue.js
Normal file
8
config/webpack/loaders/vue.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
module.exports = {
|
||||
test: /\.vue(\.erb)?$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'vue-loader'
|
||||
}
|
||||
]
|
||||
};
|
|
@ -14,6 +14,7 @@ default: &default
|
|||
cache_manifest: false
|
||||
|
||||
extensions:
|
||||
- .vue
|
||||
- .js
|
||||
- .sass
|
||||
- .scss
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
class AddAutomaticOperationColumnToDossierOperationLog < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_column :dossier_operation_logs, :automatic_operation, :bool, default: false, null: false
|
||||
end
|
||||
end
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2018_12_21_103901) do
|
||||
ActiveRecord::Schema.define(version: 2019_01_10_163655) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
@ -218,6 +218,7 @@ ActiveRecord::Schema.define(version: 2018_12_21_103901) do
|
|||
t.bigint "gestionnaire_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.boolean "automatic_operation", default: false, null: false
|
||||
t.index ["dossier_id"], name: "index_dossier_operation_logs_on_dossier_id"
|
||||
t.index ["gestionnaire_id"], name: "index_dossier_operation_logs_on_gestionnaire_id"
|
||||
end
|
||||
|
|
|
@ -15,7 +15,11 @@
|
|||
"rails-ujs": "^5.2.1",
|
||||
"ramda": "^0.25.0",
|
||||
"select2": "^4.0.6-rc.1",
|
||||
"turbolinks": "^5.2.0"
|
||||
"turbolinks": "^5.2.0",
|
||||
"vue": "^2.5.21",
|
||||
"vue-loader": "^15.5.1",
|
||||
"vue-template-compiler": "^2.5.21",
|
||||
"vuedraggable": "^2.16.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eclint": "^2.8.0",
|
||||
|
|
|
@ -182,6 +182,7 @@ describe Admin::ProceduresController, type: :controller do
|
|||
|
||||
context 'when procedure is correctly save' do
|
||||
before do
|
||||
Flipflop::FeatureSet.current.test!.switch!(:new_champs_editor, true)
|
||||
post :create, params: { procedure: procedure_params }
|
||||
end
|
||||
|
||||
|
@ -197,8 +198,7 @@ describe Admin::ProceduresController, type: :controller do
|
|||
it { expect(subject.duree_conservation_dossiers_hors_ds).to eq(duree_conservation_dossiers_hors_ds) }
|
||||
end
|
||||
|
||||
it { is_expected.to redirect_to(admin_procedure_types_de_champ_path(procedure_id: Procedure.last.id)) }
|
||||
|
||||
it { is_expected.to redirect_to(champs_procedure_path(Procedure.last)) }
|
||||
it { expect(flash[:notice]).to be_present }
|
||||
end
|
||||
|
||||
|
@ -723,7 +723,7 @@ describe Admin::ProceduresController, type: :controller do
|
|||
let(:path) { procedure_owned.path }
|
||||
|
||||
it {
|
||||
expect(response.body).to include('Un brouillon de démarche existe déjà avec ce lien.')
|
||||
expect(response.body).to include('Une démarche en test existe déjà avec ce lien.')
|
||||
}
|
||||
end
|
||||
|
||||
|
|
77
spec/controllers/concerns/procedure_context_concern_spec.rb
Normal file
77
spec/controllers/concerns/procedure_context_concern_spec.rb
Normal file
|
@ -0,0 +1,77 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ProcedureContextConcern, type: :controller do
|
||||
class TestController < ActionController::Base
|
||||
include ProcedureContextConcern
|
||||
|
||||
before_action :restore_procedure_context
|
||||
|
||||
def index
|
||||
head :ok
|
||||
end
|
||||
end
|
||||
|
||||
controller TestController do
|
||||
end
|
||||
|
||||
describe '#restore_procedure_context' do
|
||||
subject { get :index }
|
||||
|
||||
context 'when no return location has been stored' do
|
||||
it 'succeeds, without defining a procedure on the controller' do
|
||||
expect(subject.status).to eq 200
|
||||
expect(assigns(:procedure)).to be nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no procedure_id is present in the stored return location' do
|
||||
before do
|
||||
controller.store_location_for(:user, dossiers_path)
|
||||
end
|
||||
|
||||
it 'succeeds, without assigns a procedure on the controller' do
|
||||
expect(subject.status).to eq 200
|
||||
expect(assigns(:procedure)).to be nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a procedure location has been stored' do
|
||||
context 'when the stored procedure does not exist' do
|
||||
before do
|
||||
controller.store_location_for(:user, new_dossier_path(procedure_id: '0'))
|
||||
end
|
||||
|
||||
it 'redirects with an error' do
|
||||
expect(subject.status).to eq 302
|
||||
expect(subject).to redirect_to root_path
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the stored procedure is not published' do
|
||||
let(:procedure) { create :procedure }
|
||||
|
||||
before do
|
||||
controller.store_location_for(:user, new_dossier_path(procedure_id: procedure.id))
|
||||
end
|
||||
|
||||
it 'redirects with an error' do
|
||||
expect(subject.status).to eq 302
|
||||
expect(subject).to redirect_to root_path
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the stored procedure exists' do
|
||||
let(:procedure) { create :procedure, :published }
|
||||
|
||||
before do
|
||||
controller.store_location_for(:user, new_dossier_path(procedure_id: procedure.id))
|
||||
end
|
||||
|
||||
it 'succeeds, and assigns the procedure on the controller' do
|
||||
expect(subject.status).to eq 200
|
||||
expect(assigns(:procedure)).to eq procedure
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
41
spec/controllers/devise/store_location_extension_spec.rb
Normal file
41
spec/controllers/devise/store_location_extension_spec.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Devise::StoreLocationExtension, type: :controller do
|
||||
class TestController < ActionController::Base
|
||||
include Devise::Controllers::StoreLocation
|
||||
include Devise::StoreLocationExtension
|
||||
end
|
||||
|
||||
controller TestController do
|
||||
end
|
||||
|
||||
describe '#get_stored_location_for' do
|
||||
context 'when a location has been previously stored' do
|
||||
before { subject.store_location_for(:user, dossiers_path) }
|
||||
|
||||
it 'returns the stored location without clearing it' do
|
||||
expect(subject.get_stored_location_for(:user)).to eq dossiers_path
|
||||
expect(subject.stored_location_for(:user)).to eq dossiers_path
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no location has been stored' do
|
||||
it { expect(subject.get_stored_location_for(:user)).to be nil }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#clear_stored_location_for" do
|
||||
context 'when a location has been previously stored' do
|
||||
before { subject.store_location_for(:user, dossiers_path) }
|
||||
|
||||
it 'delete the stored location' do
|
||||
subject.clear_stored_location_for(:user)
|
||||
expect(subject.stored_location_for(:user)).to be nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no location has been stored' do
|
||||
it { expect(subject.clear_stored_location_for(:user)).to be nil }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -171,7 +171,10 @@ describe InvitesController, type: :controller do
|
|||
let(:email) { nil }
|
||||
|
||||
context 'and user is not connected' do
|
||||
it { is_expected.to redirect_to new_user_session_path }
|
||||
it 'redirects to the sign-in page' do
|
||||
expect(subject).to redirect_to new_user_session_path
|
||||
expect(controller.stored_location_for(:user)).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
context 'and user is connected' do
|
||||
|
@ -186,20 +189,29 @@ describe InvitesController, type: :controller do
|
|||
context 'when email is blank' do
|
||||
let(:email) { '' }
|
||||
|
||||
it { is_expected.to redirect_to new_user_session_path }
|
||||
it 'redirects to the sign-in page' do
|
||||
expect(subject).to redirect_to new_user_session_path
|
||||
expect(controller.stored_location_for(:user)).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
context 'when email is not blank' do
|
||||
context 'when email is affected at an user' do
|
||||
let(:email) { user.email }
|
||||
|
||||
it { is_expected.to redirect_to new_user_session_path }
|
||||
it 'redirects to the sign-in page' do
|
||||
expect(subject).to redirect_to new_user_session_path
|
||||
expect(controller.stored_location_for(:user)).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
context 'when email is not affected at an user' do
|
||||
let(:email) { 'new_user@octo.com' }
|
||||
|
||||
it { is_expected.to redirect_to new_user_registration_path(user: { email: email }) }
|
||||
it 'redirects to the sign-up page' do
|
||||
expect(subject).to redirect_to new_user_registration_path(user: { email: email })
|
||||
expect(controller.stored_location_for(:user)).to be_present
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -213,6 +225,10 @@ describe InvitesController, type: :controller do
|
|||
|
||||
subject! { get :show, params: { id: invite.id } }
|
||||
|
||||
it 'clears the stored return location' do
|
||||
expect(controller.stored_location_for(:user)).to be nil
|
||||
end
|
||||
|
||||
context 'when invitation ID is attached at the user email account' do
|
||||
let(:email) { user.email }
|
||||
|
||||
|
|
|
@ -854,6 +854,11 @@ describe NewUser::DossiersController, type: :controller do
|
|||
|
||||
subject { get :new, params: { procedure_id: procedure_id } }
|
||||
|
||||
it 'clears the stored procedure context' do
|
||||
subject
|
||||
expect(controller.stored_location_for(:user)).to be nil
|
||||
end
|
||||
|
||||
context 'when params procedure_id is present' do
|
||||
context 'when procedure_id is valid' do
|
||||
context 'when user is logged in' do
|
||||
|
|
|
@ -9,17 +9,30 @@ describe Users::RegistrationsController, type: :controller do
|
|||
end
|
||||
|
||||
describe '#new' do
|
||||
subject! { get :new }
|
||||
subject { get :new }
|
||||
|
||||
it { expect(response).to have_http_status(:ok) }
|
||||
it { expect(response).to render_template(:new) }
|
||||
it { expect(subject).to have_http_status(:ok) }
|
||||
it { expect(subject).to render_template(:new) }
|
||||
|
||||
context 'when an email address is provided' do
|
||||
render_views true
|
||||
subject! { get :new, params: { user: { email: 'test@exemple.fr' } } }
|
||||
subject { get :new, params: { user: { email: 'test@exemple.fr' } } }
|
||||
|
||||
it 'prefills the form with the email address' do
|
||||
expect(response.body).to include('test@exemple.fr')
|
||||
expect(subject.body).to include('test@exemple.fr')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a procedure location has been stored' do
|
||||
let(:procedure) { create :procedure, :published }
|
||||
|
||||
before do
|
||||
controller.store_location_for(:user, new_dossier_path(procedure_id: procedure.id))
|
||||
end
|
||||
|
||||
it 'makes the saved procedure available' do
|
||||
expect(subject.status).to eq 200
|
||||
expect(assigns(:procedure)).to eq procedure
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -173,38 +173,18 @@ describe Users::SessionsController, type: :controller do
|
|||
describe '#new' do
|
||||
subject { get :new }
|
||||
|
||||
context 'when procedure_id is not present in user_return_to session params' do
|
||||
it { expect(subject.status).to eq 200 }
|
||||
end
|
||||
it { expect(subject.status).to eq 200 }
|
||||
|
||||
context 'when procedure_id is present in user_return_to session params' do
|
||||
context 'when procedure_id does not exist' do
|
||||
before do
|
||||
session["user_return_to"] = '?procedure_id=0'
|
||||
end
|
||||
context 'when a procedure location has been stored' do
|
||||
let(:procedure) { create :procedure, :published }
|
||||
|
||||
it { expect(subject.status).to eq 302 }
|
||||
it { expect(subject).to redirect_to root_path }
|
||||
before do
|
||||
controller.store_location_for(:user, new_dossier_path(procedure_id: procedure.id))
|
||||
end
|
||||
|
||||
context 'when procedure is not published' do
|
||||
let(:procedure) { create :procedure }
|
||||
before do
|
||||
session["user_return_to"] = "?procedure_id=#{procedure.id}"
|
||||
end
|
||||
|
||||
it { expect(subject.status).to eq 302 }
|
||||
it { expect(subject).to redirect_to root_path }
|
||||
end
|
||||
|
||||
context 'when procedure_id exist' do
|
||||
let(:procedure) { create :procedure, :published }
|
||||
|
||||
before do
|
||||
session["user_return_to"] = "?procedure_id=#{procedure.id}"
|
||||
end
|
||||
|
||||
it { expect(subject.status).to eq 200 }
|
||||
it 'makes the saved procedure available' do
|
||||
expect(subject.status).to eq 200
|
||||
expect(assigns(:procedure)).to eq procedure
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,9 +5,11 @@ feature 'As an administrateur I wanna create a new procedure', js: true do
|
|||
include ProcedureSpecHelper
|
||||
|
||||
let(:administrateur) { create(:administrateur, :with_procedure) }
|
||||
let(:test_strategy) { Flipflop::FeatureSet.current.test! }
|
||||
|
||||
before do
|
||||
Flipflop::FeatureSet.current.test!.switch!(:publish_draft, true)
|
||||
test_strategy.switch!(:publish_draft, true)
|
||||
test_strategy.switch!(:new_champs_editor, true)
|
||||
login_as administrateur, scope: :administrateur
|
||||
visit root_path
|
||||
end
|
||||
|
@ -45,13 +47,13 @@ feature 'As an administrateur I wanna create a new procedure', js: true do
|
|||
fill_in_dummy_procedure_details
|
||||
click_on 'save-procedure'
|
||||
|
||||
expect(page).to have_current_path(admin_procedure_types_de_champ_path(Procedure.last))
|
||||
expect(page).to have_current_path(champs_procedure_path(Procedure.last))
|
||||
end
|
||||
end
|
||||
|
||||
context "when publish_draft disabled" do
|
||||
before do
|
||||
Flipflop::FeatureSet.current.test!.switch!(:publish_draft, false)
|
||||
test_strategy.switch!(:publish_draft, false)
|
||||
end
|
||||
|
||||
scenario 'Finding save button for new procedure, libelle, description and cadre_juridique required' do
|
||||
|
@ -68,7 +70,7 @@ feature 'As an administrateur I wanna create a new procedure', js: true do
|
|||
fill_in_dummy_procedure_details(fill_path: false)
|
||||
click_on 'save-procedure'
|
||||
|
||||
expect(page).to have_current_path(admin_procedure_types_de_champ_path(Procedure.last))
|
||||
expect(page).to have_current_path(champs_procedure_path(Procedure.last))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -95,12 +97,22 @@ feature 'As an administrateur I wanna create a new procedure', js: true do
|
|||
end
|
||||
|
||||
scenario 'Add champ, add file, visualize them in procedure preview' do
|
||||
fill_in 'procedure_types_de_champ_attributes_0_libelle', with: 'libelle de champ'
|
||||
click_on 'add_type_de_champ'
|
||||
expect(page).to have_current_path(admin_procedure_types_de_champ_path(Procedure.last))
|
||||
expect(page).to have_selector('#procedure_types_de_champ_attributes_1_libelle')
|
||||
expect(Procedure.last.types_de_champ.first.libelle).to eq('libelle de champ')
|
||||
page.refresh
|
||||
expect(page).to have_current_path(champs_procedure_path(Procedure.last))
|
||||
|
||||
within '.footer' do
|
||||
click_on 'Ajouter un champ'
|
||||
end
|
||||
expect(page).to have_selector('#procedure_types_de_champ_attributes_0_libelle')
|
||||
fill_in 'procedure_types_de_champ_attributes_0_libelle', with: 'libelle de champ'
|
||||
expect(page).to have_content('Champs enregistrés')
|
||||
|
||||
within '.footer' do
|
||||
click_on 'Ajouter un champ'
|
||||
end
|
||||
expect(page).to have_selector('#procedure_types_de_champ_attributes_1_libelle')
|
||||
|
||||
click_on Procedure.last.libelle
|
||||
click_on 'onglet-pieces'
|
||||
expect(page).to have_current_path(admin_procedure_pieces_justificatives_path(Procedure.last))
|
||||
fill_in 'procedure_types_de_piece_justificative_attributes_0_libelle', with: 'libelle de piece'
|
||||
|
@ -117,8 +129,15 @@ feature 'As an administrateur I wanna create a new procedure', js: true do
|
|||
end
|
||||
|
||||
scenario 'After adding champ and file, make publication' do
|
||||
page.refresh
|
||||
|
||||
within '.footer' do
|
||||
click_on 'Ajouter un champ'
|
||||
end
|
||||
fill_in 'procedure_types_de_champ_attributes_0_libelle', with: 'libelle de champ'
|
||||
click_on 'add_type_de_champ'
|
||||
expect(page).to have_content('Champs enregistrés')
|
||||
|
||||
click_on Procedure.last.libelle
|
||||
click_on 'onglet-pieces'
|
||||
|
||||
expect(page).to have_current_path(admin_procedure_pieces_justificatives_path(Procedure.last))
|
||||
|
@ -131,7 +150,7 @@ feature 'As an administrateur I wanna create a new procedure', js: true do
|
|||
find('#publish-procedure').click
|
||||
|
||||
within '#publish-modal' do
|
||||
expect(page).to have_field('procedure_path', with: 'lien-de-la-procedure')
|
||||
expect(page).to have_field('procedure_path')
|
||||
click_on 'publish'
|
||||
end
|
||||
|
||||
|
|
|
@ -2,9 +2,6 @@ module ProcedureSpecHelper
|
|||
def fill_in_dummy_procedure_details(fill_path: true)
|
||||
fill_in 'procedure_libelle', with: 'libelle de la procedure'
|
||||
fill_in 'procedure_description', with: 'description de la procedure'
|
||||
if fill_path
|
||||
fill_in 'procedure_path', with: 'lien-de-la-procedure'
|
||||
end
|
||||
fill_in 'procedure_cadre_juridique', with: 'cadre juridique'
|
||||
fill_in 'procedure_duree_conservation_dossiers_dans_ds', with: '3'
|
||||
fill_in 'procedure_duree_conservation_dossiers_hors_ds', with: '6'
|
||||
|
|
|
@ -26,21 +26,18 @@ feature 'Administrateurs can edit procedures', js: true do
|
|||
administrateur: administrateur)
|
||||
end
|
||||
|
||||
scenario 'the administrator can edit the libelle and the path' do
|
||||
scenario 'the administrator can edit the libelle' do
|
||||
visit admin_procedures_draft_path
|
||||
click_on procedure.libelle
|
||||
click_on 'Description'
|
||||
|
||||
expect(page).to have_field('procedure_libelle', with: procedure.libelle)
|
||||
expect(page).to have_field('procedure_path', with: procedure.path)
|
||||
|
||||
fill_in('procedure_libelle', with: 'Ma petite démarche')
|
||||
fill_in('procedure_path', with: 'nouveau-lien-demarche')
|
||||
|
||||
click_on 'Enregistrer'
|
||||
|
||||
expect(page).to have_field('procedure_libelle', with: 'Ma petite démarche')
|
||||
expect(page).to have_field('procedure_path', with: 'nouveau-lien-demarche')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
95
spec/features/new_administrateur/procedures_spec.rb
Normal file
95
spec/features/new_administrateur/procedures_spec.rb
Normal file
|
@ -0,0 +1,95 @@
|
|||
require 'spec_helper'
|
||||
|
||||
feature 'As an administrateur I edit procedure', js: true do
|
||||
let(:administrateur) { procedure.administrateur }
|
||||
let(:procedure) { create(:procedure) }
|
||||
|
||||
before do
|
||||
login_as administrateur, scope: :administrateur
|
||||
visit champs_procedure_path(procedure)
|
||||
end
|
||||
|
||||
it "Add a new champ" do
|
||||
within '.footer' do
|
||||
click_on 'Ajouter un champ'
|
||||
end
|
||||
expect(page).to have_selector('#procedure_types_de_champ_attributes_0_libelle')
|
||||
fill_in 'procedure_types_de_champ_attributes_0_libelle', with: 'libellé de champ'
|
||||
expect(page).to have_content('Champs enregistrés')
|
||||
|
||||
page.refresh
|
||||
within '.footer' do
|
||||
click_on 'Enregistrer'
|
||||
end
|
||||
|
||||
expect(page).to have_content('Champs enregistrés')
|
||||
end
|
||||
|
||||
it "Add multiple champs" do
|
||||
within '.footer' do
|
||||
click_on 'Ajouter un champ'
|
||||
click_on 'Ajouter un champ'
|
||||
click_on 'Ajouter un champ'
|
||||
click_on 'Ajouter un champ'
|
||||
end
|
||||
expect(page).not_to have_content('Le libellé doit être rempli.')
|
||||
expect(page).not_to have_content('Modifications non sauvegardées.')
|
||||
expect(page).not_to have_content('Champs enregistrés')
|
||||
fill_in 'procedure_types_de_champ_attributes_0_libelle', with: 'libellé de champ 0'
|
||||
|
||||
expect(page).to have_selector('#procedure_types_de_champ_attributes_0_libelle')
|
||||
expect(page).to have_selector('#procedure_types_de_champ_attributes_1_libelle')
|
||||
expect(page).to have_selector('#procedure_types_de_champ_attributes_2_libelle')
|
||||
expect(page).to have_selector('#procedure_types_de_champ_attributes_3_libelle')
|
||||
|
||||
expect(page).to have_content('Le libellé doit être rempli.')
|
||||
expect(page).to have_content('Modifications non sauvegardées.')
|
||||
expect(page).not_to have_content('Champs enregistrés')
|
||||
fill_in 'procedure_types_de_champ_attributes_2_libelle', with: 'libellé de champ 2'
|
||||
|
||||
within '.draggable-item-3' do
|
||||
click_on 'Supprimer'
|
||||
end
|
||||
|
||||
expect(page).to have_content('Le libellé doit être rempli.')
|
||||
expect(page).to have_content('Modifications non sauvegardées.')
|
||||
expect(page).not_to have_content('Champs enregistrés')
|
||||
fill_in 'procedure_types_de_champ_attributes_1_libelle', with: 'libellé de champ 1'
|
||||
|
||||
expect(page).not_to have_content('Le libellé doit être rempli.')
|
||||
expect(page).not_to have_content('Modifications non sauvegardées.')
|
||||
expect(page).to have_content('Champs enregistrés')
|
||||
page.refresh
|
||||
|
||||
expect(page).to have_content('Supprimer', count: 3)
|
||||
end
|
||||
|
||||
it "Remove champs" do
|
||||
within '.footer' do
|
||||
click_on 'Ajouter un champ'
|
||||
end
|
||||
fill_in 'procedure_types_de_champ_attributes_0_libelle', with: 'libellé de champ'
|
||||
expect(page).to have_content('Champs enregistrés')
|
||||
page.refresh
|
||||
|
||||
click_on 'Supprimer'
|
||||
expect(page).to have_content('Champs enregistrés')
|
||||
expect(page).not_to have_content('Supprimer')
|
||||
page.refresh
|
||||
|
||||
expect(page).not_to have_content('Supprimer')
|
||||
end
|
||||
|
||||
it "Only add valid champs" do
|
||||
within '.footer' do
|
||||
click_on 'Ajouter un champ'
|
||||
end
|
||||
expect(page).to have_selector('#procedure_types_de_champ_attributes_0_description')
|
||||
fill_in 'procedure_types_de_champ_attributes_0_description', with: 'déscription du champ'
|
||||
expect(page).to have_content('Le libellé doit être rempli.')
|
||||
expect(page).not_to have_content('Champs enregistrés')
|
||||
|
||||
fill_in 'procedure_types_de_champ_attributes_0_libelle', with: 'libellé de champ'
|
||||
expect(page).to have_content('Champs enregistrés')
|
||||
end
|
||||
end
|
|
@ -34,7 +34,7 @@ feature 'Signing up:' do
|
|||
end
|
||||
|
||||
context 'when visiting a procedure' do
|
||||
let(:procedure) { create :simple_procedure }
|
||||
let(:procedure) { create :simple_procedure, :with_service }
|
||||
|
||||
before do
|
||||
visit commencer_path(path: procedure.path)
|
||||
|
@ -43,13 +43,14 @@ feature 'Signing up:' do
|
|||
scenario 'a new user can sign-up and fill the procedure' do
|
||||
expect(page).to have_current_path new_user_session_path
|
||||
click_on 'Créer un compte'
|
||||
expect_page_to_have_procedure_description(procedure)
|
||||
|
||||
sign_up_with user_email, user_password
|
||||
expect(page).to have_content "nous avons besoin de vérifier votre adresse #{user_email}"
|
||||
|
||||
click_confirmation_link_for user_email
|
||||
expect(page).to have_content 'Votre compte a été activé'
|
||||
expect(page).to have_content procedure.libelle
|
||||
expect_page_to_have_procedure_description(procedure)
|
||||
end
|
||||
end
|
||||
|
53
spec/features/sessions/sign_in_spec.rb
Normal file
53
spec/features/sessions/sign_in_spec.rb
Normal file
|
@ -0,0 +1,53 @@
|
|||
require 'spec_helper'
|
||||
|
||||
feature 'Signin in:' do
|
||||
let!(:user) { create(:user, password: password) }
|
||||
let(:password) { 'testpassword' }
|
||||
|
||||
scenario 'an existing user can sign-in' do
|
||||
visit root_path
|
||||
click_on 'Connexion'
|
||||
|
||||
sign_in_with user.email, password
|
||||
|
||||
expect(page).to have_current_path dossiers_path
|
||||
end
|
||||
|
||||
context 'when visiting a procedure' do
|
||||
let(:procedure) { create :simple_procedure, :with_service }
|
||||
|
||||
before do
|
||||
visit commencer_path(path: procedure.path)
|
||||
end
|
||||
|
||||
scenario 'an existing user can sign-in and fill the procedure' do
|
||||
expect(page).to have_current_path new_user_session_path
|
||||
expect_page_to_have_procedure_description(procedure)
|
||||
|
||||
sign_in_with user.email, password
|
||||
|
||||
expect(page).to have_current_path identite_dossier_path(user.reload.dossiers.last)
|
||||
expect_page_to_have_procedure_description(procedure)
|
||||
expect(page).to have_content "Données d'identité"
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a user is not confirmed yet' do
|
||||
let!(:user) { create(:user, password: password, confirmed_at: nil) }
|
||||
|
||||
# Ideally, when signing-in with an unconfirmed account,
|
||||
# the user would be redirected to the "resend email confirmation" page.
|
||||
#
|
||||
# However the check for unconfirmed accounts is made by Warden every time a page is loaded –
|
||||
# and much earlier than SessionsController#create.
|
||||
#
|
||||
# For now only test the default behavior (an error message is displayed).
|
||||
scenario 'they get an error message' do
|
||||
visit root_path
|
||||
click_on 'Connexion'
|
||||
|
||||
sign_in_with user.email, password
|
||||
expect(page).to have_content 'Vous devez confirmer votre adresse email pour continuer'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -40,6 +40,7 @@ RSpec.describe AutoArchiveProcedureJob, type: :job do
|
|||
it {
|
||||
expect(dossier1.state).to eq Dossier.states.fetch(:brouillon)
|
||||
expect(dossier2.state).to eq Dossier.states.fetch(:en_instruction)
|
||||
expect(dossier2.dossier_operation_logs.pluck(:gestionnaire_id, :operation, :automatic_operation)).to match([[nil, 'passer_en_instruction', true]])
|
||||
expect(dossier3.state).to eq Dossier.states.fetch(:en_instruction)
|
||||
expect(dossier4.state).to eq Dossier.states.fetch(:en_instruction)
|
||||
expect(dossier5.state).to eq Dossier.states.fetch(:en_instruction)
|
||||
|
|
|
@ -13,13 +13,17 @@ RSpec.describe AutoReceiveDossiersForProcedureJob, type: :job do
|
|||
|
||||
before do
|
||||
Timecop.freeze(date)
|
||||
nouveau_dossier1
|
||||
nouveau_dossier2
|
||||
dossier_recu
|
||||
dossier_brouillon
|
||||
dossiers = [
|
||||
nouveau_dossier1,
|
||||
nouveau_dossier2,
|
||||
dossier_recu,
|
||||
dossier_brouillon
|
||||
]
|
||||
|
||||
create(:attestation_template, procedure: procedure)
|
||||
AutoReceiveDossiersForProcedureJob.new.perform(procedure.id, state)
|
||||
|
||||
dossiers.each(&:reload)
|
||||
end
|
||||
|
||||
after { Timecop.return }
|
||||
|
@ -29,17 +33,18 @@ RSpec.describe AutoReceiveDossiersForProcedureJob, type: :job do
|
|||
let(:state) { Dossier.states.fetch(:en_instruction) }
|
||||
|
||||
it {
|
||||
expect(nouveau_dossier1.reload.en_instruction?).to be true
|
||||
expect(nouveau_dossier1.reload.en_instruction_at).to eq(date)
|
||||
expect(nouveau_dossier1.en_instruction?).to be true
|
||||
expect(nouveau_dossier1.en_instruction_at).to eq(date)
|
||||
expect(nouveau_dossier1.dossier_operation_logs.pluck(:gestionnaire_id, :operation, :automatic_operation)).to match([[nil, 'passer_en_instruction', true]])
|
||||
|
||||
expect(nouveau_dossier2.reload.en_instruction?).to be true
|
||||
expect(nouveau_dossier2.reload.en_instruction_at).to eq(date)
|
||||
expect(nouveau_dossier2.en_instruction?).to be true
|
||||
expect(nouveau_dossier2.en_instruction_at).to eq(date)
|
||||
|
||||
expect(dossier_recu.reload.en_instruction?).to be true
|
||||
expect(dossier_recu.reload.en_instruction_at).to eq(instruction_date)
|
||||
expect(dossier_recu.en_instruction?).to be true
|
||||
expect(dossier_recu.en_instruction_at).to eq(instruction_date)
|
||||
|
||||
expect(dossier_brouillon.reload.brouillon?).to be true
|
||||
expect(dossier_brouillon.reload.en_instruction_at).to eq(nil)
|
||||
expect(dossier_brouillon.brouillon?).to be true
|
||||
expect(dossier_brouillon.en_instruction_at).to eq(nil)
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -47,23 +52,24 @@ RSpec.describe AutoReceiveDossiersForProcedureJob, type: :job do
|
|||
let(:state) { Dossier.states.fetch(:accepte) }
|
||||
|
||||
it {
|
||||
expect(nouveau_dossier1.reload.accepte?).to be true
|
||||
expect(nouveau_dossier1.reload.en_instruction_at).to eq(date)
|
||||
expect(nouveau_dossier1.reload.processed_at).to eq(date)
|
||||
expect(nouveau_dossier1.reload.attestation).to be_present
|
||||
expect(nouveau_dossier1.accepte?).to be true
|
||||
expect(nouveau_dossier1.en_instruction_at).to eq(date)
|
||||
expect(nouveau_dossier1.processed_at).to eq(date)
|
||||
expect(nouveau_dossier1.attestation).to be_present
|
||||
expect(nouveau_dossier1.dossier_operation_logs.pluck(:gestionnaire_id, :operation, :automatic_operation)).to match([[nil, 'accepter', true]])
|
||||
|
||||
expect(nouveau_dossier2.reload.accepte?).to be true
|
||||
expect(nouveau_dossier2.reload.en_instruction_at).to eq(date)
|
||||
expect(nouveau_dossier2.reload.processed_at).to eq(date)
|
||||
expect(nouveau_dossier2.reload.attestation).to be_present
|
||||
expect(nouveau_dossier2.accepte?).to be true
|
||||
expect(nouveau_dossier2.en_instruction_at).to eq(date)
|
||||
expect(nouveau_dossier2.processed_at).to eq(date)
|
||||
expect(nouveau_dossier2.attestation).to be_present
|
||||
|
||||
expect(dossier_recu.reload.en_instruction?).to be true
|
||||
expect(dossier_recu.reload.en_instruction_at).to eq(instruction_date)
|
||||
expect(dossier_recu.reload.processed_at).to eq(nil)
|
||||
expect(dossier_recu.en_instruction?).to be true
|
||||
expect(dossier_recu.en_instruction_at).to eq(instruction_date)
|
||||
expect(dossier_recu.processed_at).to eq(nil)
|
||||
|
||||
expect(dossier_brouillon.reload.brouillon?).to be true
|
||||
expect(dossier_brouillon.reload.en_instruction_at).to eq(nil)
|
||||
expect(dossier_brouillon.reload.processed_at).to eq(nil)
|
||||
expect(dossier_brouillon.brouillon?).to be true
|
||||
expect(dossier_brouillon.en_instruction_at).to eq(nil)
|
||||
expect(dossier_brouillon.processed_at).to eq(nil)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -760,4 +760,76 @@ describe Dossier do
|
|||
it { expect(long_expired_dossier).to be_retention_expired }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#accepter!' do
|
||||
let(:dossier) { create(:dossier) }
|
||||
let!(:gestionnaire) { create(:gestionnaire) }
|
||||
let!(:now) { Time.zone.parse('01/01/2100') }
|
||||
let(:attestation) { Attestation.new }
|
||||
|
||||
before do
|
||||
allow(NotificationMailer).to receive(:send_closed_notification).and_return(double(deliver_later: true))
|
||||
allow(dossier).to receive(:build_attestation).and_return(attestation)
|
||||
|
||||
Timecop.freeze(now)
|
||||
dossier.accepter!(gestionnaire, 'motivation')
|
||||
dossier.reload
|
||||
end
|
||||
|
||||
after { Timecop.return }
|
||||
|
||||
it { expect(dossier.motivation).to eq('motivation') }
|
||||
it { expect(dossier.en_instruction_at).to eq(now) }
|
||||
it { expect(dossier.processed_at).to eq(now) }
|
||||
it { expect(dossier.state).to eq('accepte') }
|
||||
it { expect(dossier.dossier_operation_logs.pluck(:gestionnaire_id, :operation, :automatic_operation)).to match([[gestionnaire.id, 'accepter', false]]) }
|
||||
it { expect(NotificationMailer).to have_received(:send_closed_notification).with(dossier) }
|
||||
it { expect(dossier.attestation).to eq(attestation) }
|
||||
end
|
||||
|
||||
describe '#accepter_automatiquement!' do
|
||||
let(:dossier) { create(:dossier) }
|
||||
let!(:now) { Time.zone.parse('01/01/2100') }
|
||||
let(:attestation) { Attestation.new }
|
||||
|
||||
before do
|
||||
allow(NotificationMailer).to receive(:send_closed_notification).and_return(double(deliver_later: true))
|
||||
allow(dossier).to receive(:build_attestation).and_return(attestation)
|
||||
|
||||
Timecop.freeze(now)
|
||||
dossier.accepter_automatiquement!
|
||||
dossier.reload
|
||||
end
|
||||
|
||||
after { Timecop.return }
|
||||
|
||||
it { expect(dossier.motivation).to eq(nil) }
|
||||
it { expect(dossier.en_instruction_at).to eq(now) }
|
||||
it { expect(dossier.processed_at).to eq(now) }
|
||||
it { expect(dossier.state).to eq('accepte') }
|
||||
it { expect(dossier.dossier_operation_logs.pluck(:gestionnaire_id, :operation, :automatic_operation)).to match([[nil, 'accepter', true]]) }
|
||||
it { expect(NotificationMailer).to have_received(:send_closed_notification).with(dossier) }
|
||||
it { expect(dossier.attestation).to eq(attestation) }
|
||||
end
|
||||
|
||||
describe '#passer_en_instruction!' do
|
||||
let(:dossier) { create(:dossier) }
|
||||
let(:gestionnaire) { create(:gestionnaire) }
|
||||
|
||||
before { dossier.passer_en_instruction!(gestionnaire) }
|
||||
|
||||
it { expect(dossier.state).to eq('en_instruction') }
|
||||
it { expect(dossier.followers_gestionnaires).to include(gestionnaire) }
|
||||
it { expect(dossier.dossier_operation_logs.pluck(:gestionnaire_id, :operation)).to match([[gestionnaire.id, 'passer_en_instruction']]) }
|
||||
end
|
||||
|
||||
describe '#passer_automatiquement_en_instruction!' do
|
||||
let(:dossier) { create(:dossier) }
|
||||
let(:gestionnaire) { create(:gestionnaire) }
|
||||
|
||||
before { dossier.passer_automatiquement_en_instruction! }
|
||||
|
||||
it { expect(dossier.followers_gestionnaires).not_to include(gestionnaire) }
|
||||
it { expect(dossier.dossier_operation_logs.pluck(:gestionnaire_id, :operation, :automatic_operation)).to match([[nil, 'passer_en_instruction', true]]) }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -50,6 +50,14 @@ module FeatureHelpers
|
|||
|
||||
visit "/users/confirmation?#{token_params}"
|
||||
end
|
||||
|
||||
def expect_page_to_have_procedure_description(procedure)
|
||||
# Procedure context on the page
|
||||
expect(page).to have_content(procedure.libelle)
|
||||
expect(page).to have_content(procedure.description)
|
||||
# Procedure contact infos in the footer
|
||||
expect(page).to have_content(procedure.service.email)
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.configure do |config|
|
||||
|
|
|
@ -72,7 +72,7 @@ describe 'admin/procedures/show.html.haml', type: :view do
|
|||
end
|
||||
|
||||
describe 'procedure link is present' do
|
||||
it { expect(rendered).to have_content('Cette démarche est archivée et n’est donc pas accessible par le public.') }
|
||||
it { expect(rendered).to have_content('Cette démarche est archivée et n’est donc plus accessible par le public.') }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,25 +4,61 @@ describe 'layouts/procedure_context.html.haml', type: :view do
|
|||
let(:procedure) { create(:simple_procedure, :with_service) }
|
||||
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||
|
||||
before do
|
||||
assign(:dossier, dossier)
|
||||
end
|
||||
|
||||
subject do
|
||||
render html: 'Column content', layout: 'layouts/procedure_context.html.haml'
|
||||
end
|
||||
|
||||
it 'renders a description of the procedure' do
|
||||
expect(subject).to have_text(dossier.procedure.libelle)
|
||||
expect(subject).to have_text(dossier.procedure.description)
|
||||
context 'when a procedure is assigned' do
|
||||
before do
|
||||
assign(:procedure, procedure)
|
||||
end
|
||||
|
||||
it 'renders a description of the procedure' do
|
||||
expect(subject).to have_text(procedure.libelle)
|
||||
expect(subject).to have_text(procedure.description)
|
||||
end
|
||||
|
||||
it 'renders the inner content' do
|
||||
expect(subject).to have_text('Column content')
|
||||
end
|
||||
|
||||
it 'renders the procedure footer' do
|
||||
expect(subject).to have_text(procedure.service.nom)
|
||||
expect(subject).to have_text(procedure.service.email)
|
||||
end
|
||||
end
|
||||
|
||||
it 'renders the inner content' do
|
||||
expect(subject).to have_text('Column content')
|
||||
context 'when a dossier is assigned' do
|
||||
before do
|
||||
assign(:dossier, dossier)
|
||||
end
|
||||
|
||||
it 'renders a description of the procedure' do
|
||||
expect(subject).to have_text(dossier.procedure.libelle)
|
||||
expect(subject).to have_text(dossier.procedure.description)
|
||||
end
|
||||
|
||||
it 'renders the inner content' do
|
||||
expect(subject).to have_text('Column content')
|
||||
end
|
||||
|
||||
it 'renders the procedure footer' do
|
||||
expect(subject).to have_text(dossier.procedure.service.nom)
|
||||
expect(subject).to have_text(dossier.procedure.service.email)
|
||||
end
|
||||
end
|
||||
|
||||
it 'renders the dossier footer' do
|
||||
expect(subject).to have_text(dossier.procedure.service.nom)
|
||||
expect(subject).to have_text(dossier.procedure.service.email)
|
||||
context 'when neither procedure or dossier are assigned' do
|
||||
it 'renders a placeholder for the procedure' do
|
||||
expect(subject).to have_selector('.no-procedure')
|
||||
end
|
||||
|
||||
it 'renders the inner content' do
|
||||
expect(subject).to have_text('Column content')
|
||||
end
|
||||
|
||||
it 'renders a generic footer' do
|
||||
expect(subject).to have_text('Mentions légales')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
describe 'new_user/dossiers/_dossier_footer.html.haml', type: :view do
|
||||
describe 'new_user/procedure_footer.html.haml', type: :view do
|
||||
let(:service) { create(:service) }
|
||||
let(:dossier) {
|
||||
dossier = create(:dossier)
|
||||
|
@ -6,7 +6,7 @@ describe 'new_user/dossiers/_dossier_footer.html.haml', type: :view do
|
|||
return dossier
|
||||
}
|
||||
|
||||
subject { render 'new_user/dossiers/dossier_footer.html.haml', dossier: dossier }
|
||||
subject { render 'new_user/procedure_footer.html.haml', procedure: dossier.procedure, dossier: dossier }
|
||||
|
||||
it "affiche les informations de contact" do
|
||||
expect(subject).to have_text(service.nom)
|
|
@ -10,24 +10,12 @@ describe 'users/sessions/new.html.haml', type: :view do
|
|||
|
||||
before do
|
||||
assign(:user, User.new)
|
||||
render
|
||||
end
|
||||
|
||||
context 'when user_return_to session params contains a procedure_id' do
|
||||
before do
|
||||
assign(:dossier, dossier)
|
||||
render
|
||||
end
|
||||
|
||||
it { expect(rendered).to have_selector('.procedure-logos') }
|
||||
it { expect(rendered).to have_content(dossier.procedure.libelle) }
|
||||
it { expect(rendered).to have_content(dossier.procedure.description) }
|
||||
end
|
||||
|
||||
context 'when user_return_to session params not contains a procedure_id' do
|
||||
before do
|
||||
render
|
||||
end
|
||||
|
||||
it { expect(rendered).to have_content('Un outil simple') }
|
||||
it 'renders' do
|
||||
expect(rendered).to have_field('Email')
|
||||
expect(rendered).to have_field('Mot de passe')
|
||||
expect(rendered).to have_button('Se connecter')
|
||||
end
|
||||
end
|
||||
|
|
149
yarn.lock
149
yarn.lock
|
@ -767,6 +767,21 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45"
|
||||
integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==
|
||||
|
||||
"@vue/component-compiler-utils@^2.4.0":
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-2.5.0.tgz#411846d582d393f701f747517ddd29275ce64ca4"
|
||||
integrity sha512-mSB8jWmE/ZeYZHPDEx9hNiiRh5P2V1Q0tObxEQWtxxfXtkIAvPnj7oucGm5SO8Y/QwIlDJgAGqHfj5MCjoKoOg==
|
||||
dependencies:
|
||||
consolidate "^0.15.1"
|
||||
hash-sum "^1.0.2"
|
||||
lru-cache "^4.1.2"
|
||||
merge-source-map "^1.1.0"
|
||||
postcss "^7.0.7"
|
||||
postcss-selector-parser "^5.0.0"
|
||||
prettier "1.13.7"
|
||||
source-map "^0.7.3"
|
||||
vue-template-es2015-compiler "^1.6.0"
|
||||
|
||||
"@webassemblyjs/ast@1.7.11":
|
||||
version "1.7.11"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.7.11.tgz#b988582cafbb2b095e8b556526f30c90d057cace"
|
||||
|
@ -1370,6 +1385,11 @@ block-stream@*:
|
|||
dependencies:
|
||||
inherits "~2.0.0"
|
||||
|
||||
bluebird@^3.1.1:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7"
|
||||
integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==
|
||||
|
||||
bluebird@^3.5.1:
|
||||
version "3.5.1"
|
||||
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
|
||||
|
@ -1757,6 +1777,15 @@ chalk@^2.0, chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.0, chalk@^2.4.1:
|
|||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.3.0"
|
||||
|
||||
chalk@^2.4.2:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||
dependencies:
|
||||
ansi-styles "^3.2.1"
|
||||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.3.0"
|
||||
|
||||
chardet@^0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
|
||||
|
@ -2089,6 +2118,13 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0:
|
|||
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
|
||||
integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
|
||||
|
||||
consolidate@^0.15.1:
|
||||
version "0.15.1"
|
||||
resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.15.1.tgz#21ab043235c71a07d45d9aad98593b0dba56bab7"
|
||||
integrity sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==
|
||||
dependencies:
|
||||
bluebird "^3.1.1"
|
||||
|
||||
constants-browserify@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
|
||||
|
@ -2467,6 +2503,11 @@ date-now@^0.1.4:
|
|||
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
|
||||
integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=
|
||||
|
||||
de-indent@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
|
||||
integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=
|
||||
|
||||
debounce@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131"
|
||||
|
@ -3827,6 +3868,11 @@ hash-base@^3.0.0:
|
|||
inherits "^2.0.1"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
hash-sum@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-1.0.2.tgz#33b40777754c6432573c120cc3808bbd10d47f04"
|
||||
integrity sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=
|
||||
|
||||
hash.js@^1.0.0, hash.js@^1.0.3:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812"
|
||||
|
@ -3835,6 +3881,11 @@ hash.js@^1.0.0, hash.js@^1.0.3:
|
|||
inherits "^2.0.3"
|
||||
minimalistic-assert "^1.0.1"
|
||||
|
||||
he@^1.1.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
||||
|
||||
hex-color-regex@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
|
||||
|
@ -4932,7 +4983,7 @@ lru-cache@^4.0.1, lru-cache@^4.1.1:
|
|||
pseudomap "^1.0.2"
|
||||
yallist "^2.1.2"
|
||||
|
||||
lru-cache@^4.1.3:
|
||||
lru-cache@^4.1.2, lru-cache@^4.1.3:
|
||||
version "4.1.5"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
|
||||
integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
|
||||
|
@ -5051,6 +5102,13 @@ merge-descriptors@1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
||||
integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
|
||||
|
||||
merge-source-map@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646"
|
||||
integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==
|
||||
dependencies:
|
||||
source-map "^0.6.1"
|
||||
|
||||
methods@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
|
||||
|
@ -6568,6 +6626,15 @@ postcss-selector-parser@^4.0.0:
|
|||
indexes-of "^1.0.1"
|
||||
uniq "^1.0.1"
|
||||
|
||||
postcss-selector-parser@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c"
|
||||
integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==
|
||||
dependencies:
|
||||
cssesc "^2.0.0"
|
||||
indexes-of "^1.0.1"
|
||||
uniq "^1.0.1"
|
||||
|
||||
postcss-selector-parser@^5.0.0-rc.4:
|
||||
version "5.0.0-rc.4"
|
||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0-rc.4.tgz#ca5e77238bf152966378c13e91ad6d611568ea87"
|
||||
|
@ -6633,6 +6700,15 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.5:
|
|||
source-map "^0.6.1"
|
||||
supports-color "^5.5.0"
|
||||
|
||||
postcss@^7.0.7:
|
||||
version "7.0.8"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.8.tgz#2a3c5f2bdd00240cd0d0901fd998347c93d36696"
|
||||
integrity sha512-WudsIzuTKRw9IInRTPBgVXJ7DKR26HT09Rxp0g3w0Fqh3TUtYICcUmvC0xURj04o3vdcDtnjCAUCECg/p341iQ==
|
||||
dependencies:
|
||||
chalk "^2.4.2"
|
||||
source-map "^0.6.1"
|
||||
supports-color "^6.0.0"
|
||||
|
||||
prelude-ls@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
|
||||
|
@ -6650,6 +6726,11 @@ prettier-linter-helpers@^1.0.0:
|
|||
dependencies:
|
||||
fast-diff "^1.1.2"
|
||||
|
||||
prettier@1.13.7:
|
||||
version "1.13.7"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.7.tgz#850f3b8af784a49a6ea2d2eaa7ed1428a34b7281"
|
||||
integrity sha512-KIU72UmYPGk4MujZGYMFwinB7lOf2LsDNGSOC8ufevsrPLISrZbNJlWstRi3m0AMuszbH+EFSQ/r6w56RSPK6w==
|
||||
|
||||
prettier@^1.15.3:
|
||||
version "1.15.3"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.15.3.tgz#1feaac5bdd181237b54dbe65d874e02a1472786a"
|
||||
|
@ -7505,6 +7586,11 @@ sort-keys@^2.0.0:
|
|||
dependencies:
|
||||
is-plain-obj "^1.0.0"
|
||||
|
||||
sortablejs@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.7.0.tgz#80a2b2370abd568e1cec8c271131ef30a904fa28"
|
||||
integrity sha1-gKKyNwq9Vo4c7IwnETHvMKkE+ig=
|
||||
|
||||
source-list-map@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085"
|
||||
|
@ -7551,6 +7637,11 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
|
|||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
source-map@^0.7.3:
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
||||
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
|
||||
|
||||
spark-md5@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/spark-md5/-/spark-md5-3.0.0.tgz#3722227c54e2faf24b1dc6d933cc144e6f71bfef"
|
||||
|
@ -7821,6 +7912,13 @@ supports-color@^5.5.0:
|
|||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
supports-color@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a"
|
||||
integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==
|
||||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
svgo@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.1.1.tgz#12384b03335bcecd85cfa5f4e3375fed671cb985"
|
||||
|
@ -8410,6 +8508,55 @@ vm-browserify@0.0.4:
|
|||
dependencies:
|
||||
indexof "0.0.1"
|
||||
|
||||
vue-hot-reload-api@^2.3.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.1.tgz#b2d3d95402a811602380783ea4f566eb875569a2"
|
||||
integrity sha512-AA86yKZ5uOKz87/q1UpngEXhbRkaYg1b7HMMVRobNV1IVKqZe8oLIzo6iMocVwZXnYitlGwf2k4ZRLOZlS8oPQ==
|
||||
|
||||
vue-loader@^15.5.1:
|
||||
version "15.5.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.5.1.tgz#e005d5fc2481a55a19910f0dcf434206d68acc2a"
|
||||
integrity sha512-gsTA9xRzu9jGBzkcrAB8my14RkHMzdr5rY/mCFmxgY2tOVsd2Z1MaYCDXHu5nX6PyHAsVK2/hXmarPln/2MiIw==
|
||||
dependencies:
|
||||
"@vue/component-compiler-utils" "^2.4.0"
|
||||
hash-sum "^1.0.2"
|
||||
loader-utils "^1.1.0"
|
||||
vue-hot-reload-api "^2.3.0"
|
||||
vue-style-loader "^4.1.0"
|
||||
|
||||
vue-style-loader@^4.1.0:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.2.tgz#dedf349806f25ceb4e64f3ad7c0a44fba735fcf8"
|
||||
integrity sha512-0ip8ge6Gzz/Bk0iHovU9XAUQaFt/G2B61bnWa2tCcqqdgfHs1lF9xXorFbE55Gmy92okFT+8bfmySuUOu13vxQ==
|
||||
dependencies:
|
||||
hash-sum "^1.0.2"
|
||||
loader-utils "^1.0.2"
|
||||
|
||||
vue-template-compiler@^2.5.21:
|
||||
version "2.5.21"
|
||||
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.21.tgz#a57ceb903177e8f643560a8d639a0f8db647054a"
|
||||
integrity sha512-Vmk5Cv7UcmI99B9nXJEkaK262IQNnHp5rJYo+EwYpe2epTAXqcVyExhV6pk8jTkxQK2vRc8v8KmZBAwdmUZvvw==
|
||||
dependencies:
|
||||
de-indent "^1.0.2"
|
||||
he "^1.1.0"
|
||||
|
||||
vue-template-es2015-compiler@^1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz#dc42697133302ce3017524356a6c61b7b69b4a18"
|
||||
integrity sha512-x3LV3wdmmERhVCYy3quqA57NJW7F3i6faas++pJQWtknWT+n7k30F4TVdHvCLn48peTJFRvCpxs3UuFPqgeELg==
|
||||
|
||||
vue@^2.5.21:
|
||||
version "2.5.21"
|
||||
resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.21.tgz#3d33dcd03bb813912ce894a8303ab553699c4a85"
|
||||
integrity sha512-Aejvyyfhn0zjVeLvXd70h4hrE4zZDx1wfZqia6ekkobLmUZ+vNFQer53B4fu0EjWBSiqApxPejzkO1Znt3joxQ==
|
||||
|
||||
vuedraggable@^2.16.0:
|
||||
version "2.17.0"
|
||||
resolved "https://registry.yarnpkg.com/vuedraggable/-/vuedraggable-2.17.0.tgz#489c16c9bcb9eb06f441944d3c52e5f2bb7060f9"
|
||||
integrity sha512-TAC5tJTSbHSINQCSB59qHnuzT0Ad+E3IgvSWuA1e9UaebD8DxKaY1tCdvL3XvuLoaM3wc1dhpP/NbjpdxYsrng==
|
||||
dependencies:
|
||||
sortablejs "^1.7.0"
|
||||
|
||||
watchpack@^1.5.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00"
|
||||
|
|
Loading…
Reference in a new issue