optional invite
This commit is contained in:
+1
-1
@@ -69,7 +69,7 @@ RSpec/MultipleMemoizedHelpers:
|
|||||||
Max: 9
|
Max: 9
|
||||||
|
|
||||||
Metrics/BlockNesting:
|
Metrics/BlockNesting:
|
||||||
Max: 4
|
Max: 5
|
||||||
|
|
||||||
Rails/I18nLocaleTexts:
|
Rails/I18nLocaleTexts:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ module Api
|
|||||||
:name,
|
:name,
|
||||||
:external_id,
|
:external_id,
|
||||||
{
|
{
|
||||||
submitters: [%i[name uuid is_requester invite_by_uuid linked_to_uuid email]],
|
submitters: [%i[name uuid is_requester invite_by_uuid optional_invite_by_uuid linked_to_uuid email]],
|
||||||
fields: [[:uuid, :submitter_uuid, :name, :type,
|
fields: [[:uuid, :submitter_uuid, :name, :type,
|
||||||
:required, :readonly, :default_value,
|
:required, :readonly, :default_value,
|
||||||
:title, :description,
|
:title, :description,
|
||||||
|
|||||||
@@ -9,13 +9,15 @@ class SubmitFormInviteController < ApplicationController
|
|||||||
|
|
||||||
return head :unprocessable_entity unless can_invite?(submitter)
|
return head :unprocessable_entity unless can_invite?(submitter)
|
||||||
|
|
||||||
invite_submitters = filter_invite_submitters(submitter)
|
invite_submitters = filter_invite_submitters(submitter, 'invite_by_uuid')
|
||||||
|
optional_invite_submitters = filter_invite_submitters(submitter, 'optional_invite_by_uuid')
|
||||||
|
|
||||||
ApplicationRecord.transaction do
|
ApplicationRecord.transaction do
|
||||||
invite_submitters.each do |item|
|
(invite_submitters + optional_invite_submitters).each do |item|
|
||||||
attrs = submitters_attributes.find { |e| e[:uuid] == item['uuid'] }
|
attrs = submitters_attributes.find { |e| e[:uuid] == item['uuid'] }
|
||||||
|
|
||||||
next unless attrs
|
next unless attrs
|
||||||
|
next if attrs[:email].blank?
|
||||||
|
|
||||||
submitter.submission.submitters.create!(**attrs, account_id: submitter.account_id)
|
submitter.submission.submitters.create!(**attrs, account_id: submitter.account_id)
|
||||||
|
|
||||||
@@ -46,9 +48,9 @@ class SubmitFormInviteController < ApplicationController
|
|||||||
!submitter.submission.template.archived_at?
|
!submitter.submission.template.archived_at?
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_invite_submitters(submitter)
|
def filter_invite_submitters(submitter, key = 'invite_by_uuid')
|
||||||
(submitter.submission.template_submitters || submitter.submission.template.submitters).select do |s|
|
(submitter.submission.template_submitters || submitter.submission.template.submitters).select do |s|
|
||||||
s['invite_by_uuid'] == submitter.uuid && submitter.submission.submitters.none? { |e| e.uuid == s['uuid'] }
|
s[key] == submitter.uuid && submitter.submission.submitters.none? { |e| e.uuid == s['uuid'] }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ class TemplatesController < ApplicationController
|
|||||||
params.require(:template).permit(
|
params.require(:template).permit(
|
||||||
:name,
|
:name,
|
||||||
{ schema: [[:attachment_uuid, :name, { conditions: [%i[field_uuid value action operation]] }]],
|
{ schema: [[:attachment_uuid, :name, { conditions: [%i[field_uuid value action operation]] }]],
|
||||||
submitters: [%i[name uuid is_requester linked_to_uuid invite_by_uuid email]],
|
submitters: [%i[name uuid is_requester linked_to_uuid invite_by_uuid optional_invite_by_uuid email]],
|
||||||
fields: [[:uuid, :submitter_uuid, :name, :type,
|
fields: [[:uuid, :submitter_uuid, :name, :type,
|
||||||
:required, :readonly, :default_value,
|
:required, :readonly, :default_value,
|
||||||
:title, :description,
|
:title, :description,
|
||||||
|
|||||||
@@ -17,38 +17,47 @@ class TemplatesRecipientsController < ApplicationController
|
|||||||
private
|
private
|
||||||
|
|
||||||
def submitters_params
|
def submitters_params
|
||||||
params.require(:template).permit(
|
permit_params = { submitters: [%i[name uuid is_requester optional_invite_by_uuid
|
||||||
submitters: [%i[name uuid is_requester invite_by_uuid linked_to_uuid email option]]
|
invite_by_uuid linked_to_uuid email option]] }
|
||||||
).fetch(:submitters, {}).values.filter_map do |s|
|
|
||||||
|
params.require(:template).permit(permit_params).fetch(:submitters, {}).values.filter_map do |s|
|
||||||
next if s[:uuid].blank?
|
next if s[:uuid].blank?
|
||||||
|
|
||||||
if s[:is_requester] == '1' && s[:invite_by_uuid].blank?
|
if s[:is_requester] == '1' && s[:invite_by_uuid].blank? && s[:optional_invite_by_uuid].blank?
|
||||||
s[:is_requester] = true
|
s[:is_requester] = true
|
||||||
else
|
else
|
||||||
s.delete(:is_requester)
|
s.delete(:is_requester)
|
||||||
end
|
end
|
||||||
|
|
||||||
s.delete(:invite_by_uuid) if s[:invite_by_uuid].blank?
|
s.delete(:invite_by_uuid) if s[:invite_by_uuid].blank?
|
||||||
|
s.delete(:optional_invite_by_uuid) if s[:optional_invite_by_uuid].blank?
|
||||||
|
|
||||||
option = s.delete(:option)
|
normalize_option_value(s)
|
||||||
|
|
||||||
if option.present?
|
|
||||||
case option
|
|
||||||
when 'is_requester'
|
|
||||||
s[:is_requester] = true
|
|
||||||
when 'not_set'
|
|
||||||
s.delete(:is_requester)
|
|
||||||
s.delete(:email)
|
|
||||||
s.delete(:linked_to_uuid)
|
|
||||||
s.delete(:invite_by_uuid)
|
|
||||||
when /\Alinked_to_(.*)\z/
|
|
||||||
s[:linked_to_uuid] = ::Regexp.last_match(-1)
|
|
||||||
when /\Ainvite_by_(.*)\z/
|
|
||||||
s[:invite_by_uuid] = ::Regexp.last_match(-1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
s
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def normalize_option_value(attrs)
|
||||||
|
option = attrs.delete(:option)
|
||||||
|
|
||||||
|
if option.present?
|
||||||
|
case option
|
||||||
|
when 'is_requester'
|
||||||
|
attrs[:is_requester] = true
|
||||||
|
when 'not_set'
|
||||||
|
attrs.delete(:is_requester)
|
||||||
|
attrs.delete(:email)
|
||||||
|
attrs.delete(:linked_to_uuid)
|
||||||
|
attrs.delete(:invite_by_uuid)
|
||||||
|
attrs.delete(:optional_invite_by_uuid)
|
||||||
|
when /\Alinked_to_(.*)\z/
|
||||||
|
attrs[:linked_to_uuid] = ::Regexp.last_match(-1)
|
||||||
|
when /\Aoptional_invite_by_(.*)\z/
|
||||||
|
attrs[:optional_invite_by_uuid] = ::Regexp.last_match(-1)
|
||||||
|
when /\Ainvite_by_(.*)\z/
|
||||||
|
attrs[:invite_by_uuid] = ::Regexp.last_match(-1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
attrs
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import LinkedInput from './elements/linked_input'
|
|||||||
import CheckboxGroup from './elements/checkbox_group'
|
import CheckboxGroup from './elements/checkbox_group'
|
||||||
import MaskedInput from './elements/masked_input'
|
import MaskedInput from './elements/masked_input'
|
||||||
import SetDateButton from './elements/set_date_button'
|
import SetDateButton from './elements/set_date_button'
|
||||||
|
import IndeterminateCheckbox from './elements/indeterminate_checkbox'
|
||||||
|
|
||||||
import * as TurboInstantClick from './lib/turbo_instant_click'
|
import * as TurboInstantClick from './lib/turbo_instant_click'
|
||||||
|
|
||||||
@@ -99,6 +100,7 @@ safeRegisterElement('linked-input', LinkedInput)
|
|||||||
safeRegisterElement('checkbox-group', CheckboxGroup)
|
safeRegisterElement('checkbox-group', CheckboxGroup)
|
||||||
safeRegisterElement('masked-input', MaskedInput)
|
safeRegisterElement('masked-input', MaskedInput)
|
||||||
safeRegisterElement('set-date-button', SetDateButton)
|
safeRegisterElement('set-date-button', SetDateButton)
|
||||||
|
safeRegisterElement('indeterminate-checkbox', IndeterminateCheckbox)
|
||||||
|
|
||||||
safeRegisterElement('template-builder', class extends HTMLElement {
|
safeRegisterElement('template-builder', class extends HTMLElement {
|
||||||
connectedCallback () {
|
connectedCallback () {
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
export default class extends HTMLElement {
|
||||||
|
connectedCallback () {
|
||||||
|
if (this.dataset.indeterminate === 'true') {
|
||||||
|
this.checkbox.indeterminate = true
|
||||||
|
this.checkbox.readOnly = true
|
||||||
|
}
|
||||||
|
|
||||||
|
this.checkbox.addEventListener('click', () => {
|
||||||
|
this.checkbox.setAttribute('name', this.dataset.name)
|
||||||
|
|
||||||
|
if (this.showIndeterminateEl) {
|
||||||
|
this.showIndeterminateEl.classList.add('hidden')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.checkbox.readOnly) {
|
||||||
|
this.checkbox.checked = this.checkbox.readOnly = false
|
||||||
|
} else if (!this.checkbox.checked) {
|
||||||
|
if (this.showIndeterminateEl) {
|
||||||
|
this.showIndeterminateEl.classList.remove('hidden')
|
||||||
|
}
|
||||||
|
|
||||||
|
this.checkbox.setAttribute('name', this.dataset.indeterminateName)
|
||||||
|
this.checkbox.checked = this.checkbox.readOnly = this.checkbox.indeterminate = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
get checkbox () {
|
||||||
|
return this.querySelector('input[type="checkbox"]')
|
||||||
|
}
|
||||||
|
|
||||||
|
get showIndeterminateEl () {
|
||||||
|
return document.getElementById(this.dataset.showIndeterminateId)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ safeRegisterElement('submission-form', class extends HTMLElement {
|
|||||||
this.app = createApp(Form, {
|
this.app = createApp(Form, {
|
||||||
submitter: JSON.parse(this.dataset.submitter),
|
submitter: JSON.parse(this.dataset.submitter),
|
||||||
inviteSubmitters: JSON.parse(this.dataset.inviteSubmitters),
|
inviteSubmitters: JSON.parse(this.dataset.inviteSubmitters),
|
||||||
|
optionalInviteSubmitters: JSON.parse(this.dataset.optionalInviteSubmitters),
|
||||||
schema: JSON.parse(this.dataset.schema),
|
schema: JSON.parse(this.dataset.schema),
|
||||||
canSendEmail: this.dataset.canSendEmail === 'true',
|
canSendEmail: this.dataset.canSendEmail === 'true',
|
||||||
previousSignatureValue: this.dataset.previousSignatureValue,
|
previousSignatureValue: this.dataset.previousSignatureValue,
|
||||||
|
|||||||
@@ -498,6 +498,7 @@
|
|||||||
<InviteForm
|
<InviteForm
|
||||||
v-else-if="isInvite"
|
v-else-if="isInvite"
|
||||||
:submitters="inviteSubmitters"
|
:submitters="inviteSubmitters"
|
||||||
|
:optional-submitters="optionalInviteSubmitters"
|
||||||
:submitter-slug="submitterSlug"
|
:submitter-slug="submitterSlug"
|
||||||
:authenticity-token="authenticityToken"
|
:authenticity-token="authenticityToken"
|
||||||
:url="baseUrl + submitPath + '/invite'"
|
:url="baseUrl + submitPath + '/invite'"
|
||||||
@@ -627,6 +628,11 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: () => []
|
default: () => []
|
||||||
},
|
},
|
||||||
|
optionalInviteSubmitters: {
|
||||||
|
type: Array,
|
||||||
|
required: false,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
withSignatureId: {
|
withSignatureId: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -1320,7 +1326,7 @@ export default {
|
|||||||
const formData = new FormData(this.$refs.form)
|
const formData = new FormData(this.$refs.form)
|
||||||
const isLastStep = (submitStep === this.stepFields.length - 1) || forceComplete
|
const isLastStep = (submitStep === this.stepFields.length - 1) || forceComplete
|
||||||
|
|
||||||
if (isLastStep && !emptyRequiredField && !this.inviteSubmitters.length) {
|
if (isLastStep && !emptyRequiredField && !this.inviteSubmitters.length && !this.optionalInviteSubmitters.length) {
|
||||||
formData.append('completed', 'true')
|
formData.append('completed', 'true')
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1359,7 +1365,7 @@ export default {
|
|||||||
if (emptyRequiredField === nextStep) {
|
if (emptyRequiredField === nextStep) {
|
||||||
this.showFillAllRequiredFields = true
|
this.showFillAllRequiredFields = true
|
||||||
}
|
}
|
||||||
} else if (this.inviteSubmitters.length) {
|
} else if (this.inviteSubmitters.length || this.optionalInviteSubmitters.length) {
|
||||||
this.isInvite = true
|
this.isInvite = true
|
||||||
} else {
|
} else {
|
||||||
this.performComplete(response)
|
this.performComplete(response)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
:value="authenticityToken"
|
:value="authenticityToken"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(submitter, index) in submitters"
|
v-for="(submitter, index) in [...submitters, ...optionalSubmitters]"
|
||||||
:key="submitter.uuid"
|
:key="submitter.uuid"
|
||||||
:class="{ 'mt-4': index !== 0 }"
|
:class="{ 'mt-4': index !== 0 }"
|
||||||
>
|
>
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
dir="auto"
|
dir="auto"
|
||||||
class="label text-2xl"
|
class="label text-2xl"
|
||||||
>
|
>
|
||||||
{{ t('invite') }} {{ submitter.name }}
|
{{ t('invite') }} {{ submitter.name }} <template v-if="!submitters.includes(submitter)">({{ t('optional') }})</template>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
:id="submitter.uuid"
|
:id="submitter.uuid"
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
class="base-input !text-2xl w-full"
|
class="base-input !text-2xl w-full"
|
||||||
:placeholder="t('email')"
|
:placeholder="t('email')"
|
||||||
type="email"
|
type="email"
|
||||||
required
|
:required="submitters.includes(submitter)"
|
||||||
autofocus="true"
|
autofocus="true"
|
||||||
name="submission[submitters][][email]"
|
name="submission[submitters][][email]"
|
||||||
>
|
>
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
class="mr-1 animate-spin"
|
class="mr-1 animate-spin"
|
||||||
/>
|
/>
|
||||||
<span>
|
<span>
|
||||||
{{ t('submit') }}
|
{{ t('complete') }}
|
||||||
</span><span
|
</span><span
|
||||||
v-if="isSubmitting"
|
v-if="isSubmitting"
|
||||||
class="w-6 flex justify-start mr-1"
|
class="w-6 flex justify-start mr-1"
|
||||||
@@ -78,6 +78,11 @@ export default {
|
|||||||
type: Array,
|
type: Array,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
optionalSubmitters: {
|
||||||
|
type: Array,
|
||||||
|
required: false,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
url: {
|
url: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<%= form_for '', url: template_submissions_path(template), html: { class: 'space-y-4', autocomplete: 'off' }, data: { turbo_frame: :_top } do |f| %>
|
<%= form_for '', url: template_submissions_path(template), html: { class: 'space-y-4', autocomplete: 'off' }, data: { turbo_frame: :_top } do |f| %>
|
||||||
<% submitters = template.submitters.reject { |e| e['invite_by_uuid'].present? } %>
|
<% submitters = template.submitters.reject { |e| e['invite_by_uuid'].present? || e['optional_invite_by_uuid'].present? } %>
|
||||||
<dynamic-list class="space-y-4">
|
<dynamic-list class="space-y-4">
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<div class="card card-compact bg-base-300/40" data-targets="dynamic-list.items">
|
<div class="card card-compact bg-base-300/40" data-targets="dynamic-list.items">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<%= form_for '', url: template_submissions_path(template), html: { class: 'space-y-4', autocomplete: 'off' }, data: { turbo_frame: :_top } do |f| %>
|
<%= form_for '', url: template_submissions_path(template), html: { class: 'space-y-4', autocomplete: 'off' }, data: { turbo_frame: :_top } do |f| %>
|
||||||
<% submitters = template.submitters.reject { |e| e['invite_by_uuid'].present? } %>
|
<% submitters = template.submitters.reject { |e| e['invite_by_uuid'].present? || e['optional_invite_by_uuid'].present? } %>
|
||||||
<% if submitters.size == 1 %>
|
<% if submitters.size == 1 %>
|
||||||
<submitter-item class="form-control">
|
<submitter-item class="form-control">
|
||||||
<emails-textarea data-bulk-enabled="<%= Docuseal.demo? || !Docuseal.multitenant? || can?(:manage, :bulk_send) %>" data-limit="<%= Docuseal.multitenant? ? (can?(:manage, :bulk_send) ? 40 : 1) : nil %>">
|
<emails-textarea data-bulk-enabled="<%= Docuseal.demo? || !Docuseal.multitenant? || can?(:manage, :bulk_send) %>" data-limit="<%= Docuseal.multitenant? ? (can?(:manage, :bulk_send) ? 40 : 1) : nil %>">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<%= form_for '', url: template_submissions_path(template), html: { class: 'space-y-4', autocomplete: 'off' }, data: { turbo_frame: :_top } do |f| %>
|
<%= form_for '', url: template_submissions_path(template), html: { class: 'space-y-4', autocomplete: 'off' }, data: { turbo_frame: :_top } do |f| %>
|
||||||
<% submitters = template.submitters.reject { |e| e['invite_by_uuid'].present? } %>
|
<% submitters = template.submitters.reject { |e| e['invite_by_uuid'].present? || e['optional_invite_by_uuid'].present? } %>
|
||||||
<dynamic-list class="space-y-4">
|
<dynamic-list class="space-y-4">
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<div class="card card-compact bg-base-300/40" data-targets="dynamic-list.items">
|
<div class="card card-compact bg-base-300/40" data-targets="dynamic-list.items">
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<% data_attachments = attachments_index.values.select { |e| e.record_id == submitter.id }.to_json(only: %i[uuid created_at], methods: %i[url filename content_type]) %>
|
<% data_attachments = attachments_index.values.select { |e| e.record_id == submitter.id }.to_json(only: %i[uuid created_at], methods: %i[url filename content_type]) %>
|
||||||
<% data_fields = (submitter.submission.template_fields || submitter.submission.template.fields).select { |f| f['submitter_uuid'] == submitter.uuid }.to_json %>
|
<% data_fields = (submitter.submission.template_fields || submitter.submission.template.fields).select { |f| f['submitter_uuid'] == submitter.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 %>
|
<% 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 %>
|
||||||
<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['completed_redirect_url'] %>" data-completed-message="<%= (configs[:completed_message]&.compact_blank.presence || submitter.submission.template.preferences['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-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>
|
<% 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['completed_redirect_url'] %>" data-completed-message="<%= (configs[:completed_message]&.compact_blank.presence || submitter.submission.template.preferences['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>
|
||||||
|
|||||||
@@ -223,16 +223,16 @@
|
|||||||
<div class="space-y-3 divide-y">
|
<div class="space-y-3 divide-y">
|
||||||
<% @template.submitters.each_with_index do |submitter, index| %>
|
<% @template.submitters.each_with_index do |submitter, index| %>
|
||||||
<div class="pt-3">
|
<div class="pt-3">
|
||||||
<%= f.fields_for :submitters, item = Struct.new(:name, :uuid, :is_requester, :email, :invite_by_uuid, :linked_to_uuid, :option).new(*submitter.values_at('name', 'uuid', 'is_requester', 'email', 'invite_by_uuid', 'linked_to_uuid')), index: do |ff| %>
|
<%= f.fields_for :submitters, item = Struct.new(:name, :uuid, :is_requester, :email, :invite_by_uuid, :optional_invite_by_uuid, :linked_to_uuid, :option).new(*submitter.values_at('name', 'uuid', 'is_requester', 'email', 'invite_by_uuid', 'optional_invite_by_uuid', 'linked_to_uuid')), index: do |ff| %>
|
||||||
<% item.option = item.is_requester.present? ? 'is_requester' : (item.email.present? ? 'email' : (item.linked_to_uuid.present? ? "linked_to_#{item.linked_to_uuid}" : (item.invite_by_uuid.present? ? "invite_by_#{item.invite_by_uuid}" : ''))) %>
|
<% item.option = item.is_requester.present? ? 'is_requester' : (item.email.present? ? 'email' : (item.linked_to_uuid.present? ? "linked_to_#{item.linked_to_uuid}" : (item.invite_by_uuid.present? ? "invite_by_#{item.invite_by_uuid}" : (item.optional_invite_by_uuid.present? ? "optional_invite_by_#{item.optional_invite_by_uuid}" : '')))) %>
|
||||||
<%= ff.hidden_field :uuid %>
|
<%= ff.hidden_field :uuid %>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= ff.text_field :name, class: 'w-full outline-none border-transparent focus:border-transparent focus:ring-0 bg-base-100 px-1 peer mb-2', autocomplete: 'off', placeholder: "#{index + 1}#{(index + 1).ordinal} Party", required: true %>
|
<%= ff.text_field :name, class: 'w-full outline-none border-transparent focus:border-transparent focus:ring-0 bg-base-100 px-1 peer mb-2', autocomplete: 'off', placeholder: "#{index + 1}#{(index + 1).ordinal} Party", required: true %>
|
||||||
<% if @template.submitters.size == 2 %>
|
<% if @template.submitters.size == 2 %>
|
||||||
<%= ff.email_field :email, class: 'base-input', autocomplete: 'off', placeholder: t('default_email'), disabled: ff.object.is_requester || ff.object.invite_by_uuid.present?, id: field_uuid = SecureRandom.uuid %>
|
<%= ff.email_field :email, class: 'base-input', autocomplete: 'off', placeholder: t('default_email'), disabled: ff.object.is_requester || ff.object.invite_by_uuid.present? || ff.object.optional_invite_by_uuid.present?, id: field_uuid = SecureRandom.uuid %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<toggle-attribute data-target-id="<%= email_field_uuid = SecureRandom.uuid %>" data-class-name="hidden" data-value="email">
|
<toggle-attribute data-target-id="<%= email_field_uuid = SecureRandom.uuid %>" data-class-name="hidden" data-value="email">
|
||||||
<%= ff.select :option, [[t('not_specified'), 'not_set'], [t('submission_requester'), 'is_requester'], [t('specified_email'), 'email'], *(@template.submitters - [submitter]).map { |e| [t('invite_by_name', name: e['name']), "invite_by_#{e['uuid']}"] }, *(@template.submitters - [submitter]).map { |e| [t('same_as_name', name: e['name']), "linked_to_#{e['uuid']}"] }], {}, class: 'base-select mb-3' %>
|
<%= ff.select :option, [[t('not_specified'), 'not_set'], [t('submission_requester'), 'is_requester'], [t('specified_email'), 'email'], *(@template.submitters - [submitter]).flat_map { |e| [[t('invite_by_name', name: e['name']), "invite_by_#{e['uuid']}"], [t('invite_by_name', name: e['name']) + " (#{t(:optional).capitalize})", "optional_invite_by_#{e['uuid']}"]] }, *(@template.submitters - [submitter]).map { |e| [t('same_as_name', name: e['name']), "linked_to_#{e['uuid']}"] }], {}, class: 'base-select mb-3' %>
|
||||||
</toggle-attribute>
|
</toggle-attribute>
|
||||||
<%= ff.email_field :email, class: "base-input #{'hidden' if item.option != 'email'}", autocomplete: 'off', placeholder: t('default_email'), id: email_field_uuid %>
|
<%= ff.email_field :email, class: "base-input #{'hidden' if item.option != 'email'}", autocomplete: 'off', placeholder: t('default_email'), id: email_field_uuid %>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -250,10 +250,12 @@
|
|||||||
<% if index == 1 %>
|
<% if index == 1 %>
|
||||||
<label class="flex items-center space-x-2 cursor-pointer">
|
<label class="flex items-center space-x-2 cursor-pointer">
|
||||||
<toggle-attribute data-target-id="<%= field_uuid %>" class="flex" data-attribute="disabled">
|
<toggle-attribute data-target-id="<%= field_uuid %>" class="flex" data-attribute="disabled">
|
||||||
<%= ff.check_box :invite_by_uuid, { class: 'base-checkbox' }, @template.submitters.first['uuid'], '' %>
|
<indeterminate-checkbox data-indeterminate="<%= ff.object.optional_invite_by_uuid.present? %>" data-show-indeterminate-id="invite_optional" data-name="<%= ff.field_name(:invite_by_uuid) %>" data-indeterminate-name="<%= ff.field_name(:optional_invite_by_uuid) %>" class="flex">
|
||||||
|
<%= ff.check_box ff.object.optional_invite_by_uuid.present? ? :optional_invite_by_uuid : :invite_by_uuid, { class: 'base-checkbox' }, @template.submitters.first['uuid'], '' %>
|
||||||
|
</indeterminate-checkbox>
|
||||||
</toggle-attribute>
|
</toggle-attribute>
|
||||||
<span class="select-none">
|
<span class="select-none">
|
||||||
<%= t('invite_by_name', name: @template.submitters.first['name']) %>
|
<%= t('invite_by_name', name: @template.submitters.first['name']) %> <span id="invite_optional" class="<%= 'hidden' if ff.object.optional_invite_by_uuid.blank? %>">(<%= t(:optional).capitalize %>)</span>
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ module Submissions
|
|||||||
|
|
||||||
def maybe_add_invite_submitters(submission, template)
|
def maybe_add_invite_submitters(submission, template)
|
||||||
template.submitters.each do |item|
|
template.submitters.each do |item|
|
||||||
next if item['invite_by_uuid'].blank? ||
|
next if item['invite_by_uuid'].blank? && item['optional_invite_by_uuid'].blank?
|
||||||
submission.template_submitters.any? { |e| e['uuid'] == item['uuid'] }
|
next if submission.template_submitters.any? { |e| e['uuid'] == item['uuid'] }
|
||||||
|
|
||||||
submission.template_submitters << item
|
submission.template_submitters << item
|
||||||
end
|
end
|
||||||
|
|||||||
+2
-2
@@ -26,8 +26,8 @@ module Templates
|
|||||||
|
|
||||||
def filter_undefined_submitters(template)
|
def filter_undefined_submitters(template)
|
||||||
template.submitters.to_a.select do |item|
|
template.submitters.to_a.select do |item|
|
||||||
item['invite_by_uuid'].blank? && item['linked_to_uuid'].blank? &&
|
item['invite_by_uuid'].blank? && item['optional_invite_by_uuid'].blank? &&
|
||||||
item['is_requester'].blank? && item['email'].blank?
|
item['linked_to_uuid'].blank? && item['is_requester'].blank? && item['email'].blank?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user