From 7cb2f91fea530eb576c3f61ef4bab6eb14c24cd0 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 13 Apr 2021 17:38:58 +0100 Subject: [PATCH 1/9] Add revisions feature flag --- config/initializers/flipper.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/config/initializers/flipper.rb b/config/initializers/flipper.rb index cec532155..17c876839 100644 --- a/config/initializers/flipper.rb +++ b/config/initializers/flipper.rb @@ -32,6 +32,7 @@ features = [ :hide_instructeur_email, :instructeur_bypass_email_login_token, :make_experts_notifiable, + :procedure_revisions, :procedure_routage_api ] From 15e90132642555f0a6ee3da6a711ec220b9e8300 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Fri, 18 Jun 2021 11:13:18 +0200 Subject: [PATCH 2/9] Set published_at on revision when publishing a procedure --- app/models/procedure.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/models/procedure.rb b/app/models/procedure.rb index 07ca5e6ff..c2313239a 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -689,6 +689,11 @@ class Procedure < ApplicationRecord end end + def publish_revision! + update!(draft_revision: create_new_revision, published_revision: draft_revision) + published_revision.touch(:published_at) + end + private def before_publish From 0d25f523099facff9473ae61fb44f0718ca7bf9c Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 20 Jan 2021 13:21:23 +0100 Subject: [PATCH 3/9] Add changed? and compare on ProcedureRevision --- app/models/procedure.rb | 8 +++ app/models/procedure_revision.rb | 117 +++++++++++++++++++++++++++++++ app/models/type_de_champ.rb | 6 ++ 3 files changed, 131 insertions(+) diff --git a/app/models/procedure.rb b/app/models/procedure.rb index c2313239a..4a3b7fa82 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -333,6 +333,14 @@ class Procedure < ApplicationRecord publiee? || close? || depubliee? end + def draft_changed? + publiee? && published_revision.changed?(draft_revision) + end + + def revision_changes + published_revision.compare(draft_revision) + end + def accepts_new_dossiers? publiee? || brouillon? end diff --git a/app/models/procedure_revision.rb b/app/models/procedure_revision.rb index 42c646ee2..ee616fa87 100644 --- a/app/models/procedure_revision.rb +++ b/app/models/procedure_revision.rb @@ -101,8 +101,125 @@ class ProcedureRevision < ApplicationRecord !draft? end + def changed?(revision) + types_de_champ != revision.types_de_champ || types_de_champ_private != revision.types_de_champ_private + end + + def compare(revision) + changes = [] + changes += compare_types_de_champ(types_de_champ, revision.types_de_champ) + changes += compare_types_de_champ(types_de_champ_private, revision.types_de_champ_private) + changes + end + private + def compare_types_de_champ(from_tdc, to_tdc) + if from_tdc == to_tdc + [] + else + from_h = from_tdc.index_by(&:stable_id) + to_h = to_tdc.index_by(&:stable_id) + + from_sids = from_h.keys + to_sids = to_h.keys + + removed = (from_sids - to_sids).map do |sid| + { op: :remove, label: from_h[sid].libelle, position: from_sids.index(sid) } + end + + added = (to_sids - from_sids).map do |sid| + { op: :add, label: to_h[sid].libelle, position: to_sids.index(sid) } + end + + kept = from_sids.intersection(to_sids) + + moved = kept + .map { |sid| [sid, from_sids.index(sid), to_sids.index(sid)] } + .filter { |_, from_index, to_index| from_index != to_index } + .map do |sid, from_index, to_index| + { op: :move, label: from_h[sid].libelle, from: from_index, to: to_index, position: to_index } + end + + changed = kept + .map { |sid| [sid, from_h[sid], to_h[sid]] } + .flat_map do |sid, from, to| + compare_type_de_champ(from, to) + .each { |h| h[:position] = to_sids.index(sid) } + end + + (removed + added + moved + changed) + .sort_by { |h| h[:position] } + .each { |h| h.delete(:position) } + end + end + + def compare_type_de_champ(from_type_de_champ, to_type_de_champ) + changes = [] + if from_type_de_champ.type_champ != to_type_de_champ.type_champ + changes << { + op: :update, + attribute: :type_champ, + label: from_type_de_champ.libelle, + from: from_type_de_champ.type_champ, + to: to_type_de_champ.type_champ + } + end + if from_type_de_champ.libelle != to_type_de_champ.libelle + changes << { + op: :update, + attribute: :libelle, + label: from_type_de_champ.libelle, + from: from_type_de_champ.libelle, + to: to_type_de_champ.libelle + } + end + if from_type_de_champ.description != to_type_de_champ.description + changes << { + op: :update, + attribute: :description, + label: from_type_de_champ.libelle, + from: from_type_de_champ.description, + to: to_type_de_champ.description + } + end + if from_type_de_champ.mandatory? != to_type_de_champ.mandatory? + changes << { + op: :update, + attribute: :mandatory, + label: from_type_de_champ.libelle, + from: from_type_de_champ.mandatory?, + to: to_type_de_champ.mandatory? + } + end + if to_type_de_champ.drop_down_list? + if from_type_de_champ.drop_down_list_options != to_type_de_champ.drop_down_list_options + changes << { + op: :update, + attribute: :drop_down_options, + label: from_type_de_champ.libelle, + from: from_type_de_champ.drop_down_list_options, + to: to_type_de_champ.drop_down_list_options + } + end + elsif to_type_de_champ.piece_justificative? + if from_type_de_champ.piece_justificative_template_checksum != to_type_de_champ.piece_justificative_template_checksum + changes << { + op: :update, + attribute: :piece_justificative_template, + label: from_type_de_champ.libelle, + from: from_type_de_champ.piece_justificative_template_filename, + to: to_type_de_champ.piece_justificative_template_filename + } + end + elsif to_type_de_champ.repetition? + if from_type_de_champ.types_de_champ != to_type_de_champ.types_de_champ + changes += compare_types_de_champ(from_type_de_champ.types_de_champ, to_type_de_champ.types_de_champ) + end + end + changes + end + def revise_type_de_champ(type_de_champ) types_de_champ_association = type_de_champ.private? ? :revision_types_de_champ_private : :revision_types_de_champ association = send(types_de_champ_association).find_by!(type_de_champ: type_de_champ) diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index 88fa0585c..35f168586 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -226,6 +226,12 @@ class TypeDeChamp < ApplicationRecord end end + def piece_justificative_template_checksum + if piece_justificative_template.attached? + piece_justificative_template.checksum + end + end + def drop_down_list_value if drop_down_list_options.present? drop_down_list_options.reject(&:empty?).join("\r\n") From 9d3416af539c977e03f87f1734478dbefceb612e Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Fri, 18 Jun 2021 11:15:10 +0200 Subject: [PATCH 4/9] Implement revision changes UI --- app/assets/stylesheets/utils.scss | 4 ++ .../procedures/_publication_form.html.haml | 54 ++++++++++--------- .../procedures/_revision_changes.html.haml | 34 ++++++++++++ .../procedures/publication.html.haml | 3 ++ .../procedures/show.html.haml | 14 ++++- 5 files changed, 82 insertions(+), 27 deletions(-) create mode 100644 app/views/new_administrateur/procedures/_revision_changes.html.haml diff --git a/app/assets/stylesheets/utils.scss b/app/assets/stylesheets/utils.scss index 19d084813..8dbdc9b45 100644 --- a/app/assets/stylesheets/utils.scss +++ b/app/assets/stylesheets/utils.scss @@ -61,3 +61,7 @@ .mb-2 { margin-bottom: 2 * $default-spacer; } + +.mb-1 { + margin-bottom: $default-spacer; +} diff --git a/app/views/new_administrateur/procedures/_publication_form.html.haml b/app/views/new_administrateur/procedures/_publication_form.html.haml index 8699b1c9e..881996d81 100644 --- a/app/views/new_administrateur/procedures/_publication_form.html.haml +++ b/app/views/new_administrateur/procedures/_publication_form.html.haml @@ -1,40 +1,44 @@ .card.mb-4 %h2.card-title Publiez votre démarche = form_tag admin_procedure_publish_path(procedure_id: procedure.id), method: :put, class: 'form' do - %p.mb-4 Publiez votre démarche, et partagez la à vos usagers. Aucune modification ne sera possible. - %p Personnalisez le lien public de la démarche pour en faciliter l’accès (obligatoire pour publier votre démarche) : - %p.empty-text - = commencer_url(path: '') - = text_field_tag(:path, procedure.path, - id: 'procedure_path', - label: 'Adresse de diffusion', - placeholder: 'chemin-de-la-démarche', - required: true, - class: 'form', - pattern: '^[a-z0-9_-]{3,200}$', - title: "De 3 à 200 caractères; minuscules, chiffres et tiret seulement", - data: { debounce: true, url: admin_procedure_publish_validate_path(procedure)}, - autocomplete: 'off', - style: 'width: 300px; display: inline;') - .text-info.mb-4 - Attention, diffusez toujours le lien complet affiché ci-dessus, et non pas un lien générique vers #{APPLICATION_NAME}. Ne dites pas non plus aux usagers de se rendre sur le site générique #{APPLICATION_NAME}, donnez-leur toujours le lien complet. - %h2.card-title 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 - = text_field_tag(:lien_site_web, procedure.lien_site_web, + - if procedure.draft_changed? + %p.mb-4 Publiez une nouvelle version de votre démarche. Les changements suivants seront appliqués : + = render partial: 'revision_changes', locals: { changes: procedure.revision_changes } + - else + %p.mb-4 Publiez votre démarche, et partagez la à vos usagers. Aucune modification ne sera possible. + %p Personnalisez le lien public de la démarche pour en faciliter l’accès (obligatoire pour publier votre démarche) : + %p.empty-text + = commencer_url(path: '') + = text_field_tag(:path, procedure.path, + id: 'procedure_path', + label: 'Adresse de diffusion', + placeholder: 'chemin-de-la-démarche', required: true, - class: 'form-control', + class: 'form', + pattern: '^[a-z0-9_-]{3,200}$', + title: "De 3 à 200 caractères; minuscules, chiffres et tiret seulement", + data: { debounce: true, url: admin_procedure_publish_validate_path(procedure)}, autocomplete: 'off', - placeholder: 'https://exemple.gouv.fr/ma_demarche') + style: 'width: 300px; display: inline;') + .text-info.mb-4 + Attention, diffusez toujours le lien complet affiché ci-dessus, et non pas un lien générique vers #{APPLICATION_NAME}. Ne dites pas non plus aux usagers de se rendre sur le site générique #{APPLICATION_NAME}, donnez-leur toujours le lien complet. + %h2.card-title 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 + = text_field_tag(:lien_site_web, procedure.lien_site_web, + required: true, + class: 'form-control', + autocomplete: 'off', + placeholder: 'https://exemple.gouv.fr/ma_demarche') - 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) + - if errors.details[:path]&.pluck(:error)&.include?(:taken) && procedure.path_available?(administrateur, procedure.path) - errors.delete(:path) - options = { class: "button primary", id: 'publish' } - if errors.details[:path].present? - options[:disabled] = :disabled .flex.justify-end - = submit_tag procedure_publish_text(@procedure, :submit), options + = submit_tag procedure_publish_text(procedure, :submit), options diff --git a/app/views/new_administrateur/procedures/_revision_changes.html.haml b/app/views/new_administrateur/procedures/_revision_changes.html.haml new file mode 100644 index 000000000..78643af66 --- /dev/null +++ b/app/views/new_administrateur/procedures/_revision_changes.html.haml @@ -0,0 +1,34 @@ +%ul + - changes.each do |change| + - case change[:op] + - when :add + %li.mb-1= "Le champ « #{change[:label]} » a été ajouté." + - when :remove + %li.mb-1= "Le champ « #{change[:label]} » a été supprimé." + - when :update + - case change[:attribute] + - when :libelle + %li.mb-1= "Le libellé du champ « #{change[:label]} » a changé en « #{change[:to]} »." + - when :type_champ + %li.mb-1= "Le type du champ « #{change[:label]} » a changé. Il est maintenant de type « #{t("activerecord.attributes.type_de_champ.type_champs.#{change[:to]}")} »." + - when :description + %li.mb-1= "La description du champ « #{change[:label]} » a changé. La nouvelle description est « #{change[:to]} »." + - when :mandatory + - if change[:from] == false + %li.mb-1= "Le champ « #{change[:label]} » est maintenant obligatoire." + - else + %li.mb-1= "Le champ « #{change[:label]} » n'est plus obligatoire." + - when :piece_justificative_template + %li.mb-1= "Le champ « #{change[:label]} » a changé de modèle de pièce justificative." + - when :drop_down_options + - added = change[:to].sort - change[:from].sort + - removed = change[:from].sort - change[:to].sort + %li.mb-1 + = "Les options de sélection du champ « #{change[:label]} » ont changé." + %ul + - if added.present? + %li= "Valeurs ajoutés : #{added.map{ |term| "« #{term.strip} »" }.join(", ")}." + - if removed.present? + %li= "Valeurs supprimés : #{removed.map{ |term| "« #{term.strip} »" }.join(", ")}." + - if changes.any? { |change| change[:op] == :move } + %li.mb-1 Des champs ont changé de position diff --git a/app/views/new_administrateur/procedures/publication.html.haml b/app/views/new_administrateur/procedures/publication.html.haml index efd17f78e..4b07fd278 100644 --- a/app/views/new_administrateur/procedures/publication.html.haml +++ b/app/views/new_administrateur/procedures/publication.html.haml @@ -14,6 +14,9 @@ - if @procedure.close? || @procedure.depubliee? %p.mb-4 Cette démarche est close et n’est donc plus accessible par le public. Vous pouvez la réactiver : = render partial: 'publication_form', locals: { procedure: @procedure, administrateur: @current_administrateur } + - elsif @procedure.draft_changed? + %p.mb-4 Cette démarche est déjà publiée. Elle a été modifiée depuis sa publication. Vous pouvez publier les changements effectués dans une nouvelle version de cette démarche : + = render partial: 'publication_form', locals: { procedure: @procedure, administrateur: @current_administrateur } - elsif @procedure.publiee? %p Cette démarche est publiée, certains éléments ne peuvent plus être modifiés. Pour y accéder vous pouvez utiliser le lien : diff --git a/app/views/new_administrateur/procedures/show.html.haml b/app/views/new_administrateur/procedures/show.html.haml index 82d2983d0..ed51d41c6 100644 --- a/app/views/new_administrateur/procedures/show.html.haml +++ b/app/views/new_administrateur/procedures/show.html.haml @@ -29,6 +29,16 @@ %span.icon.archive Clore + - if @procedure.draft_changed? + = link_to 'Publier les modifications', admin_procedure_publication_path(@procedure), class: 'button primary', id: 'publish-procedure-link', data: { disable_with: "Publication..." } + +- if @procedure.draft_changed? + .container + .card.featured + .card-title + Des champs ont été changés + = render partial: 'revision_changes', locals: { changes: @procedure.revision_changes } + .container %h2.procedure-admin-explanation Indispensable avant publication .procedure-grid @@ -41,7 +51,7 @@ %p.card-admin-subtitle Logo, nom, description %p.button Modifier - - if !@procedure.locked? + - if !@procedure.locked? || @procedure.feature_enabled?(:procedure_revisions) = link_to champs_admin_procedure_path(@procedure), class: 'card-admin' do - if @procedure.draft_types_de_champ.count > 0 %div @@ -159,7 +169,7 @@ %p.card-admin-subtitle Notifications automatiques %p.button Modifier - - if !@procedure.locked? + - if !@procedure.locked? || @procedure.feature_enabled?(:procedure_revisions) = link_to annotations_admin_procedure_path(@procedure), class: 'card-admin' do - if @procedure.draft_types_de_champ_private.present? %div From e68441d573b0c10f21a0546ff3f17bf535faa8ef Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 28 Apr 2021 15:08:48 +0200 Subject: [PATCH 5/9] Allow publishing revisions when feature flag is enabled --- .../new_administrateur/administrateur_controller.rb | 7 +++++++ .../new_administrateur/procedures_controller.rb | 10 +++++++--- .../new_administrateur/types_de_champ_controller.rb | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/controllers/new_administrateur/administrateur_controller.rb b/app/controllers/new_administrateur/administrateur_controller.rb index 6a8da5753..7c5f4cdda 100644 --- a/app/controllers/new_administrateur/administrateur_controller.rb +++ b/app/controllers/new_administrateur/administrateur_controller.rb @@ -19,6 +19,13 @@ module NewAdministrateur end end + def procedure_revisable? + if @procedure.locked? && !@procedure.feature_enabled?(:procedure_revisions) + flash.alert = 'Démarche verrouillée' + redirect_to admin_procedure_path(@procedure) + end + end + def reset_procedure if @procedure.brouillon? @procedure.reset! diff --git a/app/controllers/new_administrateur/procedures_controller.rb b/app/controllers/new_administrateur/procedures_controller.rb index 7ef2b56f3..c0c697143 100644 --- a/app/controllers/new_administrateur/procedures_controller.rb +++ b/app/controllers/new_administrateur/procedures_controller.rb @@ -1,7 +1,7 @@ module NewAdministrateur class ProceduresController < AdministrateurController before_action :retrieve_procedure, only: [:champs, :annotations, :edit, :monavis, :update_monavis, :jeton, :update_jeton, :publication, :publish, :transfert, :allow_expert_review, :experts_require_administrateur_invitation] - before_action :procedure_locked?, only: [:champs, :annotations] + before_action :procedure_revisable?, only: [:champs, :annotations] ITEMS_PER_PAGE = 25 @@ -154,12 +154,16 @@ module NewAdministrateur def publish @procedure.assign_attributes(publish_params) - if @procedure.publish_or_reopen!(current_administrateur) + if @procedure.draft_changed? + @procedure.publish_revision! + flash.notice = "Nouvelle version de la démarche publiée" redirect_to admin_procedure_path(@procedure) + elsif @procedure.publish_or_reopen!(current_administrateur) flash.notice = "Démarche publiée" - else redirect_to admin_procedure_path(@procedure) + else flash.alert = @procedure.errors.full_messages + redirect_to admin_procedure_path(@procedure) end end diff --git a/app/controllers/new_administrateur/types_de_champ_controller.rb b/app/controllers/new_administrateur/types_de_champ_controller.rb index 160110985..4d4e1685c 100644 --- a/app/controllers/new_administrateur/types_de_champ_controller.rb +++ b/app/controllers/new_administrateur/types_de_champ_controller.rb @@ -1,7 +1,7 @@ module NewAdministrateur class TypesDeChampController < AdministrateurController before_action :retrieve_procedure, only: [:create, :update, :move, :destroy] - before_action :procedure_locked?, only: [:create, :update, :move, :destroy] + before_action :procedure_revisable?, only: [:create, :update, :move, :destroy] def create type_de_champ = @procedure.draft_revision.add_type_de_champ(type_de_champ_create_params) From 8d49b5556a7fafb2b96992c6474e228b715a226f Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 21 Jan 2021 11:32:01 +0100 Subject: [PATCH 6/9] test revision changes --- spec/models/procedure_revision_spec.rb | 144 +++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/spec/models/procedure_revision_spec.rb b/spec/models/procedure_revision_spec.rb index be67e94c6..787a552a6 100644 --- a/spec/models/procedure_revision_spec.rb +++ b/spec/models/procedure_revision_spec.rb @@ -152,5 +152,149 @@ describe ProcedureRevision do expect(new_revision.revision_types_de_champ).not_to eq(revision.revision_types_de_champ) expect(new_revision.revision_types_de_champ_private).not_to eq(revision.revision_types_de_champ_private) end + + describe '#compare' do + let(:type_de_champ_first) { revision.types_de_champ.first } + let(:type_de_champ_second) { revision.types_de_champ.second } + + it 'type_de_champ' do + expect(new_revision.types_de_champ.size).to eq(2) + new_type_de_champ = new_revision.add_type_de_champ({ + type_champ: TypeDeChamp.type_champs.fetch(:text), + libelle: "Un champ text" + }) + revision.reload + expect(new_revision.types_de_champ.size).to eq(3) + expect(new_revision.types_de_champ.last).to eq(new_type_de_champ) + expect(new_revision.revision_types_de_champ.last.position).to eq(2) + expect(new_revision.revision_types_de_champ.last.type_de_champ).to eq(new_type_de_champ) + expect(new_revision.revision_types_de_champ.last.type_de_champ.revision).to eq(new_revision) + expect(procedure.active_revision.changed?(new_revision)).to be_truthy + expect(procedure.active_revision.compare(new_revision)).to eq([ + { + op: :add, + label: "Un champ text" + } + ]) + + new_revision.find_or_clone_type_de_champ(new_revision.types_de_champ.first.stable_id).update(libelle: 'modifier le libelle') + expect(procedure.active_revision.compare(new_revision.reload)).to eq([ + { + op: :update, + attribute: :libelle, + label: type_de_champ_first.libelle, + from: type_de_champ_first.libelle, + to: "modifier le libelle" + }, + { + op: :add, + label: "Un champ text" + } + ]) + expect(new_revision.types_de_champ.first.revision).to eq(new_revision) + + new_revision.move_type_de_champ(new_revision.types_de_champ.second.stable_id, 2) + expect(procedure.active_revision.compare(new_revision.reload)).to eq([ + { + op: :update, + attribute: :libelle, + label: type_de_champ_first.libelle, + from: type_de_champ_first.libelle, + to: "modifier le libelle" + }, + { + op: :add, + label: "Un champ text" + }, + { + op: :move, + label: type_de_champ_second.libelle, + from: 1, + to: 2 + } + ]) + expect(new_revision.types_de_champ.last.revision).to eq(revision) + + new_revision.remove_type_de_champ(new_revision.types_de_champ.first.stable_id) + expect(procedure.active_revision.compare(new_revision.reload)).to eq([ + { + op: :remove, + label: type_de_champ_first.libelle + }, + { + op: :add, + label: "Un champ text" + } + ]) + + new_revision.find_or_clone_type_de_champ(new_revision.types_de_champ.last.stable_id).update(description: 'une description') + new_revision.find_or_clone_type_de_champ(new_revision.types_de_champ.last.stable_id).update(mandatory: true) + expect(procedure.active_revision.compare(new_revision.reload)).to eq([ + { + op: :remove, + label: type_de_champ_first.libelle + }, + { + op: :add, + label: "Un champ text" + }, + { + op: :update, + attribute: :description, + label: type_de_champ_second.libelle, + from: type_de_champ_second.description, + to: "une description" + }, + { + op: :update, + attribute: :mandatory, + label: type_de_champ_second.libelle, + from: false, + to: true + } + ]) + + new_revision.find_or_clone_type_de_champ(new_revision.types_de_champ.last.types_de_champ.first.stable_id).update(type_champ: :drop_down_list) + new_revision.find_or_clone_type_de_champ(new_revision.types_de_champ.last.types_de_champ.first.stable_id).update(drop_down_options: ['one', 'two']) + expect(procedure.active_revision.compare(new_revision.reload)).to eq([ + { + op: :remove, + label: type_de_champ_first.libelle + }, + { + op: :add, + label: "Un champ text" + }, + { + op: :update, + attribute: :description, + label: type_de_champ_second.libelle, + from: type_de_champ_second.description, + to: "une description" + }, + { + op: :update, + attribute: :mandatory, + label: type_de_champ_second.libelle, + from: false, + to: true + }, + { + op: :update, + attribute: :type_champ, + label: "sub type de champ", + from: "text", + to: "drop_down_list" + }, + { + op: :update, + attribute: :drop_down_options, + label: "sub type de champ", + from: [], + to: ["one", "two"] + } + ]) + end + end end end From eadae7af6b22e176bbe6b5c10e4a4a3c15c08c44 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 16 Jun 2021 10:48:15 +0200 Subject: [PATCH 7/9] show all available tdc for procedure presentation --- app/models/procedure.rb | 35 ++++++++ app/models/procedure_presentation.rb | 12 +-- ...ocedure_presentation_and_revisions_spec.rb | 90 +++++++++++++++++++ 3 files changed, 126 insertions(+), 11 deletions(-) create mode 100644 spec/models/procedure_presentation_and_revisions_spec.rb diff --git a/app/models/procedure.rb b/app/models/procedure.rb index 4a3b7fa82..c93777103 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -87,6 +87,41 @@ class Procedure < ApplicationRecord brouillon? ? draft_types_de_champ_private : published_types_de_champ_private end + def types_de_champ_for_procedure_presentation + explanatory_types_de_champ = [:header_section, :explication].map { |k| TypeDeChamp.type_champs.fetch(k) } + + if brouillon? + TypeDeChamp + .joins(:revisions) + .where.not(type_champ: explanatory_types_de_champ) + .where(procedure_revisions: { id: draft_revision_id }) + .order(:position) + else + # fetch all type_de_champ.stable_id for all the revisions expect draft + # and for each stable_id take the bigger (more recent) type_de_champ.id + recent_ids = TypeDeChamp + .joins(:revisions) + .where.not(type_champ: explanatory_types_de_champ) + .where(procedure_revisions: { procedure_id: id }) + .where.not(procedure_revisions: { id: draft_revision_id }) + .group(:stable_id) + .select('MAX(types_de_champ.id)') + + # fetch the more recent procedure_revision_types_de_champ + # which includes recents_ids + recents_prtdc = ProcedureRevisionTypeDeChamp + .where(type_de_champ_id: recent_ids) + .where.not(revision_id: draft_revision_id) + .group(:type_de_champ_id) + .select('MAX(id)') + + TypeDeChamp + .joins(:revision_types_de_champ) + .where(revision_types_de_champ: { id: recents_prtdc }) + .order(:position, 'revision_types_de_champ.revision_id': :desc) + end + end + def types_de_champ_for_tags if brouillon? draft_types_de_champ diff --git a/app/models/procedure_presentation.rb b/app/models/procedure_presentation.rb index 4ccaccd75..d60891bde 100644 --- a/app/models/procedure_presentation.rb +++ b/app/models/procedure_presentation.rb @@ -66,20 +66,10 @@ class ProcedurePresentation < ApplicationRecord ) end - explanatory_types_de_champ = [:header_section, :explication].map { |k| TypeDeChamp.type_champs.fetch(k) } - - fields.concat procedure.types_de_champ - .where.not(type_champ: explanatory_types_de_champ) - .order(:id) + fields.concat procedure.types_de_champ_for_procedure_presentation .pluck(:libelle, :stable_id) .map { |(libelle, stable_id)| field_hash(libelle, TYPE_DE_CHAMP, stable_id.to_s) } - fields.concat procedure.types_de_champ_private - .where.not(type_champ: explanatory_types_de_champ) - .order(:id) - .pluck(:libelle, :stable_id) - .map { |(libelle, stable_id)| field_hash(libelle, TYPE_DE_CHAMP_PRIVATE, stable_id.to_s) } - fields end diff --git a/spec/models/procedure_presentation_and_revisions_spec.rb b/spec/models/procedure_presentation_and_revisions_spec.rb new file mode 100644 index 000000000..087b2e17e --- /dev/null +++ b/spec/models/procedure_presentation_and_revisions_spec.rb @@ -0,0 +1,90 @@ +describe ProcedurePresentation do + describe "#types_de_champ_for_procedure_presentation" do + subject { procedure.types_de_champ_for_procedure_presentation.pluck(:libelle) } + + context 'for a draft procedure' do + let(:procedure) { create(:procedure) } + + context 'when there are one tdc on a published revision' do + let!(:tdc) { { type_champ: :number, libelle: 'libelle 1' } } + + before { procedure.draft_revision.add_type_de_champ(tdc) } + + it { is_expected.to match(['libelle 1']) } + end + end + + context 'for a published procedure' do + let(:procedure) { create(:procedure, :published) } + let!(:tdc) { { type_champ: :number, libelle: 'libelle 1' } } + + before do + procedure.draft_revision.add_type_de_champ(tdc) + procedure.publish_revision! + end + + it { is_expected.to match(['libelle 1']) } + + context 'when there is another published revision with an added tdc' do + let!(:added_tdc) { { type_champ: :number, libelle: 'libelle 2' } } + + before do + procedure.draft_revision.add_type_de_champ(added_tdc) + procedure.publish_revision! + end + + it { is_expected.to match(['libelle 1', 'libelle 2']) } + end + + context 'add one tdc above the first one' do + let!(:tdc2) { { type_champ: :number, libelle: 'libelle 2' } } + + before do + created_tdc2 = procedure.draft_revision.add_type_de_champ(tdc2) + procedure.draft_revision.move_type_de_champ(created_tdc2.stable_id, 0) + procedure.publish_revision! + end + + it { is_expected.to match(['libelle 2', 'libelle 1']) } + + context 'and finaly, when this tdc is removed' do + let!(:previous_tdc2) { procedure.published_revision.types_de_champ.find_by(libelle: 'libelle 2') } + + before do + procedure.draft_revision.remove_type_de_champ(previous_tdc2.stable_id) + + procedure.publish_revision! + end + + it { is_expected.to match(['libelle 1', 'libelle 2']) } + end + end + + context 'when there is another published revision with a renamed tdc' do + let!(:previous_tdc) { procedure.published_revision.types_de_champ.first } + let!(:changed_tdc) { { type_champ: :number, libelle: 'changed libelle 1' } } + + before do + type_de_champ = procedure.draft_revision.find_or_clone_type_de_champ(previous_tdc.id) + type_de_champ.update(changed_tdc) + + procedure.publish_revision! + end + + it { is_expected.to match(['changed libelle 1']) } + end + + context 'when there is another published which removes a previous tdc' do + let!(:previous_tdc) { procedure.published_revision.types_de_champ.first } + + before do + type_de_champ = procedure.draft_revision.remove_type_de_champ(previous_tdc.id) + + procedure.publish_revision! + end + + it { is_expected.to match(['libelle 1']) } + end + end + end +end From 19195008e87a3ccf3c10c0466363ab73ff6c7827 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 22 Jun 2021 10:17:10 +0200 Subject: [PATCH 8/9] Expose removed types_de_champ in exports --- app/models/dossier.rb | 32 +++++++----------------- app/models/procedure.rb | 14 +++-------- app/models/procedure_presentation.rb | 4 +-- app/services/procedure_export_service.rb | 5 ++-- spec/models/dossier_spec.rb | 8 +++--- spec/models/procedure_revision_spec.rb | 4 +-- 6 files changed, 22 insertions(+), 45 deletions(-) diff --git a/app/models/dossier.rb b/app/models/dossier.rb index a2ba7403a..11fdb15f7 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -764,19 +764,19 @@ class Dossier < ApplicationRecord log_dossier_operation(avis.claimant, :demander_un_avis, avis) end - def spreadsheet_columns_csv(types_de_champ:, types_de_champ_private:) - spreadsheet_columns(with_etablissement: true, types_de_champ: types_de_champ, types_de_champ_private: types_de_champ_private) + def spreadsheet_columns_csv(types_de_champ:) + spreadsheet_columns(with_etablissement: true, types_de_champ: types_de_champ) end - def spreadsheet_columns_xlsx(types_de_champ:, types_de_champ_private:) - spreadsheet_columns(types_de_champ: types_de_champ, types_de_champ_private: types_de_champ_private) + def spreadsheet_columns_xlsx(types_de_champ:) + spreadsheet_columns(types_de_champ: types_de_champ) end - def spreadsheet_columns_ods(types_de_champ:, types_de_champ_private:) - spreadsheet_columns(types_de_champ: types_de_champ, types_de_champ_private: types_de_champ_private) + def spreadsheet_columns_ods(types_de_champ:) + spreadsheet_columns(types_de_champ: types_de_champ) end - def spreadsheet_columns(with_etablissement: false, types_de_champ:, types_de_champ_private:) + def spreadsheet_columns(with_etablissement: false, types_de_champ:) columns = [ ['ID', id.to_s], ['Email', user_email_for(:display)] @@ -843,26 +843,12 @@ class Dossier < ApplicationRecord columns << ['Groupe instructeur', groupe_instructeur.label] end - columns + champs_for_export(types_de_champ) + champs_private_for_export(types_de_champ_private) + columns + champs_for_export(types_de_champ) end def champs_for_export(types_de_champ) # Index values by stable_id - values = champs.reject(&:exclude_from_export?).reduce({}) do |champs, champ| - champs[champ.stable_id] = champ.for_export - champs - end - - # Get all the champs values for the types de champ in the final list. - # Dossier might not have corresponding champ – display nil. - types_de_champ.map do |type_de_champ| - [type_de_champ.libelle, values[type_de_champ.stable_id]] - end - end - - def champs_private_for_export(types_de_champ) - # Index values by stable_id - values = champs_private.reject(&:exclude_from_export?).reduce({}) do |champs, champ| + values = (champs + champs_private).reject(&:exclude_from_export?).reduce({}) do |champs, champ| champs[champ.stable_id] = champ.for_export champs end diff --git a/app/models/procedure.rb b/app/models/procedure.rb index c93777103..e6d44f691 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -88,14 +88,14 @@ class Procedure < ApplicationRecord end def types_de_champ_for_procedure_presentation - explanatory_types_de_champ = [:header_section, :explication].map { |k| TypeDeChamp.type_champs.fetch(k) } + explanatory_types_de_champ = [:header_section, :explication, :repetition].map { |k| TypeDeChamp.type_champs.fetch(k) } if brouillon? TypeDeChamp .joins(:revisions) .where.not(type_champ: explanatory_types_de_champ) .where(procedure_revisions: { id: draft_revision_id }) - .order(:position) + .order(:private, :position) else # fetch all type_de_champ.stable_id for all the revisions expect draft # and for each stable_id take the bigger (more recent) type_de_champ.id @@ -118,7 +118,7 @@ class Procedure < ApplicationRecord TypeDeChamp .joins(:revision_types_de_champ) .where(revision_types_de_champ: { id: recents_prtdc }) - .order(:position, 'revision_types_de_champ.revision_id': :desc) + .order(:private, :position, 'revision_types_de_champ.revision_id': :desc) end end @@ -146,14 +146,6 @@ class Procedure < ApplicationRecord end end - def types_de_champ_for_export - types_de_champ.reject(&:exclude_from_export?) - end - - def types_de_champ_private_for_export - types_de_champ_private.reject(&:exclude_from_export?) - end - has_many :administrateurs_procedures has_many :administrateurs, through: :administrateurs_procedures, after_remove: -> (procedure, _admin) { procedure.validate! } has_many :groupe_instructeurs, dependent: :destroy diff --git a/app/models/procedure_presentation.rb b/app/models/procedure_presentation.rb index d60891bde..309b63d31 100644 --- a/app/models/procedure_presentation.rb +++ b/app/models/procedure_presentation.rb @@ -67,8 +67,8 @@ class ProcedurePresentation < ApplicationRecord end fields.concat procedure.types_de_champ_for_procedure_presentation - .pluck(:libelle, :stable_id) - .map { |(libelle, stable_id)| field_hash(libelle, TYPE_DE_CHAMP, stable_id.to_s) } + .pluck(:libelle, :private, :stable_id) + .map { |(libelle, is_private, stable_id)| field_hash(libelle, is_private ? TYPE_DE_CHAMP_PRIVATE : TYPE_DE_CHAMP, stable_id.to_s) } fields end diff --git a/app/services/procedure_export_service.rb b/app/services/procedure_export_service.rb index 3cafccdff..d6c8ed69d 100644 --- a/app/services/procedure_export_service.rb +++ b/app/services/procedure_export_service.rb @@ -84,11 +84,10 @@ class ProcedureExportService end def spreadsheet_columns(format) - types_de_champ = @procedure.types_de_champ_for_export - types_de_champ_private = @procedure.types_de_champ_private_for_export + types_de_champ = @procedure.types_de_champ_for_procedure_presentation.to_a Proc.new do |instance| - instance.send(:"spreadsheet_columns_#{format}", types_de_champ: types_de_champ, types_de_champ_private: types_de_champ_private) + instance.send(:"spreadsheet_columns_#{format}", types_de_champ: types_de_champ) end end end diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 90f76235f..e4ac26716 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -1364,8 +1364,8 @@ describe Dossier do it "should have champs from all revisions" do expect(dossier.types_de_champ.map(&:libelle)).to eq([text_type_de_champ.libelle, datetime_type_de_champ.libelle, "Yes/no", explication_type_de_champ.libelle]) expect(dossier_second_revision.types_de_champ.map(&:libelle)).to eq([datetime_type_de_champ.libelle, "Updated yes/no", explication_type_de_champ.libelle, "New text field"]) - expect(dossier.champs_for_export(dossier.procedure.types_de_champ_for_export).map { |(libelle)| libelle }).to eq([datetime_type_de_champ.libelle, "Updated yes/no", "New text field"]) - expect(dossier.champs_for_export(dossier.procedure.types_de_champ_for_export)).to eq(dossier_second_revision.champs_for_export(dossier_second_revision.procedure.types_de_champ_for_export)) + expect(dossier.champs_for_export(dossier.procedure.types_de_champ_for_procedure_presentation).map { |(libelle)| libelle }).to eq([text_type_de_champ.libelle, datetime_type_de_champ.libelle, "Updated yes/no", "New text field"]) + expect(dossier.champs_for_export(dossier.procedure.types_de_champ_for_procedure_presentation)).to eq(dossier_second_revision.champs_for_export(dossier_second_revision.procedure.types_de_champ_for_procedure_presentation)) end end @@ -1373,7 +1373,7 @@ describe Dossier do let(:procedure) { create(:procedure, :with_type_de_champ, :with_explication) } it "should not contain non-exportable types de champ" do - expect(dossier.champs_for_export(dossier.procedure.types_de_champ_for_export).map { |(libelle)| libelle }).to eq([text_type_de_champ.libelle]) + expect(dossier.champs_for_export(dossier.procedure.types_de_champ_for_procedure_presentation).map { |(libelle)| libelle }).to eq([text_type_de_champ.libelle]) end end end @@ -1451,6 +1451,6 @@ describe Dossier do describe "#spreadsheet_columns" do let(:dossier) { create(:dossier) } - it { expect(dossier.spreadsheet_columns(types_de_champ: [], types_de_champ_private: [])).to include(["État du dossier", "Brouillon"]) } + it { expect(dossier.spreadsheet_columns(types_de_champ: [])).to include(["État du dossier", "Brouillon"]) } end end diff --git a/spec/models/procedure_revision_spec.rb b/spec/models/procedure_revision_spec.rb index 787a552a6..799eff756 100644 --- a/spec/models/procedure_revision_spec.rb +++ b/spec/models/procedure_revision_spec.rb @@ -56,7 +56,7 @@ describe ProcedureRevision do revision.reload expect(revision.types_de_champ.index(type_de_champ)).to eq(2) expect(revision.procedure.types_de_champ.index(type_de_champ)).to eq(2) - expect(revision.procedure.types_de_champ_for_export.index(type_de_champ)).to eq(2) + expect(revision.procedure.types_de_champ_for_procedure_presentation.index(type_de_champ)).to eq(2) end it 'move up' do @@ -66,7 +66,7 @@ describe ProcedureRevision do revision.reload expect(revision.types_de_champ.index(last_type_de_champ)).to eq(0) expect(revision.procedure.types_de_champ.index(last_type_de_champ)).to eq(0) - expect(revision.procedure.types_de_champ_for_export.index(last_type_de_champ)).to eq(0) + expect(revision.procedure.types_de_champ_for_procedure_presentation.index(last_type_de_champ)).to eq(0) end context 'repetition' do From 35eccb5630460644566f7ff67e9f659ca0216b97 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 22 Jun 2021 12:20:04 +0200 Subject: [PATCH 9/9] Show separate blocks for types de champ and annotation changes --- app/models/procedure.rb | 8 +++++ app/models/procedure_revision.rb | 12 +++++-- .../procedures/_revision_changes.html.haml | 5 +-- .../procedures/show.html.haml | 21 ++++++++--- .../groupe_instructeurs/fr.yml | 10 ++++++ spec/models/procedure_revision_spec.rb | 36 ++++++++++++++----- 6 files changed, 73 insertions(+), 19 deletions(-) diff --git a/app/models/procedure.rb b/app/models/procedure.rb index e6d44f691..25674e078 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -368,6 +368,14 @@ class Procedure < ApplicationRecord published_revision.compare(draft_revision) end + def revision_types_de_champ_private_changes + revision_changes.filter { |change| change[:private] } + end + + def revision_types_de_champ_changes + revision_changes.filter { |change| !change[:private] } + end + def accepts_new_dossiers? publiee? || brouillon? end diff --git a/app/models/procedure_revision.rb b/app/models/procedure_revision.rb index ee616fa87..939450b5e 100644 --- a/app/models/procedure_revision.rb +++ b/app/models/procedure_revision.rb @@ -125,11 +125,11 @@ class ProcedureRevision < ApplicationRecord to_sids = to_h.keys removed = (from_sids - to_sids).map do |sid| - { op: :remove, label: from_h[sid].libelle, position: from_sids.index(sid) } + { op: :remove, label: from_h[sid].libelle, private: from_h[sid].private?, position: from_sids.index(sid) } end added = (to_sids - from_sids).map do |sid| - { op: :add, label: to_h[sid].libelle, position: to_sids.index(sid) } + { op: :add, label: to_h[sid].libelle, private: to_h[sid].private?, position: to_sids.index(sid) } end kept = from_sids.intersection(to_sids) @@ -138,7 +138,7 @@ class ProcedureRevision < ApplicationRecord .map { |sid| [sid, from_sids.index(sid), to_sids.index(sid)] } .filter { |_, from_index, to_index| from_index != to_index } .map do |sid, from_index, to_index| - { op: :move, label: from_h[sid].libelle, from: from_index, to: to_index, position: to_index } + { op: :move, label: from_h[sid].libelle, private: from_h[sid].private?, from: from_index, to: to_index, position: to_index } end changed = kept @@ -161,6 +161,7 @@ class ProcedureRevision < ApplicationRecord op: :update, attribute: :type_champ, label: from_type_de_champ.libelle, + private: from_type_de_champ.private?, from: from_type_de_champ.type_champ, to: to_type_de_champ.type_champ } @@ -170,6 +171,7 @@ class ProcedureRevision < ApplicationRecord op: :update, attribute: :libelle, label: from_type_de_champ.libelle, + private: from_type_de_champ.private?, from: from_type_de_champ.libelle, to: to_type_de_champ.libelle } @@ -179,6 +181,7 @@ class ProcedureRevision < ApplicationRecord op: :update, attribute: :description, label: from_type_de_champ.libelle, + private: from_type_de_champ.private?, from: from_type_de_champ.description, to: to_type_de_champ.description } @@ -188,6 +191,7 @@ class ProcedureRevision < ApplicationRecord op: :update, attribute: :mandatory, label: from_type_de_champ.libelle, + private: from_type_de_champ.private?, from: from_type_de_champ.mandatory?, to: to_type_de_champ.mandatory? } @@ -198,6 +202,7 @@ class ProcedureRevision < ApplicationRecord op: :update, attribute: :drop_down_options, label: from_type_de_champ.libelle, + private: from_type_de_champ.private?, from: from_type_de_champ.drop_down_list_options, to: to_type_de_champ.drop_down_list_options } @@ -208,6 +213,7 @@ class ProcedureRevision < ApplicationRecord op: :update, attribute: :piece_justificative_template, label: from_type_de_champ.libelle, + private: from_type_de_champ.private?, from: from_type_de_champ.piece_justificative_template_filename, to: to_type_de_champ.piece_justificative_template_filename } diff --git a/app/views/new_administrateur/procedures/_revision_changes.html.haml b/app/views/new_administrateur/procedures/_revision_changes.html.haml index 78643af66..aa430ede6 100644 --- a/app/views/new_administrateur/procedures/_revision_changes.html.haml +++ b/app/views/new_administrateur/procedures/_revision_changes.html.haml @@ -30,5 +30,6 @@ %li= "Valeurs ajoutés : #{added.map{ |term| "« #{term.strip} »" }.join(", ")}." - if removed.present? %li= "Valeurs supprimés : #{removed.map{ |term| "« #{term.strip} »" }.join(", ")}." - - if changes.any? { |change| change[:op] == :move } - %li.mb-1 Des champs ont changé de position + - move_changes = changes.filter { |change| change[:op] == :move }.size + - if move_changes != 0 + %li.mb-1= t(:has_move_changes, count: move_changes, scope: [:new_administrateur, :revision_changes]) diff --git a/app/views/new_administrateur/procedures/show.html.haml b/app/views/new_administrateur/procedures/show.html.haml index ed51d41c6..4a86a7953 100644 --- a/app/views/new_administrateur/procedures/show.html.haml +++ b/app/views/new_administrateur/procedures/show.html.haml @@ -33,11 +33,22 @@ = link_to 'Publier les modifications', admin_procedure_publication_path(@procedure), class: 'button primary', id: 'publish-procedure-link', data: { disable_with: "Publication..." } - if @procedure.draft_changed? - .container - .card.featured - .card-title - Des champs ont été changés - = render partial: 'revision_changes', locals: { changes: @procedure.revision_changes } + - types_de_champ_changes = @procedure.revision_types_de_champ_changes + - types_de_champ_private_changes = @procedure.revision_types_de_champ_private_changes + + - if types_de_champ_changes.present? + .container + .card.featured + .card-title + = t(:has_changes, count: types_de_champ_changes.size, scope: [:new_administrateur, :revision_changes]) + = render partial: 'revision_changes', locals: { changes: types_de_champ_changes } + + - if types_de_champ_private_changes.present? + .container + .card.featured + .card-title + = t(:has_private_changes, count: types_de_champ_private_changes.size, scope: [:new_administrateur, :revision_changes]) + = render partial: 'revision_changes', locals: { changes: types_de_champ_private_changes } .container %h2.procedure-admin-explanation Indispensable avant publication diff --git a/config/locales/views/new_administrateur/groupe_instructeurs/fr.yml b/config/locales/views/new_administrateur/groupe_instructeurs/fr.yml index 2243a9caf..6f1b05090 100644 --- a/config/locales/views/new_administrateur/groupe_instructeurs/fr.yml +++ b/config/locales/views/new_administrateur/groupe_instructeurs/fr.yml @@ -27,3 +27,13 @@ fr: existing_groupe: one: "%{count} groupe existe" other: "%{count} groupes existent" + revision_changes: + has_changes: + one: Un champ a été changé + other: "%{count} champs ont été changés" + has_private_changes: + one: Une annotation privée a été changée + other: "%{count} deux annotations privées ont été changées" + has_move_changes: + one: Un champ a changé de position + other: "%{count} champs ont changé de position" diff --git a/spec/models/procedure_revision_spec.rb b/spec/models/procedure_revision_spec.rb index 799eff756..0d14d7837 100644 --- a/spec/models/procedure_revision_spec.rb +++ b/spec/models/procedure_revision_spec.rb @@ -173,7 +173,8 @@ describe ProcedureRevision do expect(procedure.active_revision.compare(new_revision)).to eq([ { op: :add, - label: "Un champ text" + label: "Un champ text", + private: false } ]) @@ -183,12 +184,14 @@ describe ProcedureRevision do op: :update, attribute: :libelle, label: type_de_champ_first.libelle, + private: false, from: type_de_champ_first.libelle, to: "modifier le libelle" }, { op: :add, - label: "Un champ text" + label: "Un champ text", + private: false } ]) expect(new_revision.types_de_champ.first.revision).to eq(new_revision) @@ -199,16 +202,19 @@ describe ProcedureRevision do op: :update, attribute: :libelle, label: type_de_champ_first.libelle, + private: false, from: type_de_champ_first.libelle, to: "modifier le libelle" }, { op: :add, - label: "Un champ text" + label: "Un champ text", + private: false }, { op: :move, label: type_de_champ_second.libelle, + private: false, from: 1, to: 2 } @@ -219,11 +225,13 @@ describe ProcedureRevision do expect(procedure.active_revision.compare(new_revision.reload)).to eq([ { op: :remove, - label: type_de_champ_first.libelle + label: type_de_champ_first.libelle, + private: false }, { op: :add, - label: "Un champ text" + label: "Un champ text", + private: false } ]) @@ -232,16 +240,19 @@ describe ProcedureRevision do expect(procedure.active_revision.compare(new_revision.reload)).to eq([ { op: :remove, - label: type_de_champ_first.libelle + label: type_de_champ_first.libelle, + private: false }, { op: :add, - label: "Un champ text" + label: "Un champ text", + private: false }, { op: :update, attribute: :description, label: type_de_champ_second.libelle, + private: false, from: type_de_champ_second.description, to: "une description" }, @@ -249,6 +260,7 @@ describe ProcedureRevision do op: :update, attribute: :mandatory, label: type_de_champ_second.libelle, + private: false, from: false, to: true } @@ -259,16 +271,19 @@ describe ProcedureRevision do expect(procedure.active_revision.compare(new_revision.reload)).to eq([ { op: :remove, - label: type_de_champ_first.libelle + label: type_de_champ_first.libelle, + private: false }, { op: :add, - label: "Un champ text" + label: "Un champ text", + private: false }, { op: :update, attribute: :description, label: type_de_champ_second.libelle, + private: false, from: type_de_champ_second.description, to: "une description" }, @@ -276,6 +291,7 @@ describe ProcedureRevision do op: :update, attribute: :mandatory, label: type_de_champ_second.libelle, + private: false, from: false, to: true }, @@ -283,6 +299,7 @@ describe ProcedureRevision do op: :update, attribute: :type_champ, label: "sub type de champ", + private: false, from: "text", to: "drop_down_list" }, @@ -290,6 +307,7 @@ describe ProcedureRevision do op: :update, attribute: :drop_down_options, label: "sub type de champ", + private: false, from: [], to: ["one", "two"] }