Merge branches 'develop' and 'develop' of github.com:sgmap/tps into develop
This commit is contained in:
commit
86e26e520c
17 changed files with 222 additions and 6 deletions
2
Gemfile
2
Gemfile
|
@ -22,6 +22,8 @@ gem 'jbuilder', '~> 2.0'
|
||||||
# bundle exec rake doc:rails generates the API under doc/api.
|
# bundle exec rake doc:rails generates the API under doc/api.
|
||||||
gem 'sdoc', '~> 0.4.0', group: :doc
|
gem 'sdoc', '~> 0.4.0', group: :doc
|
||||||
|
|
||||||
|
# Enable deep clone of active record models
|
||||||
|
gem 'deep_cloneable', '~> 2.2.1'
|
||||||
|
|
||||||
# Use ActiveModel has_secure_password
|
# Use ActiveModel has_secure_password
|
||||||
# gem 'bcrypt', '~> 3.1.7'
|
# gem 'bcrypt', '~> 3.1.7'
|
||||||
|
|
|
@ -119,6 +119,8 @@ GEM
|
||||||
sprockets (>= 2.0.0)
|
sprockets (>= 2.0.0)
|
||||||
database_cleaner (1.4.1)
|
database_cleaner (1.4.1)
|
||||||
debug_inspector (0.0.2)
|
debug_inspector (0.0.2)
|
||||||
|
deep_cloneable (2.2.1)
|
||||||
|
activerecord (>= 3.1.0, < 5.2.0)
|
||||||
devise (3.4.1)
|
devise (3.4.1)
|
||||||
bcrypt (~> 3.0)
|
bcrypt (~> 3.0)
|
||||||
orm_adapter (~> 0.1)
|
orm_adapter (~> 0.1)
|
||||||
|
@ -634,6 +636,7 @@ DEPENDENCIES
|
||||||
coffee-rails (~> 4.1.0)
|
coffee-rails (~> 4.1.0)
|
||||||
css_splitter
|
css_splitter
|
||||||
database_cleaner
|
database_cleaner
|
||||||
|
deep_cloneable (~> 2.2.1)
|
||||||
devise
|
devise
|
||||||
draper
|
draper
|
||||||
factory_girl
|
factory_girl
|
||||||
|
@ -690,4 +693,4 @@ DEPENDENCIES
|
||||||
will_paginate-bootstrap
|
will_paginate-bootstrap
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.11.2
|
1.12.5
|
||||||
|
|
|
@ -83,6 +83,23 @@ class Admin::ProceduresController < AdminController
|
||||||
change_status({archived: params[:archive]})
|
change_status({archived: params[:archive]})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def clone
|
||||||
|
@procedure = current_administrateur.procedures.find(params[:procedure_id])
|
||||||
|
|
||||||
|
new_procedure = @procedure.clone
|
||||||
|
if new_procedure
|
||||||
|
flash.notice = 'Procédure clonée'
|
||||||
|
redirect_to edit_admin_procedure_path(id: new_procedure.id)
|
||||||
|
else
|
||||||
|
flash.now.alert = @procedure.errors.full_messages.join('<br />').html_safe
|
||||||
|
render 'index'
|
||||||
|
end
|
||||||
|
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
flash.alert = 'Procédure inéxistante'
|
||||||
|
redirect_to admin_procedures_path
|
||||||
|
end
|
||||||
|
|
||||||
def active_class
|
def active_class
|
||||||
@active_class = 'active'
|
@active_class = 'active'
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,10 +22,11 @@ class CommentairesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
@commentaire.body = params['texte_commentaire']
|
@commentaire.body = params['texte_commentaire']
|
||||||
@commentaire.save unless flash.alert
|
saved = false
|
||||||
|
saved = @commentaire.save unless flash.alert
|
||||||
|
|
||||||
if is_gestionnaire?
|
if is_gestionnaire?
|
||||||
NotificationMailer.new_answer(@commentaire.dossier).deliver_now!
|
NotificationMailer.new_answer(@commentaire.dossier).deliver_now! if saved
|
||||||
redirect_to url_for(controller: 'backoffice/dossiers', action: :show, id: params['dossier_id'])
|
redirect_to url_for(controller: 'backoffice/dossiers', action: :show, id: params['dossier_id'])
|
||||||
elsif current_user.email != @commentaire.dossier.user.email
|
elsif current_user.email != @commentaire.dossier.user.email
|
||||||
invite = Invite.where(dossier: @commentaire.dossier, user: current_user).first
|
invite = Invite.where(dossier: @commentaire.dossier, user: current_user).first
|
||||||
|
|
32
app/controllers/gestionnaires/passwords_controller.rb
Normal file
32
app/controllers/gestionnaires/passwords_controller.rb
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
class Gestionnaires::PasswordsController < Devise::PasswordsController
|
||||||
|
# GET /resource/password/new
|
||||||
|
# def new
|
||||||
|
# super
|
||||||
|
# end
|
||||||
|
|
||||||
|
# POST /resource/password
|
||||||
|
# def create
|
||||||
|
# super
|
||||||
|
# end
|
||||||
|
|
||||||
|
# GET /resource/password/edit?reset_password_token=abcdef
|
||||||
|
# def edit
|
||||||
|
# super
|
||||||
|
# end
|
||||||
|
|
||||||
|
# PUT /resource/password
|
||||||
|
# def update
|
||||||
|
# super
|
||||||
|
# end
|
||||||
|
|
||||||
|
# protected
|
||||||
|
|
||||||
|
# def after_resetting_password_path_for(resource)
|
||||||
|
# super(resource)
|
||||||
|
# end
|
||||||
|
|
||||||
|
# The path used after sending reset password instructions
|
||||||
|
# def after_sending_reset_password_instructions_path_for(resource_name)
|
||||||
|
# super(resource_name)
|
||||||
|
# end
|
||||||
|
end
|
|
@ -58,4 +58,11 @@ class Procedure < ActiveRecord::Base
|
||||||
published?
|
published?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def clone
|
||||||
|
procedure = self.deep_clone(include: [ :types_de_piece_justificative, :types_de_champ, :module_api_carto ])
|
||||||
|
procedure.archived = false
|
||||||
|
procedure.published = false
|
||||||
|
return procedure if procedure.save
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
%thead
|
%thead
|
||||||
%th#ID= smart_listing.sortable 'ID', 'id'
|
%th#ID= smart_listing.sortable 'ID', 'id'
|
||||||
%th#libelle= smart_listing.sortable 'Libellé', 'libelle'
|
%th#libelle= smart_listing.sortable 'Libellé', 'libelle'
|
||||||
|
%th#lien Actions
|
||||||
|
|
||||||
- @procedures.each do |procedure|
|
- @procedures.each do |procedure|
|
||||||
- procedure = procedure.decorate
|
- procedure = procedure.decorate
|
||||||
|
@ -10,6 +11,7 @@
|
||||||
%td.col-md-1.col-lg-1= procedure.id
|
%td.col-md-1.col-lg-1= procedure.id
|
||||||
%td.col-md-6.col-lg-6
|
%td.col-md-6.col-lg-6
|
||||||
= link_to(procedure.libelle, "/admin/procedures/#{procedure.id}")
|
= link_to(procedure.libelle, "/admin/procedures/#{procedure.id}")
|
||||||
|
%td= link_to('cloner', admin_procedure_clone_path(procedure.id), 'data-method' => :put, class: 'btn-xs btn-primary')
|
||||||
|
|
||||||
= smart_listing.paginate
|
= smart_listing.paginate
|
||||||
= smart_listing.pagination_per_page_links
|
= smart_listing.pagination_per_page_links
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
%th#ID= smart_listing.sortable 'ID', 'id'
|
%th#ID= smart_listing.sortable 'ID', 'id'
|
||||||
%th#libelle= smart_listing.sortable 'Libellé', 'libelle'
|
%th#libelle= smart_listing.sortable 'Libellé', 'libelle'
|
||||||
%th#lien Lien
|
%th#lien Lien
|
||||||
|
%th#lien Actions
|
||||||
|
|
||||||
- @procedures.each do |procedure|
|
- @procedures.each do |procedure|
|
||||||
- procedure = procedure.decorate
|
- procedure = procedure.decorate
|
||||||
|
@ -12,6 +13,7 @@
|
||||||
%td.col-md-6.col-lg-6
|
%td.col-md-6.col-lg-6
|
||||||
= link_to(procedure.libelle, "/admin/procedures/#{procedure.id}")
|
= link_to(procedure.libelle, "/admin/procedures/#{procedure.id}")
|
||||||
%td= link_to procedure.lien, procedure.lien
|
%td= link_to procedure.lien, procedure.lien
|
||||||
|
%td= link_to('cloner', admin_procedure_clone_path(procedure.id), 'data-method' => :put, class: 'btn-xs btn-primary')
|
||||||
|
|
||||||
= smart_listing.paginate
|
= smart_listing.paginate
|
||||||
= smart_listing.pagination_per_page_links
|
= smart_listing.pagination_per_page_links
|
||||||
|
|
31
app/views/gestionnaires/passwords/edit.html.haml
Normal file
31
app/views/gestionnaires/passwords/edit.html.haml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
= devise_error_messages!
|
||||||
|
|
||||||
|
#form_login
|
||||||
|
= image_tag('logo-tps.png')
|
||||||
|
%br
|
||||||
|
%h2#gestionnaire_login Changement de mot de passe
|
||||||
|
|
||||||
|
%br
|
||||||
|
%br
|
||||||
|
#new_user
|
||||||
|
= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f|
|
||||||
|
= f.hidden_field :reset_password_token
|
||||||
|
%h4
|
||||||
|
= f.label 'Nouveau mot de passe'
|
||||||
|
|
||||||
|
.input-group
|
||||||
|
.input-group-addon
|
||||||
|
%span.glyphicon.glyphicon-asterisk
|
||||||
|
= f.password_field :password, autofocus: true, autocomplete: "off", class: 'form-control'
|
||||||
|
%br
|
||||||
|
%h4
|
||||||
|
= f.label 'Retaper le mot de passe'
|
||||||
|
.input-group
|
||||||
|
.input-group-addon
|
||||||
|
%span.glyphicon.glyphicon-asterisk
|
||||||
|
= f.password_field :password_confirmation, autocomplete: "off", class: 'form-control'
|
||||||
|
%br
|
||||||
|
%br
|
||||||
|
.actions
|
||||||
|
= f.submit "Changer", class:'btn btn-primary'
|
||||||
|
%br
|
22
app/views/gestionnaires/passwords/new.html.haml
Normal file
22
app/views/gestionnaires/passwords/new.html.haml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
= devise_error_messages!
|
||||||
|
|
||||||
|
#form_login
|
||||||
|
= image_tag('logo-tps.png')
|
||||||
|
%br
|
||||||
|
%h2#gestionnaire_login Mot de passe oublié
|
||||||
|
|
||||||
|
%br
|
||||||
|
%br
|
||||||
|
#new_user
|
||||||
|
= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f|
|
||||||
|
%h4
|
||||||
|
= f.label :email
|
||||||
|
.input-group
|
||||||
|
.input-group-addon
|
||||||
|
%span.glyphicon.glyphicon-user
|
||||||
|
= f.email_field :email, class: 'form-control', placeholder: 'Email'
|
||||||
|
%br
|
||||||
|
%br
|
||||||
|
.actions
|
||||||
|
= f.submit "Renvoyer", class:'btn btn-primary'
|
||||||
|
%br
|
|
@ -25,4 +25,5 @@
|
||||||
%br
|
%br
|
||||||
.actions
|
.actions
|
||||||
= f.submit "Se connecter", class:'btn btn-primary'
|
= f.submit "Se connecter", class:'btn btn-primary'
|
||||||
%br
|
%br
|
||||||
|
= render "gestionnaires/shared/links"
|
||||||
|
|
2
app/views/gestionnaires/shared/_links.html.erb
Normal file
2
app/views/gestionnaires/shared/_links.html.erb
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<%= link_to "Mot de passe oublié ?", new_password_path(resource_name) %><br />
|
||||||
|
|
|
@ -9,8 +9,9 @@ Rails.application.routes.draw do
|
||||||
}, skip: [:password, :registrations]
|
}, skip: [:password, :registrations]
|
||||||
|
|
||||||
devise_for :gestionnaires, controllers: {
|
devise_for :gestionnaires, controllers: {
|
||||||
sessions: 'gestionnaires/sessions'
|
sessions: 'gestionnaires/sessions',
|
||||||
}, skip: [:password, :registrations]
|
passwords: 'gestionnaires/passwords'
|
||||||
|
}, skip: [:registrations]
|
||||||
|
|
||||||
devise_for :users, controllers: {
|
devise_for :users, controllers: {
|
||||||
sessions: 'users/sessions',
|
sessions: 'users/sessions',
|
||||||
|
@ -25,6 +26,8 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
devise_scope :gestionnaire do
|
devise_scope :gestionnaire do
|
||||||
get '/gestionnaires/sign_in/demo' => 'gestionnaires/sessions#demo'
|
get '/gestionnaires/sign_in/demo' => 'gestionnaires/sessions#demo'
|
||||||
|
get '/gestionnaires/edit' => 'gestionnaires/registrations#edit', :as => 'edit_gestionnaires_registration'
|
||||||
|
put '/gestionnaires' => 'gestionnaires/registrations#update', :as => 'gestionnaires_registration'
|
||||||
end
|
end
|
||||||
|
|
||||||
devise_scope :administrateur do
|
devise_scope :administrateur do
|
||||||
|
@ -100,6 +103,7 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
put 'archive' => 'procedures#archive', as: :archive
|
put 'archive' => 'procedures#archive', as: :archive
|
||||||
put 'publish' => 'procedures#publish', as: :publish
|
put 'publish' => 'procedures#publish', as: :publish
|
||||||
|
put 'clone' => 'procedures#clone', as: :clone
|
||||||
|
|
||||||
resource :accompagnateurs, only: [:show, :update]
|
resource :accompagnateurs, only: [:show, :update]
|
||||||
|
|
||||||
|
|
|
@ -265,4 +265,35 @@ describe Admin::ProceduresController, type: :controller do
|
||||||
it { expect(flash[:alert]).to have_content 'Procédure inéxistante' }
|
it { expect(flash[:alert]).to have_content 'Procédure inéxistante' }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'PUT #clone' do
|
||||||
|
let!(:procedure) { create(:procedure, administrateur: admin) }
|
||||||
|
subject { put :clone, procedure_id: procedure.id }
|
||||||
|
|
||||||
|
it { expect{ subject }.to change(Procedure, :count).by(1) }
|
||||||
|
|
||||||
|
context 'when admin is the owner of the procedure' do
|
||||||
|
before do
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates a new procedure and redirect to it' do
|
||||||
|
expect(response).to redirect_to edit_admin_procedure_path(id: Procedure.last.id)
|
||||||
|
expect(flash[:notice]).to have_content 'Procédure clonée'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when admin is not the owner of the procedure' do
|
||||||
|
let(:admin_2) { create(:administrateur) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
sign_out admin
|
||||||
|
sign_in admin_2
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(response).to redirect_to :admin_procedures }
|
||||||
|
it { expect(flash[:alert]).to have_content 'Procédure inéxistante' }
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -91,5 +91,17 @@ describe Backoffice::CommentairesController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'comment cannot be saved' do
|
||||||
|
before do
|
||||||
|
allow_any_instance_of(Commentaire).to receive(:save).and_return(false)
|
||||||
|
end
|
||||||
|
it 'Notification email is not sent' do
|
||||||
|
expect(NotificationMailer).not_to receive(:new_answer)
|
||||||
|
expect(NotificationMailer).not_to receive(:deliver_now!)
|
||||||
|
|
||||||
|
post :create, dossier_id: dossier_id, texte_commentaire: texte_commentaire
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -122,4 +122,44 @@ describe Procedure do
|
||||||
it { expect { subject }.to raise_error(ActiveRecord::RecordNotFound) }
|
it { expect { subject }.to raise_error(ActiveRecord::RecordNotFound) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'clone' do
|
||||||
|
let(:archived) { false }
|
||||||
|
let(:published) { false }
|
||||||
|
let(:procedure) { create(:procedure, archived: archived, published: published) }
|
||||||
|
let!(:type_de_champ_0) { create(:type_de_champ, procedure: procedure, order_place: 0) }
|
||||||
|
let!(:type_de_champ_1) { create(:type_de_champ, procedure: procedure, order_place: 1) }
|
||||||
|
let!(:piece_justificative_0) { create(:type_de_piece_justificative, procedure: procedure, order_place: 0) }
|
||||||
|
let!(:piece_justificative_1) { create(:type_de_piece_justificative, procedure: procedure, order_place: 1) }
|
||||||
|
subject { procedure.clone }
|
||||||
|
|
||||||
|
it 'should duplicate specific objects with different id' do
|
||||||
|
expect(subject.id).not_to eq(procedure.id)
|
||||||
|
expect(subject).to have_same_attributes_as(procedure)
|
||||||
|
expect(subject.module_api_carto).to have_same_attributes_as(procedure.module_api_carto)
|
||||||
|
|
||||||
|
subject.types_de_champ.zip(procedure.types_de_champ).each do |stc, ptc|
|
||||||
|
expect(stc).to have_same_attributes_as(ptc)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject.types_de_piece_justificative.zip(procedure.types_de_piece_justificative).each do |stc, ptc|
|
||||||
|
expect(stc).to have_same_attributes_as(ptc)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should not duplicate specific related objects' do
|
||||||
|
expect(subject.dossiers).to eq([])
|
||||||
|
expect(subject.gestionnaires).to eq([])
|
||||||
|
expect(subject.assign_to).to eq([])
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'procedure status is reset' do
|
||||||
|
let(:archived) { true }
|
||||||
|
let(:published) { true }
|
||||||
|
it 'sets published and archived to false' do
|
||||||
|
expect(subject.archived).to be_falsey
|
||||||
|
expect(subject.published).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -113,4 +113,11 @@ RSpec.configure do |config|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RSpec::Matchers.define :have_same_attributes_as do |expected|
|
||||||
|
match do |actual|
|
||||||
|
ignored = [:id, :procedure_id, :updated_at, :created_at]
|
||||||
|
actual.attributes.with_indifferent_access.except(*ignored) == expected.attributes.with_indifferent_access.except(*ignored)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue