Introduce permanent and customizable procedure url
This commit is contained in:
parent
b68b62b8f0
commit
e5002dbb11
27 changed files with 5164 additions and 49 deletions
92
app/assets/javascripts/admin_procedures_modal.js
Normal file
92
app/assets/javascripts/admin_procedures_modal.js
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
$(document).on('page:load', init_path_modal);
|
||||||
|
$(document).ready(init_path_modal);
|
||||||
|
|
||||||
|
function init_path_modal() {
|
||||||
|
path_modal_action();
|
||||||
|
path_validation_action();
|
||||||
|
path_type_init();
|
||||||
|
path_validation($("input[id='procedure_path']"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function path_modal_action() {
|
||||||
|
$('#publishModal').on('show.bs.modal', function (event) {
|
||||||
|
$("#publishModal .modal-body .table .tr_content").hide();
|
||||||
|
|
||||||
|
var button = $(event.relatedTarget) // Button that triggered the modal
|
||||||
|
var modal_title = button.data('modal_title'); // Extract info from data-* attributes
|
||||||
|
var modal_index = button.data('modal_index'); // Extract info from data-* attributes
|
||||||
|
|
||||||
|
var modal = $(this)
|
||||||
|
modal.find('#publishModal_title').html(modal_title);
|
||||||
|
$("#publishModal .modal-body .table #"+modal_index).show();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function path_validation_action() {
|
||||||
|
$("input[id='procedure_path']").keyup(function (key) {
|
||||||
|
if (key.keyCode != 13)
|
||||||
|
path_validation(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function togglePathMessage(valid, mine) {
|
||||||
|
$('#path_messages .message').hide();
|
||||||
|
|
||||||
|
if (valid === true && mine === true) {
|
||||||
|
$('#path_is_mine').show();
|
||||||
|
} else if (valid === true && mine === false) {
|
||||||
|
$('#path_is_not_mine').show();
|
||||||
|
} else if (valid === false && mine === null) {
|
||||||
|
$('#path_is_invalid').show();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((valid && mine === null) || mine === true)
|
||||||
|
$('#publishModal #publish').removeAttr('disabled')
|
||||||
|
else
|
||||||
|
$('#publishModal #publish').attr('disabled', 'disabled')
|
||||||
|
}
|
||||||
|
|
||||||
|
function path_validation(el) {
|
||||||
|
var valid = validatePath($(el).val());
|
||||||
|
toggleErrorClass(el, valid);
|
||||||
|
togglePathMessage(valid, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function validatePath(path) {
|
||||||
|
console.log(path);
|
||||||
|
|
||||||
|
var re = /^[a-z0-9_]{3,30}$/;
|
||||||
|
return re.test(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function path_type_init() {
|
||||||
|
display = 'label';
|
||||||
|
|
||||||
|
var bloodhound = new Bloodhound({
|
||||||
|
datumTokenizer: Bloodhound.tokenizers.obj.whitespace(display),
|
||||||
|
queryTokenizer: Bloodhound.tokenizers.whitespace,
|
||||||
|
|
||||||
|
remote: {
|
||||||
|
url: '/admin/procedures/path_list?request=%QUERY',
|
||||||
|
wildcard: '%QUERY'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
bloodhound.initialize();
|
||||||
|
|
||||||
|
$("#procedure_path").typeahead({
|
||||||
|
minLength: 1
|
||||||
|
}, {
|
||||||
|
display: display,
|
||||||
|
source: bloodhound,
|
||||||
|
templates: {
|
||||||
|
suggestion: Handlebars.compile("<div class='path_mine_{{mine}}'>{{label}}</div>")
|
||||||
|
},
|
||||||
|
limit: 5
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#procedure_path').bind('typeahead:select', function(ev, suggestion) {
|
||||||
|
togglePathMessage(true, suggestion['mine']);
|
||||||
|
});
|
||||||
|
}
|
|
@ -29,6 +29,7 @@
|
||||||
//= require franceconnect
|
//= require franceconnect
|
||||||
//= require bootstrap-wysihtml5
|
//= require bootstrap-wysihtml5
|
||||||
//= require bootstrap-wysihtml5/locales/fr-FR
|
//= require bootstrap-wysihtml5/locales/fr-FR
|
||||||
|
//= require handlebars
|
||||||
//= require typeahead.bundle
|
//= require typeahead.bundle
|
||||||
|
|
||||||
$(document).on('page:load', scroll_to);
|
$(document).on('page:load', scroll_to);
|
||||||
|
|
|
@ -156,7 +156,7 @@ function add_event_search_address() {
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#search_by_address input[type='address']").keypress(function (e) {
|
$("#search_by_address input[type='address']").keypress(function (e) {
|
||||||
if (e.which == 13)
|
if (e.keyCode == 13)
|
||||||
get_address_point($(this).val());
|
get_address_point($(this).val());
|
||||||
});
|
});
|
||||||
}
|
}
|
18
app/assets/stylesheets/admin_procedures_modal.scss
Normal file
18
app/assets/stylesheets/admin_procedures_modal.scss
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
.path_mine_false {
|
||||||
|
color: red
|
||||||
|
}
|
||||||
|
|
||||||
|
#path_messages {
|
||||||
|
.message {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#publishModal {
|
||||||
|
.twitter-typeahead {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
.tt-menu {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
}
|
|
@ -132,4 +132,13 @@ table {
|
||||||
.info h4 {
|
.info h4 {
|
||||||
margin: 0 0 5px;
|
margin: 0 0 5px;
|
||||||
color: #777;
|
color: #777;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#search_by_address {
|
||||||
|
.twitter-typeahead {
|
||||||
|
width: 555px;
|
||||||
|
}
|
||||||
|
.tt-menu {
|
||||||
|
width: 555px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
.tt-menu {
|
.tt-menu {
|
||||||
width: 555px;
|
|
||||||
padding: 8px 0;
|
padding: 8px 0;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
|
@ -18,10 +18,6 @@
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.twitter-typeahead {
|
|
||||||
width: 555px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tt-suggestion:hover {
|
.tt-suggestion:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|
|
@ -87,11 +87,44 @@ class Admin::ProceduresController < AdminController
|
||||||
end
|
end
|
||||||
|
|
||||||
def publish
|
def publish
|
||||||
change_status({published: true})
|
if ! ProcedurePathFormatValidator.new().validate_string(params[:procedure_path])
|
||||||
|
flash.alert = 'Lien de la procédure invalide'
|
||||||
|
return redirect_to admin_procedures_path
|
||||||
|
end
|
||||||
|
|
||||||
|
procedure_path = ProcedurePath.find_by_path(params[:procedure_path])
|
||||||
|
@procedure = current_administrateur.procedures.find(params[:procedure_id])
|
||||||
|
|
||||||
|
if (procedure_path)
|
||||||
|
if (procedure_path.administrateur_id == current_administrateur.id)
|
||||||
|
procedure_path.procedure.archive
|
||||||
|
@procedure.publish(params[:procedure_path])
|
||||||
|
else
|
||||||
|
flash.alert = 'Ce lien appartient à un autre administrateur et ne peut pas être utilisé.'
|
||||||
|
return redirect_to admin_procedures_path
|
||||||
|
end
|
||||||
|
else
|
||||||
|
@procedure.publish(params[:procedure_path])
|
||||||
|
end
|
||||||
|
|
||||||
|
flash.notice = "Procédure publiée"
|
||||||
|
redirect_to admin_procedures_path
|
||||||
|
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
flash.alert = 'Procédure inéxistante'
|
||||||
|
redirect_to admin_procedures_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def archive
|
def archive
|
||||||
change_status({archived: params[:archive]})
|
@procedure = current_administrateur.procedures.find(params[:procedure_id])
|
||||||
|
@procedure.archive
|
||||||
|
|
||||||
|
flash.notice = "Procédure archivée"
|
||||||
|
redirect_to admin_procedures_path
|
||||||
|
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
flash.alert = 'Procédure inéxistante'
|
||||||
|
redirect_to admin_procedures_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def clone
|
def clone
|
||||||
|
@ -123,6 +156,12 @@ class Admin::ProceduresController < AdminController
|
||||||
@draft_class = 'active'
|
@draft_class = 'active'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def path_list
|
||||||
|
render json: ProcedurePath.where("path LIKE '%#{params[:request]}%'").pluck(:path, :administrateur_id).inject([]) {
|
||||||
|
|acc, value| acc.push({ label: value.first, mine: value.second == current_administrateur.id })
|
||||||
|
}.to_json
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def create_procedure_params
|
def create_procedure_params
|
||||||
|
@ -132,16 +171,4 @@ class Admin::ProceduresController < AdminController
|
||||||
def create_module_api_carto_params
|
def create_module_api_carto_params
|
||||||
params.require(:procedure).require(:module_api_carto_attributes).permit(:id, :use_api_carto, :quartiers_prioritaires, :cadastre)
|
params.require(:procedure).require(:module_api_carto_attributes).permit(:id, :use_api_carto, :quartiers_prioritaires, :cadastre)
|
||||||
end
|
end
|
||||||
|
|
||||||
def change_status(status_options)
|
|
||||||
@procedure = current_administrateur.procedures.find(params[:procedure_id])
|
|
||||||
@procedure.update_attributes(status_options)
|
|
||||||
|
|
||||||
flash.notice = 'Procédure éditée'
|
|
||||||
redirect_to admin_procedures_path
|
|
||||||
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
|
||||||
flash.alert = 'Procédure inéxistante'
|
|
||||||
redirect_to admin_procedures_path
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -23,7 +23,11 @@ class Users::DossiersController < UsersController
|
||||||
end
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
procedure = Procedure.where(archived: false, published: true).find(params[:procedure_id])
|
if (! params[:procedure_path].nil?)
|
||||||
|
procedure = ProcedurePath.where(path: params[:procedure_path]).first!.procedure
|
||||||
|
else
|
||||||
|
procedure = Procedure.where(archived: false, published: true).find(params[:procedure_id])
|
||||||
|
end
|
||||||
|
|
||||||
dossier = Dossier.create(procedure: procedure, user: current_user, state: 'draft')
|
dossier = Dossier.create(procedure: procedure, user: current_user, state: 'draft')
|
||||||
siret = params[:siret] || current_user.siret
|
siret = params[:siret] || current_user.siret
|
||||||
|
|
|
@ -2,7 +2,7 @@ class ProcedureDecorator < Draper::Decorator
|
||||||
delegate_all
|
delegate_all
|
||||||
|
|
||||||
def lien
|
def lien
|
||||||
h.new_users_dossiers_url(procedure_id: id)
|
h.commencer_url(procedure_path: path) unless path.nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
def created_at_fr
|
def created_at_fr
|
||||||
|
|
|
@ -3,6 +3,8 @@ class Procedure < ActiveRecord::Base
|
||||||
has_many :types_de_champ, dependent: :destroy
|
has_many :types_de_champ, dependent: :destroy
|
||||||
has_many :dossiers
|
has_many :dossiers
|
||||||
|
|
||||||
|
has_one :procedure_path, dependent: :destroy
|
||||||
|
|
||||||
has_one :module_api_carto, dependent: :destroy
|
has_one :module_api_carto, dependent: :destroy
|
||||||
|
|
||||||
belongs_to :administrateur
|
belongs_to :administrateur
|
||||||
|
@ -15,12 +17,17 @@ class Procedure < ActiveRecord::Base
|
||||||
accepts_nested_attributes_for :types_de_champ,:reject_if => proc { |attributes| attributes['libelle'].blank? }, :allow_destroy => true
|
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_piece_justificative, :reject_if => proc { |attributes| attributes['libelle'].blank? }, :allow_destroy => true
|
||||||
accepts_nested_attributes_for :module_api_carto
|
accepts_nested_attributes_for :module_api_carto
|
||||||
|
accepts_nested_attributes_for :procedure_path
|
||||||
|
|
||||||
mount_uploader :logo, ProcedureLogoUploader
|
mount_uploader :logo, ProcedureLogoUploader
|
||||||
|
|
||||||
validates :libelle, presence: true, allow_blank: false, allow_nil: false
|
validates :libelle, presence: true, allow_blank: false, allow_nil: false
|
||||||
validates :description, presence: true, allow_blank: false, allow_nil: false
|
validates :description, presence: true, allow_blank: false, allow_nil: false
|
||||||
|
|
||||||
|
def path
|
||||||
|
procedure_path.path unless procedure_path.nil?
|
||||||
|
end
|
||||||
|
|
||||||
def types_de_champ_ordered
|
def types_de_champ_ordered
|
||||||
types_de_champ.order(:order_place)
|
types_de_champ.order(:order_place)
|
||||||
end
|
end
|
||||||
|
@ -65,4 +72,14 @@ class Procedure < ActiveRecord::Base
|
||||||
return procedure if procedure.save
|
return procedure if procedure.save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def publish(path)
|
||||||
|
self.update_attributes!({ published: true })
|
||||||
|
ProcedurePath.create!(path: path, procedure: self, administrateur: self.administrateur)
|
||||||
|
end
|
||||||
|
|
||||||
|
def archive
|
||||||
|
self.procedure_path.destroy! if self.path
|
||||||
|
self.update_attributes!({ archived: true })
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
8
app/models/procedure_path.rb
Normal file
8
app/models/procedure_path.rb
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
class ProcedurePath < ActiveRecord::Base
|
||||||
|
validates :path, procedure_path_format: true, presence: true, allow_blank: false, allow_nil: false
|
||||||
|
validates :administrateur_id, presence: true, allow_blank: false, allow_nil: false
|
||||||
|
validates :procedure_id, presence: true, allow_blank: false, allow_nil: false
|
||||||
|
|
||||||
|
belongs_to :procedure
|
||||||
|
belongs_to :administrateur
|
||||||
|
end
|
16
app/validators/procedure_path_format_validator.rb
Normal file
16
app/validators/procedure_path_format_validator.rb
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
class ProcedurePathFormatValidator < ActiveModel::Validator
|
||||||
|
|
||||||
|
def path_regex
|
||||||
|
/^[a-z0-9_]{3,30}$/
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate(record)
|
||||||
|
return false if record.path.blank?
|
||||||
|
record.errors[:path] << "Path invalide" unless path_regex.match(record.path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_string(path)
|
||||||
|
return false if path.blank?
|
||||||
|
path_regex.match(path)
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,7 +3,7 @@
|
||||||
%thead
|
%thead
|
||||||
%th#ID= smart_listing.sortable 'ID', 'id'
|
%th#ID= smart_listing.sortable 'ID', 'id'
|
||||||
%th#libelle= smart_listing.sortable 'Libellé', 'libelle'
|
%th#libelle= smart_listing.sortable 'Libellé', 'libelle'
|
||||||
- unless @draft_class
|
- if @active_class
|
||||||
%th#lien Lien
|
%th#lien Lien
|
||||||
%th#created_at= smart_listing.sortable 'Date création', 'created_at'
|
%th#created_at= smart_listing.sortable 'Date création', 'created_at'
|
||||||
%th#lien Actions
|
%th#lien Actions
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
%td.col-md-1.col-lg-1= procedure.id
|
%td.col-md-1.col-lg-1= procedure.id
|
||||||
%td.col-md-6.col-lg-6
|
%td.col-md-6.col-lg-6
|
||||||
= link_to(procedure.libelle, "/admin/procedures/#{procedure.id}")
|
= link_to(procedure.libelle, "/admin/procedures/#{procedure.id}")
|
||||||
- unless @draft_class
|
- if @active_class
|
||||||
%td= link_to procedure.lien, procedure.lien
|
%td= link_to procedure.lien, procedure.lien
|
||||||
%td
|
%td
|
||||||
= procedure.created_at_fr
|
= procedure.created_at_fr
|
||||||
|
|
45
app/views/admin/procedures/_modal_publish.html.haml
Normal file
45
app/views/admin/procedures/_modal_publish.html.haml
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#publishModal.modal.fade{"aria-labelledby" => "myModalLabel", :role => "dialog", :tabindex => "-1"}
|
||||||
|
.modal-dialog.modal-lg{:role => "document"}
|
||||||
|
= form_tag admin_procedure_publish_path(procedure_id: @procedure.id), method: :put do
|
||||||
|
.modal-content
|
||||||
|
.modal-header
|
||||||
|
%button.close{"aria-label" => "Close", "data-dismiss" => "modal", :type => "button"}
|
||||||
|
%span{"aria-hidden" => "true"} ×
|
||||||
|
%h4#myModalLabel.modal-title
|
||||||
|
Publier la procédure
|
||||||
|
%span#publishModal_title
|
||||||
|
.modal-body
|
||||||
|
Vous vous apprêtez à publier votre procédure au public.
|
||||||
|
%b
|
||||||
|
Elle ne pourra plus être modifiée à l'issue de cette publication.
|
||||||
|
%br
|
||||||
|
Afin de faciliter l'accès à la procédure, vous êtes invité à personnaliser l'adresse d'accès si vous le souhaitez.
|
||||||
|
%br
|
||||||
|
.form-group
|
||||||
|
%br
|
||||||
|
%h4 Lien de la procédure
|
||||||
|
%p.center
|
||||||
|
= root_url
|
||||||
|
= text_field_tag('procedure_path', @procedure.libelle.downcase.gsub(/[^a-z0-9\-_]/,"_").gsub(/_*$/, '').gsub(/_+/, '_'),
|
||||||
|
id: 'procedure_path',
|
||||||
|
placeholder: 'Chemin vers la procédure',
|
||||||
|
class:'form-control',
|
||||||
|
maxlength: 30,
|
||||||
|
style: 'width: 300px; display: inline')
|
||||||
|
#path_messages
|
||||||
|
#path_is_mine.text-warning.center.message
|
||||||
|
Ce lien est déjà utilisé par une de vos procédure.
|
||||||
|
%br
|
||||||
|
Si vous voulez l'utiliser, l'ancienne procédure sera archivée (plus accessible du public).
|
||||||
|
#path_is_not_mine.text-danger.center.message
|
||||||
|
Ce lien est déjà utilisé par une procédure.
|
||||||
|
%br
|
||||||
|
Vous ne pouvez pas l'utiliser car il appartient à un autre administrateur.
|
||||||
|
#path_is_invalid.text-danger.center.message
|
||||||
|
Ce lien n'est pas valide. Seuls les caractères a-z, 0-9 et '_' sont autorisés.
|
||||||
|
.modal-footer
|
||||||
|
= submit_tag 'Annuler', class: %w(btn btn btn-default), id: 'cancel', data: { dismiss: 'modal' }
|
||||||
|
= submit_tag 'Publier', class: %w(btn btn btn-success),
|
||||||
|
id: 'publish',
|
||||||
|
data: { disable_with: 'Publication en cours', submit: true},
|
||||||
|
disabled: :disabled
|
|
@ -2,17 +2,11 @@
|
||||||
=render partial: 'head', locals: {active: 'Informations'}
|
=render partial: 'head', locals: {active: 'Informations'}
|
||||||
|
|
||||||
-if ! @facade.procedure.published?
|
-if ! @facade.procedure.published?
|
||||||
= form_tag admin_procedure_publish_path(procedure_id: @facade.procedure.id, publish: true), method: :put, style:'float: right; margin-top: 10px' do
|
%a.btn.btn-success{"data-target" => "#publishModal", "data-toggle" => "modal", :type => "button", style:'float: right; margin-top: 10px'}
|
||||||
%button#archive.btn.btn-small.btn-success.text-info{type: :button}
|
%i.fa.fa-eraser
|
||||||
%i.fa.fa-eraser
|
Publier
|
||||||
Publier
|
%br
|
||||||
#confirm
|
=render partial: '/admin/procedures/modal_publish'
|
||||||
%button#valid.btn.btn-small.btn-success{type: :submit}
|
|
||||||
%i.fa.fa-check
|
|
||||||
Valider
|
|
||||||
%button#cancel.btn.btn-small.btn-danger{type: :button}
|
|
||||||
%i.fa.fa-remove
|
|
||||||
Annuler
|
|
||||||
|
|
||||||
-else
|
-else
|
||||||
= form_tag admin_procedure_archive_path(procedure_id: @facade.procedure.id, archive: !@facade.procedure.archived?), method: :put, style:'float: right; margin-top: 10px' do
|
= form_tag admin_procedure_archive_path(procedure_id: @facade.procedure.id, archive: !@facade.procedure.archived?), method: :put, style:'float: right; margin-top: 10px' do
|
||||||
|
@ -38,7 +32,10 @@
|
||||||
%div
|
%div
|
||||||
%h3 Lien procédure
|
%h3 Lien procédure
|
||||||
%div{style:'margin-left:3%'}
|
%div{style:'margin-left:3%'}
|
||||||
-if @facade.procedure.published?
|
-if @facade.procedure.archived?
|
||||||
|
%b
|
||||||
|
Cette procédure a été archivée et n'est plus accessible par le public.
|
||||||
|
-elsif @facade.procedure.published?
|
||||||
= @facade.procedure.lien
|
= @facade.procedure.lien
|
||||||
-else
|
-else
|
||||||
%b
|
%b
|
||||||
|
|
|
@ -17,5 +17,4 @@
|
||||||
-# .etape.etapes_menu.col-md-3.col-lg-3
|
-# .etape.etapes_menu.col-md-3.col-lg-3
|
||||||
-# %h3
|
-# %h3
|
||||||
-# = "#{@facade.procedure.module_api_carto.use_api_carto? ? '4' : '3'} - Mon dossier"
|
-# = "#{@facade.procedure.module_api_carto.use_api_carto? ? '4' : '3'} - Mon dossier"
|
||||||
-# .etape.etapes_informations.col-md-9.col-lg-9
|
-# .etape.etapes_informations.col-md-9.col-lg-9
|
||||||
|
|
|
@ -89,6 +89,7 @@ Rails.application.routes.draw do
|
||||||
get 'sign_in' => '/administrateurs/sessions#new'
|
get 'sign_in' => '/administrateurs/sessions#new'
|
||||||
get 'procedures/archived' => 'procedures#archived'
|
get 'procedures/archived' => 'procedures#archived'
|
||||||
get 'procedures/draft' => 'procedures#draft'
|
get 'procedures/draft' => 'procedures#draft'
|
||||||
|
get 'procedures/path_list' => 'procedures#path_list'
|
||||||
get 'profile' => 'profile#show', as: :profile
|
get 'profile' => 'profile#show', as: :profile
|
||||||
|
|
||||||
resources :procedures do
|
resources :procedures do
|
||||||
|
@ -161,5 +162,9 @@ Rails.application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
namespace :commencer do
|
||||||
|
get '/:procedure_path' => '/users/dossiers#new'
|
||||||
|
end
|
||||||
|
|
||||||
apipie
|
apipie
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
class AddProcedurePathMappingTable < ActiveRecord::Migration
|
||||||
|
class ProcedurePath < ActiveRecord::Base
|
||||||
|
end
|
||||||
|
|
||||||
|
def change
|
||||||
|
create_table :procedure_paths do |t|
|
||||||
|
t.string :path, limit: 30, null: true, unique: true, index: true
|
||||||
|
t.integer :procedure_id, unique: true, null: true
|
||||||
|
t.integer :administrateur_id, unique: true, null: true
|
||||||
|
end
|
||||||
|
add_foreign_key :procedure_paths, :procedures
|
||||||
|
add_foreign_key :procedure_paths, :administrateurs
|
||||||
|
|
||||||
|
Procedure.all.each do |procedure|
|
||||||
|
ProcedurePath.create(path: "#{procedure.id}", procedure_id: procedure.id, administrateur_id: procedure.administrateur.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
12
db/schema.rb
12
db/schema.rb
|
@ -11,7 +11,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 20160622081321) do
|
ActiveRecord::Schema.define(version: 20160622081322) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
@ -226,6 +226,14 @@ ActiveRecord::Schema.define(version: 20160622081321) do
|
||||||
|
|
||||||
add_index "pieces_justificatives", ["type_de_piece_justificative_id"], name: "index_pieces_justificatives_on_type_de_piece_justificative_id", using: :btree
|
add_index "pieces_justificatives", ["type_de_piece_justificative_id"], name: "index_pieces_justificatives_on_type_de_piece_justificative_id", using: :btree
|
||||||
|
|
||||||
|
create_table "procedure_paths", force: :cascade do |t|
|
||||||
|
t.string "path", limit: 30
|
||||||
|
t.integer "procedure_id"
|
||||||
|
t.integer "administrateur_id"
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index "procedure_paths", ["path"], name: "index_procedure_paths_on_path", using: :btree
|
||||||
|
|
||||||
create_table "procedures", force: :cascade do |t|
|
create_table "procedures", force: :cascade do |t|
|
||||||
t.string "libelle"
|
t.string "libelle"
|
||||||
t.string "description"
|
t.string "description"
|
||||||
|
@ -304,4 +312,6 @@ ActiveRecord::Schema.define(version: 20160622081321) do
|
||||||
add_foreign_key "cerfas", "dossiers"
|
add_foreign_key "cerfas", "dossiers"
|
||||||
add_foreign_key "commentaires", "dossiers"
|
add_foreign_key "commentaires", "dossiers"
|
||||||
add_foreign_key "dossiers", "users"
|
add_foreign_key "dossiers", "users"
|
||||||
|
add_foreign_key "procedure_paths", "administrateurs"
|
||||||
|
add_foreign_key "procedure_paths", "procedures"
|
||||||
end
|
end
|
||||||
|
|
|
@ -263,6 +263,93 @@ describe Admin::ProceduresController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'PUT #publish' do
|
||||||
|
let(:procedure) { create(:procedure, administrateur: admin) }
|
||||||
|
let(:procedure2) { create(:procedure, :published, administrateur: admin) }
|
||||||
|
let(:procedure3) { create(:procedure, :published) }
|
||||||
|
|
||||||
|
context 'when admin is the owner of the procedure' do
|
||||||
|
before do
|
||||||
|
put :publish, procedure_id: procedure.id, procedure_path: procedure_path
|
||||||
|
procedure.reload
|
||||||
|
procedure2.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'procedure path does not exist' do
|
||||||
|
let(:procedure_path) { 'new_path' }
|
||||||
|
|
||||||
|
it 'publish the given procedure' do
|
||||||
|
expect(procedure.published).to be_truthy
|
||||||
|
expect(procedure.path).to eq(procedure_path)
|
||||||
|
expect(response).to redirect_to :admin_procedures
|
||||||
|
expect(flash[:notice]).to have_content 'Procédure publiée'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'procedure path exists and is owned by current administrator' do
|
||||||
|
let(:procedure_path) { procedure2.path }
|
||||||
|
|
||||||
|
it 'publish the given procedure' do
|
||||||
|
expect(procedure.published).to be_truthy
|
||||||
|
expect(procedure.path).to eq(procedure_path)
|
||||||
|
expect(response).to redirect_to :admin_procedures
|
||||||
|
expect(flash[:notice]).to have_content 'Procédure publiée'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'archive previous procedure' do
|
||||||
|
expect(procedure2.published).to be_truthy
|
||||||
|
expect(procedure2.archived).to be_truthy
|
||||||
|
expect(procedure2.path).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'procedure path exists and is not owned by current administrator' do
|
||||||
|
let(:procedure_path) { procedure3.path }
|
||||||
|
|
||||||
|
it 'does not publish the given procedure' do
|
||||||
|
expect(procedure.published).to be_falsey
|
||||||
|
expect(procedure.path).to be_nil
|
||||||
|
expect(response).to redirect_to :admin_procedures
|
||||||
|
expect(flash[:alert]).to have_content 'Ce lien appartient à un autre administrateur et ne peut pas être utilisé.'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'previous procedure remains published' do
|
||||||
|
expect(procedure2.published).to be_truthy
|
||||||
|
expect(procedure2.archived).to be_falsey
|
||||||
|
expect(procedure2.path).to match(/fake_path/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'procedure path is invalid' do
|
||||||
|
let(:procedure_path) { 'Invalid Procedure Path' }
|
||||||
|
|
||||||
|
it 'does not publish the given procedure' do
|
||||||
|
expect(procedure.published).to be_falsey
|
||||||
|
expect(procedure.path).to be_nil
|
||||||
|
expect(response).to redirect_to :admin_procedures
|
||||||
|
expect(flash[:alert]).to have_content 'Lien de la procédure invalide'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when admin is not the owner of the procedure' do
|
||||||
|
let(:admin_2) { create(:administrateur) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
sign_out admin
|
||||||
|
sign_in admin_2
|
||||||
|
|
||||||
|
put :publish, procedure_id: procedure.id, procedure_path: 'fake_path'
|
||||||
|
procedure.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'fails' do
|
||||||
|
expect(response).to redirect_to :admin_procedures
|
||||||
|
expect(flash[:alert]).to have_content 'Procédure inéxistante'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'PUT #archive' do
|
describe 'PUT #archive' do
|
||||||
let(:procedure) { create(:procedure, administrateur: admin) }
|
let(:procedure) { create(:procedure, administrateur: admin) }
|
||||||
|
|
||||||
|
@ -278,7 +365,7 @@ describe Admin::ProceduresController, type: :controller do
|
||||||
|
|
||||||
it { expect(procedure.archived).to be_truthy }
|
it { expect(procedure.archived).to be_truthy }
|
||||||
it { expect(response).to redirect_to :admin_procedures }
|
it { expect(response).to redirect_to :admin_procedures }
|
||||||
it { expect(flash[:notice]).to have_content 'Procédure éditée' }
|
it { expect(flash[:notice]).to have_content 'Procédure archivée' }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when owner want reactive procedure' do
|
context 'when owner want reactive procedure' do
|
||||||
|
@ -337,4 +424,33 @@ describe Admin::ProceduresController, type: :controller do
|
||||||
it { expect(flash[:alert]).to have_content 'Procédure inéxistante' }
|
it { expect(flash[:alert]).to have_content 'Procédure inéxistante' }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'GET #path_list' do
|
||||||
|
let!(:procedure) { create(:procedure, :published, administrateur: admin) }
|
||||||
|
let(:admin2) { create(:administrateur) }
|
||||||
|
let!(:procedure2) { create(:procedure, :published, administrateur: admin2) }
|
||||||
|
subject { get :path_list }
|
||||||
|
let(:body) { JSON.parse(response.body) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(response.status).to eq(200) }
|
||||||
|
it { expect(body.size).to eq(2) }
|
||||||
|
it { expect(body.first['label']).to eq(procedure.path) }
|
||||||
|
it { expect(body.first['mine']).to be_truthy }
|
||||||
|
it { expect(body.second['label']).to eq(procedure2.path) }
|
||||||
|
it { expect(body.second['mine']).to be_falsy }
|
||||||
|
|
||||||
|
context 'filtered' do
|
||||||
|
subject { get :path_list, request: procedure2.path }
|
||||||
|
|
||||||
|
it { expect(response.status).to eq(200) }
|
||||||
|
it { expect(body.size).to eq(1) }
|
||||||
|
it { expect(body.first['label']).to eq(procedure2.path) }
|
||||||
|
it { expect(body.first['mine']).to be_falsy }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
29
spec/decorators/procedure_decorator_spec.rb
Normal file
29
spec/decorators/procedure_decorator_spec.rb
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe ProcedureDecorator do
|
||||||
|
let(:procedure) { create(:procedure, :published, created_at: Time.new(2015, 12, 24, 14, 10)) }
|
||||||
|
subject { procedure.decorate }
|
||||||
|
|
||||||
|
describe 'lien' do
|
||||||
|
subject { super().lien }
|
||||||
|
it { is_expected.to match(/fake_path/) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'created_at_fr' do
|
||||||
|
subject { super().created_at_fr }
|
||||||
|
it { is_expected.to eq('24/12/2015 14:10') }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'logo_img' do
|
||||||
|
subject { super().logo_img }
|
||||||
|
it { is_expected.to eq('logo-tps.png') }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'geographic_information' do
|
||||||
|
subject { super().geographic_information }
|
||||||
|
it { expect(subject.use_api_carto).to be_falsey }
|
||||||
|
it { expect(subject.quartiers_prioritaires).to be_falsey }
|
||||||
|
it { expect(subject.cadastre).to be_falsey }
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -1,4 +1,5 @@
|
||||||
FactoryGirl.define do
|
FactoryGirl.define do
|
||||||
|
sequence(:published_path) { |n| "fake_path#{n}" }
|
||||||
factory :procedure do
|
factory :procedure do
|
||||||
lien_demarche 'http://localhost'
|
lien_demarche 'http://localhost'
|
||||||
libelle 'Demande de subvention'
|
libelle 'Demande de subvention'
|
||||||
|
@ -6,6 +7,7 @@ FactoryGirl.define do
|
||||||
organisation "Orga SGMAP"
|
organisation "Orga SGMAP"
|
||||||
direction "direction SGMAP"
|
direction "direction SGMAP"
|
||||||
published false
|
published false
|
||||||
|
administrateur { create(:administrateur) }
|
||||||
|
|
||||||
after(:build) do |procedure, _evaluator|
|
after(:build) do |procedure, _evaluator|
|
||||||
if procedure.module_api_carto.nil?
|
if procedure.module_api_carto.nil?
|
||||||
|
@ -55,8 +57,8 @@ FactoryGirl.define do
|
||||||
end
|
end
|
||||||
|
|
||||||
trait :published do
|
trait :published do
|
||||||
after(:build) do |procedure, _evaluator|
|
after(:create) do |procedure, _evaluator|
|
||||||
procedure.published = true
|
procedure.publish(generate(:published_path))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
5
spec/factories/procedure_path.rb
Normal file
5
spec/factories/procedure_path.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
FactoryGirl.define do
|
||||||
|
factory :procedure_path do
|
||||||
|
path 'fake_path'
|
||||||
|
end
|
||||||
|
end
|
38
spec/models/procedure_path_spec.rb
Normal file
38
spec/models/procedure_path_spec.rb
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe ProcedurePath do
|
||||||
|
describe 'assocations' do
|
||||||
|
it { is_expected.to belong_to(:administrateur) }
|
||||||
|
it { is_expected.to belong_to(:procedure) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'attributes' do
|
||||||
|
it { is_expected.to have_db_column(:path) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'validation' do
|
||||||
|
context 'path' do
|
||||||
|
let(:admin) { create(:administrateur) }
|
||||||
|
let(:procedure) { create(:procedure) }
|
||||||
|
let(:procedure_path) { create(:procedure_path, administrateur: admin, procedure: procedure, path: path) }
|
||||||
|
|
||||||
|
context 'path is nil' do
|
||||||
|
let(:path) { nil }
|
||||||
|
it { expect{procedure_path}.to raise_error }
|
||||||
|
end
|
||||||
|
context 'path is empty' do
|
||||||
|
let(:path) { '' }
|
||||||
|
it { expect{procedure_path}.to raise_error }
|
||||||
|
end
|
||||||
|
context 'path is invalid' do
|
||||||
|
let(:path) { 'Demande de subvention' }
|
||||||
|
it { expect{procedure_path}.to raise_error(ActiveRecord::RecordInvalid) }
|
||||||
|
end
|
||||||
|
context 'path is invalid' do
|
||||||
|
let(:path) { 'ma_super_procedure' }
|
||||||
|
it { expect{procedure_path}.not_to raise_error }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -19,6 +19,7 @@ describe Procedure do
|
||||||
it { is_expected.to have_db_column(:logo) }
|
it { is_expected.to have_db_column(:logo) }
|
||||||
it { is_expected.to have_db_column(:logo_secure_token) }
|
it { is_expected.to have_db_column(:logo_secure_token) }
|
||||||
it { is_expected.to have_db_column(:cerfa_flag) }
|
it { is_expected.to have_db_column(:cerfa_flag) }
|
||||||
|
it { is_expected.to have_db_column(:published) }
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'validation' do
|
describe 'validation' do
|
||||||
|
@ -156,10 +157,47 @@ describe Procedure do
|
||||||
describe 'procedure status is reset' do
|
describe 'procedure status is reset' do
|
||||||
let(:archived) { true }
|
let(:archived) { true }
|
||||||
let(:published) { true }
|
let(:published) { true }
|
||||||
it 'sets published and archived to false' do
|
it 'Not published nor archived' do
|
||||||
expect(subject.archived).to be_falsey
|
expect(subject.archived).to be_falsey
|
||||||
expect(subject.published).to be_falsey
|
expect(subject.published).to be_falsey
|
||||||
|
expect(subject.path).to be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'publish' do
|
||||||
|
let(:procedure) { create(:procedure, :published) }
|
||||||
|
let(:procedure_path) { ProcedurePath.find(procedure.procedure_path.id) }
|
||||||
|
|
||||||
|
it 'is available from a valid path' do
|
||||||
|
expect(procedure.path).to match(/fake_path/)
|
||||||
|
expect(procedure.published).to be_truthy
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is correctly set in ProcedurePath table' do
|
||||||
|
expect(ProcedurePath.count(path: procedure.path)).to eq(1)
|
||||||
|
expect(procedure_path.procedure_id).to eq(procedure.id)
|
||||||
|
expect(procedure_path.administrateur_id).to eq(procedure.administrateur_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'archive' do
|
||||||
|
let(:procedure) { create(:procedure, :published) }
|
||||||
|
let(:procedure_path) { ProcedurePath.find(procedure.procedure_path.id) }
|
||||||
|
before do
|
||||||
|
procedure.archive
|
||||||
|
procedure.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is not available from a valid path anymore' do
|
||||||
|
expect(procedure.path).to be_nil
|
||||||
|
expect(procedure.published).to be_truthy
|
||||||
|
expect(procedure.archived).to be_truthy
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is not in ProcedurePath table anymore' do
|
||||||
|
expect(ProcedurePath.count(path: procedure.path)).to eq(0)
|
||||||
|
expect(ProcedurePath.find_by_procedure_id(procedure.id)).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,8 +2,7 @@ require 'spec_helper'
|
||||||
|
|
||||||
describe 'admin/procedures/show.html.haml', type: :view do
|
describe 'admin/procedures/show.html.haml', type: :view do
|
||||||
let(:archived) { false }
|
let(:archived) { false }
|
||||||
let(:published) { false }
|
let(:procedure) { create(:procedure, archived: archived) }
|
||||||
let(:procedure) { create(:procedure, published: published, archived: archived) }
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
assign(:facade, AdminProceduresShowFacades.new(procedure.decorate))
|
assign(:facade, AdminProceduresShowFacades.new(procedure.decorate))
|
||||||
|
@ -16,9 +15,16 @@ describe 'admin/procedures/show.html.haml', type: :view do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'archive and unarchive button' do
|
describe 'archive and unarchive button' do
|
||||||
let(:published) { true }
|
before do
|
||||||
|
procedure.publish('fake_path')
|
||||||
|
render
|
||||||
|
end
|
||||||
|
|
||||||
context 'when procedure is published' do
|
context 'when procedure is published' do
|
||||||
|
before do
|
||||||
|
procedure.publish('fake_path')
|
||||||
|
procedure.reload
|
||||||
|
end
|
||||||
it { expect(rendered).to have_content('Archiver') }
|
it { expect(rendered).to have_content('Archiver') }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -35,8 +41,19 @@ describe 'admin/procedures/show.html.haml', type: :view do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'is present when already published' do
|
context 'is present when already published' do
|
||||||
let(:published) { true }
|
before do
|
||||||
it { expect(rendered).to have_content(new_users_dossiers_url(procedure_id: procedure.id)) }
|
procedure.publish('fake_path')
|
||||||
|
render
|
||||||
|
end
|
||||||
|
it { expect(rendered).to have_content(commencer_url(procedure_path: procedure.path)) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'is not present when archived' do
|
||||||
|
before do
|
||||||
|
procedure.archive
|
||||||
|
render
|
||||||
|
end
|
||||||
|
it { expect(rendered).to have_content('Cette procédure a été archivée et n\'est plus accessible par le public.') }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
4608
vendor/assets/javascripts/handlebars.js
vendored
Normal file
4608
vendor/assets/javascripts/handlebars.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue