diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index a48d3b33b..527bf34c7 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -16,6 +16,7 @@ class ApplicationController < ActionController::Base before_action :staging_authenticate before_action :set_active_storage_host + before_action :setup_javascript_settings before_action :setup_tracking helper_method :multiple_devise_profile_connect?, :instructeur_signed_in?, :current_instructeur, @@ -114,6 +115,10 @@ class ApplicationController < ActionController::Base ActiveStorage::Current.host = request.base_url end + def setup_javascript_settings + gon.autosave = Rails.application.config.ds_autosave + end + def setup_tracking gon.matomo = matomo_config gon.sentry = sentry_config diff --git a/app/javascript/new_design/autosave.js b/app/javascript/new_design/autosave.js index 70476407c..6ad125465 100644 --- a/app/javascript/new_design/autosave.js +++ b/app/javascript/new_design/autosave.js @@ -10,9 +10,10 @@ import { removeClass } from '@utils'; -const AUTOSAVE_DEBOUNCE_DELAY = 3000; // 3 seconds -const AUTOSAVE_STATUS_VISIBLE_DURATION = 6000; // 5 seconds +const AUTOSAVE_DEBOUNCE_DELAY = gon.autosave.debounce_delay; +const AUTOSAVE_STATUS_VISIBLE_DURATION = gon.autosave.status_visible_duration; +// Create a controller responsible for queuing autosave operations. const autosaveController = new AutosaveController(AUTOSAVE_DEBOUNCE_DELAY); // Whenever a 'change' event is triggered on one of the form inputs, try to autosave. diff --git a/config/application.rb b/config/application.rb index b42657278..65080acaf 100644 --- a/config/application.rb +++ b/config/application.rb @@ -40,8 +40,14 @@ module TPS Administrate::ApplicationController.helper(TPS::Application.helpers) end - config.ds_weekly_overview = ENV['APP_NAME'] == 'tps' config.middleware.use Rack::Attack config.middleware.use Flipper::Middleware::Memoizer, preload_all: true + + config.ds_weekly_overview = ENV['APP_NAME'] == 'tps' + + config.ds_autosave = { + debounce_delay: 3000, + status_visible_duration: 6000 + } end end diff --git a/config/environments/test.rb b/config/environments/test.rb index 0f05338b6..7f100ca27 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -53,4 +53,9 @@ Rails.application.configure do # Raises error for missing translations # config.action_view.raise_on_missing_translations = true + + config.ds_autosave = { + debounce_delay: 500, + status_visible_duration: 500 + } end diff --git a/spec/features/users/brouillon_spec.rb b/spec/features/users/brouillon_spec.rb index b6c284cbb..90bea2630 100644 --- a/spec/features/users/brouillon_spec.rb +++ b/spec/features/users/brouillon_spec.rb @@ -186,6 +186,47 @@ feature 'The user' do expect(page).to have_no_text('RIB.pdf') end + context 'when the draft autosave is enabled' do + before do + Flipper.enable_actor(:autosave_dossier_draft, user) + end + + scenario 'autosave a draft', js: true do + log_in(user, simple_procedure) + fill_individual + + expect(page).not_to have_button('Enregistrer le brouillon') + expect(page).to have_content('Votre brouillon est automatiquement enregistré') + + fill_in('texte obligatoire', with: 'a valid user input') + blur + + expect(page).to have_css('span', text: 'Brouillon enregistré', visible: true) + + visit current_path + expect(page).to have_field('texte obligatoire', with: 'a valid user input') + end + + scenario 'retry on autosave error', js: true do + log_in(user, simple_procedure) + fill_individual + + # Test autosave failure + logout(:user) # Make the subsequent autosave requests fail + fill_in('texte obligatoire', with: 'a valid user input') + blur + expect(page).to have_css('span', text: 'Impossible d’enregistrer le brouillon', visible: true) + + # Test that retrying after a failure works + login_as(user, scope: :user) # Make the autosave requests work again + click_on 'réessayer' + expect(page).to have_css('span', text: 'Brouillon enregistré', visible: true) + + visit current_path + expect(page).to have_field('texte obligatoire', with: 'a valid user input') + end + end + private def log_in(user, procedure)