Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa99b4ebdc | ||
|
|
83c793a2a5 | ||
|
|
d078727070 | ||
|
|
0d8e2c5ff0 | ||
|
|
ea062d7494 | ||
|
|
d525e0597a | ||
|
|
964b5d4e74 | ||
|
|
abf17eb09f | ||
|
|
178809dad7 | ||
|
|
881d189715 | ||
|
|
48a8973910 | ||
|
|
ae891932c5 | ||
|
|
a8b5e00814 | ||
|
|
e98432d7e4 | ||
|
|
29ff58ed98 | ||
|
|
a621575ffc | ||
|
|
d7c7efc203 | ||
|
|
4f013ca927 | ||
|
|
d9823feef7 | ||
|
|
676d775544 | ||
|
|
840ad17258 | ||
|
|
ce0cd09b70 | ||
|
|
bb752fbc00 | ||
|
|
c71fb04404 | ||
|
|
e856cf8787 | ||
|
|
71aae65bc6 | ||
|
|
7a33444f9b | ||
|
|
e12ec9d986 |
No files matched your search
@@ -1,27 +1,14 @@
|
|||||||
name: Build Docker Images
|
name: Build Docker Images
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
push:
|
||||||
inputs:
|
tags:
|
||||||
version:
|
- "*.*.*"
|
||||||
description: Version
|
|
||||||
type: string
|
|
||||||
required: true
|
|
||||||
image:
|
|
||||||
description: QEMU image
|
|
||||||
type: string
|
|
||||||
required: false
|
|
||||||
default: tonistiigi/binfmt:latest
|
|
||||||
os:
|
|
||||||
description: OS
|
|
||||||
type: string
|
|
||||||
required: false
|
|
||||||
default: ubuntu-24.04-arm
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ${{ inputs.os }}
|
runs-on: ubuntu-24.04-arm
|
||||||
timeout-minutes: 20
|
timeout-minutes: 30
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
@@ -34,18 +21,16 @@ jobs:
|
|||||||
uses: docker/metadata-action@v4
|
uses: docker/metadata-action@v4
|
||||||
with:
|
with:
|
||||||
images: docuseal/docuseal
|
images: docuseal/docuseal
|
||||||
tags: latest,${{ inputs.version }}
|
tags: type=semver,pattern={{version}}
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v3
|
||||||
with:
|
|
||||||
image: ${{ inputs.image }}
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Create .version file
|
- name: Create .version file
|
||||||
run: echo ${{ inputs.version }} > .version
|
run: echo ${{ github.ref_name }} > .version
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
|
|||||||
@@ -77,24 +77,27 @@ GEM
|
|||||||
annotaterb (4.14.0)
|
annotaterb (4.14.0)
|
||||||
arabic-letter-connector (0.1.1)
|
arabic-letter-connector (0.1.1)
|
||||||
ast (2.4.3)
|
ast (2.4.3)
|
||||||
aws-eventstream (1.3.0)
|
aws-eventstream (1.4.0)
|
||||||
aws-partitions (1.1027.0)
|
aws-partitions (1.1197.0)
|
||||||
aws-sdk-core (3.214.0)
|
aws-sdk-core (3.240.0)
|
||||||
aws-eventstream (~> 1, >= 1.3.0)
|
aws-eventstream (~> 1, >= 1.3.0)
|
||||||
aws-partitions (~> 1, >= 1.992.0)
|
aws-partitions (~> 1, >= 1.992.0)
|
||||||
aws-sigv4 (~> 1.9)
|
aws-sigv4 (~> 1.9)
|
||||||
|
base64
|
||||||
|
bigdecimal
|
||||||
jmespath (~> 1, >= 1.6.1)
|
jmespath (~> 1, >= 1.6.1)
|
||||||
aws-sdk-kms (1.96.0)
|
logger
|
||||||
aws-sdk-core (~> 3, >= 3.210.0)
|
aws-sdk-kms (1.118.0)
|
||||||
|
aws-sdk-core (~> 3, >= 3.239.1)
|
||||||
aws-sigv4 (~> 1.5)
|
aws-sigv4 (~> 1.5)
|
||||||
aws-sdk-s3 (1.176.1)
|
aws-sdk-s3 (1.208.0)
|
||||||
aws-sdk-core (~> 3, >= 3.210.0)
|
aws-sdk-core (~> 3, >= 3.234.0)
|
||||||
aws-sdk-kms (~> 1)
|
aws-sdk-kms (~> 1)
|
||||||
aws-sigv4 (~> 1.5)
|
aws-sigv4 (~> 1.5)
|
||||||
aws-sdk-secretsmanager (1.110.0)
|
aws-sdk-secretsmanager (1.110.0)
|
||||||
aws-sdk-core (~> 3, >= 3.210.0)
|
aws-sdk-core (~> 3, >= 3.210.0)
|
||||||
aws-sigv4 (~> 1.5)
|
aws-sigv4 (~> 1.5)
|
||||||
aws-sigv4 (1.10.1)
|
aws-sigv4 (1.12.1)
|
||||||
aws-eventstream (~> 1, >= 1.0.2)
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
azure-storage-blob (2.0.3)
|
azure-storage-blob (2.0.3)
|
||||||
azure-storage-common (~> 2.0)
|
azure-storage-common (~> 2.0)
|
||||||
|
|||||||
@@ -182,13 +182,13 @@ module Api
|
|||||||
def submissions_params
|
def submissions_params
|
||||||
permitted_attrs = [
|
permitted_attrs = [
|
||||||
:send_email, :send_sms, :bcc_completed, :completed_redirect_url, :reply_to, :go_to_last,
|
:send_email, :send_sms, :bcc_completed, :completed_redirect_url, :reply_to, :go_to_last,
|
||||||
:require_phone_2fa, :expire_at, :name,
|
:require_phone_2fa, :require_email_2fa, :expire_at, :name,
|
||||||
{
|
{
|
||||||
variables: {},
|
variables: {},
|
||||||
message: %i[subject body],
|
message: %i[subject body],
|
||||||
submitters: [[:send_email, :send_sms, :completed_redirect_url, :uuid, :name, :email, :role,
|
submitters: [[:send_email, :send_sms, :completed_redirect_url, :uuid, :name, :email, :role,
|
||||||
:completed, :phone, :application_key, :external_id, :reply_to, :go_to_last,
|
:completed, :phone, :application_key, :external_id, :reply_to, :go_to_last,
|
||||||
:require_phone_2fa, :order,
|
:require_phone_2fa, :require_email_2fa, :order, :invite_by,
|
||||||
{ metadata: {}, values: {}, roles: [], readonly_fields: [], message: %i[subject body],
|
{ metadata: {}, values: {}, roles: [], readonly_fields: [], message: %i[subject body],
|
||||||
fields: [:name, :uuid, :default_value, :value, :title, :description,
|
fields: [:name, :uuid, :default_value, :value, :title, :description,
|
||||||
:readonly, :required, :validation_pattern, :invalid_message,
|
:readonly, :required, :validation_pattern, :invalid_message,
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ module Api
|
|||||||
|
|
||||||
submitter_params.permit(
|
submitter_params.permit(
|
||||||
:send_email, :send_sms, :reply_to, :completed_redirect_url, :uuid, :name, :email, :role,
|
:send_email, :send_sms, :reply_to, :completed_redirect_url, :uuid, :name, :email, :role,
|
||||||
:completed, :phone, :application_key, :external_id, :go_to_last, :require_phone_2fa,
|
:completed, :phone, :application_key, :external_id, :go_to_last, :require_phone_2fa, :require_email_2fa,
|
||||||
{ metadata: {}, values: {}, readonly_fields: [], message: %i[subject body],
|
{ metadata: {}, values: {}, readonly_fields: [], message: %i[subject body],
|
||||||
fields: [[:name, :uuid, :default_value, :value, :required,
|
fields: [[:name, :uuid, :default_value, :value, :required,
|
||||||
:readonly, :validation_pattern, :invalid_message,
|
:readonly, :validation_pattern, :invalid_message,
|
||||||
|
|||||||
@@ -12,6 +12,14 @@ class SubmissionsController < ApplicationController
|
|||||||
authorize!(:create, Submission)
|
authorize!(:create, Submission)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
FIELD_ICONS = {
|
||||||
|
'text' => 'text_size', 'signature' => 'writing_sign', 'date' => 'calendar_event',
|
||||||
|
'number' => 'square_number_1', 'image' => 'photo', 'initials' => 'letter_case_upper',
|
||||||
|
'file' => 'paperclip', 'select' => 'select', 'checkbox' => 'checkbox', 'radio' => 'circle_dot',
|
||||||
|
'stamp' => 'rubber_stamp', 'cells' => 'columns_3', 'multiple' => 'checks', 'phone' => 'phone_check',
|
||||||
|
'payment' => 'credit_card', 'verification' => 'id'
|
||||||
|
}.freeze
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@submission = Submissions.preload_with_pages(@submission)
|
@submission = Submissions.preload_with_pages(@submission)
|
||||||
|
|
||||||
@@ -45,14 +53,15 @@ class SubmissionsController < ApplicationController
|
|||||||
else
|
else
|
||||||
submissions_attrs = submissions_params[:submission].to_h.values
|
submissions_attrs = submissions_params[:submission].to_h.values
|
||||||
|
|
||||||
submissions_attrs, =
|
submissions_attrs, _, new_fields =
|
||||||
Submissions::NormalizeParamUtils.normalize_submissions_params!(submissions_attrs, @template)
|
Submissions::NormalizeParamUtils.normalize_submissions_params!(submissions_attrs, @template, add_fields: true)
|
||||||
|
|
||||||
Submissions.create_from_submitters(template: @template,
|
Submissions.create_from_submitters(template: @template,
|
||||||
user: current_user,
|
user: current_user,
|
||||||
source: :invite,
|
source: :invite,
|
||||||
submitters_order: params[:preserve_order] == '1' ? 'preserved' : 'random',
|
submitters_order: params[:preserve_order] == '1' ? 'preserved' : 'random',
|
||||||
submissions_attrs:,
|
submissions_attrs:,
|
||||||
|
new_fields:,
|
||||||
params: params.merge('send_completed_email' => true))
|
params: params.merge('send_completed_email' => true))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ import AutosizeField from './elements/autosize_field'
|
|||||||
import GoogleDriveFilePicker from './elements/google_drive_file_picker'
|
import GoogleDriveFilePicker from './elements/google_drive_file_picker'
|
||||||
import OpenModal from './elements/open_modal'
|
import OpenModal from './elements/open_modal'
|
||||||
import BarChart from './elements/bar_chart'
|
import BarChart from './elements/bar_chart'
|
||||||
|
import FieldCondition from './elements/field_condition'
|
||||||
|
|
||||||
import * as TurboInstantClick from './lib/turbo_instant_click'
|
import * as TurboInstantClick from './lib/turbo_instant_click'
|
||||||
|
|
||||||
@@ -142,6 +143,7 @@ safeRegisterElement('autosize-field', AutosizeField)
|
|||||||
safeRegisterElement('google-drive-file-picker', GoogleDriveFilePicker)
|
safeRegisterElement('google-drive-file-picker', GoogleDriveFilePicker)
|
||||||
safeRegisterElement('open-modal', OpenModal)
|
safeRegisterElement('open-modal', OpenModal)
|
||||||
safeRegisterElement('bar-chart', BarChart)
|
safeRegisterElement('bar-chart', BarChart)
|
||||||
|
safeRegisterElement('field-condition', FieldCondition)
|
||||||
|
|
||||||
safeRegisterElement('template-builder', class extends HTMLElement {
|
safeRegisterElement('template-builder', class extends HTMLElement {
|
||||||
connectedCallback () {
|
connectedCallback () {
|
||||||
|
|||||||
@@ -0,0 +1,151 @@
|
|||||||
|
export default class extends HTMLElement {
|
||||||
|
connectedCallback () {
|
||||||
|
this.targetId = this.dataset.targetId
|
||||||
|
this.fieldId = this.dataset.fieldId
|
||||||
|
this.action = (this.dataset.action || '').trim()
|
||||||
|
this.expectedValue = this.dataset.value
|
||||||
|
|
||||||
|
this.targetEl = document.getElementById(this.targetId)
|
||||||
|
this.sourceEl = document.getElementById(this.fieldId)
|
||||||
|
|
||||||
|
this.bindListeners()
|
||||||
|
|
||||||
|
this.evaluateAndApply()
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnectedCallback () {
|
||||||
|
this.unbindListeners()
|
||||||
|
}
|
||||||
|
|
||||||
|
bindListeners () {
|
||||||
|
this.eventsFor(this.sourceEl).forEach((ev) => {
|
||||||
|
this.sourceEl.addEventListener(ev, this.evaluateAndApply)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
unbindListeners () {
|
||||||
|
this.eventsFor(this.sourceEl).forEach((ev) => {
|
||||||
|
this.sourceEl.removeEventListener(ev, this.evaluateAndApply)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
eventsFor (el) {
|
||||||
|
if (!el) return []
|
||||||
|
|
||||||
|
const tag = el.tagName.toLowerCase()
|
||||||
|
|
||||||
|
if (tag === 'textarea') return ['input']
|
||||||
|
if (tag === 'input') return ['input', 'change']
|
||||||
|
|
||||||
|
return ['change']
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluateAndApply = () => {
|
||||||
|
const fieldConditions = document.querySelectorAll(`field-condition[data-target-id="${this.targetId}"]`)
|
||||||
|
|
||||||
|
const result = [...fieldConditions].reduce((acc, cond) => {
|
||||||
|
if (cond.dataset.operation === 'or') {
|
||||||
|
acc.push(acc.pop() || cond.checkCondition())
|
||||||
|
} else {
|
||||||
|
acc.push(cond.checkCondition())
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
this.apply(!result.includes(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
checkCondition () {
|
||||||
|
const action = this.action
|
||||||
|
const actual = this.getSourceValue()
|
||||||
|
const expected = this.expectedValue
|
||||||
|
|
||||||
|
if (action === 'empty' || action === 'unchecked') return this.isEmpty(actual)
|
||||||
|
if (action === 'not_empty' || action === 'checked') return !this.isEmpty(actual)
|
||||||
|
|
||||||
|
if (action === 'equal') {
|
||||||
|
const list = Array.isArray(actual) ? actual : [actual]
|
||||||
|
return list.filter((v) => v !== null && v !== undefined).map(String).includes(String(expected))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === 'contains') return this.contains(actual, expected)
|
||||||
|
|
||||||
|
if (action === 'not_equal') {
|
||||||
|
const list = Array.isArray(actual) ? actual : [actual]
|
||||||
|
return !list.filter((v) => v !== null && v !== undefined).map(String).includes(String(expected))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === 'does_not_contain') return !this.contains(actual, expected)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
getSourceValue () {
|
||||||
|
const el = this.sourceEl
|
||||||
|
|
||||||
|
if (!el) return
|
||||||
|
|
||||||
|
const tag = el.tagName.toLowerCase()
|
||||||
|
const type = (el.getAttribute('type') || '').toLowerCase()
|
||||||
|
|
||||||
|
if (tag === 'select') return el.value
|
||||||
|
if (tag === 'textarea') return el.value
|
||||||
|
if (tag === 'input' && type === 'checkbox') return el.checked ? (el.value || '1') : null
|
||||||
|
if (tag === 'input') return el.value
|
||||||
|
|
||||||
|
return el.value ?? null
|
||||||
|
}
|
||||||
|
|
||||||
|
isEmpty (obj) {
|
||||||
|
if (obj == null) return true
|
||||||
|
|
||||||
|
if (Array.isArray(obj)) {
|
||||||
|
return obj.length === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof obj === 'string') {
|
||||||
|
return obj.trim().length === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof obj === 'object') {
|
||||||
|
return Object.keys(obj).length === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj === false) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
contains (actual, expected) {
|
||||||
|
if (expected === null || expected === undefined) return false
|
||||||
|
|
||||||
|
const exp = String(expected)
|
||||||
|
|
||||||
|
if (Array.isArray(actual)) return actual.filter((v) => v !== null && v !== undefined).map(String).includes(exp)
|
||||||
|
|
||||||
|
if (typeof actual === 'string') return actual.includes(exp)
|
||||||
|
|
||||||
|
return actual !== null && actual !== undefined && String(actual) === exp
|
||||||
|
}
|
||||||
|
|
||||||
|
apply (passed) {
|
||||||
|
const controls = this.targetEl.matches('input, select, textarea, button')
|
||||||
|
? [this.targetEl]
|
||||||
|
: Array.from(this.targetEl.querySelectorAll('input, select, textarea, button'))
|
||||||
|
|
||||||
|
if (passed) {
|
||||||
|
this.targetEl.style.display = ''
|
||||||
|
this.targetEl.labels.forEach((label) => { label.style.display = '' })
|
||||||
|
|
||||||
|
controls.forEach((c) => (c.disabled = false))
|
||||||
|
} else {
|
||||||
|
this.targetEl.style.display = 'none'
|
||||||
|
this.targetEl.labels.forEach((label) => { label.style.display = 'none' })
|
||||||
|
|
||||||
|
controls.forEach((c) => (c.disabled = true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,6 +37,7 @@ safeRegisterElement('submission-form', class extends HTMLElement {
|
|||||||
withSignatureId: this.dataset.withSignatureId === 'true',
|
withSignatureId: this.dataset.withSignatureId === 'true',
|
||||||
requireSigningReason: this.dataset.requireSigningReason === 'true',
|
requireSigningReason: this.dataset.requireSigningReason === 'true',
|
||||||
withConfetti: this.dataset.withConfetti !== 'false',
|
withConfetti: this.dataset.withConfetti !== 'false',
|
||||||
|
withFieldLabels: this.dataset.withFieldLabels !== 'false',
|
||||||
withDisclosure: this.dataset.withDisclosure === 'true',
|
withDisclosure: this.dataset.withDisclosure === 'true',
|
||||||
reuseSignature: this.dataset.reuseSignature !== 'false',
|
reuseSignature: this.dataset.reuseSignature !== 'false',
|
||||||
withTypedSignature: this.dataset.withTypedSignature !== 'false',
|
withTypedSignature: this.dataset.withTypedSignature !== 'false',
|
||||||
|
|||||||
@@ -560,7 +560,7 @@ export default {
|
|||||||
return style
|
return style
|
||||||
},
|
},
|
||||||
isNarrow () {
|
isNarrow () {
|
||||||
return this.area.h > 0 && (this.area.w / this.area.h) > 6
|
return this.area.h > 0 && ((this.area.w * this.pageWidth) / (this.area.h * this.pageHeight)) > 4.5
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
:scroll-el="scrollEl"
|
:scroll-el="scrollEl"
|
||||||
:with-signature-id="withSignatureId"
|
:with-signature-id="withSignatureId"
|
||||||
:attachments-index="attachmentsIndex"
|
:attachments-index="attachmentsIndex"
|
||||||
:with-label="!isAnonymousChecboxes && showFieldNames"
|
:with-label="withFieldLabels && !isAnonymousChecboxes && showFieldNames"
|
||||||
:current-step="currentStepFields"
|
:current-step="currentStepFields"
|
||||||
:scroll-padding="scrollPadding"
|
:scroll-padding="scrollPadding"
|
||||||
@focus-step="[saveStep(), currentField.type !== 'checkbox' ? isFormVisible = true : '', goToStep($event, false, true)]"
|
@focus-step="[saveStep(), currentField.type !== 'checkbox' ? isFormVisible = true : '', goToStep($event, false, true)]"
|
||||||
@@ -537,7 +537,7 @@
|
|||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-if="stepFields.length < 80"
|
v-if="stepFields.length < 80"
|
||||||
class="flex justify-center mt-3 sm:mt-4 mb-0 sm:mb-1"
|
class="flex justify-center mt-3 sm:mt-4 mb-0 sm:mb-1 select-none"
|
||||||
>
|
>
|
||||||
<div class="flex items-center flex-wrap steps-progress">
|
<div class="flex items-center flex-wrap steps-progress">
|
||||||
<a
|
<a
|
||||||
@@ -737,6 +737,11 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
|
withFieldLabels: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
withConfetti: {
|
withConfetti: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const en = {
|
|||||||
esignature_disclosure: 'eSignature Disclosure',
|
esignature_disclosure: 'eSignature Disclosure',
|
||||||
signature: 'Signature',
|
signature: 'Signature',
|
||||||
initials: 'Initials',
|
initials: 'Initials',
|
||||||
drawn_signature_on_a_touchscreen_device: 'Drawn signature on a touchscreen device',
|
sign_on_the_touchscreen: 'Sign on the touchscreen',
|
||||||
approved: 'Approved',
|
approved: 'Approved',
|
||||||
reviewed: 'Reviewed',
|
reviewed: 'Reviewed',
|
||||||
other: 'Other',
|
other: 'Other',
|
||||||
@@ -120,7 +120,7 @@ const es = {
|
|||||||
select_a_reason: 'Selecciona una razón',
|
select_a_reason: 'Selecciona una razón',
|
||||||
value_is_invalid: 'El valor no es válido',
|
value_is_invalid: 'El valor no es válido',
|
||||||
verification_code_is_invalid: 'El código de verificación no es válido',
|
verification_code_is_invalid: 'El código de verificación no es válido',
|
||||||
drawn_signature_on_a_touchscreen_device: 'Firma dibujada en un dispositivo con pantalla táctil',
|
sign_on_the_touchscreen: 'Firmar en pantalla táctil',
|
||||||
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Escanea el código QR con la aplicación de la cámara para abrir el formulario en el móvil y dibujar tu firma',
|
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Escanea el código QR con la aplicación de la cámara para abrir el formulario en el móvil y dibujar tu firma',
|
||||||
by_clicking_you_agree_to_the: 'Al hacer clic en "{button}", usted acepta el',
|
by_clicking_you_agree_to_the: 'Al hacer clic en "{button}", usted acepta el',
|
||||||
electronic_signature_disclosure: 'Divulgación de Firma Electrónica',
|
electronic_signature_disclosure: 'Divulgación de Firma Electrónica',
|
||||||
@@ -221,7 +221,7 @@ const it = {
|
|||||||
select_a_reason: 'Seleziona una ragione',
|
select_a_reason: 'Seleziona una ragione',
|
||||||
value_is_invalid: 'Il valore non è valido',
|
value_is_invalid: 'Il valore non è valido',
|
||||||
verification_code_is_invalid: 'Il codice di verifica non è valido',
|
verification_code_is_invalid: 'Il codice di verifica non è valido',
|
||||||
drawn_signature_on_a_touchscreen_device: 'Firma disegnata su un dispositivo con schermo tattile',
|
sign_on_the_touchscreen: 'Firma su schermo tattile',
|
||||||
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: "Scansiona il codice QR con l'app della fotocamera per aprire il modulo sul cellulare e disegnare la tua firma",
|
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: "Scansiona il codice QR con l'app della fotocamera per aprire il modulo sul cellulare e disegnare la tua firma",
|
||||||
by_clicking_you_agree_to_the: 'Cliccando su "{button}", accetti il',
|
by_clicking_you_agree_to_the: 'Cliccando su "{button}", accetti il',
|
||||||
electronic_signature_disclosure: 'Divulgazione della Firma Elettronica',
|
electronic_signature_disclosure: 'Divulgazione della Firma Elettronica',
|
||||||
@@ -316,7 +316,7 @@ const de = {
|
|||||||
esignature_disclosure: 'Hinweis zur eSignatur',
|
esignature_disclosure: 'Hinweis zur eSignatur',
|
||||||
signature: 'Unterschrift',
|
signature: 'Unterschrift',
|
||||||
initials: 'Initialen',
|
initials: 'Initialen',
|
||||||
drawn_signature_on_a_touchscreen_device: 'Auf einem Touchscreen-Gerät gezeichnete Unterschrift',
|
sign_on_the_touchscreen: 'Auf Touchscreen signieren',
|
||||||
approved: 'Genehmigt',
|
approved: 'Genehmigt',
|
||||||
reviewed: 'Geprüft',
|
reviewed: 'Geprüft',
|
||||||
other: 'Sonstiges',
|
other: 'Sonstiges',
|
||||||
@@ -417,7 +417,7 @@ const fr = {
|
|||||||
esignature_disclosure: 'Déclaration eSignature',
|
esignature_disclosure: 'Déclaration eSignature',
|
||||||
signature: 'Signature',
|
signature: 'Signature',
|
||||||
initials: 'Initiales',
|
initials: 'Initiales',
|
||||||
drawn_signature_on_a_touchscreen_device: 'Signature dessinée sur un appareil à écran tactile',
|
sign_on_the_touchscreen: 'Signer sur écran tactile',
|
||||||
approved: 'Approuvé',
|
approved: 'Approuvé',
|
||||||
reviewed: 'Révisé',
|
reviewed: 'Révisé',
|
||||||
other: 'Autre',
|
other: 'Autre',
|
||||||
@@ -524,7 +524,7 @@ const pl = {
|
|||||||
select_a_reason: 'Wybierz powód',
|
select_a_reason: 'Wybierz powód',
|
||||||
value_is_invalid: 'Wartość jest nieprawidłowa',
|
value_is_invalid: 'Wartość jest nieprawidłowa',
|
||||||
verification_code_is_invalid: 'Kod weryfikacyjny jest nieprawidłowy',
|
verification_code_is_invalid: 'Kod weryfikacyjny jest nieprawidłowy',
|
||||||
drawn_signature_on_a_touchscreen_device: 'Podpis odręczny na urządzeniu z ekranem dotykowym',
|
sign_on_the_touchscreen: 'Podpisz na ekranie dotykowym',
|
||||||
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Zeskanuj kod QR za pomocą aplikacji aparatu, aby otworzyć formularz na telefonie i narysować swój podpis',
|
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Zeskanuj kod QR za pomocą aplikacji aparatu, aby otworzyć formularz na telefonie i narysować swój podpis',
|
||||||
by_clicking_you_agree_to_the: 'Klikając na "{button}", zgadzasz się na',
|
by_clicking_you_agree_to_the: 'Klikając na "{button}", zgadzasz się na',
|
||||||
electronic_signature_disclosure: 'Ujawnienie Elektronicznej Sygnatury',
|
electronic_signature_disclosure: 'Ujawnienie Elektronicznej Sygnatury',
|
||||||
@@ -625,7 +625,7 @@ const uk = {
|
|||||||
select_a_reason: 'Виберіть причину',
|
select_a_reason: 'Виберіть причину',
|
||||||
value_is_invalid: 'Значення є неправильним',
|
value_is_invalid: 'Значення є неправильним',
|
||||||
verification_code_is_invalid: 'Код підтвердження є неправильним',
|
verification_code_is_invalid: 'Код підтвердження є неправильним',
|
||||||
drawn_signature_on_a_touchscreen_device: 'Підпис на сенсорному пристрої',
|
sign_on_the_touchscreen: 'Підписати на сенсорному екрані',
|
||||||
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Скануйте QR-код за допомогою програми камери, щоб відкрити форму на мобільному пристрої та намалювати свій підпис',
|
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Скануйте QR-код за допомогою програми камери, щоб відкрити форму на мобільному пристрої та намалювати свій підпис',
|
||||||
by_clicking_you_agree_to_the: 'Натиснувши на "{button}", ви погоджуєтеся з',
|
by_clicking_you_agree_to_the: 'Натиснувши на "{button}", ви погоджуєтеся з',
|
||||||
electronic_signature_disclosure: 'Розголошення Електронного Підпису',
|
electronic_signature_disclosure: 'Розголошення Електронного Підпису',
|
||||||
@@ -726,7 +726,7 @@ const cs = {
|
|||||||
select_a_reason: 'Vyberte důvod',
|
select_a_reason: 'Vyberte důvod',
|
||||||
value_is_invalid: 'Hodnota je neplatná',
|
value_is_invalid: 'Hodnota je neplatná',
|
||||||
verification_code_is_invalid: 'Ověřovací kód je neplatný',
|
verification_code_is_invalid: 'Ověřovací kód je neplatný',
|
||||||
drawn_signature_on_a_touchscreen_device: 'Namalovaný podpis na dotykovém zařízení',
|
sign_on_the_touchscreen: 'Podepsat na dotykové obrazovce',
|
||||||
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Naskenujte QR kód pomocí aplikace fotoaparátu, abyste otevřeli formulář na mobilním zařízení a nakreslili svůj podpis',
|
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Naskenujte QR kód pomocí aplikace fotoaparátu, abyste otevřeli formulář na mobilním zařízení a nakreslili svůj podpis',
|
||||||
by_clicking_you_agree_to_the: 'Kliknutím na "{button}" souhlasíte s',
|
by_clicking_you_agree_to_the: 'Kliknutím na "{button}" souhlasíte s',
|
||||||
electronic_signature_disclosure: 'Zveřejněním Elektronického Podpisu',
|
electronic_signature_disclosure: 'Zveřejněním Elektronického Podpisu',
|
||||||
@@ -827,7 +827,7 @@ const pt = {
|
|||||||
select_a_reason: 'Selecione um motivo',
|
select_a_reason: 'Selecione um motivo',
|
||||||
value_is_invalid: 'Valor é inválido',
|
value_is_invalid: 'Valor é inválido',
|
||||||
verification_code_is_invalid: 'Código de verificação é inválido',
|
verification_code_is_invalid: 'Código de verificação é inválido',
|
||||||
drawn_signature_on_a_touchscreen_device: 'Assinatura desenhada em um dispositivo com tela sensível ao toque',
|
sign_on_the_touchscreen: 'Assinar na tela sensível',
|
||||||
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Escaneie o código QR com o aplicativo da câmera para abrir o formulário no celular e desenhar sua assinatura',
|
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Escaneie o código QR com o aplicativo da câmera para abrir o formulário no celular e desenhar sua assinatura',
|
||||||
by_clicking_you_agree_to_the: 'Ao clicar em "{button}", você concorda com o',
|
by_clicking_you_agree_to_the: 'Ao clicar em "{button}", você concorda com o',
|
||||||
electronic_signature_disclosure: 'Divulgação de Assinatura Eletrônica',
|
electronic_signature_disclosure: 'Divulgação de Assinatura Eletrônica',
|
||||||
@@ -928,7 +928,7 @@ const he = {
|
|||||||
select_a_reason: 'בחר סיבה',
|
select_a_reason: 'בחר סיבה',
|
||||||
value_is_invalid: 'ערך לא תקין',
|
value_is_invalid: 'ערך לא תקין',
|
||||||
verification_code_is_invalid: 'קוד האימות אינו תקין',
|
verification_code_is_invalid: 'קוד האימות אינו תקין',
|
||||||
drawn_signature_on_a_touchscreen_device: 'חתימה שנוצרה במכשיר עם מסך מגע',
|
sign_on_the_touchscreen: 'חתום על מסך המגע',
|
||||||
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'סרוק את קוד ה-QR באמצעות אפליקציית המצלמה כדי לפתוח את הטופס במובייל ולצייר את החתימה שלך',
|
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'סרוק את קוד ה-QR באמצעות אפליקציית המצלמה כדי לפתוח את הטופס במובייל ולצייר את החתימה שלך',
|
||||||
by_clicking_you_agree_to_the: 'על ידי לחיצה על "{button}", אתה מסכים ל',
|
by_clicking_you_agree_to_the: 'על ידי לחיצה על "{button}", אתה מסכים ל',
|
||||||
electronic_signature_disclosure: 'חשיפת חתימה אלקטרונית',
|
electronic_signature_disclosure: 'חשיפת חתימה אלקטרונית',
|
||||||
@@ -1029,7 +1029,7 @@ const nl = {
|
|||||||
select_a_reason: 'Selecteer een reden',
|
select_a_reason: 'Selecteer een reden',
|
||||||
value_is_invalid: 'Waarde is ongeldig',
|
value_is_invalid: 'Waarde is ongeldig',
|
||||||
verification_code_is_invalid: 'Verificatiecode is ongeldig',
|
verification_code_is_invalid: 'Verificatiecode is ongeldig',
|
||||||
drawn_signature_on_a_touchscreen_device: 'Getekende handtekening op een apparaat met een touchscreen',
|
sign_on_the_touchscreen: 'Onderteken op touchscreen',
|
||||||
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Scan de QR-code met de camera-app om het formulier op mobiel te openen en uw handtekening te tekenen',
|
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'Scan de QR-code met de camera-app om het formulier op mobiel te openen en uw handtekening te tekenen',
|
||||||
by_clicking_you_agree_to_the: 'Door op "{button}" te klikken, gaat u akkoord met de',
|
by_clicking_you_agree_to_the: 'Door op "{button}" te klikken, gaat u akkoord met de',
|
||||||
electronic_signature_disclosure: 'Openbaarmaking van Elektronische Handtekening',
|
electronic_signature_disclosure: 'Openbaarmaking van Elektronische Handtekening',
|
||||||
@@ -1131,7 +1131,7 @@ const ar = {
|
|||||||
value_is_invalid: 'القيمة غير صالحة',
|
value_is_invalid: 'القيمة غير صالحة',
|
||||||
verification_code_is_invalid: 'رمز التحقق غير صالح',
|
verification_code_is_invalid: 'رمز التحقق غير صالح',
|
||||||
already_paid: 'تم الدفع بالفعل',
|
already_paid: 'تم الدفع بالفعل',
|
||||||
drawn_signature_on_a_touchscreen_device: 'توقيع مرسوم على جهاز بشاشة تعمل باللمس',
|
sign_on_the_touchscreen: 'وقع على شاشة اللمس',
|
||||||
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'امسح رمز الاستجابة السريعة باستخدام تطبيق الكاميرا لفتح النموذج على الهاتف المحمول ورسم توقيعك',
|
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: 'امسح رمز الاستجابة السريعة باستخدام تطبيق الكاميرا لفتح النموذج على الهاتف المحمول ورسم توقيعك',
|
||||||
by_clicking_you_agree_to_the: 'بالنقر فوق "{button}"، أنت توافق على',
|
by_clicking_you_agree_to_the: 'بالنقر فوق "{button}"، أنت توافق على',
|
||||||
electronic_signature_disclosure: 'كشف التوقيع الإلكتروني',
|
electronic_signature_disclosure: 'كشف التوقيع الإلكتروني',
|
||||||
@@ -1229,7 +1229,7 @@ const ko = {
|
|||||||
reviewed_by: '검토자',
|
reviewed_by: '검토자',
|
||||||
authored_by: '작성자',
|
authored_by: '작성자',
|
||||||
select_a_reason: '이유 선택',
|
select_a_reason: '이유 선택',
|
||||||
drawn_signature_on_a_touchscreen_device: '터치스크린 장치에서 그린 서명',
|
sign_on_the_touchscreen: '터치스크린에서 서명',
|
||||||
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: '카메라 앱으로 QR 코드를 스캔하여 모바일에서 양식을 열고 서명을 그리세요',
|
scan_the_qr_code_with_the_camera_app_to_open_the_form_on_mobile_and_draw_your_signature: '카메라 앱으로 QR 코드를 스캔하여 모바일에서 양식을 열고 서명을 그리세요',
|
||||||
by_clicking_you_agree_to_the: '"{button}"를 클릭함으로써, 다음에 동의하게 됩니다',
|
by_clicking_you_agree_to_the: '"{button}"를 클릭함으로써, 다음에 동의하게 됩니다',
|
||||||
electronic_signature_disclosure: '전자 서명 공개',
|
electronic_signature_disclosure: '전자 서명 공개',
|
||||||
@@ -1326,7 +1326,7 @@ const ja = {
|
|||||||
esignature_disclosure: '電子署名開示',
|
esignature_disclosure: '電子署名開示',
|
||||||
signature: '署名',
|
signature: '署名',
|
||||||
initials: 'イニシャル',
|
initials: 'イニシャル',
|
||||||
drawn_signature_on_a_touchscreen_device: 'タッチスクリーンデバイスで描かれた署名',
|
sign_on_the_touchscreen: 'タッチスクリーンで署名',
|
||||||
approved: '承認済み',
|
approved: '承認済み',
|
||||||
reviewed: '確認済み',
|
reviewed: '確認済み',
|
||||||
other: 'その他',
|
other: 'その他',
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
<div class="space-x-2 flex flex-none">
|
<div class="space-x-2 flex flex-none">
|
||||||
<span
|
<span
|
||||||
v-if="isDrawInitials"
|
v-if="isDrawInitials"
|
||||||
class="tooltip"
|
class="md:tooltip"
|
||||||
:data-tip="t('type_initial')"
|
:data-tip="t('type_initial')"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-else
|
v-else
|
||||||
class="tooltip ml-2"
|
class="md:tooltip ml-2"
|
||||||
:data-tip="t('draw_initials')"
|
:data-tip="t('draw_initials')"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class="tooltip"
|
class="md:tooltip"
|
||||||
:data-tip="t('click_to_upload')"
|
:data-tip="t('click_to_upload')"
|
||||||
>
|
>
|
||||||
<label class="btn btn-outline btn-sm font-medium inline-flex flex-nowrap upload-image-button">
|
<label class="btn btn-outline btn-sm font-medium inline-flex flex-nowrap upload-image-button">
|
||||||
|
|||||||
@@ -100,7 +100,7 @@
|
|||||||
<input
|
<input
|
||||||
:id="field.uuid"
|
:id="field.uuid"
|
||||||
ref="phone"
|
ref="phone"
|
||||||
:value="phoneValue"
|
:value="defaultValue && detectedPhoneValueDialCode ? phoneValue.split('+' + detectedPhoneValueDialCode).slice(-1).join('') : phoneValue"
|
||||||
:readonly="!!defaultValue"
|
:readonly="!!defaultValue"
|
||||||
class="base-input !text-2xl !rounded-l-none !border-l-0 !outline-none w-full"
|
class="base-input !text-2xl !rounded-l-none !border-l-0 !outline-none w-full"
|
||||||
autocomplete="tel"
|
autocomplete="tel"
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
<div class="space-x-2 flex flex-none">
|
<div class="space-x-2 flex flex-none">
|
||||||
<span
|
<span
|
||||||
v-if="isTextSignature && format !== 'typed_or_upload' && format !== 'typed' && format !== 'upload'"
|
v-if="isTextSignature && format !== 'typed_or_upload' && format !== 'typed' && format !== 'upload'"
|
||||||
class="tooltip"
|
class="md:tooltip"
|
||||||
:data-tip="t('draw_signature')"
|
:data-tip="t('draw_signature')"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-else-if="withTypedSignature && format !== 'drawn_or_upload' && format !== 'typed_or_upload' && format !== 'typed' && format !== 'drawn' && format !== 'upload'"
|
v-else-if="withTypedSignature && format !== 'drawn_or_upload' && format !== 'typed_or_upload' && format !== 'typed' && format !== 'drawn' && format !== 'upload'"
|
||||||
class="tooltip ml-2"
|
class="md:tooltip ml-2"
|
||||||
:class="{ 'hidden sm:inline': modelValue || computedPreviousValue }"
|
:class="{ 'hidden sm:inline': modelValue || computedPreviousValue }"
|
||||||
:data-tip="t('type_text')"
|
:data-tip="t('type_text')"
|
||||||
>
|
>
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-if="format !== 'typed' && format !== 'drawn' && format !== 'upload' && format !== 'drawn_or_typed'"
|
v-if="format !== 'typed' && format !== 'drawn' && format !== 'upload' && format !== 'drawn_or_typed'"
|
||||||
class="tooltip"
|
class="md:tooltip"
|
||||||
:class="{ 'hidden sm:inline': modelValue || computedPreviousValue }"
|
:class="{ 'hidden sm:inline': modelValue || computedPreviousValue }"
|
||||||
:data-tip="t('take_photo')"
|
:data-tip="t('take_photo')"
|
||||||
>
|
>
|
||||||
@@ -86,8 +86,8 @@
|
|||||||
</a>
|
</a>
|
||||||
<span
|
<span
|
||||||
v-if="withQrButton && !modelValue && !computedPreviousValue && format !== 'typed_or_upload' && format !== 'typed' && format !== 'upload'"
|
v-if="withQrButton && !modelValue && !computedPreviousValue && format !== 'typed_or_upload' && format !== 'typed' && format !== 'upload'"
|
||||||
class="tooltip before:translate-x-[-90%]"
|
class="md:tooltip before:translate-x-[-90%]"
|
||||||
:data-tip="t('drawn_signature_on_a_touchscreen_device')"
|
:data-tip="t('sign_on_the_touchscreen')"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="#"
|
||||||
@@ -142,7 +142,7 @@
|
|||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else
|
||||||
class="relative"
|
class="relative select-none"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="!modelValue && !computedPreviousValue && !isShowQr && !isTextSignature && isSignatureStarted"
|
v-if="!modelValue && !computedPreviousValue && !isShowQr && !isTextSignature && isSignatureStarted"
|
||||||
@@ -176,7 +176,7 @@
|
|||||||
class="top-0 bottom-0 right-0 left-0 absolute bg-base-content/10 rounded-2xl"
|
class="top-0 bottom-0 right-0 left-0 absolute bg-base-content/10 rounded-2xl"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="absolute top-1.5 right-1.5 tooltip"
|
class="absolute top-1.5 right-1.5 md:tooltip"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="#"
|
||||||
@@ -281,7 +281,7 @@
|
|||||||
<div
|
<div
|
||||||
v-else-if="withDisclosure"
|
v-else-if="withDisclosure"
|
||||||
dir="auto"
|
dir="auto"
|
||||||
class="text-base-content/60 text-xs text-center w-full mt-1"
|
class="text-base-content/60 text-xs text-center w-full mt-1 select-none"
|
||||||
>
|
>
|
||||||
{{ t('by_clicking_you_agree_to_the').replace('{button}', buttonText.charAt(0).toUpperCase() + buttonText.slice(1)) }} <a
|
{{ t('by_clicking_you_agree_to_the').replace('{button}', buttonText.charAt(0).toUpperCase() + buttonText.slice(1)) }} <a
|
||||||
href="https://www.docuseal.com/esign-disclosure"
|
href="https://www.docuseal.com/esign-disclosure"
|
||||||
|
|||||||
@@ -154,15 +154,22 @@
|
|||||||
v-if="field.options && withOptions && (isExpandOptions || field.options.length < 5)"
|
v-if="field.options && withOptions && (isExpandOptions || field.options.length < 5)"
|
||||||
ref="options"
|
ref="options"
|
||||||
class="border-t border-base-300 mx-2 pt-2 space-y-1.5"
|
class="border-t border-base-300 mx-2 pt-2 space-y-1.5"
|
||||||
draggable="true"
|
@dragover="onOptionDragover"
|
||||||
@dragstart.prevent.stop
|
@drop="reorderOptions"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(option, index) in field.options"
|
v-for="(option, index) in field.options"
|
||||||
:key="option.uuid"
|
:key="option.uuid"
|
||||||
class="flex space-x-1.5 items-center"
|
class="flex space-x-1.5 items-center"
|
||||||
|
:data-option-uuid="option.uuid"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="text-sm w-3.5 cursor-grab select-none"
|
||||||
|
:draggable="editable && !defaultField"
|
||||||
|
@dragstart.stop="onOptionDragstart($event, option)"
|
||||||
|
@dragend.stop="optionDragRef = null"
|
||||||
|
@dragover.prevent.stop="onOptionDragover"
|
||||||
>
|
>
|
||||||
<span class="text-sm w-3.5">
|
|
||||||
{{ index + 1 }}.
|
{{ index + 1 }}.
|
||||||
</span>
|
</span>
|
||||||
<div
|
<div
|
||||||
@@ -176,6 +183,7 @@
|
|||||||
dir="auto"
|
dir="auto"
|
||||||
required
|
required
|
||||||
:placeholder="`${t('option')} ${index + 1}`"
|
:placeholder="`${t('option')} ${index + 1}`"
|
||||||
|
@keydown.enter="option.value ? addOptionAt(index + 1) : null"
|
||||||
@blur="save"
|
@blur="save"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
@@ -198,6 +206,7 @@
|
|||||||
:readonly="!editable || defaultField"
|
:readonly="!editable || defaultField"
|
||||||
required
|
required
|
||||||
dir="auto"
|
dir="auto"
|
||||||
|
@keydown.enter="option.value ? addOptionAt(index + 1) : null"
|
||||||
@focus="maybeFocusOnOptionArea(option)"
|
@focus="maybeFocusOnOptionArea(option)"
|
||||||
@blur="save"
|
@blur="save"
|
||||||
>
|
>
|
||||||
@@ -217,7 +226,7 @@
|
|||||||
<button
|
<button
|
||||||
v-else-if="field.options && editable && !defaultField"
|
v-else-if="field.options && editable && !defaultField"
|
||||||
class="field-add-option text-center text-sm w-full pb-1"
|
class="field-add-option text-center text-sm w-full pb-1"
|
||||||
@click="addOption"
|
@click="addOptionAt(field.options.length)"
|
||||||
>
|
>
|
||||||
+ {{ t('add_option') }}
|
+ {{ t('add_option') }}
|
||||||
</button>
|
</button>
|
||||||
@@ -363,7 +372,8 @@ export default {
|
|||||||
isShowFontModal: false,
|
isShowFontModal: false,
|
||||||
isShowConditionsModal: false,
|
isShowConditionsModal: false,
|
||||||
isShowDescriptionModal: false,
|
isShowDescriptionModal: false,
|
||||||
renderDropdown: false
|
renderDropdown: false,
|
||||||
|
optionDragRef: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -450,15 +460,17 @@ export default {
|
|||||||
closeDropdown () {
|
closeDropdown () {
|
||||||
this.$el.getRootNode().activeElement.blur()
|
this.$el.getRootNode().activeElement.blur()
|
||||||
},
|
},
|
||||||
addOption () {
|
addOptionAt (index) {
|
||||||
this.isExpandOptions = true
|
this.isExpandOptions = true
|
||||||
|
|
||||||
this.field.options.push({ value: '', uuid: v4() })
|
const insertAt = index ?? this.field.options.length
|
||||||
|
|
||||||
|
this.field.options.splice(insertAt, 0, { value: '', uuid: v4() })
|
||||||
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const inputs = this.$refs.options.querySelectorAll('input')
|
const inputs = this.$refs.options.querySelectorAll('input')
|
||||||
|
|
||||||
inputs[inputs.length - 1]?.focus()
|
inputs[insertAt]?.focus()
|
||||||
})
|
})
|
||||||
|
|
||||||
this.save()
|
this.save()
|
||||||
@@ -515,6 +527,70 @@ export default {
|
|||||||
this.isNameFocus = false
|
this.isNameFocus = false
|
||||||
|
|
||||||
this.save()
|
this.save()
|
||||||
|
},
|
||||||
|
onOptionDragstart (event, option) {
|
||||||
|
this.optionDragRef = option
|
||||||
|
|
||||||
|
const root = this.$el.getRootNode()
|
||||||
|
const hiddenEl = document.createElement('div')
|
||||||
|
|
||||||
|
hiddenEl.style.width = '1px'
|
||||||
|
hiddenEl.style.height = '1px'
|
||||||
|
hiddenEl.style.opacity = '0'
|
||||||
|
hiddenEl.style.position = 'fixed'
|
||||||
|
|
||||||
|
root.querySelector('#docuseal_modal_container')?.appendChild(hiddenEl)
|
||||||
|
event.dataTransfer?.setDragImage(hiddenEl, 0, 0)
|
||||||
|
|
||||||
|
setTimeout(() => { hiddenEl.remove() }, 1000)
|
||||||
|
|
||||||
|
event.dataTransfer.effectAllowed = 'move'
|
||||||
|
},
|
||||||
|
onOptionDragover (e) {
|
||||||
|
if (!this.optionDragRef) return
|
||||||
|
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
|
||||||
|
const targetRow = e.target.closest('[data-option-uuid]')
|
||||||
|
|
||||||
|
if (!targetRow) return
|
||||||
|
|
||||||
|
const dragRow = this.$refs.options?.querySelector(`[data-option-uuid="${this.optionDragRef.uuid}"]`)
|
||||||
|
|
||||||
|
if (!dragRow) return
|
||||||
|
if (targetRow === dragRow) return
|
||||||
|
|
||||||
|
const rows = Array.from(this.$refs.options.querySelectorAll('[data-option-uuid]'))
|
||||||
|
|
||||||
|
const currentIndex = rows.indexOf(dragRow)
|
||||||
|
const targetIndex = rows.indexOf(targetRow)
|
||||||
|
|
||||||
|
if (currentIndex < targetIndex) {
|
||||||
|
targetRow.after(dragRow)
|
||||||
|
} else {
|
||||||
|
targetRow.before(dragRow)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
reorderOptions (e) {
|
||||||
|
if (!this.optionDragRef) return
|
||||||
|
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
|
||||||
|
const rows = Array.from(this.$refs.options.querySelectorAll('[data-option-uuid]'))
|
||||||
|
|
||||||
|
const newOrder = rows
|
||||||
|
.map((el) => this.field.options.find((opt) => opt.uuid === el.dataset.optionUuid))
|
||||||
|
.filter(Boolean)
|
||||||
|
|
||||||
|
if (newOrder.length === this.field.options.length) {
|
||||||
|
this.field.options.splice(0, this.field.options.length, ...newOrder)
|
||||||
|
|
||||||
|
this.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.optionDragRef = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
ref="fields"
|
ref="fields"
|
||||||
class="fields mb-1 mt-2"
|
class="fields mb-1 mt-2"
|
||||||
@dragover.prevent="onFieldDragover"
|
@dragover.prevent="onFieldDragover"
|
||||||
@drop="reorderFields"
|
@drop="fieldsDragFieldRef.value ? reorderFields() : null"
|
||||||
>
|
>
|
||||||
<Field
|
<Field
|
||||||
v-for="field in submitterFields"
|
v-for="field in submitterFields"
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ class SendSubmitterVerificationEmailJob
|
|||||||
def perform(params = {})
|
def perform(params = {})
|
||||||
submitter = Submitter.find(params['submitter_id'])
|
submitter = Submitter.find(params['submitter_id'])
|
||||||
|
|
||||||
SubmitterMailer.otp_verification_email(submitter).deliver_now!
|
locale = params['locale'].presence || submitter.account.locale
|
||||||
|
|
||||||
|
SubmitterMailer.otp_verification_email(submitter, locale:).deliver_now!
|
||||||
|
|
||||||
SubmissionEvent.create!(submitter_id: params['submitter_id'],
|
SubmissionEvent.create!(submitter_id: params['submitter_id'],
|
||||||
event_type: 'send_2fa_email',
|
event_type: 'send_2fa_email',
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ class SendTestWebhookRequestJob
|
|||||||
|
|
||||||
USER_AGENT = 'DocuSeal.com Webhook'
|
USER_AGENT = 'DocuSeal.com Webhook'
|
||||||
|
|
||||||
|
HttpsError = Class.new(StandardError)
|
||||||
|
LocalhostError = Class.new(StandardError)
|
||||||
|
|
||||||
def perform(params = {})
|
def perform(params = {})
|
||||||
submitter = Submitter.find_by(id: params['submitter_id'])
|
submitter = Submitter.find_by(id: params['submitter_id'])
|
||||||
|
|
||||||
@@ -16,6 +19,17 @@ class SendTestWebhookRequestJob
|
|||||||
|
|
||||||
return unless webhook_url
|
return unless webhook_url
|
||||||
|
|
||||||
|
if Docuseal.multitenant?
|
||||||
|
uri = begin
|
||||||
|
URI(webhook_url.url)
|
||||||
|
rescue URI::Error
|
||||||
|
Addressable::URI.parse(webhook_url.url).normalize
|
||||||
|
end
|
||||||
|
|
||||||
|
raise HttpsError, 'Only HTTPS is allowed.' if uri.scheme != 'https'
|
||||||
|
raise LocalhostError, "Can't send to localhost." if uri.host.in?(SendWebhookRequest::LOCALHOSTS)
|
||||||
|
end
|
||||||
|
|
||||||
Faraday.post(webhook_url.url,
|
Faraday.post(webhook_url.url,
|
||||||
{
|
{
|
||||||
event_type: 'form.completed',
|
event_type: 'form.completed',
|
||||||
|
|||||||
@@ -144,13 +144,13 @@ class SubmitterMailer < ApplicationMailer
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def otp_verification_email(submitter)
|
def otp_verification_email(submitter, locale: nil)
|
||||||
@submitter = submitter
|
@submitter = submitter
|
||||||
@otp_code = EmailVerificationCodes.generate([submitter.email.downcase.strip, submitter.slug].join(':'))
|
@otp_code = EmailVerificationCodes.generate([submitter.email.downcase.strip, submitter.slug].join(':'))
|
||||||
|
|
||||||
assign_message_metadata('otp_verification_email', submitter)
|
assign_message_metadata('otp_verification_email', submitter)
|
||||||
|
|
||||||
I18n.with_locale(submitter.account.locale) do
|
I18n.with_locale(locale || submitter.account.locale) do
|
||||||
mail(to: submitter.email, subject: I18n.t('email_verification'))
|
mail(to: submitter.email, subject: I18n.t('email_verification'))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -45,10 +45,12 @@ class AccountConfig < ApplicationRecord
|
|||||||
WITH_SIGNATURE_ID = 'with_signature_id'
|
WITH_SIGNATURE_ID = 'with_signature_id'
|
||||||
WITH_FILE_LINKS_KEY = 'with_file_links'
|
WITH_FILE_LINKS_KEY = 'with_file_links'
|
||||||
WITH_SIGNATURE_ID_REASON_KEY = 'with_signature_id_reason'
|
WITH_SIGNATURE_ID_REASON_KEY = 'with_signature_id_reason'
|
||||||
|
RECIPIENT_FORM_FIELDS_KEY = 'recipient_form_fields'
|
||||||
WITH_AUDIT_VALUES_KEY = 'with_audit_values'
|
WITH_AUDIT_VALUES_KEY = 'with_audit_values'
|
||||||
WITH_SUBMITTER_TIMEZONE_KEY = 'with_submitter_timezone'
|
WITH_SUBMITTER_TIMEZONE_KEY = 'with_submitter_timezone'
|
||||||
REQUIRE_SIGNING_REASON_KEY = 'require_signing_reason'
|
REQUIRE_SIGNING_REASON_KEY = 'require_signing_reason'
|
||||||
REUSE_SIGNATURE_KEY = 'reuse_signature'
|
REUSE_SIGNATURE_KEY = 'reuse_signature'
|
||||||
|
WITH_FIELD_LABELS_KEY = 'with_field_labels'
|
||||||
COMBINE_PDF_RESULT_KEY = 'combine_pdf_result_key'
|
COMBINE_PDF_RESULT_KEY = 'combine_pdf_result_key'
|
||||||
DOCUMENT_FILENAME_FORMAT_KEY = 'document_filename_format'
|
DOCUMENT_FILENAME_FORMAT_KEY = 'document_filename_format'
|
||||||
POLICY_LINKS_KEY = 'policy_links'
|
POLICY_LINKS_KEY = 'policy_links'
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M4 5m0 2a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2z"></path>
|
||||||
|
<path d="M16 3l0 4"></path>
|
||||||
|
<path d="M8 3l0 4"></path>
|
||||||
|
<path d="M4 11l16 0"></path>
|
||||||
|
<path d="M8 15h2v2h-2z"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 450 B |
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M9 11l3 3l8 -8"></path>
|
||||||
|
<path d="M20 12v6a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2h9"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 346 B |
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M7 12l5 5l10 -10"></path>
|
||||||
|
<path d="M2 12l5 5m5 -5l5 -5"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 303 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M3 3m0 1a1 1 0 0 1 1 -1h16a1 1 0 0 1 1 1v16a1 1 0 0 1 -1 1h-16a1 1 0 0 1 -1 -1zm6 -1v18m6 -18v18"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 343 B |
@@ -0,0 +1,6 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M3 5m0 3a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3z"></path>
|
||||||
|
<path d="M3 10l18 0"></path>
|
||||||
|
<path d="M7 15l.01 0"></path>
|
||||||
|
<path d="M11 15l2 0"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 419 B |
@@ -0,0 +1,7 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M3 4m0 3a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v10a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3z"></path>
|
||||||
|
<path d="M9 10m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0"></path>
|
||||||
|
<path d="M15 8l2 0"></path>
|
||||||
|
<path d="M15 12l2 0"></path>
|
||||||
|
<path d="M7 16l10 0"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 478 B |
@@ -0,0 +1,6 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M3 19v-10.5a3.5 3.5 0 0 1 7 0v10.5"></path>
|
||||||
|
<path d="M3 13h7"></path>
|
||||||
|
<path d="M14 19v-10.5a3.5 3.5 0 0 1 7 0v10.5"></path>
|
||||||
|
<path d="M14 13h7"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 394 B |
@@ -0,0 +1,6 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M15 8h.01"></path>
|
||||||
|
<path d="M3 6a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v12a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3v-12z"></path>
|
||||||
|
<path d="M3 16l5 -5c.928 -.893 2.072 -.893 3 0l5 5"></path>
|
||||||
|
<path d="M14 14l1 -1c.928 -.893 2.072 -.893 3 0l3 3"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 481 B |
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M21 17.85h-18c0 -4.05 1.421 -4.05 3.79 -4.05c5.21 0 1.21 -4.59 1.21 -6.8a4 4 0 1 1 8 0c0 2.21 -4 6.8 1.21 6.8c2.369 0 3.79 0 3.79 4.05z"></path>
|
||||||
|
<path d="M5 21h14"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 411 B |
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M3 3m0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v14a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z"></path>
|
||||||
|
<path d="M9 11l3 3l3 -3"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 361 B |
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M3 3m0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v14a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z"></path>
|
||||||
|
<path d="M10 10l2 -2v8"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 360 B |
@@ -0,0 +1,8 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M3 7v-2h13v2"></path>
|
||||||
|
<path d="M10 5v14"></path>
|
||||||
|
<path d="M12 19h-4"></path>
|
||||||
|
<path d="M15 13v-1h6v1"></path>
|
||||||
|
<path d="M18 12v7"></path>
|
||||||
|
<path d="M17 19h2"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 410 B |
@@ -1,6 +1,6 @@
|
|||||||
<a target="_blank" href="<%= Docuseal::GITHUB_URL %>" rel="noopener noreferrer nofollow" class="relative flex items-center rounded-full px-2 py-0.5 text-xs leading-4 mt-1 text-base-content border border-base-300 tooltip tooltip-bottom" data-tip="Give a star on GitHub">
|
<a target="_blank" href="<%= Docuseal::GITHUB_URL %>" rel="noopener noreferrer nofollow" class="relative flex items-center rounded-full px-2 py-0.5 text-xs leading-4 mt-1 text-base-content border border-base-300 tooltip tooltip-bottom" data-tip="Give a star on GitHub">
|
||||||
<span class="flex items-center justify-between space-x-0.5 font-medium">
|
<span class="flex items-center justify-between space-x-0.5 font-medium">
|
||||||
<%= svg_icon('start', class: 'h-3 w-3') %>
|
<%= svg_icon('start', class: 'h-3 w-3') %>
|
||||||
<span>10k</span>
|
<span>11k</span>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -12,7 +12,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="grid <%= 'md:grid-cols-2' if submitters.size > 1 %> gap-4">
|
<div class="grid <%= 'md:grid-cols-2' if submitters.size > 1 %> gap-4">
|
||||||
<% submitters.each_with_index do |item, index| %>
|
<% submitters.each_with_index do |item, index| %>
|
||||||
<% prefillable_fields = local_assigns[:prefillable_fields].to_a.select { |f| f['submitter_uuid'] == item['uuid'] } %>
|
<% prefillable_fields = local_assigns[:prefillable_fields].to_a.select { |f| f['submitter_uuid'] == item['uuid'] }.presence %>
|
||||||
|
<% prefillable_fields ||= local_assigns[:recipient_form_fields].presence %>
|
||||||
<submitter-item class="form-control">
|
<submitter-item class="form-control">
|
||||||
<% if submitters.size > 1 %>
|
<% if submitters.size > 1 %>
|
||||||
<label class="label pt-0 pb-1">
|
<label class="label pt-0 pb-1">
|
||||||
@@ -29,14 +30,14 @@
|
|||||||
<div class="grid <%= 'md:grid-cols-2 gap-1' if submitters.size == 1 %>">
|
<div class="grid <%= 'md:grid-cols-2 gap-1' if submitters.size == 1 %>">
|
||||||
<submitters-autocomplete data-field="email">
|
<submitters-autocomplete data-field="email">
|
||||||
<linked-input data-target-id="<%= "detailed_email_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
<linked-input data-target-id="<%= "detailed_email_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||||
<%= tag.input type: 'email', multiple: true, name: 'submission[1][submitters][][email]', autocomplete: 'off', class: 'base-input !h-10 mt-1.5 w-full', placeholder: (local_assigns[:require_email_2fa] == true ? t(:email) : "#{t('email')} (#{t('optional')})"), value: item['email'].presence || ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.email : ''), id: "detailed_email_#{item['uuid']}", required: local_assigns[:require_email_2fa] == true %>
|
<%= tag.input type: 'email', multiple: true, name: 'submission[1][submitters][][email]', autocomplete: 'off', class: 'base-input !h-10 mt-1.5 w-full', placeholder: (local_assigns[:require_email_2fa] == true || local_assigns[:prefillable_fields].present? ? t(:email) : "#{t('email')} (#{t('optional')})"), value: item['email'].presence || ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.email : ''), id: "detailed_email_#{item['uuid']}", required: local_assigns[:require_email_2fa] == true %>
|
||||||
</linked-input>
|
</linked-input>
|
||||||
</submitters-autocomplete>
|
</submitters-autocomplete>
|
||||||
<% has_phone_field = true %>
|
<% has_phone_field = true %>
|
||||||
<custom-validation data-invalid-message="<%= t('use_international_format_1xxx_') %>">
|
<custom-validation data-invalid-message="<%= t('use_international_format_1xxx_') %>">
|
||||||
<submitters-autocomplete data-field="phone">
|
<submitters-autocomplete data-field="phone">
|
||||||
<linked-input data-target-id="<%= "detailed_phone_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
<linked-input data-target-id="<%= "detailed_phone_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||||
<%= tag.input type: 'tel', pattern: '^\+[0-9\s\-]+$', 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 %>
|
<%= tag.input type: 'tel', pattern: '^\+[0-9\s\-]+$', name: 'submission[1][submitters][][phone]', autocomplete: 'off', class: 'base-input !h-10 mt-1.5 w-full', placeholder: local_assigns[:require_phone_2fa] == true || local_assigns[:prefillable_fields].present? ? t(:phone) : "#{t('phone')} (#{t('optional')})", id: "detailed_phone_#{item['uuid']}", required: local_assigns[:require_phone_2fa] == true %>
|
||||||
</linked-input>
|
</linked-input>
|
||||||
</submitters-autocomplete>
|
</submitters-autocomplete>
|
||||||
</custom-validation>
|
</custom-validation>
|
||||||
@@ -59,17 +60,23 @@
|
|||||||
</custom-validation>
|
</custom-validation>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% prefillable_fields.each do |field| %>
|
<% prefillable_fields.each do |field| %>
|
||||||
|
<% field_id = "detailed_field_#{index}_#{field['uuid'] || field['name'].parameterize}" %>
|
||||||
<% if field['type'] == 'checkbox' %>
|
<% if field['type'] == 'checkbox' %>
|
||||||
<label for="detailed_field_<%= field['uuid'] %>" class="flex items-center justify-between mt-1.5 pl-3 pr-2.5 h-10 border border-base-content/20 rounded-full cursor-pointer transition-colors bg-white">
|
<label for="<%= field_id %>" class="flex items-center justify-between mt-1.5 pl-3 pr-2.5 h-10 border border-base-content/20 rounded-full cursor-pointer transition-colors bg-white">
|
||||||
<span class="text-base select-none px-1"> <%= field['title'].presence || field['name'] %></span>
|
<span class="text-base select-none px-1"> <%= field['title'].presence || field['name'] %></span>
|
||||||
<%= tag.input type: 'checkbox', name: "submission[1][submitters][][values][#{field['uuid']}]", id: "detailed_field_#{field['uuid']}", class: 'toggle toggle-sm', style: 'width: 38px; --handleoffset: 17px', checked: field['default_value'].present? && (field['default_value'] == true || field['default_value'].to_s == '1' || field['default_value'].to_s.downcase == 'true'), required: field['required'], value: 'true' %>
|
<%= tag.input type: 'checkbox', name: "submission[1][submitters][][values][#{field['uuid'] || field['name']}]", id: field_id, class: 'toggle toggle-sm', style: 'width: 38px; --handleoffset: 17px', checked: field['default_value'].present? && (field['default_value'] == true || field['default_value'].to_s == '1' || field['default_value'].to_s.downcase == 'true'), required: field['required'], value: 'true' %>
|
||||||
</label>
|
</label>
|
||||||
<% elsif field['type'] == 'select' || field['type'] == 'radio' %>
|
<% elsif field['type'] == 'select' || field['type'] == 'radio' %>
|
||||||
<%= select_tag "submission[1][submitters][][values][#{field['uuid']}]", options_for_select(field['options'].pluck('value'), field['default_value']), prompt: t(:select), id: "detailed_field_#{field['uuid']}", class: 'select select-sm base-input !h-10 mt-1.5 ', required: field['required'] %>
|
<%= select_tag "submission[1][submitters][][values][#{field['uuid'] || field['name']}]", options_for_select(field['options'].pluck('value'), field['default_value']), prompt: t(:select), id: field_id, class: 'select select-sm base-input !h-10 mt-1.5 ', required: field['required'] %>
|
||||||
<% elsif field['type'] == 'date' %>
|
<% elsif field['type'] == 'date' %>
|
||||||
<%= tag.input type: field['type'], name: "submission[1][submitters][][values][#{field['uuid']}]", autocomplete: 'off', class: 'base-input !h-10 mt-1.5 w-full border rounded p-3', placeholder: (field['required'] ? field['title'].presence || field['name'] : "#{field['title'].presence || field['name']} (#{t('optional')})"), value: field['default_value'], id: "detailed_field_#{field['uuid']}", required: field['required'] %>
|
<%= tag.input type: field['type'], name: "submission[1][submitters][][values][#{field['uuid'] || field['name']}]", autocomplete: 'off', class: 'base-input !h-10 mt-1.5 w-full border rounded p-3', placeholder: (field['required'] ? field['title'].presence || field['name'] : "#{field['title'].presence || field['name']} (#{t('optional')})"), value: field['default_value'], id: field_id, required: field['required'] %>
|
||||||
<% elsif field['type'] != 'phone' %>
|
<% elsif field['type'] != 'phone' %>
|
||||||
<%= tag.input type: field['type'], name: "submission[1][submitters][][values][#{field['uuid']}]", autocomplete: 'off', class: 'base-input !h-10 mt-1.5 w-full border rounded p-3', placeholder: (field['required'] ? field['title'].presence || field['name'] : "#{field['title'].presence || field['name']} (#{t('optional')})"), value: field['default_value'], id: "detailed_field_#{field['uuid']}", required: field['required'] %>
|
<%= tag.input type: field['type'], name: "submission[1][submitters][][values][#{field['uuid'] || field['name']}]", autocomplete: 'off', class: 'base-input !h-10 mt-1.5 w-full border rounded p-3', placeholder: (field['required'] ? field['title'].presence || field['name'] : "#{field['title'].presence || field['name']} (#{t('optional')})"), value: field['default_value'], id: field_id, required: field['required'] %>
|
||||||
|
<% end %>
|
||||||
|
<% field['conditions']&.each do |condition| %>
|
||||||
|
<% if (condition_field = prefillable_fields.find { |f| f['uuid'] == condition['field_uuid'] || f['name'] == condition['field_name'] }) %>
|
||||||
|
<field-condition data-target-id="<%= field_id %>" data-field-id="<%= "detailed_field_#{index}_#{condition['field_uuid'] || condition['field_name'].parameterize}" %>" data-action="<%= condition['action'] %>" data-value="<%= condition_field['options'].present? ? condition_field['options'].find { |o| o['uuid'] == condition['value'] }&.dig('value') || condition['value'] : condition['value'] %>" data-operation="<%= condition['operation'] %>"></field-condition>
|
||||||
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -79,7 +86,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% if params[:selfsign].blank? && local_assigns[:prefillable_fields].blank? %>
|
<% if params[:selfsign].blank? && local_assigns[:prefillable_fields].blank? && local_assigns[:recipient_form_fields].blank? %>
|
||||||
<a href="#" class="btn btn-primary btn-sm w-full flex items-center justify-center" data-action="click:dynamic-list#addItem">
|
<a href="#" class="btn btn-primary btn-sm w-full flex items-center justify-center" data-action="click:dynamic-list#addItem">
|
||||||
<%= svg_icon('user_plus', class: 'w-4 h-4 stroke-2') %>
|
<%= svg_icon('user_plus', class: 'w-4 h-4 stroke-2') %>
|
||||||
<span><%= t('add_new') %></span>
|
<span><%= t('add_new') %></span>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<% font_size_px = (field.dig('preferences', 'font_size').presence || Submissions::GenerateResultAttachments::FONT_SIZE).to_i * local_assigns.fetch(:font_scale) { 1000.0 / PdfUtils::US_LETTER_W } %>
|
<% font_size_px = (field.dig('preferences', 'font_size').presence || Submissions::GenerateResultAttachments::FONT_SIZE).to_i * local_assigns.fetch(:font_scale) { 1000.0 / PdfUtils::US_LETTER_W } %>
|
||||||
<field-value dir="auto" class="flex absolute <%= 'font-courier' if font == 'Courier' %> <%= 'font-times' if font == 'Times' %> <%= 'font-bold' if font_type == 'bold' || font_type == 'bold_italic' %> <%= 'italic' if font_type == 'italic' || font_type == 'bold_italic' %> <%= align == 'right' ? 'text-right' : (align == 'center' ? 'text-center' : '') %>" style="<%= "color: #{color}; " if color.present? %><%= "background: #{bg_color}; " if bg_color.present? %>width: <%= area['w'] * 100 %>%; height: <%= area['h'] * 100 %>%; left: <%= area['x'] * 100 %>%; top: <%= area['y'] * 100 %>%; font-size: <%= fs = "clamp(1pt, #{font_size_px / 10}vw, #{font_size_px}px)" %>; line-height: calc(<%= fs %> * 1.3); font-size: <%= fs = "#{font_size_px / 10}cqmin" %>; line-height: calc(<%= fs %> * 1.3)">
|
<field-value dir="auto" class="flex absolute <%= 'font-courier' if font == 'Courier' %> <%= 'font-times' if font == 'Times' %> <%= 'font-bold' if font_type == 'bold' || font_type == 'bold_italic' %> <%= 'italic' if font_type == 'italic' || font_type == 'bold_italic' %> <%= align == 'right' ? 'text-right' : (align == 'center' ? 'text-center' : '') %>" style="<%= "color: #{color}; " if color.present? %><%= "background: #{bg_color}; " if bg_color.present? %>width: <%= area['w'] * 100 %>%; height: <%= area['h'] * 100 %>%; left: <%= area['x'] * 100 %>%; top: <%= area['y'] * 100 %>%; font-size: <%= fs = "clamp(1pt, #{font_size_px / 10}vw, #{font_size_px}px)" %>; line-height: calc(<%= fs %> * 1.3); font-size: <%= fs = "#{font_size_px / 10}cqmin" %>; line-height: calc(<%= fs %> * 1.3)">
|
||||||
<% if field['type'] == 'signature' %>
|
<% if field['type'] == 'signature' %>
|
||||||
<% is_narrow = area['h']&.positive? && (area['w'].to_f / area['h']) > 6 %>
|
<% is_narrow = area['h'].positive? && ((area['w'] * local_assigns[:page_width]).to_f / (area['h'] * local_assigns[:page_height])) > 4.5 %>
|
||||||
<div class="flex justify-between w-full h-full gap-1 <%= is_narrow && (local_assigns[:with_signature_id] || field.dig('preferences', 'reason_field_uuid').present?) ? 'flex-row' : 'flex-col' %>">
|
<div class="flex justify-between w-full h-full gap-1 <%= is_narrow && (local_assigns[:with_signature_id] || field.dig('preferences', 'reason_field_uuid').present?) ? 'flex-row' : 'flex-col' %>">
|
||||||
<div class="flex overflow-hidden <%= is_narrow && (local_assigns[:with_signature_id] || field.dig('preferences', 'reason_field_uuid').present?) ? 'w-1/2' : 'flex-grow' %>" style="min-height: 50%">
|
<div class="flex overflow-hidden <%= is_narrow && (local_assigns[:with_signature_id] || field.dig('preferences', 'reason_field_uuid').present?) ? 'w-1/2' : 'flex-grow' %>" style="min-height: 50%">
|
||||||
<img class="object-contain mx-auto" src="<%= attachments_index[value].url %>">
|
<img class="object-contain mx-auto" src="<%= attachments_index[value].url %>">
|
||||||
@@ -50,13 +50,14 @@
|
|||||||
<%= svg_icon('check', class: "aspect-square #{area['w'] > area['h'] ? '!w-auto !h-full' : '!w-full !h-auto'}") %>
|
<%= svg_icon('check', class: "aspect-square #{area['w'] > area['h'] ? '!w-auto !h-full' : '!w-full !h-auto'}") %>
|
||||||
</div>
|
</div>
|
||||||
<% elsif field['type'].in?(%w[multiple radio]) && area['option_uuid'] %>
|
<% elsif field['type'].in?(%w[multiple radio]) && area['option_uuid'] %>
|
||||||
<% option = field['options']&.find { |o| o['uuid'] == area['option_uuid'] } %>
|
<% if (option = field['options']&.find { |o| o['uuid'] == area['option_uuid'] }) %>
|
||||||
<% option_name = option['value'].presence || "Option #{field['options'].index(option) + 1}" %>
|
<% option_name = option['value'].presence || "Option #{field['options'].index(option) + 1}" %>
|
||||||
<% if option && Array.wrap(value).include?(option_name) %>
|
<% if Array.wrap(value).include?(option_name) %>
|
||||||
<div class="w-full flex items-center justify-center">
|
<div class="w-full flex items-center justify-center">
|
||||||
<%= svg_icon('check', class: "aspect-square #{area['w'] > area['h'] ? '!w-auto !h-full' : '!w-full !h-auto'}") %>
|
<%= svg_icon('check', class: "aspect-square #{area['w'] > area['h'] ? '!w-auto !h-full' : '!w-full !h-auto'}") %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<% end %>
|
||||||
<% elsif field['type'] == 'cells' && area['cell_w'].to_f > 0.0 %>
|
<% elsif field['type'] == 'cells' && area['cell_w'].to_f > 0.0 %>
|
||||||
<% cell_width = area['cell_w'] / area['w'] * 100 %>
|
<% cell_width = area['cell_w'] / area['w'] * 100 %>
|
||||||
<div class="w-full flex items-center <%= 'justify-end' if align == 'right' %>">
|
<div class="w-full flex items-center <%= 'justify-end' if align == 'right' %>">
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<% require_phone_2fa = @template.preferences['require_phone_2fa'] == true %>
|
<% require_phone_2fa = @template.preferences['require_phone_2fa'] == true %>
|
||||||
<% require_email_2fa = @template.preferences['require_email_2fa'] == true %>
|
<% require_email_2fa = @template.preferences['require_email_2fa'] == true %>
|
||||||
<% prefillable_fields = @template.fields.select { |f| f['prefillable'] } %>
|
<% prefillable_fields = @template.fields.select { |f| f['prefillable'] } %>
|
||||||
<% only_detailed = require_phone_2fa || require_email_2fa || prefillable_fields.present? %>
|
<% recipient_form_fields = Accounts.load_recipient_form_fields(current_account) if prefillable_fields.blank? %>
|
||||||
|
<% only_detailed = require_phone_2fa || require_email_2fa || prefillable_fields.present? || recipient_form_fields.present? %>
|
||||||
<%= render 'shared/turbo_modal_large', title: params[:selfsign] ? t('add_recipients') : t('add_new_recipients') do %>
|
<%= render 'shared/turbo_modal_large', title: params[:selfsign] ? t('add_recipients') : t('add_new_recipients') do %>
|
||||||
<% options = [only_detailed ? nil : [t('via_email'), 'email'], only_detailed ? nil : [t('via_phone'), 'phone'], [t('detailed'), 'detailed'], [t('upload_list'), 'list']].compact %>
|
<% options = [only_detailed ? nil : [t('via_email'), 'email'], only_detailed ? nil : [t('via_phone'), 'phone'], [t('detailed'), 'detailed'], [t('upload_list'), 'list']].compact %>
|
||||||
<toggle-visible data-element-ids="<%= options.map(&:last).to_json %>" class="relative text-center px-2 mt-4 block">
|
<toggle-visible data-element-ids="<%= options.map(&:last).to_json %>" class="relative text-center px-2 mt-4 block">
|
||||||
@@ -26,7 +27,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<div id="detailed" class="<%= 'hidden' unless only_detailed %>">
|
<div id="detailed" class="<%= 'hidden' unless only_detailed %>">
|
||||||
<%= render 'detailed_form', template: @template, require_phone_2fa:, require_email_2fa:, prefillable_fields: %>
|
<%= render 'detailed_form', template: @template, require_phone_2fa:, require_email_2fa:, prefillable_fields:, recipient_form_fields: %>
|
||||||
</div>
|
</div>
|
||||||
<div id="list" class="hidden">
|
<div id="list" class="hidden">
|
||||||
<%= render 'list_form', template: @template %>
|
<%= render 'list_form', template: @template %>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<% font_scale = 1040.0 / PdfUtils::US_LETTER_W %>
|
<% font_scale = 1040.0 / PdfUtils::US_LETTER_W %>
|
||||||
<% configs = AccountConfig.where(account_id: @submission.account_id, key: [AccountConfig::COMBINE_PDF_RESULT_KEY, AccountConfig::WITH_SIGNATURE_ID, AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY, AccountConfig::WITH_SIGNATURE_ID_REASON_KEY]) %>
|
<% configs = AccountConfig.where(account_id: @submission.account_id, key: [AccountConfig::COMBINE_PDF_RESULT_KEY, AccountConfig::WITH_SIGNATURE_ID, AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY, AccountConfig::WITH_SIGNATURE_ID_REASON_KEY]) %>
|
||||||
<% with_signature_id = configs.find { |e| e.key == AccountConfig::WITH_SIGNATURE_ID }&.value == true %>
|
<% with_signature_id = configs.find { |e| e.key == AccountConfig::WITH_SIGNATURE_ID }&.value == true %>
|
||||||
<% is_combined_enabled = configs.find { |e| e.key == AccountConfig::COMBINE_PDF_RESULT_KEY }&.value == true %>
|
<% is_combined_enabled = configs.find { |e| e.key == AccountConfig::COMBINE_PDF_RESULT_KEY }&.value == true && !@submission.template_fields&.any? { |f| f['type'] == 'verification' } %>
|
||||||
<% with_submitter_timezone = configs.find { |e| e.key == AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY }&.value == true %>
|
<% with_submitter_timezone = configs.find { |e| e.key == AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY }&.value == true %>
|
||||||
<% with_signature_id_reason = configs.find { |e| e.key == AccountConfig::WITH_SIGNATURE_ID_REASON_KEY }&.value != false %>
|
<% with_signature_id_reason = configs.find { |e| e.key == AccountConfig::WITH_SIGNATURE_ID_REASON_KEY }&.value != false %>
|
||||||
<div style="max-width: 1600px" class="mx-auto pl-4">
|
<div style="max-width: 1600px" class="mx-auto pl-4">
|
||||||
@@ -93,8 +93,10 @@
|
|||||||
<div class="pr-3.5 pl-0.5">
|
<div class="pr-3.5 pl-0.5">
|
||||||
<% fields_index = Templates.build_field_areas_index(@submission.template_fields || @submission.template.fields) %>
|
<% fields_index = Templates.build_field_areas_index(@submission.template_fields || @submission.template.fields) %>
|
||||||
<% submitters_index = @submission.submitters.index_by(&:uuid) %>
|
<% submitters_index = @submission.submitters.index_by(&:uuid) %>
|
||||||
|
<% submitters_order_index = nil %>
|
||||||
<% attachments_index = ActiveStorage::Attachment.where(record: @submission.submitters, name: :attachments).preload(:blob).index_by(&:uuid) %>
|
<% attachments_index = ActiveStorage::Attachment.where(record: @submission.submitters, name: :attachments).preload(:blob).index_by(&:uuid) %>
|
||||||
<% page_blob_struct = Struct.new(:url, :metadata, keyword_init: true) %>
|
<% page_blob_struct = Struct.new(:url, :metadata, keyword_init: true) %>
|
||||||
|
<% bg_classes = %w[bg-red-100 bg-sky-100 bg-emerald-100 bg-yellow-100 bg-purple-100 bg-pink-100 bg-cyan-100 bg-orange-100 bg-lime-100 bg-indigo-100] %>
|
||||||
<% schema.each do |item| %>
|
<% schema.each do |item| %>
|
||||||
<% document = @submission.schema_documents.find { |e| e.uuid == item['attachment_uuid'] } %>
|
<% document = @submission.schema_documents.find { |e| e.uuid == item['attachment_uuid'] } %>
|
||||||
<% document_annots_index = document.metadata.dig('pdf', 'annotations')&.group_by { |e| e['page'] } || {} %>
|
<% document_annots_index = document.metadata.dig('pdf', 'annotations')&.group_by { |e| e['page'] } || {} %>
|
||||||
@@ -111,8 +113,8 @@
|
|||||||
<% fields_index.dig(document.uuid, index)&.each do |(area, field)| %>
|
<% fields_index.dig(document.uuid, index)&.each do |(area, field)| %>
|
||||||
<% value = values[field['uuid']].presence || (field['default_value'] != '{{date}}' && field['readonly'] == true && field['conditions'].blank? && field['default_value'].present? ? Submitters::SubmitValues.template_default_value_for_submitter(field['default_value'], @submission.submitters.find { |e| e.uuid == field['submitter_uuid'] }, with_time: false) : nil) %>
|
<% value = values[field['uuid']].presence || (field['default_value'] != '{{date}}' && field['readonly'] == true && field['conditions'].blank? && field['default_value'].present? ? Submitters::SubmitValues.template_default_value_for_submitter(field['default_value'], @submission.submitters.find { |e| e.uuid == field['submitter_uuid'] }, with_time: false) : nil) %>
|
||||||
<% value ||= field['default_value'] if field['type'] == 'heading' %>
|
<% value ||= field['default_value'] if field['type'] == 'heading' %>
|
||||||
<% next if value.blank? %>
|
|
||||||
<% submitter = submitters_index[field['submitter_uuid']] %>
|
<% submitter = submitters_index[field['submitter_uuid']] %>
|
||||||
|
<% if value.present? %>
|
||||||
<% if (mask = field.dig('preferences', 'mask').presence) && signed_in? && can?(:read, @submission) %>
|
<% if (mask = field.dig('preferences', 'mask').presence) && signed_in? && can?(:read, @submission) %>
|
||||||
<span class="group">
|
<span class="group">
|
||||||
<span class="hidden group-hover:inline">
|
<span class="hidden group-hover:inline">
|
||||||
@@ -125,6 +127,16 @@
|
|||||||
<% else %>
|
<% else %>
|
||||||
<%= render 'submissions/value', page_width: width, page_height: height, font_scale:, area:, field:, attachments_index:, value: mask.present? ? Array.wrap(value).map { |e| TextUtils.mask_value(e, mask) }.join(', ') : value, locale: @submission.account.locale, timezone: @submission.account.timezone, submitter:, with_signature_id:, with_submitter_timezone:, with_signature_id_reason: %>
|
<%= render 'submissions/value', page_width: width, page_height: height, font_scale:, area:, field:, attachments_index:, value: mask.present? ? Array.wrap(value).map { |e| TextUtils.mask_value(e, mask) }.join(', ') : value, locale: @submission.account.locale, timezone: @submission.account.timezone, submitter:, with_signature_id:, with_submitter_timezone:, with_signature_id_reason: %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<% elsif field['readonly'] != true && submitter && !submitter.completed_at? %>
|
||||||
|
<% submitters_order_index ||= (@submission.template_submitters || @submission.template.submitters).each_with_index.to_h { |s, i| [s['uuid'], i] } %>
|
||||||
|
<% submitter_index = submitters_order_index[submitter.uuid] %>
|
||||||
|
<% bg_class = bg_classes[submitter_index % bg_classes.size] %>
|
||||||
|
<div class="absolute overflow-visible" style="width: <%= area['w'] * 100 %>%; height: <%= area['h'] * 100 %>%; left: <%= area['x'] * 100 %>%; top: <%= area['y'] * 100 %>%;">
|
||||||
|
<div class="flex h-full w-full bg-opacity-80 justify-center items-center <%= bg_class %>">
|
||||||
|
<%= svg_icon(SubmissionsController::FIELD_ICONS[field['type']], class: 'max-h-10 w-full h-full stroke-2 opacity-50') %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</page-container>
|
</page-container>
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
<% data_fields = Submissions.filtered_conditions_fields(submitter).to_json %>
|
<% data_fields = Submissions.filtered_conditions_fields(submitter).to_json %>
|
||||||
<% invite_submitters = (submitter.submission.template_submitters || submitter.submission.template.submitters).select { |s| s['invite_by_uuid'] == submitter.uuid && submitter.submission.submitters.none? { |e| e.uuid == s['uuid'] } }.to_json %>
|
<% invite_submitters = (submitter.submission.template_submitters || submitter.submission.template.submitters).select { |s| s['invite_by_uuid'] == submitter.uuid && submitter.submission.submitters.none? { |e| e.uuid == s['uuid'] } }.to_json %>
|
||||||
<% optional_invite_submitters = (submitter.submission.template_submitters || submitter.submission.template.submitters).select { |s| s['optional_invite_by_uuid'] == submitter.uuid && submitter.submission.submitters.none? { |e| e.uuid == s['uuid'] } }.to_json %>
|
<% optional_invite_submitters = (submitter.submission.template_submitters || submitter.submission.template.submitters).select { |s| s['optional_invite_by_uuid'] == submitter.uuid && submitter.submission.submitters.none? { |e| e.uuid == s['uuid'] } }.to_json %>
|
||||||
<submission-form data-is-demo="<%= Docuseal.demo? %>" data-schema="<%= schema.to_json %>" data-reuse-signature="<%= configs[:reuse_signature] %>" data-require-signing-reason="<%= configs[:require_signing_reason] %>" data-with-signature-id="<%= configs[:with_signature_id] %>" data-with-confetti="<%= configs[:with_confetti] %>" data-completed-redirect-url="<%= submitter.preferences['completed_redirect_url'].presence || submitter.submission.template&.preferences&.dig('completed_redirect_url') %>" data-completed-message="<%= (configs[:completed_message]&.compact_blank.presence || submitter.submission.template&.preferences&.dig('completed_message') || {}).to_json %>" data-completed-button="<%= configs[:completed_button].to_json %>" data-go-to-last="<%= submitter.preferences.key?('go_to_last') ? submitter.preferences['go_to_last'] : submitter.opened_at? %>" data-submitter="<%= submitter.to_json(only: %i[uuid slug name phone email]) %>" data-can-send-email="<%= Accounts.can_send_emails?(submitter.submission.account) %>" data-optional-invite-submitters="<%= optional_invite_submitters %>" data-invite-submitters="<%= invite_submitters %>" data-attachments="<%= data_attachments %>" data-fields="<%= data_fields %>" data-values="<%= submitter.values.to_json %>" data-with-typed-signature="<%= configs[:with_typed_signature] %>" data-previous-signature-value="<%= local_assigns[:signature_attachment]&.uuid %>" data-remember-signature="<%= configs[:prefill_signature] %>" data-dry-run="<%= local_assigns[:dry_run] %>" data-expand="<%= local_assigns[:expand] %>" data-scroll-padding="<%= local_assigns[:scroll_padding] %>" data-language="<%= I18n.locale.to_s.split('-').first %>"></submission-form>
|
<submission-form data-is-demo="<%= Docuseal.demo? %>" data-schema="<%= schema.to_json %>" data-reuse-signature="<%= configs[:reuse_signature] %>" data-require-signing-reason="<%= configs[:require_signing_reason] %>" data-with-signature-id="<%= configs[:with_signature_id] %>" data-with-field-labels="<%= configs[:with_field_labels] %>" data-with-confetti="<%= configs[:with_confetti] %>" data-completed-redirect-url="<%= submitter.preferences['completed_redirect_url'].presence || submitter.submission.template&.preferences&.dig('completed_redirect_url') %>" data-completed-message="<%= (configs[:completed_message]&.compact_blank.presence || submitter.submission.template&.preferences&.dig('completed_message') || {}).to_json %>" data-completed-button="<%= configs[:completed_button].to_json %>" data-go-to-last="<%= submitter.preferences.key?('go_to_last') ? submitter.preferences['go_to_last'] : submitter.opened_at? %>" data-submitter="<%= submitter.to_json(only: %i[uuid slug name phone email]) %>" data-can-send-email="<%= Accounts.can_send_emails?(submitter.submission.account) %>" data-optional-invite-submitters="<%= optional_invite_submitters %>" data-invite-submitters="<%= invite_submitters %>" data-attachments="<%= data_attachments %>" data-fields="<%= data_fields %>" data-values="<%= submitter.values.to_json %>" data-with-typed-signature="<%= configs[:with_typed_signature] %>" data-previous-signature-value="<%= local_assigns[:signature_attachment]&.uuid %>" data-remember-signature="<%= configs[:prefill_signature] %>" data-dry-run="<%= local_assigns[:dry_run] %>" data-expand="<%= local_assigns[:expand] %>" data-scroll-padding="<%= local_assigns[:scroll_padding] %>" data-language="<%= I18n.locale.to_s.split('-').first %>"></submission-form>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"ignored_warnings": [
|
"ignored_warnings": [
|
||||||
{
|
{
|
||||||
"fingerprint": "bbd1bdad94998e53a48921859065e06cd1595502d4dc40362afcaa90307b591a",
|
"fingerprint": "de39648cd3f79d51e95e45f05fc77da49b0ad68bf80458061151016c0ef78208",
|
||||||
"note": "Permitted parameters are necessary for creating submitters via API"
|
"note": "Permitted parameters are necessary for creating submitters via API"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -876,6 +876,7 @@ en: &en
|
|||||||
you_requested_to_reset_your_password_use_the_link_below_to_continue: You requested to reset your password. Use the link below to continue
|
you_requested_to_reset_your_password_use_the_link_below_to_continue: You requested to reset your password. Use the link below to continue
|
||||||
if_you_didnt_request_this_you_can_ignore_this_email: "If you didn't request this, please ignore this email."
|
if_you_didnt_request_this_you_can_ignore_this_email: "If you didn't request this, please ignore this email."
|
||||||
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Your password won't change until you open the link above and set a new one."
|
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Your password won't change until you open the link above and set a new one."
|
||||||
|
too_many_requests_try_again_later: Too many requests, try again later.
|
||||||
devise:
|
devise:
|
||||||
confirmations:
|
confirmations:
|
||||||
confirmed: Your email address has been successfully confirmed.
|
confirmed: Your email address has been successfully confirmed.
|
||||||
@@ -1847,6 +1848,7 @@ es: &es
|
|||||||
you_requested_to_reset_your_password_use_the_link_below_to_continue: Solicitaste restablecer tu contraseña. Usa el enlace a continuación para continuar.
|
you_requested_to_reset_your_password_use_the_link_below_to_continue: Solicitaste restablecer tu contraseña. Usa el enlace a continuación para continuar.
|
||||||
if_you_didnt_request_this_you_can_ignore_this_email: "Si no solicitaste esto, puedes ignorar este correo electrónico."
|
if_you_didnt_request_this_you_can_ignore_this_email: "Si no solicitaste esto, puedes ignorar este correo electrónico."
|
||||||
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Tu contraseña no cambiará hasta que abras el enlace anterior y establezcas una nueva."
|
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Tu contraseña no cambiará hasta que abras el enlace anterior y establezcas una nueva."
|
||||||
|
too_many_requests_try_again_later: Demasiadas solicitudes. Intenta de nuevo más tarde.
|
||||||
devise:
|
devise:
|
||||||
confirmations:
|
confirmations:
|
||||||
confirmed: Tu dirección de correo electrónico ha sido confirmada correctamente.
|
confirmed: Tu dirección de correo electrónico ha sido confirmada correctamente.
|
||||||
@@ -2819,6 +2821,7 @@ it: &it
|
|||||||
you_requested_to_reset_your_password_use_the_link_below_to_continue: Hai richiesto di reimpostare la tua password. Usa il link qui sotto per continuare.
|
you_requested_to_reset_your_password_use_the_link_below_to_continue: Hai richiesto di reimpostare la tua password. Usa il link qui sotto per continuare.
|
||||||
if_you_didnt_request_this_you_can_ignore_this_email: "Se non hai richiesto questo, puoi ignorare questa email."
|
if_you_didnt_request_this_you_can_ignore_this_email: "Se non hai richiesto questo, puoi ignorare questa email."
|
||||||
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "La tua password non cambierà finché non apri il link sopra e ne imposti una nuova."
|
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "La tua password non cambierà finché non apri il link sopra e ne imposti una nuova."
|
||||||
|
too_many_requests_try_again_later: Troppe richieste. Riprova più tardi.
|
||||||
devise:
|
devise:
|
||||||
confirmations:
|
confirmations:
|
||||||
confirmed: Il tuo indirizzo email è stato confermato con successo.
|
confirmed: Il tuo indirizzo email è stato confermato con successo.
|
||||||
@@ -3787,6 +3790,7 @@ fr: &fr
|
|||||||
you_requested_to_reset_your_password_use_the_link_below_to_continue: Vous avez demandé à réinitialiser votre mot de passe. Utilisez le lien ci-dessous pour continuer.
|
you_requested_to_reset_your_password_use_the_link_below_to_continue: Vous avez demandé à réinitialiser votre mot de passe. Utilisez le lien ci-dessous pour continuer.
|
||||||
if_you_didnt_request_this_you_can_ignore_this_email: "Si vous n'avez pas fait cette demande, veuillez ignorer cet e-mail."
|
if_you_didnt_request_this_you_can_ignore_this_email: "Si vous n'avez pas fait cette demande, veuillez ignorer cet e-mail."
|
||||||
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Votre mot de passe ne changera pas tant que vous n’aurez pas ouvert le lien ci-dessus et défini un nouveau mot de passe."
|
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Votre mot de passe ne changera pas tant que vous n’aurez pas ouvert le lien ci-dessus et défini un nouveau mot de passe."
|
||||||
|
too_many_requests_try_again_later: Trop de demandes. Réessayez plus tard.
|
||||||
devise:
|
devise:
|
||||||
confirmations:
|
confirmations:
|
||||||
confirmed: Votre adresse e-mail a été confirmée avec succès.
|
confirmed: Votre adresse e-mail a été confirmée avec succès.
|
||||||
@@ -4758,6 +4762,7 @@ pt: &pt
|
|||||||
you_requested_to_reset_your_password_use_the_link_below_to_continue: Você solicitou a redefinição da sua senha. Use o link abaixo para continuar.
|
you_requested_to_reset_your_password_use_the_link_below_to_continue: Você solicitou a redefinição da sua senha. Use o link abaixo para continuar.
|
||||||
if_you_didnt_request_this_you_can_ignore_this_email: "Se você não solicitou isso, pode ignorar este e-mail."
|
if_you_didnt_request_this_you_can_ignore_this_email: "Se você não solicitou isso, pode ignorar este e-mail."
|
||||||
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Sua senha não será alterada até que você abra o link acima e defina uma nova."
|
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Sua senha não será alterada até que você abra o link acima e defina uma nova."
|
||||||
|
too_many_requests_try_again_later: Muitas solicitações. Tente novamente mais tarde.
|
||||||
devise:
|
devise:
|
||||||
confirmations:
|
confirmations:
|
||||||
confirmed: Seu endereço de e-mail foi confirmado com sucesso.
|
confirmed: Seu endereço de e-mail foi confirmado com sucesso.
|
||||||
@@ -5729,6 +5734,7 @@ de: &de
|
|||||||
you_requested_to_reset_your_password_use_the_link_below_to_continue: Sie haben angefordert, Ihr Passwort zurückzusetzen. Verwenden Sie den untenstehenden Link, um fortzufahren.
|
you_requested_to_reset_your_password_use_the_link_below_to_continue: Sie haben angefordert, Ihr Passwort zurückzusetzen. Verwenden Sie den untenstehenden Link, um fortzufahren.
|
||||||
if_you_didnt_request_this_you_can_ignore_this_email: "Wenn Sie dies nicht angefordert haben, können Sie diese E-Mail ignorieren."
|
if_you_didnt_request_this_you_can_ignore_this_email: "Wenn Sie dies nicht angefordert haben, können Sie diese E-Mail ignorieren."
|
||||||
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Ihr Passwort wird erst geändert, wenn Sie den obigen Link öffnen und ein neues festlegen."
|
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Ihr Passwort wird erst geändert, wenn Sie den obigen Link öffnen und ein neues festlegen."
|
||||||
|
too_many_requests_try_again_later: Zu viele Anfragen. Versuchen Sie es später erneut.
|
||||||
devise:
|
devise:
|
||||||
confirmations:
|
confirmations:
|
||||||
confirmed: Ihre E-Mail-Adresse wurde erfolgreich bestätigt.
|
confirmed: Ihre E-Mail-Adresse wurde erfolgreich bestätigt.
|
||||||
@@ -5938,6 +5944,7 @@ pl:
|
|||||||
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: Nadawca zażądał uwierzytelniania dwuskładnikowego za pośrednictwem hasła jednorazowego wysłanego na Twój adres e-mail <b>%{email}</b>.
|
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: Nadawca zażądał uwierzytelniania dwuskładnikowego za pośrednictwem hasła jednorazowego wysłanego na Twój adres e-mail <b>%{email}</b>.
|
||||||
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: Skontaktuj się z nadawcą, aby podać swój adres e-mail do uwierzytelniania dwuskładnikowego.
|
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: Skontaktuj się z nadawcą, aby podać swój adres e-mail do uwierzytelniania dwuskładnikowego.
|
||||||
rate_limit_exceeded: Przekroczono limit
|
rate_limit_exceeded: Przekroczono limit
|
||||||
|
too_many_requests_try_again_later: Zbyt wiele żądań. Spróbuj ponownie później.
|
||||||
|
|
||||||
uk:
|
uk:
|
||||||
require_phone_2fa_to_open: Вимагати двофакторну автентифікацію через телефон для відкриття
|
require_phone_2fa_to_open: Вимагати двофакторну автентифікацію через телефон для відкриття
|
||||||
@@ -6034,6 +6041,7 @@ uk:
|
|||||||
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: Відправник запросив двофакторну автентифікацію за допомогою одноразового пароля, відправленого на вашу електронну пошту <b>%{email}</b>.
|
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: Відправник запросив двофакторну автентифікацію за допомогою одноразового пароля, відправленого на вашу електронну пошту <b>%{email}</b>.
|
||||||
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: Будь ласка, зв'яжіться з відправником, щоб вказати вашу електронну пошту для двофакторної автентифікації.
|
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: Будь ласка, зв'яжіться з відправником, щоб вказати вашу електронну пошту для двофакторної автентифікації.
|
||||||
rate_limit_exceeded: Перевищено ліміт
|
rate_limit_exceeded: Перевищено ліміт
|
||||||
|
too_many_requests_try_again_later: Забагато запитів. Спробуйте пізніше.
|
||||||
|
|
||||||
cs:
|
cs:
|
||||||
require_phone_2fa_to_open: Vyžadovat otevření pomocí telefonního 2FA
|
require_phone_2fa_to_open: Vyžadovat otevření pomocí telefonního 2FA
|
||||||
@@ -6130,6 +6138,7 @@ cs:
|
|||||||
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: Odesílatel požádal o dvoufaktorové ověření pomocí jednorázového hesla odeslaného na vaši e-mailovou adresu <b>%{email}</b>.
|
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: Odesílatel požádal o dvoufaktorové ověření pomocí jednorázového hesla odeslaného na vaši e-mailovou adresu <b>%{email}</b>.
|
||||||
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: Prosím kontaktujte odesílatele a uveďte svůj e-mail pro dvoufaktorové ověření.
|
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: Prosím kontaktujte odesílatele a uveďte svůj e-mail pro dvoufaktorové ověření.
|
||||||
rate_limit_exceeded: Překročena hranice
|
rate_limit_exceeded: Překročena hranice
|
||||||
|
too_many_requests_try_again_later: Příliš mnoho požadavků. Zkuste to později.
|
||||||
|
|
||||||
he:
|
he:
|
||||||
require_phone_2fa_to_open: דרוש אימות דו-שלבי באמצעות טלפון לפתיחה
|
require_phone_2fa_to_open: דרוש אימות דו-שלבי באמצעות טלפון לפתיחה
|
||||||
@@ -6226,6 +6235,7 @@ he:
|
|||||||
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: השולח ביקש אימות דו-שלבי באמצעות סיסמה חד-פעמית שנשלחה לכתובת הדוא"ל שלך <b>%{email}</b>.
|
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: השולח ביקש אימות דו-שלבי באמצעות סיסמה חד-פעמית שנשלחה לכתובת הדוא"ל שלך <b>%{email}</b>.
|
||||||
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: אנא פנה לשולח וציין את כתובת הדוא"ל שלך לאימות דו-שלבי.
|
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: אנא פנה לשולח וציין את כתובת הדוא"ל שלך לאימות דו-שלבי.
|
||||||
rate_limit_exceeded: חריגה ממגבלת
|
rate_limit_exceeded: חריגה ממגבלת
|
||||||
|
too_many_requests_try_again_later: יותר מדי בקשות. נסה שוב מאוחר יותר.
|
||||||
|
|
||||||
nl: &nl
|
nl: &nl
|
||||||
templates_that_require_email_or_phone_2fa_cannot_be_used_via_a_shared_link: Sjablonen waarvoor e-mail- of telefoon-2FA vereist is, kunnen niet via een gedeelde link worden gebruikt.
|
templates_that_require_email_or_phone_2fa_cannot_be_used_via_a_shared_link: Sjablonen waarvoor e-mail- of telefoon-2FA vereist is, kunnen niet via een gedeelde link worden gebruikt.
|
||||||
@@ -7081,6 +7091,7 @@ nl: &nl
|
|||||||
you_requested_to_reset_your_password_use_the_link_below_to_continue: Je hebt gevraagd je wachtwoord te resetten. Gebruik de onderstaande link om verder te gaan.
|
you_requested_to_reset_your_password_use_the_link_below_to_continue: Je hebt gevraagd je wachtwoord te resetten. Gebruik de onderstaande link om verder te gaan.
|
||||||
if_you_didnt_request_this_you_can_ignore_this_email: "Als je dit niet hebt aangevraagd, kun je deze e-mail negeren."
|
if_you_didnt_request_this_you_can_ignore_this_email: "Als je dit niet hebt aangevraagd, kun je deze e-mail negeren."
|
||||||
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Je wachtwoord wordt niet gewijzigd totdat je de bovenstaande link opent en een nieuw wachtwoord instelt."
|
your_password_wont_change_until_you_open_the_link_above_and_set_a_new_one: "Je wachtwoord wordt niet gewijzigd totdat je de bovenstaande link opent en een nieuw wachtwoord instelt."
|
||||||
|
too_many_requests_try_again_later: Te veel verzoeken. Probeer het later opnieuw.
|
||||||
devise:
|
devise:
|
||||||
confirmations:
|
confirmations:
|
||||||
confirmed: Je e-mailadres is succesvol bevestigd.
|
confirmed: Je e-mailadres is succesvol bevestigd.
|
||||||
@@ -7290,6 +7301,7 @@ ar:
|
|||||||
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: طلب المرسل المصادقة الثنائية عبر كلمة مرور لمرة واحدة مرسلة إلى عنوان بريدك الإلكتروني <b>%{email}</b>.
|
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: طلب المرسل المصادقة الثنائية عبر كلمة مرور لمرة واحدة مرسلة إلى عنوان بريدك الإلكتروني <b>%{email}</b>.
|
||||||
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: يرجى الاتصال بالمرسل لتحديد عنوان بريدك الإلكتروني للمصادقة الثنائية.
|
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: يرجى الاتصال بالمرسل لتحديد عنوان بريدك الإلكتروني للمصادقة الثنائية.
|
||||||
rate_limit_exceeded: تم تجاوز الحد المسموح به
|
rate_limit_exceeded: تم تجاوز الحد المسموح به
|
||||||
|
too_many_requests_try_again_later: طلبات كثيرة جدًا. حاول مرة أخرى لاحقًا.
|
||||||
|
|
||||||
ko:
|
ko:
|
||||||
require_phone_2fa_to_open: 휴대폰 2FA를 열 때 요구함
|
require_phone_2fa_to_open: 휴대폰 2FA를 열 때 요구함
|
||||||
@@ -7386,6 +7398,7 @@ ko:
|
|||||||
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: 발신자가 <b>%{email}</b> 이메일 주소로 전송된 일회용 비밀번호를 통해 2단계 인증을 요청했습니다.
|
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: 발신자가 <b>%{email}</b> 이메일 주소로 전송된 일회용 비밀번호를 통해 2단계 인증을 요청했습니다.
|
||||||
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: 2단계 인증을 위해 이메일 주소를 지정하려면 발신자에게 문의하세요.
|
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: 2단계 인증을 위해 이메일 주소를 지정하려면 발신자에게 문의하세요.
|
||||||
rate_limit_exceeded: 속도 제한 초과
|
rate_limit_exceeded: 속도 제한 초과
|
||||||
|
too_many_requests_try_again_later: 요청이 너무 많습니다. 나중에 다시 시도하세요.
|
||||||
|
|
||||||
ja:
|
ja:
|
||||||
require_phone_2fa_to_open: 電話による2段階認証が必要です
|
require_phone_2fa_to_open: 電話による2段階認証が必要です
|
||||||
@@ -7482,6 +7495,7 @@ ja:
|
|||||||
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: 送信者は、<b>%{email}</b> メールアドレスに送信されたワンタイムパスワードによる2段階認証を要求しました。
|
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_email_html: 送信者は、<b>%{email}</b> メールアドレスに送信されたワンタイムパスワードによる2段階認証を要求しました。
|
||||||
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: 2段階認証用にメールアドレスを指定するために、送信者にお問い合わせください。
|
please_contact_the_requester_to_specify_your_email_for_two_factor_authentication: 2段階認証用にメールアドレスを指定するために、送信者にお問い合わせください。
|
||||||
rate_limit_exceeded: レート制限を超えました
|
rate_limit_exceeded: レート制限を超えました
|
||||||
|
too_many_requests_try_again_later: リクエストが多すぎます。後でもう一度お試しください。
|
||||||
|
|
||||||
en-US:
|
en-US:
|
||||||
<<: *en
|
<<: *en
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ class AddIsFirstToCompletedSubmitters < ActiveRecord::Migration[8.0]
|
|||||||
add_index :completed_submitters, %i[account_id completed_at],
|
add_index :completed_submitters, %i[account_id completed_at],
|
||||||
where: 'is_first = TRUE',
|
where: 'is_first = TRUE',
|
||||||
name: 'index_completed_submitters_account_id_completed_at_is_first'
|
name: 'index_completed_submitters_account_id_completed_at_is_first'
|
||||||
add_index :completed_submitters, :submission_id, unique: true, where: 'is_first = TRUE'
|
|
||||||
|
add_index :completed_submitters, :submission_id, unique: adapter_name != 'Mysql2',
|
||||||
|
where: 'is_first = TRUE'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -151,7 +151,8 @@ const token = jwt.sign({
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"drawFieldType": {
|
"drawFieldType": {
|
||||||
@@ -194,7 +195,8 @@ const token = jwt.sign({
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
@@ -321,7 +323,8 @@ const token = jwt.sign({
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
@@ -444,6 +447,12 @@ const token = jwt.sign({
|
|||||||
"default": true,
|
"default": true,
|
||||||
"description": "Set `false` to now show the fields list on the right. Fields list is displayed by default."
|
"description": "Set `false` to now show the fields list on the right. Fields list is displayed by default."
|
||||||
},
|
},
|
||||||
|
"withFieldsDetection": {
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": false,
|
||||||
|
"description": "Display a button to automatically detect and add fields to the document with AI."
|
||||||
|
},
|
||||||
"withFieldPlaceholder": {
|
"withFieldPlaceholder": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"required": false,
|
"required": false,
|
||||||
@@ -483,7 +492,7 @@ const token = jwt.sign({
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "en",
|
"default": "en",
|
||||||
"description": "UI language, 'en', 'es', 'de', 'fr', 'pt', 'he', 'ar' languages are available."
|
"description": "UI language, 'en', 'es', 'de', 'fr', 'pt', 'nl', 'he', 'ar' languages are available."
|
||||||
},
|
},
|
||||||
"i18n": {
|
"i18n": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|||||||
@@ -118,7 +118,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
@@ -249,7 +250,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
@@ -336,7 +338,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"data-draw-field-type": {
|
"data-draw-field-type": {
|
||||||
@@ -408,6 +411,12 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"description": "Set `false` to now show the fields list on the right. Fields list is displayed by default."
|
"description": "Set `false` to now show the fields list on the right. Fields list is displayed by default."
|
||||||
},
|
},
|
||||||
|
"data-with-fields-detection": {
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": false,
|
||||||
|
"description": "Display a button to automatically detect and add fields to the document with AI."
|
||||||
|
},
|
||||||
"data-with-field-placeholder": {
|
"data-with-field-placeholder": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"required": false,
|
"required": false,
|
||||||
@@ -453,7 +462,7 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "en",
|
"default": "en",
|
||||||
"description": "UI language, 'en', 'es', 'de', 'fr', 'pt', 'he', 'ar' languages are available."
|
"description": "UI language, 'en', 'es', 'de', 'fr', 'pt', 'nl', 'he', 'ar' languages are available."
|
||||||
},
|
},
|
||||||
"data-background-color": {
|
"data-background-color": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@@ -142,7 +142,8 @@ const token = jwt.sign({
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"drawFieldType": {
|
"drawFieldType": {
|
||||||
@@ -185,7 +186,8 @@ const token = jwt.sign({
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
@@ -312,7 +314,8 @@ const token = jwt.sign({
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
@@ -435,6 +438,12 @@ const token = jwt.sign({
|
|||||||
"default": true,
|
"default": true,
|
||||||
"description": "Set `false` to now show the fields list on the right. Fields list is displayed by default."
|
"description": "Set `false` to now show the fields list on the right. Fields list is displayed by default."
|
||||||
},
|
},
|
||||||
|
"withFieldsDetection": {
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": false,
|
||||||
|
"description": "Display a button to automatically detect and add fields to the document with AI."
|
||||||
|
},
|
||||||
"withFieldPlaceholder": {
|
"withFieldPlaceholder": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"required": false,
|
"required": false,
|
||||||
@@ -474,7 +483,7 @@ const token = jwt.sign({
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "en",
|
"default": "en",
|
||||||
"description": "UI language, 'en', 'es', 'de', 'fr', 'pt', 'he', 'ar' languages are available."
|
"description": "UI language, 'en', 'es', 'de', 'fr', 'pt', 'nl', 'he', 'ar' languages are available."
|
||||||
},
|
},
|
||||||
"i18n": {
|
"i18n": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|||||||
@@ -163,7 +163,8 @@ const token = jwt.sign({
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"draw-field-type": {
|
"draw-field-type": {
|
||||||
@@ -206,7 +207,8 @@ const token = jwt.sign({
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
@@ -333,7 +335,8 @@ const token = jwt.sign({
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
@@ -450,6 +453,12 @@ const token = jwt.sign({
|
|||||||
"default": true,
|
"default": true,
|
||||||
"description": "Set `false` to now show the fields list on the right. Fields list is displayed by default."
|
"description": "Set `false` to now show the fields list on the right. Fields list is displayed by default."
|
||||||
},
|
},
|
||||||
|
"with-fields-detection": {
|
||||||
|
"type": "boolean",
|
||||||
|
"required": false,
|
||||||
|
"default": false,
|
||||||
|
"description": "Display a button to automatically detect and add fields to the document with AI."
|
||||||
|
},
|
||||||
"with-field-placeholder": {
|
"with-field-placeholder": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"required": false,
|
"required": false,
|
||||||
@@ -483,7 +492,7 @@ const token = jwt.sign({
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"required": false,
|
"required": false,
|
||||||
"default": "en",
|
"default": "en",
|
||||||
"description": "UI language, 'en', 'es', 'de', 'fr', 'pt', 'he', 'ar' languages are available."
|
"description": "UI language, 'en', 'es', 'de', 'fr', 'pt', 'nl', 'he', 'ar' languages are available."
|
||||||
},
|
},
|
||||||
"i18n": {
|
"i18n": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export class AppComponent {}
|
|||||||
"src": {
|
"src": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": true,
|
"required": true,
|
||||||
"description": "Public URL of the document signing form. There are two types of URLs: <li><code>/d/{slug}</code> - template form signing URL can be copied from the template page in the admin dashboard. Also template \"slug\" key can be obtained via the <code>/templates</code> API.</li><li><code>/s/{slug}</code> - individual signer URL. Signer \"slug\" key can be obtained via the <code>/submissions</code> API which is used to initiate signature requests for a template form with recipients.</li>"
|
"description": "Public URL of the document signing form. There are two types of URLs: <ul class=\"list-inside list-disc\"><li><code>/d/{slug}</code> - template form signing URL can be copied from the template page in the admin dashboard. Also template \"slug\" key can be obtained via the <code>/templates</code> API.</li><li><code>/s/{slug}</code> - individual signer URL. Signer \"slug\" key can be obtained via the <code>/submissions</code> API which is used to initiate signature requests for a template form with recipients.</li></ul>"
|
||||||
},
|
},
|
||||||
"email": {
|
"email": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
"data-src": {
|
"data-src": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": true,
|
"required": true,
|
||||||
"description": "Public URL of the document signing form. There are two types of URLs: <li><code>/d/{slug}</code> - template form signing URL can be copied from the template page in the admin dashboard. Also template \"slug\" key can be obtained via the <code>/templates</code> API.</li><li><code>/s/{slug}</code> - individual signer URL. Signer \"slug\" key can be obtained via the <code>/submissions</code> API which is used to initiate signature requests for a template form with recipients.</li>"
|
"description": "Public URL of the document signing form. There are two types of URLs: <ul class=\"list-inside list-disc\"><li><code>/d/{slug}</code> - template form signing URL can be copied from the template page in the admin dashboard. Also template \"slug\" key can be obtained via the <code>/templates</code> API.</li><li><code>/s/{slug}</code> - individual signer URL. Signer \"slug\" key can be obtained via the <code>/submissions</code> API which is used to initiate signature requests for a template form with recipients.</li></ul>"
|
||||||
},
|
},
|
||||||
"data-email": {
|
"data-email": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export function App() {
|
|||||||
"src": {
|
"src": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": true,
|
"required": true,
|
||||||
"description": "Public URL of the document signing form. There are two types of URLs: <li><code>/d/{slug}</code> - template form signing URL can be copied from the template page in the admin dashboard. Also template \"slug\" key can be obtained via the <code>/templates</code> API.</li><li><code>/s/{slug}</code> - individual signer URL. Signer \"slug\" key can be obtained via the <code>/submissions</code> API which is used to initiate signature requests for a template form with recipients.</li>"
|
"description": "Public URL of the document signing form. There are two types of URLs: <ul class=\"list-inside list-disc\"><li><code>/d/{slug}</code> - template form signing URL can be copied from the template page in the admin dashboard. Also template \"slug\" key can be obtained via the <code>/templates</code> API.</li><li><code>/s/{slug}</code> - individual signer URL. Signer \"slug\" key can be obtained via the <code>/submissions</code> API which is used to initiate signature requests for a template form with recipients.</li></ul>"
|
||||||
},
|
},
|
||||||
"email": {
|
"email": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export default {
|
|||||||
"src": {
|
"src": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": true,
|
"required": true,
|
||||||
"description": "Public URL of the document signing form. There are two types of URLs: <li><code>/d/{slug}</code> - template form signing URL can be copied from the template page in the admin dashboard. Also template \"slug\" key can be obtained via the <code>/templates</code> API.</li><li><code>/s/{slug}</code> - individual signer URL. Signer \"slug\" key can be obtained via the <code>/submissions</code> API which is used to initiate signature requests for a template form with recipients.</li>"
|
"description": "Public URL of the document signing form. There are two types of URLs: <ul class=\"list-inside list-disc\"><li><code>/d/{slug}</code> - template form signing URL can be copied from the template page in the admin dashboard. Also template \"slug\" key can be obtained via the <code>/templates</code> API.</li><li><code>/s/{slug}</code> - individual signer URL. Signer \"slug\" key can be obtained via the <code>/submissions</code> API which is used to initiate signature requests for a template form with recipients.</li></ul>"
|
||||||
},
|
},
|
||||||
"email": {
|
"email": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@@ -251,7 +251,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"required": {
|
"required": {
|
||||||
@@ -277,6 +278,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Font color of the field value."
|
"description": "Font color of the field value."
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color."
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value."
|
"description": "Horizontal alignment of the field text value."
|
||||||
@@ -300,6 +305,13 @@
|
|||||||
"mask": {
|
"mask": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Indicates if the field is masked on the document."
|
"description": "Indicates if the field is masked on the document."
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -714,7 +726,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"required": {
|
"required": {
|
||||||
@@ -740,6 +753,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Font color of the field value."
|
"description": "Font color of the field value."
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color."
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value."
|
"description": "Horizontal alignment of the field text value."
|
||||||
@@ -763,6 +780,13 @@
|
|||||||
"mask": {
|
"mask": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Indicates if the field is masked on the document."
|
"description": "Indicates if the field is masked on the document."
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1782,6 +1806,11 @@
|
|||||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
|
"require_email_2fa": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Set to `true` to require email 2FA verification via a one-time code sent to the email address in order to access the documents.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
"message": {
|
"message": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -1933,6 +1962,15 @@
|
|||||||
],
|
],
|
||||||
"default": "black"
|
"default": "black"
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color.",
|
||||||
|
"enum": [
|
||||||
|
"black",
|
||||||
|
"white",
|
||||||
|
"blue"
|
||||||
|
]
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value.",
|
"description": "Horizontal alignment of the field text value.",
|
||||||
@@ -1986,6 +2024,13 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2622,6 +2667,10 @@
|
|||||||
"event_timestamp": {
|
"event_timestamp": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Date and time when the event was triggered."
|
"description": "Date and time when the event was triggered."
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Additional event details object."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2733,7 +2782,8 @@
|
|||||||
"id": 1,
|
"id": 1,
|
||||||
"submitter_id": 2,
|
"submitter_id": 2,
|
||||||
"event_type": "view_form",
|
"event_type": "view_form",
|
||||||
"event_timestamp": "2023-12-14T15:47:24.566Z"
|
"event_timestamp": "2023-12-14T15:47:24.566Z",
|
||||||
|
"data": {}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"documents": [
|
"documents": [
|
||||||
@@ -3318,7 +3368,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
@@ -3471,6 +3522,15 @@
|
|||||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
|
"require_email_2fa": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Set to `true` to require email 2FA verification via a one-time code sent to the email address in order to access the documents.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"invite_by": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Set the role name of the previous party that should invite this party via email."
|
||||||
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "A list of configurations for document form fields.",
|
"description": "A list of configurations for document form fields.",
|
||||||
@@ -3609,6 +3669,15 @@
|
|||||||
],
|
],
|
||||||
"default": "black"
|
"default": "black"
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color.",
|
||||||
|
"enum": [
|
||||||
|
"black",
|
||||||
|
"white",
|
||||||
|
"blue"
|
||||||
|
]
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value.",
|
"description": "Horizontal alignment of the field text value.",
|
||||||
@@ -3662,6 +3731,13 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3744,7 +3820,6 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
"submission_id",
|
|
||||||
"uuid",
|
"uuid",
|
||||||
"email",
|
"email",
|
||||||
"slug",
|
"slug",
|
||||||
@@ -3833,6 +3908,53 @@
|
|||||||
"awaiting"
|
"awaiting"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"values": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "An array of pre-filled values for the submitter.",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"field",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"field": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Document template field name."
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Pre-filled value of the field."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"role": {
|
"role": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The role of the submitter."
|
"description": "The role of the submitter."
|
||||||
@@ -3944,7 +4066,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"required": {
|
"required": {
|
||||||
@@ -3970,6 +4093,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Font color of the field value."
|
"description": "Font color of the field value."
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color."
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value."
|
"description": "Horizontal alignment of the field text value."
|
||||||
@@ -3993,6 +4120,13 @@
|
|||||||
"mask": {
|
"mask": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Indicates if the field is masked on the document."
|
"description": "Indicates if the field is masked on the document."
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -4040,27 +4174,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"documents": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "List of documents attached to the one-off submission.",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"attachment_uuid",
|
|
||||||
"name"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"attachment_uuid": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Unique indentifier of attached document to the one-off submission."
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Name of the attached document to the one-off submission."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"expire_at": {
|
"expire_at": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Specify the expiration date and time after which the submission becomes unavailable for signature.",
|
"description": "Specify the expiration date and time after which the submission becomes unavailable for signature.",
|
||||||
@@ -4158,7 +4271,7 @@
|
|||||||
"Submissions"
|
"Submissions"
|
||||||
],
|
],
|
||||||
"summary": "Create a submission from DOCX",
|
"summary": "Create a submission from DOCX",
|
||||||
"description": "The API endpoint provides functionality to create a one-off submission request from a DOCX file with dynamic content variables. Use <code>[[variable_name]]</code> text tags to define dynamic content variables in the document. See <a href=\"https://www.docuseal.com/examples/demo_template.docx\" target=\"_blank\" class=\"link font-bold\">https://www.docuseal.com/examples/demo_template.docx</a> for the specific text variable syntax, including dynamic content tables and list. You can also use the <code>{{signature}}</code> fillable field syntax to define fillable fields, as in a PDF.<br><b>Related Guides</b><br><a href=\"https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form\" class=\"link\">Use embedded text field tags to create a fillable form</a>",
|
"description": "The API endpoint provides functionality to create a one-off submission request from a DOCX file with dynamic content variables. Use <code>[[variable_name]]</code> text tags to define dynamic content variables in the document. See <a href=\"https://www.docuseal.com/examples/demo_template.docx\" target=\"_blank\" class=\"link font-bold\">https://www.docuseal.com/examples/demo_template.docx</a> for the specific text variable syntax, including dynamic content tables and list. You can also use the <code>{{signature}}</code> field syntax to define fillable fields, as in a PDF.<br><b>Related Guides</b><br><a href=\"https://www.docuseal.com/guides/use-dynamic-content-variables-in-docx-to-create-personalized-documents\" class=\"link\">Use dynamic content variables in DOCX to create personalized documents</a>",
|
||||||
"operationId": "createSubmissionFromDocx",
|
"operationId": "createSubmissionFromDocx",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"requestBody": {
|
"requestBody": {
|
||||||
@@ -4189,7 +4302,7 @@
|
|||||||
},
|
},
|
||||||
"variables": {
|
"variables": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "Dynamic content variables object",
|
"description": "Dynamic content variables object. Variable values can be strings, numbers, arrays, objects, or HTML content used to generate styled text, paragraphs, and tables in DOCX.",
|
||||||
"example": {
|
"example": {
|
||||||
"variable_name": "value"
|
"variable_name": "value"
|
||||||
}
|
}
|
||||||
@@ -4327,6 +4440,15 @@
|
|||||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
|
"require_email_2fa": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Set to `true` to require email 2FA verification via a one-time code sent to the email address in order to access the documents.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"invite_by": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Set the role name of the previous party that should invite this party via email."
|
||||||
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "A list of configurations for document form fields.",
|
"description": "A list of configurations for document form fields.",
|
||||||
@@ -4465,6 +4587,15 @@
|
|||||||
],
|
],
|
||||||
"default": "black"
|
"default": "black"
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color.",
|
||||||
|
"enum": [
|
||||||
|
"black",
|
||||||
|
"white",
|
||||||
|
"blue"
|
||||||
|
]
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value.",
|
"description": "Horizontal alignment of the field text value.",
|
||||||
@@ -4518,6 +4649,13 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4595,7 +4733,6 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
"submission_id",
|
|
||||||
"uuid",
|
"uuid",
|
||||||
"email",
|
"email",
|
||||||
"slug",
|
"slug",
|
||||||
@@ -4684,6 +4821,53 @@
|
|||||||
"awaiting"
|
"awaiting"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"values": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "An array of pre-filled values for the submitter.",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"field",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"field": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Document template field name."
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Pre-filled value of the field."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"role": {
|
"role": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The role of the submitter."
|
"description": "The role of the submitter."
|
||||||
@@ -4795,7 +4979,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"required": {
|
"required": {
|
||||||
@@ -4821,6 +5006,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Font color of the field value."
|
"description": "Font color of the field value."
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color."
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value."
|
"description": "Horizontal alignment of the field text value."
|
||||||
@@ -4844,6 +5033,13 @@
|
|||||||
"mask": {
|
"mask": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Indicates if the field is masked on the document."
|
"description": "Indicates if the field is masked on the document."
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -4891,27 +5087,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"documents": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "List of documents attached to the one-off submission.",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"attachment_uuid",
|
|
||||||
"name"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"attachment_uuid": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Unique indentifier of attached document to the one-off submission."
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Name of the attached document to the one-off submission."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"expire_at": {
|
"expire_at": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Specify the expiration date and time after which the submission becomes unavailable for signature.",
|
"description": "Specify the expiration date and time after which the submission becomes unavailable for signature.",
|
||||||
@@ -5198,6 +5373,15 @@
|
|||||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
|
"require_email_2fa": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Set to `true` to require email 2FA verification via a one-time code sent to the email address in order to access the documents.",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"invite_by": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Set the role name of the previous party that should invite this party via email."
|
||||||
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "A list of configurations for document form fields.",
|
"description": "A list of configurations for document form fields.",
|
||||||
@@ -5336,6 +5520,15 @@
|
|||||||
],
|
],
|
||||||
"default": "black"
|
"default": "black"
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color.",
|
||||||
|
"enum": [
|
||||||
|
"black",
|
||||||
|
"white",
|
||||||
|
"blue"
|
||||||
|
]
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value.",
|
"description": "Horizontal alignment of the field text value.",
|
||||||
@@ -5389,6 +5582,13 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5461,7 +5661,6 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
"submission_id",
|
|
||||||
"uuid",
|
"uuid",
|
||||||
"email",
|
"email",
|
||||||
"slug",
|
"slug",
|
||||||
@@ -5550,6 +5749,53 @@
|
|||||||
"awaiting"
|
"awaiting"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"values": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "An array of pre-filled values for the submitter.",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"field",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"field": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Document template field name."
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Pre-filled value of the field."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"role": {
|
"role": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The role of the submitter."
|
"description": "The role of the submitter."
|
||||||
@@ -5661,7 +5907,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"required": {
|
"required": {
|
||||||
@@ -5687,6 +5934,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Font color of the field value."
|
"description": "Font color of the field value."
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color."
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value."
|
"description": "Horizontal alignment of the field text value."
|
||||||
@@ -5710,6 +5961,13 @@
|
|||||||
"mask": {
|
"mask": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Indicates if the field is masked on the document."
|
"description": "Indicates if the field is masked on the document."
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -5757,27 +6015,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"documents": {
|
|
||||||
"type": "array",
|
|
||||||
"description": "List of documents attached to the one-off submission.",
|
|
||||||
"items": {
|
|
||||||
"type": "object",
|
|
||||||
"required": [
|
|
||||||
"attachment_uuid",
|
|
||||||
"name"
|
|
||||||
],
|
|
||||||
"properties": {
|
|
||||||
"attachment_uuid": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Unique indentifier of attached document to the one-off submission."
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Name of the attached document to the one-off submission."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"expire_at": {
|
"expire_at": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Specify the expiration date and time after which the submission becomes unavailable for signature.",
|
"description": "Specify the expiration date and time after which the submission becomes unavailable for signature.",
|
||||||
@@ -6078,6 +6315,10 @@
|
|||||||
"event_timestamp": {
|
"event_timestamp": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Date and time when the event was triggered."
|
"description": "Date and time when the event was triggered."
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Additional event details object."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6185,7 +6426,8 @@
|
|||||||
"id": 12,
|
"id": 12,
|
||||||
"submitter_id": 7,
|
"submitter_id": 7,
|
||||||
"event_type": "view_form",
|
"event_type": "view_form",
|
||||||
"event_timestamp": "2023-12-14T15:47:17.351Z"
|
"event_timestamp": "2023-12-14T15:47:17.351Z",
|
||||||
|
"data": {}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"values": [
|
"values": [
|
||||||
@@ -6435,6 +6677,15 @@
|
|||||||
],
|
],
|
||||||
"default": "black"
|
"default": "black"
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color.",
|
||||||
|
"enum": [
|
||||||
|
"black",
|
||||||
|
"white",
|
||||||
|
"blue"
|
||||||
|
]
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value.",
|
"description": "Horizontal alignment of the field text value.",
|
||||||
@@ -6488,6 +6739,13 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6990,6 +7248,10 @@
|
|||||||
"event_timestamp": {
|
"event_timestamp": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Date and time when the event was triggered."
|
"description": "Date and time when the event was triggered."
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Additional event details object."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7126,7 +7388,8 @@
|
|||||||
"id": 12,
|
"id": 12,
|
||||||
"submitter_id": 7,
|
"submitter_id": 7,
|
||||||
"event_type": "view_form",
|
"event_type": "view_form",
|
||||||
"event_timestamp": "2023-12-14T15:48:17.351Z"
|
"event_timestamp": "2023-12-14T15:48:17.351Z",
|
||||||
|
"data": {}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"values": [
|
"values": [
|
||||||
@@ -7346,7 +7609,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"required": {
|
"required": {
|
||||||
@@ -7372,6 +7636,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Font color of the field value."
|
"description": "Font color of the field value."
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color."
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value."
|
"description": "Horizontal alignment of the field text value."
|
||||||
@@ -7395,6 +7663,13 @@
|
|||||||
"mask": {
|
"mask": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Indicates if the field is masked on the document."
|
"description": "Indicates if the field is masked on the document."
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -7793,7 +8068,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"required": {
|
"required": {
|
||||||
@@ -7819,6 +8095,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Font color of the field value."
|
"description": "Font color of the field value."
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color."
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value."
|
"description": "Horizontal alignment of the field text value."
|
||||||
@@ -7842,6 +8122,13 @@
|
|||||||
"mask": {
|
"mask": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Indicates if the field is masked on the document."
|
"description": "Indicates if the field is masked on the document."
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -8294,7 +8581,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"required": {
|
"required": {
|
||||||
@@ -8320,6 +8608,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Font color of the field value."
|
"description": "Font color of the field value."
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color."
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value."
|
"description": "Horizontal alignment of the field text value."
|
||||||
@@ -8343,6 +8635,13 @@
|
|||||||
"mask": {
|
"mask": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Indicates if the field is masked on the document."
|
"description": "Indicates if the field is masked on the document."
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -8674,7 +8973,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
@@ -8812,6 +9112,15 @@
|
|||||||
],
|
],
|
||||||
"default": "black"
|
"default": "black"
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color.",
|
||||||
|
"enum": [
|
||||||
|
"black",
|
||||||
|
"white",
|
||||||
|
"blue"
|
||||||
|
]
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value.",
|
"description": "Horizontal alignment of the field text value.",
|
||||||
@@ -8865,6 +9174,13 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8989,7 +9305,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"required": {
|
"required": {
|
||||||
@@ -9015,6 +9332,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Font color of the field value."
|
"description": "Font color of the field value."
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color."
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value."
|
"description": "Horizontal alignment of the field text value."
|
||||||
@@ -9038,6 +9359,13 @@
|
|||||||
"mask": {
|
"mask": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Indicates if the field is masked on the document."
|
"description": "Indicates if the field is masked on the document."
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -9369,7 +9697,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
@@ -9515,6 +9844,15 @@
|
|||||||
],
|
],
|
||||||
"default": "black"
|
"default": "black"
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color.",
|
||||||
|
"enum": [
|
||||||
|
"black",
|
||||||
|
"white",
|
||||||
|
"blue"
|
||||||
|
]
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value.",
|
"description": "Horizontal alignment of the field text value.",
|
||||||
@@ -9568,6 +9906,13 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9702,7 +10047,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"required": {
|
"required": {
|
||||||
@@ -9728,6 +10074,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Font color of the field value."
|
"description": "Font color of the field value."
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color."
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value."
|
"description": "Horizontal alignment of the field text value."
|
||||||
@@ -9751,6 +10101,13 @@
|
|||||||
"mask": {
|
"mask": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Indicates if the field is masked on the document."
|
"description": "Indicates if the field is masked on the document."
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -10169,7 +10526,8 @@
|
|||||||
"stamp",
|
"stamp",
|
||||||
"payment",
|
"payment",
|
||||||
"phone",
|
"phone",
|
||||||
"verification"
|
"verification",
|
||||||
|
"strikethrough"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"required": {
|
"required": {
|
||||||
@@ -10195,6 +10553,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Font color of the field value."
|
"description": "Font color of the field value."
|
||||||
},
|
},
|
||||||
|
"background": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Field box background color."
|
||||||
|
},
|
||||||
"align": {
|
"align": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Horizontal alignment of the field text value."
|
"description": "Horizontal alignment of the field text value."
|
||||||
@@ -10218,6 +10580,13 @@
|
|||||||
"mask": {
|
"mask": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Indicates if the field is masked on the document."
|
"description": "Indicates if the field is masked on the document."
|
||||||
|
},
|
||||||
|
"reasons": {
|
||||||
|
"description": "An array of signature reasons to choose from.",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -281,6 +281,10 @@ Get submission creation, completion, expiration, and archiving notifications usi
|
|||||||
"event_timestamp": {
|
"event_timestamp": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Date and time when the event was triggered."
|
"description": "Date and time when the event was triggered."
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Additional event details object."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,6 +101,10 @@ module Accounts
|
|||||||
new_template
|
new_template
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def load_recipient_form_fields(_account)
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
|
||||||
def load_signing_pkcs(account)
|
def load_signing_pkcs(account)
|
||||||
cert_data =
|
cert_data =
|
||||||
if Docuseal.multitenant?
|
if Docuseal.multitenant?
|
||||||
|
|||||||
@@ -1,7 +1,35 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module DownloadUtils
|
module DownloadUtils
|
||||||
LOCALHOSTS = %w[0.0.0.0 127.0.0.1 localhost].freeze
|
LOCALHOSTS = Set[
|
||||||
|
'0.0.0.0',
|
||||||
|
'127.0.0.1',
|
||||||
|
'127.0.1.1',
|
||||||
|
'localhost',
|
||||||
|
'localhost.localdomain',
|
||||||
|
'::1',
|
||||||
|
'[::1]',
|
||||||
|
'ip6-localhost',
|
||||||
|
'ip6-loopback',
|
||||||
|
'127.0.0.0',
|
||||||
|
'127.255.255.255',
|
||||||
|
'::',
|
||||||
|
'0:0:0:0:0:0:0:1',
|
||||||
|
'[0:0:0:0:0:0:0:1]',
|
||||||
|
'0000:0000:0000:0000:0000:0000:0000:0001',
|
||||||
|
'[0000:0000:0000:0000:0000:0000:0000:0001]',
|
||||||
|
'::0',
|
||||||
|
'0::0',
|
||||||
|
'::ffff:127.0.0.1',
|
||||||
|
'[::ffff:127.0.0.1]',
|
||||||
|
'::ffff:7f00:1',
|
||||||
|
'[::ffff:7f00:1]',
|
||||||
|
'local',
|
||||||
|
'localhost.local',
|
||||||
|
'ip6-localnet',
|
||||||
|
'ip6-allnodes',
|
||||||
|
'ip6-allrouters'
|
||||||
|
].freeze
|
||||||
|
|
||||||
UnableToDownload = Class.new(StandardError)
|
UnableToDownload = Class.new(StandardError)
|
||||||
|
|
||||||
@@ -14,10 +42,7 @@ module DownloadUtils
|
|||||||
Addressable::URI.parse(url).normalize
|
Addressable::URI.parse(url).normalize
|
||||||
end
|
end
|
||||||
|
|
||||||
if Docuseal.multitenant?
|
validate_uri!(uri) if Docuseal.multitenant?
|
||||||
raise UnableToDownload, "Error loading: #{uri}. Only HTTPS is allowed." if uri.scheme != 'https'
|
|
||||||
raise UnableToDownload, "Error loading: #{uri}. Can't download from localhost." if uri.host.in?(LOCALHOSTS)
|
|
||||||
end
|
|
||||||
|
|
||||||
resp = conn.get(uri)
|
resp = conn.get(uri)
|
||||||
|
|
||||||
@@ -26,9 +51,16 @@ module DownloadUtils
|
|||||||
resp
|
resp
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def validate_uri!(uri)
|
||||||
|
raise UnableToDownload, "Error loading: #{uri}. Only HTTPS is allowed." if uri.scheme != 'https'
|
||||||
|
raise UnableToDownload, "Error loading: #{uri}. Can't download from localhost." if uri.host.in?(LOCALHOSTS)
|
||||||
|
end
|
||||||
|
|
||||||
def conn
|
def conn
|
||||||
Faraday.new do |faraday|
|
Faraday.new do |faraday|
|
||||||
faraday.response :follow_redirects
|
faraday.response :follow_redirects, callback: lambda { |_, new_env|
|
||||||
|
validate_uri!(new_env[:url]) if Docuseal.multitenant?
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -71,7 +71,11 @@ module Params
|
|||||||
end
|
end
|
||||||
|
|
||||||
def validate_submitter(submitter_params)
|
def validate_submitter(submitter_params)
|
||||||
|
if submitter_params['invite_by'].present?
|
||||||
|
required(submitter_params, :role)
|
||||||
|
else
|
||||||
required(submitter_params, %i[email phone name])
|
required(submitter_params, %i[email phone name])
|
||||||
|
end
|
||||||
|
|
||||||
type(submitter_params, :name, String)
|
type(submitter_params, :name, String)
|
||||||
type(submitter_params, :reply_to, String)
|
type(submitter_params, :reply_to, String)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
module SendWebhookRequest
|
module SendWebhookRequest
|
||||||
USER_AGENT = 'DocuSeal.com Webhook'
|
USER_AGENT = 'DocuSeal.com Webhook'
|
||||||
|
|
||||||
LOCALHOSTS = %w[0.0.0.0 127.0.0.1 localhost].freeze
|
LOCALHOSTS = DownloadUtils::LOCALHOSTS
|
||||||
|
|
||||||
MANUAL_ATTEMPT = 99_999
|
MANUAL_ATTEMPT = 99_999
|
||||||
AUTOMATED_RETRY_RANGE = 1..(MANUAL_ATTEMPT - 1)
|
AUTOMATED_RETRY_RANGE = 1..(MANUAL_ATTEMPT - 1)
|
||||||
|
|||||||
@@ -133,9 +133,9 @@ module Submissions
|
|||||||
end
|
end
|
||||||
|
|
||||||
def create_from_submitters(template:, user:, submissions_attrs:, source:, with_template: true,
|
def create_from_submitters(template:, user:, submissions_attrs:, source:, with_template: true,
|
||||||
submitters_order: DEFAULT_SUBMITTERS_ORDER, params: {})
|
submitters_order: DEFAULT_SUBMITTERS_ORDER, params: {}, new_fields: nil)
|
||||||
Submissions::CreateFromSubmitters.call(
|
Submissions::CreateFromSubmitters.call(
|
||||||
template:, user:, submissions_attrs:, source:, submitters_order:, params:, with_template:
|
template:, user:, submissions_attrs:, source:, submitters_order:, params:, with_template:, new_fields:
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ module Submissions
|
|||||||
module_function
|
module_function
|
||||||
|
|
||||||
# rubocop:disable Metrics
|
# rubocop:disable Metrics
|
||||||
def call(template:, user:, submissions_attrs:, source:, submitters_order:, params: {}, with_template: true)
|
def call(template:, user:, submissions_attrs:, source:, submitters_order:, params: {}, with_template: true,
|
||||||
|
new_fields: nil)
|
||||||
preferences = Submitters.normalize_preferences(user.account, user, params)
|
preferences = Submitters.normalize_preferences(user.account, user, params)
|
||||||
|
|
||||||
submissions = Array.wrap(submissions_attrs).filter_map do |attrs|
|
submissions = Array.wrap(submissions_attrs).filter_map do |attrs|
|
||||||
@@ -67,7 +68,7 @@ module Submissions
|
|||||||
preferences: preferences.merge(submission_preferences))
|
preferences: preferences.merge(submission_preferences))
|
||||||
end
|
end
|
||||||
|
|
||||||
maybe_set_template_fields(submission, attrs[:submitters], with_template:)
|
maybe_set_template_fields(submission, attrs[:submitters], with_template:, new_fields:)
|
||||||
|
|
||||||
if submission.submitters.size > template.submitters.size
|
if submission.submitters.size > template.submitters.size
|
||||||
raise BaseError, 'Defined more signing parties than in template'
|
raise BaseError, 'Defined more signing parties than in template'
|
||||||
@@ -81,7 +82,7 @@ module Submissions
|
|||||||
|
|
||||||
next if submission.submitters.blank?
|
next if submission.submitters.blank?
|
||||||
|
|
||||||
maybe_add_invite_submitters(submission, template)
|
maybe_add_invite_submitters(submission, template, attrs[:submitters])
|
||||||
|
|
||||||
submission.template = nil unless with_template
|
submission.template = nil unless with_template
|
||||||
|
|
||||||
@@ -92,7 +93,6 @@ module Submissions
|
|||||||
|
|
||||||
submissions
|
submissions
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics
|
|
||||||
|
|
||||||
def maybe_enqueue_expire_at(submissions)
|
def maybe_enqueue_expire_at(submissions)
|
||||||
submissions.each do |submission|
|
submissions.each do |submission|
|
||||||
@@ -102,8 +102,16 @@ module Submissions
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def maybe_add_invite_submitters(submission, template)
|
def maybe_add_invite_submitters(submission, template, submitter_attrs)
|
||||||
template.submitters.each_with_index do |item, index|
|
template.submitters.each_with_index do |item, index|
|
||||||
|
submitter_attr = submitter_attrs.find { |e| e['role'].to_s.casecmp?(item['name'].to_s) }
|
||||||
|
|
||||||
|
if submitter_attr && submitter_attr['invite_by'].present?
|
||||||
|
invite_by_uuid = template.submitters.find { |s| s['name'] == submitter_attr['invite_by'] }&.dig('uuid')
|
||||||
|
|
||||||
|
item = item.merge('invite_by_uuid' => invite_by_uuid) if invite_by_uuid
|
||||||
|
end
|
||||||
|
|
||||||
next if item['invite_by_uuid'].blank? && item['optional_invite_by_uuid'].blank?
|
next if item['invite_by_uuid'].blank? && item['optional_invite_by_uuid'].blank?
|
||||||
next if submission.template_submitters.any? { |e| e['uuid'] == item['uuid'] }
|
next if submission.template_submitters.any? { |e| e['uuid'] == item['uuid'] }
|
||||||
|
|
||||||
@@ -127,7 +135,8 @@ module Submissions
|
|||||||
}.compact_blank
|
}.compact_blank
|
||||||
end
|
end
|
||||||
|
|
||||||
def maybe_set_template_fields(submission, submitters_attrs, default_submitter_uuid: nil, with_template: true)
|
def maybe_set_template_fields(submission, submitters_attrs, default_submitter_uuid: nil, with_template: true,
|
||||||
|
new_fields: nil)
|
||||||
template_fields = (submission.template_fields || submission.template.fields).deep_dup
|
template_fields = (submission.template_fields || submission.template.fields).deep_dup
|
||||||
|
|
||||||
submitters = submission.template_submitters || submission.template.submitters
|
submitters = submission.template_submitters || submission.template.submitters
|
||||||
@@ -141,9 +150,9 @@ module Submissions
|
|||||||
process_fields_param(submitter_attrs[:fields], template_fields, submitter_uuid)
|
process_fields_param(submitter_attrs[:fields], template_fields, submitter_uuid)
|
||||||
end
|
end
|
||||||
|
|
||||||
if template_fields != (submission.template_fields || submission.template.fields) ||
|
if template_fields != (submission.template_fields || submission.template.fields) || new_fields.present? ||
|
||||||
submitters_attrs.any? { |e| e[:completed].present? } || !with_template || submission.variables.present?
|
submitters_attrs.any? { |e| e[:completed].present? } || !with_template || submission.variables.present?
|
||||||
submission.template_fields = template_fields
|
submission.template_fields = new_fields ? new_fields + template_fields : template_fields
|
||||||
submission.template_schema = submission.template.schema if submission.template_schema.blank?
|
submission.template_schema = submission.template.schema if submission.template_schema.blank?
|
||||||
submission.variables_schema = submission.template.variables_schema if submission.template &&
|
submission.variables_schema = submission.template.variables_schema if submission.template &&
|
||||||
submission.variables_schema.blank?
|
submission.variables_schema.blank?
|
||||||
@@ -151,6 +160,7 @@ module Submissions
|
|||||||
|
|
||||||
submission
|
submission
|
||||||
end
|
end
|
||||||
|
# rubocop:enable Metrics
|
||||||
|
|
||||||
def merge_submitters_and_fields(submitter_attrs, template_submitters, template_fields)
|
def merge_submitters_and_fields(submitter_attrs, template_submitters, template_fields)
|
||||||
selected_submitters = submitter_attrs[:roles].map do |role|
|
selected_submitters = submitter_attrs[:roles].map do |role|
|
||||||
|
|||||||
@@ -333,12 +333,12 @@ module Submissions
|
|||||||
|
|
||||||
result = nil
|
result = nil
|
||||||
|
|
||||||
if area['h']&.positive? && (area['w'].to_f / area['h']) > 6
|
|
||||||
area_x = area['x'] * width
|
area_x = area['x'] * width
|
||||||
area_y = area['y'] * height
|
area_y = area['y'] * height
|
||||||
area_w = area['w'] * width
|
area_w = area['w'] * width
|
||||||
area_h = area['h'] * height
|
area_h = area['h'] * height
|
||||||
|
|
||||||
|
if area_h.positive? && (area_w.to_f / area_h) > 4.5
|
||||||
half_width = area_w / 2.0
|
half_width = area_w / 2.0
|
||||||
scale = [half_width / image.width, area_h / image.height].min
|
scale = [half_width / image.width, area_h / image.height].min
|
||||||
image_width = image.width * scale
|
image_width = image.width * scale
|
||||||
@@ -396,7 +396,7 @@ module Submissions
|
|||||||
font:,
|
font:,
|
||||||
font_size: base_font_size)
|
font_size: base_font_size)
|
||||||
|
|
||||||
result = layouter.fit([text], area['w'] * width, base_font_size / 0.65)
|
result = layouter.fit([text], area_w, base_font_size / 0.65)
|
||||||
|
|
||||||
break if result.status == :success
|
break if result.status == :success
|
||||||
|
|
||||||
@@ -405,30 +405,30 @@ module Submissions
|
|||||||
break if id_string.length < 8
|
break if id_string.length < 8
|
||||||
end
|
end
|
||||||
|
|
||||||
reason_result = layouter.fit([reason_text], area['w'] * width, height)
|
reason_result = layouter.fit([reason_text], area_w, height)
|
||||||
text_height = result.lines.sum(&:height) + reason_result.lines.sum(&:height)
|
text_height = result.lines.sum(&:height) + reason_result.lines.sum(&:height)
|
||||||
|
|
||||||
image_height = (area['h'] * height) - text_height
|
image_height = area_h - text_height
|
||||||
image_height = (area['h'] * height) / 2 if image_height < (area['h'] * height) / 2
|
image_height = area_h / 2 if image_height < area_h / 2
|
||||||
|
|
||||||
scale = [(area['w'] * width) / image.width, image_height / image.height].min
|
scale = [area_w / image.width, image_height / image.height].min
|
||||||
|
|
||||||
io = StringIO.new(image.resize([scale * 4, 1].select(&:positive?).min).write_to_buffer('.png'))
|
io = StringIO.new(image.resize([scale * 4, 1].select(&:positive?).min).write_to_buffer('.png'))
|
||||||
|
|
||||||
layouter.fit([text], area['w'] * width, base_font_size / 0.65)
|
layouter.fit([text], area_w, base_font_size / 0.65)
|
||||||
.draw(canvas, (area['x'] * width) + TEXT_LEFT_MARGIN,
|
.draw(canvas, area_x + TEXT_LEFT_MARGIN,
|
||||||
height - (area['y'] * height) - TEXT_TOP_MARGIN - image_height)
|
height - area_y - TEXT_TOP_MARGIN - image_height)
|
||||||
|
|
||||||
layouter.fit([reason_text], area['w'] * width, reason_result.lines.sum(&:height))
|
layouter.fit([reason_text], area_w, reason_result.lines.sum(&:height))
|
||||||
.draw(canvas, (area['x'] * width) + TEXT_LEFT_MARGIN,
|
.draw(canvas, area_x + TEXT_LEFT_MARGIN,
|
||||||
height - (area['y'] * height) - TEXT_TOP_MARGIN -
|
height - area_y - TEXT_TOP_MARGIN -
|
||||||
result.lines.sum(&:height) - image_height)
|
result.lines.sum(&:height) - image_height)
|
||||||
|
|
||||||
canvas.image(
|
canvas.image(
|
||||||
io,
|
io,
|
||||||
at: [
|
at: [
|
||||||
(area['x'] * width) + (area['w'] * width / 2) - ((image.width * scale) / 2),
|
area_x + (area_w / 2) - ((image.width * scale) / 2),
|
||||||
height - (area['y'] * height) - (image.height * scale / 2) - (image_height / 2)
|
height - area_y - (image.height * scale / 2) - (image_height / 2)
|
||||||
],
|
],
|
||||||
width: image.width * scale,
|
width: image.width * scale,
|
||||||
height: image.height * scale
|
height: image.height * scale
|
||||||
@@ -522,10 +522,17 @@ module Submissions
|
|||||||
if field['type'].in?(%w[multiple radio])
|
if field['type'].in?(%w[multiple radio])
|
||||||
option = field['options']&.find { |o| o['uuid'] == area['option_uuid'] }
|
option = field['options']&.find { |o| o['uuid'] == area['option_uuid'] }
|
||||||
|
|
||||||
|
value =
|
||||||
|
if option
|
||||||
option_name = option['value'].presence
|
option_name = option['value'].presence
|
||||||
option_name ||= "#{I18n.t('option', locale: locale)} #{field['options'].index(option) + 1}"
|
option_name ||= "#{I18n.t('option', locale: locale)} #{field['options'].index(option) + 1}"
|
||||||
|
|
||||||
value = Array.wrap(value).include?(option_name)
|
Array.wrap(value).include?(option_name)
|
||||||
|
else
|
||||||
|
Rollbar.error("Invalid option: #{field['uuid']}") if defined?(Rollbar)
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
next unless value == true
|
next unless value == true
|
||||||
@@ -641,7 +648,7 @@ module Submissions
|
|||||||
text_params = { font:, fill_color:, font_size: }
|
text_params = { font:, fill_color:, font_size: }
|
||||||
text_params[:line_height] = text_params[:font_size] * (FONTS_LINE_HEIGHT[font_name] || 1)
|
text_params[:line_height] = text_params[:font_size] * (FONTS_LINE_HEIGHT[font_name] || 1)
|
||||||
|
|
||||||
text = HexaPDF::Layout::TextFragment.create(value, **text_params)
|
text = HexaPDF::Layout::TextFragment.create(value.tr("\u00A0", ' '), **text_params)
|
||||||
|
|
||||||
lines = layouter.fit([text], area['w'] * width, height).lines
|
lines = layouter.fit([text], area['w'] * width, height).lines
|
||||||
box_height = lines.sum(&:height)
|
box_height = lines.sum(&:height)
|
||||||
|
|||||||
@@ -4,21 +4,23 @@ module Submissions
|
|||||||
module NormalizeParamUtils
|
module NormalizeParamUtils
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
def normalize_submissions_params!(submissions_params, template)
|
def normalize_submissions_params!(submissions_params, template, add_fields: false)
|
||||||
attachments = []
|
attachments = []
|
||||||
|
fields = []
|
||||||
|
|
||||||
Array.wrap(submissions_params).each do |submission|
|
Array.wrap(submissions_params).each do |submission|
|
||||||
submission[:submitters].each_with_index do |submitter, index|
|
submission[:submitters].each_with_index do |submitter, index|
|
||||||
_, new_attachments = normalize_submitter_params!(submitter, template, index)
|
_, new_attachments, new_fields = normalize_submitter_params!(submitter, template, index, add_fields:)
|
||||||
|
|
||||||
attachments.push(*new_attachments)
|
attachments.push(*new_attachments)
|
||||||
|
fields.push(*new_fields)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
[submissions_params, attachments]
|
[submissions_params, attachments, fields]
|
||||||
end
|
end
|
||||||
|
|
||||||
def normalize_submitter_params!(submitter_params, template, index = nil, for_submitter: nil)
|
def normalize_submitter_params!(submitter_params, template, index = nil, for_submitter: nil, add_fields: false)
|
||||||
with_values = submitter_params[:values].present?
|
with_values = submitter_params[:values].present?
|
||||||
|
|
||||||
default_values = with_values ? submitter_params[:values] : {}
|
default_values = with_values ? submitter_params[:values] : {}
|
||||||
@@ -30,18 +32,19 @@ module Submissions
|
|||||||
|
|
||||||
return submitter_params if default_values.blank?
|
return submitter_params if default_values.blank?
|
||||||
|
|
||||||
values, new_attachments =
|
values, new_attachments, new_fields =
|
||||||
Submitters::NormalizeValues.call(template,
|
Submitters::NormalizeValues.call(template,
|
||||||
default_values,
|
default_values,
|
||||||
submitter_name: submitter_params[:role] ||
|
submitter_name: submitter_params[:role] ||
|
||||||
template.submitters.dig(index, 'name'),
|
template.submitters.dig(index, 'name'),
|
||||||
role_names: submitter_params[:roles],
|
role_names: submitter_params[:roles],
|
||||||
for_submitter:,
|
for_submitter:,
|
||||||
|
add_fields:,
|
||||||
throw_errors: !with_values)
|
throw_errors: !with_values)
|
||||||
|
|
||||||
submitter_params[:values] = values
|
submitter_params[:values] = values
|
||||||
|
|
||||||
[submitter_params, new_attachments]
|
[submitter_params, new_attachments, new_fields]
|
||||||
end
|
end
|
||||||
|
|
||||||
def save_default_value_attachments!(attachments, submitters)
|
def save_default_value_attachments!(attachments, submitters)
|
||||||
|
|||||||
@@ -106,7 +106,8 @@ module Submitters
|
|||||||
if AccountConfig.exists?(account_id: submitter.submission.account_id,
|
if AccountConfig.exists?(account_id: submitter.submission.account_id,
|
||||||
key: AccountConfig::COMBINE_PDF_RESULT_KEY,
|
key: AccountConfig::COMBINE_PDF_RESULT_KEY,
|
||||||
value: true) &&
|
value: true) &&
|
||||||
submitter.submission.submitters.all?(&:completed_at?)
|
submitter.submission.submitters.all?(&:completed_at?) &&
|
||||||
|
submitter.submission.template_fields.none? { |f| f['type'] == 'verification' }
|
||||||
return [submitter.submission.combined_document_attachment || Submissions::EnsureCombinedGenerated.call(submitter)]
|
return [submitter.submission.combined_document_attachment || Submissions::EnsureCombinedGenerated.call(submitter)]
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -157,6 +158,7 @@ module Submitters
|
|||||||
preferences['send_email'] = params['send_email'].in?(TRUE_VALUES) if params.key?('send_email')
|
preferences['send_email'] = params['send_email'].in?(TRUE_VALUES) if params.key?('send_email')
|
||||||
preferences['send_sms'] = params['send_sms'].in?(TRUE_VALUES) if params.key?('send_sms')
|
preferences['send_sms'] = params['send_sms'].in?(TRUE_VALUES) if params.key?('send_sms')
|
||||||
preferences['require_phone_2fa'] = params['require_phone_2fa'].in?(TRUE_VALUES) if params.key?('require_phone_2fa')
|
preferences['require_phone_2fa'] = params['require_phone_2fa'].in?(TRUE_VALUES) if params.key?('require_phone_2fa')
|
||||||
|
preferences['require_email_2fa'] = params['require_email_2fa'].in?(TRUE_VALUES) if params.key?('require_email_2fa')
|
||||||
preferences['bcc_completed'] = params['bcc_completed'] if params.key?('bcc_completed')
|
preferences['bcc_completed'] = params['bcc_completed'] if params.key?('bcc_completed')
|
||||||
preferences['reply_to'] = params['reply_to'] if params.key?('reply_to')
|
preferences['reply_to'] = params['reply_to'] if params.key?('reply_to')
|
||||||
preferences['go_to_last'] = params['go_to_last'] if params.key?('go_to_last')
|
preferences['go_to_last'] = params['go_to_last'] if params.key?('go_to_last')
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ module Submitters
|
|||||||
AccountConfig::ENFORCE_SIGNING_ORDER_KEY,
|
AccountConfig::ENFORCE_SIGNING_ORDER_KEY,
|
||||||
AccountConfig::REQUIRE_SIGNING_REASON_KEY,
|
AccountConfig::REQUIRE_SIGNING_REASON_KEY,
|
||||||
AccountConfig::REUSE_SIGNATURE_KEY,
|
AccountConfig::REUSE_SIGNATURE_KEY,
|
||||||
|
AccountConfig::WITH_FIELD_LABELS_KEY,
|
||||||
AccountConfig::ALLOW_TO_PARTIAL_DOWNLOAD_KEY,
|
AccountConfig::ALLOW_TO_PARTIAL_DOWNLOAD_KEY,
|
||||||
AccountConfig::ALLOW_TYPED_SIGNATURE,
|
AccountConfig::ALLOW_TYPED_SIGNATURE,
|
||||||
AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY,
|
AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY,
|
||||||
@@ -35,13 +36,14 @@ module Submitters
|
|||||||
enforce_signing_order = find_safe_value(configs, AccountConfig::ENFORCE_SIGNING_ORDER_KEY) == true
|
enforce_signing_order = find_safe_value(configs, AccountConfig::ENFORCE_SIGNING_ORDER_KEY) == true
|
||||||
with_submitter_timezone = find_safe_value(configs, AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY) == true
|
with_submitter_timezone = find_safe_value(configs, AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY) == true
|
||||||
with_signature_id_reason = find_safe_value(configs, AccountConfig::WITH_SIGNATURE_ID_REASON_KEY) != false
|
with_signature_id_reason = find_safe_value(configs, AccountConfig::WITH_SIGNATURE_ID_REASON_KEY) != false
|
||||||
|
with_field_labels = find_safe_value(configs, AccountConfig::WITH_FIELD_LABELS_KEY) != false
|
||||||
policy_links = find_safe_value(configs, AccountConfig::POLICY_LINKS_KEY)
|
policy_links = find_safe_value(configs, AccountConfig::POLICY_LINKS_KEY)
|
||||||
|
|
||||||
attrs = { completed_button:, with_typed_signature:, with_confetti:,
|
attrs = { completed_button:, with_typed_signature:, with_confetti:,
|
||||||
reuse_signature:, with_decline:, with_partial_download:,
|
reuse_signature:, with_decline:, with_partial_download:,
|
||||||
policy_links:, enforce_signing_order:, completed_message:,
|
policy_links:, enforce_signing_order:, completed_message:,
|
||||||
require_signing_reason:, prefill_signature:, with_submitter_timezone:,
|
require_signing_reason:, prefill_signature:, with_submitter_timezone:,
|
||||||
with_signature_id_reason:, with_signature_id: }
|
with_signature_id_reason:, with_signature_id:, with_field_labels: }
|
||||||
|
|
||||||
keys.each do |key|
|
keys.each do |key|
|
||||||
attrs[key.to_sym] = configs.find { |e| e.key == key.to_s }&.value
|
attrs[key.to_sym] = configs.find { |e| e.key == key.to_s }&.value
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ module Submitters
|
|||||||
|
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
def call(template, values, submitter_name: nil, role_names: nil, for_submitter: nil, throw_errors: false)
|
# rubocop:disable Metrics
|
||||||
|
def call(template, values, submitter_name: nil, role_names: nil, for_submitter: nil, throw_errors: false,
|
||||||
|
add_fields: false)
|
||||||
fields =
|
fields =
|
||||||
if role_names.present?
|
if role_names.present?
|
||||||
fetch_roles_fields(template, roles: role_names)
|
fetch_roles_fields(template, roles: role_names)
|
||||||
@@ -29,6 +31,8 @@ module Submitters
|
|||||||
fields_name_index = build_fields_index(fields)
|
fields_name_index = build_fields_index(fields)
|
||||||
|
|
||||||
attachments = []
|
attachments = []
|
||||||
|
new_fields = []
|
||||||
|
recipient_form_fields = nil
|
||||||
|
|
||||||
normalized_values = values.to_h.each_with_object({}) do |(key, value), acc|
|
normalized_values = values.to_h.each_with_object({}) do |(key, value), acc|
|
||||||
next if key.blank?
|
next if key.blank?
|
||||||
@@ -40,7 +44,23 @@ module Submitters
|
|||||||
if value_fields.blank?
|
if value_fields.blank?
|
||||||
value_fields = fields_name_index[key].presence || fields_name_index[key.to_s.downcase]
|
value_fields = fields_name_index[key].presence || fields_name_index[key.to_s.downcase]
|
||||||
|
|
||||||
raise(UnknownFieldName, "Unknown field: #{key}") if value_fields.blank? && throw_errors
|
if value_fields.blank?
|
||||||
|
if add_fields && (recipient_form_fields ||= Accounts.load_recipient_form_fields(template.account))
|
||||||
|
new_field = recipient_form_fields.to_a.find { |e| e['name'] == key }.deep_dup
|
||||||
|
|
||||||
|
if new_field && fields.present?
|
||||||
|
new_field = new_field.except('conditions')
|
||||||
|
.merge('uuid' => SecureRandom.uuid,
|
||||||
|
'readonly' => true,
|
||||||
|
'submitter_uuid' => fields.first['submitter_uuid'])
|
||||||
|
|
||||||
|
new_fields.push(new_field)
|
||||||
|
value_fields = [new_field]
|
||||||
|
end
|
||||||
|
elsif throw_errors
|
||||||
|
raise(UnknownFieldName, "Unknown field: #{key}")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
next if value_fields.blank?
|
next if value_fields.blank?
|
||||||
@@ -59,8 +79,9 @@ module Submitters
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
[normalized_values, attachments]
|
[normalized_values, attachments, new_fields]
|
||||||
end
|
end
|
||||||
|
# rubocop:enable Metrics
|
||||||
|
|
||||||
def normalize_value(field, value)
|
def normalize_value(field, value)
|
||||||
if field['type'] == 'checkbox'
|
if field['type'] == 'checkbox'
|
||||||
|
|||||||