commit
10e64b2f92
67 changed files with 690 additions and 783 deletions
|
@ -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']);
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
||||||
|
|
|
@ -45,4 +45,51 @@
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.send-dossier-actions-bar {
|
||||||
|
// scss-lint:disable VendorPrefix
|
||||||
|
position: -webkit-sticky; // This is needed on Safari (tested on 12.1)
|
||||||
|
// scss-lint:enable VendorPrefix
|
||||||
|
position: sticky;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: $default-padding;
|
||||||
|
margin-left: -$default-padding;
|
||||||
|
margin-right: -$default-padding;
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: $default-spacer;
|
||||||
|
padding-right: $default-padding;
|
||||||
|
padding-left: $default-padding;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
border-top-left-radius: 5px;
|
||||||
|
border-top-right-radius: 5px;
|
||||||
|
border-bottom: none;
|
||||||
|
|
||||||
|
.button {
|
||||||
|
min-height: 38px;
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are more than one button, align the "Send" button to the right
|
||||||
|
.button:not(:first-of-type).send {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal layout
|
||||||
|
@media (min-width: 500px) {
|
||||||
|
padding-top: $default-spacer * 2;
|
||||||
|
padding-bottom: $default-spacer * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compact layout
|
||||||
|
@media (max-width: 500px) {
|
||||||
|
padding-top: $default-spacer;
|
||||||
|
padding-bottom: $default-spacer;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,10 +108,6 @@ footer {
|
||||||
.footer-row {
|
.footer-row {
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// In this case, the bottom margin is defined directly on each individual column
|
// In this case, the bottom margin is defined directly on each individual column
|
||||||
&.footer-columns {
|
&.footer-columns {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|
|
@ -2,6 +2,13 @@
|
||||||
@import "common";
|
@import "common";
|
||||||
@import "constants";
|
@import "constants";
|
||||||
|
|
||||||
|
.procedure-header {
|
||||||
|
a.header-link {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 1 * $default-padding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#procedure-show {
|
#procedure-show {
|
||||||
h1 {
|
h1 {
|
||||||
color: $black;
|
color: $black;
|
||||||
|
@ -9,11 +16,6 @@
|
||||||
margin-bottom: 1 * $default-padding;
|
margin-bottom: 1 * $default-padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.notifications {
|
|
||||||
display: inline-block;
|
|
||||||
margin-bottom: 1 * $default-padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dossiers-table {
|
.dossiers-table {
|
||||||
margin-top: $default-spacer;
|
margin-top: $default-spacer;
|
||||||
margin-bottom: 3 * $default-spacer;
|
margin-bottom: 3 * $default-spacer;
|
||||||
|
|
|
@ -53,7 +53,7 @@ $stat-card-half-horizontal-spacing: 4 * $default-space;
|
||||||
|
|
||||||
.stat-card-half {
|
.stat-card-half {
|
||||||
width: calc((100% - #{$stat-card-half-horizontal-spacing}) / 2);
|
width: calc((100% - #{$stat-card-half-horizontal-spacing}) / 2);
|
||||||
margin-right: 3 * $default-space;
|
margin-right: $stat-card-half-horizontal-spacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-card-title {
|
.stat-card-title {
|
||||||
|
|
|
@ -40,33 +40,20 @@ class Admin::AttestationTemplatesController < AdminController
|
||||||
end
|
end
|
||||||
|
|
||||||
def preview
|
def preview
|
||||||
@title = activated_attestation_params[:title]
|
@attestation = (@procedure.attestation_template || AttestationTemplate.new).render_attributes_for(activated_attestation_params)
|
||||||
@body = activated_attestation_params[:body]
|
|
||||||
@footer = activated_attestation_params[:footer]
|
|
||||||
@created_at = Time.zone.now
|
|
||||||
|
|
||||||
# In a case of a preview, when the user does not change its images,
|
|
||||||
# the images are not uploaded and thus should be retrieved from previous
|
|
||||||
# attestation_template
|
|
||||||
@logo = activated_attestation_params[:logo] || @procedure.attestation_template&.proxy_logo
|
|
||||||
@signature = activated_attestation_params[:signature] || @procedure.attestation_template&.proxy_signature
|
|
||||||
|
|
||||||
render 'admin/attestation_templates/show', formats: [:pdf]
|
render 'admin/attestation_templates/show', formats: [:pdf]
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_logo
|
def delete_logo
|
||||||
attestation_template = @procedure.attestation_template
|
@procedure.attestation_template.logo.purge_later
|
||||||
attestation_template.logo.purge_later
|
|
||||||
attestation_template.logo_active_storage.purge_later
|
|
||||||
|
|
||||||
flash.notice = 'le logo a bien été supprimée'
|
flash.notice = 'le logo a bien été supprimée'
|
||||||
redirect_to edit_admin_procedure_attestation_template_path(@procedure)
|
redirect_to edit_admin_procedure_attestation_template_path(@procedure)
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_signature
|
def delete_signature
|
||||||
attestation_template = @procedure.attestation_template
|
@procedure.attestation_template.signature.purge_later
|
||||||
attestation_template.signature.purge_later
|
|
||||||
attestation_template.signature_active_storage.purge_later
|
|
||||||
|
|
||||||
flash.notice = 'la signature a bien été supprimée'
|
flash.notice = 'la signature a bien été supprimée'
|
||||||
redirect_to edit_admin_procedure_attestation_template_path(@procedure)
|
redirect_to edit_admin_procedure_attestation_template_path(@procedure)
|
||||||
|
|
|
@ -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,35 +206,8 @@ 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
|
|
||||||
|
|
||||||
flash.notice = 'le logo a bien été supprimé'
|
flash.notice = 'le logo a bien été supprimé'
|
||||||
redirect_to edit_admin_procedure_path(@procedure)
|
redirect_to edit_admin_procedure_path(@procedure)
|
||||||
|
@ -274,6 +233,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?
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -16,18 +16,11 @@ module Instructeurs
|
||||||
def attestation
|
def attestation
|
||||||
if dossier.attestation.pdf.attached?
|
if dossier.attestation.pdf.attached?
|
||||||
redirect_to url_for(dossier.attestation.pdf)
|
redirect_to url_for(dossier.attestation.pdf)
|
||||||
elsif dossier.attestation.pdf_active_storage.attached?
|
|
||||||
redirect_to url_for(dossier.attestation.pdf_active_storage)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def apercu_attestation
|
def apercu_attestation
|
||||||
@title = dossier.procedure.attestation_template.title_for_dossier(dossier)
|
@attestation = dossier.procedure.attestation_template.render_attributes_for(dossier: dossier)
|
||||||
@body = dossier.procedure.attestation_template.body_for_dossier(dossier)
|
|
||||||
@footer = dossier.procedure.attestation_template.footer
|
|
||||||
@created_at = Time.zone.now
|
|
||||||
@logo = dossier.procedure.attestation_template&.proxy_logo
|
|
||||||
@signature = dossier.procedure.attestation_template&.proxy_signature
|
|
||||||
|
|
||||||
render 'admin/attestation_templates/show', formats: [:pdf]
|
render 'admin/attestation_templates/show', formats: [:pdf]
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,24 +7,25 @@ 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)
|
||||||
|
|
||||||
groupe_instructeurs = current_instructeur.groupe_instructeurs.where(procedure: @procedures)
|
dossiers = current_instructeur.dossiers.joins(:groupe_instructeur)
|
||||||
|
@dossiers_count_per_procedure = dossiers.all_state.group('groupe_instructeurs.procedure_id').reorder(nil).count
|
||||||
|
@dossiers_a_suivre_count_per_procedure = dossiers.without_followers.en_cours.group('groupe_instructeurs.procedure_id').reorder(nil).count
|
||||||
|
@dossiers_archived_count_per_procedure = dossiers.archived.group('groupe_instructeurs.procedure_id').count
|
||||||
|
@dossiers_termines_count_per_procedure = dossiers.termine.group('groupe_instructeurs.procedure_id').reorder(nil).count
|
||||||
|
|
||||||
dossiers = current_instructeur.dossiers
|
groupe_ids = current_instructeur.groupe_instructeurs.pluck(:id)
|
||||||
@dossiers_count_per_groupe_instructeur = dossiers.all_state.group(:groupe_instructeur_id).reorder(nil).count
|
|
||||||
@dossiers_a_suivre_count_per_groupe_instructeur = dossiers.without_followers.en_cours.group(:groupe_instructeur_id).reorder(nil).count
|
|
||||||
@dossiers_archived_count_per_groupe_instructeur = dossiers.archived.group(:groupe_instructeur_id).count
|
|
||||||
@dossiers_termines_count_per_groupe_instructeur = dossiers.termine.group(:groupe_instructeur_id).reorder(nil).count
|
|
||||||
|
|
||||||
@followed_dossiers_count_per_groupe_instructeur = current_instructeur
|
@followed_dossiers_count_per_procedure = current_instructeur
|
||||||
.followed_dossiers
|
.followed_dossiers
|
||||||
|
.joins(:groupe_instructeur)
|
||||||
.en_cours
|
.en_cours
|
||||||
.where(groupe_instructeur: groupe_instructeurs)
|
.where(groupe_instructeur_id: groupe_ids)
|
||||||
.group(:groupe_instructeur_id)
|
.group('groupe_instructeurs.procedure_id')
|
||||||
.reorder(nil)
|
.reorder(nil)
|
||||||
.count
|
.count
|
||||||
end
|
end
|
||||||
|
@ -205,6 +206,13 @@ module Instructeurs
|
||||||
redirect_to instructeur_procedure_path(procedure)
|
redirect_to instructeur_procedure_path(procedure)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def stats
|
||||||
|
@procedure = procedure
|
||||||
|
@usual_traitement_time = @procedure.stats_usual_traitement_time
|
||||||
|
@dossiers_funnel = @procedure.stats_dossiers_funnel
|
||||||
|
@termines_states = @procedure.stats_termines_states
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def find_field(table, column)
|
def find_field(table, column)
|
||||||
|
@ -235,7 +243,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
|
||||||
|
|
|
@ -14,7 +14,7 @@ module Manager
|
||||||
end
|
end
|
||||||
|
|
||||||
def reinvite
|
def reinvite
|
||||||
Administrateur.find_inactive_by_id(params[:id]).invite!(current_administration.id)
|
Administrateur.find_inactive_by_id(params[:id]).user.invite_administrateur!(current_administration.id)
|
||||||
flash.notice = "Invitation renvoyée"
|
flash.notice = "Invitation renvoyée"
|
||||||
redirect_to manager_administrateur_path(params[:id])
|
redirect_to manager_administrateur_path(params[:id])
|
||||||
end
|
end
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -50,8 +50,6 @@ module Users
|
||||||
def attestation
|
def attestation
|
||||||
if dossier.attestation.pdf.attached?
|
if dossier.attestation.pdf.attached?
|
||||||
redirect_to url_for(dossier.attestation.pdf)
|
redirect_to url_for(dossier.attestation.pdf)
|
||||||
elsif dossier.attestation.pdf_active_storage.attached?
|
|
||||||
redirect_to url_for(dossier.attestation.pdf_active_storage)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,6 @@ const sources = [
|
||||||
{
|
{
|
||||||
type: 'address',
|
type: 'address',
|
||||||
url: '/address/suggestions'
|
url: '/address/suggestions'
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'path',
|
|
||||||
url: '/admin/procedures/path_list'
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module ActiveStorage
|
module ActiveStorage
|
||||||
# Wraps an ActiveStorage::Service to route direct upload and direct download URLs through our proxy,
|
# Wraps an ActiveStorage::Service to route direct upload and direct download URLs through our proxy,
|
||||||
# thus avoiding exposing the storage provider’s URL to our end-users.
|
# thus avoiding exposing the storage provider’s URL to our end-users. It also overrides upload and
|
||||||
|
# object_for methods to fetch and put blobs through encryption proxy.
|
||||||
class Service::DsProxyService < SimpleDelegator
|
class Service::DsProxyService < SimpleDelegator
|
||||||
attr_reader :wrapped
|
attr_reader :wrapped
|
||||||
|
|
||||||
|
@ -23,8 +24,37 @@ module ActiveStorage
|
||||||
publicize(url)
|
publicize(url)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# This method is responsible for writing to object storage. We directly use direct upload
|
||||||
|
# url to ensure we upload through encryption proxy.
|
||||||
|
def upload(key, io, checksum: nil, **)
|
||||||
|
wrapped.send(:instrument, :upload, key: key, checksum: checksum) do
|
||||||
|
url = url_for_direct_upload(key, expires_in: 1.hour)
|
||||||
|
data = Fog::Storage.parse_data(io)
|
||||||
|
|
||||||
|
headers = { 'Content-Type' => wrapped.send(:guess_content_type, io) }.merge(data[:headers])
|
||||||
|
if checksum
|
||||||
|
headers['ETag'] = wrapped.send(:convert_base64digest_to_hexdigest, checksum)
|
||||||
|
end
|
||||||
|
|
||||||
|
response = Typhoeus::Request.new(
|
||||||
|
url,
|
||||||
|
method: :put,
|
||||||
|
body: data[:body].read,
|
||||||
|
headers: headers
|
||||||
|
).run
|
||||||
|
|
||||||
|
if response.success?
|
||||||
|
response
|
||||||
|
else
|
||||||
|
raise ActiveStorage::IntegrityError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# This method is responsible for reading from object storage. We use url method
|
||||||
|
# on the service to ensure we download through encryption proxy.
|
||||||
def object_for(key, &block)
|
def object_for(key, &block)
|
||||||
blob_url = url(key)
|
blob_url = url(key)
|
||||||
if block_given?
|
if block_given?
|
||||||
|
|
|
@ -6,17 +6,12 @@ class ApplicationMailer < ActionMailer::Base
|
||||||
# Attach the procedure logo to the email (if any).
|
# Attach the procedure logo to the email (if any).
|
||||||
# Returns the attachment url.
|
# Returns the attachment url.
|
||||||
def attach_logo(procedure)
|
def attach_logo(procedure)
|
||||||
return nil if !procedure.logo?
|
|
||||||
|
|
||||||
if procedure.logo.attached?
|
if procedure.logo.attached?
|
||||||
logo_filename = procedure.logo.filename.to_s
|
logo_filename = procedure.logo.filename.to_s
|
||||||
attachments.inline[logo_filename] = procedure.logo.download
|
attachments.inline[logo_filename] = procedure.logo.download
|
||||||
elsif procedure.logo_active_storage.attached?
|
attachments[logo_filename].url
|
||||||
logo_filename = procedure.logo_active_storage.filename.to_s
|
|
||||||
attachments.inline[logo_filename] = procedure.logo_active_storage.download
|
|
||||||
end
|
end
|
||||||
|
|
||||||
attachments[logo_filename].url
|
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
# A problem occured when reading logo, maybe the logo is missing and we should clean the procedure to remove logo reference ?
|
# A problem occured when reading logo, maybe the logo is missing and we should clean the procedure to remove logo reference ?
|
||||||
Raven.extra_context(procedure_id: procedure.id)
|
Raven.extra_context(procedure_id: procedure.id)
|
||||||
|
|
|
@ -4,13 +4,10 @@ class Attestation < ApplicationRecord
|
||||||
belongs_to :dossier
|
belongs_to :dossier
|
||||||
|
|
||||||
has_one_attached :pdf
|
has_one_attached :pdf
|
||||||
has_one_attached :pdf_active_storage
|
|
||||||
|
|
||||||
def pdf_url
|
def pdf_url
|
||||||
if pdf.attached?
|
if pdf.attached?
|
||||||
Rails.application.routes.url_helpers.url_for(pdf)
|
Rails.application.routes.url_helpers.url_for(pdf)
|
||||||
elsif pdf_active_storage.attached?
|
|
||||||
Rails.application.routes.url_helpers.url_for(pdf_active_storage)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,9 +7,7 @@ class AttestationTemplate < ApplicationRecord
|
||||||
belongs_to :procedure
|
belongs_to :procedure
|
||||||
|
|
||||||
has_one_attached :logo
|
has_one_attached :logo
|
||||||
has_one_attached :logo_active_storage
|
|
||||||
has_one_attached :signature
|
has_one_attached :signature
|
||||||
has_one_attached :signature_active_storage
|
|
||||||
|
|
||||||
validates :footer, length: { maximum: 190 }
|
validates :footer, length: { maximum: 190 }
|
||||||
|
|
||||||
|
@ -54,14 +52,6 @@ class AttestationTemplate < ApplicationRecord
|
||||||
# we don't want to run virus scanner on duplicated file
|
# we don't want to run virus scanner on duplicated file
|
||||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||||
)
|
)
|
||||||
elsif logo_active_storage.attached?
|
|
||||||
attestation_template.logo.attach(
|
|
||||||
io: StringIO.new(logo_active_storage.download),
|
|
||||||
filename: logo_active_storage.filename.to_s,
|
|
||||||
content_type: logo_active_storage.content_type,
|
|
||||||
# we don't want to run virus scanner on duplicated file
|
|
||||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if signature.attached?
|
if signature.attached?
|
||||||
|
@ -72,65 +62,34 @@ class AttestationTemplate < ApplicationRecord
|
||||||
# we don't want to run virus scanner on duplicated file
|
# we don't want to run virus scanner on duplicated file
|
||||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||||
)
|
)
|
||||||
elsif signature_active_storage.attached?
|
|
||||||
attestation_template.signature.attach(
|
|
||||||
io: StringIO.new(signature_active_storage.download),
|
|
||||||
filename: signature_active_storage.filename.to_s,
|
|
||||||
content_type: signature_active_storage.content_type,
|
|
||||||
# we don't want to run virus scanner on duplicated file
|
|
||||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
attestation_template
|
attestation_template
|
||||||
end
|
end
|
||||||
|
|
||||||
def logo?
|
|
||||||
logo.attached? || logo_active_storage.attached?
|
|
||||||
end
|
|
||||||
|
|
||||||
def signature?
|
|
||||||
signature.attached? || signature_active_storage.attached?
|
|
||||||
end
|
|
||||||
|
|
||||||
def logo_url
|
def logo_url
|
||||||
if logo.attached?
|
if logo.attached?
|
||||||
Rails.application.routes.url_helpers.url_for(logo)
|
Rails.application.routes.url_helpers.url_for(logo)
|
||||||
elsif logo_active_storage.attached?
|
|
||||||
Rails.application.routes.url_helpers.url_for(logo_active_storage)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def signature_url
|
def signature_url
|
||||||
if signature.attached?
|
if signature.attached?
|
||||||
Rails.application.routes.url_helpers.url_for(signature)
|
Rails.application.routes.url_helpers.url_for(signature)
|
||||||
elsif signature_active_storage.attached?
|
|
||||||
Rails.application.routes.url_helpers.url_for(signature_active_storage)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def proxy_logo
|
def render_attributes_for(params = {})
|
||||||
if logo.attached?
|
dossier = params.fetch(:dossier, false)
|
||||||
logo
|
|
||||||
elsif logo_active_storage.attached?
|
|
||||||
logo_active_storage
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def proxy_signature
|
{
|
||||||
if signature.attached?
|
created_at: Time.zone.now,
|
||||||
signature
|
title: dossier ? replace_tags(title, dossier) : params.fetch(:title, ''),
|
||||||
elsif signature_active_storage.attached?
|
body: dossier ? replace_tags(body, dossier) : params.fetch(:body, ''),
|
||||||
signature_active_storage
|
footer: params.fetch(:footer, footer),
|
||||||
end
|
logo: params.fetch(:logo, logo.attached? ? logo : nil),
|
||||||
end
|
signature: params.fetch(:signature, signature.attached? ? signature : nil)
|
||||||
|
}
|
||||||
def title_for_dossier(dossier)
|
|
||||||
replace_tags(title, dossier)
|
|
||||||
end
|
|
||||||
|
|
||||||
def body_for_dossier(dossier)
|
|
||||||
replace_tags(body, dossier)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -147,14 +106,8 @@ class AttestationTemplate < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_pdf(dossier)
|
def build_pdf(dossier)
|
||||||
action_view = ActionView::Base.new(ActionController::Base.view_paths,
|
attestation = render_attributes_for(dossier: dossier)
|
||||||
logo: proxy_logo,
|
action_view = ActionView::Base.new(ActionController::Base.view_paths, attestation: attestation)
|
||||||
title: title_for_dossier(dossier),
|
|
||||||
body: body_for_dossier(dossier),
|
|
||||||
signature: proxy_signature,
|
|
||||||
footer: footer,
|
|
||||||
created_at: Time.zone.now)
|
|
||||||
|
|
||||||
attestation_view = action_view.render(file: 'admin/attestation_templates/show', formats: [:pdf])
|
attestation_view = action_view.render(file: 'admin/attestation_templates/show', formats: [:pdf])
|
||||||
|
|
||||||
StringIO.new(attestation_view)
|
StringIO.new(attestation_view)
|
||||||
|
|
30
app/models/concerns/procedure_stats_concern.rb
Normal file
30
app/models/concerns/procedure_stats_concern.rb
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
module ProcedureStatsConcern
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
def stats_usual_traitement_time
|
||||||
|
Rails.cache.fetch("#{cache_key_with_version}/stats_usual_traitement_time", expires_in: 12.hours) do
|
||||||
|
usual_traitement_time
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def stats_dossiers_funnel
|
||||||
|
Rails.cache.fetch("#{cache_key_with_version}/stats_dossiers_funnel", expires_in: 12.hours) do
|
||||||
|
[
|
||||||
|
['Démarrés', dossiers.count],
|
||||||
|
['Déposés', dossiers.state_not_brouillon.count],
|
||||||
|
['Instruction débutée', dossiers.state_instruction_commencee.count],
|
||||||
|
['Traités', dossiers.state_termine.count]
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def stats_termines_states
|
||||||
|
Rails.cache.fetch("#{cache_key_with_version}/stats_termines_states", expires_in: 12.hours) do
|
||||||
|
[
|
||||||
|
['Acceptés', dossiers.where(state: :accepte).count],
|
||||||
|
['Refusés', dossiers.where(state: :refuse).count],
|
||||||
|
['Classés sans suite', dossiers.where(state: :sans_suite).count]
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -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
|
||||||
|
|
|
@ -3,6 +3,8 @@ require Rails.root.join('lib', 'percentile')
|
||||||
class Procedure < ApplicationRecord
|
class Procedure < ApplicationRecord
|
||||||
self.ignored_columns = ['logo', 'logo_secure_token']
|
self.ignored_columns = ['logo', 'logo_secure_token']
|
||||||
|
|
||||||
|
include ProcedureStatsConcern
|
||||||
|
|
||||||
MAX_DUREE_CONSERVATION = 36
|
MAX_DUREE_CONSERVATION = 36
|
||||||
|
|
||||||
has_many :types_de_champ, -> { root.public_only.ordered }, inverse_of: :procedure, dependent: :destroy
|
has_many :types_de_champ, -> { root.public_only.ordered }, inverse_of: :procedure, dependent: :destroy
|
||||||
|
@ -30,7 +32,6 @@ class Procedure < ApplicationRecord
|
||||||
has_one :defaut_groupe_instructeur, -> { where(label: GroupeInstructeur::DEFAULT_LABEL) }, class_name: 'GroupeInstructeur', inverse_of: :procedure
|
has_one :defaut_groupe_instructeur, -> { where(label: GroupeInstructeur::DEFAULT_LABEL) }, class_name: 'GroupeInstructeur', inverse_of: :procedure
|
||||||
|
|
||||||
has_one_attached :logo
|
has_one_attached :logo
|
||||||
has_one_attached :logo_active_storage
|
|
||||||
has_one_attached :notice
|
has_one_attached :notice
|
||||||
has_one_attached :deliberation
|
has_one_attached :deliberation
|
||||||
|
|
||||||
|
@ -45,7 +46,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 +65,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 +77,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 +89,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 +109,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 +132,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 +178,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 +213,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
|
||||||
|
@ -264,7 +303,6 @@ class Procedure < ApplicationRecord
|
||||||
clone_attachment(:piece_justificative_template, original, kopy)
|
clone_attachment(:piece_justificative_template, original, kopy)
|
||||||
elsif original.is_a?(Procedure)
|
elsif original.is_a?(Procedure)
|
||||||
clone_attachment(:logo, original, kopy)
|
clone_attachment(:logo, original, kopy)
|
||||||
clone_attachment(:logo_active_storage, original, kopy)
|
|
||||||
clone_attachment(:notice, original, kopy)
|
clone_attachment(:notice, original, kopy)
|
||||||
clone_attachment(:deliberation, original, kopy)
|
clone_attachment(:deliberation, original, kopy)
|
||||||
end
|
end
|
||||||
|
@ -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)
|
||||||
|
@ -465,15 +469,9 @@ class Procedure < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def logo?
|
|
||||||
logo.attached? || logo_active_storage.attached?
|
|
||||||
end
|
|
||||||
|
|
||||||
def logo_url
|
def logo_url
|
||||||
if logo.attached?
|
if logo.attached?
|
||||||
Rails.application.routes.url_helpers.url_for(logo)
|
Rails.application.routes.url_helpers.url_for(logo)
|
||||||
elsif logo_active_storage.attached?
|
|
||||||
Rails.application.routes.url_helpers.url_for(logo_active_storage)
|
|
||||||
else
|
else
|
||||||
ActionController::Base.helpers.image_url("marianne.svg")
|
ActionController::Base.helpers.image_url("marianne.svg")
|
||||||
end
|
end
|
||||||
|
@ -497,41 +495,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 +546,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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
class MonAvisEmbedValidator < ActiveModel::Validator
|
class MonAvisEmbedValidator < ActiveModel::Validator
|
||||||
def validate(record)
|
def validate(record)
|
||||||
# We need to ensure the embed code is not any random string in order to avoid injections
|
# We need to ensure the embed code is not any random string in order to avoid injections
|
||||||
r = Regexp.new('<a href="https://monavis.numerique.gouv.fr/Demarches/\d+.*key=[[:alnum:]]+.*">\s*<img src="https://monavis.numerique.gouv.fr/monavis-static/bouton-blanc|bleu.png" alt="Je donne mon avis" title="Je donne mon avis sur cette démarche" />\s*</a>', Regexp::MULTILINE)
|
r = Regexp.new('<a href="https://monavis|voxusagers.numerique.gouv.fr/Demarches/\d+.*key=[[:alnum:]]+.*">\s*<img src="(https://monavis.numerique.gouv.fr/monavis-static/bouton-blanc|bleu.png)|(https://voxusagers.numerique.gouv.fr/static/bouton-(bleu|blanc).svg)" alt="Je donne mon avis" title="Je donne mon avis sur cette démarche" />\s*</a>', Regexp::MULTILINE)
|
||||||
if record.monavis_embed.present? && !r.match?(record.monavis_embed)
|
if record.monavis_embed.present? && !r.match?(record.monavis_embed)
|
||||||
record.errors[:base] << "Le code fourni ne correspond pas au format des codes MonAvis reconnus par la plateforme."
|
record.errors[:base] << "Le code fourni ne correspond pas au format des codes MonAvis reconnus par la plateforme."
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,11 +17,11 @@
|
||||||
celle-ci est également disponible au téléchargement depuis l’espace personnel de l’usager.
|
celle-ci est également disponible au téléchargement depuis l’espace personnel de l’usager.
|
||||||
|
|
||||||
.image-upload
|
.image-upload
|
||||||
- if @attestation_template.logo?
|
- if @attestation_template.logo.attached?
|
||||||
= image_tag @attestation_template.logo_url, class: 'thumbnail'
|
= image_tag @attestation_template.logo_url, class: 'thumbnail'
|
||||||
.form-group
|
.form-group
|
||||||
= f.label :logo, "Logo de l'attestation"
|
= f.label :logo, "Logo de l'attestation"
|
||||||
- if @attestation_template.logo?
|
- if @attestation_template.logo.attached?
|
||||||
= link_to 'Supprimer le logo', admin_procedure_attestation_template_logo_path(@procedure), method: :delete
|
= link_to 'Supprimer le logo', admin_procedure_attestation_template_logo_path(@procedure), method: :delete
|
||||||
= f.file_field :logo, accept: 'image/png, image/jpg, image/jpeg'
|
= f.file_field :logo, accept: 'image/png, image/jpg, image/jpeg'
|
||||||
%p.help-block
|
%p.help-block
|
||||||
|
@ -54,11 +54,11 @@
|
||||||
= tag[:description]
|
= tag[:description]
|
||||||
|
|
||||||
.image-upload
|
.image-upload
|
||||||
- if @attestation_template.signature?
|
- if @attestation_template.signature.attached?
|
||||||
= image_tag @attestation_template.signature_url, class: 'thumbnail'
|
= image_tag @attestation_template.signature_url, class: 'thumbnail'
|
||||||
.form-group
|
.form-group
|
||||||
= f.label :signature, "Tampon de l'attestation"
|
= f.label :signature, "Tampon de l'attestation"
|
||||||
- if @attestation_template.signature?
|
- if @attestation_template.signature.attached?
|
||||||
= link_to 'Supprimer le tampon', admin_procedure_attestation_template_signature_path(@procedure), method: :delete
|
= link_to 'Supprimer le tampon', admin_procedure_attestation_template_signature_path(@procedure), method: :delete
|
||||||
= f.file_field :signature, accept: 'image/png, image/jpg, image/jpeg'
|
= f.file_field :signature, accept: 'image/png, image/jpg, image/jpeg'
|
||||||
%p.help-block
|
%p.help-block
|
||||||
|
|
|
@ -19,6 +19,14 @@ max_logo_width = body_width
|
||||||
max_logo_height = 50.mm
|
max_logo_height = 50.mm
|
||||||
max_signature_size = 50.mm
|
max_signature_size = 50.mm
|
||||||
|
|
||||||
|
title = @attestation.fetch(:title)
|
||||||
|
body = @attestation.fetch(:body)
|
||||||
|
footer = @attestation.fetch(:footer)
|
||||||
|
created_at = @attestation.fetch(:created_at)
|
||||||
|
|
||||||
|
logo = @attestation[:logo]
|
||||||
|
signature = @attestation[:signature]
|
||||||
|
|
||||||
prawn_document(margin: [top_margin, right_margin, bottom_margin, left_margin], page_size: page_size) do |pdf|
|
prawn_document(margin: [top_margin, right_margin, bottom_margin, left_margin], page_size: page_size) do |pdf|
|
||||||
pdf.font_families.update( 'liberation serif' => { normal: Rails.root.join('lib/prawn/fonts/liberation_serif/LiberationSerif-Regular.ttf' )})
|
pdf.font_families.update( 'liberation serif' => { normal: Rails.root.join('lib/prawn/fonts/liberation_serif/LiberationSerif-Regular.ttf' )})
|
||||||
pdf.font 'liberation serif'
|
pdf.font 'liberation serif'
|
||||||
|
@ -29,30 +37,30 @@ prawn_document(margin: [top_margin, right_margin, bottom_margin, left_margin], p
|
||||||
body_height = pdf.cursor - footer_height
|
body_height = pdf.cursor - footer_height
|
||||||
|
|
||||||
pdf.bounding_box([0, pdf.cursor], width: body_width, height: body_height) do
|
pdf.bounding_box([0, pdf.cursor], width: body_width, height: body_height) do
|
||||||
if @logo.present?
|
if logo.present?
|
||||||
logo_file = if @logo.is_a?(ActiveStorage::Attached::One)
|
logo_file = if logo.is_a?(ActiveStorage::Attached::One)
|
||||||
@logo.download
|
logo.download
|
||||||
else
|
else
|
||||||
@logo.read
|
logo.read
|
||||||
end
|
end
|
||||||
pdf.image StringIO.new(logo_file), fit: [max_logo_width , max_logo_height], position: :center
|
pdf.image StringIO.new(logo_file), fit: [max_logo_width , max_logo_height], position: :center
|
||||||
end
|
end
|
||||||
|
|
||||||
pdf.fill_color grey
|
pdf.fill_color grey
|
||||||
pdf.pad_top(40) { pdf.text "le #{l(@created_at, format: '%e %B %Y')}", size: 10, align: :right, character_spacing: -0.5 }
|
pdf.pad_top(40) { pdf.text "le #{l(created_at, format: '%e %B %Y')}", size: 10, align: :right, character_spacing: -0.5 }
|
||||||
|
|
||||||
pdf.fill_color black
|
pdf.fill_color black
|
||||||
pdf.pad_top(40) { pdf.text @title, size: 18, character_spacing: -0.2 }
|
pdf.pad_top(40) { pdf.text title, size: 18, character_spacing: -0.2 }
|
||||||
|
|
||||||
pdf.fill_color grey
|
pdf.fill_color grey
|
||||||
pdf.pad_top(30) { pdf.text @body, size: 10, character_spacing: -0.2, align: :justify }
|
pdf.pad_top(30) { pdf.text body, size: 10, character_spacing: -0.2, align: :justify }
|
||||||
|
|
||||||
if @signature.present?
|
if signature.present?
|
||||||
pdf.pad_top(40) do
|
pdf.pad_top(40) do
|
||||||
signature_file = if @signature.is_a?(ActiveStorage::Attached::One)
|
signature_file = if signature.is_a?(ActiveStorage::Attached::One)
|
||||||
@signature.download
|
signature.download
|
||||||
else
|
else
|
||||||
@signature.read
|
signature.read
|
||||||
end
|
end
|
||||||
pdf.image StringIO.new(signature_file), fit: [max_signature_size , max_signature_size], position: :right
|
pdf.image StringIO.new(signature_file), fit: [max_signature_size , max_signature_size], position: :right
|
||||||
end
|
end
|
||||||
|
@ -62,6 +70,6 @@ prawn_document(margin: [top_margin, right_margin, bottom_margin, left_margin], p
|
||||||
pdf.repeat(:all) do
|
pdf.repeat(:all) do
|
||||||
pdf.move_cursor_to footer_height - 10
|
pdf.move_cursor_to footer_height - 10
|
||||||
pdf.fill_color grey
|
pdf.fill_color grey
|
||||||
pdf.text @footer, align: :center, size: 8
|
pdf.text footer, align: :center, size: 8
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
.row
|
.row
|
||||||
.col-md-6
|
.col-md-6
|
||||||
%h4 Logo de la démarche
|
%h4 Logo de la démarche
|
||||||
- if @procedure.logo?
|
- if @procedure.logo.attached?
|
||||||
= image_tag @procedure.logo_url, { style: 'height: 40px; display: inline; margin-right: 6px;', id: 'preview_procedure_logo' }
|
= image_tag @procedure.logo_url, { style: 'height: 40px; display: inline; margin-right: 6px;', id: 'preview_procedure_logo' }
|
||||||
\-
|
\-
|
||||||
|
|
||||||
|
|
|
@ -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 à l’issue de cette publication.
|
%b Elle ne pourra plus être modifiée à l’issue de cette publication.
|
||||||
%br
|
|
||||||
Afin de faciliter l’accès à la démarche, vous êtes invité à personnaliser l’adresse 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 l’accè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 s’agit d’une 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 l’utiliser, l’ancienne 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 l’utiliser 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'
|
|
||||||
|
|
13
app/views/admin/procedures/_publish_buttons.html.haml
Normal file
13
app/views/admin/procedures/_publish_buttons.html.haml
Normal 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
|
11
app/views/admin/procedures/_publish_path_message.html.haml
Normal file
11
app/views/admin/procedures/_publish_path_message.html.haml
Normal 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)
|
|
@ -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 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
|
|
||||||
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 l’utiliser car il appartient à un autre administrateur.
|
|
|
@ -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 %>
|
|
|
@ -1 +0,0 @@
|
||||||
<%= "togglePathMessage(true, #{@mine})" %>
|
|
4
app/views/admin/procedures/publish_validate.js.haml
Normal file
4
app/views/admin/procedures/publish_validate.js.haml
Normal 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 })
|
|
@ -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
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
%strong Logo
|
%strong Logo
|
||||||
%p
|
%p
|
||||||
- if field.data.logo?
|
- if field.data.logo.attached?
|
||||||
= image_tag field.data.logo_url
|
= image_tag field.data.logo_url
|
||||||
- else
|
- else
|
||||||
Aucun
|
Aucun
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
%strong Signature
|
%strong Signature
|
||||||
%p
|
%p
|
||||||
- if field.data.signature?
|
- if field.data.signature.attached?
|
||||||
= image_tag field.data.signature_url
|
= image_tag field.data.signature_url
|
||||||
- else
|
- else
|
||||||
Aucun
|
Aucun
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
%li
|
%li
|
||||||
%object
|
%object
|
||||||
= link_to(instructeur_procedure_path(p, statut: 'a-suivre')) do
|
= link_to(instructeur_procedure_path(p, statut: 'a-suivre')) do
|
||||||
- a_suivre_count = @dossiers_a_suivre_count_per_groupe_instructeur[p.defaut_groupe_instructeur.id] || 0
|
- a_suivre_count = @dossiers_a_suivre_count_per_procedure[p.id] || 0
|
||||||
.stats-number
|
.stats-number
|
||||||
= a_suivre_count
|
= a_suivre_count
|
||||||
.stats-legend
|
.stats-legend
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
= link_to(instructeur_procedure_path(p, statut: 'suivis')) do
|
= link_to(instructeur_procedure_path(p, statut: 'suivis')) do
|
||||||
- if current_instructeur.notifications_per_procedure[p.id].present?
|
- if current_instructeur.notifications_per_procedure[p.id].present?
|
||||||
%span.notifications{ 'aria-label': "notifications" }
|
%span.notifications{ 'aria-label': "notifications" }
|
||||||
- followed_count = @followed_dossiers_count_per_groupe_instructeur[p.defaut_groupe_instructeur.id] || 0
|
- followed_count = @followed_dossiers_count_per_procedure[p.id] || 0
|
||||||
.stats-number
|
.stats-number
|
||||||
= followed_count
|
= followed_count
|
||||||
.stats-legend
|
.stats-legend
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
= link_to(instructeur_procedure_path(p, statut: 'traites')) do
|
= link_to(instructeur_procedure_path(p, statut: 'traites')) do
|
||||||
- if current_instructeur.notifications_per_procedure(:termine)[p.id].present?
|
- if current_instructeur.notifications_per_procedure(:termine)[p.id].present?
|
||||||
%span.notifications{ 'aria-label': "notifications" }
|
%span.notifications{ 'aria-label': "notifications" }
|
||||||
- termines_count = @dossiers_termines_count_per_groupe_instructeur[p.defaut_groupe_instructeur.id] || 0
|
- termines_count = @dossiers_termines_count_per_procedure[p.id] || 0
|
||||||
.stats-number
|
.stats-number
|
||||||
= termines_count
|
= termines_count
|
||||||
.stats-legend
|
.stats-legend
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
%li
|
%li
|
||||||
%object
|
%object
|
||||||
= link_to(instructeur_procedure_path(p, statut: 'tous')) do
|
= link_to(instructeur_procedure_path(p, statut: 'tous')) do
|
||||||
- dossier_count = @dossiers_count_per_groupe_instructeur[p.defaut_groupe_instructeur.id] || 0
|
- dossier_count = @dossiers_count_per_procedure[p.id] || 0
|
||||||
.stats-number
|
.stats-number
|
||||||
= dossier_count
|
= dossier_count
|
||||||
.stats-legend
|
.stats-legend
|
||||||
|
@ -55,7 +55,7 @@
|
||||||
%li
|
%li
|
||||||
%object
|
%object
|
||||||
= link_to(instructeur_procedure_path(p, statut: 'archives')) do
|
= link_to(instructeur_procedure_path(p, statut: 'archives')) do
|
||||||
- archived_count = @dossiers_archived_count_per_groupe_instructeur[p.defaut_groupe_instructeur.id] || 0
|
- archived_count = @dossiers_archived_count_per_procedure[p.id] || 0
|
||||||
.stats-number
|
.stats-number
|
||||||
= archived_count
|
= archived_count
|
||||||
.stats-legend
|
.stats-legend
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
|
|
||||||
.procedure-header
|
.procedure-header
|
||||||
%h1= procedure_libelle @procedure
|
%h1= procedure_libelle @procedure
|
||||||
= link_to 'configurez vos notifications', email_notifications_instructeur_procedure_path(@procedure), class: 'notifications'
|
= link_to 'gestion des notifications', email_notifications_instructeur_procedure_path(@procedure), class: 'header-link'
|
||||||
|
|
|
||||||
|
= link_to 'statistiques', stats_instructeur_procedure_path(@procedure), class: 'header-link'
|
||||||
|
|
||||||
|
|
||||||
%ul.tabs
|
%ul.tabs
|
||||||
|
|
32
app/views/instructeurs/procedures/stats.html.haml
Normal file
32
app/views/instructeurs/procedures/stats.html.haml
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
- title = "Statistiques · #{@procedure.libelle}"
|
||||||
|
- content_for(:title, title)
|
||||||
|
|
||||||
|
= render partial: 'new_administrateur/breadcrumbs',
|
||||||
|
locals: { steps: [link_to(@procedure.libelle, procedure_path(@procedure)),
|
||||||
|
'Statistiques'] }
|
||||||
|
|
||||||
|
.statistiques
|
||||||
|
%h1.new-h1= title
|
||||||
|
.stat-cards
|
||||||
|
- if @usual_traitement_time.present?
|
||||||
|
.stat-card.big-number-card
|
||||||
|
%span.big-number-card-title TEMPS DE TRAITEMENT USUEL
|
||||||
|
%span.big-number-card-number
|
||||||
|
= distance_of_time_in_words(@usual_traitement_time)
|
||||||
|
%span.big-number-card-detail
|
||||||
|
90% des demandes du mois dernier ont été traitées en moins de #{distance_of_time_in_words(@usual_traitement_time)}.
|
||||||
|
|
||||||
|
.stat-cards
|
||||||
|
.stat-card.stat-card-half.pull-left
|
||||||
|
%span.stat-card-title AVANCÉE DES DOSSIERS
|
||||||
|
.chart-container
|
||||||
|
.chart
|
||||||
|
= area_chart @dossiers_funnel
|
||||||
|
|
||||||
|
.stat-card.stat-card-half.pull-left
|
||||||
|
%span.stat-card-title TAUX D’ACCEPTATION
|
||||||
|
.chart-container
|
||||||
|
.chart
|
||||||
|
- colors = %w(#C3D9FF #0069CC #1C7EC9) # from _colors.scss
|
||||||
|
= pie_chart @termines_states, colors: colors
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
locals: { champ: champ, form: champ_form }
|
locals: { champ: champ, form: champ_form }
|
||||||
|
|
||||||
- if !apercu
|
- if !apercu
|
||||||
.send-wrapper
|
.send-dossier-actions-bar
|
||||||
- if dossier.brouillon?
|
- if dossier.brouillon?
|
||||||
= f.button 'Enregistrer le brouillon',
|
= f.button 'Enregistrer le brouillon',
|
||||||
formnovalidate: true,
|
formnovalidate: true,
|
||||||
|
|
|
@ -163,6 +163,8 @@ fr:
|
||||||
procedure:
|
procedure:
|
||||||
attributes:
|
attributes:
|
||||||
path:
|
path:
|
||||||
|
taken: est déjà utilisé par une démarche. Vous ne pouvez pas l’utiliser car il appartient à un autre administrateur.
|
||||||
|
taken_can_be_claimed: est identique à celui d’une autre de vos démarches publiées. Si vous publiez cette démarche, l’ancienne 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:
|
||||||
|
|
|
@ -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
|
||||||
|
@ -286,6 +285,7 @@ Rails.application.routes.draw do
|
||||||
post 'add_filter'
|
post 'add_filter'
|
||||||
get 'remove_filter' => 'procedures#remove_filter', as: 'remove_filter'
|
get 'remove_filter' => 'procedures#remove_filter', as: 'remove_filter'
|
||||||
get 'download_dossiers'
|
get 'download_dossiers'
|
||||||
|
get 'stats'
|
||||||
get 'email_notifications'
|
get 'email_notifications'
|
||||||
patch 'update_email_notifications'
|
patch 'update_email_notifications'
|
||||||
|
|
||||||
|
|
8
db/migrate/20190917115911_drop_flipflop_features.rb
Normal file
8
db/migrate/20190917115911_drop_flipflop_features.rb
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
class DropFlipflopFeatures < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
remove_column :administrateurs, :features
|
||||||
|
remove_column :instructeurs, :features
|
||||||
|
|
||||||
|
drop_table :flipflop_features
|
||||||
|
end
|
||||||
|
end
|
8
db/migrate/20190917120039_remove_carrierwave_columns.rb
Normal file
8
db/migrate/20190917120039_remove_carrierwave_columns.rb
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
class RemoveCarrierwaveColumns < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
remove_columns :procedures, :logo, :logo_secure_token
|
||||||
|
remove_columns :commentaires, :file, :piece_justificative_id
|
||||||
|
remove_columns :attestations, :pdf, :content_secure_token
|
||||||
|
remove_columns :attestation_templates, :logo, :logo_secure_token, :signature, :signature_secure_token
|
||||||
|
end
|
||||||
|
end
|
31
db/migrate/20190917120047_remove_devise_columns.rb
Normal file
31
db/migrate/20190917120047_remove_devise_columns.rb
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
class RemoveDeviseColumns < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
remove_columns :administrateurs,
|
||||||
|
:encrypted_password,
|
||||||
|
:reset_password_token,
|
||||||
|
:reset_password_sent_at,
|
||||||
|
:remember_created_at,
|
||||||
|
:sign_in_count,
|
||||||
|
:current_sign_in_at,
|
||||||
|
:last_sign_in_at,
|
||||||
|
:current_sign_in_ip,
|
||||||
|
:last_sign_in_ip,
|
||||||
|
:failed_attempts,
|
||||||
|
:unlock_token,
|
||||||
|
:locked_at
|
||||||
|
|
||||||
|
remove_columns :instructeurs,
|
||||||
|
:encrypted_password,
|
||||||
|
:reset_password_token,
|
||||||
|
:reset_password_sent_at,
|
||||||
|
:remember_created_at,
|
||||||
|
:sign_in_count,
|
||||||
|
:current_sign_in_at,
|
||||||
|
:last_sign_in_at,
|
||||||
|
:current_sign_in_ip,
|
||||||
|
:last_sign_in_ip,
|
||||||
|
:failed_attempts,
|
||||||
|
:unlock_token,
|
||||||
|
:locked_at
|
||||||
|
end
|
||||||
|
end
|
6
db/migrate/20190917120856_remove_unused_columns.rb
Normal file
6
db/migrate/20190917120856_remove_unused_columns.rb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
class RemoveUnusedColumns < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
remove_column :dossiers, :json_latlngs
|
||||||
|
remove_column :services, :siret
|
||||||
|
end
|
||||||
|
end
|
6
db/migrate/20190917151652_make_path_nonnull.rb
Normal file
6
db/migrate/20190917151652_make_path_nonnull.rb
Normal 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
|
54
db/schema.rb
54
db/schema.rb
|
@ -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_08_28_073736) 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"
|
||||||
|
@ -49,26 +49,11 @@ ActiveRecord::Schema.define(version: 2019_08_28_073736) do
|
||||||
|
|
||||||
create_table "administrateurs", id: :serial, force: :cascade do |t|
|
create_table "administrateurs", id: :serial, force: :cascade do |t|
|
||||||
t.string "email", default: "", null: false
|
t.string "email", default: "", null: false
|
||||||
t.string "encrypted_password", default: "", null: false
|
|
||||||
t.string "reset_password_token"
|
|
||||||
t.datetime "reset_password_sent_at"
|
|
||||||
t.datetime "remember_created_at"
|
|
||||||
t.integer "sign_in_count", default: 0, null: false
|
|
||||||
t.datetime "current_sign_in_at"
|
|
||||||
t.datetime "last_sign_in_at"
|
|
||||||
t.string "current_sign_in_ip"
|
|
||||||
t.string "last_sign_in_ip"
|
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.boolean "active", default: false
|
t.boolean "active", default: false
|
||||||
t.jsonb "features", default: {}, null: false
|
|
||||||
t.string "encrypted_token"
|
t.string "encrypted_token"
|
||||||
t.integer "failed_attempts", default: 0, null: false
|
|
||||||
t.string "unlock_token"
|
|
||||||
t.datetime "locked_at"
|
|
||||||
t.index ["email"], name: "index_administrateurs_on_email", unique: true
|
t.index ["email"], name: "index_administrateurs_on_email", unique: true
|
||||||
t.index ["reset_password_token"], name: "index_administrateurs_on_reset_password_token", unique: true
|
|
||||||
t.index ["unlock_token"], name: "index_administrateurs_on_unlock_token", unique: true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "administrateurs_instructeurs", id: false, force: :cascade do |t|
|
create_table "administrateurs_instructeurs", id: false, force: :cascade do |t|
|
||||||
|
@ -130,24 +115,18 @@ ActiveRecord::Schema.define(version: 2019_08_28_073736) do
|
||||||
t.text "title"
|
t.text "title"
|
||||||
t.text "body"
|
t.text "body"
|
||||||
t.text "footer"
|
t.text "footer"
|
||||||
t.string "logo"
|
|
||||||
t.string "signature"
|
|
||||||
t.boolean "activated"
|
t.boolean "activated"
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.integer "procedure_id"
|
t.integer "procedure_id"
|
||||||
t.string "logo_secure_token"
|
|
||||||
t.string "signature_secure_token"
|
|
||||||
t.index ["procedure_id"], name: "index_attestation_templates_on_procedure_id", unique: true
|
t.index ["procedure_id"], name: "index_attestation_templates_on_procedure_id", unique: true
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "attestations", id: :serial, force: :cascade do |t|
|
create_table "attestations", id: :serial, force: :cascade do |t|
|
||||||
t.string "pdf"
|
|
||||||
t.string "title"
|
t.string "title"
|
||||||
t.integer "dossier_id", null: false
|
t.integer "dossier_id", null: false
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.string "content_secure_token"
|
|
||||||
t.index ["dossier_id"], name: "index_attestations_on_dossier_id"
|
t.index ["dossier_id"], name: "index_attestations_on_dossier_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -205,8 +184,6 @@ ActiveRecord::Schema.define(version: 2019_08_28_073736) do
|
||||||
t.string "body"
|
t.string "body"
|
||||||
t.integer "dossier_id"
|
t.integer "dossier_id"
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.integer "piece_justificative_id"
|
|
||||||
t.string "file"
|
|
||||||
t.bigint "user_id"
|
t.bigint "user_id"
|
||||||
t.bigint "instructeur_id"
|
t.bigint "instructeur_id"
|
||||||
t.index ["dossier_id"], name: "index_commentaires_on_dossier_id"
|
t.index ["dossier_id"], name: "index_commentaires_on_dossier_id"
|
||||||
|
@ -266,7 +243,6 @@ ActiveRecord::Schema.define(version: 2019_08_28_073736) do
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.string "state"
|
t.string "state"
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
t.text "json_latlngs"
|
|
||||||
t.boolean "archived", default: false
|
t.boolean "archived", default: false
|
||||||
t.datetime "en_construction_at"
|
t.datetime "en_construction_at"
|
||||||
t.datetime "en_instruction_at"
|
t.datetime "en_instruction_at"
|
||||||
|
@ -348,13 +324,6 @@ ActiveRecord::Schema.define(version: 2019_08_28_073736) do
|
||||||
t.index ["user_id"], name: "index_feedbacks_on_user_id"
|
t.index ["user_id"], name: "index_feedbacks_on_user_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "flipflop_features", force: :cascade do |t|
|
|
||||||
t.string "key", null: false
|
|
||||||
t.boolean "enabled", default: false, null: false
|
|
||||||
t.datetime "created_at", null: false
|
|
||||||
t.datetime "updated_at", null: false
|
|
||||||
end
|
|
||||||
|
|
||||||
create_table "flipper_features", force: :cascade do |t|
|
create_table "flipper_features", force: :cascade do |t|
|
||||||
t.string "key", null: false
|
t.string "key", null: false
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
|
@ -443,26 +412,11 @@ ActiveRecord::Schema.define(version: 2019_08_28_073736) do
|
||||||
|
|
||||||
create_table "instructeurs", id: :serial, force: :cascade do |t|
|
create_table "instructeurs", id: :serial, force: :cascade do |t|
|
||||||
t.string "email", default: "", null: false
|
t.string "email", default: "", null: false
|
||||||
t.string "encrypted_password", default: "", null: false
|
|
||||||
t.string "reset_password_token"
|
|
||||||
t.datetime "reset_password_sent_at"
|
|
||||||
t.datetime "remember_created_at"
|
|
||||||
t.integer "sign_in_count", default: 0, null: false
|
|
||||||
t.datetime "current_sign_in_at"
|
|
||||||
t.datetime "last_sign_in_at"
|
|
||||||
t.string "current_sign_in_ip"
|
|
||||||
t.string "last_sign_in_ip"
|
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.text "encrypted_login_token"
|
t.text "encrypted_login_token"
|
||||||
t.datetime "login_token_created_at"
|
t.datetime "login_token_created_at"
|
||||||
t.jsonb "features", default: {"enable_email_login_token"=>true}, null: false
|
|
||||||
t.integer "failed_attempts", default: 0, null: false
|
|
||||||
t.string "unlock_token"
|
|
||||||
t.datetime "locked_at"
|
|
||||||
t.index ["email"], name: "index_instructeurs_on_email", unique: true
|
t.index ["email"], name: "index_instructeurs_on_email", unique: true
|
||||||
t.index ["reset_password_token"], name: "index_instructeurs_on_reset_password_token", unique: true
|
|
||||||
t.index ["unlock_token"], name: "index_instructeurs_on_unlock_token", unique: true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "invites", id: :serial, force: :cascade do |t|
|
create_table "invites", id: :serial, force: :cascade do |t|
|
||||||
|
@ -505,9 +459,7 @@ ActiveRecord::Schema.define(version: 2019_08_28_073736) do
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.boolean "euro_flag", default: false
|
t.boolean "euro_flag", default: false
|
||||||
t.string "logo"
|
|
||||||
t.boolean "cerfa_flag", default: false
|
t.boolean "cerfa_flag", default: false
|
||||||
t.string "logo_secure_token"
|
|
||||||
t.string "lien_site_web"
|
t.string "lien_site_web"
|
||||||
t.string "lien_notice"
|
t.string "lien_notice"
|
||||||
t.boolean "for_individual", default: false
|
t.boolean "for_individual", default: false
|
||||||
|
@ -528,12 +480,13 @@ ActiveRecord::Schema.define(version: 2019_08_28_073736) 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
|
||||||
|
|
||||||
|
@ -566,7 +519,6 @@ ActiveRecord::Schema.define(version: 2019_08_28_073736) do
|
||||||
t.string "telephone"
|
t.string "telephone"
|
||||||
t.text "horaires"
|
t.text "horaires"
|
||||||
t.text "adresse"
|
t.text "adresse"
|
||||||
t.string "siret"
|
|
||||||
t.index ["administrateur_id", "nom"], name: "index_services_on_administrateur_id_and_nom", unique: true
|
t.index ["administrateur_id", "nom"], name: "index_services_on_administrateur_id_and_nom", unique: true
|
||||||
t.index ["administrateur_id"], name: "index_services_on_administrateur_id"
|
t.index ["administrateur_id"], name: "index_services_on_administrateur_id"
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
namespace :'2019_05_29_migrate_commentaire_pj' do
|
|
||||||
task run: :environment do
|
|
||||||
commentaires = Commentaire.where
|
|
||||||
.not(file: nil)
|
|
||||||
.left_joins(:piece_jointe_attachment)
|
|
||||||
.where('active_storage_attachments.id IS NULL')
|
|
||||||
.order(:created_at)
|
|
||||||
|
|
||||||
limit = ENV['LIMIT']
|
|
||||||
if limit
|
|
||||||
commentaires.limit!(limit.to_i)
|
|
||||||
end
|
|
||||||
|
|
||||||
progress = ProgressReport.new(commentaires.count)
|
|
||||||
commentaires.find_each do |commentaire|
|
|
||||||
if commentaire.file.present?
|
|
||||||
dossier = Dossier.unscope(where: :hidden_at).find(commentaire.dossier_id)
|
|
||||||
uri = URI.parse(URI.escape(commentaire.file_url))
|
|
||||||
response = Typhoeus.get(uri)
|
|
||||||
if response.success?
|
|
||||||
filename = commentaire.file.filename || commentaire.file_identifier
|
|
||||||
updated_at = commentaire.updated_at
|
|
||||||
dossier_updated_at = dossier.updated_at
|
|
||||||
commentaire.piece_jointe.attach(
|
|
||||||
io: StringIO.new(response.body),
|
|
||||||
filename: filename,
|
|
||||||
content_type: commentaire.file.content_type,
|
|
||||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
|
||||||
)
|
|
||||||
commentaire.update_column(:updated_at, updated_at)
|
|
||||||
dossier.update_column(:updated_at, dossier_updated_at)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
progress.inc
|
|
||||||
end
|
|
||||||
progress.finish
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -30,13 +30,13 @@ describe Admin::AttestationTemplatesController, type: :controller do
|
||||||
|
|
||||||
context 'with an interlaced png' do
|
context 'with an interlaced png' do
|
||||||
let(:upload_params) { { logo: interlaced_logo } }
|
let(:upload_params) { { logo: interlaced_logo } }
|
||||||
it { expect(assigns(:logo).read).to eq(uninterlaced_logo.read) }
|
it { expect(assigns(:attestation)[:logo].read).to eq(uninterlaced_logo.read) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'if an attestation template does not exist on the procedure' do
|
context 'if an attestation template does not exist on the procedure' do
|
||||||
let(:attestation_template) { nil }
|
let(:attestation_template) { nil }
|
||||||
it { expect(subject.status).to eq(200) }
|
it { expect(subject.status).to eq(200) }
|
||||||
it { expect(assigns).to include(upload_params.stringify_keys) }
|
it { expect(assigns(:attestation)).to include(upload_params) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'if an attestation template exists on the procedure' do
|
context 'if an attestation template exists on the procedure' do
|
||||||
|
@ -48,18 +48,18 @@ describe Admin::AttestationTemplatesController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
it { expect(subject.status).to eq(200) }
|
it { expect(subject.status).to eq(200) }
|
||||||
it { expect(assigns).to include(upload_params.stringify_keys) }
|
it { expect(assigns(:attestation)).to include(upload_params) }
|
||||||
it { expect(assigns[:created_at]).to eq(Time.zone.now) }
|
it { expect(assigns(:attestation)[:created_at]).to eq(Time.zone.now) }
|
||||||
it { expect(assigns(:logo).download).to eq(logo2.read) }
|
it { expect(assigns(:attestation)[:logo].download).to eq(logo2.read) }
|
||||||
it { expect(assigns(:signature).download).to eq(signature2.read) }
|
it { expect(assigns(:attestation)[:signature].download).to eq(signature2.read) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with empty logo' do
|
context 'with empty logo' do
|
||||||
it { expect(subject.status).to eq(200) }
|
it { expect(subject.status).to eq(200) }
|
||||||
it { expect(assigns).to include(upload_params.stringify_keys) }
|
it { expect(assigns(:attestation)).to include(upload_params) }
|
||||||
it { expect(assigns[:created_at]).to eq(Time.zone.now) }
|
it { expect(assigns(:attestation)[:created_at]).to eq(Time.zone.now) }
|
||||||
it { expect(assigns(:logo)).to eq(nil) }
|
it { expect(assigns(:attestation)[:logo]).to eq(nil) }
|
||||||
it { expect(assigns(:signature)).to eq(nil) }
|
it { expect(assigns(:attestation)[:signature]).to eq(nil) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -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 l’utiliser, l’ancienne 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 l’utiliser 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) {
|
||||||
|
@ -796,10 +687,11 @@ describe Admin::ProceduresController, type: :controller do
|
||||||
patch :update_monavis, params: { procedure_id: procedure.id, procedure: procedure_params }
|
patch :update_monavis, params: { procedure_id: procedure.id, procedure: procedure_params }
|
||||||
procedure.reload
|
procedure.reload
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:monavis_embed) {
|
let(:monavis_embed) {
|
||||||
<<-MSG
|
<<-MSG
|
||||||
<a href="https://monavis.numerique.gouv.fr/Demarches/123?&view-mode=formulaire-avis&nd_mode=en-ligne-enti%C3%A8rement&nd_source=button&key=cd4a872d475e4045666057f">
|
<a href="https://voxusagers.numerique.gouv.fr/Demarches/2136?&view-mode=formulaire-avis&nd_mode=en-ligne-enti%C3%A8rement&nd_source=button&key=e93e77cfd9bf7cce9d10f7a10be55730">
|
||||||
<img src="https://monavis.numerique.gouv.fr/monavis-static/bouton-blanc.png" alt="Je donne mon avis" title="Je donne mon avis sur cette démarche" />
|
<img src="https://voxusagers.numerique.gouv.fr/static/bouton-bleu.svg" alt="Je donne mon avis" title="Je donne mon avis sur cette démarche" />
|
||||||
</a>
|
</a>
|
||||||
MSG
|
MSG
|
||||||
}
|
}
|
||||||
|
@ -820,6 +712,24 @@ describe Admin::ProceduresController, type: :controller do
|
||||||
it { expect(response.body).to include "MonAvis" }
|
it { expect(response.body).to include "MonAvis" }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when the embed code is valid with the original format' do
|
||||||
|
let(:monavis_embed) {
|
||||||
|
<<-MSG
|
||||||
|
<a href="https://monavis.numerique.gouv.fr/Demarches/123?&view-mode=formulaire-avis&nd_mode=en-ligne-enti%C3%A8rement&nd_source=button&key=cd4a872d475e4045666057f">
|
||||||
|
<img src="https://monavis.numerique.gouv.fr/monavis-static/bouton-blanc.png" alt="Je donne mon avis" title="Je donne mon avis sur cette démarche" />
|
||||||
|
</a>
|
||||||
|
MSG
|
||||||
|
}
|
||||||
|
describe 'the monavis field is updated' do
|
||||||
|
subject { procedure }
|
||||||
|
|
||||||
|
it { expect(subject.monavis_embed).to eq(monavis_embed) }
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(flash[:notice]).to be_present }
|
||||||
|
it { expect(response.body).to include "MonAvis" }
|
||||||
|
end
|
||||||
|
|
||||||
context 'when the embed code is not valid' do
|
context 'when the embed code is not valid' do
|
||||||
let(:monavis_embed) { 'invalid embed code' }
|
let(:monavis_embed) { 'invalid embed code' }
|
||||||
|
|
||||||
|
|
|
@ -125,11 +125,11 @@ describe Instructeurs::ProceduresController, type: :controller do
|
||||||
let(:state) { Dossier.states.fetch(:brouillon) }
|
let(:state) { Dossier.states.fetch(:brouillon) }
|
||||||
before { subject }
|
before { subject }
|
||||||
|
|
||||||
it { expect(assigns(:dossiers_count_per_groupe_instructeur)[procedure.defaut_groupe_instructeur.id]).to eq(nil) }
|
it { expect(assigns(:dossiers_count_per_procedure)[procedure.id]).to eq(nil) }
|
||||||
it { expect(assigns(:dossiers_a_suivre_count_per_groupe_instructeur)[procedure.defaut_groupe_instructeur.id]).to eq(nil) }
|
it { expect(assigns(:dossiers_a_suivre_count_per_procedure)[procedure.id]).to eq(nil) }
|
||||||
it { expect(assigns(:dossiers_archived_count_per_groupe_instructeur)[procedure.defaut_groupe_instructeur.id]).to eq(nil) }
|
it { expect(assigns(:dossiers_archived_count_per_procedure)[procedure.id]).to eq(nil) }
|
||||||
it { expect(assigns(:followed_dossiers_count_per_groupe_instructeur)[procedure.defaut_groupe_instructeur.id]).to eq(nil) }
|
it { expect(assigns(:followed_dossiers_count_per_procedure)[procedure.id]).to eq(nil) }
|
||||||
it { expect(assigns(:dossiers_termines_count_per_groupe_instructeur)[procedure.defaut_groupe_instructeur.id]).to eq(nil) }
|
it { expect(assigns(:dossiers_termines_count_per_procedure)[procedure.id]).to eq(nil) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with not draft state on multiple procedures" do
|
context "with not draft state on multiple procedures" do
|
||||||
|
@ -149,17 +149,67 @@ describe Instructeurs::ProceduresController, type: :controller do
|
||||||
subject
|
subject
|
||||||
end
|
end
|
||||||
|
|
||||||
it { expect(assigns(:dossiers_count_per_groupe_instructeur)[procedure.defaut_groupe_instructeur.id]).to eq(3) }
|
it { expect(assigns(:dossiers_count_per_procedure)[procedure.id]).to eq(3) }
|
||||||
it { expect(assigns(:dossiers_a_suivre_count_per_groupe_instructeur)[procedure.defaut_groupe_instructeur.id]).to eq(3) }
|
it { expect(assigns(:dossiers_a_suivre_count_per_procedure)[procedure.id]).to eq(3) }
|
||||||
it { expect(assigns(:followed_dossiers_count_per_groupe_instructeur)[procedure.defaut_groupe_instructeur.id]).to eq(nil) }
|
it { expect(assigns(:followed_dossiers_count_per_procedure)[procedure.id]).to eq(nil) }
|
||||||
it { expect(assigns(:dossiers_archived_count_per_groupe_instructeur)[procedure.defaut_groupe_instructeur.id]).to eq(1) }
|
it { expect(assigns(:dossiers_archived_count_per_procedure)[procedure.id]).to eq(1) }
|
||||||
it { expect(assigns(:dossiers_termines_count_per_groupe_instructeur)[procedure.defaut_groupe_instructeur.id]).to eq(nil) }
|
it { expect(assigns(:dossiers_termines_count_per_procedure)[procedure.id]).to eq(nil) }
|
||||||
|
|
||||||
it { expect(assigns(:dossiers_count_per_groupe_instructeur)[procedure2.defaut_groupe_instructeur.id]).to eq(3) }
|
it { expect(assigns(:dossiers_count_per_procedure)[procedure2.id]).to eq(3) }
|
||||||
it { expect(assigns(:dossiers_a_suivre_count_per_groupe_instructeur)[procedure2.defaut_groupe_instructeur.id]).to eq(nil) }
|
it { expect(assigns(:dossiers_a_suivre_count_per_procedure)[procedure2.id]).to eq(nil) }
|
||||||
it { expect(assigns(:followed_dossiers_count_per_groupe_instructeur)[procedure2.defaut_groupe_instructeur.id]).to eq(1) }
|
it { expect(assigns(:followed_dossiers_count_per_procedure)[procedure2.id]).to eq(1) }
|
||||||
it { expect(assigns(:dossiers_archived_count_per_groupe_instructeur)[procedure2.defaut_groupe_instructeur.id]).to eq(nil) }
|
it { expect(assigns(:dossiers_archived_count_per_procedure)[procedure2.id]).to eq(nil) }
|
||||||
it { expect(assigns(:dossiers_termines_count_per_groupe_instructeur)[procedure2.defaut_groupe_instructeur.id]).to eq(1) }
|
it { expect(assigns(:dossiers_termines_count_per_procedure)[procedure2.id]).to eq(1) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with a routed procedure" do
|
||||||
|
let!(:procedure) { create(:procedure, :published) }
|
||||||
|
let!(:gi_p1_1) { procedure.defaut_groupe_instructeur }
|
||||||
|
let!(:gi_p1_2) { GroupeInstructeur.create(label: '2', procedure: procedure) }
|
||||||
|
|
||||||
|
context 'with multiple dossiers en construction on each group' do
|
||||||
|
before do
|
||||||
|
alternate_gis = 0.upto(20).map { |i| i.even? ? gi_p1_1 : gi_p1_2 }
|
||||||
|
|
||||||
|
alternate_gis.take(4).each { |gi| create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_construction), groupe_instructeur: gi) }
|
||||||
|
|
||||||
|
alternate_gis.take(6).each do |gi|
|
||||||
|
instructeur.followed_dossiers << create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_instruction), groupe_instructeur: gi)
|
||||||
|
end
|
||||||
|
|
||||||
|
alternate_gis.take(10).each { |gi| create(:dossier, procedure: procedure, state: Dossier.states.fetch(:sans_suite), groupe_instructeur: gi) }
|
||||||
|
alternate_gis.take(14).each { |gi| create(:dossier, procedure: procedure, state: Dossier.states.fetch(:sans_suite), archived: true, groupe_instructeur: gi) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when an instructeur belongs to the 2 gi' do
|
||||||
|
before do
|
||||||
|
instructeur.groupe_instructeurs << gi_p1_1 << gi_p1_2
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(assigns(:dossiers_a_suivre_count_per_procedure)[procedure.id]).to eq(4) }
|
||||||
|
it { expect(assigns(:followed_dossiers_count_per_procedure)[procedure.id]).to eq(6) }
|
||||||
|
it { expect(assigns(:dossiers_termines_count_per_procedure)[procedure.id]).to eq(10) }
|
||||||
|
it { expect(assigns(:dossiers_count_per_procedure)[procedure.id]).to eq(4 + 6 + 10) }
|
||||||
|
it { expect(assigns(:dossiers_archived_count_per_procedure)[procedure.id]).to eq(14) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when an instructeur only belongs to one of them gi' do
|
||||||
|
before do
|
||||||
|
instructeur.groupe_instructeurs << gi_p1_1
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(assigns(:dossiers_a_suivre_count_per_procedure)[procedure.id]).to eq(2) }
|
||||||
|
# An instructeur cannot follow a dossier which belongs to another groupe
|
||||||
|
it { expect(assigns(:followed_dossiers_count_per_procedure)[procedure.id]).to eq(3) }
|
||||||
|
it { expect(assigns(:dossiers_termines_count_per_procedure)[procedure.id]).to eq(5) }
|
||||||
|
it { expect(assigns(:dossiers_count_per_procedure)[procedure.id]).to eq(2 + 3 + 5) }
|
||||||
|
it { expect(assigns(:dossiers_archived_count_per_procedure)[procedure.id]).to eq(7) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,7 +14,10 @@ FactoryBot.define do
|
||||||
else
|
else
|
||||||
procedure = create(:procedure, :published, :with_type_de_champ, :with_type_de_champ_private)
|
procedure = create(:procedure, :published, :with_type_de_champ, :with_type_de_champ_private)
|
||||||
end
|
end
|
||||||
dossier.groupe_instructeur = procedure.defaut_groupe_instructeur
|
|
||||||
|
if dossier.groupe_instructeur.nil?
|
||||||
|
dossier.groupe_instructeur = procedure.defaut_groupe_instructeur
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
trait :with_entreprise do
|
trait :with_entreprise do
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -2,17 +2,27 @@ require 'spec_helper'
|
||||||
|
|
||||||
feature 'procedure locked' do
|
feature 'procedure locked' do
|
||||||
let(:administrateur) { create(:administrateur) }
|
let(:administrateur) { create(:administrateur) }
|
||||||
let (:published_at) { nil }
|
|
||||||
let(:procedure) { create(:procedure, administrateur: administrateur, published_at: published_at) }
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
login_as administrateur, scope: :administrateur
|
login_as administrateur.user, scope: :user
|
||||||
visit admin_procedure_path(procedure)
|
visit admin_procedure_path(procedure)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when procedure is not published' do
|
context 'when procedure is not published' do
|
||||||
|
let(:procedure) { create(:procedure, administrateur: administrateur) }
|
||||||
|
|
||||||
scenario 'info label is not present' do
|
scenario 'info label is not present' do
|
||||||
expect(page).not_to have_content('Cette démarche a été publiée, certains éléments ne peuvent plus être modifiés')
|
expect(page).to have_content('Test et publication')
|
||||||
|
expect(page).not_to have_content('Cette démarche est publiée, certains éléments ne peuvent plus être modifiés.')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when procedure is published' do
|
||||||
|
let(:procedure) { create(:procedure, :published, administrateur: administrateur) }
|
||||||
|
|
||||||
|
scenario 'info label is present' do
|
||||||
|
expect(page).to have_content('Publication')
|
||||||
|
expect(page).to have_content('Cette démarche est publiée, certains éléments ne peuvent plus être modifiés.')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -159,9 +159,11 @@ describe AttestationTemplate, type: :model do
|
||||||
.update(value: 'libelle2')
|
.update(value: 'libelle2')
|
||||||
end
|
end
|
||||||
|
|
||||||
it { expect(view_args[:title]).to eq('title libelle1') }
|
it do
|
||||||
it { expect(view_args[:body]).to eq('body libelle2') }
|
expect(view_args[:attestation][:title]).to eq('title libelle1')
|
||||||
it { expect(attestation.title).to eq('title libelle1') }
|
expect(view_args[:attestation][:body]).to eq('body libelle2')
|
||||||
|
expect(attestation.title).to eq('title libelle1')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -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 }
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -21,7 +21,7 @@ describe 'users/dossiers/brouillon.html.haml', type: :view do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'affiche les boutons de validation' do
|
it 'affiche les boutons de validation' do
|
||||||
expect(rendered).to have_selector('.send-wrapper')
|
expect(rendered).to have_selector('.send-dossier-actions-bar')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'prépare le footer' do
|
it 'prépare le footer' do
|
||||||
|
|
Loading…
Reference in a new issue