diff --git a/app/components/attachment/edit_component.rb b/app/components/attachment/edit_component.rb index 5ae74730c..b8116772b 100644 --- a/app/components/attachment/edit_component.rb +++ b/app/components/attachment/edit_component.rb @@ -58,7 +58,7 @@ class Attachment::EditComponent < ApplicationComponent direct_upload: @direct_upload, id: champ&.input_id, aria: { describedby: champ&.describedby_id }, - data: { auto_attach_url: helpers.auto_attach_url(form, form.object) } + data: { auto_attach_url: helpers.auto_attach_url(form.object) } } end diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index b650015ee..d6f4cd03f 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -214,7 +214,11 @@ module Instructeurs end dossier.save dossier.log_modifier_annotations!(current_instructeur) - redirect_to annotations_privees_instructeur_dossier_path(procedure, dossier) + + respond_to do |format| + format.html { redirect_to annotations_privees_instructeur_dossier_path(procedure, dossier) } + format.turbo_stream + end end def print @@ -252,17 +256,22 @@ module Instructeurs private + def dossier_scope + if action_name == 'update_annotations' + Dossier + .where(id: current_instructeur.dossiers.visible_by_administration) + .or(Dossier.where(id: current_user.dossiers.for_procedure_preview)) + else + current_instructeur.dossiers.visible_by_administration + end + end + def dossier - @dossier ||= current_instructeur - .dossiers - .visible_by_administration - .find(params[:dossier_id]) + @dossier ||= dossier_scope.find(params[:dossier_id]) end def dossier_with_champs - @dossier ||= current_instructeur - .dossiers - .visible_by_administration + @dossier ||= dossier_scope .with_champs .with_annotations .find(params[:dossier_id]) @@ -304,7 +313,7 @@ module Instructeurs end def redirect_on_dossier_not_found - if !current_instructeur.dossiers.visible_by_administration.exists?(id: params[:dossier_id]) + if !dossier_scope.exists?(id: params[:dossier_id]) redirect_to instructeur_procedure_path(procedure) end end diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index d777e6143..4d6d6821b 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -5,12 +5,10 @@ module Users layout 'procedure_context', only: [:identite, :update_identite, :siret, :update_siret] ACTIONS_ALLOWED_TO_ANY_USER = [:index, :recherche, :new, :transferer_all] - ACTIONS_ALLOWED_TO_OWNER_OR_INVITE = [:show, :demande, :messagerie, :brouillon, :update_brouillon, :modifier, :update, :create_commentaire, :papertrail] - ACTIONS_ALLOWED_TO_OWNER_OR_INVITE_HIDDEN = [:restore] + ACTIONS_ALLOWED_TO_OWNER_OR_INVITE = [:show, :demande, :messagerie, :brouillon, :update_brouillon, :modifier, :update, :create_commentaire, :papertrail, :restore] - before_action :ensure_ownership!, except: ACTIONS_ALLOWED_TO_ANY_USER + ACTIONS_ALLOWED_TO_OWNER_OR_INVITE + ACTIONS_ALLOWED_TO_OWNER_OR_INVITE_HIDDEN + before_action :ensure_ownership!, except: ACTIONS_ALLOWED_TO_ANY_USER + ACTIONS_ALLOWED_TO_OWNER_OR_INVITE before_action :ensure_ownership_or_invitation!, only: ACTIONS_ALLOWED_TO_OWNER_OR_INVITE - before_action :ensure_ownership_or_invitation_hidden!, only: ACTIONS_ALLOWED_TO_OWNER_OR_INVITE_HIDDEN before_action :ensure_dossier_can_be_updated, only: [:update_identite, :update_brouillon, :modifier, :update] before_action :forbid_invite_submission!, only: [:update_brouillon] before_action :forbid_closed_submission!, only: [:update_brouillon] @@ -298,7 +296,7 @@ module Users end def restore - hidden_dossier.restore(current_user) + dossier.restore(current_user) flash.notice = t('users.dossiers.restore') redirect_to dossiers_path end @@ -363,16 +361,22 @@ module Users }) end - def dossier - @dossier ||= Dossier.visible_by_user.find(params[:id] || params[:dossier_id]) + def dossier_scope + if action_name == 'update_brouillon' + Dossier.visible_by_user.or(Dossier.for_procedure_preview) + elsif action_name == 'restore' + Dossier.hidden_by_user + else + Dossier.visible_by_user + end end - def hidden_dossier - @hidden_dossier ||= Dossier.hidden_by_user.find(params[:id] || params[:dossier_id]) + def dossier + @dossier ||= dossier_scope.find(params[:id] || params[:dossier_id]) end def dossier_with_champs - Dossier.with_champs.visible_by_user.find(params[:id]) + dossier_scope.with_champs.find(params[:id]) end def should_change_groupe_instructeur? @@ -449,12 +453,6 @@ module Users end end - def ensure_ownership_or_invitation_hidden! - if !current_user.owns_or_invite?(hidden_dossier) - forbidden! - end - end - def forbid_invite_submission! if passage_en_construction? && !current_user.owns?(dossier) forbidden! diff --git a/app/helpers/champ_helper.rb b/app/helpers/champ_helper.rb index 0381e9c32..d2fc3d4ee 100644 --- a/app/helpers/champ_helper.rb +++ b/app/helpers/champ_helper.rb @@ -20,12 +20,17 @@ module ChampHelper simple_format(auto_linked_text, {}, sanitize: false) end - def auto_attach_url(form, object) - if object.is_a?(Champ) && object.persisted? && object.public? + def auto_attach_url(object) + if object.is_a?(Champ) champs_piece_justificative_url(object.id) end end + def autosave_available?(champ) + # FIXME: enable autosave on champs private? once we figured out how to batch audit events + champ.dossier.brouillon? && !champ.repetition? + end + def geo_area_label(geo_area) case geo_area.source when GeoArea.sources.fetch(:cadastre) diff --git a/app/helpers/dossier_helper.rb b/app/helpers/dossier_helper.rb index c64d1e87a..91c2b4360 100644 --- a/app/helpers/dossier_helper.rb +++ b/app/helpers/dossier_helper.rb @@ -29,10 +29,6 @@ module DossierHelper new_dossier_url(procedure_id: revision.procedure.id, brouillon: revision.draft? ? true : nil) end - def autosave_available?(dossier) - dossier.brouillon? - end - def dossier_submission_is_closed?(dossier) dossier.brouillon? && dossier.procedure.close? end diff --git a/app/policies/champ_policy.rb b/app/policies/champ_policy.rb index a3af2f225..b0e720341 100644 --- a/app/policies/champ_policy.rb +++ b/app/policies/champ_policy.rb @@ -37,7 +37,7 @@ class ChampPolicy < ApplicationPolicy resolved_scope = resolved_scope.or(instructeur_clause) end - resolved_scope + resolved_scope.or(joined_scope.where('dossiers.for_procedure_preview': true)) end end end diff --git a/app/views/administrateurs/procedures/apercu.html.haml b/app/views/administrateurs/procedures/apercu.html.haml index 53bd9beb7..17ca22944 100644 --- a/app/views/administrateurs/procedures/apercu.html.haml +++ b/app/views/administrateurs/procedures/apercu.html.haml @@ -15,9 +15,4 @@ - if @tab == 'dossier' = render partial: "shared/dossiers/edit", locals: { dossier: @dossier } - else - .container - = form_for @dossier, url: '', method: :get, html: { class: 'form' } do |f| - = f.fields_for :champs_private, @dossier.champs_private do |champ_form| - - champ = champ_form.object - = render partial: "shared/dossiers/editable_champs/editable_champ", - locals: { champ: champ, form: champ_form } + = render partial: "shared/dossiers/edit_annotations", locals: { dossier: @dossier, seen_at: nil } diff --git a/app/views/instructeurs/dossiers/_autosave.html.haml b/app/views/instructeurs/dossiers/_autosave.html.haml new file mode 100644 index 000000000..73b60b790 --- /dev/null +++ b/app/views/instructeurs/dossiers/_autosave.html.haml @@ -0,0 +1,17 @@ +.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… + diff --git a/app/views/instructeurs/dossiers/annotations_privees.html.haml b/app/views/instructeurs/dossiers/annotations_privees.html.haml index 4341a0c98..3212cac3c 100644 --- a/app/views/instructeurs/dossiers/annotations_privees.html.haml +++ b/app/views/instructeurs/dossiers/annotations_privees.html.haml @@ -2,16 +2,5 @@ = render partial: "header", locals: { dossier: @dossier } -#dossier-annotations-privees.container - - if @dossier.champs_private.present? - %section - = form_for @dossier, url: annotations_instructeur_dossier_path(@dossier.procedure, @dossier), html: { class: 'form', multipart: true } do |f| - - @dossier.champs_private.each do |champ| - = fields_for champ.input_name, champ do |form| - = render partial: "shared/dossiers/editable_champs/editable_champ", locals: { form: form, champ: champ, seen_at: @annotations_privees_seen_at } - - .send-wrapper - = f.submit 'Sauvegarder', class: 'button primary send', data: { disable: true } - - - else - %h2.empty-text Aucune annotation privée +#dossier-annotations-privees + = render partial: "shared/dossiers/edit_annotations", locals: { dossier: @dossier, seen_at: @annotations_privees_seen_at } diff --git a/app/views/shared/dossiers/_edit.html.haml b/app/views/shared/dossiers/_edit.html.haml index a195538bd..3b0002ddd 100644 --- a/app/views/shared/dossiers/_edit.html.haml +++ b/app/views/shared/dossiers/_edit.html.haml @@ -1,9 +1,7 @@ .dossier-edit.container = render partial: "shared/dossiers/submit_is_over", locals: { dossier: dossier } - - if dossier.for_procedure_preview? - - form_options = { url: '', method: :get } - - elsif dossier.brouillon? + - if dossier.brouillon? - form_options = { url: brouillon_dossier_url(dossier), method: :patch } - else - form_options = { url: modifier_dossier_url(dossier), method: :patch } @@ -14,10 +12,7 @@ %p.mandatory-explanation= t('utils.asterisk_html') - if dossier.brouillon? %p.mandatory-explanation - - if autosave_available?(dossier) - = t('views.shared.dossiers.edit.autosave') - - else - Pour enregistrer votre dossier et le reprendre plus tard, cliquez sur le bouton « Enregistrer le brouillon » en bas à gauche du formulaire. + = t('views.shared.dossiers.edit.autosave') - if dossier.france_connect_information.present? = render partial: "shared/dossiers/france_connect_informations", locals: { user_information: dossier.france_connect_information } - if notice_url(dossier.procedure).present? @@ -28,7 +23,7 @@ %hr - if dossier.show_groupe_instructeur_selector? - %span{ data: autosave_available?(dossier) ? { controller: 'autosave', autosave_url_value: brouillon_dossier_path(dossier) } : {} } + %span{ data: dossier.brouillon? ? { controller: 'autosave', autosave_url_value: brouillon_dossier_path(dossier) } : {} } = f.label :groupe_instructeur_id do = dossier.procedure.routing_criteria_name %span.mandatory * @@ -44,13 +39,7 @@ .dossier-edit-sticky-footer .send-dossier-actions-bar - if dossier.brouillon? - - if autosave_available?(dossier) - = render partial: 'users/dossiers/autosave' - - else - = f.button 'Enregistrer le brouillon', - formnovalidate: true, - class: 'button send secondary', - data: { 'disable-with': "Envoi en cours…" } + = render partial: 'users/dossiers/autosave' - if dossier.can_transition_to_en_construction? = f.button t('views.shared.dossiers.edit.submit_dossier'), diff --git a/app/views/shared/dossiers/_edit_annotations.html.haml b/app/views/shared/dossiers/_edit_annotations.html.haml new file mode 100644 index 000000000..163dd5862 --- /dev/null +++ b/app/views/shared/dossiers/_edit_annotations.html.haml @@ -0,0 +1,19 @@ +.container.dossier-edit + - if dossier.champs_private.present? + %section + = form_for dossier, url: annotations_instructeur_dossier_path(dossier.procedure, dossier), html: { class: 'form', multipart: true } do |f| + - dossier.champs_private.each do |champ| + = fields_for champ.input_name, champ do |form| + = render partial: "shared/dossiers/editable_champs/editable_champ", locals: { form: form, champ: champ, seen_at: seen_at } + + - if !dossier.for_procedure_preview? + - if autosave_available?(dossier.champs_private.first) + .dossier-edit-sticky-footer + .send-dossier-actions-bar + = render partial: 'autosave' + - else + .send-wrapper + = f.submit 'Sauvegarder', class: 'button primary send', data: { disable: true } + + - else + %h2.empty-text Aucune annotation privée diff --git a/app/views/shared/dossiers/editable_champs/_editable_champ.html.haml b/app/views/shared/dossiers/editable_champs/_editable_champ.html.haml index 32334011d..d33042f15 100644 --- a/app/views/shared/dossiers/editable_champs/_editable_champ.html.haml +++ b/app/views/shared/dossiers/editable_champs/_editable_champ.html.haml @@ -1,5 +1,4 @@ -- autosave_controller = autosave_available?(champ.dossier) && !champ.repetition? ? { controller: 'autosave', autosave_url_value: brouillon_dossier_path(champ.dossier) } : {} -.editable-champ{ class: "editable-champ-#{champ.type_champ}", id: champ.input_group_id, data: autosave_controller } +.editable-champ{ class: "editable-champ-#{champ.type_champ}", id: champ.input_group_id, data: autosave_available?(champ) ? { controller: 'autosave' } : {} } - if champ.repetition? %h3.header-subsection= champ.libelle - if champ.description.present? diff --git a/config/locales/en.yml b/config/locales/en.yml index 0458720c6..741aaf0e7 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -140,6 +140,9 @@ 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 diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 2fce3244c..46d80f6cd 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -135,6 +135,9 @@ 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