diff --git a/app/assets/stylesheets/new_design/messagerie.scss b/app/assets/stylesheets/new_design/messagerie.scss index c8fe54379..034cbcea3 100644 --- a/app/assets/stylesheets/new_design/messagerie.scss +++ b/app/assets/stylesheets/new_design/messagerie.scss @@ -23,4 +23,8 @@ .message-textarea { margin-bottom: $default-spacer; } + + .form input[type="file"] { + margin-bottom: 0; + } } 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/helpers/application_helper.rb b/app/helpers/application_helper.rb index 76d73157f..2889bb9c5 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -44,6 +44,18 @@ module ApplicationHelper # rubocop:enable Rails/OutputSafety end + def disable_element(selector) + # rubocop:disable Rails/OutputSafety + raw("document.querySelector('#{selector}').disabled = true;") + # rubocop:enable Rails/OutputSafety + end + + def enable_element(selector) + # rubocop:disable Rails/OutputSafety + raw("document.querySelector('#{selector}').disabled = false;") + # rubocop:enable Rails/OutputSafety + end + def current_email current_user&.email || current_gestionnaire&.email || 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/lib/tasks/2018_09_12_ftap.rake b/lib/tasks/2018_09_12_ftap.rake new file mode 100644 index 000000000..2bb6e3f07 --- /dev/null +++ b/lib/tasks/2018_09_12_ftap.rake @@ -0,0 +1,89 @@ +namespace :'2018_09_12_ftap' do + task :run do + procedure = Procedure.find(5812) + dossiers = procedure.dossiers.all + + labels_for_text_tdc = [ + 'Bref descriptif du projet', + 'Montant et nature des économies générées', + 'Contacts en cours avec les porteurs de projets' + ] + + labels_for_text_tdc.each_with_index { |l, i| add_first_text(procedure, dossiers, l, i) } + + ditp_private_tdc_order_place = procedure.types_de_champ_private.find_by(libelle: 'Avis DITP').order_place + + labels_for_mark_before_DITP = [ + 'Ambition usagers/agents', + 'Caractère stratégique et novateur', + 'Gouvernance' + ] + + labels_for_mark_before_DITP.each_with_index { |l, i| add_mark(procedure, dossiers, l, ditp_private_tdc_order_place + i) } + + change_to_select_with_number(procedure, 'Avis DINSIC') + change_to_select_with_number(procedure, 'Avis DB') + + change_option_for_avis_tdc(procedure) + end + + def change_option_for_avis_tdc(procedure) + drop_down_list = procedure.types_de_champ_private.find_by(libelle: 'Avis', type_champ: 'drop_down_list').drop_down_list + drop_down_list.update(value: "Favorable\r\nDéfavorable\r\nFavorable avec réserves\r\nFavorable avec réserves - stratégique") + end + + def add_first_text(procedure, dossiers, libelle, order_place) + if procedure.types_de_champ_private.find_by(libelle: libelle).nil? + + move_down_tdc_below(procedure, order_place) + + tdc = TypesDeChamp::TextareaTypeDeChamp.create!( + libelle: libelle, + type_champ: 'textarea', + procedure: procedure, + order_place: order_place, + private: true + ) + + procedure.types_de_champ_private << tdc + + dossiers.each do |dossier| + dossier.champs << Champs::TextareaChamp.create!(type_de_champ: tdc, private: true) + end + end + end + + def add_mark(procedure, dossiers, libelle, order_place) + if procedure.types_de_champ_private.find_by(libelle: libelle).nil? + move_down_tdc_below(procedure, order_place) + + tdc = TypesDeChamp::DropDownListTypeDeChamp.create!( + libelle: libelle, + type_champ: 'drop_down_list', + procedure: procedure, + order_place: order_place, + private: true + ) + + DropDownList.create!(value: "0\r\n1\r\n2\r\n3\r\n4", type_de_champ: tdc) + + procedure.types_de_champ_private << tdc + + dossiers.each do |dossier| + dossier.champs << Champs::DropDownListChamp.create!(type_de_champ: tdc, private: true) + end + end + end + + def move_down_tdc_below(procedure, order_place) + tdcs_to_move_down = procedure.types_de_champ_private.where('order_place >= ?', order_place) + tdcs_to_move_down.each do |tdc| + tdc.update(order_place: (tdc.order_place + 1)) + end + end + + def change_to_select_with_number(procedure, libelle) + drop_down_list = procedure.types_de_champ_private.find_by(libelle: libelle, type_champ: 'drop_down_list').drop_down_list + drop_down_list.update(value: "0\r\n1\r\n2\r\n3\r\n4") + end +end 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