From 2754dc9c9e5805164ef59aae2dc295adc684c267 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Mon, 4 Feb 2019 16:43:26 +0100 Subject: [PATCH 01/16] Avoid n+1 when loading types de champ in to the editor --- app/helpers/procedure_helper.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/helpers/procedure_helper.rb b/app/helpers/procedure_helper.rb index 443626b8e..fe3395201 100644 --- a/app/helpers/procedure_helper.rb +++ b/app/helpers/procedure_helper.rb @@ -89,6 +89,9 @@ module ProcedureHelper .merge(include: TYPES_DE_CHAMP_INCLUDE.merge(types_de_champ: TYPES_DE_CHAMP_BASE)) def types_de_champ_as_json(types_de_champ) - types_de_champ.as_json(TYPES_DE_CHAMP) + types_de_champ.includes(:drop_down_list, + piece_justificative_template_attachment: :blob, + types_de_champ: [:drop_down_list, piece_justificative_template_attachment: :blob]) + .as_json(TYPES_DE_CHAMP) end end From 1d75a32cac0bbafc5787117cefb59a380456cd46 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Mon, 4 Feb 2019 17:08:41 +0100 Subject: [PATCH 02/16] Add a default text type de champ to editor --- .../new_design/administrateur/DraggableItem.js | 4 +--- .../new_design/administrateur/champs-editor.js | 8 ++++++++ spec/features/admin/procedure_creation_spec.rb | 6 ------ .../features/new_administrateur/procedures_spec.rb | 14 +++----------- 4 files changed, 12 insertions(+), 20 deletions(-) diff --git a/app/javascript/new_design/administrateur/DraggableItem.js b/app/javascript/new_design/administrateur/DraggableItem.js index e1ff2a357..95d284120 100644 --- a/app/javascript/new_design/administrateur/DraggableItem.js +++ b/app/javascript/new_design/administrateur/DraggableItem.js @@ -130,9 +130,7 @@ export default { addChamp() { this.typesDeChamp.push({ type_champ: 'text', - drop_down_list: {}, - types_de_champ: [], - options: {} + types_de_champ: [] }); } } diff --git a/app/javascript/new_design/administrateur/champs-editor.js b/app/javascript/new_design/administrateur/champs-editor.js index 8445b458d..3b47de908 100644 --- a/app/javascript/new_design/administrateur/champs-editor.js +++ b/app/javascript/new_design/administrateur/champs-editor.js @@ -53,6 +53,14 @@ function initEditor(el) { this.update = update; this.updateAll = updateAll; + + // We add an initial type de champ here if form is empty + if (this.state.typesDeChamp.length === 0) { + this.state.typesDeChamp.push({ + type_champ: 'text', + types_de_champ: [] + }); + } } }); } diff --git a/spec/features/admin/procedure_creation_spec.rb b/spec/features/admin/procedure_creation_spec.rb index f8fd9a74a..eefc0853f 100644 --- a/spec/features/admin/procedure_creation_spec.rb +++ b/spec/features/admin/procedure_creation_spec.rb @@ -100,9 +100,6 @@ feature 'As an administrateur I wanna create a new procedure', js: true do page.refresh expect(page).to have_current_path(champs_procedure_path(Procedure.last)) - within '.footer' do - click_on 'Ajouter un champ' - end expect(page).to have_selector('#procedure_types_de_champ_attributes_0_libelle') fill_in 'procedure_types_de_champ_attributes_0_libelle', with: 'libelle de champ' expect(page).to have_content('Formulaire mis à jour') @@ -131,9 +128,6 @@ feature 'As an administrateur I wanna create a new procedure', js: true do scenario 'After adding champ and file, make publication' do page.refresh - within '.footer' do - click_on 'Ajouter un champ' - end fill_in 'procedure_types_de_champ_attributes_0_libelle', with: 'libelle de champ' expect(page).to have_content('Formulaire mis à jour') diff --git a/spec/features/new_administrateur/procedures_spec.rb b/spec/features/new_administrateur/procedures_spec.rb index 47ba7e66f..c1b3b1b8b 100644 --- a/spec/features/new_administrateur/procedures_spec.rb +++ b/spec/features/new_administrateur/procedures_spec.rb @@ -11,6 +11,8 @@ feature 'As an administrateur I edit procedure', js: true do end it "Add a new champ" do + click_on 'Supprimer' + within '.footer' do click_on 'Ajouter un champ' end @@ -31,7 +33,6 @@ feature 'As an administrateur I edit procedure', js: true do click_on 'Ajouter un champ' click_on 'Ajouter un champ' click_on 'Ajouter un champ' - click_on 'Ajouter un champ' end expect(page).not_to have_content('Le libellé doit être rempli.') expect(page).not_to have_content('Modifications non sauvegardées.') @@ -66,9 +67,6 @@ feature 'As an administrateur I edit procedure', js: true do end it "Remove champs" do - within '.footer' do - click_on 'Ajouter un champ' - end fill_in 'procedure_types_de_champ_attributes_0_libelle', with: 'libellé de champ' expect(page).to have_content('Formulaire mis à jour') page.refresh @@ -78,13 +76,10 @@ feature 'As an administrateur I edit procedure', js: true do expect(page).not_to have_content('Supprimer') page.refresh - expect(page).not_to have_content('Supprimer') + expect(page).to have_content('Supprimer', count: 1) end it "Only add valid champs" do - within '.footer' do - click_on 'Ajouter un champ' - end expect(page).to have_selector('#procedure_types_de_champ_attributes_0_description') fill_in 'procedure_types_de_champ_attributes_0_description', with: 'déscription du champ' expect(page).to have_content('Le libellé doit être rempli.') @@ -95,9 +90,6 @@ feature 'As an administrateur I edit procedure', js: true do end it "Add repetition champ" do - within '.footer' do - click_on 'Ajouter un champ' - end expect(page).to have_selector('#procedure_types_de_champ_attributes_0_libelle') select('Bloc répétable', from: 'procedure_types_de_champ_attributes_0_type_champ') fill_in 'procedure_types_de_champ_attributes_0_libelle', with: 'libellé de champ' From a9a853b669723fba22bcca44730e9993669746e3 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Mon, 4 Feb 2019 21:04:05 +0100 Subject: [PATCH 03/16] Fix and simplify linked-drop-down-list js --- .../champs/linked-drop-down-list.js | 49 +++++++++---------- .../_linked_drop_down_list.html.haml | 5 +- .../features/new_user/linked_dropdown_spec.rb | 5 +- 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/app/javascript/new_design/champs/linked-drop-down-list.js b/app/javascript/new_design/champs/linked-drop-down-list.js index c49d3dcd7..c1e14d50d 100644 --- a/app/javascript/new_design/champs/linked-drop-down-list.js +++ b/app/javascript/new_design/champs/linked-drop-down-list.js @@ -1,29 +1,28 @@ -addEventListener('turbolinks:load', () => { - const primaries = document.querySelectorAll('select[data-secondary-options]'); +import { delegate } from '@utils'; - for (let primary of primaries) { - let secondary = document.querySelector( - `select[data-secondary-id="${primary.dataset.primaryId}"]` - ); - let secondaryOptions = JSON.parse(primary.dataset.secondaryOptions); +const PRIMARY_SELECTOR = 'select[data-secondary-options]'; +const SECONDARY_SELECTOR = 'select[data-secondary]'; +const CHAMP_SELECTOR = '.editable-champ'; - primary.addEventListener('change', e => { - let option, options, element; +delegate('change', PRIMARY_SELECTOR, evt => { + const primary = evt.target; + const secondary = primary + .closest(CHAMP_SELECTOR) + .querySelector(SECONDARY_SELECTOR); + const options = JSON.parse(primary.dataset.secondaryOptions); - while ((option = secondary.firstChild)) { - secondary.removeChild(option); - } - - options = secondaryOptions[e.target.value]; - - for (let option of options) { - element = document.createElement('option'); - element.textContent = option; - element.value = option; - secondary.appendChild(element); - } - - secondary.selectedIndex = 0; - }); - } + selectOptions(secondary, options[primary.value]); }); + +function selectOptions(selectElement, options) { + selectElement.innerHTML = ''; + + for (let option of options) { + let element = document.createElement('option'); + element.textContent = option; + element.value = option; + selectElement.appendChild(element); + } + + selectElement.selectedIndex = 0; +} diff --git a/app/views/shared/dossiers/editable_champs/_linked_drop_down_list.html.haml b/app/views/shared/dossiers/editable_champs/_linked_drop_down_list.html.haml index 03afe6832..fcabeefa9 100644 --- a/app/views/shared/dossiers/editable_champs/_linked_drop_down_list.html.haml +++ b/app/views/shared/dossiers/editable_champs/_linked_drop_down_list.html.haml @@ -1,10 +1,9 @@ - if champ.drop_down_list && champ.drop_down_list.options.any? - - champ_id = champ.object_id = form.select :primary_value, champ.primary_options, { required: champ.mandatory? }, - { data: { "secondary-options" => champ.secondary_options, "primary-id" => champ_id } } + { data: { secondary_options: champ.secondary_options } } = form.select :secondary_value, champ.secondary_options[champ.primary_value], { required: champ.mandatory? }, - { data: { "secondary-id" => champ_id } } + { data: { secondary: true } } diff --git a/spec/features/new_user/linked_dropdown_spec.rb b/spec/features/new_user/linked_dropdown_spec.rb index 769057fcd..e9940f43d 100644 --- a/spec/features/new_user/linked_dropdown_spec.rb +++ b/spec/features/new_user/linked_dropdown_spec.rb @@ -74,7 +74,8 @@ feature 'linked dropdown lists' do def secondary_id_for(libelle) primary_id = primary_id_for(libelle) - link = find("\##{primary_id}")['data-primary-id'] - find("[data-secondary-id=\"#{link}\"]")['id'] + find("\##{primary_id}") + .ancestor('.editable-champ') + .find("[data-secondary]")['id'] end end From cb72507c1284b2bcc34e6d7e64bdc0e0488fd37b Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Mon, 4 Feb 2019 21:04:15 +0100 Subject: [PATCH 04/16] Simplify repetition js --- .../new_design/champs/repetition.js | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/app/javascript/new_design/champs/repetition.js b/app/javascript/new_design/champs/repetition.js index a70b48c71..b6a380f1d 100644 --- a/app/javascript/new_design/champs/repetition.js +++ b/app/javascript/new_design/champs/repetition.js @@ -4,21 +4,19 @@ const BUTTON_SELECTOR = '.button.remove-row'; const DESTROY_INPUT_SELECTOR = 'input[type=hidden][name*=_destroy]'; const CHAMP_SELECTOR = '.editable-champ'; -addEventListener('turbolinks:load', () => { - delegate('click', BUTTON_SELECTOR, evt => { - evt.preventDefault(); +delegate('click', BUTTON_SELECTOR, evt => { + evt.preventDefault(); - const row = evt.target.closest('.row'); + const row = evt.target.closest('.row'); - for (let input of row.querySelectorAll(DESTROY_INPUT_SELECTOR)) { - input.disabled = false; - input.value = true; - } - for (let champ of row.querySelectorAll(CHAMP_SELECTOR)) { - champ.remove(); - } + for (let input of row.querySelectorAll(DESTROY_INPUT_SELECTOR)) { + input.disabled = false; + input.value = true; + } + for (let champ of row.querySelectorAll(CHAMP_SELECTOR)) { + champ.remove(); + } - evt.target.remove(); - row.classList.remove('row'); - }); + evt.target.remove(); + row.classList.remove('row'); }); From d67af741d57e462e7aa85400fe8a49aef201e9ae Mon Sep 17 00:00:00 2001 From: Frederic Merizen Date: Tue, 5 Feb 2019 11:42:29 +0100 Subject: [PATCH 05/16] [#3356] Prepare for multiples tags per type de champ --- app/models/concerns/tags_substitution_concern.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/app/models/concerns/tags_substitution_concern.rb b/app/models/concerns/tags_substitution_concern.rb index 5b15236d1..898ad8f5b 100644 --- a/app/models/concerns/tags_substitution_concern.rb +++ b/app/models/concerns/tags_substitution_concern.rb @@ -167,12 +167,14 @@ module TagsSubstitutionConcern end def types_de_champ_tags(types_de_champ, available_for_states) - types_de_champ.map do |tdc| - { - libelle: tdc.libelle, - description: tdc.description, - available_for_states: available_for_states - } + types_de_champ.flat_map do |tdc| + [ + { + libelle: tdc.libelle, + description: tdc.description, + available_for_states: available_for_states + } + ] end end From bcfc0f253564db97e9952f3a974a7044773bcee3 Mon Sep 17 00:00:00 2001 From: Frederic Merizen Date: Tue, 5 Feb 2019 13:00:58 +0100 Subject: [PATCH 06/16] [#3356] Let types de champ decide their tags --- app/models/concerns/tags_substitution_concern.rb | 12 ++++-------- app/models/type_de_champ.rb | 9 +++++++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/app/models/concerns/tags_substitution_concern.rb b/app/models/concerns/tags_substitution_concern.rb index 898ad8f5b..ea3414544 100644 --- a/app/models/concerns/tags_substitution_concern.rb +++ b/app/models/concerns/tags_substitution_concern.rb @@ -167,15 +167,11 @@ module TagsSubstitutionConcern end def types_de_champ_tags(types_de_champ, available_for_states) - types_de_champ.flat_map do |tdc| - [ - { - libelle: tdc.libelle, - description: tdc.description, - available_for_states: available_for_states - } - ] + tags = types_de_champ.flat_map(&:tags_for_template) + tags.each do |tag| + tag[:available_for_states] = available_for_states end + tags end def replace_tags(text, dossier) diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index 1b167c67a..d7faa2904 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -174,6 +174,15 @@ class TypeDeChamp < ApplicationRecord end end + def tags_for_template + [ + { + libelle: libelle, + description: description + } + ] + end + private def setup_procedure From 140a65cb3624f58cd78866a26975ab0fcb39d5ef Mon Sep 17 00:00:00 2001 From: Frederic Merizen Date: Tue, 5 Feb 2019 14:44:23 +0100 Subject: [PATCH 07/16] [#3356] Simplify detection of handling champ --- app/models/concerns/tags_substitution_concern.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/models/concerns/tags_substitution_concern.rb b/app/models/concerns/tags_substitution_concern.rb index ea3414544..f91cf2fb5 100644 --- a/app/models/concerns/tags_substitution_concern.rb +++ b/app/models/concerns/tags_substitution_concern.rb @@ -196,8 +196,7 @@ module TagsSubstitutionConcern def replace_type_de_champ_tags(text, types_de_champ, dossier_champs) types_de_champ.inject(text) do |acc, tag| champ = dossier_champs - .select { |dossier_champ| dossier_champ.libelle == tag[:libelle] } - .first + .detect { |dossier_champ| dossier_champ.libelle == tag[:libelle] } replace_tag(acc, tag, champ) end From 656061b21a258302d9a278292c1bffcf4b729dd3 Mon Sep 17 00:00:00 2001 From: Frederic Merizen Date: Tue, 5 Feb 2019 15:19:19 +0100 Subject: [PATCH 08/16] [#3356] Clarify naming --- app/models/concerns/tags_substitution_concern.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/concerns/tags_substitution_concern.rb b/app/models/concerns/tags_substitution_concern.rb index f91cf2fb5..c312f6782 100644 --- a/app/models/concerns/tags_substitution_concern.rb +++ b/app/models/concerns/tags_substitution_concern.rb @@ -193,8 +193,8 @@ module TagsSubstitutionConcern .inject(text) { |acc, (tags, data)| replace_tags_with_values_from_data(acc, tags, data) } end - def replace_type_de_champ_tags(text, types_de_champ, dossier_champs) - types_de_champ.inject(text) do |acc, tag| + def replace_type_de_champ_tags(text, tags, dossier_champs) + tags.inject(text) do |acc, tag| champ = dossier_champs .detect { |dossier_champ| dossier_champ.libelle == tag[:libelle] } From 5bc8bbbaa2522f233a58eba12c4089bebbcfa2b9 Mon Sep 17 00:00:00 2001 From: Frederic Merizen Date: Tue, 5 Feb 2019 15:25:54 +0100 Subject: [PATCH 09/16] [#3356] Let tags handle their own substitution --- .../concerns/tags_substitution_concern.rb | 20 +++++++++---------- app/models/type_de_champ.rb | 8 ++++++-- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/app/models/concerns/tags_substitution_concern.rb b/app/models/concerns/tags_substitution_concern.rb index c312f6782..285f34e25 100644 --- a/app/models/concerns/tags_substitution_concern.rb +++ b/app/models/concerns/tags_substitution_concern.rb @@ -195,35 +195,33 @@ module TagsSubstitutionConcern def replace_type_de_champ_tags(text, tags, dossier_champs) tags.inject(text) do |acc, tag| - champ = dossier_champs - .detect { |dossier_champ| dossier_champ.libelle == tag[:libelle] } - - replace_tag(acc, tag, champ) + replace_tag(acc, tag, dossier_champs) end end def replace_tags_with_values_from_data(text, tags, data) if data.present? tags.inject(text) do |acc, tag| - if tag.key?(:target) - value = data.send(tag[:target]) - else - value = instance_exec(data, &tag[:lambda]) - end - replace_tag(acc, tag, value) + replace_tag(acc, tag, data) end else text end end - def replace_tag(text, tag, value) + def replace_tag(text, tag, data) libelle = Regexp.quote(tag[:libelle]) # allow any kind of space (non-breaking or other) in the tag’s libellé to match any kind of space in the template # (the '\\ |' is there because plain ASCII spaces were escaped by preceding Regexp.quote) libelle.gsub!(/\\ |[[:blank:]]/, "[[:blank:]]") + if tag.key?(:target) + value = data.send(tag[:target]) + else + value = instance_exec(data, &tag[:lambda]) + end + text.gsub(/--#{libelle}--/, value.to_s) end end diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index d7faa2904..ee34fc0bb 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -175,10 +175,14 @@ class TypeDeChamp < ApplicationRecord end def tags_for_template + l = libelle [ { - libelle: libelle, - description: description + libelle: l, + description: description, + lambda: -> (champs) { + champs.detect { |champ| champ.libelle == l } + } } ] end From a8b9da9d3b09201a2692bdf04ca7f8e4e957b1ba Mon Sep 17 00:00:00 2001 From: Frederic Merizen Date: Tue, 5 Feb 2019 15:27:42 +0100 Subject: [PATCH 10/16] [#3356] Remove redundant method --- app/models/concerns/tags_substitution_concern.rb | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/app/models/concerns/tags_substitution_concern.rb b/app/models/concerns/tags_substitution_concern.rb index 285f34e25..a02d26270 100644 --- a/app/models/concerns/tags_substitution_concern.rb +++ b/app/models/concerns/tags_substitution_concern.rb @@ -179,8 +179,8 @@ module TagsSubstitutionConcern return '' end - text = replace_type_de_champ_tags(text, filter_tags(champ_public_tags), dossier.champs) - text = replace_type_de_champ_tags(text, filter_tags(champ_private_tags), dossier.champs_private) + text = replace_tags_with_values_from_data(text, filter_tags(champ_public_tags), dossier.champs) + text = replace_tags_with_values_from_data(text, filter_tags(champ_private_tags), dossier.champs_private) tags_and_datas = [ [dossier_tags, dossier], @@ -193,12 +193,6 @@ module TagsSubstitutionConcern .inject(text) { |acc, (tags, data)| replace_tags_with_values_from_data(acc, tags, data) } end - def replace_type_de_champ_tags(text, tags, dossier_champs) - tags.inject(text) do |acc, tag| - replace_tag(acc, tag, dossier_champs) - end - end - def replace_tags_with_values_from_data(text, tags, data) if data.present? tags.inject(text) do |acc, tag| From 4a3d402a3252c5447befdb02ff2b24676c0cca50 Mon Sep 17 00:00:00 2001 From: Frederic Merizen Date: Tue, 5 Feb 2019 15:30:26 +0100 Subject: [PATCH 11/16] [#3356] No need for special treatment --- app/models/concerns/tags_substitution_concern.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/models/concerns/tags_substitution_concern.rb b/app/models/concerns/tags_substitution_concern.rb index a02d26270..1162beb0e 100644 --- a/app/models/concerns/tags_substitution_concern.rb +++ b/app/models/concerns/tags_substitution_concern.rb @@ -179,10 +179,9 @@ module TagsSubstitutionConcern return '' end - text = replace_tags_with_values_from_data(text, filter_tags(champ_public_tags), dossier.champs) - text = replace_tags_with_values_from_data(text, filter_tags(champ_private_tags), dossier.champs_private) - tags_and_datas = [ + [champ_public_tags, dossier.champs], + [champ_private_tags, dossier.champs_private], [dossier_tags, dossier], [INDIVIDUAL_TAGS, dossier.individual], [ENTREPRISE_TAGS, dossier.etablissement&.entreprise] From d3498e10bdb064d5d635f0b8ccbc91a766006505 Mon Sep 17 00:00:00 2001 From: Frederic Merizen Date: Tue, 5 Feb 2019 16:28:26 +0100 Subject: [PATCH 12/16] [#3356] Let dynamic type handle tag generation --- app/models/type_de_champ.rb | 14 +------------- app/models/types_de_champ/type_de_champ_base.rb | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index ee34fc0bb..727767c6e 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -38,6 +38,7 @@ class TypeDeChamp < ApplicationRecord has_many :types_de_champ, -> { ordered }, foreign_key: :parent_id, class_name: 'TypeDeChamp', dependent: :destroy store_accessor :options, :cadastres, :quartiers_prioritaires, :parcelles_agricoles, :old_pj + delegate :tags_for_template, to: :dynamic_type # TODO simplify after migrating `options` column to (non YAML encoded) JSON class MaybeYaml @@ -174,19 +175,6 @@ class TypeDeChamp < ApplicationRecord end end - def tags_for_template - l = libelle - [ - { - libelle: l, - description: description, - lambda: -> (champs) { - champs.detect { |champ| champ.libelle == l } - } - } - ] - end - private def setup_procedure diff --git a/app/models/types_de_champ/type_de_champ_base.rb b/app/models/types_de_champ/type_de_champ_base.rb index 4f77596c3..fb05bd2ab 100644 --- a/app/models/types_de_champ/type_de_champ_base.rb +++ b/app/models/types_de_champ/type_de_champ_base.rb @@ -1,9 +1,22 @@ class TypesDeChamp::TypeDeChampBase include ActiveModel::Validations - delegate :libelle, to: :@type_de_champ + delegate :description, :libelle, to: :@type_de_champ def initialize(type_de_champ) @type_de_champ = type_de_champ end + + def tags_for_template + l = libelle + [ + { + libelle: l, + description: description, + lambda: -> (champs) { + champs.detect { |champ| champ.libelle == l } + } + } + ] + end end From a3d7c8de552840630fa226246daf3083c26814f6 Mon Sep 17 00:00:00 2001 From: Frederic Merizen Date: Tue, 5 Feb 2019 16:31:23 +0100 Subject: [PATCH 13/16] [Fix #3356] Add tags for primary menu only / secondary menu only --- .../linked_drop_down_list_type_de_champ.rb | 28 +++++++++++++++ .../concern/tags_substitution_concern_spec.rb | 34 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/app/models/types_de_champ/linked_drop_down_list_type_de_champ.rb b/app/models/types_de_champ/linked_drop_down_list_type_de_champ.rb index a90b7a0f0..50f4aa111 100644 --- a/app/models/types_de_champ/linked_drop_down_list_type_de_champ.rb +++ b/app/models/types_de_champ/linked_drop_down_list_type_de_champ.rb @@ -21,6 +21,34 @@ class TypesDeChamp::LinkedDropDownListTypeDeChamp < TypesDeChamp::TypeDeChampBas secondary_options end + def tags_for_template + tags = super + l = libelle + tags.push( + { + libelle: "#{l}/primaire", + description: "#{description} (menu primaire)", + lambda: -> (champs) { + champs + .detect { |champ| champ.libelle == l } + &.primary_value + } + } + ) + tags.push( + { + libelle: "#{l}/secondaire", + description: "#{description} (menu secondaire)", + lambda: -> (champs) { + champs + .detect { |champ| champ.libelle == l } + &.secondary_value + } + } + ) + tags + end + private def check_presence_of_primary_options diff --git a/spec/models/concern/tags_substitution_concern_spec.rb b/spec/models/concern/tags_substitution_concern_spec.rb index f7b95edf2..7c68e1fbf 100644 --- a/spec/models/concern/tags_substitution_concern_spec.rb +++ b/spec/models/concern/tags_substitution_concern_spec.rb @@ -110,6 +110,40 @@ describe TagsSubstitutionConcern, type: :model do end end + context 'when the procedure has a linked drop down menus type de champ' do + let(:types_de_champ) do + [ + create(:type_de_champ_linked_drop_down_list, libelle: 'libelle') + ] + end + + let(:template) { 'tout : --libelle--, primaire : --libelle/primaire--, secondaire : --libelle/secondaire--' } + + context 'and the champ has no value' do + it { is_expected.to eq('tout : , primaire : , secondaire : ') } + end + + context 'and the champ has a primary value' do + before do + c = dossier.champs.detect { |champ| champ.libelle == 'libelle' } + c.primary_value = 'primo' + c.save + end + it { is_expected.to eq('tout : primo / , primaire : primo, secondaire : ') } + end + + context 'and the champ has a primary and secondary value' do + before do + c = dossier.champs.detect { |champ| champ.libelle == 'libelle' } + c.primary_value = 'primo' + c.secondary_value = 'secundo' + c.save + end + + it { is_expected.to eq('tout : primo / secundo, primaire : primo, secondaire : secundo') } + end + end + context 'when the dossier has a motivation' do let(:dossier) { create(:dossier, motivation: 'motivation') } From a255e61556db744516c3879187429b27c6af2c66 Mon Sep 17 00:00:00 2001 From: Frederic Merizen Date: Tue, 5 Feb 2019 16:41:21 +0100 Subject: [PATCH 14/16] [#3356] Improve formatting for menus that only have a primary value --- app/models/champs/linked_drop_down_list_champ.rb | 2 +- spec/models/concern/tags_substitution_concern_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/champs/linked_drop_down_list_champ.rb b/app/models/champs/linked_drop_down_list_champ.rb index cb4ff4ae8..d28b3004f 100644 --- a/app/models/champs/linked_drop_down_list_champ.rb +++ b/app/models/champs/linked_drop_down_list_champ.rb @@ -30,7 +30,7 @@ class Champs::LinkedDropDownListChamp < Champ end def to_s - value.present? ? [primary_value, secondary_value].compact.join(' / ') : "" + value.present? ? [primary_value, secondary_value].select(&:present?).join(' / ') : "" end def for_export diff --git a/spec/models/concern/tags_substitution_concern_spec.rb b/spec/models/concern/tags_substitution_concern_spec.rb index 7c68e1fbf..b2a640214 100644 --- a/spec/models/concern/tags_substitution_concern_spec.rb +++ b/spec/models/concern/tags_substitution_concern_spec.rb @@ -129,7 +129,7 @@ describe TagsSubstitutionConcern, type: :model do c.primary_value = 'primo' c.save end - it { is_expected.to eq('tout : primo / , primaire : primo, secondaire : ') } + it { is_expected.to eq('tout : primo, primaire : primo, secondaire : ') } end context 'and the champ has a primary and secondary value' do From 5715cdaa4c19edc38bdbb681bbd3eab2810d9516 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Tue, 5 Feb 2019 11:29:49 +0100 Subject: [PATCH 15/16] [fix #3363] use organisation_name in dossier summary --- app/models/dossier.rb | 4 ++-- spec/models/dossier_spec.rb | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 2dee58040..f35370ed4 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -186,7 +186,7 @@ class Dossier < ApplicationRecord "Dossier en brouillon répondant à la démarche ", procedure.libelle, " gérée par l'organisme ", - procedure.organisation + procedure.organisation_name ] else parts = [ @@ -195,7 +195,7 @@ class Dossier < ApplicationRecord " sur la démarche ", procedure.libelle, " gérée par l'organisme ", - procedure.organisation + procedure.organisation_name ] end diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 451fdffbe..60e8dab8c 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -236,14 +236,15 @@ describe Dossier do end describe "#text_summary" do - let(:procedure) { create(:procedure, libelle: "Démarche", organisation: "Organisme") } + let(:service) { create(:service, nom: 'nom du service') } + let(:procedure) { create(:procedure, libelle: "Démarche", organisation: "Organisme", service: service) } context 'when the dossier has been en_construction' do let(:dossier) { create :dossier, procedure: procedure, state: Dossier.states.fetch(:en_construction), en_construction_at: "31/12/2010".to_date } subject { dossier.text_summary } - it { is_expected.to eq("Dossier déposé le 31/12/2010 sur la démarche Démarche gérée par l'organisme Organisme") } + it { is_expected.to eq("Dossier déposé le 31/12/2010 sur la démarche Démarche gérée par l'organisme nom du service") } end context 'when the dossier has not been en_construction' do @@ -251,7 +252,7 @@ describe Dossier do subject { dossier.text_summary } - it { is_expected.to eq("Dossier en brouillon répondant à la démarche Démarche gérée par l'organisme Organisme") } + it { is_expected.to eq("Dossier en brouillon répondant à la démarche Démarche gérée par l'organisme nom du service") } end end From f6714cd9a3030f2f4b621eda8df355b2d2eb2279 Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Tue, 5 Feb 2019 14:23:43 +0100 Subject: [PATCH 16/16] If ClamavService fails then raise an error --- app/services/clamav_service.rb | 14 ++++++++++---- spec/services/clamav_service_spec.rb | 20 +++++++++++++++----- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/app/services/clamav_service.rb b/app/services/clamav_service.rb index 1b6ea0c19..7acae2a0a 100644 --- a/app/services/clamav_service.rb +++ b/app/services/clamav_service.rb @@ -1,15 +1,21 @@ class ClamavService def self.safe_file?(file_path) if Rails.env.development? - Rails.logger.info("Rails.env = development => fake scan") # FIXME : remove me return true end FileUtils.chmod(0666, file_path) client = ClamAV::Client.new - response = client.execute(ClamAV::Commands::ScanCommand.new(file_path)) - Rails.logger.info("ClamAV response for #{file_path} : #{response.first.class.name}") # FIXME : remove me - response.first.class != ClamAV::VirusResponse + response = client.execute(ClamAV::Commands::ScanCommand.new(file_path)).first + if response.class == ClamAV::SuccessResponse + true + elsif response.class == ClamAV::VirusResponse + false + elsif response.class == ClamAV::ErrorResponse + raise "ClamAV ErrorResponse : #{response.error_str}" + else + raise "ClamAV unkown response #{response.class.name}" + end end end diff --git a/spec/services/clamav_service_spec.rb b/spec/services/clamav_service_spec.rb index be77ccc3f..4f843e620 100644 --- a/spec/services/clamav_service_spec.rb +++ b/spec/services/clamav_service_spec.rb @@ -4,17 +4,27 @@ describe ClamavService do describe '.safe_file?' do let(:path_file) { '/tmp/plop.txt' } - subject { ClamavService.safe_file? path_file } + subject { ClamavService.safe_file?(path_file) } before do - client = instance_double("ClamAV::Client", :execute => [ClamAV::SuccessResponse]) + client = double("ClamAV::Client", execute: [response]) allow(ClamAV::Client).to receive(:new).and_return(client) + allow(FileUtils).to receive(:chmod).with(0666, path_file).and_return(true) end - it 'change permission of file path' do - allow(FileUtils).to receive(:chmod).with(0666, path_file).and_return(true) + context 'When response type is ClamAV::SuccessResponse' do + let(:response) { ClamAV::SuccessResponse.new("OK") } + it { expect(subject).to eq(true) } + end - subject + context 'When response type is ClamAV::VirusResponse' do + let(:response) { ClamAV::VirusResponse.new("KO", "VirusN4ame") } + it { expect(subject).to eq(false) } + end + + context 'When response type is ClamAV::ErrorResponse' do + let(:response) { ClamAV::ErrorResponse.new("File not found") } + it { expect { subject }.to raise_error("ClamAV ErrorResponse : File not found") } end end end