From 55a9b31b9389f07d26a7034933e1a889a6f235df Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 6 Sep 2018 18:23:27 +0100 Subject: [PATCH 1/5] Cleanup SIRET champ --- .../stylesheets/new_design/spinner.scss | 1 - app/controllers/champs/siret_controller.rb | 68 +++++++++------ app/javascript/new_design/champs/siret.js | 35 -------- app/javascript/new_design/spinner.js | 16 ++++ app/javascript/packs/application.js | 2 +- app/javascript/shared/utils.js | 11 +++ app/views/champs/siret/index.js.erb | 5 -- app/views/champs/siret/show.js.erb | 6 ++ .../siret/_delete_etablissement.html.haml | 5 -- .../champs/siret/_etablissement.html.haml | 21 ++++- .../dossiers/editable_champs/_siret.html.haml | 10 +-- config/routes.rb | 2 +- .../champs/siret_controller_spec.rb | 82 +++++++++++++++++++ 13 files changed, 183 insertions(+), 81 deletions(-) delete mode 100644 app/javascript/new_design/champs/siret.js create mode 100644 app/javascript/new_design/spinner.js create mode 100644 app/javascript/shared/utils.js delete mode 100644 app/views/champs/siret/index.js.erb create mode 100644 app/views/champs/siret/show.js.erb delete mode 100644 app/views/shared/champs/siret/_delete_etablissement.html.haml create mode 100644 spec/controllers/champs/siret_controller_spec.rb diff --git a/app/assets/stylesheets/new_design/spinner.scss b/app/assets/stylesheets/new_design/spinner.scss index 94e9b5866..fba2cee82 100644 --- a/app/assets/stylesheets/new_design/spinner.scss +++ b/app/assets/stylesheets/new_design/spinner.scss @@ -12,7 +12,6 @@ } .right-spinner { - display: none; position: absolute; top: 3.7em; right: 1.2em; diff --git a/app/controllers/champs/siret_controller.rb b/app/controllers/champs/siret_controller.rb index e1227fa64..dd1d73b18 100644 --- a/app/controllers/champs/siret_controller.rb +++ b/app/controllers/champs/siret_controller.rb @@ -1,31 +1,51 @@ class Champs::SiretController < ApplicationController - def index - siret, champ_id = params.required([:siret, :champ_id]) - @champ = Champs::SiretChamp.find(champ_id) - @etablissement = @champ.etablissement - if siret == 'blank' - if @etablissement - @etablissement.mark_for_destruction - end - @blank = true - elsif siret == 'invalid' - if @etablissement - @etablissement.mark_for_destruction - end - @error = "Le numéro de SIRET doit comporter exactement 14 chiffres." - else - etablissement_attributes = ApiEntrepriseService.get_etablissement_params_for_siret(siret, @champ.dossier.procedure_id) - if etablissement_attributes.present? - @etablissement = @champ.build_etablissement(etablissement_attributes) - @etablissement.champ = @champ + before_action :authenticate_logged_user! + + def show + @position = params[:position] + extract_siret + find_etablisement + + if @siret.empty? + @etablissement&.mark_for_destruction + elsif @siret.present? && @siret.length == 14 + etablissement = find_etablisement_with_siret + if etablissement.present? + @etablissement = etablissement else - message = ['Nous n’avons pas trouvé d’établissement correspondant à ce numéro de SIRET.'] - message << helpers.link_to('Plus d’informations', "https://faq.demarches-simplifiees.fr/article/4-erreur-siret", target: '_blank') - @error = helpers.safe_join(message, ' ') + @etablissement&.mark_for_destruction + @siret = :not_found end + else + @etablissement&.mark_for_destruction + @siret = :invalid end - respond_to do |format| - format.js + end + + private + + def extract_siret + if params[:dossier].key?(:champs_attributes) + @siret = params[:dossier][:champs_attributes][@position][:value] + @attribute = "dossier[champs_attributes][#{@position}][etablissement_attributes]" + else + @siret = params[:dossier][:champs_private_attributes][@position][:value] + @attribute = "dossier[champs_private_attributes][#{@position}][etablissement_attributes]" + end + end + + def find_etablisement + if params[:champ_id].present? + champ = Champ.find_by(dossier_id: logged_user.dossiers, id: params[:champ_id]) + @etablissement = champ&.etablissement + end + @procedure_id = champ&.dossier&.procedure_id || 'aperçu' + end + + def find_etablisement_with_siret + etablissement_attributes = ApiEntrepriseService.get_etablissement_params_for_siret(@siret, @procedure_id) + if etablissement_attributes.present? + Etablissement.new(etablissement_attributes) end end end diff --git a/app/javascript/new_design/champs/siret.js b/app/javascript/new_design/champs/siret.js deleted file mode 100644 index 9b3e29a75..000000000 --- a/app/javascript/new_design/champs/siret.js +++ /dev/null @@ -1,35 +0,0 @@ -import $ from 'jquery'; - -$(document).on('input', '[data-siret]', evt => { - const input = $(evt.target); - const value = input.val(); - const url = input.data('siret'); - - switch (value.length) { - case 0: - input.removeData('invalid'); - $.get(url, { siret: 'blank' }); - break; - case 14: - input.attr('disabled', true); - $('.spinner').show(); - $.get(url, { siret: value }).then( - () => { - input.removeData('invalid'); - input.removeAttr('disabled'); - $('.spinner').hide(); - }, - () => { - input.removeAttr('disabled'); - input.data('invalid', true); - $('.spinner').hide(); - } - ); - break; - default: - if (!input.data('invalid')) { - input.data('invalid', true); - $.get(url, { siret: 'invalid' }); - } - } -}); diff --git a/app/javascript/new_design/spinner.js b/app/javascript/new_design/spinner.js new file mode 100644 index 000000000..7c92ca53b --- /dev/null +++ b/app/javascript/new_design/spinner.js @@ -0,0 +1,16 @@ +import Rails from 'rails-ujs'; +import { show, hide } from '../shared/utils'; + +const { delegate } = Rails; + +function showSpinner() { + [...document.querySelectorAll('.spinner')].forEach(show); +} + +function hideSpinner() { + [...document.querySelectorAll('.spinner')].forEach(hide); +} + +delegate(document, '[data-spinner]', 'ajax:complete', hideSpinner); +delegate(document, '[data-spinner]', 'ajax:stopped', hideSpinner); +delegate(document, '[data-spinner]', 'ajax:send', showSpinner); diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 196074a15..f953f6100 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -12,13 +12,13 @@ import '../shared/safari-11-file-xhr-workaround'; import '../shared/autocomplete'; import '../shared/remote-input'; +import '../new_design/spinner'; import '../new_design/buttons'; import '../new_design/form-validation'; import '../new_design/carto'; import '../new_design/select2'; import '../new_design/champs/linked-drop-down-list'; -import '../new_design/champs/siret'; import { toggleCondidentielExplanation } from '../new_design/avis'; import { togglePrintMenu } from '../new_design/dossier'; diff --git a/app/javascript/shared/utils.js b/app/javascript/shared/utils.js new file mode 100644 index 000000000..9339dd07f --- /dev/null +++ b/app/javascript/shared/utils.js @@ -0,0 +1,11 @@ +export function show({ classList }) { + classList.remove('hidden'); +} + +export function hide({ classList }) { + classList.add('hidden'); +} + +export function toggle({ classList }) { + classList.toggle('hidden'); +} diff --git a/app/views/champs/siret/index.js.erb b/app/views/champs/siret/index.js.erb deleted file mode 100644 index 3b74d6a35..000000000 --- a/app/views/champs/siret/index.js.erb +++ /dev/null @@ -1,5 +0,0 @@ -<% if @blank || @error %> - <%= render_to_element("#etablissement-for-#{@champ.id}", partial: 'shared/champs/siret/delete_etablissement', locals: { message: @error, position: @champ.order_place, etablissement: @etablissement }) %> -<% else %> - <%= render_to_element("#etablissement-for-#{@champ.id}", partial: 'shared/champs/siret/etablissement', locals: { position: @champ.order_place, etablissement: @etablissement }) %> -<% end %> diff --git a/app/views/champs/siret/show.js.erb b/app/views/champs/siret/show.js.erb new file mode 100644 index 000000000..f0ab71e4f --- /dev/null +++ b/app/views/champs/siret/show.js.erb @@ -0,0 +1,6 @@ +<%= render_to_element(".siret-info-#{@position}", + partial: 'shared/champs/siret/etablissement', + locals: { + siret: @siret, + attribute: @attribute, + etablissement: @etablissement }) %> diff --git a/app/views/shared/champs/siret/_delete_etablissement.html.haml b/app/views/shared/champs/siret/_delete_etablissement.html.haml deleted file mode 100644 index 1d443c0d2..000000000 --- a/app/views/shared/champs/siret/_delete_etablissement.html.haml +++ /dev/null @@ -1,5 +0,0 @@ -.mandatory= message -- if etablissement.present? - - champ_attributes = etablissement.champ.private? ? 'champs_private_attributes' : 'champs_attributes' - = fields_for "dossier[#{champ_attributes}][#{position}][etablissement_attributes]", etablissement do |form| - = form.hidden_field :_destroy diff --git a/app/views/shared/champs/siret/_etablissement.html.haml b/app/views/shared/champs/siret/_etablissement.html.haml index 893a5ef2a..0b1e81850 100644 --- a/app/views/shared/champs/siret/_etablissement.html.haml +++ b/app/views/shared/champs/siret/_etablissement.html.haml @@ -1,4 +1,17 @@ -= render partial: 'shared/dossiers/editable_champs/etablissement_titre', locals: { etablissement: etablissement } -- champ_attributes = etablissement.champ.private? ? 'champs_private_attributes' : 'champs_attributes' -= fields_for "dossier[#{champ_attributes}][#{position}][etablissement_attributes]", etablissement do |form| - = render partial: 'shared/dossiers/editable_champs/etablissement', locals: { form: form, signature: etablissement.sign } +- case siret +- when :invalid + Le numéro de SIRET doit comporter exactement 14 chiffres. + +- when :not_found + Nous n’avons pas trouvé d’établissement correspondant à ce numéro de SIRET. + = link_to('Plus d’informations', "https://faq.demarches-simplifiees.fr/article/4-erreur-siret", target: '_blank') + +- else + - if siret.present? && siret == etablissement&.siret + = render partial: 'shared/dossiers/editable_champs/etablissement_titre', locals: { etablissement: etablissement } + = fields_for attribute, etablissement do |form| + = render partial: 'shared/dossiers/editable_champs/etablissement', locals: { form: form, signature: etablissement.sign } + + - elsif etablissement.present? + = fields_for attribute, etablissement do |form| + = form.hidden_field :_destroy diff --git a/app/views/shared/dossiers/editable_champs/_siret.html.haml b/app/views/shared/dossiers/editable_champs/_siret.html.haml index b67817792..740061365 100644 --- a/app/views/shared/dossiers/editable_champs/_siret.html.haml +++ b/app/views/shared/dossiers/editable_champs/_siret.html.haml @@ -1,11 +1,11 @@ = form.text_field :value, placeholder: champ.libelle, class: 'small-margin', - data: { siret: champ.persisted? ? champs_siret_path(format: :js, champ_id: champ) : nil }, + data: { remote: true, debounce: true, url: champs_siret_path(form.index), params: { champ_id: champ&.id }.to_query, spinner: true }, required: champ.mandatory? -.spinner.right-spinner -%div{ id: "etablissement-for-#{champ.id}" } +.spinner.right-spinner.hidden +%div{ class: "siret-info-#{form.index}" } - if champ.etablissement.present? = render partial: 'shared/dossiers/editable_champs/etablissement_titre', locals: { etablissement: champ.etablissement } - = form.fields_for :etablissement do |form| - = render partial: 'shared/dossiers/editable_champs/etablissement', locals: { form: form, signature: champ.etablissement.sign } + = form.fields_for :etablissement do |form| + = render partial: 'shared/dossiers/editable_champs/etablissement', locals: { form: form, signature: champ.etablissement.sign } diff --git a/config/routes.rb b/config/routes.rb index f440e3f6f..12b5dab91 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -110,7 +110,7 @@ Rails.application.routes.draw do end namespace :champs do - get ':champ_id/siret' => 'siret#index', as: 'siret' + get ':position/siret', to: 'siret#show', as: :siret get ':position/dossier_link', to: 'dossier_link#show', as: :dossier_link end diff --git a/spec/controllers/champs/siret_controller_spec.rb b/spec/controllers/champs/siret_controller_spec.rb new file mode 100644 index 000000000..6d848a117 --- /dev/null +++ b/spec/controllers/champs/siret_controller_spec.rb @@ -0,0 +1,82 @@ +require 'spec_helper' + +describe Champs::SiretController, type: :controller do + let(:user) { create(:user) } + let(:procedure) { create(:procedure, :published) } + + describe '#show' do + let(:dossier) { create(:dossier, user: user, procedure: procedure) } + let(:params) do + { + dossier: { + champs_attributes: { + '1' => { value: "#{siret}" } + } + }, + position: '1' + } + end + let(:siret) { '' } + + context 'when user is connected' do + render_views + before { sign_in user } + + context 'when siret empty' do + before { + get :show, params: params, format: 'js' + } + + it 'empty info message' do + expect(response.body).to include('.siret-info-1') + expect(response.body).to include('innerHTML = ""') + end + end + + context 'when siret invalid' do + let(:siret) { '1234' } + before { + get :show, params: params, format: 'js' + } + + it 'invalid error' do + expect(response.body).to include('Le numéro de SIRET doit comporter exactement 14 chiffres.') + end + end + + context 'when siret not found' do + let(:siret) { '0' * 14 } + before { + expect(subject).to receive(:find_etablisement_with_siret).and_return(false) + get :show, params: params, format: 'js' + } + + it 'not found error' do + expect(response.body).to include('Nous n’avons pas trouvé d’établissement correspondant à ce numéro de SIRET.') + end + end + + context 'when siret found' do + let(:siret) { etablissement.siret } + let(:etablissement) { build(:etablissement) } + before { + expect(subject).to receive(:find_etablisement_with_siret).and_return(etablissement) + get :show, params: params, format: 'js' + } + + it 'etablissement info message' do + expect(response.body).to include(etablissement.entreprise_raison_sociale) + expect(response.body).to include(etablissement.entreprise_capital_social.to_s) + end + end + end + + context 'when user is not connected' do + before { + get :show, params: { position: '1' }, format: 'js' + } + + it { expect(response.code).to eq('401') } + end + end +end From f923881cef048b533db15801a5db3b6a5e7e029f Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 12 Sep 2018 17:15:22 +0200 Subject: [PATCH 2/5] Support: fix task --- lib/tasks/2018_09_12_ftap.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks/2018_09_12_ftap.rake b/lib/tasks/2018_09_12_ftap.rake index 2bb6e3f07..26df40615 100644 --- a/lib/tasks/2018_09_12_ftap.rake +++ b/lib/tasks/2018_09_12_ftap.rake @@ -1,5 +1,5 @@ namespace :'2018_09_12_ftap' do - task :run do + task run: :environment do procedure = Procedure.find(5812) dossiers = procedure.dossiers.all From 0b6debf9a6f0b22016734f5934e11a866566e3da Mon Sep 17 00:00:00 2001 From: gregoirenovel Date: Wed, 12 Sep 2018 18:31:02 +0200 Subject: [PATCH 3/5] Fix a typo --- app/views/demandes/new.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/demandes/new.html.haml b/app/views/demandes/new.html.haml index ee4997b35..215cfafaf 100644 --- a/app/views/demandes/new.html.haml +++ b/app/views/demandes/new.html.haml @@ -67,7 +67,7 @@ required: true = label_tag :nb_of_dossiers do - Nombre de dossiers usagers qui seront démateerialisés, par an ? (Mettez 0 si vous ne savez pas) + Nombre de dossiers usagers qui seront dématérialisés, par an ? (Mettez 0 si vous ne savez pas) %span.mandatory * = number_field_tag :nb_of_dossiers, nil, required: true From bfe72402354c321b691038b949fd48c20e8eec0a Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 12 Sep 2018 16:42:04 +0200 Subject: [PATCH 4/5] Fix event bubbling on Mobile Safari --- app/assets/stylesheets/application.scss | 14 ++++++++++++++ app/assets/stylesheets/new_design/common.scss | 14 ++++++++++++++ app/views/layouts/application.html.haml | 2 +- app/views/layouts/new_application.html.haml | 2 +- 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 46390dbaf..df644ab8b 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -83,6 +83,20 @@ form { overflow: hidden; } +// Mobile Safari doesn't bubble mouse events by default, unless: +// +// - the target element of the event is a link or a form field. +// - the target element, or any of its ancestors up to but not including the , has an explicit event handler set for any of the mouse events. This event handler may be an empty function. +// - the target element, or any of its ancestors up to and including the document has a cursor: pointer CSS declarations. +// +// (See https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html) +// +// This is a problem for us, because we bind a lot of click events as +// `document.on('click', '.my-element', …)` – which requires proper bubbling. +.ios #wrap { + cursor: pointer; +} + #wrap::after { content: ""; display: block; diff --git a/app/assets/stylesheets/new_design/common.scss b/app/assets/stylesheets/new_design/common.scss index c68d0181e..ff13f26ae 100644 --- a/app/assets/stylesheets/new_design/common.scss +++ b/app/assets/stylesheets/new_design/common.scss @@ -18,6 +18,20 @@ select { min-height: 100%; } +// Mobile Safari doesn't bubble mouse events by default, unless: +// +// - the target element of the event is a link or a form field. +// - the target element, or any of its ancestors up to but not including the , has an explicit event handler set for any of the mouse events. This event handler may be an empty function. +// - the target element, or any of its ancestors up to and including the document has a cursor: pointer CSS declarations. +// +// (See https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html) +// +// This is a problem for us, because we bind a lot of click events as +// `document.on('click', '.my-element', …)` – which requires proper bubbling. +.ios .page-wrapper { + cursor: pointer; +} + h1 { font-size: 36px; font-weight: bold; diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 5ea2ebf56..81397c33f 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -20,7 +20,7 @@ DATA = [{ sentry: #{raw(sentry_config)} }]; - %body + %body{ class: browser.platform.ios? ? 'ios' : nil } = render partial: 'layouts/outdated_browser_banner' = render partial: 'layouts/pre_maintenance' - if staging? diff --git a/app/views/layouts/new_application.html.haml b/app/views/layouts/new_application.html.haml index 164b26452..833127d93 100644 --- a/app/views/layouts/new_application.html.haml +++ b/app/views/layouts/new_application.html.haml @@ -25,7 +25,7 @@ DATA = [{ sentry: #{raw(sentry_config)} }]; - %body + %body{ class: browser.platform.ios? ? 'ios' : nil } .page-wrapper = render partial: "layouts/outdated_browser_banner" = render partial: 'layouts/pre_maintenance' From a94397a70c38cd7db69b2fb91070794a96b33159 Mon Sep 17 00:00:00 2001 From: Frederic Merizen Date: Thu, 13 Sep 2018 10:21:45 +0200 Subject: [PATCH 5/5] [Fix #2562] Make dossier filters case insensitive --- .../new_gestionnaire/procedures_controller.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controllers/new_gestionnaire/procedures_controller.rb b/app/controllers/new_gestionnaire/procedures_controller.rb index 968c04e3b..8078a9947 100644 --- a/app/controllers/new_gestionnaire/procedures_controller.rb +++ b/app/controllers/new_gestionnaire/procedures_controller.rb @@ -221,19 +221,19 @@ module NewGestionnaire current_filters.map do |filter| case filter['table'] when 'self' - dossiers.where("? LIKE ?", filter['column'], "%#{filter['value']}%") + dossiers.where("? ILIKE ?", filter['column'], "%#{filter['value']}%") when 'france_connect_information' dossiers .includes(user: :france_connect_information) - .where("? LIKE ?", "france_connect_informations.#{filter['column']}", "%#{filter['value']}%") + .where("? ILIKE ?", "france_connect_informations.#{filter['column']}", "%#{filter['value']}%") when 'type_de_champ', 'type_de_champ_private' relation = filter['table'] == 'type_de_champ' ? :champs : :champs_private dossiers .includes(relation) .where("champs.type_de_champ_id = ?", filter['column'].to_i) - .where("champs.value LIKE ?", "%#{filter['value']}%") + .where("champs.value ILIKE ?", "%#{filter['value']}%") when 'entreprise' table = 'etablissement' if filter['column'] == 'date_creation' @@ -244,12 +244,12 @@ module NewGestionnaire else dossiers .includes(table) - .where("#{table.pluralize}.entreprise_#{filter['column']} LIKE ?", "%#{filter['value']}%") + .where("#{table.pluralize}.entreprise_#{filter['column']} ILIKE ?", "%#{filter['value']}%") end when 'user', 'etablissement' dossiers .includes(filter['table']) - .where("#{filter['table'].pluralize}.#{filter['column']} LIKE ?", "%#{filter['value']}%") + .where("#{filter['table'].pluralize}.#{filter['column']} ILIKE ?", "%#{filter['value']}%") end.pluck(:id) end.reduce(:&) end