diff --git a/app/controllers/admin/procedures_controller.rb b/app/controllers/admin/procedures_controller.rb index 6532cc3a3..9016db63a 100644 --- a/app/controllers/admin/procedures_controller.rb +++ b/app/controllers/admin/procedures_controller.rb @@ -205,6 +205,20 @@ class Admin::ProceduresController < AdminController 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) + @available = procedure.path_available?(path) + @mine = procedure.path_is_mine?(path) + else + @available = !ProcedurePath.exists?(path: path) + @mine = ProcedurePath.mine?(current_administrateur, path) + end + end + def delete_deliberation procedure = Procedure.find(params[:id]) diff --git a/app/models/procedure.rb b/app/models/procedure.rb index 79f432ee6..1a4b33206 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -120,6 +120,14 @@ class Procedure < ApplicationRecord publiee_ou_archivee? end + def path_available?(path) + !ProcedurePath.where.not(procedure: self).exists?(path: path) + end + + def path_is_mine?(path) + ProcedurePath.where.not(procedure: self).mine?(administrateur, path) + end + # This method is needed for transition. Eventually this will be the same as brouillon?. def brouillon_avec_lien? Flipflop.publish_draft? && brouillon? && procedure_path.present? diff --git a/app/models/procedure_path.rb b/app/models/procedure_path.rb index 7bab10680..c6b6fb754 100644 --- a/app/models/procedure_path.rb +++ b/app/models/procedure_path.rb @@ -11,6 +11,11 @@ class ProcedurePath < ApplicationRecord .find_or_initialize_by(path: path).validate end + def self.mine?(administrateur, path) + procedure_path = find_by(path: path) + procedure_path && administrateur.owns?(procedure_path) + end + def self.find_with_path(path) joins(:procedure) .where.not(procedures: { aasm_state: :archivee }) diff --git a/app/views/admin/procedures/_unavailable.html.haml b/app/views/admin/procedures/_unavailable.html.haml new file mode 100644 index 000000000..dd3868512 --- /dev/null +++ b/app/views/admin/procedures/_unavailable.html.haml @@ -0,0 +1,8 @@ +- if mine + Ce lien est déjà utilisé par une de vos procédure. + %br + Si vous voulez l’utiliser, l’ancienne procédure sera archivée (plus accessible du public). +- else + Ce lien est déjà utilisé par une procédure. + %br + Vous ne pouvez pas l’utiliser car il appartient à un autre administrateur. diff --git a/app/views/admin/procedures/check_availability.js.erb b/app/views/admin/procedures/check_availability.js.erb new file mode 100644 index 000000000..91c9a76ba --- /dev/null +++ b/app/views/admin/procedures/check_availability.js.erb @@ -0,0 +1,11 @@ +<% if @available %> + <%= remove_element('.unavailable-path-message', inner: true) %> + <%= enable_element('button[type=submit]') %> +<% else %> + <%= render_to_element('.unavailable-path-message', partial: 'unavailable', locals: { mine: @mine }) %> + <% if @mine %> + <%= enable_element('button[type=submit]') %> + <% else %> + <%= disable_element('button[type=submit]') %> + <% end %> +<% end %> diff --git a/config/routes.rb b/config/routes.rb index 19adc8ed6..f440e3f6f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -179,6 +179,7 @@ Rails.application.routes.draw do get 'procedures/archived' => 'procedures#archived' get 'procedures/draft' => 'procedures#draft' get 'procedures/path_list' => 'procedures#path_list' + get 'procedures/available' => 'procedures#check_availability' get 'profile' => 'profile#show', as: :profile post 'renew_api_token' => 'profile#renew_api_token', as: :renew_api_token diff --git a/spec/controllers/admin/procedures_controller_spec.rb b/spec/controllers/admin/procedures_controller_spec.rb index feb45dea2..caa042d7d 100644 --- a/spec/controllers/admin/procedures_controller_spec.rb +++ b/spec/controllers/admin/procedures_controller_spec.rb @@ -721,4 +721,52 @@ describe Admin::ProceduresController, type: :controller do it { expect(procedure.deliberation.attached?).to eq(false) } it { expect(response).to redirect_to(edit_admin_procedure_path(procedure)) } 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' do + let(:procedure_owned) { create(:procedure, :with_path, administrateur: admin) } + let(:path) { procedure_owned.path } + + it { + expect(response.body).to include('Ce lien est déjà utilisé par une de vos procédure.') + expect(response.body).to include('Si vous voulez l’utiliser, l’ancienne procédure 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 procédure.') + expect(response.body).to include('Vous ne pouvez pas l’utiliser car il appartient à un autre administrateur.') + } + end + end end