Merge pull request #4048 from betagouv/procedure-path

Cleanup, simplify and readd suggestions for procedure paths
This commit is contained in:
Nicolas Bouilleaud 2019-09-17 16:40:32 +02:00 committed by GitHub
commit 394a2773db
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 294 additions and 509 deletions

View file

@ -1,70 +0,0 @@
/* globals $ */
$(document).on('turbolinks:load', init_path_modal);
var PROCEDURE_PATH_SELECTOR = 'input[data-autocomplete=path]';
function init_path_modal() {
path_modal_action();
path_validation_action();
path_type_init();
path_validation($(PROCEDURE_PATH_SELECTOR));
}
function path_modal_action() {
$('#publish-modal').on('show.bs.modal', function(event) {
$('#publish-modal .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('#publish-modal-title').html(modal_title);
$('#publish-modal .modal-body .table #' + modal_index).show();
});
}
function path_validation_action() {
$(PROCEDURE_PATH_SELECTOR).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)
$('#publish-modal #publish').removeAttr('disabled');
else $('#publish-modal #publish').attr('disabled', 'disabled');
}
function path_validation(el) {
var valid = validatePath($(el).val());
toggleErrorClass(el, valid);
togglePathMessage(valid, null);
}
function toggleErrorClass(node, boolean) {
if (boolean) $(node).removeClass('input-error');
else $(node).addClass('input-error');
}
function validatePath(path) {
var re = /^[a-z0-9_-]{3,50}$/;
return re.test(path);
}
function path_type_init() {
$(PROCEDURE_PATH_SELECTOR).on('autocomplete:select', function(event) {
togglePathMessage(true, event.detail['mine']);
});
}

View file

@ -1,24 +0,0 @@
.path-mine-false {
color: #FF0000;
}
#path-messages {
.message {
display: none;
}
}
#publish-modal {
.algolia-autocomplete {
width: 300px;
}
.aa-dropdown-menu {
width: 300px;
}
// Fix the input not being displayed on the same line than the text before
.aa-input {
vertical-align: initial !important;
}
}

View file

@ -13,7 +13,6 @@
// = require _card // = require _card
// = require _helpers // = require _helpers
// = require _turbolinks // = require _turbolinks
// = require admin_procedures_modal
// = require admin_type_de_champ // = require admin_type_de_champ
// = require carte // = require carte
// = require custom_mails // = require custom_mails

View file

@ -2,7 +2,7 @@ class Admin::ProceduresController < AdminController
include SmartListing::Helper::ControllerExtensions include SmartListing::Helper::ControllerExtensions
helper SmartListing::Helper helper SmartListing::Helper
before_action :retrieve_procedure, only: [:show, :edit, :delete_logo, :delete_deliberation, :delete_notice, :monavis, :update_monavis] before_action :retrieve_procedure, only: [:show, :edit, :delete_logo, :delete_deliberation, :delete_notice, :monavis, :update_monavis, :publish_validate, :publish]
def index def index
if current_administrateur.procedures.count != 0 if current_administrateur.procedures.count != 0
@ -40,11 +40,16 @@ class Admin::ProceduresController < AdminController
end end
def show def show
if @procedure.brouillon?
@procedure_lien = commencer_test_url(path: @procedure.path)
else
@procedure_lien = commencer_url(path: @procedure.path)
end
@procedure.path = @procedure.suggested_path(current_administrateur)
@current_administrateur = current_administrateur
end end
def edit def edit
@path = @procedure.path || @procedure.default_path
@availability = @procedure.path_availability(current_administrateur, @path)
end end
def destroy def destroy
@ -63,13 +68,10 @@ class Admin::ProceduresController < AdminController
def new def new
@procedure ||= Procedure.new(for_individual: true) @procedure ||= Procedure.new(for_individual: true)
@availability = Procedure::PATH_AVAILABLE
end end
def create def create
@procedure = Procedure.new(procedure_params.merge(administrateurs: [current_administrateur])) @procedure = Procedure.new(procedure_params.merge(administrateurs: [current_administrateur]))
@path = @procedure.path
@availability = Procedure.path_availability(current_administrateur, @procedure.path)
if !@procedure.save if !@procedure.save
flash.now.alert = @procedure.errors.full_messages flash.now.alert = @procedure.errors.full_messages
@ -87,10 +89,6 @@ class Admin::ProceduresController < AdminController
if !@procedure.update(procedure_params) if !@procedure.update(procedure_params)
flash.now.alert = @procedure.errors.full_messages flash.now.alert = @procedure.errors.full_messages
@path = procedure_params[:path]
if @path.present?
@availability = @procedure.path_availability(current_administrateur, @path)
end
render 'edit' render 'edit'
elsif @procedure.brouillon? elsif @procedure.brouillon?
reset_procedure reset_procedure
@ -102,31 +100,19 @@ class Admin::ProceduresController < AdminController
end end
end end
def publish_validate
@procedure.assign_attributes(publish_params)
end
def publish def publish
path = params[:path] @procedure.assign_attributes(publish_params)
lien_site_web = params[:lien_site_web]
procedure = current_administrateur.procedures.find(params[:procedure_id])
procedure.path = path @procedure.publish_or_reopen!(current_administrateur)
procedure.lien_site_web = lien_site_web
if !procedure.validate flash.notice = "Démarche publiée"
flash.alert = 'Lien de la démarche invalide ou lien vers la démarche manquant'
return redirect_to admin_procedures_path
else
procedure.path = nil
end
if procedure.publish_or_reopen!(current_administrateur, path, lien_site_web)
flash.notice = "Démarche publiée"
redirect_to admin_procedures_path
else
@mine = false
render '/admin/procedures/publish', formats: 'js'
end
rescue ActiveRecord::RecordNotFound
flash.alert = 'Démarche inexistante'
redirect_to admin_procedures_path redirect_to admin_procedures_path
rescue ActiveRecord::RecordInvalid
render 'publish_validate', formats: :js
end end
def transfer def transfer
@ -220,32 +206,6 @@ class Admin::ProceduresController < AdminController
@draft_class = 'active' @draft_class = 'active'
end end
def path_list
json_path_list = Procedure
.find_with_path(params[:request])
.order(:id)
.map do |procedure|
{
label: procedure.path,
mine: current_administrateur.owns?(procedure)
}
end.to_json
render json: json_path_list
end
def check_availability
path = params[:procedure][:path]
procedure_id = params[:procedure][:id]
if procedure_id.present?
procedure = current_administrateur.procedures.find(procedure_id)
@availability = procedure.path_availability(current_administrateur, path)
else
@availability = Procedure.path_availability(current_administrateur, path)
end
end
def delete_logo def delete_logo
@procedure.logo.purge_later @procedure.logo.purge_later
@procedure.logo_active_storage.purge_later @procedure.logo_active_storage.purge_later
@ -274,6 +234,10 @@ class Admin::ProceduresController < AdminController
params[:from_new_from_existing].present? params[:from_new_from_existing].present?
end end
def publish_params
params.permit(:path, :lien_site_web)
end
def procedure_params def procedure_params
editable_params = [:libelle, :description, :organisation, :direction, :lien_site_web, :cadre_juridique, :deliberation, :notice, :web_hook_url, :euro_flag, :logo, :auto_archive_on, :monavis_embed] editable_params = [:libelle, :description, :organisation, :direction, :lien_site_web, :cadre_juridique, :deliberation, :notice, :web_hook_url, :euro_flag, :logo, :auto_archive_on, :monavis_embed]
permited_params = if @procedure&.locked? permited_params = if @procedure&.locked?

View file

@ -25,7 +25,7 @@ class AdminController < ApplicationController
end end
def reset_procedure def reset_procedure
if @procedure.brouillon_avec_lien? if @procedure.brouillon?
@procedure.reset! @procedure.reset!
end end
end end

View file

@ -7,7 +7,7 @@ module Instructeurs
def index def index
@procedures = current_instructeur @procedures = current_instructeur
.visible_procedures .procedures
.with_attached_logo .with_attached_logo
.includes(:defaut_groupe_instructeur) .includes(:defaut_groupe_instructeur)
.order(archived_at: :desc, published_at: :desc, created_at: :desc) .order(archived_at: :desc, published_at: :desc, created_at: :desc)
@ -235,7 +235,7 @@ module Instructeurs
end end
def redirect_to_avis_if_needed def redirect_to_avis_if_needed
if current_instructeur.visible_procedures.count == 0 && current_instructeur.avis.count > 0 if current_instructeur.procedures.count == 0 && current_instructeur.avis.count > 0
redirect_to instructeur_avis_index_path redirect_to instructeur_avis_index_path
end end
end end

View file

@ -20,7 +20,7 @@ module NewAdministrateur
end end
def reset_procedure def reset_procedure
if @procedure.brouillon_avec_lien? if @procedure.brouillon?
@procedure.reset! @procedure.reset!
end end
end end

View file

@ -3,21 +3,21 @@ module Users
layout 'procedure_context' layout 'procedure_context'
def commencer def commencer
@procedure = Procedure.publiees.find_by(path: params[:path]) @procedure = retrieve_procedure
return procedure_not_found if @procedure.blank? return procedure_not_found if @procedure.blank? || @procedure.brouillon?
render 'commencer/show' render 'commencer/show'
end end
def commencer_test def commencer_test
@procedure = Procedure.brouillons.find_by(path: params[:path]) @procedure = retrieve_procedure
return procedure_not_found if @procedure.blank? return procedure_not_found if @procedure.blank? || @procedure.publiee?
render 'commencer/show' render 'commencer/show'
end end
def sign_in def sign_in
@procedure = Procedure.find_by(path: params[:path]) @procedure = retrieve_procedure
return procedure_not_found if @procedure.blank? return procedure_not_found if @procedure.blank?
store_user_location!(@procedure) store_user_location!(@procedure)
@ -25,7 +25,7 @@ module Users
end end
def sign_up def sign_up
@procedure = Procedure.find_by(path: params[:path]) @procedure = retrieve_procedure
return procedure_not_found if @procedure.blank? return procedure_not_found if @procedure.blank?
store_user_location!(@procedure) store_user_location!(@procedure)
@ -33,7 +33,7 @@ module Users
end end
def france_connect def france_connect
@procedure = Procedure.find_by(path: params[:path]) @procedure = retrieve_procedure
return procedure_not_found if @procedure.blank? return procedure_not_found if @procedure.blank?
store_user_location!(@procedure) store_user_location!(@procedure)
@ -41,23 +41,25 @@ module Users
end end
def procedure_for_help def procedure_for_help
Procedure.publiees.find_by(path: params[:path]) || Procedure.brouillons.find_by(path: params[:path]) retrieve_procedure
end end
private private
def retrieve_procedure
Procedure.publiees.or(Procedure.brouillons).find_by(path: params[:path])
end
def procedure_not_found def procedure_not_found
procedure = Procedure.find_by(path: params[:path]) procedure = Procedure.find_by(path: params[:path])
if procedure&.archivee? if procedure&.archivee?
flash.alert = t('errors.messages.procedure_archived') flash.alert = t('errors.messages.procedure_archived')
elsif procedure&.publiee?
flash.alert = t('errors.messages.procedure_not_draft')
else else
flash.alert = t('errors.messages.procedure_not_found') flash.alert = t('errors.messages.procedure_not_found')
end end
return redirect_to root_path redirect_to root_path
end end
def store_user_location!(procedure) def store_user_location!(procedure)

View file

@ -1,11 +1,9 @@
module ProcedureHelper module ProcedureHelper
def procedure_lien(procedure) def procedure_lien(procedure)
if procedure.path.present? if procedure.brouillon?
if procedure.brouillon_avec_lien? commencer_test_url(path: procedure.path)
commencer_test_url(path: procedure.path) else
else commencer_url(path: procedure.path)
commencer_url(path: procedure.path)
end
end end
end end

View file

@ -5,10 +5,6 @@ const sources = [
{ {
type: 'address', type: 'address',
url: '/address/suggestions' url: '/address/suggestions'
},
{
type: 'path',
url: '/admin/procedures/path_list'
} }
]; ];

View file

@ -24,10 +24,6 @@ class Instructeur < ApplicationRecord
has_one :user has_one :user
def visible_procedures
procedures.merge(Procedure.avec_lien.or(Procedure.archivees))
end
def follow(dossier) def follow(dossier)
begin begin
followed_dossiers << dossier followed_dossiers << dossier

View file

@ -45,7 +45,6 @@ class Procedure < ApplicationRecord
scope :by_libelle, -> { order(libelle: :asc) } scope :by_libelle, -> { order(libelle: :asc) }
scope :created_during, -> (range) { where(created_at: range) } scope :created_during, -> (range) { where(created_at: range) }
scope :cloned_from_library, -> { where(cloned_from_library: true) } scope :cloned_from_library, -> { where(cloned_from_library: true) }
scope :avec_lien, -> { where.not(path: nil) }
scope :declarative, -> { where.not(declarative_with_state: nil) } scope :declarative, -> { where.not(declarative_with_state: nil) }
scope :for_api, -> { scope :for_api, -> {
@ -65,8 +64,10 @@ class Procedure < ApplicationRecord
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
validates :administrateurs, presence: true validates :administrateurs, presence: true
validates :lien_site_web, presence: true, if: :publiee?
validate :validate_for_publication, on: :publication
validate :check_juridique validate :check_juridique
validates :path, format: { with: /\A[a-z0-9_\-]{3,50}\z/ }, uniqueness: { scope: :aasm_state, case_sensitive: false }, presence: true, allow_blank: false, allow_nil: true validates :path, presence: true, format: { with: /\A[a-z0-9_\-]{3,50}\z/ }, uniqueness: { scope: [:path, :archived_at, :hidden_at], case_sensitive: false }
# FIXME: remove duree_conservation_required flag once all procedures are converted to the new style # FIXME: remove duree_conservation_required flag once all procedures are converted to the new style
validates :duree_conservation_dossiers_dans_ds, allow_nil: false, numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: MAX_DUREE_CONSERVATION }, if: :durees_conservation_required validates :duree_conservation_dossiers_dans_ds, allow_nil: false, numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: MAX_DUREE_CONSERVATION }, if: :durees_conservation_required
validates :duree_conservation_dossiers_hors_ds, allow_nil: false, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, if: :durees_conservation_required validates :duree_conservation_dossiers_hors_ds, allow_nil: false, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, if: :durees_conservation_required
@ -75,7 +76,8 @@ class Procedure < ApplicationRecord
validates_with MonAvisEmbedValidator validates_with MonAvisEmbedValidator
before_save :update_juridique_required before_save :update_juridique_required
before_save :update_durees_conservation_required before_save :update_durees_conservation_required
before_create :ensure_path_exists after_initialize :ensure_path_exists
before_save :ensure_path_exists
after_create :ensure_default_groupe_instructeur after_create :ensure_default_groupe_instructeur
include AASM include AASM
@ -86,11 +88,8 @@ class Procedure < ApplicationRecord
state :archivee state :archivee
state :hidden state :hidden
event :publish, after: :after_publish, guard: :can_publish? do event :publish, before: :before_publish, after: :after_publish do
transitions from: :brouillon, to: :publiee transitions from: :brouillon, to: :publiee
end
event :reopen, after: :after_reopen, guard: :can_publish? do
transitions from: :archivee, to: :publiee transitions from: :archivee, to: :publiee
end end
@ -109,12 +108,18 @@ class Procedure < ApplicationRecord
end end
end end
def publish_or_reopen!(administrateur, path, lien_site_web) def publish_or_reopen!(administrateur)
if archivee? && may_reopen?(administrateur, path, lien_site_web) Procedure.transaction do
reopen!(administrateur, path, lien_site_web) if brouillon?
elsif may_publish?(administrateur, path, lien_site_web) reset!
reset! end
publish!(administrateur, path, lien_site_web)
other_procedure = other_procedure_with_path(path)
if other_procedure.present? && administrateur.owns?(other_procedure)
other_procedure.archive!
end
publish!
end end
end end
@ -126,6 +131,44 @@ class Procedure < ApplicationRecord
end end
end end
def validate_for_publication
old_attributes = self.slice(:aasm_state, :archived_at)
self.aasm_state = :publiee
self.archived_at = nil
is_valid = validate
self.attributes = old_attributes
is_valid
end
def suggested_path(administrateur)
if path_customized?
return path
end
slug = libelle&.parameterize&.first(50)
suggestion = slug
counter = 1
while !path_available?(administrateur, suggestion)
counter = counter + 1
suggestion = "#{slug}-#{counter}"
end
suggestion
end
def other_procedure_with_path(path)
Procedure.publiees
.where.not(id: self.id)
.find_by(path: path)
end
def path_available?(administrateur, path)
procedure = other_procedure_with_path(path)
procedure.blank? || administrateur.owns?(procedure)
end
def locked? def locked?
publiee_ou_archivee? publiee_ou_archivee?
end end
@ -134,11 +177,6 @@ class Procedure < ApplicationRecord
!archivee? !archivee?
end end
# This method is needed for transition. Eventually this will be the same as brouillon?.
def brouillon_avec_lien?
brouillon? && path.present?
end
def publiee_ou_archivee? def publiee_ou_archivee?
publiee? || archivee? publiee? || archivee?
end end
@ -174,8 +212,8 @@ class Procedure < ApplicationRecord
types_de_champ_private.map(&:build_champ) types_de_champ_private.map(&:build_champ)
end end
def default_path def path_customized?
libelle&.parameterize&.first(50) !path.match?(/[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}/)
end end
def organisation_name def organisation_name
@ -370,40 +408,6 @@ class Procedure < ApplicationRecord
percentile_time(:en_construction_at, :processed_at, 90) percentile_time(:en_construction_at, :processed_at, 90)
end end
PATH_AVAILABLE = :available
PATH_AVAILABLE_PUBLIEE = :available_publiee
PATH_NOT_AVAILABLE = :not_available
PATH_NOT_AVAILABLE_BROUILLON = :not_available_brouillon
PATH_CAN_PUBLISH = [PATH_AVAILABLE, PATH_AVAILABLE_PUBLIEE]
def path_availability(administrateur, path)
Procedure.path_availability(administrateur, path, id)
end
def self.path_availability(administrateur, path, exclude_id = nil)
if exclude_id.present?
procedure = where.not(id: exclude_id).find_by(path: path)
else
procedure = find_by(path: path)
end
if procedure.blank?
PATH_AVAILABLE
elsif administrateur.owns?(procedure)
if procedure.brouillon?
PATH_NOT_AVAILABLE_BROUILLON
else
PATH_AVAILABLE_PUBLIEE
end
else
PATH_NOT_AVAILABLE
end
end
def self.find_with_path(path)
where.not(aasm_state: :archivee).where("path LIKE ?", "%#{path}%")
end
def populate_champ_stable_ids def populate_champ_stable_ids
TypeDeChamp.where(procedure: self, stable_id: nil).find_each do |type_de_champ| TypeDeChamp.where(procedure: self, stable_id: nil).find_each do |type_de_champ|
type_de_champ.update_column(:stable_id, type_de_champ.id) type_de_champ.update_column(:stable_id, type_de_champ.id)
@ -497,41 +501,21 @@ class Procedure < ApplicationRecord
end end
end end
def claim_path_ownership!(path) def before_publish
procedure = Procedure.joins(:administrateurs) update!(archived_at: nil)
.where(administrateurs: { id: administrateur_ids })
.find_by(path: path)
if procedure&.publiee? && procedure != self
procedure.archive!
end
update!(path: path)
end end
def can_publish?(administrateur, path, lien_site_web) def after_publish
path_availability(administrateur, path).in?(PATH_CAN_PUBLISH) && lien_site_web.present?
end
def after_publish(administrateur, path, lien_site_web)
update!(published_at: Time.zone.now) update!(published_at: Time.zone.now)
claim_path_ownership!(path)
end
def after_reopen(administrateur, path, lien_site_web)
update!(published_at: Time.zone.now, archived_at: nil)
claim_path_ownership!(path)
end end
def after_archive def after_archive
update!(archived_at: Time.zone.now, path: SecureRandom.uuid) update!(archived_at: Time.zone.now)
end end
def after_hide def after_hide
now = Time.zone.now now = Time.zone.now
update!(hidden_at: now, path: SecureRandom.uuid) update!(hidden_at: now)
dossiers.update_all(hidden_at: now) dossiers.update_all(hidden_at: now)
end end
@ -568,7 +552,7 @@ class Procedure < ApplicationRecord
end end
def ensure_path_exists def ensure_path_exists
if self.path.nil? if self.path.blank?
self.path = SecureRandom.uuid self.path = SecureRandom.uuid
end end
end end

View file

@ -24,12 +24,10 @@ class ProcedureSerializer < ActiveModel::Serializer
end end
def link def link
if object.path.present? if object.brouillon?
if object.brouillon_avec_lien? commencer_test_url(path: object.path)
commencer_test_url(path: object.path) else
else commencer_url(path: object.path)
commencer_url(path: object.path)
end
end end
end end

View file

@ -1,63 +1,49 @@
#publish-modal.modal{ "aria-labelledby" => "myModalLabel", :role => "dialog", :tabindex => "-1" } #publish-modal.modal{ "aria-labelledby" => "myModalLabel", :role => "dialog", :tabindex => "-1" }
.modal-dialog.modal-lg{ :role => "document" } .modal-dialog.modal-lg{ :role => "document" }
= form_tag admin_procedure_publish_path(procedure_id: @procedure.id), method: :put, remote: true do = form_tag admin_procedure_publish_path(procedure_id: procedure.id), method: :put, remote: true do
.modal-content .modal-content
.modal-header .modal-header
%button.close{ "aria-label" => "Close", "data-dismiss" => "modal", :type => "button" } %button.close{ "aria-label" => "Close", "data-dismiss" => "modal", :type => "button" }
%span{ "aria-hidden" => "true" } × %span{ "aria-hidden" => "true" } ×
%h4#myModalLabel.modal-title %h4#myModalLabel.modal-title
= procedure_modal_text(@procedure, :title) = procedure_modal_text(procedure, :title)
%span#publish-modal-title %span#publish-modal-title
.modal-body .modal-body
= procedure_modal_text(@procedure, :body) .text-info
- if !@procedure.archivee? %p
%b = procedure_modal_text(procedure, :body)
Elle ne pourra plus être modifiée à lissue de cette publication. %b Elle ne pourra plus être modifiée à lissue de cette publication.
%br
Afin de faciliter laccès à la démarche, vous êtes invité à personnaliser ladresse d'accès si vous le souhaitez.
%br
.form-group .form-group
%br %h4 Adresse de la démarche
%h4 Lien de la démarche %p Vous pouvez personnaliser le lien public de la démarche pour en faciliter laccès.
%p.center %p
= commencer_url(path: '') = commencer_url(path: '')
= text_field_tag(:path, @procedure.path || @procedure.default_path, = text_field_tag(:path, procedure.path,
id: 'procedure_path', id: 'procedure_path',
placeholder: 'Chemin vers la démarche', placeholder: 'chemin-de-la-démarche',
data: { autocomplete: 'path' }, required: true,
class: 'form-control', class: 'form-control',
maxlength: 50, pattern: '^[a-z0-9_-]{3,50}$',
style: 'width: 300px; display: inline;') title: "De 3 à 50 caractères; minuscules, chiffres et tiret seulement",
%br data: { remote: true, debounce: true, url: admin_procedure_publish_validate_path(procedure) },
.alert.alert-info autocomplete: 'off',
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. style: 'width: 300px; display: inline;')
%br = render 'publish_path_message', procedure: procedure, administrateur: administrateur
%br .text-info
Prenez quelques minutes pour savoir comment établir une bonne relation avec les usagers de votre démarche : 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.
= link_to "Regarder la vidéo de 5 minutes",
"https://vimeo.com/334463514",
target: "_blank"
.form-group .form-group
%h4 Où les usagers trouveront-ils le lien vers cette démarche ? * %h4 Diffusion de la démarche
%p Où les utilisateurs trouveront-ils le lien de la démarche ? Typiquement, il sagit dune page de votre site web.
%p.center %p.center
= text_field_tag(:lien_site_web, @procedure.lien_site_web, = text_field_tag(:lien_site_web, procedure.lien_site_web,
required: true, required: true,
class: 'form-control', class: 'form-control',
autocomplete: 'off',
placeholder: 'https://exemple.gouv.fr/ma_demarche') placeholder: 'https://exemple.gouv.fr/ma_demarche')
.text-info
#path-messages Prenez quelques minutes pour savoir comment établir une bonne relation avec les usagers de votre démarche :
#path_is_mine.text-warning.center.message = link_to "Regarder la vidéo de 5 minutes.",
Ce lien est déjà utilisé par une de vos démarche. "https://vimeo.com/334463514",
%br target: "_blank"
Si vous voulez lutiliser, lancienne démarche sera archivée (plus accessible du public).
#path_is_not_mine.text-danger.center.message
Ce lien est déjà utilisé par une démarche.
%br
Vous ne pouvez pas lutiliser car il appartient à un autre administrateur.
#path_is_invalid.text-danger.center.message
Ce lien
= t('activerecord.errors.models.procedure.attributes.path.invalid')
.modal-footer .modal-footer
= submit_tag procedure_modal_text(@procedure, :submit), class: %w(btn btn btn-success), disabled: :disabled, id: 'publish' = render 'publish_buttons', procedure: procedure, administrateur: administrateur
= button_tag "Annuler", class: %w(btn btn btn-default), data: { dismiss: :modal }, id: 'cancel'

View file

@ -0,0 +1,13 @@
#publish-buttons
= button_tag "Annuler", class: %w(btn btn-default), data: { dismiss: :modal }
- procedure.validate(:publication)
- errors = procedure.errors
-# Ignore the :taken error if the path can be claimed
- if errors.details[:path]&.pluck(:error)&.include?(:taken) && procedure.path_available?(administrateur, procedure.path)
- errors.delete(:path)
- options = { class: %w(btn btn-success), id: 'publish' }
- if errors.details[:path].present?
- options[:disabled] = :disabled
= submit_tag procedure_modal_text(@procedure, :submit), options

View file

@ -0,0 +1,11 @@
#publish-path-message
- procedure.validate(:publication)
- errors = procedure.errors
-# Ignore the :taken error if the path can be claimed, and instead display the :taken_can_be_claimed error message.
- if errors.details[:path]&.pluck(:error)&.include?(:taken) && procedure.path_available?(administrateur, procedure.path)
.alert.alert-warning
= errors.full_message('Le lien public', errors.generate_message(:path, :taken_can_be_claimed))
- elsif errors.messages[:path].present?
-# Display the actual errors for :path
.alert.alert-danger
= errors.full_message('Le lien public', errors.messages[:path].first)

View file

@ -1,11 +0,0 @@
- case availability
- when Procedure::PATH_AVAILABLE_PUBLIEE
Ce lien est déjà utilisé par une de vos démarche.
%br
Si vous voulez lutiliser, lancienne démarche sera archivée lors de la publication de la démarche (plus accessible du public).
- when Procedure::PATH_NOT_AVAILABLE_BROUILLON
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
Vous ne pouvez pas lutiliser car il appartient à un autre administrateur.

View file

@ -1,11 +0,0 @@
<% if @availability == Procedure::PATH_AVAILABLE %>
<%= remove_element('.unavailable-path-message', inner: true) %>
<% else %>
<%= render_to_element('.unavailable-path-message', partial: 'unavailable', locals: { availability: @availability }) %>
<% end %>
<% if @availability.in?(Procedure::PATH_CAN_PUBLISH) %>
<%= enable_element('button[type=submit]') %>
<% else %>
<%= disable_element('button[type=submit]') %>
<% end %>

View file

@ -1 +0,0 @@
<%= "togglePathMessage(true, #{@mine})" %>

View file

@ -0,0 +1,4 @@
= render_to_element("#publish-path-message", partial: 'publish_path_message', outer: true,
locals: { procedure: @procedure, administrateur: current_administrateur })
= render_to_element("#publish-buttons", partial: 'publish_buttons', outer: true,
locals: { procedure: @procedure, administrateur: current_administrateur })

View file

@ -1,7 +1,7 @@
= render partial: 'admin/closed_mail_template_attestation_inconsistency_alert' = render partial: 'admin/closed_mail_template_attestation_inconsistency_alert'
.row.white-back .row.white-back
#procedure_show #procedure_show
= render partial: '/admin/procedures/modal_publish' = render 'modal_publish', procedure: @procedure, administrateur: @current_administrateur
= render partial: '/admin/procedures/modal_transfer' = render partial: '/admin/procedures/modal_transfer'
- if @procedure.brouillon? - if @procedure.brouillon?
@ -44,7 +44,7 @@
.lien-demarche .lien-demarche
%h3 %h3
- if @procedure.brouillon_avec_lien? - if @procedure.brouillon?
Test et publication Test et publication
- else - else
Publication Publication
@ -54,16 +54,16 @@
- elsif @procedure.publiee? - elsif @procedure.publiee?
Cette démarche est <strong>publiée</strong>, certains éléments ne peuvent plus être modifiés. 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 : Pour y accéder vous pouvez utiliser le lien :
= link_to procedure_lien(@procedure), sanitize_url(procedure_lien(@procedure)), target: :blank, rel: :noopener = link_to @procedure_lien, sanitize_url(@procedure_lien), target: :blank, rel: :noopener
%br %br
%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. 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? - elsif @procedure.brouillon?
- if @procedure.missing_steps.empty? - if @procedure.missing_steps.empty?
%p %p
Cette démarche est actuellement <strong>en test</strong>, Cette démarche est actuellement <strong>en test</strong>,
pour y accéder vous pouvez utiliser le lien : pour y accéder vous pouvez utiliser le lien :
= link_to procedure_lien(@procedure), sanitize_url(procedure_lien(@procedure)), target: :blank, rel: :noopener = link_to @procedure_lien, sanitize_url(@procedure_lien), target: :blank, rel: :noopener
%p %p
Toute personne ayant la connaissance de ce lien pourra ainsi remplir des dossiers de test sur votre démarche. Toute personne ayant la connaissance de ce lien pourra ainsi remplir des dossiers de test sur votre démarche.
%br %br
@ -117,7 +117,7 @@
- if @procedure.missing_steps.include?(:service) - if @procedure.missing_steps.include?(:service)
%p.alert.alert-danger %p.alert.alert-danger
Vous devez renseigner les coordonnées de votre Service administratif avant de pouvoir publier votre démarche. Vous devez renseigner les coordonnées de votre Service administratif avant de pouvoir publier votre démarche.
= link_to 'Cliquez ici.', (current_administrateur.services.present? ? url_for(services_path(procedure_id: @procedure.id)) : url_for(new_service_path(procedure_id: @procedure.id))) = link_to 'Cliquez ici.', (@current_administrateur.services.present? ? url_for(services_path(procedure_id: @procedure.id)) : url_for(new_service_path(procedure_id: @procedure.id)))
- if @procedure.missing_steps.include?(:instructeurs) - if @procedure.missing_steps.include?(:instructeurs)
%p.alert.alert-danger %p.alert.alert-danger

View file

@ -15,7 +15,7 @@
- if nav_bar_profile == :instructeur && instructeur_signed_in? - if nav_bar_profile == :instructeur && instructeur_signed_in?
- current_url = request.path_info - current_url = request.path_info
%ul.header-tabs %ul.header-tabs
- if current_instructeur.visible_procedures.count > 0 - if current_instructeur.procedures.count > 0
%li %li
= active_link_to "Démarches", instructeur_procedures_path, active: :inclusive, class: 'tab-link' = active_link_to "Démarches", instructeur_procedures_path, active: :inclusive, class: 'tab-link'
- if current_instructeur.avis.count > 0 - if current_instructeur.avis.count > 0

View file

@ -11,7 +11,7 @@
#procedure-list #procedure-list
%a#onglet-infos{ href: url_for(admin_procedure_path(@procedure)) } %a#onglet-infos{ href: url_for(admin_procedure_path(@procedure)) }
.procedure-list-element{ class: ('active' if active == 'Informations') } .procedure-list-element{ class: ('active' if active == 'Informations') }
- if @procedure.brouillon_avec_lien? - if @procedure.brouillon?
Test et publication Test et publication
- else - else
Publication Publication

View file

@ -163,6 +163,8 @@ fr:
procedure: procedure:
attributes: attributes:
path: path:
taken: est déjà utilisé par une démarche. Vous ne pouvez pas lutiliser car il appartient à un autre administrateur.
taken_can_be_claimed: est identique à celui dune autre de vos démarches publiées. Si vous publiez cette démarche, lancienne sera archivée et ne sera plus accessible au public.
invalid: n'est pas valide. Il doit comporter au moins 3 caractères, au plus 50 caractères et seuls les caractères a-z, 0-9, '_' et '-' sont autorisés. invalid: n'est pas valide. Il doit comporter au moins 3 caractères, au plus 50 caractères et seuls les caractères a-z, 0-9, '_' et '-' sont autorisés.
errors: errors:

View file

@ -159,8 +159,6 @@ Rails.application.routes.draw do
patch 'activate' => '/administrateurs/activate#create' patch 'activate' => '/administrateurs/activate#create'
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 'procedures/available' => 'procedures#check_availability'
resources :procedures do resources :procedures do
collection do collection do
@ -176,6 +174,7 @@ Rails.application.routes.draw do
resources :mail_templates, only: [:index, :edit, :update] resources :mail_templates, only: [:index, :edit, :update]
put 'archive' => 'procedures#archive', as: :archive put 'archive' => 'procedures#archive', as: :archive
get 'publish_validate' => 'procedures#publish_validate', as: :publish_validate
put 'publish' => 'procedures#publish', as: :publish put 'publish' => 'procedures#publish', as: :publish
post 'transfer' => 'procedures#transfer', as: :transfer post 'transfer' => 'procedures#transfer', as: :transfer
put 'clone' => 'procedures#clone', as: :clone put 'clone' => 'procedures#clone', as: :clone

View file

@ -0,0 +1,6 @@
class MakePathNonnull < ActiveRecord::Migration[5.2]
def change
change_column_null :procedures, :path, false
add_index :procedures, [:path, :archived_at, :hidden_at], unique: true
end
end

View file

@ -10,7 +10,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: 2019_09_17_120856) do ActiveRecord::Schema.define(version: 2019_09_17_151652) 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"
@ -480,12 +480,13 @@ ActiveRecord::Schema.define(version: 2019_09_17_120856) do
t.string "cadre_juridique" t.string "cadre_juridique"
t.boolean "juridique_required", default: true t.boolean "juridique_required", default: true
t.boolean "durees_conservation_required", default: true t.boolean "durees_conservation_required", default: true
t.string "path" t.string "path", null: false
t.string "declarative_with_state" t.string "declarative_with_state"
t.text "monavis_embed" t.text "monavis_embed"
t.index ["declarative_with_state"], name: "index_procedures_on_declarative_with_state" t.index ["declarative_with_state"], name: "index_procedures_on_declarative_with_state"
t.index ["hidden_at"], name: "index_procedures_on_hidden_at" t.index ["hidden_at"], name: "index_procedures_on_hidden_at"
t.index ["parent_procedure_id"], name: "index_procedures_on_parent_procedure_id" t.index ["parent_procedure_id"], name: "index_procedures_on_parent_procedure_id"
t.index ["path", "archived_at", "hidden_at"], name: "index_procedures_on_path_and_archived_at_and_hidden_at", unique: true
t.index ["service_id"], name: "index_procedures_on_service_id" t.index ["service_id"], name: "index_procedures_on_service_id"
end end

View file

@ -340,7 +340,7 @@ describe Admin::ProceduresController, type: :controller do
context 'when admin is the owner of the procedure' do context 'when admin is the owner of the procedure' do
before do before do
put :publish, params: { procedure_id: procedure.id, path: path, lien_site_web: lien_site_web } put :publish, format: :js, params: { procedure_id: procedure.id, path: path, lien_site_web: lien_site_web }
procedure.reload procedure.reload
procedure2.reload procedure2.reload
end end
@ -383,7 +383,6 @@ describe Admin::ProceduresController, type: :controller do
expect(procedure.publiee?).to be_falsey expect(procedure.publiee?).to be_falsey
expect(procedure.path).not_to match(path) expect(procedure.path).not_to match(path)
expect(procedure.lien_site_web).to match(lien_site_web) expect(procedure.lien_site_web).to match(lien_site_web)
expect(response.status).to eq 200
end end
it 'previous procedure remains published' do it 'previous procedure remains published' do
@ -401,8 +400,6 @@ describe Admin::ProceduresController, type: :controller do
expect(procedure.publiee?).to be_falsey expect(procedure.publiee?).to be_falsey
expect(procedure.path).not_to match(path) expect(procedure.path).not_to match(path)
expect(procedure.lien_site_web).to match(lien_site_web) expect(procedure.lien_site_web).to match(lien_site_web)
expect(response).to redirect_to :admin_procedures
expect(flash[:alert]).to have_content 'Lien de la démarche invalide'
end end
end end
end end
@ -419,8 +416,7 @@ describe Admin::ProceduresController, type: :controller do
end end
it 'fails' do it 'fails' do
expect(response).to redirect_to :admin_procedures expect(response).to have_http_status(404)
expect(flash[:alert]).to have_content 'Démarche inexistante'
end end
end end
@ -573,54 +569,6 @@ describe Admin::ProceduresController, type: :controller do
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) }
let!(:procedure3) { create(:procedure, :published, administrateur: admin2) }
subject { get :path_list }
let(:body) { JSON.parse(response.body) }
describe 'when no params' do
before do
subject
end
it { expect(response.status).to eq(200) }
it { expect(body.size).to eq(3) }
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 }
end
context 'filtered' do
before do
subject
end
subject { get :path_list, params: { request: URI.encode(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
context 'when procedure is archived' do
let!(:procedure3) { create(:procedure, :archived, administrateur: admin2) }
before do
subject
end
it 'do not return on the json' do
expect(body.size).to eq(2)
end
end
end
describe 'POST #transfer' do describe 'POST #transfer' do
let!(:procedure) { create :procedure, :with_service, administrateur: admin } let!(:procedure) { create :procedure, :with_service, administrateur: admin }
@ -716,63 +664,6 @@ describe Admin::ProceduresController, type: :controller do
end end
end end
describe "GET #check_availability" do
render_views
let(:procedure) { create(:procedure, :with_path, administrateur: admin) }
let(:params) {
{
procedure: {
path: path,
id: procedure.id
}
}
}
let(:path) { generate(:published_path) }
before do
get :check_availability, params: params, format: 'js'
end
context 'self path' do
let(:path) { procedure.path }
it { expect(response.body).to include("innerHTML = ''") }
end
context 'available path' do
it { expect(response.body).to include("innerHTML = ''") }
end
context 'my path (brouillon)' do
let(:procedure_owned) { create(:procedure, :with_path, administrateur: admin) }
let(:path) { procedure_owned.path }
it {
expect(response.body).to include('Une démarche en test existe déjà avec ce lien.')
}
end
context 'my path' do
let(:procedure_owned) { create(:procedure, :published, administrateur: admin) }
let(:path) { procedure_owned.path }
it {
expect(response.body).to include('Ce lien est déjà utilisé par une de vos démarche.')
expect(response.body).to include('Si vous voulez lutiliser, lancienne démarche sera archivée')
}
end
context 'unavailable path' do
let(:procedure_not_owned) { create(:procedure, :with_path, administrateur: create(:administrateur)) }
let(:path) { procedure_not_owned.path }
it {
expect(response.body).to include('Ce lien est déjà utilisé par une démarche.')
expect(response.body).to include('Vous ne pouvez pas lutiliser car il appartient à un autre administrateur.')
}
end
end
describe 'PATCH #monavis' do describe 'PATCH #monavis' do
let!(:procedure) { create(:procedure, administrateur: admin) } let!(:procedure) { create(:procedure, administrateur: admin) }
let(:procedure_params) { let(:procedure_params) {

View file

@ -11,6 +11,7 @@ FactoryBot.define do
duree_conservation_dossiers_hors_ds { 6 } duree_conservation_dossiers_hors_ds { 6 }
ask_birthday { false } ask_birthday { false }
lien_site_web { "https://mon-site.gouv" } lien_site_web { "https://mon-site.gouv" }
path { SecureRandom.uuid }
transient do transient do
administrateur {} administrateur {}
@ -48,7 +49,8 @@ FactoryBot.define do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
procedure.for_individual = true procedure.for_individual = true
procedure.types_de_champ << create(:type_de_champ, libelle: 'Texte obligatoire', mandatory: true) procedure.types_de_champ << create(:type_de_champ, libelle: 'Texte obligatoire', mandatory: true)
procedure.publish!(procedure.administrateurs.first, generate(:published_path), procedure.lien_site_web) procedure.path = generate(:published_path)
procedure.publish!
end end
end end
@ -147,13 +149,15 @@ FactoryBot.define do
trait :published do trait :published do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
procedure.publish!(procedure.administrateurs.first, generate(:published_path), procedure.lien_site_web) procedure.path = generate(:published_path)
procedure.publish!
end end
end end
trait :archived do trait :archived do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
procedure.publish!(procedure.administrateurs.first, generate(:published_path), procedure.lien_site_web) procedure.path = generate(:published_path)
procedure.publish!
procedure.archive! procedure.archive!
end end
end end
@ -162,14 +166,16 @@ FactoryBot.define do
# For now the behavior is the same than :archived # For now the behavior is the same than :archived
# (it may be different in the future though) # (it may be different in the future though)
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
procedure.publish!(procedure.administrateurs.first, generate(:published_path), procedure.lien_site_web) procedure.path = generate(:published_path)
procedure.publish!
procedure.archive! procedure.archive!
end end
end end
trait :hidden do trait :hidden do
after(:build) do |procedure, _evaluator| after(:build) do |procedure, _evaluator|
procedure.publish!(procedure.administrateurs.first, generate(:published_path), procedure.lien_site_web) procedure.path = generate(:published_path)
procedure.publish!
procedure.hide! procedure.hide!
end end
end end

View file

@ -7,23 +7,39 @@ feature 'As an administrateur I wanna clone a procedure', js: true do
let(:administrateur) { create(:administrateur) } let(:administrateur) { create(:administrateur) }
before do before do
create :procedure, :with_service,
aasm_state: :publiee, published_at: Time.zone.now,
administrateurs: [administrateur],
libelle: 'libellé de la procédure',
path: 'libelle-de-la-procedure'
login_as administrateur.user, scope: :user login_as administrateur.user, scope: :user
visit new_from_existing_admin_procedures_path
end end
context 'Cloning procedure' do context 'Cloning a procedure owned by the current admin' do
before 'Create procedure' do scenario do
page.find_by_id('from-scratch').click visit admin_procedures_path
fill_in_dummy_procedure_details
page.find_by_id('save-procedure').click
end
scenario 'Cloning' do
visit admin_procedures_draft_path
expect(page.find_by_id('procedures')['data-item-count']).to eq('1') expect(page.find_by_id('procedures')['data-item-count']).to eq('1')
page.all('.clone-btn').first.click page.all('.clone-btn').first.click
visit admin_procedures_draft_path visit admin_procedures_draft_path
expect(page.find_by_id('procedures')['data-item-count']).to eq('2') expect(page.find_by_id('procedures')['data-item-count']).to eq('1')
click_on Procedure.last.libelle
expect(page).to have_current_path(admin_procedure_path(Procedure.last))
find('#publish-procedure').click
within '#publish-modal' do
expect(find_field('procedure_path').value).to eq 'libelle-de-la-procedure'
expect(page).to have_text('ancienne sera archivée')
fill_in 'lien_site_web', with: 'http://some.website'
click_on 'publish'
end
page.refresh
visit admin_procedures_archived_path
expect(page.find_by_id('procedures')['data-item-count']).to eq('1')
visit admin_procedures_draft_path
expect(page.find_by_id('procedures')['data-item-count']).to eq('0')
end end
end end
end end

View file

@ -98,11 +98,16 @@ feature 'As an administrateur I wanna create a new procedure', js: true do
click_on Procedure.last.libelle click_on Procedure.last.libelle
expect(page).to have_current_path(admin_procedure_path(Procedure.last)) expect(page).to have_current_path(admin_procedure_path(Procedure.last))
expect(page).to have_content('en test')
# Only check the path even though the link is the complete URL
# (Capybara runs the app on an arbitrary host/port.)
expect(page).to have_link(nil, href: /#{commencer_test_path(Procedure.last.path)}/)
expect(page).to have_selector('#publish-procedure', visible: true) expect(page).to have_selector('#publish-procedure', visible: true)
find('#publish-procedure').click find('#publish-procedure').click
within '#publish-modal' do within '#publish-modal' do
expect(page).to have_field('procedure_path') expect(find_field('procedure_path').value).to eq 'libelle-de-la-procedure'
fill_in 'lien_site_web', with: 'http://some.website' fill_in 'lien_site_web', with: 'http://some.website'
click_on 'publish' click_on 'publish'
end end

View file

@ -12,31 +12,6 @@ describe Instructeur, type: :model do
assign(procedure_2) assign(procedure_2)
end end
describe '#visible_procedures' do
let(:procedure_not_assigned) { create :procedure, administrateur: admin }
let(:procedure_with_default_path) { create :procedure, administrateur: admin }
let(:procedure_with_custom_path) { create :procedure, :with_path, administrateur: admin }
let(:procedure_archived_manually) { create :procedure, :archived, administrateur: admin }
let(:procedure_archived_automatically) { create :procedure, :archived_automatically, administrateur: admin }
before do
assign(procedure_with_default_path)
assign(procedure_with_custom_path)
assign(procedure_archived_manually)
assign(procedure_archived_automatically)
end
subject { instructeur.visible_procedures }
it do
expect(subject).not_to include(procedure_not_assigned)
expect(subject).to include(procedure_with_default_path)
expect(subject).to include(procedure_with_custom_path)
expect(subject).to include(procedure_archived_manually)
expect(subject).to include(procedure_archived_automatically)
end
end
describe 'follow' do describe 'follow' do
let(:dossier) { create :dossier } let(:dossier) { create :dossier }
let(:already_followed_dossier) { create :dossier } let(:already_followed_dossier) { create :dossier }

View file

@ -547,12 +547,12 @@ describe Procedure do
end end
describe '#publish!' do describe '#publish!' do
let(:procedure) { create(:procedure) } let(:procedure) { create(:procedure, path: 'example-path') }
let(:now) { Time.zone.now.beginning_of_minute } let(:now) { Time.zone.now.beginning_of_minute }
before do before do
Timecop.freeze(now) Timecop.freeze(now)
procedure.publish!(procedure.administrateurs.first, "example-path", procedure.lien_site_web) procedure.publish!
end end
after { Timecop.return } after { Timecop.return }
@ -616,6 +616,22 @@ describe Procedure do
it { expect(procedure.archived_at).to eq(now) } it { expect(procedure.archived_at).to eq(now) }
end end
describe 'path_customized?' do
let(:procedure) { create :procedure }
subject { procedure.path_customized? }
context 'when the path is still the default' do
it { is_expected.to be_falsey }
end
context 'when the path has been changed' do
before { procedure.path = 'custom_path' }
it { is_expected.to be_truthy }
end
end
describe 'total_dossier' do describe 'total_dossier' do
let(:procedure) { create :procedure } let(:procedure) { create :procedure }
@ -630,12 +646,45 @@ describe Procedure do
it { is_expected.to eq 2 } it { is_expected.to eq 2 }
end end
describe '#default_path' do describe 'suggested_path' do
let(:procedure) { create(:procedure, libelle: 'A long libelle with àccênts, blabla coucou hello un deux trois voila') } let(:procedure) { create :procedure, aasm_state: :publiee, libelle: 'Inscription au Collège' }
subject { procedure.default_path } subject { procedure.suggested_path(procedure.administrateurs.first) }
it { is_expected.to eq('a-long-libelle-with-accents-blabla-coucou-hello-un') } context 'when the path has been customized' do
before { procedure.path = 'custom_path' }
it { is_expected.to eq 'custom_path' }
end
context 'when the suggestion does not conflict' do
it { is_expected.to eq 'inscription-au-college' }
end
context 'when the suggestion conflicts with one procedure' do
before do
create :procedure, aasm_state: :publiee, path: 'inscription-au-college'
end
it { is_expected.to eq 'inscription-au-college-2' }
end
context 'when the suggestion conflicts with several procedures' do
before do
create :procedure, aasm_state: :publiee, path: 'inscription-au-college'
create :procedure, aasm_state: :publiee, path: 'inscription-au-college-2'
end
it { is_expected.to eq 'inscription-au-college-3' }
end
context 'when the suggestion conflicts with another procedure of the same admin' do
before do
create :procedure, aasm_state: :publiee, path: 'inscription-au-college', administrateurs: procedure.administrateurs
end
it { is_expected.to eq 'inscription-au-college' }
end
end end
describe ".default_scope" do describe ".default_scope" do

View file

@ -6,6 +6,7 @@ describe 'admin/procedures/show.html.haml', type: :view do
before do before do
assign(:procedure, procedure) assign(:procedure, procedure)
assign(:procedure_lien, commencer_url(path: procedure.path))
end end
describe 'procedure is draft' do describe 'procedure is draft' do
@ -41,7 +42,7 @@ describe 'admin/procedures/show.html.haml', type: :view do
describe 'procedure is published' do describe 'procedure is published' do
before do before do
procedure.publish!(procedure.administrateurs.first, 'fake_path', procedure.lien_site_web) procedure.publish!
procedure.reload procedure.reload
render render
end end
@ -59,7 +60,7 @@ describe 'admin/procedures/show.html.haml', type: :view do
describe 'procedure is archived' do describe 'procedure is archived' do
before do before do
procedure.publish!(procedure.administrateurs.first, 'fake_path', procedure.lien_site_web) procedure.publish!
procedure.archive! procedure.archive!
procedure.reload procedure.reload
render render