Merge from docusealco/wip
This commit is contained in:
@@ -22,7 +22,7 @@ class TemplatesPreferencesController < ApplicationController
|
||||
preferences: %i[bcc_completed request_email_subject request_email_body
|
||||
documents_copy_email_subject documents_copy_email_body
|
||||
documents_copy_email_enabled documents_copy_email_attach_audit
|
||||
documents_copy_email_attach_documents
|
||||
documents_copy_email_attach_documents documents_copy_email_reply_to
|
||||
completed_notification_email_attach_documents
|
||||
completed_redirect_url
|
||||
submitters_order
|
||||
|
||||
@@ -20,7 +20,8 @@ export default targetable(class extends HTMLElement {
|
||||
fetch(this.dataset.src).then(async (response) => {
|
||||
if (response.ok) {
|
||||
const urls = await response.json()
|
||||
const isSafariIos = /iPhone|iPad|iPod/i.test(navigator.userAgent)
|
||||
const isMobileSafariIos = 'ontouchstart' in window && navigator.maxTouchPoints > 0 && /AppleWebKit/i.test(navigator.userAgent)
|
||||
const isSafariIos = isMobileSafariIos || /iPhone|iPad|iPod/i.test(navigator.userAgent)
|
||||
|
||||
if (isSafariIos && urls.length > 1) {
|
||||
this.downloadSafariIos(urls)
|
||||
|
||||
@@ -197,7 +197,10 @@
|
||||
<span v-else-if="field.type === 'date'">
|
||||
{{ formattedDate }}
|
||||
</span>
|
||||
<span v-else-if="field.type === 'number'">
|
||||
<span
|
||||
v-else-if="field.type === 'number'"
|
||||
class="w-full"
|
||||
>
|
||||
{{ formatNumber(modelValue, field.preferences?.format) }}
|
||||
</span>
|
||||
<span
|
||||
|
||||
@@ -215,7 +215,8 @@ export default {
|
||||
fetch(this.baseUrl + `/submitters/${this.submitterSlug}/download`).then(async (response) => {
|
||||
if (response.ok) {
|
||||
const urls = await response.json()
|
||||
const isSafariIos = /iPhone|iPad|iPod/i.test(navigator.userAgent)
|
||||
const isMobileSafariIos = 'ontouchstart' in window && navigator.maxTouchPoints > 0 && /AppleWebKit/i.test(navigator.userAgent)
|
||||
const isSafariIos = isMobileSafariIos || /iPhone|iPad|iPod/i.test(navigator.userAgent)
|
||||
|
||||
if (isSafariIos && urls.length > 1) {
|
||||
this.downloadSafariIos(urls)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
/>
|
||||
<FieldAreas
|
||||
:steps="readonlyConditionalFields.map((e) => [e])"
|
||||
:values="readonlyConditionalFields.reduce((acc, f) => { acc[f.uuid] = (values[f.uuid] || f.default_value); return acc }, {})"
|
||||
:values="readonlyConditionalFieldValues"
|
||||
:submitter="submitter"
|
||||
:attachments-index="attachmentsIndex"
|
||||
:submittable="false"
|
||||
@@ -23,6 +23,7 @@
|
||||
<FormulaFieldAreas
|
||||
v-if="formulaFields.length"
|
||||
:fields="formulaFields"
|
||||
:readonly-values="readonlyConditionalFieldValues"
|
||||
:values="values"
|
||||
/>
|
||||
<Teleport
|
||||
@@ -855,7 +856,16 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
isMobile () {
|
||||
return /android|iphone|ipad/i.test(navigator.userAgent)
|
||||
const isMobileSafariIos = 'ontouchstart' in window && navigator.maxTouchPoints > 0 && /AppleWebKit/i.test(navigator.userAgent)
|
||||
|
||||
return isMobileSafariIos || /android|iphone|ipad/i.test(navigator.userAgent)
|
||||
},
|
||||
readonlyConditionalFieldValues () {
|
||||
return this.readonlyConditionalFields.reduce((acc, f) => {
|
||||
acc[f.uuid] = (this.values[f.uuid] || f.default_value)
|
||||
|
||||
return acc
|
||||
}, {})
|
||||
},
|
||||
attachmentConditionsIndex () {
|
||||
return this.schema.reduce((acc, item) => {
|
||||
@@ -1103,7 +1113,9 @@ export default {
|
||||
this.minimizeForm()
|
||||
}
|
||||
|
||||
if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) {
|
||||
const isMobileSafariIos = 'ontouchstart' in window && navigator.maxTouchPoints > 0 && /AppleWebKit/i.test(navigator.userAgent)
|
||||
|
||||
if (isMobileSafariIos || /iPhone|iPad|iPod/i.test(navigator.userAgent)) {
|
||||
this.$nextTick(() => {
|
||||
const root = this.$root.$el.parentNode.getRootNode()
|
||||
const scrollbox = root.getElementById('scrollbox')
|
||||
|
||||
@@ -38,6 +38,11 @@ export default {
|
||||
required: false,
|
||||
default: () => []
|
||||
},
|
||||
readonlyValues: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({})
|
||||
},
|
||||
values: {
|
||||
type: Object,
|
||||
required: false,
|
||||
@@ -87,7 +92,7 @@ export default {
|
||||
},
|
||||
calculateFormula (field) {
|
||||
const transformedFormula = field.preferences.formula.replace(/{{(.*?)}}/g, (match, uuid) => {
|
||||
return this.values[uuid] || 0.0
|
||||
return this.readonlyValues[uuid] || this.values[uuid] || 0.0
|
||||
})
|
||||
|
||||
return this.math.evaluate(transformedFormula.toLowerCase())
|
||||
|
||||
@@ -125,12 +125,16 @@ export default {
|
||||
async mounted () {
|
||||
this.isLoading = true
|
||||
|
||||
Promise.all([
|
||||
import('@eid-easy/eideasy-widget'),
|
||||
this.start()
|
||||
]).finally(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
if (new URLSearchParams(window.location.search).get('submit') === 'true') {
|
||||
this.$emit('submit')
|
||||
} else {
|
||||
Promise.all([
|
||||
import('@eid-easy/eideasy-widget'),
|
||||
this.start()
|
||||
]).finally(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
start () {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<div
|
||||
v-if="isSelected || isDraw"
|
||||
class="top-0 bottom-0 right-0 left-0 absolute border border-1.5 pointer-events-none"
|
||||
:class="field.type === 'heading' ? '' : borderColors[submitterIndex]"
|
||||
:class="field.type === 'heading' ? '' : borderColors[submitterIndex % borderColors.length]"
|
||||
/>
|
||||
<div
|
||||
v-if="field.type === 'cells' && (isSelected || isDraw)"
|
||||
@@ -20,7 +20,7 @@
|
||||
v-for="(cellW, index) in cells"
|
||||
:key="index"
|
||||
class="absolute top-0 bottom-0 border-r"
|
||||
:class="field.type === 'heading' ? '' : borderColors[submitterIndex]"
|
||||
:class="field.type === 'heading' ? '' : borderColors[submitterIndex % borderColors.length]"
|
||||
:style="{ left: (cellW / area.w * 100) + '%' }"
|
||||
>
|
||||
<span
|
||||
@@ -70,7 +70,7 @@
|
||||
@keydown.enter.prevent="onNameEnter"
|
||||
@focus="onNameFocus"
|
||||
@blur="onNameBlur"
|
||||
>{{ optionIndexText }} {{ (defaultField ? (field.title || field.name) : field.name) || defaultName }}</span>
|
||||
>{{ optionIndexText }} {{ (defaultField ? (defaultField.title || field.title || field.name) : field.name) || defaultName }}</span>
|
||||
<div
|
||||
v-if="isSettingsFocus || (isValueInput && field.type !== 'heading') || (isNameFocus && !['checkbox', 'phone'].includes(field.type))"
|
||||
class="flex items-center ml-1.5"
|
||||
@@ -161,7 +161,7 @@
|
||||
ref="touchValueTarget"
|
||||
class="flex items-center h-full w-full"
|
||||
dir="auto"
|
||||
:class="[isValueInput ? 'bg-opacity-50' : 'bg-opacity-80', field.type === 'heading' ? 'bg-gray-50' : bgColors[submitterIndex], isDefaultValuePresent || isValueInput || (withFieldPlaceholder && field.areas) ? (alignClasses[field.preferences?.align] || '') : 'justify-center']"
|
||||
:class="[isValueInput ? 'bg-opacity-50' : 'bg-opacity-80', field.type === 'heading' ? 'bg-gray-50' : bgColors[submitterIndex % bgColors.length], isDefaultValuePresent || isValueInput || (withFieldPlaceholder && field.areas) ? (alignClasses[field.preferences?.align] || '') : 'justify-center']"
|
||||
@click="focusValueInput"
|
||||
>
|
||||
<span
|
||||
@@ -212,7 +212,7 @@
|
||||
:contenteditable="isValueInput"
|
||||
class="whitespace-pre-wrap outline-none empty:before:content-[attr(placeholder)] before:text-gray-400"
|
||||
:class="{ 'cursor-text': isValueInput }"
|
||||
:placeholder="withFieldPlaceholder && !isValueInput ? field.name || defaultName : t('type_value')"
|
||||
:placeholder="withFieldPlaceholder && !isValueInput ? defaultField?.title || field.title || field.name || defaultName : t('type_value')"
|
||||
@blur="onDefaultValueBlur"
|
||||
@paste.prevent="onPaste"
|
||||
@keydown.enter="onDefaultValueEnter"
|
||||
@@ -420,16 +420,6 @@ export default {
|
||||
},
|
||||
borderColors () {
|
||||
return [
|
||||
'border-red-500/80',
|
||||
'border-sky-500/80',
|
||||
'border-emerald-500/80',
|
||||
'border-yellow-300/80',
|
||||
'border-purple-600/80',
|
||||
'border-pink-500/80',
|
||||
'border-cyan-500/80',
|
||||
'border-orange-500/80',
|
||||
'border-lime-500/80',
|
||||
'border-indigo-500/80',
|
||||
'border-red-500/80',
|
||||
'border-sky-500/80',
|
||||
'border-emerald-500/80',
|
||||
@@ -444,16 +434,6 @@ export default {
|
||||
},
|
||||
bgColors () {
|
||||
return [
|
||||
'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',
|
||||
'bg-red-100',
|
||||
'bg-sky-100',
|
||||
'bg-emerald-100',
|
||||
|
||||
@@ -179,6 +179,7 @@
|
||||
:with-arrows="template.schema.length > 1"
|
||||
:item="item"
|
||||
:document="sortedDocuments[index]"
|
||||
:data-document-uuid="item.attachment_uuid"
|
||||
:accept-file-types="acceptFileTypes"
|
||||
:with-replace-button="withUploadButton"
|
||||
:editable="editable"
|
||||
@@ -266,6 +267,7 @@
|
||||
:input-mode="inputMode"
|
||||
:default-fields="[...defaultRequiredFields, ...defaultFields]"
|
||||
:allow-draw="!onlyDefinedFields"
|
||||
:data-document-uuid="document.uuid"
|
||||
:default-submitters="defaultSubmitters"
|
||||
:with-field-placeholder="withFieldPlaceholder"
|
||||
:draw-field="drawField"
|
||||
@@ -701,7 +703,9 @@ export default {
|
||||
return this.locale.split('-')[0].toLowerCase()
|
||||
},
|
||||
isMobile () {
|
||||
return /android|iphone|ipad/i.test(navigator.userAgent)
|
||||
const isMobileSafariIos = 'ontouchstart' in window && navigator.maxTouchPoints > 0 && /AppleWebKit/i.test(navigator.userAgent)
|
||||
|
||||
return isMobileSafariIos || /android|iphone|ipad/i.test(navigator.userAgent)
|
||||
},
|
||||
defaultDateFormat () {
|
||||
const isUsBrowser = Intl.DateTimeFormat().resolvedOptions().locale.endsWith('-US')
|
||||
@@ -770,13 +774,17 @@ export default {
|
||||
}
|
||||
})
|
||||
|
||||
const defineSubmittersUuids = this.defineSubmitters.map((name) => {
|
||||
return this.template.submitters.find(e => e.name === name)?.uuid
|
||||
})
|
||||
|
||||
this.defineSubmitters.forEach((name, index) => {
|
||||
const submitter = (this.template.submitters[index] ||= {})
|
||||
|
||||
submitter.name = name || this.submitterDefaultNames[index]
|
||||
|
||||
if (existingSubmittersUuids.filter(Boolean).length) {
|
||||
submitter.uuid = existingSubmittersUuids[index] || submitter.uuid || v4()
|
||||
if (defineSubmittersUuids.filter(Boolean).length || existingSubmittersUuids.filter(Boolean).length) {
|
||||
submitter.uuid = defineSubmittersUuids[index] || existingSubmittersUuids[index] || submitter.uuid || v4()
|
||||
} else {
|
||||
submitter.uuid ||= v4()
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
:input-mode="inputMode"
|
||||
:number="index"
|
||||
:editable="editable"
|
||||
:data-page="index"
|
||||
:areas="areasIndex[index]"
|
||||
:allow-draw="allowDraw"
|
||||
:is-drag="isDrag"
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
/>
|
||||
<Contenteditable
|
||||
ref="name"
|
||||
:model-value="(defaultField ? (field.title || field.name) : field.name) || defaultName"
|
||||
:model-value="(defaultField ? (defaultField.title || field.title || field.name) : field.name) || defaultName"
|
||||
:editable="editable && !defaultField && field.type != 'heading'"
|
||||
:icon-inline="true"
|
||||
:icon-width="18"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="flex items-center space-x-2">
|
||||
<span
|
||||
class="w-3 h-3 flex-shrink-0 rounded-full"
|
||||
:class="colors[submitters.indexOf(selectedSubmitter)]"
|
||||
:class="colors[submitters.indexOf(selectedSubmitter) % colors.length]"
|
||||
/>
|
||||
<Contenteditable
|
||||
v-model="selectedSubmitter.name"
|
||||
@@ -53,7 +53,7 @@
|
||||
<span class="py-1 flex items-center">
|
||||
<span
|
||||
class="rounded-full w-3 h-3 ml-1 mr-3"
|
||||
:class="colors[index]"
|
||||
:class="colors[index % colors.length]"
|
||||
/>
|
||||
<span>
|
||||
{{ submitter.name }}
|
||||
@@ -101,7 +101,7 @@
|
||||
>
|
||||
<button
|
||||
class="mx-1 w-3 h-3 rounded-full"
|
||||
:class="colors[submitters.indexOf(selectedSubmitter)]"
|
||||
:class="colors[submitters.indexOf(selectedSubmitter) % colors.length]"
|
||||
/>
|
||||
</label>
|
||||
<label
|
||||
@@ -113,7 +113,7 @@
|
||||
<div class="flex items-center space-x-2">
|
||||
<span
|
||||
class="w-3 h-3 rounded-full"
|
||||
:class="colors[submitters.indexOf(selectedSubmitter)]"
|
||||
:class="colors[submitters.indexOf(selectedSubmitter) % colors.length]"
|
||||
/>
|
||||
<Contenteditable
|
||||
v-model="selectedSubmitter.name"
|
||||
@@ -153,7 +153,7 @@
|
||||
<span class="py-1 flex items-center">
|
||||
<span
|
||||
class="rounded-full w-3 h-3 ml-1 mr-3"
|
||||
:class="colors[index]"
|
||||
:class="colors[index % colors.length]"
|
||||
/>
|
||||
<span>
|
||||
{{ submitter.name }}
|
||||
@@ -275,16 +275,6 @@ export default {
|
||||
computed: {
|
||||
colors () {
|
||||
return [
|
||||
'bg-red-500',
|
||||
'bg-sky-500',
|
||||
'bg-emerald-500',
|
||||
'bg-yellow-300',
|
||||
'bg-purple-600',
|
||||
'bg-pink-500',
|
||||
'bg-cyan-500',
|
||||
'bg-orange-500',
|
||||
'bg-lime-500',
|
||||
'bg-indigo-500',
|
||||
'bg-red-500',
|
||||
'bg-sky-500',
|
||||
'bg-emerald-500',
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
:field="field"
|
||||
:type-index="fields.filter((f) => f.type === field.type).indexOf(field)"
|
||||
:editable="editable && (!fieldsDragFieldRef.value || fieldsDragFieldRef.value !== field)"
|
||||
:default-field="defaultFields.find((f) => f.name === field.name)"
|
||||
:default-field="defaultFieldsIndex[field.name]"
|
||||
:draggable="editable"
|
||||
@dragstart="fieldsDragFieldRef.value = field"
|
||||
@dragend="fieldsDragFieldRef.value = null"
|
||||
@@ -299,6 +299,13 @@ export default {
|
||||
isShowFieldSearch () {
|
||||
return this.submitterDefaultFields.length > 15
|
||||
},
|
||||
defaultFieldsIndex () {
|
||||
return this.defaultFields.reduce((acc, field) => {
|
||||
acc[field.name] = field
|
||||
|
||||
return acc
|
||||
}, {})
|
||||
},
|
||||
fieldIconsSorted () {
|
||||
if (this.fieldTypes.length) {
|
||||
return this.fieldTypes.reduce((acc, type) => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
class="relative cursor-crosshair select-none"
|
||||
class="relative select-none"
|
||||
:class="{ 'cursor-crosshair': allowDraw }"
|
||||
:style="drawField ? 'touch-action: none' : ''"
|
||||
>
|
||||
<img
|
||||
@@ -25,7 +26,7 @@
|
||||
:field="item.field"
|
||||
:editable="editable"
|
||||
:with-field-placeholder="withFieldPlaceholder"
|
||||
:default-field="defaultFields.find((f) => f.name === item.field.name)"
|
||||
:default-field="defaultFieldsIndex[item.field.name]"
|
||||
:default-submitters="defaultSubmitters"
|
||||
:max-page="totalPages - 1"
|
||||
@start-resize="resizeDirection = $event"
|
||||
@@ -142,6 +143,13 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
defaultFieldsIndex () {
|
||||
return this.defaultFields.reduce((acc, field) => {
|
||||
acc[field.name] = field
|
||||
|
||||
return acc
|
||||
}, {})
|
||||
},
|
||||
defaultFieldType () {
|
||||
if (this.drawFieldType) {
|
||||
return this.drawFieldType
|
||||
@@ -154,7 +162,9 @@ export default {
|
||||
}
|
||||
},
|
||||
isMobile () {
|
||||
return /android|iphone|ipad/i.test(navigator.userAgent)
|
||||
const isMobileSafariIos = 'ontouchstart' in window && navigator.maxTouchPoints > 0 && /AppleWebKit/i.test(navigator.userAgent)
|
||||
|
||||
return isMobileSafariIos || /android|iphone|ipad/i.test(navigator.userAgent)
|
||||
},
|
||||
resizeDirectionClasses () {
|
||||
return {
|
||||
|
||||
@@ -104,17 +104,17 @@
|
||||
@update:model-value="onUpdateName"
|
||||
/>
|
||||
</div>
|
||||
<Teleport
|
||||
v-if="isShowConditionsModal"
|
||||
:to="modalContainerEl"
|
||||
>
|
||||
<ConditionsModal
|
||||
:item="item"
|
||||
:build-default-name="buildDefaultName"
|
||||
@close="isShowConditionsModal = false"
|
||||
/>
|
||||
</Teleport>
|
||||
</div>
|
||||
<Teleport
|
||||
v-if="isShowConditionsModal"
|
||||
:to="modalContainerEl"
|
||||
>
|
||||
<ConditionsModal
|
||||
:item="item"
|
||||
:build-default-name="buildDefaultName"
|
||||
@close="isShowConditionsModal = false"
|
||||
/>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
@@ -121,7 +121,7 @@ class SubmitterMailer < ApplicationMailer
|
||||
@body ||= @email_config.value['body'] if @email_config
|
||||
|
||||
assign_message_metadata('submitter_documents_copy', @submitter)
|
||||
reply_to = build_submitter_reply_to(submitter)
|
||||
reply_to = build_submitter_reply_to(submitter, email_config: @email_config, documents_copy_email: true)
|
||||
|
||||
I18n.with_locale(@current_account.locale) do
|
||||
subject =
|
||||
@@ -140,8 +140,10 @@ class SubmitterMailer < ApplicationMailer
|
||||
|
||||
private
|
||||
|
||||
def build_submitter_reply_to(submitter)
|
||||
def build_submitter_reply_to(submitter, email_config: nil, documents_copy_email: nil)
|
||||
reply_to = submitter.preferences['reply_to'].presence
|
||||
reply_to ||= submitter.template.preferences['documents_copy_email_reply_to'].presence if documents_copy_email
|
||||
reply_to ||= email_config.value['reply_to'].presence if email_config
|
||||
|
||||
if reply_to.blank? && (submitter.submission.created_by_user || submitter.template.author)&.email != submitter.email
|
||||
reply_to = (submitter.submission.created_by_user || submitter.template.author)&.friendly_name&.sub(/\+\w+@/, '@')
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<div class="collapse-content">
|
||||
<%= form_for AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::SUBMITTER_DOCUMENTS_COPY_EMAIL_KEY), url: settings_personalization_path, method: :post, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
||||
<%= f.hidden_field :key %>
|
||||
<%= f.fields_for :value, Struct.new(:subject, :body, :attach_audit_log, :attach_documents).new(*f.object.value.values_at('subject', 'body', 'attach_audit_log', 'attach_documents')) do |ff| %>
|
||||
<%= f.fields_for :value, Struct.new(:subject, :body, :reply_to, :attach_audit_log, :attach_documents).new(*f.object.value.values_at('subject', 'body', 'reply_to', 'attach_audit_log', 'attach_documents')) do |ff| %>
|
||||
<div class="form-control">
|
||||
<%= ff.label :subject, t('subject'), class: 'label' %>
|
||||
<%= ff.text_field :subject, required: true, class: 'base-input', dir: 'auto' %>
|
||||
@@ -24,6 +24,12 @@
|
||||
<%= ff.text_area :body, required: true, class: 'base-input w-full py-2', dir: 'auto' %>
|
||||
</autoresize-textarea>
|
||||
</div>
|
||||
<% if can?(:manage, :reply_to) %>
|
||||
<div class="form-control">
|
||||
<%= ff.label :reply_to, t('reply_to'), class: 'label' %>
|
||||
<%= ff.email_field :reply_to, class: 'base-input', dir: 'auto', placeholder: t(:email) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="flex items-center justify-between pt-2.5 mx-1">
|
||||
<span>
|
||||
<%= t('attach_documents') %>
|
||||
|
||||
@@ -61,3 +61,4 @@
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= render 'shared/review_form' %>
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
<%= form_for @template, url: template_preferences_path(@template), method: :post, html: { autocomplete: 'off', class: 'mt-1' }, data: { close_on_submit: false } do |f| %>
|
||||
<toggle-on-submit data-element-id="email_saved_alert2"></toggle-on-submit>
|
||||
<% configs = AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::SUBMITTER_DOCUMENTS_COPY_EMAIL_KEY).value %>
|
||||
<%= f.fields_for :preferences, Struct.new(:documents_copy_email_subject, :documents_copy_email_body, :documents_copy_email_enabled, :documents_copy_email_attach_audit, :documents_copy_email_attach_documents).new(@template.preferences['documents_copy_email_subject'].presence || configs['subject'], @template.preferences['documents_copy_email_body'].presence || configs['body'], @template.preferences['documents_copy_email_enabled'], configs['attach_audit_log'] != false && @template.preferences['documents_copy_email_attach_audit'] != false, configs['attach_documents'] != false && @template.preferences['documents_copy_email_attach_documents'] != false) do |ff| %>
|
||||
<%= f.fields_for :preferences, Struct.new(:documents_copy_email_reply_to, :documents_copy_email_subject, :documents_copy_email_body, :documents_copy_email_enabled, :documents_copy_email_attach_audit, :documents_copy_email_attach_documents).new(@template.preferences['documents_copy_email_reply_to'].presence || configs['reply_to'], @template.preferences['documents_copy_email_subject'].presence || configs['subject'], @template.preferences['documents_copy_email_body'].presence || configs['body'], @template.preferences['documents_copy_email_enabled'], configs['attach_audit_log'] != false && @template.preferences['documents_copy_email_attach_audit'] != false, configs['attach_documents'] != false && @template.preferences['documents_copy_email_attach_documents'] != false) do |ff| %>
|
||||
<div class="form-control">
|
||||
<%= ff.label :documents_copy_email_subject, t('email_subject'), class: 'label' %>
|
||||
<%= ff.text_field :documents_copy_email_subject, required: true, class: 'base-input', dir: 'auto' %>
|
||||
@@ -134,6 +134,12 @@
|
||||
<%= ff.text_area :documents_copy_email_body, required: true, class: 'base-input w-full py-2', dir: 'auto' %>
|
||||
</autoresize-textarea>
|
||||
</div>
|
||||
<% if can?(:manage, :reply_to) %>
|
||||
<div class="form-control">
|
||||
<%= ff.label :documents_copy_email_reply_to, t('reply_to'), class: 'label' %>
|
||||
<%= ff.email_field :documents_copy_email_reply_to, class: 'base-input', dir: 'auto', placeholder: t(:email) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="flex items-center justify-between pt-2.5 px-1 mb-2">
|
||||
<span>
|
||||
<%= t('attach_documents_to_the_email') %>
|
||||
|
||||
+36
-6
@@ -20,6 +20,7 @@ en: &en
|
||||
language_ko: 한국어
|
||||
hi_there: Hi there
|
||||
thanks: Thanks
|
||||
reply_to: Reply to
|
||||
pending_by_me: Pending by me
|
||||
partially_completed: Partially completed
|
||||
unarchive: Unarchive
|
||||
@@ -682,6 +683,10 @@ en: &en
|
||||
click_here_to_learn_more_about_user_roles_and_permissions_html: '<a href="https://www.docuseal.com/resources/manage-users-and-roles" class="link" rel="noopener noreferrer nofollow" target="_blank">Click here</a> to learn more about user roles and permissions.'
|
||||
count_10_signature_request_emails_sent_this_month_upgrade_to_pro_to_send_unlimited_signature_request_email: '%{count} / 10 signature request emails sent this month. Upgrade to Pro to send unlimited signature request email.'
|
||||
test_mode_emails_limit_will_be_reset_within_24_hours: Test mode emails limit will be reset within 24 hours.
|
||||
on_a_scale_of_1_to_10_how_satisfied_are_you_with_the_docuseal_product_: On a scale of 1 to 10, how satisfied are you with the DocuSeal product?
|
||||
tell_us_more_about_your_experience: Tell us more about your experience
|
||||
extremely_dissatisfied: Extremely Dissatisfied
|
||||
extremely_satisfied: Extremely Satisfied
|
||||
submission_event_names:
|
||||
send_email_to_html: '<b>Email sent</b> to %{submitter_name}'
|
||||
send_reminder_email_to_html: '<b>Reminder email sent</b> to %{submitter_name}'
|
||||
@@ -720,6 +725,7 @@ en: &en
|
||||
read: Read your data
|
||||
|
||||
es: &es
|
||||
reply_to: Responder a
|
||||
partially_completed: Parcialmente completado
|
||||
pending_by_me: Pendiente por mi
|
||||
add: Agregar
|
||||
@@ -1384,6 +1390,10 @@ es: &es
|
||||
click_here_to_learn_more_about_user_roles_and_permissions_html: '<a href="https://www.docuseal.com/resources/manage-users-and-roles" class="link" rel="noopener noreferrer nofollow" target="_blank">Haz clic aquí</a> para obtener más información sobre los roles y permisos de usuario.'
|
||||
count_10_signature_request_emails_sent_this_month_upgrade_to_pro_to_send_unlimited_signature_request_email: '%{count} / 10 correos electrónicos de solicitud de firma enviados este mes. Mejora a Pro para enviar solicitudes de firma ilimitadas.'
|
||||
test_mode_emails_limit_will_be_reset_within_24_hours: El límite de correos electrónicos en modo de prueba se restablecerá en 24 horas.
|
||||
on_a_scale_of_1_to_10_how_satisfied_are_you_with_the_docuseal_product_: 'En una escala del 1 al 10, ¿qué tan satisfecho estás con el producto DocuSeal?'
|
||||
tell_us_more_about_your_experience: Cuéntanos más sobre tu experiencia
|
||||
extremely_dissatisfied: Extremadamente insatisfecho
|
||||
extremely_satisfied: Extremadamente satisfecho
|
||||
submission_event_names:
|
||||
send_email_to_html: '<b>Correo electrónico enviado</b> a %{submitter_name}'
|
||||
send_reminder_email_to_html: '<b>Correo de recordatorio enviado</b> a %{submitter_name}'
|
||||
@@ -1422,6 +1432,7 @@ es: &es
|
||||
read: Leer tus datos
|
||||
|
||||
it: &it
|
||||
reply_to: Rispondi a
|
||||
pending_by_me: In sospeso da me
|
||||
add: Aggiungi
|
||||
adding: Aggiungendo
|
||||
@@ -1437,7 +1448,7 @@ it: &it
|
||||
document_name: Nome del Documento
|
||||
unarchive: Ripristina
|
||||
awaiting_completion_by_the_other_party: "In attesa di completamento da parte dell'altra parte"
|
||||
enforce_recipients_order: Aplicar el orden de los destinatarios
|
||||
enforce_recipients_order: "Applicare l'ordine dei destinatari"
|
||||
first_party: 'Prima parte'
|
||||
docuseal_trusted_signature: "Firma Fiduciaria DocuSeal"
|
||||
hello_name: Ciao %{name}
|
||||
@@ -2085,6 +2096,10 @@ it: &it
|
||||
click_here_to_learn_more_about_user_roles_and_permissions_html: '<a href="https://www.docuseal.com/resources/manage-users-and-roles" class="link" rel="noopener noreferrer nofollow" target="_blank">Fai clic qui</a> per saperne di più sui ruoli e le autorizzazioni degli utenti.'
|
||||
count_10_signature_request_emails_sent_this_month_upgrade_to_pro_to_send_unlimited_signature_request_email: '%{count} / 10 e-mail di richiesta di firma inviati questo mese. Passa a Pro per inviare richieste di firma illimitate.'
|
||||
test_mode_emails_limit_will_be_reset_within_24_hours: Il limite di e-mail in modalità di test verrà ripristinato entro 24 ore.
|
||||
on_a_scale_of_1_to_10_how_satisfied_are_you_with_the_docuseal_product_: 'Su una scala da 1 a 10, quanto sei soddisfatto del prodotto DocuSeal?'
|
||||
tell_us_more_about_your_experience: Raccontaci di più sulla tua esperienza
|
||||
extremely_dissatisfied: Estremamente insoddisfatto
|
||||
extremely_satisfied: Estremamente soddisfatto
|
||||
submission_event_names:
|
||||
send_email_to_html: '<b>E-mail inviato</b> a %{submitter_name}'
|
||||
send_reminder_email_to_html: '<b>E-mail di promemoria inviato</b> a %{submitter_name}'
|
||||
@@ -2123,6 +2138,7 @@ it: &it
|
||||
read: Leggi i tuoi dati
|
||||
|
||||
fr: &fr
|
||||
reply_to: Répondre à
|
||||
partially_completed: Partiellement complété
|
||||
pending_by_me: En attente par moi
|
||||
add: Ajouter
|
||||
@@ -2741,11 +2757,11 @@ fr: &fr
|
||||
unverified: Non vérifié
|
||||
document: Document
|
||||
completed_at: Terminé le
|
||||
edit_recipient: Modifica Destinatario
|
||||
update_recipient: Aggiorna Destinatario
|
||||
use_international_format_1xxx_: 'Utilizza il formato internazionale: +1xxx...'
|
||||
submitter_cannot_be_updated: Il mittente non può essere aggiornato.
|
||||
at_least_one_field_must_be_filled: Almeno un campo deve essere compilato.
|
||||
edit_recipient: Modifier le destinataire
|
||||
update_recipient: Mettre à jour le destinataire
|
||||
use_international_format_1xxx_: 'Utilisez un format international : +1xxx...'
|
||||
submitter_cannot_be_updated: Le soumissionnaire ne peut pas être mis à jour.
|
||||
at_least_one_field_must_be_filled: Au moins un champ doit être rempli.
|
||||
archived_users: Utilisateurs Archivés
|
||||
embedding_users: Utilisateurs Intégrés
|
||||
view_embedding_users: Voir les Utilisateurs Intégrés
|
||||
@@ -2788,6 +2804,10 @@ fr: &fr
|
||||
click_here_to_learn_more_about_user_roles_and_permissions_html: '<a href="https://www.docuseal.com/resources/manage-users-and-roles" class="link" rel="noopener noreferrer nofollow" target="_blank">Cliquez ici</a> pour en savoir plus sur les rôles et les autorisations des utilisateurs.'
|
||||
count_10_signature_request_emails_sent_this_month_upgrade_to_pro_to_send_unlimited_signature_request_email: '%{count} / 10 e-mails de demande de signature envoyés ce mois-ci. Passez à Pro pour envoyer des demandes de signature illimitées.'
|
||||
test_mode_emails_limit_will_be_reset_within_24_hours: La limite d'e-mails en mode test sera réinitialisée dans les 24 heures.
|
||||
on_a_scale_of_1_to_10_how_satisfied_are_you_with_the_docuseal_product_: 'Sur une échelle de 1 à 10, à quel point êtes-vous satisfait du produit DocuSeal?'
|
||||
tell_us_more_about_your_experience: Parlez-nous davantage de votre expérience
|
||||
extremely_dissatisfied: Extrêmement insatisfait
|
||||
extremely_satisfied: Extrêmement satisfait
|
||||
submission_event_names:
|
||||
send_email_to_html: '<b>E-mail envoyé</b> à %{submitter_name}'
|
||||
send_reminder_email_to_html: '<b>E-mail de rappel envoyé</b> à %{submitter_name}'
|
||||
@@ -2826,6 +2846,7 @@ fr: &fr
|
||||
read: Lire vos données
|
||||
|
||||
pt: &pt
|
||||
reply_to: Responder a
|
||||
partially_completed: Parcialmente concluído
|
||||
pending_by_me: Pendente por mim
|
||||
add: Adicionar
|
||||
@@ -3490,6 +3511,10 @@ pt: &pt
|
||||
click_here_to_learn_more_about_user_roles_and_permissions_html: '<a href="https://www.docuseal.com/resources/manage-users-and-roles" class="link" rel="noopener noreferrer nofollow" target="_blank">Clique aqui</a> para saber mais sobre os papéis e permissões dos usuários.'
|
||||
count_10_signature_request_emails_sent_this_month_upgrade_to_pro_to_send_unlimited_signature_request_email: '%{count} / 10 e-mails de solicitação de assinatura enviados este mês. Faça upgrade para Pro para enviar solicitações de assinatura ilimitadas.'
|
||||
test_mode_emails_limit_will_be_reset_within_24_hours: O limite de e-mails no modo de teste será redefinido em 24 horas.
|
||||
on_a_scale_of_1_to_10_how_satisfied_are_you_with_the_docuseal_product_: 'Em uma escala de 1 a 10, quão satisfeito você está com o produto DocuSeal?'
|
||||
tell_us_more_about_your_experience: Conte-nos mais sobre sua experiência
|
||||
extremely_dissatisfied: Extremamente insatisfeito
|
||||
extremely_satisfied: Extremamente satisfeito
|
||||
submission_event_names:
|
||||
send_email_to_html: '<b>E-mail enviado</b> para %{submitter_name}'
|
||||
send_reminder_email_to_html: '<b>E-mail de lembrete enviado</b> para %{submitter_name}'
|
||||
@@ -3528,6 +3553,7 @@ pt: &pt
|
||||
read: Ler seus dados
|
||||
|
||||
de: &de
|
||||
reply_to: Antworten auf
|
||||
partially_completed: Teilweise abgeschlossen
|
||||
pending_by_me: Ausstehend von mir
|
||||
add: Hinzufügen
|
||||
@@ -4192,6 +4218,10 @@ de: &de
|
||||
click_here_to_learn_more_about_user_roles_and_permissions_html: '<a href="https://www.docuseal.com/resources/manage-users-and-roles" class="link" rel="noopener noreferrer nofollow" target="_blank">Klicken Sie hier</a>, um mehr über Benutzerrollen und -berechtigungen zu erfahren.'
|
||||
count_10_signature_request_emails_sent_this_month_upgrade_to_pro_to_send_unlimited_signature_request_email: '%{count} / 10 Signaturanfrage-E-Mails wurden diesen Monat gesendet. Upgraden Sie zu Pro, um unbegrenzte Signaturanfragen zu senden.'
|
||||
test_mode_emails_limit_will_be_reset_within_24_hours: Das Limit für E-Mails im Testmodus wird innerhalb von 24 Stunden zurückgesetzt.
|
||||
on_a_scale_of_1_to_10_how_satisfied_are_you_with_the_docuseal_product_: 'Auf einer Skala von 1 bis 10, wie zufrieden sind Sie mit dem DocuSeal-Produkt?'
|
||||
tell_us_more_about_your_experience: Erzählen Sie uns mehr über Ihre Erfahrung
|
||||
extremely_dissatisfied: Extrem unzufrieden
|
||||
extremely_satisfied: Extrem zufrieden
|
||||
submission_event_names:
|
||||
send_email_to_html: '<b>E-Mail gesendet</b> an %{submitter_name}'
|
||||
send_reminder_email_to_html: '<b>Erinnerungs-E-Mail gesendet</b> an %{submitter_name}'
|
||||
|
||||
@@ -31,7 +31,8 @@ module Submissions
|
||||
next if uuid.blank?
|
||||
next if submitter_attrs.slice('email', 'phone', 'name').compact_blank.blank?
|
||||
|
||||
submission.template_submitters << template.submitters.find { |e| e['uuid'] == uuid }
|
||||
template_submitter = template.submitters.find { |e| e['uuid'] == uuid }
|
||||
submission.template_submitters << template_submitter.except('optional_invite_by_uuid', 'invite_by_uuid')
|
||||
|
||||
is_order_sent = submitters_order == 'random' || index.zero?
|
||||
|
||||
@@ -54,11 +55,17 @@ module Submissions
|
||||
# rubocop:enable Metrics/BlockLength
|
||||
|
||||
def maybe_add_invite_submitters(submission, template)
|
||||
template.submitters.each do |item|
|
||||
template.submitters.each_with_index do |item, index|
|
||||
next if item['invite_by_uuid'].blank? && item['optional_invite_by_uuid'].blank?
|
||||
next if submission.template_submitters.any? { |e| e['uuid'] == item['uuid'] }
|
||||
|
||||
submission.template_submitters << item
|
||||
if index.zero?
|
||||
submission.template_submitters.insert(1, item)
|
||||
elsif submission.template_submitters.size > index
|
||||
submission.template_submitters.insert(index, item)
|
||||
else
|
||||
submission.template_submitters << item
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -54,8 +54,8 @@ module Submitters
|
||||
submitter.ip = request.remote_ip
|
||||
submitter.ua = request.user_agent
|
||||
submitter.values = merge_default_values(submitter)
|
||||
submitter.values = merge_formula_values(submitter)
|
||||
submitter.values = maybe_remove_condition_values(submitter)
|
||||
submitter.values = merge_formula_values(submitter)
|
||||
submitter.values = submitter.values.transform_values do |v|
|
||||
v == '{{date}}' ? Time.current.in_time_zone(submitter.account.timezone).to_date.to_s : v
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user