diff --git a/app/controllers/submit_form_controller.rb b/app/controllers/submit_form_controller.rb index fcd0fdc8..6cbe16f5 100644 --- a/app/controllers/submit_form_controller.rb +++ b/app/controllers/submit_form_controller.rb @@ -7,11 +7,11 @@ class SubmitFormController < ApplicationController skip_before_action :authenticate_user! skip_authorization_check + before_action :load_submitter, only: %i[show update completed] + CONFIG_KEYS = [].freeze def show - @submitter = Submitter.find_by!(slug: params[:slug]) - submission = @submitter.submission return redirect_to submit_form_completed_path(@submitter.slug) if @submitter.completed_at? @@ -50,26 +50,24 @@ class SubmitFormController < ApplicationController end def update - submitter = Submitter.find_by!(slug: params[:slug]) - - if submitter.completed_at? + if @submitter.completed_at? return render json: { error: I18n.t('form_has_been_completed_already') }, status: :unprocessable_entity end - if submitter.template.archived_at? || submitter.submission.archived_at? + if @submitter.template.archived_at? || @submitter.submission.archived_at? return render json: { error: I18n.t('form_has_been_archived') }, status: :unprocessable_entity end - if submitter.submission.expired? + if @submitter.submission.expired? return render json: { error: I18n.t('form_has_been_expired') }, status: :unprocessable_entity end - if submitter.declined_at? + if @submitter.declined_at? return render json: { error: I18n.t('form_has_been_declined') }, status: :unprocessable_entity end - Submitters::SubmitValues.call(submitter, params, request) + Submitters::SubmitValues.call(@submitter, params, request) head :ok rescue Submitters::SubmitValues::RequiredFieldError => e @@ -80,14 +78,16 @@ class SubmitFormController < ApplicationController render json: { error: e.message }, status: :unprocessable_entity end - def completed - @submitter = Submitter.completed.find_by!(slug: params[:submit_form_slug]) - end + def completed; end def success; end private + def load_submitter + @submitter = Submitter.find_by!(slug: params[:slug] || params[:submit_form_slug]) + end + def build_attachments_index(submission) ActiveStorage::Attachment.where(record: submission.submitters, name: :attachments) .preload(:blob).index_by(&:uuid) diff --git a/app/controllers/templates_preferences_controller.rb b/app/controllers/templates_preferences_controller.rb index a9221f7b..78399e6a 100644 --- a/app/controllers/templates_preferences_controller.rb +++ b/app/controllers/templates_preferences_controller.rb @@ -25,7 +25,7 @@ class TemplatesPreferencesController < ApplicationController documents_copy_email_attach_documents documents_copy_email_reply_to completed_notification_email_attach_documents completed_redirect_url - submitters_order + submitters_order require_phone_2fa completed_notification_email_subject completed_notification_email_body completed_notification_email_enabled completed_notification_email_attach_audit] + [completed_message: %i[title body], diff --git a/app/javascript/elements/fetch_form.js b/app/javascript/elements/fetch_form.js new file mode 100644 index 00000000..b3378a63 --- /dev/null +++ b/app/javascript/elements/fetch_form.js @@ -0,0 +1,36 @@ +export default class extends HTMLElement { + connectedCallback () { + this.form.addEventListener('submit', (e) => { + e.preventDefault() + + this.submit() + }) + + if (this.dataset.onload === 'true') { + this.form.querySelector('button').click() + } + } + + submit () { + fetch(this.form.action, { + method: this.form.method, + body: new FormData(this.form) + }).then(async (resp) => { + if (!resp.ok) { + try { + const data = JSON.parse(await resp.text()) + + if (data.error) { + alert(data.error) + } + } catch (err) { + console.error(err) + } + } + }) + } + + get form () { + return this.querySelector('form') + } +} diff --git a/app/javascript/form.js b/app/javascript/form.js index 2e07f033..cbd26d1a 100644 --- a/app/javascript/form.js +++ b/app/javascript/form.js @@ -3,11 +3,13 @@ import { createApp, reactive } from 'vue' import Form from './submission_form/form' import DownloadButton from './elements/download_button' import ToggleSubmit from './elements/toggle_submit' +import FetchForm from './elements/fetch_form' const safeRegisterElement = (name, element, options = {}) => !window.customElements.get(name) && window.customElements.define(name, element, options) safeRegisterElement('download-button', DownloadButton) safeRegisterElement('toggle-submit', ToggleSubmit) +safeRegisterElement('fetch-form', FetchForm) safeRegisterElement('submission-form', class extends HTMLElement { connectedCallback () { this.appElem = document.createElement('div') diff --git a/app/views/submissions/_detailed_form.html.erb b/app/views/submissions/_detailed_form.html.erb index 37a2a88a..847ac5a8 100644 --- a/app/views/submissions/_detailed_form.html.erb +++ b/app/views/submissions/_detailed_form.html.erb @@ -31,7 +31,7 @@ "> - " id="detailed_phone_<%= item['uuid'] %>"> + <%= tag.input type: 'tel', pattern: '^\+[0-9\s\-]+$', oninvalid: "this.value ? this.setCustomValidity('#{t('use_international_format_1xxx_')}') : ''", oninput: "this.setCustomValidity('')", name: 'submission[1][submitters][][phone]', autocomplete: 'off', class: 'base-input !h-10 mt-1.5 w-full', placeholder: local_assigns[:require_phone_2fa] == true ? t(:phone) : "#{t('phone')} (#{t('optional')})", id: "detailed_phone_#{item['uuid']}", required: local_assigns[:require_phone_2fa] == true %> diff --git a/app/views/submissions/new.html.erb b/app/views/submissions/new.html.erb index 5de57e76..a7bcc8f6 100644 --- a/app/views/submissions/new.html.erb +++ b/app/views/submissions/new.html.erb @@ -1,10 +1,11 @@ +<% require_phone_2fa = @template.preferences['require_phone_2fa'] == true %> <%= render 'shared/turbo_modal_large', title: params[:selfsign] ? t('add_recipients') : t('add_new_recipients') do %> - <% options = [[t('via_email'), 'email'], [t('via_phone'), 'phone'], [t('detailed'), 'detailed'], [t('upload_list'), 'list']].compact %> + <% options = [require_phone_2fa ? nil : [t('via_email'), 'email'], require_phone_2fa ? nil : [t('via_phone'), 'phone'], [t('detailed'), 'detailed'], [t('upload_list'), 'list']].compact %>
<% options.each_with_index do |(label, value), index| %>
- <%= radio_button_tag 'option', value, value == 'email', class: 'peer hidden', data: { action: 'change:toggle-visible#trigger' } %> + <%= radio_button_tag 'option', value, value == (require_phone_2fa ? 'detailed' : 'email'), class: 'peer hidden', data: { action: 'change:toggle-visible#trigger' } %> @@ -13,14 +14,16 @@
-
- <%= render 'email_form', template: @template %> -
- -