prefillable fields
This commit is contained in:
@@ -109,7 +109,7 @@ module Api
|
||||
submitters: [%i[name uuid is_requester invite_by_uuid optional_invite_by_uuid linked_to_uuid email]],
|
||||
fields: [[:uuid, :submitter_uuid, :name, :type,
|
||||
:required, :readonly, :default_value,
|
||||
:title, :description,
|
||||
:title, :description, :prefillable,
|
||||
{ preferences: {},
|
||||
conditions: [%i[field_uuid value action operation]],
|
||||
options: [%i[value uuid]],
|
||||
|
||||
@@ -32,10 +32,7 @@ class SubmissionsController < ApplicationController
|
||||
def create
|
||||
save_template_message(@template, params) if params[:save_message] == '1'
|
||||
|
||||
if params[:is_custom_message] != '1'
|
||||
params.delete(:subject)
|
||||
params.delete(:body)
|
||||
end
|
||||
[params.delete(:subject), params.delete(:body)] if params[:is_custom_message] != '1'
|
||||
|
||||
submissions =
|
||||
if params[:emails].present?
|
||||
@@ -46,11 +43,16 @@ class SubmissionsController < ApplicationController
|
||||
emails: params[:emails],
|
||||
params: params.merge('send_completed_email' => true))
|
||||
else
|
||||
submissions_attrs = submissions_params[:submission].to_h.values
|
||||
|
||||
submissions_attrs, =
|
||||
Submissions::NormalizeParamUtils.normalize_submissions_params!(submissions_attrs, @template)
|
||||
|
||||
Submissions.create_from_submitters(template: @template,
|
||||
user: current_user,
|
||||
source: :invite,
|
||||
submitters_order: params[:preserve_order] == '1' ? 'preserved' : 'random',
|
||||
submissions_attrs: submissions_params[:submission].to_h.values,
|
||||
submissions_attrs:,
|
||||
params: params.merge('send_completed_email' => true))
|
||||
end
|
||||
|
||||
@@ -62,9 +64,8 @@ class SubmissionsController < ApplicationController
|
||||
|
||||
redirect_to template_path(@template), notice: I18n.t('new_recipients_have_been_added')
|
||||
rescue Submissions::CreateFromSubmitters::BaseError => e
|
||||
render turbo_stream: turbo_stream.replace(:submitters_error,
|
||||
partial: 'submissions/error',
|
||||
locals: { error: e.message }),
|
||||
render turbo_stream: turbo_stream.replace(:submitters_error, partial: 'submissions/error',
|
||||
locals: { error: e.message }),
|
||||
status: :unprocessable_entity
|
||||
end
|
||||
|
||||
@@ -95,7 +96,7 @@ class SubmissionsController < ApplicationController
|
||||
end
|
||||
|
||||
def submissions_params
|
||||
params.permit(submission: { submitters: [%i[uuid email phone name]] })
|
||||
params.permit(submission: { submitters: [:uuid, :email, :phone, :name, { values: {} }] })
|
||||
end
|
||||
|
||||
def load_template
|
||||
|
||||
@@ -120,7 +120,7 @@ class TemplatesController < ApplicationController
|
||||
submitters: [%i[name uuid is_requester linked_to_uuid invite_by_uuid optional_invite_by_uuid email]],
|
||||
fields: [[:uuid, :submitter_uuid, :name, :type,
|
||||
:required, :readonly, :default_value,
|
||||
:title, :description,
|
||||
:title, :description, :prefillable,
|
||||
{ preferences: {},
|
||||
conditions: [%i[field_uuid value action operation]],
|
||||
options: [%i[value uuid]],
|
||||
|
||||
@@ -27,7 +27,7 @@ class TemplatesPreferencesController < ApplicationController
|
||||
completed_redirect_url validate_unique_submitters
|
||||
require_all_submitters submitters_order require_phone_2fa
|
||||
default_expire_at_duration shared_link_2fa
|
||||
default_expire_at
|
||||
default_expire_at request_email_enabled
|
||||
completed_notification_email_subject completed_notification_email_body
|
||||
completed_notification_email_enabled completed_notification_email_attach_audit] +
|
||||
[completed_message: %i[title body],
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class TemplatesPrefillableFieldsController < ApplicationController
|
||||
PREFILLABLE_FIELD_TYPES = %w[text number cells date checkbox select radio phone].freeze
|
||||
|
||||
load_and_authorize_resource :template
|
||||
|
||||
def create
|
||||
authorize!(:update, @template)
|
||||
|
||||
field = @template.fields.find { |f| f['uuid'] == params[:field_uuid] }
|
||||
|
||||
if params[:prefillable] == 'false'
|
||||
field.delete('prefillable')
|
||||
field.delete('readonly')
|
||||
elsif params[:prefillable] == 'true'
|
||||
field['prefillable'] = true
|
||||
field['readonly'] = true
|
||||
end
|
||||
|
||||
@template.save!
|
||||
|
||||
render turbo_stream: turbo_stream.replace(:prefillable_fields_list, partial: 'list',
|
||||
locals: { template: @template })
|
||||
end
|
||||
end
|
||||
@@ -141,6 +141,7 @@
|
||||
:with-required="false"
|
||||
:with-areas="false"
|
||||
:with-signature-id="withSignatureId"
|
||||
:with-prefillable="withPrefillable"
|
||||
@click-formula="isShowFormulaModal = true"
|
||||
@click-font="isShowFontModal = true"
|
||||
@click-description="isShowDescriptionModal = true"
|
||||
@@ -353,6 +354,11 @@ export default {
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
withPrefillable: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
defaultSubmitters: {
|
||||
type: Array,
|
||||
required: false,
|
||||
|
||||
@@ -331,6 +331,7 @@
|
||||
:default-fields="[...defaultRequiredFields, ...defaultFields]"
|
||||
:allow-draw="!onlyDefinedFields || drawField"
|
||||
:with-signature-id="withSignatureId"
|
||||
:with-prefillable="withPrefillable"
|
||||
:data-document-uuid="document.uuid"
|
||||
:default-submitters="defaultSubmitters"
|
||||
:drag-field-placeholder="fieldsDragFieldRef.value || dragField"
|
||||
@@ -438,6 +439,7 @@
|
||||
:field-types="fieldTypes"
|
||||
:with-sticky-submitters="withStickySubmitters"
|
||||
:with-signature-id="withSignatureId"
|
||||
:with-prefillable="withPrefillable"
|
||||
:only-defined-fields="onlyDefinedFields"
|
||||
:editable="editable"
|
||||
:show-tour-start-form="showTourStartForm"
|
||||
@@ -543,7 +545,6 @@ export default {
|
||||
withPayment: this.withPayment,
|
||||
isPaymentConnected: this.isPaymentConnected,
|
||||
withFormula: this.withFormula,
|
||||
withSignatureId: this.withSignatureId,
|
||||
withConditions: this.withConditions,
|
||||
isInlineSize: this.isInlineSize,
|
||||
defaultDrawFieldType: this.defaultDrawFieldType,
|
||||
@@ -802,6 +803,13 @@ export default {
|
||||
language () {
|
||||
return this.locale.split('-')[0].toLowerCase()
|
||||
},
|
||||
withPrefillable () {
|
||||
if (this.template.fields) {
|
||||
return this.template.fields.some((f) => f.prefillable)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
},
|
||||
isInlineSize () {
|
||||
return CSS.supports('container-type: size')
|
||||
},
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
:areas="areasIndex[index]"
|
||||
:allow-draw="allowDraw"
|
||||
:with-signature-id="withSignatureId"
|
||||
:with-prefillable="withPrefillable"
|
||||
:is-drag="isDrag"
|
||||
:with-field-placeholder="withFieldPlaceholder"
|
||||
:default-fields="defaultFields"
|
||||
@@ -72,6 +73,11 @@ export default {
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
withPrefillable: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
drawFieldType: {
|
||||
type: String,
|
||||
required: false,
|
||||
|
||||
@@ -126,6 +126,7 @@
|
||||
:default-field="defaultField"
|
||||
:editable="editable"
|
||||
:with-signature-id="withSignatureId"
|
||||
:with-prefillable="withPrefillable"
|
||||
:background-color="dropdownBgColor"
|
||||
@click-formula="isShowFormulaModal = true"
|
||||
@click-font="isShowFontModal = true"
|
||||
@@ -308,6 +309,11 @@ export default {
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
withPrefillable: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
withOptions: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
|
||||
@@ -406,6 +406,21 @@
|
||||
<span class="label-text">{{ t('read_only') }}</span>
|
||||
</label>
|
||||
</li>
|
||||
<li
|
||||
v-if="withPrefillable && ['text', 'number', 'cells', 'date', 'checkbox', 'select', 'radio', 'phone'].includes(field['type'])"
|
||||
@click.stop
|
||||
>
|
||||
<label class="cursor-pointer py-1.5">
|
||||
<input
|
||||
v-model="field.prefillable"
|
||||
type="checkbox"
|
||||
:disabled="!editable || (defaultField && [true, false].includes(defaultField.prefillable))"
|
||||
class="toggle toggle-xs"
|
||||
@update:model-value="save"
|
||||
>
|
||||
<span class="label-text">{{ t('prefillable') }}</span>
|
||||
</label>
|
||||
</li>
|
||||
<hr
|
||||
v-if="field.type != 'stamp'"
|
||||
class="pb-0.5 mt-0.5"
|
||||
@@ -555,6 +570,11 @@ export default {
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
withPrefillable: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
withRequired: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
:type-index="fields.filter((f) => f.type === field.type).indexOf(field)"
|
||||
:editable="editable"
|
||||
:with-signature-id="withSignatureId"
|
||||
:with-prefillable="withPrefillable"
|
||||
:default-field="defaultFieldsIndex[field.name]"
|
||||
:draggable="editable"
|
||||
@dragstart="[fieldsDragFieldRef.value = field, removeDragOverlay($event), setDragPlaceholder($event)]"
|
||||
@@ -259,6 +260,11 @@ export default {
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
withPrefillable: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
template: {
|
||||
type: Object,
|
||||
required: true
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const en = {
|
||||
prefillable: 'Prefillable',
|
||||
signature_id: 'Signature ID',
|
||||
error_message: 'Error message',
|
||||
length: 'Length',
|
||||
@@ -173,6 +174,7 @@ const en = {
|
||||
}
|
||||
|
||||
const es = {
|
||||
prefillable: 'Rellenable',
|
||||
signature_id: 'ID de Firma',
|
||||
error_message: 'Mensaje de error',
|
||||
length: 'Longitud',
|
||||
@@ -347,6 +349,7 @@ const es = {
|
||||
}
|
||||
|
||||
const it = {
|
||||
prefillable: 'Precompilabile',
|
||||
signature_id: 'ID firma',
|
||||
error_message: 'Messaggio di errore',
|
||||
length: 'Lunghezza',
|
||||
@@ -521,6 +524,7 @@ const it = {
|
||||
}
|
||||
|
||||
const pt = {
|
||||
prefillable: 'Pré-preenchível',
|
||||
signature_id: 'ID da Assinatura',
|
||||
error_message: 'Mensagem de erro',
|
||||
length: 'Comprimento',
|
||||
@@ -695,6 +699,7 @@ const pt = {
|
||||
}
|
||||
|
||||
const fr = {
|
||||
prefillable: 'Pré-remplissable',
|
||||
signature_id: 'ID de signature',
|
||||
error_message: 'Message d\'erreur',
|
||||
length: 'Longueur',
|
||||
@@ -869,6 +874,7 @@ const fr = {
|
||||
}
|
||||
|
||||
const de = {
|
||||
prefillable: 'Vorausfüllbar',
|
||||
signature_id: 'Signatur-ID',
|
||||
error_message: 'Fehlermeldung',
|
||||
length: 'Länge',
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
:editable="editable"
|
||||
:with-field-placeholder="withFieldPlaceholder"
|
||||
:with-signature-id="withSignatureId"
|
||||
:with-prefillable="withPrefillable"
|
||||
:default-field="defaultFieldsIndex[item.field.name]"
|
||||
:default-submitters="defaultSubmitters"
|
||||
:max-page="totalPages - 1"
|
||||
@@ -84,6 +85,11 @@ export default {
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
withPrefillable: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
areas: {
|
||||
type: Array,
|
||||
required: false,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<% has_phone_field = false %>
|
||||
<%= 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? || e['optional_invite_by_uuid'].present? } %>
|
||||
<dynamic-list class="space-y-4">
|
||||
@@ -11,6 +12,7 @@
|
||||
</div>
|
||||
<div class="grid <%= 'md:grid-cols-2' if submitters.size > 1 %> gap-4">
|
||||
<% submitters.each_with_index do |item, index| %>
|
||||
<% prefillable_fields = local_assigns[:prefillable_fields].to_a.select { |f| f['submitter_uuid'] == item['uuid'] } %>
|
||||
<submitter-item class="form-control">
|
||||
<% if submitters.size > 1 %>
|
||||
<label class="label pt-0 pb-1">
|
||||
@@ -18,30 +20,62 @@
|
||||
</label>
|
||||
<% end %>
|
||||
<input type="hidden" name="submission[1][submitters][][uuid]" value="<%= item['uuid'] %>">
|
||||
<submitters-autocomplete data-field="name">
|
||||
<linked-input data-target-id="<%= "detailed_name_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||
<%= tag.input type: 'text', name: 'submission[1][submitters][][name]', autocomplete: 'off', class: 'base-input !h-10 w-full', placeholder: t('name'), required: index.zero? || template.preferences['require_all_submitters'], value: item['email'].present? ? current_account.submitters.accessible_by(current_ability).where.not(name: nil).order(id: :desc).find_by(email: item['email'])&.name : ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : ''), dir: 'auto', id: "detailed_name_#{item['uuid']}" %>
|
||||
</linked-input>
|
||||
</submitters-autocomplete>
|
||||
<div class="grid <%= 'md:grid-cols-2 gap-1' if submitters.size == 1 %>">
|
||||
<% if prefillable_fields.blank? %>
|
||||
<submitters-autocomplete data-field="name">
|
||||
<linked-input data-target-id="<%= "detailed_name_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||
<%= tag.input type: 'text', name: 'submission[1][submitters][][name]', autocomplete: 'off', class: 'base-input !h-10 w-full', placeholder: t('name'), required: index.zero? || template.preferences['require_all_submitters'], value: item['email'].present? ? current_account.submitters.accessible_by(current_ability).where.not(name: nil).order(id: :desc).find_by(email: item['email'])&.name : ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : ''), dir: 'auto', id: "detailed_name_#{item['uuid']}" %>
|
||||
</linked-input>
|
||||
</submitters-autocomplete>
|
||||
<div class="grid <%= 'md:grid-cols-2 gap-1' if submitters.size == 1 %>">
|
||||
<submitters-autocomplete data-field="email">
|
||||
<linked-input data-target-id="<%= "detailed_email_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||
<input type="email" multiple name="submission[1][submitters][][email]" autocomplete="off" class="base-input !h-10 mt-1.5 w-full" placeholder="<%= "#{t('email')} (#{t('optional')})" %>" value="<%= item['email'].presence || ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.email : '') %>" id="detailed_email_<%= item['uuid'] %>">
|
||||
</linked-input>
|
||||
</submitters-autocomplete>
|
||||
<% has_phone_field = true %>
|
||||
<submitters-autocomplete data-field="phone">
|
||||
<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\-]+$', oninvalid: "this.value ? this.setCustomValidity('#{t('use_international_format_1xxx_')}') : ''", oninput: "this.setCustomValidity('')", name: 'submission[1][submitters][][phone]', 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 %>
|
||||
</linked-input>
|
||||
</submitters-autocomplete>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if prefillable_fields.present? %>
|
||||
<submitters-autocomplete data-field="email">
|
||||
<linked-input data-target-id="<%= "detailed_email_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||
<input type="email" multiple name="submission[1][submitters][][email]" autocomplete="off" class="base-input !h-10 mt-1.5 w-full" placeholder="<%= "#{t('email')} (#{t('optional')})" %>" value="<%= item['email'].presence || ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.email : '') %>" id="detailed_email_<%= item['uuid'] %>">
|
||||
<input type="email" multiple name="submission[1][submitters][][email]" autocomplete="off" class="base-input !h-10 w-full" placeholder="<%= t('email') %>" value="<%= item['email'].presence || ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.email : '') %>" id="detailed_email_<%= item['uuid'] %>" required>
|
||||
</linked-input>
|
||||
</submitters-autocomplete>
|
||||
<submitters-autocomplete data-field="phone">
|
||||
<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\-]+$', oninvalid: "this.value ? this.setCustomValidity('#{t('use_international_format_1xxx_')}') : ''", oninput: "this.setCustomValidity('')", name: 'submission[1][submitters][][phone]', 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 %>
|
||||
</linked-input>
|
||||
</submitters-autocomplete>
|
||||
</div>
|
||||
<% if local_assigns[:require_phone_2fa] == true || prefillable_fields.any? { |f| f['type'] == 'phone' } %>
|
||||
<% has_phone_field = true %>
|
||||
<submitters-autocomplete data-field="phone">
|
||||
<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\-]+$', oninvalid: "this.value ? this.setCustomValidity('#{t('use_international_format_1xxx_')}') : ''", oninput: "this.setCustomValidity('')", name: 'submission[1][submitters][][phone]', autocomplete: 'off', class: 'base-input !h-10 mt-1.5 w-full', placeholder: t(:phone), id: "detailed_phone_#{item['uuid']}", required: true %>
|
||||
</linked-input>
|
||||
</submitters-autocomplete>
|
||||
<% end %>
|
||||
<% prefillable_fields.each do |field| %>
|
||||
<% 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">
|
||||
<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' %>
|
||||
</label>
|
||||
<% 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'] %>
|
||||
<% 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'] %>
|
||||
<% 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'] %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</submitter-item>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% if params[:selfsign].blank? %>
|
||||
<% if params[:selfsign].blank? && local_assigns[:prefillable_fields].blank? %>
|
||||
<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') %>
|
||||
<span><%= t('add_new') %></span>
|
||||
@@ -51,7 +85,9 @@
|
||||
<div>
|
||||
<%= render('submitters_order', f:, template:) if Accounts.can_send_emails?(current_account) %>
|
||||
<%= render 'send_email', f:, template: %>
|
||||
<%= render 'send_sms', f: %>
|
||||
<% if has_phone_field %>
|
||||
<%= render 'send_sms', f: %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.button button_title(title: t('add_recipients')), class: 'base-button' %>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<% can_send_emails = Accounts.can_send_emails?(current_account) %>
|
||||
<div class="flex justify-between items-center">
|
||||
<%= f.label :send_email, for: uuid = SecureRandom.uuid, class: 'flex items-center cursor-pointer' do %>
|
||||
<%= f.check_box :send_email, id: uuid, class: 'base-checkbox', disabled: !can_send_emails || local_assigns[:disable_email], checked: can_send_emails && !local_assigns.key?(:resend_email) && !local_assigns[:disable_email] %>
|
||||
<%= f.check_box :send_email, id: uuid, class: 'base-checkbox', disabled: !can_send_emails || local_assigns[:disable_email], checked: can_send_emails && !local_assigns.key?(:resend_email) && !local_assigns[:disable_email] && template&.preferences&.dig('request_email_enabled') != false %>
|
||||
<span class="label"><%= local_assigns[:resend_email] ? t('re_send_email') : t('send_email') %></span>
|
||||
<% end %>
|
||||
<div>
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<% require_phone_2fa = @template.preferences['require_phone_2fa'] == true %>
|
||||
<% prefillable_fields = @template.fields.select { |f| f['prefillable'] } %>
|
||||
<% only_detailed = require_phone_2fa || prefillable_fields.present? %>
|
||||
<%= render 'shared/turbo_modal_large', title: params[:selfsign] ? t('add_recipients') : t('add_new_recipients') do %>
|
||||
<% options = [require_phone_2fa ? nil : [t('via_email'), 'email'], require_phone_2fa ? 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">
|
||||
<div class="flex justify-center">
|
||||
<% options.each_with_index do |(label, value), index| %>
|
||||
<div>
|
||||
<%= radio_button_tag 'option', value, value == (require_phone_2fa ? 'detailed' : 'email'), class: 'peer hidden', data: { action: 'change:toggle-visible#trigger' } %>
|
||||
<%= radio_button_tag 'option', value, value == (only_detailed ? 'detailed' : 'email'), class: 'peer hidden', data: { action: 'change:toggle-visible#trigger' } %>
|
||||
<label for="option_<%= value %>" class="block bg-base-200 md:min-w-[112px] text-sm font-semibold whitespace-nowrap py-1.5 px-4 peer-checked:bg-base-300 <%= 'hidden sm:inline-block' if value == 'list' %> <%= 'rounded-l-3xl' if index.zero? %> <%= 'rounded-r-3xl sm:rounded-r-none' if value == 'detailed' %> <%= 'rounded-r-3xl' if index == options.size - 1 %>">
|
||||
<%= label %>
|
||||
</label>
|
||||
@@ -14,7 +16,7 @@
|
||||
</div>
|
||||
</toggle-visible>
|
||||
<div class="px-5 mb-5 mt-4">
|
||||
<% unless require_phone_2fa %>
|
||||
<% unless only_detailed %>
|
||||
<div id="email">
|
||||
<%= render 'email_form', template: @template %>
|
||||
</div>
|
||||
@@ -22,8 +24,8 @@
|
||||
<%= render 'phone_form', template: @template %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div id="detailed" class="<%= 'hidden' unless require_phone_2fa %>">
|
||||
<%= render 'detailed_form', template: @template, require_phone_2fa: %>
|
||||
<div id="detailed" class="<%= 'hidden' unless only_detailed %>">
|
||||
<%= render 'detailed_form', template: @template, require_phone_2fa:, prefillable_fields: %>
|
||||
</div>
|
||||
<div id="list" class="hidden">
|
||||
<%= render 'list_form', template: @template %>
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
<%= t('form_preferences') %>
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<%= render 'templates_prefillable_fields/form', template: @template %>
|
||||
<%= 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="form_saved_alert"></toggle-on-submit>
|
||||
<% configs = AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::SUBMITTER_COMPLETED_EMAIL_KEY).value %>
|
||||
@@ -68,7 +69,7 @@
|
||||
<%= ff.url_field :completed_redirect_url, required: false, class: 'base-input', dir: 'auto' %>
|
||||
</div>
|
||||
<%= ff.fields_for :completed_message, ff.object.completed_message do |fff| %>
|
||||
<div class="form-control mb-2 border-t mt-4">
|
||||
<div class="form-control mb-2 mt-4">
|
||||
<%= fff.label :body, t('completion_message'), class: 'label' %>
|
||||
<autoresize-textarea>
|
||||
<%= fff.text_area :body, required: false, class: 'base-input w-full py-2', dir: 'auto' %>
|
||||
@@ -162,6 +163,14 @@
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= f.fields_for :preferences, Struct.new(:request_email_enabled).new(@template.preferences['request_email_enabled']) do |ff| %>
|
||||
<div class="flex items-center justify-between py-2.5 px-1 mb-2">
|
||||
<span>
|
||||
<%= 'Send signature request email' %>
|
||||
</span>
|
||||
<%= ff.check_box :request_email_enabled, { checked: ff.object.request_email_enabled != false, class: 'toggle', onchange: 'this.form.requestSubmit()' }, 'true', 'false' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="form-control pt-2">
|
||||
<%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button' %>
|
||||
<div class="flex justify-center">
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<% select_fields = template.fields.filter_map { |f| [f['name'], f['uuid']] if f['name'].present? && f['type'].in?(TemplatesPrefillableFieldsController::PREFILLABLE_FIELD_TYPES) } %>
|
||||
<% if select_fields.present? %>
|
||||
<div class="border-b pb-4 mb-4">
|
||||
<%= form_for '', url: template_prefillable_fields_path(template), method: :post, data: { close_on_submit: false } do |f| %>
|
||||
<div class="form-control">
|
||||
<%= f.hidden_field :prefillable, value: 'true' %>
|
||||
<%= f.label :field_uuid, t(:invite_form_fields), class: 'label' %>
|
||||
<div class="join w-full">
|
||||
<%= select_tag :field_uuid, options_for_select(select_fields), prompt: t(:select_field), class: 'base-select w-full join-item', dir: 'auto', required: true %>
|
||||
<%= f.button button_title(title: t('add'), disabled_with: t('add')), class: 'base-button join-item !px-6' %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= render partial: 'templates_prefillable_fields/list', locals: { template: } %>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -0,0 +1,6 @@
|
||||
<div id="prefillable_fields_list" class="flex gap-1 px-0.5 mt-2 flex-wrap">
|
||||
<% template.fields.each do |f| %>
|
||||
<% next unless f['prefillable'] %>
|
||||
<%= button_to button_title(title: f['name'].presence || f['type'].capitalize, disabled_with: f['name'].presence || f['type'].capitalize, icon: svg_icon('x', class: 'w-4 h-4'), icon_disabled: svg_icon('loader', class: 'w-4 h-4 animate-spin')), template_prefillable_fields_path(template), params: { field_uuid: f['uuid'], prefillable: 'false' }, class: 'badge badge-lg badge-primary space-x-1 pr-3 pl-2', form: { data: { close_on_submit: false } } %>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -23,6 +23,8 @@ en: &en
|
||||
pro: Pro
|
||||
thanks: Thanks
|
||||
private: Private
|
||||
select: Select
|
||||
invite_form_fields: Invite form fields
|
||||
default_parties: Default parties
|
||||
authenticate_embedded_form_preview_with_token: Authenticate embedded form preview with token
|
||||
stripe_integration: Stripe Integration
|
||||
@@ -896,6 +898,8 @@ en: &en
|
||||
range_without_total: "%{from}-%{to} events"
|
||||
|
||||
es: &es
|
||||
select: Seleccionar
|
||||
invite_form_fields: Invitar campos del formulario
|
||||
pro: Pro
|
||||
default_parties: Partes predeterminadas
|
||||
authenticate_embedded_form_preview_with_token: Autenticar vista previa del formulario incrustado con token
|
||||
@@ -1772,6 +1776,8 @@ es: &es
|
||||
range_without_total: "%{from}-%{to} eventos"
|
||||
|
||||
it: &it
|
||||
select: Seleziona
|
||||
invite_form_fields: Invita campi modulo
|
||||
pro: Pro
|
||||
default_parties: Parti predefiniti
|
||||
authenticate_embedded_form_preview_with_token: "Autentica l'anteprima del modulo incorporato con il token"
|
||||
@@ -2648,6 +2654,8 @@ it: &it
|
||||
range_without_total: "%{from}-%{to} eventi"
|
||||
|
||||
fr: &fr
|
||||
select: Sélectionner
|
||||
invite_form_fields: Inviter des champs de formulaire
|
||||
pro: Pro
|
||||
default_parties: Parties par défaut
|
||||
authenticate_embedded_form_preview_with_token: Authentifier l’aperçu du formulaire intégré avec un jeton
|
||||
@@ -3527,6 +3535,8 @@ fr: &fr
|
||||
range_without_total: "%{from} à %{to} événements"
|
||||
|
||||
pt: &pt
|
||||
select: Selecionar
|
||||
invite_form_fields: Convidar campos do formulário
|
||||
pro: Pro
|
||||
default_parties: Partes padrão
|
||||
authenticate_embedded_form_preview_with_token: Autenticar visualização incorporada do formulário com token
|
||||
@@ -4404,6 +4414,8 @@ pt: &pt
|
||||
range_without_total: "%{from}-%{to} eventos"
|
||||
|
||||
de: &de
|
||||
select: Auswählen
|
||||
invite_form_fields: Formularfelder einladen
|
||||
pro: Pro
|
||||
default_parties: Standardparteien
|
||||
authenticate_embedded_form_preview_with_token: Authentifizieren Sie die eingebettete Formularvorschau mit Token
|
||||
|
||||
@@ -108,6 +108,7 @@ Rails.application.routes.draw do
|
||||
resource :preferences, only: %i[show create], controller: 'templates_preferences'
|
||||
resource :share_link, only: %i[show create], controller: 'templates_share_link'
|
||||
resources :recipients, only: %i[create], controller: 'templates_recipients'
|
||||
resources :prefillable_fields, only: %i[create], controller: 'templates_prefillable_fields'
|
||||
resources :submissions_export, only: %i[index new]
|
||||
end
|
||||
resources :preview_document_page, only: %i[show], path: '/preview/:signed_uuid'
|
||||
|
||||
Reference in New Issue
Block a user