diff --git a/app/controllers/submissions_resend_email_controller.rb b/app/controllers/submissions_resend_email_controller.rb new file mode 100644 index 00000000..ddc526db --- /dev/null +++ b/app/controllers/submissions_resend_email_controller.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +class SubmissionsResendEmailController < ApplicationController + load_and_authorize_resource :submission + + before_action do + authorize!(:manage, :resend_all) + authorize!(:update, @submission) + end + + def create + submitters = @submission.submitters.reject(&:completed_at?).select { |s| s.email.present? && !s.declined_at? } + + if Wabosign.multitenant? + recent_submitter_ids = + SubmissionEvent.where(submitter_id: submitters.map(&:id), + event_type: 'send_email', + created_at: 10.hours.ago..Time.current).pluck(:submitter_id).to_set + + submitters = submitters.reject { |s| recent_submitter_ids.include?(s.id) } + end + + submitters.each do |submitter| + SendSubmitterInvitationEmailJob.perform_async('submitter_id' => submitter.id) + + submitter.sent_at ||= Time.current + submitter.save! + end + + notice = + if submitters.empty? + I18n.t('email_has_been_sent_already') + else + I18n.t('emails_have_been_sent_to_n_recipients', count: submitters.size) + end + + redirect_back(fallback_location: submission_path(@submission), notice:) + end +end diff --git a/app/controllers/submissions_unarchive_controller.rb b/app/controllers/submissions_unarchive_controller.rb index 5a60a60b..8bd320a6 100644 --- a/app/controllers/submissions_unarchive_controller.rb +++ b/app/controllers/submissions_unarchive_controller.rb @@ -4,6 +4,8 @@ class SubmissionsUnarchiveController < ApplicationController load_and_authorize_resource :submission def create + authorize!(:update, @submission) + @submission.update!(archived_at: nil) redirect_to submission_path(@submission), notice: I18n.t('submission_has_been_unarchived') diff --git a/app/controllers/submitters_send_email_controller.rb b/app/controllers/submitters_send_email_controller.rb index 9cca0ee6..5467ebf4 100644 --- a/app/controllers/submitters_send_email_controller.rb +++ b/app/controllers/submitters_send_email_controller.rb @@ -4,6 +4,8 @@ class SubmittersSendEmailController < ApplicationController load_and_authorize_resource :submitter def create + authorize!(:update, @submitter) + if Wabosign.multitenant? && SubmissionEvent.exists?(submitter: @submitter, event_type: 'send_email', created_at: 10.hours.ago..Time.current) diff --git a/app/controllers/template_documents_controller.rb b/app/controllers/template_documents_controller.rb index db8ba66c..fafa6c14 100644 --- a/app/controllers/template_documents_controller.rb +++ b/app/controllers/template_documents_controller.rb @@ -10,6 +10,8 @@ class TemplateDocumentsController < ApplicationController end def create + authorize!(:update, @template) + if params[:blobs].blank? && params[:files].blank? return render json: { error: I18n.t('file_is_missing') }, status: :unprocessable_content end diff --git a/app/controllers/templates_clone_and_replace_controller.rb b/app/controllers/templates_clone_and_replace_controller.rb index de64d86d..015d1830 100644 --- a/app/controllers/templates_clone_and_replace_controller.rb +++ b/app/controllers/templates_clone_and_replace_controller.rb @@ -13,6 +13,9 @@ class TemplatesCloneAndReplaceController < ApplicationController cloned_template = Templates::Clone.call(@template, author: current_user) cloned_template.name = File.basename(params[:files].first.original_filename, '.*') + + authorize!(:create, cloned_template) + cloned_template.save! documents = Templates::ReplaceAttachments.call(cloned_template, params, extract_fields: true) diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb index 11968e4f..f32e1e1e 100644 --- a/app/controllers/templates_controller.rb +++ b/app/controllers/templates_controller.rb @@ -77,8 +77,6 @@ class TemplatesController < ApplicationController WebhookUrls.enqueue_events(@template, 'template.updated') - TemplateVersions.find_or_create_for(@template, author: current_user) if params[:revision] - head :ok end diff --git a/app/controllers/templates_folders_controller.rb b/app/controllers/templates_folders_controller.rb index 3e83023a..05ee62d8 100644 --- a/app/controllers/templates_folders_controller.rb +++ b/app/controllers/templates_folders_controller.rb @@ -6,6 +6,8 @@ class TemplatesFoldersController < ApplicationController def edit; end def update + authorize!(:update, @template) + name = [params[:parent_name], params[:name]].compact_blank.join(' / ') @template.folder = TemplateFolders.find_or_create_by_name(current_user, name) diff --git a/app/controllers/templates_restore_controller.rb b/app/controllers/templates_restore_controller.rb index d6d0505e..422b69cf 100644 --- a/app/controllers/templates_restore_controller.rb +++ b/app/controllers/templates_restore_controller.rb @@ -4,6 +4,8 @@ class TemplatesRestoreController < ApplicationController load_and_authorize_resource :template def create + authorize!(:update, @template) + @template.update!(archived_at: nil) WebhookUrls.enqueue_events(@template, 'template.updated') diff --git a/app/controllers/templates_versions_controller.rb b/app/controllers/templates_versions_controller.rb index c9a67b8f..0dbd20aa 100644 --- a/app/controllers/templates_versions_controller.rb +++ b/app/controllers/templates_versions_controller.rb @@ -14,4 +14,12 @@ class TemplatesVersionsController < ApplicationController render json: TemplateVersions.serialize(version) end + + def create + authorize!(:update, @template) + + TemplateVersions.find_or_create_for(@template, author: current_user) + + head :ok + end end diff --git a/app/javascript/application.js b/app/javascript/application.js index af25f2b4..311b1612 100644 --- a/app/javascript/application.js +++ b/app/javascript/application.js @@ -47,7 +47,6 @@ import ScrollTo from './elements/scroll_to' import SetValue from './elements/set_value' import ReviewForm from './elements/review_form' import ShowOnValue from './elements/show_on_value' -import CustomValidation from './elements/custom_validation' import ToggleClasses from './elements/toggle_classes' import AutosizeField from './elements/autosize_field' import GoogleDriveFilePicker from './elements/google_drive_file_picker' @@ -139,7 +138,6 @@ safeRegisterElement('scroll-to', ScrollTo) safeRegisterElement('set-value', SetValue) safeRegisterElement('review-form', ReviewForm) safeRegisterElement('show-on-value', ShowOnValue) -safeRegisterElement('custom-validation', CustomValidation) safeRegisterElement('toggle-classes', ToggleClasses) safeRegisterElement('autosize-field', AutosizeField) safeRegisterElement('google-drive-file-picker', GoogleDriveFilePicker) diff --git a/app/javascript/elements/custom_validation.js b/app/javascript/elements/custom_validation.js deleted file mode 100644 index ac738679..00000000 --- a/app/javascript/elements/custom_validation.js +++ /dev/null @@ -1,14 +0,0 @@ -export default class extends HTMLElement { - connectedCallback () { - const input = this.querySelector('input') - const invalidMessage = this.dataset.invalidMessage || '' - - input.addEventListener('invalid', () => { - input.setCustomValidity(input.value ? invalidMessage : '') - }) - - input.addEventListener('input', () => { - input.setCustomValidity('') - }) - } -} diff --git a/app/javascript/form.js b/app/javascript/form.js index c8d5790e..75158250 100644 --- a/app/javascript/form.js +++ b/app/javascript/form.js @@ -52,7 +52,9 @@ safeRegisterElement('submission-form', class extends HTMLElement { completedMessage: JSON.parse(this.dataset.completedMessage || '{}'), completedRedirectUrl: this.dataset.completedRedirectUrl, attachments: reactive(JSON.parse(this.dataset.attachments)), - fields: JSON.parse(this.dataset.fields) + fields: JSON.parse(this.dataset.fields), + completeButtonContainer: document.getElementById('complete_button_container'), + completeButtonScrollContainer: document.getElementById('complete_button_container_scroll') }) this.app.mount(this.appElem) diff --git a/app/javascript/submission_form/area.vue b/app/javascript/submission_form/area.vue index 69a453ac..9cfa44a1 100644 --- a/app/javascript/submission_form/area.vue +++ b/app/javascript/submission_form/area.vue @@ -643,6 +643,10 @@ export default { return new Intl.NumberFormat('de-DE').format(number) } else if (format === 'space') { return new Intl.NumberFormat('fr-FR').format(number) + } else if (format === 'percent') { + return `${number}%` + } else if (format === 'percent_space') { + return `${String(number).replace('.', ',')} %` } else { return number } diff --git a/app/javascript/submission_form/form.vue b/app/javascript/submission_form/form.vue index 2d948bc3..e63c1844 100644 --- a/app/javascript/submission_form/form.vue +++ b/app/javascript/submission_form/form.vue @@ -113,6 +113,31 @@ + + +