feat(dossier): autosave en construction
This commit is contained in:
parent
d35ceb7214
commit
d6f5be622c
14 changed files with 66 additions and 82 deletions
|
@ -188,19 +188,15 @@ module Users
|
|||
|
||||
def update
|
||||
@dossier = dossier_with_champs
|
||||
errors = update_dossier_and_compute_errors
|
||||
|
||||
if check_conditions?
|
||||
assign_dossier_and_check_conditions
|
||||
render :update_brouillon
|
||||
else
|
||||
errors = update_dossier_and_compute_errors
|
||||
if errors.present?
|
||||
flash.now.alert = errors
|
||||
end
|
||||
|
||||
if errors.present?
|
||||
flash.now.alert = errors
|
||||
render :modifier
|
||||
else
|
||||
redirect_to demande_dossier_path(@dossier)
|
||||
end
|
||||
respond_to do |format|
|
||||
format.html { render :modifier }
|
||||
format.turbo_stream { render layout: false }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -308,18 +304,6 @@ module Users
|
|||
|
||||
private
|
||||
|
||||
def check_conditions?
|
||||
params[:check_conditions] && champs_params[:dossier]
|
||||
end
|
||||
|
||||
def assign_dossier_and_check_conditions
|
||||
@dossier.assign_attributes(champs_params[:dossier])
|
||||
# We need to set dossier on champs, otherwise dossier will be reloaded
|
||||
@dossier.champs.each do |champ|
|
||||
champ.association(:dossier).target = @dossier
|
||||
end
|
||||
end
|
||||
|
||||
# if the status tab is filled, then this tab
|
||||
# else first filled tab
|
||||
# else en-cours
|
||||
|
|
|
@ -42,7 +42,10 @@ export class AutosaveController extends ApplicationController {
|
|||
this.#latestPromise = Promise.resolve();
|
||||
this.onGlobal('autosave:retry', () => this.didRequestRetry());
|
||||
this.on('change', (event) => this.onChange(event));
|
||||
this.on('input', (event) => this.onInput(event));
|
||||
|
||||
if (this.saveOnInput) {
|
||||
this.on('input', (event) => this.onInput(event));
|
||||
}
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
|
@ -80,7 +83,8 @@ export class AutosaveController extends ApplicationController {
|
|||
this.debounce(this.enqueueAutosaveRequest, AUTOSAVE_DEBOUNCE_DELAY);
|
||||
} else if (
|
||||
isSelectElement(target) ||
|
||||
isCheckboxOrRadioInputElement(target)
|
||||
isCheckboxOrRadioInputElement(target) ||
|
||||
(!this.saveOnInput && isTextInputElement(target))
|
||||
) {
|
||||
this.enqueueAutosaveRequest();
|
||||
}
|
||||
|
@ -99,6 +103,10 @@ export class AutosaveController extends ApplicationController {
|
|||
}
|
||||
}
|
||||
|
||||
private get saveOnInput() {
|
||||
return !!this.form?.dataset.saveOnInput;
|
||||
}
|
||||
|
||||
private didRequestRetry() {
|
||||
if (this.#needsRetry) {
|
||||
this.enqueueAutosaveRequest();
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
.autosave.autosave-state-idle{ data: { controller: 'autosave-status' } }
|
||||
%p.autosave-explanation
|
||||
%span.autosave-explanation-text
|
||||
= t('views.instructeurs.dossiers.autosave.autosave_draft')
|
||||
|
||||
%p.autosave-status.succeeded
|
||||
%span.autosave-icon.icon.accept
|
||||
%span.autosave-label
|
||||
= t('views.instructeurs.dossiers.autosave.autosave_confirmation')
|
||||
|
||||
%p.autosave-status.failed
|
||||
%span.autosave-icon ⚠️
|
||||
%span.autosave-label Impossible d’enregistrer les annotations
|
||||
%button.button.small.autosave-retry{ type: :button, data: { action: 'autosave-status#onClickRetryButton', autosave_status_target: 'retryButton' } }
|
||||
%span.autosave-retry-label réessayer
|
||||
%span.autosave-retrying-label enregistrement en cours…
|
||||
|
|
@ -1,13 +1,19 @@
|
|||
.autosave.autosave-state-idle{ data: { controller: 'autosave-status' } }
|
||||
%p.autosave-explanation
|
||||
%span.autosave-explanation-text
|
||||
= t('views.users.dossiers.autosave.autosave_draft')
|
||||
= link_to t('views.users.dossiers.autosave.more_infos'), FAQ_AUTOSAVE_URL, target: '_blank', rel: 'noopener', class: 'autosave-more-infos'
|
||||
- if dossier.brouillon?
|
||||
= t('views.users.dossiers.autosave.draft_explanation')
|
||||
- else
|
||||
= t('views.users.dossiers.autosave.explanation')
|
||||
= link_to t('views.users.dossiers.autosave.more_information'), FAQ_AUTOSAVE_URL, target: '_blank', rel: 'noopener', class: 'autosave-more-infos'
|
||||
|
||||
%p.autosave-status.succeeded
|
||||
%span.autosave-icon.icon.accept
|
||||
%span.autosave-label
|
||||
= t('views.users.dossiers.autosave.autosave_confirmation')
|
||||
- if dossier.brouillon?
|
||||
= t('views.users.dossiers.autosave.draft_confirmation')
|
||||
- else
|
||||
= t('views.users.dossiers.autosave.confirmation')
|
||||
= link_to t('views.users.dossiers.autosave.more_information'), FAQ_AUTOSAVE_URL, target: '_blank', rel: 'noopener', class: 'autosave-more-infos'
|
||||
|
||||
%p.autosave-status.failed
|
|
@ -2,7 +2,7 @@
|
|||
= render partial: "shared/dossiers/submit_is_over", locals: { dossier: dossier }
|
||||
|
||||
- if dossier.brouillon?
|
||||
- form_options = { url: brouillon_dossier_url(dossier), method: :patch }
|
||||
- form_options = { url: brouillon_dossier_url(dossier), method: :patch, data: { save_on_input: true } }
|
||||
- else
|
||||
- form_options = { url: modifier_dossier_url(dossier), method: :patch }
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
|||
%hr
|
||||
|
||||
- if dossier.show_groupe_instructeur_selector?
|
||||
%span{ data: { controller: dossier.brouillon? ? 'autosave' : 'check-conditions' } }
|
||||
%span{ data: { controller: 'autosave' } }
|
||||
= f.label :groupe_instructeur_id do
|
||||
= dossier.procedure.routing_criteria_name
|
||||
%span.mandatory *
|
||||
|
@ -38,20 +38,14 @@
|
|||
- if !dossier.for_procedure_preview?
|
||||
.dossier-edit-sticky-footer
|
||||
.send-dossier-actions-bar
|
||||
- if dossier.brouillon?
|
||||
= render partial: 'users/dossiers/autosave'
|
||||
= render partial: 'shared/dossiers/autosave', locals: { dossier: dossier }
|
||||
|
||||
- if dossier.can_transition_to_en_construction?
|
||||
= f.button t('views.shared.dossiers.edit.submit_dossier'),
|
||||
name: :submit_draft,
|
||||
value: true,
|
||||
class: 'button send primary',
|
||||
disabled: !current_user.owns?(dossier),
|
||||
data: { 'disable-with': "Envoi en cours…" }
|
||||
|
||||
- else
|
||||
= f.button t('views.shared.dossiers.edit.save_changes'),
|
||||
- if dossier.can_transition_to_en_construction?
|
||||
= f.button t('views.shared.dossiers.edit.submit_dossier'),
|
||||
name: :submit_draft,
|
||||
value: true,
|
||||
class: 'button send primary',
|
||||
disabled: !current_user.owns?(dossier),
|
||||
data: { 'disable-with': "Envoi en cours…" }
|
||||
|
||||
- if dossier.brouillon? && !current_user.owns?(dossier)
|
||||
|
|
5
app/views/users/dossiers/update.turbo_stream.haml
Normal file
5
app/views/users/dossiers/update.turbo_stream.haml
Normal file
|
@ -0,0 +1,5 @@
|
|||
- @dossier.champs.filter(&:conditional?).each do |champ|
|
||||
- if champ.visible?
|
||||
= turbo_stream.show champ.input_group_id
|
||||
- else
|
||||
= turbo_stream.hide champ.input_group_id
|
|
@ -137,7 +137,6 @@ en:
|
|||
edit:
|
||||
autosave: Your file is automatically saved after each modification. You can close the window at any time and pick up where you left off later.
|
||||
submit_dossier: Submit the file
|
||||
save_changes: Save the changes of the file
|
||||
messages:
|
||||
form:
|
||||
send_message: "Send message"
|
||||
|
@ -151,9 +150,6 @@ en:
|
|||
edit_identity: "Edit identity data"
|
||||
instructeurs:
|
||||
dossiers:
|
||||
autosave:
|
||||
autosave_draft: Your annotations are automatically saved.
|
||||
autosave_confirmation: Annotations saved
|
||||
tab_steps:
|
||||
to_follow: to follow
|
||||
total: total
|
||||
|
@ -192,8 +188,10 @@ en:
|
|||
dossiers:
|
||||
archived_dossier: "Your file will be kept %{duree_conservation_dossiers_dans_ds} more months"
|
||||
autosave:
|
||||
autosave_draft: Your draft is automatically saved.
|
||||
autosave_confirmation: Draft saved
|
||||
explanation: Your file is automatically saved.
|
||||
confirmation: File saved
|
||||
draft_explanation: Your draft is automatically saved.
|
||||
draft_confirmation: Draft saved
|
||||
more_information: More informations
|
||||
identite:
|
||||
identity_data: Identity data
|
||||
|
|
|
@ -132,7 +132,6 @@ fr:
|
|||
edit:
|
||||
autosave: Votre dossier est enregistré automatiquement après chaque modification. Vous pouvez à tout moment fermer la fenêtre et reprendre plus tard là où vous en étiez.
|
||||
submit_dossier: Déposer le dossier
|
||||
save_changes: Enregistrer les modifications du dossier
|
||||
messages:
|
||||
form:
|
||||
send_message: "Envoyer le message"
|
||||
|
@ -146,9 +145,6 @@ fr:
|
|||
edit_identity: "Modifier l’identité"
|
||||
instructeurs:
|
||||
dossiers:
|
||||
autosave:
|
||||
autosave_draft: Vos annotations sont automatiquement enregistrées.
|
||||
autosave_confirmation: Annotations enregistrées
|
||||
tab_steps:
|
||||
to_follow: à suivre
|
||||
total: au total
|
||||
|
@ -188,10 +184,11 @@ fr:
|
|||
dossiers:
|
||||
archived_dossier: "Votre dossier sera conservé %{duree_conservation_dossiers_dans_ds} mois supplémentaire"
|
||||
autosave:
|
||||
autosave_draft: Votre brouillon est automatiquement enregistré.
|
||||
autosave_confirmation: Brouillon enregistré
|
||||
more_information: More informations
|
||||
more_infos: En savoir plus
|
||||
explanation: Votre dossier est automatiquement enregistré.
|
||||
confirmation: Dossier enregistré
|
||||
draft_explanation: Votre brouillon est automatiquement enregistré.
|
||||
draft_confirmation: Brouillon enregistré
|
||||
more_information: En savoir plus
|
||||
identite:
|
||||
identity_data: Données d’identité
|
||||
civility: Civilité
|
||||
|
|
|
@ -649,7 +649,7 @@ describe Users::DossiersController, type: :controller do
|
|||
expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction))
|
||||
end
|
||||
|
||||
it { is_expected.to redirect_to(demande_dossier_path(dossier)) }
|
||||
it { is_expected.to have_http_status(:ok) }
|
||||
|
||||
context 'when only a single file champ are modified' do
|
||||
# A bug in ActiveRecord causes records changed through grand-parent <-> parent <-> child
|
||||
|
@ -726,7 +726,7 @@ describe Users::DossiersController, type: :controller do
|
|||
it 'does not raise any errors' do
|
||||
subject
|
||||
|
||||
expect(response).to redirect_to(demande_dossier_path(dossier))
|
||||
expect(response).to have_http_status(:ok)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -741,7 +741,7 @@ describe Users::DossiersController, type: :controller do
|
|||
|
||||
it { expect(first_champ.reload.value).to eq('beautiful value') }
|
||||
it { expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction)) }
|
||||
it { expect(response).to redirect_to(demande_dossier_path(dossier)) }
|
||||
it { expect(response).to have_http_status(:ok) }
|
||||
end
|
||||
|
||||
context 'when the dossier is followed by an instructeur' do
|
||||
|
|
|
@ -120,7 +120,8 @@ describe 'The routing', js: true do
|
|||
click_on 'Modifier mon dossier'
|
||||
|
||||
fill_in litteraire_user.dossiers.first.champs.first.libelle, with: 'some value'
|
||||
click_on 'Enregistrer les modifications du dossier'
|
||||
blur
|
||||
expect(page).to have_css('span', text: 'Dossier enregistré', visible: true)
|
||||
log_out
|
||||
|
||||
# the litteraires instructeurs should have a notification
|
||||
|
@ -214,7 +215,7 @@ describe 'The routing', js: true do
|
|||
expect(page).not_to have_selector("option", text: "Groupe inactif")
|
||||
|
||||
select(new_group, from: 'dossier_groupe_instructeur_id')
|
||||
click_on "Enregistrer les modifications du dossier"
|
||||
expect(page).to have_css('span', text: 'Dossier enregistré', visible: true)
|
||||
expect(page).to have_text(new_group)
|
||||
|
||||
log_out
|
||||
|
|
|
@ -390,6 +390,9 @@ describe 'The user' do
|
|||
expect(page).to have_no_css('label', text: 'tonnage', visible: true)
|
||||
|
||||
fill_in('age', with: '18')
|
||||
blur
|
||||
expect(page).to have_css('span', text: 'Dossier enregistré', visible: true)
|
||||
|
||||
# the champ keeps their previous value so they are all displayed
|
||||
expect(page).to have_css('label', text: 'permis de conduire', visible: true)
|
||||
expect(page).to have_css('label', text: 'tonnage', visible: true)
|
||||
|
|
|
@ -48,8 +48,10 @@ describe 'Dossier details:' do
|
|||
expect(page).to have_current_path(dossier_path(dossier))
|
||||
end
|
||||
|
||||
it_behaves_like 'the user can edit the submitted demande'
|
||||
it_behaves_like 'the user can send messages to the instructeur'
|
||||
context 'with js', js: true do
|
||||
it_behaves_like 'the user can edit the submitted demande'
|
||||
it_behaves_like 'the user can send messages to the instructeur'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
|
|
@ -10,9 +10,12 @@ RSpec.shared_examples 'the user can edit the submitted demande' do
|
|||
|
||||
expect(page).to have_current_path(modifier_dossier_path(dossier))
|
||||
fill_in('Texte obligatoire', with: 'Nouveau texte')
|
||||
click_on 'Enregistrer les modifications du dossier'
|
||||
blur
|
||||
expect(page).to have_css('span', text: 'Dossier enregistré', visible: true)
|
||||
|
||||
click_on 'Demande'
|
||||
expect(page).to have_current_path(demande_dossier_path(dossier))
|
||||
|
||||
expect(page).to have_content('Nouveau texte')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -127,7 +127,7 @@ describe 'Invitations' do
|
|||
expect(page).to have_text("user_invite@exemple.fr")
|
||||
end
|
||||
|
||||
context 'as an invited user' do
|
||||
context 'as an invited user', js: true do
|
||||
before do
|
||||
navigate_to_invited_dossier(invite)
|
||||
expect(page).to have_current_path(dossier_path(invite.dossier))
|
||||
|
|
Loading…
Reference in a new issue