diff --git a/app/javascript/controllers/turbo_input_controller.tsx b/app/javascript/controllers/turbo_input_controller.tsx new file mode 100644 index 000000000..d194a7f3c --- /dev/null +++ b/app/javascript/controllers/turbo_input_controller.tsx @@ -0,0 +1,22 @@ +import { httpRequest } from '@utils'; + +import { ApplicationController } from './application_controller'; + +export class TurboInputController extends ApplicationController { + static values = { + url: String + }; + + declare readonly urlValue: string; + + connect(): void { + this.on('input', () => this.debounce(this.load, 200)); + } + + private load(): void { + const target = this.element as HTMLInputElement; + const url = new URL(this.urlValue, document.baseURI); + url.searchParams.append(target.name, target.value); + httpRequest(url.toString()).turbo(); + } +} diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index e34fa2a8c..945d83857 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -8,7 +8,6 @@ import * as Turbo from '@hotwired/turbo'; import '../shared/activestorage/ujs'; import '../shared/remote-poller'; import '../shared/safari-11-file-xhr-workaround'; -import '../shared/remote-input'; import '../shared/franceconnect'; import '../shared/toggle-target'; import '../shared/ujs-error-handling'; @@ -19,6 +18,7 @@ import { } from '../controllers/react_controller'; import { TurboEventController } from '../controllers/turbo_event_controller'; import { GeoAreaController } from '../controllers/geo_area_controller'; +import { TurboInputController } from '../controllers/turbo_input_controller'; import '../new_design/dropdown'; import '../new_design/form-validation'; @@ -96,6 +96,7 @@ const Stimulus = Application.start(); Stimulus.register('react', ReactController); Stimulus.register('turbo-event', TurboEventController); Stimulus.register('geo-area', GeoAreaController); +Stimulus.register('turbo-input', TurboInputController); // Expose globals window.DS = window.DS || DS; diff --git a/app/javascript/shared/remote-input.js b/app/javascript/shared/remote-input.js deleted file mode 100644 index e265a1835..000000000 --- a/app/javascript/shared/remote-input.js +++ /dev/null @@ -1,21 +0,0 @@ -import { delegate, fire, debounce } from '@utils'; - -const remote = 'data-remote'; -const inputChangeSelector = `input[${remote}], textarea[${remote}]`; - -// This is a patch for ujs remote handler. Its purpose is to add -// a debounced input listener. -function handleRemote(event) { - const element = this; - - if (isRemote(element)) { - fire(element, 'change', event); - } -} - -function isRemote(element) { - const value = element.getAttribute(remote); - return value && value !== 'false'; -} - -delegate('input', inputChangeSelector, debounce(handleRemote, 200)); diff --git a/app/views/champs/dossier_link/show.js.erb b/app/views/champs/dossier_link/show.js.erb deleted file mode 100644 index cdf84195a..000000000 --- a/app/views/champs/dossier_link/show.js.erb +++ /dev/null @@ -1,3 +0,0 @@ -<%= render_to_element("##{@champ.input_group_id} .help-block", - partial: 'shared/champs/dossier_link/help_block', - locals: { id: @linked_dossier_id }) %> diff --git a/app/views/champs/dossier_link/show.turbo_stream.haml b/app/views/champs/dossier_link/show.turbo_stream.haml new file mode 100644 index 000000000..6cb304fca --- /dev/null +++ b/app/views/champs/dossier_link/show.turbo_stream.haml @@ -0,0 +1 @@ += turbo_stream.update dom_id(@champ, :help_block), partial: 'shared/champs/dossier_link/help_block', locals: { id: @linked_dossier_id } diff --git a/app/views/champs/siret/show.js.erb b/app/views/champs/siret/show.js.erb deleted file mode 100644 index 85d3c51c9..000000000 --- a/app/views/champs/siret/show.js.erb +++ /dev/null @@ -1,3 +0,0 @@ -<%= render_to_element("##{@champ.input_group_id} .siret-info", - partial: 'shared/champs/siret/etablissement', - locals: { siret: @siret, etablissement: @etablissement }) %> diff --git a/app/views/champs/siret/show.turbo_stream.haml b/app/views/champs/siret/show.turbo_stream.haml new file mode 100644 index 000000000..be1c3a1c8 --- /dev/null +++ b/app/views/champs/siret/show.turbo_stream.haml @@ -0,0 +1 @@ += turbo_stream.update dom_id(@champ, :siret_info), partial: 'shared/champs/siret/etablissement', locals: { siret: @siret, etablissement: @etablissement } diff --git a/app/views/shared/dossiers/editable_champs/_dossier_link.html.haml b/app/views/shared/dossiers/editable_champs/_dossier_link.html.haml index f3a72c1ed..4e0ad4832 100644 --- a/app/views/shared/dossiers/editable_champs/_dossier_link.html.haml +++ b/app/views/shared/dossiers/editable_champs/_dossier_link.html.haml @@ -5,7 +5,7 @@ placeholder: "Numéro de dossier", autocomplete: 'off', required: champ.mandatory?, - data: { remote: true, url: champs_dossier_link_path(champ.id) } + data: { controller: 'turbo-input', turbo_input_url_value: champs_dossier_link_path(champ.id) } - .help-block + .help-block{ id: dom_id(champ, :help_block) } = render partial: 'shared/champs/dossier_link/help_block', locals: { id: champ.value } diff --git a/app/views/shared/dossiers/editable_champs/_siret.html.haml b/app/views/shared/dossiers/editable_champs/_siret.html.haml index 402a20428..fd8681112 100644 --- a/app/views/shared/dossiers/editable_champs/_siret.html.haml +++ b/app/views/shared/dossiers/editable_champs/_siret.html.haml @@ -2,11 +2,11 @@ id: champ.input_id, aria: { describedby: champ.describedby_id }, placeholder: champ.libelle, - data: { remote: true, debounce: true, url: champs_siret_path(champ.id), spinner: true }, + data: { controller: 'turbo-input', turbo_input_url_value: champs_siret_path(champ.id) }, required: champ.mandatory?, pattern: "[0-9]{14}", title: "Le numéro de SIRET doit comporter exactement 14 chiffres" .spinner.right.hidden -.siret-info +.siret-info{ id: dom_id(champ, :siret_info) } - if champ.etablissement.present? = render partial: 'shared/dossiers/editable_champs/etablissement_titre', locals: { etablissement: champ.etablissement } diff --git a/spec/controllers/champs/dossier_link_controller_spec.rb b/spec/controllers/champs/dossier_link_controller_spec.rb index 319fad897..59a0fc29f 100644 --- a/spec/controllers/champs/dossier_link_controller_spec.rb +++ b/spec/controllers/champs/dossier_link_controller_spec.rb @@ -27,33 +27,33 @@ describe Champs::DossierLinkController, type: :controller do context 'when the dossier exist' do before do - get :show, params: params, format: :js, xhr: true + get :show, params: params, format: :turbo_stream end it 'renders the procedure name' do expect(response.body).to include('Dossier en brouillon') expect(response.body).to include(procedure.libelle) expect(response.body).to include(procedure.organisation) - expect(response.body).to include("##{champ.input_group_id} .help-block") + expect(response.body).to include(ActionView::RecordIdentifier.dom_id(champ, :help_block)) end end context 'when the dossier does not exist' do let(:dossier_id) { '13' } before do - get :show, params: params, format: :js, xhr: true + get :show, params: params, format: :turbo_stream end it 'renders error message' do expect(response.body).to include('Ce dossier est inconnu') - expect(response.body).to include("##{champ.input_group_id} .help-block") + expect(response.body).to include(ActionView::RecordIdentifier.dom_id(champ, :help_block)) end end end context 'when user is not connected' do before do - get :show, params: { champ_id: champ.id }, format: :js, xhr: true + get :show, params: { champ_id: champ.id }, format: :turbo_stream end it { expect(response.code).to eq('401') } diff --git a/spec/controllers/champs/siret_controller_spec.rb b/spec/controllers/champs/siret_controller_spec.rb index 820d4703d..f7ae6a832 100644 --- a/spec/controllers/champs/siret_controller_spec.rb +++ b/spec/controllers/champs/siret_controller_spec.rb @@ -37,7 +37,7 @@ describe Champs::SiretController, type: :controller do end context 'when the SIRET is empty' do - subject! { get :show, params: params, format: :js, xhr: true } + subject! { get :show, params: params, format: :turbo_stream } it 'clears the etablissement and SIRET on the model' do champ.reload @@ -46,15 +46,14 @@ describe Champs::SiretController, type: :controller do end it 'clears any information or error message' do - expect(response.body).to include("##{champ.input_group_id} .siret-info") - expect(response.body).to include('innerHTML = ""') + expect(response.body).to include(ActionView::RecordIdentifier.dom_id(champ, :siret_info)) end end context 'when the SIRET is invalid' do let(:siret) { '1234' } - subject! { get :show, params: params, format: :js, xhr: true } + subject! { get :show, params: params, format: :turbo_stream } it 'clears the etablissement and SIRET on the model' do champ.reload @@ -71,7 +70,7 @@ describe Champs::SiretController, type: :controller do let(:siret) { '82161143100015' } let(:api_etablissement_status) { 503 } - subject! { get :show, params: params, format: :js, xhr: true } + subject! { get :show, params: params, format: :turbo_stream } it 'clears the etablissement and SIRET on the model' do champ.reload @@ -88,7 +87,7 @@ describe Champs::SiretController, type: :controller do let(:siret) { '00000000000000' } let(:api_etablissement_status) { 404 } - subject! { get :show, params: params, format: :js, xhr: true } + subject! { get :show, params: params, format: :turbo_stream } it 'clears the etablissement and SIRET on the model' do champ.reload @@ -106,7 +105,7 @@ describe Champs::SiretController, type: :controller do let(:api_etablissement_status) { 200 } let(:api_etablissement_body) { File.read('spec/fixtures/files/api_entreprise/etablissements.json') } - subject! { get :show, params: params, format: :js, xhr: true } + subject! { get :show, params: params, format: :turbo_stream } it 'populates the etablissement and SIRET on the model' do champ.reload @@ -119,7 +118,7 @@ describe Champs::SiretController, type: :controller do end context 'when user is not signed in' do - subject! { get :show, params: { champ_id: champ.id }, format: :js, xhr: true } + subject! { get :show, params: { champ_id: champ.id }, format: :turbo_stream } it { expect(response.code).to eq('401') } end