refactor and fixes
This commit is contained in:
@@ -7,20 +7,7 @@ module Api
|
|||||||
def create
|
def create
|
||||||
submitter = Submitter.find_by!(slug: params[:submitter_slug])
|
submitter = Submitter.find_by!(slug: params[:submitter_slug])
|
||||||
|
|
||||||
blob =
|
attachment = Submitters.create_attachment!(submitter, params)
|
||||||
if (file = params[:file])
|
|
||||||
ActiveStorage::Blob.create_and_upload!(io: file.open,
|
|
||||||
filename: file.original_filename,
|
|
||||||
content_type: file.content_type)
|
|
||||||
else
|
|
||||||
ActiveStorage::Blob.find_signed(params[:blob_signed_id])
|
|
||||||
end
|
|
||||||
|
|
||||||
attachment = ActiveStorage::Attachment.create!(
|
|
||||||
blob:,
|
|
||||||
name: params[:name],
|
|
||||||
record: submitter
|
|
||||||
)
|
|
||||||
|
|
||||||
render json: attachment.as_json(only: %i[uuid], methods: %i[url filename content_type])
|
render json: attachment.as_json(only: %i[uuid], methods: %i[url filename content_type])
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ module Api
|
|||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
render json: @template.as_json(include: { author: { only: %i[id email first_name last_name] } })
|
render json: @template.as_json(include: { author: { only: %i[id email first_name last_name] },
|
||||||
|
documents: { only: %i[id filename uuid], methods: %i[url] } })
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
|||||||
@@ -18,23 +18,7 @@ class SubmitFormController < ApplicationController
|
|||||||
def update
|
def update
|
||||||
submitter = Submitter.find_by!(slug: params[:slug])
|
submitter = Submitter.find_by!(slug: params[:slug])
|
||||||
|
|
||||||
update_submitter!(submitter)
|
Submitters::SubmitValues.call(submitter, params)
|
||||||
|
|
||||||
Submissions.update_template_fields!(submitter.submission) if submitter.submission.template_fields.blank?
|
|
||||||
|
|
||||||
submitter.submission.save!
|
|
||||||
|
|
||||||
if submitter.completed_at?
|
|
||||||
GenerateSubmitterResultAttachmentsJob.perform_later(submitter)
|
|
||||||
|
|
||||||
if submitter.account.encrypted_configs.exists?(key: EncryptedConfig::WEBHOOK_URL_KEY)
|
|
||||||
SendWebhookRequestJob.perform_later(submitter)
|
|
||||||
end
|
|
||||||
|
|
||||||
submitter.submission.template.account.users.active.each do |user|
|
|
||||||
SubmitterMailer.completed_email(submitter, user).deliver_later!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
head :ok
|
head :ok
|
||||||
end
|
end
|
||||||
@@ -42,26 +26,4 @@ class SubmitFormController < ApplicationController
|
|||||||
def completed
|
def completed
|
||||||
@submitter = Submitter.find_by!(slug: params[:submit_form_slug])
|
@submitter = Submitter.find_by!(slug: params[:submit_form_slug])
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def update_submitter!(submitter)
|
|
||||||
submitter.values.merge!(normalized_values)
|
|
||||||
submitter.completed_at = Time.current if params[:completed] == 'true'
|
|
||||||
submitter.opened_at ||= Time.current
|
|
||||||
|
|
||||||
submitter.save!
|
|
||||||
|
|
||||||
submitter
|
|
||||||
end
|
|
||||||
|
|
||||||
def normalized_values
|
|
||||||
params.fetch(:values, {}).to_unsafe_h.transform_values do |v|
|
|
||||||
if params[:cast_boolean] == 'true'
|
|
||||||
v == 'true'
|
|
||||||
else
|
|
||||||
v.is_a?(Array) ? v.compact_blank : v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ window.customElements.define('submission-form', class extends HTMLElement {
|
|||||||
canSendEmail: this.dataset.canSendEmail === 'true',
|
canSendEmail: this.dataset.canSendEmail === 'true',
|
||||||
isDirectUpload: this.dataset.isDirectUpload === 'true',
|
isDirectUpload: this.dataset.isDirectUpload === 'true',
|
||||||
isDemo: this.dataset.isDemo === 'true',
|
isDemo: this.dataset.isDemo === 'true',
|
||||||
|
withConfetti: true,
|
||||||
values: reactive(JSON.parse(this.dataset.values)),
|
values: reactive(JSON.parse(this.dataset.values)),
|
||||||
attachments: reactive(JSON.parse(this.dataset.attachments)),
|
attachments: reactive(JSON.parse(this.dataset.attachments)),
|
||||||
fields: JSON.parse(this.dataset.fields)
|
fields: JSON.parse(this.dataset.fields)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
:key="areaIndex"
|
:key="areaIndex"
|
||||||
>
|
>
|
||||||
<Teleport
|
<Teleport
|
||||||
:to="`#page-${area.attachment_uuid}-${area.page}`"
|
:to="findPageElementForArea(area)"
|
||||||
>
|
>
|
||||||
<FieldArea
|
<FieldArea
|
||||||
:ref="setAreaRef"
|
:ref="setAreaRef"
|
||||||
@@ -78,10 +78,16 @@ export default {
|
|||||||
this.areaRefs = []
|
this.areaRefs = []
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
findPageElementForArea (area) {
|
||||||
|
return (this.$root.$el?.parentNode?.getRootNode() || document).getElementById(`page-${area.attachment_uuid}-${area.page}`)
|
||||||
|
},
|
||||||
scrollIntoField (field) {
|
scrollIntoField (field) {
|
||||||
this.areaRefs.find((area) => {
|
this.areaRefs.find((area) => {
|
||||||
if (area.field === field) {
|
if (area.field === field) {
|
||||||
if (document.body.style.overflow === 'hidden') {
|
const root = this.$root.$el.parentNode.getRootNode()
|
||||||
|
const container = root.body || root.querySelector('div')
|
||||||
|
|
||||||
|
if (container.style.overflow === 'hidden') {
|
||||||
this.scrollInContainer(area.$el)
|
this.scrollInContainer(area.$el)
|
||||||
} else {
|
} else {
|
||||||
area.$refs.scrollToElem.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
area.$refs.scrollToElem.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
||||||
@@ -94,13 +100,19 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
scrollInContainer (target) {
|
scrollInContainer (target) {
|
||||||
|
const root = this.$root.$el.parentNode.getRootNode()
|
||||||
|
|
||||||
|
const scrollbox = root.getElementById('scrollbox')
|
||||||
|
const formContainer = root.getElementById('form_container')
|
||||||
|
const container = root.body || root.querySelector('div')
|
||||||
|
|
||||||
const padding = 64
|
const padding = 64
|
||||||
const boxRect = window.scrollbox.children[0].getBoundingClientRect()
|
const boxRect = scrollbox.children[0].getBoundingClientRect()
|
||||||
const targetRect = target.getBoundingClientRect()
|
const targetRect = target.getBoundingClientRect()
|
||||||
|
|
||||||
const targetTopRelativeToBox = targetRect.top - boxRect.top
|
const targetTopRelativeToBox = targetRect.top - boxRect.top
|
||||||
|
|
||||||
window.scrollbox.scrollTop = targetTopRelativeToBox - document.body.offsetHeight + window.form_container.offsetHeight + target.offsetHeight + padding
|
scrollbox.scrollTop = targetTopRelativeToBox - container.offsetHeight + formContainer.offsetHeight + target.offsetHeight + padding
|
||||||
},
|
},
|
||||||
setAreaRef (el) {
|
setAreaRef (el) {
|
||||||
if (el) {
|
if (el) {
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ export default {
|
|||||||
IconLogin,
|
IconLogin,
|
||||||
IconDownload
|
IconDownload
|
||||||
},
|
},
|
||||||
|
inject: ['baseUrl'],
|
||||||
props: {
|
props: {
|
||||||
submitterSlug: {
|
submitterSlug: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -96,6 +97,11 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
|
withConfetti: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
canSendEmail: {
|
canSendEmail: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -109,19 +115,21 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async mounted () {
|
async mounted () {
|
||||||
const { default: confetti } = await import('canvas-confetti')
|
if (this.withConfetti) {
|
||||||
|
const { default: confetti } = await import('canvas-confetti')
|
||||||
|
|
||||||
confetti({
|
confetti({
|
||||||
particleCount: 50,
|
particleCount: 50,
|
||||||
startVelocity: 30,
|
startVelocity: 30,
|
||||||
spread: 140
|
spread: 140
|
||||||
})
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
sendCopyToEmail () {
|
sendCopyToEmail () {
|
||||||
this.isSendingCopy = true
|
this.isSendingCopy = true
|
||||||
|
|
||||||
fetch(`/send_submission_email.json?submitter_slug=${this.submitterSlug}`, {
|
fetch(this.baseUrl + `/send_submission_email.json?submitter_slug=${this.submitterSlug}`, {
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
alert('Email has been sent')
|
alert('Email has been sent')
|
||||||
@@ -132,7 +140,7 @@ export default {
|
|||||||
download () {
|
download () {
|
||||||
this.isDownloading = true
|
this.isDownloading = true
|
||||||
|
|
||||||
fetch(`/submitters/${this.submitterSlug}/download`).then((response) => response.json()).then((urls) => {
|
fetch(this.baseUrl + `/submitters/${this.submitterSlug}/download`).then((response) => response.json()).then((urls) => {
|
||||||
const fileRequests = urls.map((url) => {
|
const fileRequests = urls.map((url) => {
|
||||||
return () => {
|
return () => {
|
||||||
return fetch(url).then(async (resp) => {
|
return fetch(url).then(async (resp) => {
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ export default {
|
|||||||
IconCloudUpload,
|
IconCloudUpload,
|
||||||
IconInnerShadowTop
|
IconInnerShadowTop
|
||||||
},
|
},
|
||||||
|
inject: ['baseUrl'],
|
||||||
props: {
|
props: {
|
||||||
message: {
|
message: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -141,7 +142,7 @@ export default {
|
|||||||
|
|
||||||
return await Promise.all(
|
return await Promise.all(
|
||||||
blobs.map((blob) => {
|
blobs.map((blob) => {
|
||||||
return fetch('/api/attachments', {
|
return fetch(this.baseUrl + '/api/attachments', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
name: 'attachments',
|
name: 'attachments',
|
||||||
@@ -166,7 +167,7 @@ export default {
|
|||||||
formData.append('submitter_slug', this.submitterSlug)
|
formData.append('submitter_slug', this.submitterSlug)
|
||||||
formData.append('name', 'attachments')
|
formData.append('name', 'attachments')
|
||||||
|
|
||||||
return fetch('/api/attachments', {
|
return fetch(this.baseUrl + '/api/attachments', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData
|
body: formData
|
||||||
}).then(resp => resp.json()).then((data) => {
|
}).then(resp => resp.json()).then((data) => {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
v-if="!isFormVisible"
|
v-if="!isFormVisible"
|
||||||
class="btn btn-neutral text-white absolute rounded-none border-x-0 md:border md:rounded-full bottom-0 w-full md:mb-4 text-base"
|
class="btn btn-neutral flex text-white absolute rounded-none border-x-0 md:border md:rounded-full bottom-0 w-full md:mb-4 text-base"
|
||||||
@click.prevent="isFormVisible = true"
|
@click.prevent="isFormVisible = true"
|
||||||
>
|
>
|
||||||
Submit Form
|
Submit Form
|
||||||
@@ -194,7 +194,9 @@
|
|||||||
class="space-y-3.5 mx-auto"
|
class="space-y-3.5 mx-auto"
|
||||||
>
|
>
|
||||||
<template v-if="isAnonymousChecboxes">
|
<template v-if="isAnonymousChecboxes">
|
||||||
Complete hightlighted checkboxes and click <span class="font-semibold">{{ stepFields.length === currentStep + 1 ? 'submit' : 'next' }}</span>.
|
<span class="text-xl">
|
||||||
|
Complete hightlighted checkboxes and click <span class="font-semibold">{{ stepFields.length === currentStep + 1 ? 'submit' : 'next' }}</span>.
|
||||||
|
</span>
|
||||||
<input
|
<input
|
||||||
v-for="field in currentStepFields"
|
v-for="field in currentStepFields"
|
||||||
:key="field.uuid"
|
:key="field.uuid"
|
||||||
@@ -290,6 +292,7 @@
|
|||||||
<FormCompleted
|
<FormCompleted
|
||||||
v-else
|
v-else
|
||||||
:is-demo="isDemo"
|
:is-demo="isDemo"
|
||||||
|
:with-confetti="withConfetti"
|
||||||
:can-send-email="canSendEmail"
|
:can-send-email="canSendEmail"
|
||||||
:submitter-slug="submitterSlug"
|
:submitter-slug="submitterSlug"
|
||||||
/>
|
/>
|
||||||
@@ -331,6 +334,11 @@ export default {
|
|||||||
IconArrowsDiagonalMinimize2,
|
IconArrowsDiagonalMinimize2,
|
||||||
FormCompleted
|
FormCompleted
|
||||||
},
|
},
|
||||||
|
provide () {
|
||||||
|
return {
|
||||||
|
baseUrl: this.baseUrl
|
||||||
|
}
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
submitterSlug: {
|
submitterSlug: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -350,6 +358,16 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: () => []
|
default: () => []
|
||||||
},
|
},
|
||||||
|
withConfetti: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
baseUrl: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
fields: {
|
fields: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -357,16 +375,17 @@ export default {
|
|||||||
},
|
},
|
||||||
authenticityToken: {
|
authenticityToken: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: false,
|
||||||
|
default: ''
|
||||||
},
|
},
|
||||||
isDirectUpload: {
|
isDirectUpload: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: true,
|
required: false,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
isDemo: {
|
isDemo: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: true,
|
required: false,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
values: {
|
values: {
|
||||||
@@ -429,10 +448,17 @@ export default {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) {
|
if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) {
|
||||||
document.body.style.overflow = 'hidden'
|
this.$nextTick(() => {
|
||||||
|
const root = this.$root.$el.parentNode.getRootNode()
|
||||||
|
const scrollbox = root.getElementById('scrollbox')
|
||||||
|
const parent = root.body || root.querySelector('div')
|
||||||
|
|
||||||
window.scrollbox.classList.add('h-full', 'overflow-y-auto')
|
parent.style.overflow = 'hidden'
|
||||||
window.scrollbox.parentNode.classList.add('h-screen', 'overflow-y-auto')
|
|
||||||
|
scrollbox.classList.add('h-full', 'overflow-y-auto')
|
||||||
|
scrollbox.parentNode.classList.add('h-screen', 'overflow-y-auto')
|
||||||
|
scrollbox.parentNode.style.maxHeight = '-webkit-fill-available'
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -455,7 +481,7 @@ export default {
|
|||||||
if (this.isCompleted) {
|
if (this.isCompleted) {
|
||||||
return Promise.resolve({})
|
return Promise.resolve({})
|
||||||
} else {
|
} else {
|
||||||
return fetch(this.submitPath, {
|
return fetch(this.baseUrl + this.submitPath, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData || new FormData(this.$refs.form)
|
body: formData || new FormData(this.$refs.form)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ export default {
|
|||||||
IconTextSize,
|
IconTextSize,
|
||||||
IconArrowsDiagonalMinimize2
|
IconArrowsDiagonalMinimize2
|
||||||
},
|
},
|
||||||
|
inject: ['baseUrl'],
|
||||||
props: {
|
props: {
|
||||||
field: {
|
field: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -304,7 +305,7 @@ export default {
|
|||||||
file,
|
file,
|
||||||
'/direct_uploads'
|
'/direct_uploads'
|
||||||
).create((_error, data) => {
|
).create((_error, data) => {
|
||||||
fetch('/api/attachments', {
|
fetch(this.baseUrl + '/api/attachments', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
submitter_slug: this.submitterSlug,
|
submitter_slug: this.submitterSlug,
|
||||||
@@ -326,12 +327,12 @@ export default {
|
|||||||
formData.append('submitter_slug', this.submitterSlug)
|
formData.append('submitter_slug', this.submitterSlug)
|
||||||
formData.append('name', 'attachments')
|
formData.append('name', 'attachments')
|
||||||
|
|
||||||
return fetch('/api/attachments', {
|
return fetch(this.baseUrl + '/api/attachments', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData
|
body: formData
|
||||||
}).then((resp) => resp.json()).then((attachment) => {
|
}).then((resp) => resp.json()).then((attachment) => {
|
||||||
this.$emit('update:model-value', attachment.uuid)
|
|
||||||
this.$emit('attached', attachment)
|
this.$emit('attached', attachment)
|
||||||
|
this.$emit('update:model-value', attachment.uuid)
|
||||||
|
|
||||||
return resolve(attachment)
|
return resolve(attachment)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
<% unless Docuseal.demo? %>
|
<% unless Docuseal.demo? %>
|
||||||
<li>
|
<li>
|
||||||
<%= link_to Docuseal.multitenant? ? console_redirect_index_path : Docuseal::CONSOLE_URL, class: 'text-base hover:bg-base-300' do %>
|
<%= link_to Docuseal.multitenant? ? console_redirect_index_path : Docuseal::CONSOLE_URL, class: 'text-base hover:bg-base-300', data: { prefetch: false } do %>
|
||||||
Console
|
Console
|
||||||
<span class="badge badge-warning">New</span>
|
<span class="badge badge-warning">New</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -29,5 +29,7 @@ module DocuSeal
|
|||||||
|
|
||||||
config.middleware.insert_before ActionDispatch::Static, Rack::Deflater
|
config.middleware.insert_before ActionDispatch::Static, Rack::Deflater
|
||||||
config.middleware.insert_before ActionDispatch::Static, ApiPathConsiderJsonMiddleware
|
config.middleware.insert_before ActionDispatch::Static, ApiPathConsiderJsonMiddleware
|
||||||
|
|
||||||
|
ActiveSupport.run_load_hooks(:application_config, self)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -13,6 +13,20 @@ Rails.configuration.to_prepare do
|
|||||||
response.set_header('Cache-Control', 'public, max-age=31536000') if action_name == 'show'
|
response.set_header('Cache-Control', 'public, max-age=31536000') if action_name == 'show'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
ActiveStorage::Blobs::ProxyController.before_action do
|
||||||
|
response.set_header('Access-Control-Allow-Origin', '*')
|
||||||
|
response.set_header('Access-Control-Allow-Methods', 'GET')
|
||||||
|
response.set_header('Access-Control-Allow-Headers', '*')
|
||||||
|
response.set_header('Access-Control-Max-Age', '1728000')
|
||||||
|
end
|
||||||
|
|
||||||
|
ActiveStorage::Blobs::RedirectController.before_action do
|
||||||
|
response.set_header('Access-Control-Allow-Origin', '*')
|
||||||
|
response.set_header('Access-Control-Allow-Methods', 'GET')
|
||||||
|
response.set_header('Access-Control-Allow-Headers', '*')
|
||||||
|
response.set_header('Access-Control-Max-Age', '1728000')
|
||||||
|
end
|
||||||
|
|
||||||
ActiveStorage::DirectUploadsController.before_action do
|
ActiveStorage::DirectUploadsController.before_action do
|
||||||
next if current_user
|
next if current_user
|
||||||
next if Submitter.find_signed(cookies[:submitter_sid])
|
next if Submitter.find_signed(cookies[:submitter_sid])
|
||||||
|
|||||||
@@ -83,4 +83,6 @@ Rails.application.routes.draw do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
ActiveSupport.run_load_hooks(:routes, self)
|
||||||
end
|
end
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ module Submissions
|
|||||||
end
|
end
|
||||||
|
|
||||||
def create_from_emails(template:, user:, emails:, source:, send_email: false)
|
def create_from_emails(template:, user:, emails:, source:, send_email: false)
|
||||||
emails = emails.to_s.scan(User::EMAIL_REGEXP)
|
emails = emails.to_s.scan(User::EMAIL_REGEXP) unless emails.is_a?(Array)
|
||||||
|
|
||||||
emails.map do |email|
|
emails.map do |email|
|
||||||
submission = template.submissions.new(created_by_user: user, source:)
|
submission = template.submissions.new(created_by_user: user, source:)
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ module Submissions
|
|||||||
|
|
||||||
page = pdf.pages[area['page']]
|
page = pdf.pages[area['page']]
|
||||||
|
|
||||||
|
page[:Annots] ||= []
|
||||||
|
page[:Annots] = page[:Annots].reject { |e| e[:A] && e[:A][:URI].to_s.starts_with?('file:///docuseal_field') }
|
||||||
|
|
||||||
width = page.box.width
|
width = page.box.width
|
||||||
height = page.box.height
|
height = page.box.height
|
||||||
font_size = ((page.box.width / A4_SIZE[0].to_f) * FONT_SIZE).to_i
|
font_size = ((page.box.width / A4_SIZE[0].to_f) * FONT_SIZE).to_i
|
||||||
@@ -66,8 +69,6 @@ module Submissions
|
|||||||
height: image.height * scale
|
height: image.height * scale
|
||||||
)
|
)
|
||||||
when 'file'
|
when 'file'
|
||||||
page[:Annots] ||= []
|
|
||||||
|
|
||||||
items = Array.wrap(value).each_with_object([]) do |uuid, acc|
|
items = Array.wrap(value).each_with_object([]) do |uuid, acc|
|
||||||
attachment = submitter.attachments.find { |a| a.uuid == uuid }
|
attachment = submitter.attachments.find { |a| a.uuid == uuid }
|
||||||
|
|
||||||
|
|||||||
@@ -11,4 +11,21 @@ module Submitters
|
|||||||
is_more_than_two_images && original_documents.find { |a| a.uuid == attachment.uuid }&.image?
|
is_more_than_two_images && original_documents.find { |a| a.uuid == attachment.uuid }&.image?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def create_attachment!(submitter, params)
|
||||||
|
blob =
|
||||||
|
if (file = params[:file])
|
||||||
|
ActiveStorage::Blob.create_and_upload!(io: file.open,
|
||||||
|
filename: file.original_filename,
|
||||||
|
content_type: file.content_type)
|
||||||
|
else
|
||||||
|
ActiveStorage::Blob.find_signed(params[:blob_signed_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
ActiveStorage::Attachment.create!(
|
||||||
|
blob:,
|
||||||
|
name: params[:name],
|
||||||
|
record: submitter
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Submitters
|
||||||
|
module SubmitValues
|
||||||
|
module_function
|
||||||
|
|
||||||
|
def call(submitter, params)
|
||||||
|
update_submitter!(submitter, params)
|
||||||
|
|
||||||
|
Submissions.update_template_fields!(submitter.submission) if submitter.submission.template_fields.blank?
|
||||||
|
|
||||||
|
submitter.submission.save!
|
||||||
|
|
||||||
|
return unless submitter.completed_at?
|
||||||
|
|
||||||
|
GenerateSubmitterResultAttachmentsJob.perform_later(submitter)
|
||||||
|
|
||||||
|
if submitter.account.encrypted_configs.exists?(key: EncryptedConfig::WEBHOOK_URL_KEY)
|
||||||
|
SendWebhookRequestJob.perform_later(submitter)
|
||||||
|
end
|
||||||
|
|
||||||
|
submitter.submission.template.account.users.active.each do |user|
|
||||||
|
SubmitterMailer.completed_email(submitter, user).deliver_later!
|
||||||
|
end
|
||||||
|
|
||||||
|
submitter
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_submitter!(submitter, params)
|
||||||
|
submitter.values.merge!(normalized_values(params))
|
||||||
|
submitter.completed_at = Time.current if params[:completed] == 'true'
|
||||||
|
submitter.opened_at ||= Time.current
|
||||||
|
|
||||||
|
submitter.save!
|
||||||
|
|
||||||
|
submitter
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalized_values(params)
|
||||||
|
params.fetch(:values, {}).to_unsafe_h.transform_values do |v|
|
||||||
|
if params[:cast_boolean] == 'true'
|
||||||
|
v == 'true'
|
||||||
|
else
|
||||||
|
v.is_a?(Array) ? v.compact_blank : v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user