mirror of
https://github.com/docusealco/docuseal.git
synced 2026-08-07 15:25:16 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ecbbf8410 | |||
| 990b35be18 | |||
| 8002764855 | |||
| b80982658c | |||
| 443ac23c29 | |||
| 37bb987e3e | |||
| c7b08e8d30 | |||
| dd502e8cef | |||
| a554182e57 | |||
| 0c039ee64f | |||
| c6b004f107 | |||
| 2fcb08d27d | |||
| 75fe5ce381 | |||
| fd7d0eaf53 | |||
| 7e537e4232 | |||
| a892975010 | |||
| 05ec92186b |
+7
-10
@@ -344,8 +344,8 @@ GEM
|
||||
os (1.1.4)
|
||||
package_json (0.1.0)
|
||||
pagy (8.1.2)
|
||||
parallel (1.25.1)
|
||||
parser (3.3.4.0)
|
||||
parallel (1.26.3)
|
||||
parser (3.3.5.0)
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
pg (1.5.6)
|
||||
@@ -435,8 +435,7 @@ GEM
|
||||
actionpack (>= 5.2)
|
||||
railties (>= 5.2)
|
||||
retriable (3.1.2)
|
||||
rexml (3.3.6)
|
||||
strscan
|
||||
rexml (3.3.8)
|
||||
rotp (6.3.0)
|
||||
rqrcode (2.2.0)
|
||||
chunky_png (~> 1.0)
|
||||
@@ -459,18 +458,17 @@ GEM
|
||||
rspec-mocks (~> 3.13)
|
||||
rspec-support (~> 3.13)
|
||||
rspec-support (3.13.1)
|
||||
rubocop (1.65.0)
|
||||
rubocop (1.66.1)
|
||||
json (~> 2.3)
|
||||
language_server-protocol (>= 3.17.0)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.3.0.2)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 2.4, < 3.0)
|
||||
rexml (>= 3.2.5, < 4.0)
|
||||
rubocop-ast (>= 1.31.1, < 2.0)
|
||||
rubocop-ast (>= 1.32.2, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 2.4.0, < 3.0)
|
||||
rubocop-ast (1.31.3)
|
||||
rubocop-ast (1.32.3)
|
||||
parser (>= 3.3.1.0)
|
||||
rubocop-performance (1.21.0)
|
||||
rubocop (>= 1.48.1, < 2.0)
|
||||
@@ -519,7 +517,6 @@ GEM
|
||||
stringio (3.1.1)
|
||||
strip_attributes (1.13.0)
|
||||
activemodel (>= 3.0, < 8.0)
|
||||
strscan (3.1.0)
|
||||
thor (1.3.2)
|
||||
timeout (0.4.1)
|
||||
trailblazer-option (0.1.2)
|
||||
@@ -536,7 +533,7 @@ GEM
|
||||
tzinfo-data (1.2024.1)
|
||||
tzinfo (>= 1.0.0)
|
||||
uber (0.1.0)
|
||||
unicode-display_width (2.5.0)
|
||||
unicode-display_width (2.6.0)
|
||||
uniform_notifier (1.16.0)
|
||||
warden (1.2.9)
|
||||
rack (>= 2.0.9)
|
||||
|
||||
@@ -42,7 +42,7 @@ DocuSeal is an open source platform that provides secure and efficient digital d
|
||||
- PDF signature verification
|
||||
- Users management
|
||||
- Mobile-optimized
|
||||
- Signing available in 13 languages
|
||||
- 6 UI languages with signing available in 13 languages
|
||||
- API and Webhooks for integrations
|
||||
- Easy to deploy in minutes
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ class AccountsController < ApplicationController
|
||||
LOCALE_OPTIONS = {
|
||||
'en-US' => 'English (United States)',
|
||||
'en-GB' => 'English (United Kingdom)',
|
||||
'fr-FR' => 'French (France)',
|
||||
'es-ES' => 'Spanish (Spain)',
|
||||
'pt-PT' => 'Portuguese (Portugal)',
|
||||
'de-DE' => 'German (Germany)',
|
||||
'it-IT' => 'Italian (Italy)'
|
||||
'fr-FR' => 'Français',
|
||||
'es-ES' => 'Español',
|
||||
'pt-PT' => 'Português',
|
||||
'de-DE' => 'Deutsch',
|
||||
'it-IT' => 'Italiano'
|
||||
}.freeze
|
||||
|
||||
before_action :load_account
|
||||
@@ -19,21 +19,25 @@ class AccountsController < ApplicationController
|
||||
def update
|
||||
current_account.update!(account_params)
|
||||
|
||||
@encrypted_config = EncryptedConfig.find_or_initialize_by(account: current_account,
|
||||
key: EncryptedConfig::APP_URL_KEY)
|
||||
@encrypted_config.assign_attributes(app_url_params)
|
||||
unless Docuseal.multitenant?
|
||||
@encrypted_config = EncryptedConfig.find_or_initialize_by(account: current_account,
|
||||
key: EncryptedConfig::APP_URL_KEY)
|
||||
@encrypted_config.assign_attributes(app_url_params)
|
||||
|
||||
unless URI.parse(@encrypted_config.value.to_s).class.in?([URI::HTTP, URI::HTTPS])
|
||||
@encrypted_config.errors.add(:value, I18n.t('should_be_a_valid_url'))
|
||||
unless URI.parse(@encrypted_config.value.to_s).class.in?([URI::HTTP, URI::HTTPS])
|
||||
@encrypted_config.errors.add(:value, I18n.t('should_be_a_valid_url'))
|
||||
|
||||
return render :show, status: :unprocessable_entity
|
||||
return render :show, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
@encrypted_config.save!
|
||||
|
||||
Docuseal.refresh_default_url_options!
|
||||
end
|
||||
|
||||
@encrypted_config.save!
|
||||
|
||||
Docuseal.refresh_default_url_options!
|
||||
|
||||
redirect_to settings_account_path, notice: I18n.t('account_information_has_been_updated')
|
||||
with_locale do
|
||||
redirect_to settings_account_path, notice: I18n.t('account_information_has_been_updated')
|
||||
end
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
render :show, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
@@ -8,6 +8,7 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
check_authorization unless: :devise_controller?
|
||||
|
||||
around_action :with_locale
|
||||
before_action :sign_in_for_demo, if: -> { Docuseal.demo? }
|
||||
before_action :maybe_redirect_to_setup, unless: :signed_in?
|
||||
before_action :authenticate_user!, unless: :devise_controller?
|
||||
@@ -51,7 +52,18 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
private
|
||||
|
||||
def with_locale(&)
|
||||
return yield unless current_account
|
||||
|
||||
locale = params[:lang].presence if Rails.env.development?
|
||||
locale ||= current_account.locale
|
||||
|
||||
I18n.with_locale(locale, &)
|
||||
end
|
||||
|
||||
def with_browser_locale(&)
|
||||
return yield if I18n.locale != :'en-US'
|
||||
|
||||
locale = params[:lang].presence
|
||||
locale ||= request.env['HTTP_ACCEPT_LANGUAGE'].to_s[BROWSER_LOCALE_REGEXP].to_s
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@ class EsignSettingsController < ApplicationController
|
||||
default_pkcs = GenerateCertificate.load_pkcs(cert_data) if cert_data['cert'].present?
|
||||
|
||||
custom_pkcs_list = (cert_data['custom'] || []).map do |e|
|
||||
{ 'pkcs' => OpenSSL::PKCS12.new(Base64.urlsafe_decode64(e['data']), e['password'].to_s),
|
||||
'name' => e['name'],
|
||||
'status' => e['status'] }
|
||||
pkcs = e['data'].present? ? OpenSSL::PKCS12.new(Base64.urlsafe_decode64(e['data']), e['password'].to_s) : nil
|
||||
|
||||
{ 'pkcs' => pkcs, 'name' => e['name'], 'status' => e['status'] }
|
||||
end
|
||||
|
||||
@pkcs_list = [
|
||||
@@ -56,7 +56,7 @@ class EsignSettingsController < ApplicationController
|
||||
|
||||
save_new_cert!(@encrypted_config, @cert_record)
|
||||
|
||||
redirect_to settings_esign_path, notice: I18n.t('certificate_has_been_successfully_added_')
|
||||
redirect_to settings_esign_path, notice: I18n.t('certificate_has_been_successfully_added')
|
||||
rescue OpenSSL::PKCS12::PKCS12Error => e
|
||||
Rollbar.error(e) if defined?(Rollbar)
|
||||
|
||||
@@ -66,10 +66,16 @@ class EsignSettingsController < ApplicationController
|
||||
end
|
||||
|
||||
def update
|
||||
@encrypted_config.value['custom'].each { |e| e['status'] = 'validate' }
|
||||
@encrypted_config.value['custom'].to_a.each { |e| e['status'] = 'validate' }
|
||||
|
||||
custom_cert_data = @encrypted_config.value['custom'].find { |e| e['name'] == params[:name] }
|
||||
custom_cert_data['status'] = 'default' if custom_cert_data
|
||||
custom_cert_data = @encrypted_config.value['custom'].to_a.find { |e| e['name'] == params[:name] }
|
||||
|
||||
if custom_cert_data
|
||||
custom_cert_data['status'] = 'default'
|
||||
elsif params[:name] == Docuseal::AATL_CERT_NAME
|
||||
@encrypted_config.value['custom'] ||= []
|
||||
@encrypted_config.value['custom'] << { 'name' => params[:name], 'status' => 'default' }
|
||||
end
|
||||
|
||||
@encrypted_config.save!
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ class SetupController < ApplicationController
|
||||
def account_params
|
||||
return {} unless params[:account]
|
||||
|
||||
params.require(:account).permit(:name, :timezone)
|
||||
params.require(:account).permit(:name, :timezone, :locale)
|
||||
end
|
||||
|
||||
def encrypted_config_params
|
||||
|
||||
@@ -12,16 +12,20 @@ class SubmitFormController < ApplicationController
|
||||
def show
|
||||
@submitter = Submitter.find_by!(slug: params[:slug])
|
||||
|
||||
submission = @submitter.submission
|
||||
|
||||
return redirect_to submit_form_completed_path(@submitter.slug) if @submitter.completed_at?
|
||||
return render :archived if @submitter.submission.template.archived_at? || @submitter.submission.archived_at?
|
||||
return render :expired if @submitter.submission.expired?
|
||||
return render :archived if submission.template.archived_at? || submission.archived_at?
|
||||
return render :expired if submission.expired?
|
||||
return render :declined if @submitter.declined_at?
|
||||
return render :awaiting if submission.template.preferences['submitters_order'] == 'preserved' &&
|
||||
!Submitters.current_submitter_order?(@submitter)
|
||||
|
||||
Submitters.preload_with_pages(@submitter)
|
||||
|
||||
Submitters::MaybeUpdateDefaultValues.call(@submitter, current_user)
|
||||
|
||||
@attachments_index = ActiveStorage::Attachment.where(record: @submitter.submission.submitters, name: :attachments)
|
||||
@attachments_index = ActiveStorage::Attachment.where(record: submission.submitters, name: :attachments)
|
||||
.preload(:blob).index_by(&:uuid)
|
||||
|
||||
@form_configs = Submitters::FormConfigs.call(@submitter, CONFIG_KEYS)
|
||||
|
||||
@@ -116,7 +116,8 @@ class TemplatesController < ApplicationController
|
||||
end
|
||||
|
||||
def authorized_clone_account_id?(account_id)
|
||||
true_user.account_id.to_s == account_id.to_s || true_user.account.linked_accounts.exists?(id: account_id)
|
||||
true_user.account_id.to_s == account_id.to_s ||
|
||||
true_user.account.linked_accounts.accessible_by(current_ability).exists?(id: account_id)
|
||||
end
|
||||
|
||||
def maybe_redirect_to_template(template)
|
||||
|
||||
@@ -24,6 +24,7 @@ class TemplatesPreferencesController < ApplicationController
|
||||
documents_copy_email_enabled documents_copy_email_attach_audit
|
||||
completed_notification_email_attach_documents
|
||||
completed_redirect_url
|
||||
submitters_order
|
||||
completed_notification_email_subject completed_notification_email_body
|
||||
completed_notification_email_enabled completed_notification_email_attach_audit] +
|
||||
[completed_message: %i[title body]]
|
||||
|
||||
@@ -9,7 +9,7 @@ class UserSignaturesController < ApplicationController
|
||||
def update
|
||||
file = params[:file]
|
||||
|
||||
return redirect_to settings_profile_index_path, notice: I18n.t('Unable to save signature') if file.blank?
|
||||
return redirect_to settings_profile_index_path, notice: I18n.t('unable_to_save_signature') if file.blank?
|
||||
|
||||
blob = ActiveStorage::Blob.create_and_upload!(io: file.open,
|
||||
filename: file.original_filename,
|
||||
@@ -24,7 +24,7 @@ class UserSignaturesController < ApplicationController
|
||||
if @user_config.update(value: attachment.uuid)
|
||||
redirect_to settings_profile_index_path, notice: I18n.t('signature_has_been_saved')
|
||||
else
|
||||
redirect_to settings_profile_index_path, notice: I18n.t('Unable to save signature')
|
||||
redirect_to settings_profile_index_path, notice: I18n.t('unable_to_save_signature')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -150,7 +150,8 @@ safeRegisterElement('import-list', class extends HTMLElement {
|
||||
this.app = createApp(ImportList, {
|
||||
template: JSON.parse(this.dataset.template),
|
||||
multitenant: this.dataset.multitenant === 'true',
|
||||
authenticityToken: document.querySelector('meta[name="csrf-token"]')?.content
|
||||
authenticityToken: document.querySelector('meta[name="csrf-token"]')?.content,
|
||||
i18n: JSON.parse(this.dataset.i18n || '{}')
|
||||
})
|
||||
|
||||
this.app.mount(this.appElem)
|
||||
|
||||
@@ -51,10 +51,6 @@ button[disabled] .enabled {
|
||||
@apply input input-bordered bg-white;
|
||||
}
|
||||
|
||||
.base-input-slim {
|
||||
@apply input input-bordered bg-white h-10;
|
||||
}
|
||||
|
||||
.base-textarea {
|
||||
@apply textarea textarea-bordered bg-white rounded-3xl;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ safeRegisterElement('submission-form', class extends HTMLElement {
|
||||
isDemo: this.dataset.isDemo === 'true',
|
||||
attribution: this.dataset.attribution !== 'false',
|
||||
scrollPadding: this.dataset.scrollPadding || '-80px',
|
||||
language: this.dataset.language,
|
||||
dryRun: this.dataset.dryRun === 'true',
|
||||
expand: ['true', 'false'].includes(this.dataset.expand) ? this.dataset.expand === 'true' : null,
|
||||
withSignatureId: this.dataset.withSignatureId === 'true',
|
||||
|
||||
@@ -222,7 +222,7 @@ export default {
|
||||
this.downloadUrls(urls)
|
||||
}
|
||||
} else {
|
||||
alert('Failed to download files')
|
||||
alert(this.t('failed_to_download_files'))
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
@@ -1183,10 +1183,6 @@ export default {
|
||||
return Promise.reject(new Error(data.error))
|
||||
}
|
||||
|
||||
if (isLastStep) {
|
||||
this.isSecondWalkthrough = true
|
||||
}
|
||||
|
||||
const nextStep = (isLastStep && emptyRequiredField) || this.stepFields[this.currentStep + 1]
|
||||
|
||||
if (nextStep) {
|
||||
@@ -1211,7 +1207,7 @@ export default {
|
||||
})
|
||||
}).catch(error => {
|
||||
if (error?.message === 'Image too small') {
|
||||
alert('Signature is too small - please redraw.')
|
||||
alert(this.t('signature_is_too_small_please_redraw'))
|
||||
} else {
|
||||
console.log(error)
|
||||
}
|
||||
|
||||
@@ -418,7 +418,7 @@ import MobileFields from './mobile_fields'
|
||||
import { IconPlus, IconUsersPlus, IconDeviceFloppy, IconChevronDown, IconEye, IconWritingSign, IconInnerShadowTop, IconInfoCircle, IconAdjustments } from '@tabler/icons-vue'
|
||||
import { v4 } from 'uuid'
|
||||
import { ref, computed } from 'vue'
|
||||
import { en as i18nEn } from './i18n'
|
||||
import * as i18n from './i18n'
|
||||
|
||||
export default {
|
||||
name: 'TemplateBuilder',
|
||||
@@ -679,6 +679,9 @@ export default {
|
||||
computed: {
|
||||
selectedAreaRef: () => ref(),
|
||||
fieldsDragFieldRef: () => ref(),
|
||||
language () {
|
||||
return this.locale.split('-')[0].toLowerCase()
|
||||
},
|
||||
defaultDateFormat () {
|
||||
const isUsBrowser = Intl.DateTimeFormat().resolvedOptions().locale.endsWith('-US')
|
||||
const isUsTimezone = new Intl.DateTimeFormat('en-US', { timeZoneName: 'short' }).format(new Date()).match(/\s(?:CST|CDT|PST|PDT|EST|EDT)$/)
|
||||
@@ -786,7 +789,7 @@ export default {
|
||||
document.activeElement.blur()
|
||||
},
|
||||
t (key) {
|
||||
return this.i18n[key] || i18nEn[key] || key
|
||||
return this.i18n[key] || i18n[this.language]?.[key] || i18n.en[key] || key
|
||||
},
|
||||
removePendingFields () {
|
||||
this.template.fields = this.template.fields.filter((f) => {
|
||||
@@ -1451,7 +1454,7 @@ export default {
|
||||
if (!this.template.fields.length) {
|
||||
e.preventDefault()
|
||||
|
||||
alert('Please draw fields to prepare the document.')
|
||||
alert(this.t('please_draw_fields_to_prepare_the_document'))
|
||||
} else {
|
||||
const submitterWithoutFields =
|
||||
this.template.submitters.find((submitter) => !this.template.fields.some((f) => f.submitter_uuid === submitter.uuid))
|
||||
@@ -1459,7 +1462,7 @@ export default {
|
||||
if (submitterWithoutFields) {
|
||||
e.preventDefault()
|
||||
|
||||
alert(`Please add fields for the ${submitterWithoutFields.name}. Or, remove the ${submitterWithoutFields.name} if not needed.`)
|
||||
alert(this.t('please_add_fields_for_the_submitter_name_or_remove_the_submitter_name_if_not_needed').replaceAll('{submitter_name}', submitterWithoutFields.name))
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1475,13 +1478,13 @@ export default {
|
||||
}
|
||||
|
||||
if (!this.template.fields.length) {
|
||||
alert('Please draw fields to prepare the document.')
|
||||
alert(this.t('please_draw_fields_to_prepare_the_document'))
|
||||
} else {
|
||||
const submitterWithoutFields =
|
||||
this.template.submitters.find((submitter) => !this.template.fields.some((f) => f.submitter_uuid === submitter.uuid))
|
||||
|
||||
if (submitterWithoutFields) {
|
||||
alert(`Please add fields for the ${submitterWithoutFields.name}. Or, remove the ${submitterWithoutFields.name} if not needed.`)
|
||||
alert(this.t('please_add_fields_for_the_submitter_name_or_remove_the_submitter_name_if_not_needed').replaceAll('{submitter_name}', submitterWithoutFields.name))
|
||||
} else {
|
||||
this.isSaving = true
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@ export default {
|
||||
},
|
||||
validateSaveAndClose () {
|
||||
if (!this.withConditions) {
|
||||
return alert('Available only in Pro')
|
||||
return alert(this.t('available_only_in_pro'))
|
||||
}
|
||||
|
||||
if (this.conditions.find((f) => f.field_uuid)) {
|
||||
|
||||
@@ -105,7 +105,7 @@ export default {
|
||||
|
||||
this.upload()
|
||||
} else {
|
||||
alert('Only PDF and images are supported.')
|
||||
alert(this.t('only_pdf_and_images_are_supported'))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
v-else-if="type == 'phone' && (fieldTypes.length === 0 || fieldTypes.includes(type))"
|
||||
class="tooltip tooltip-bottom flex"
|
||||
:class="{'tooltip-bottom-end': withPayment, 'tooltip-bottom': !withPayment }"
|
||||
data-tip="Unlock SMS-verified phone number field with paid plan. Use text field for phone numbers without verification."
|
||||
:data-tip="t('unlock_sms_verified_phone_number_field_with_paid_plan_use_text_field_for_phone_numbers_without_verification')"
|
||||
>
|
||||
<a
|
||||
href="https://www.docuseal.co/pricing"
|
||||
@@ -168,13 +168,13 @@
|
||||
>
|
||||
<ul class="list-disc list-outside ml-3">
|
||||
<li>
|
||||
Draw a text field on the page with a mouse
|
||||
{{ t('draw_a_text_field_on_the_page_with_a_mouse') }}
|
||||
</li>
|
||||
<li>
|
||||
Drag & drop any other field type on the page
|
||||
{{ t('drag_and_drop_any_other_field_type_on_the_page') }}
|
||||
</li>
|
||||
<li>
|
||||
Click on the field type above to start drawing it
|
||||
{{ t('click_on_the_field_type_above_to_start_drawing_it') }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -195,7 +195,7 @@ export default {
|
||||
},
|
||||
validateSaveAndClose () {
|
||||
if (!this.withFormula) {
|
||||
return alert('Available only in Pro')
|
||||
return alert(this.t('available_only_in_pro'))
|
||||
}
|
||||
|
||||
const normalizedFormula = this.normalizeFormula(this.formula)
|
||||
|
||||
@@ -104,6 +104,15 @@ const en = {
|
||||
field: 'Field',
|
||||
group: 'Group',
|
||||
draw_a_text_field_on_the_page_with_a_mouse: 'Draw a text field on the page with a mouse',
|
||||
drag_and_drop_any_other_field_type_on_the_page: 'Drag & drop any other field type on the page',
|
||||
click_on_the_field_type_above_to_start_drawing_it: 'Click on the field type above to start drawing it',
|
||||
please_draw_fields_to_prepare_the_document: 'Please draw fields to prepare the document.',
|
||||
only_pdf_and_images_are_supported: 'Only PDF and images are supported.',
|
||||
unlock_sms_verified_phone_number_field_with_paid_plan_use_text_field_for_phone_numbers_without_verification: 'Unlock SMS-verified phone number field with paid plan. Use text field for phone numbers without verification.',
|
||||
available_only_in_pro: 'Available only in Pro',
|
||||
failed_to_download_files: 'Failed to download files',
|
||||
signature_is_too_small_please_redraw: 'Signature is too small - please redraw.',
|
||||
please_add_fields_for_the_submitter_name_or_remove_the_submitter_name_if_not_needed: 'Please add fields for the {submitter_name}. Or, remove the {submitter_name} if not needed.',
|
||||
draw_field: 'Draw {field} Field',
|
||||
replace: 'Replace',
|
||||
uploading_: 'Uploading...',
|
||||
@@ -128,4 +137,699 @@ const en = {
|
||||
learn_more: 'Learn more'
|
||||
}
|
||||
|
||||
export { en }
|
||||
const es = {
|
||||
editable: 'Editable',
|
||||
search_field: 'Campo de búsqueda',
|
||||
field_not_found: 'Campo no encontrado',
|
||||
clear: 'Borrar',
|
||||
type_value: 'Escriba valor',
|
||||
align: 'Alinear',
|
||||
add_all_required_fields_to_continue: 'Agregar todos los campos requeridos para continuar',
|
||||
uploaded_pdf_contains_form_fields_keep_or_remove_them: 'El PDF cargado tiene campos. ¿Mantenerlos o eliminarlos?',
|
||||
keep: 'Mantener',
|
||||
left: 'Izquierda',
|
||||
heading: 'Encabezado',
|
||||
validation: 'Validación',
|
||||
add_blank_page: 'Agregar página en blanco',
|
||||
right: 'Derecha',
|
||||
center: 'Centro',
|
||||
with_logo: 'Con logotipo',
|
||||
description: 'Descripción',
|
||||
signing_date: 'Fecha de Firma',
|
||||
display_title: 'Título de visualización',
|
||||
unchecked: 'No marcado',
|
||||
price: 'Precio',
|
||||
equal: 'Igual',
|
||||
not_equal: 'No es igual',
|
||||
contains: 'Contiene',
|
||||
does_not_contain: 'No contiene',
|
||||
not_empty: 'No vacío',
|
||||
empty: 'Vacío',
|
||||
select_field_: 'Seleccionar campo...',
|
||||
select_value_: 'Seleccionar valor...',
|
||||
remove_condition: 'Eliminar condición',
|
||||
add_condition: 'Agregar condición',
|
||||
condition: 'Condición',
|
||||
formula: 'Fórmula',
|
||||
edit: 'Editar',
|
||||
settings: 'Configuración',
|
||||
up: 'Arriba',
|
||||
down: 'Abajo',
|
||||
set_signing_date: 'Establecer fecha de firma',
|
||||
are_you_sure: '¿Estás seguro?',
|
||||
sign_yourself: 'Firma tú mismo',
|
||||
checked: 'Seleccionado',
|
||||
send: 'Enviar',
|
||||
remove: 'Eliminar',
|
||||
save: 'Guardar',
|
||||
cancel: 'Cancelar',
|
||||
or_add_field_without_drawing: 'O añadir campo sin dibujar',
|
||||
draw_field_on_the_document: 'Dibujar campo {field} en el documento',
|
||||
click_to_upload: 'Haz clic para cargar',
|
||||
or_drag_and_drop_files: 'o arrastra y suelta archivos',
|
||||
uploading: 'Subiendo',
|
||||
processing_: 'Procesando...',
|
||||
add_pdf_documents_or_images: 'Agregar documentos PDF o imágenes',
|
||||
add_documents_or_images: 'Agregar documentos o imágenes',
|
||||
required: 'Requerido',
|
||||
default_value: 'Valor predeterminado',
|
||||
format: 'Formato',
|
||||
read_only: 'Solo lectura',
|
||||
page: 'Página',
|
||||
draw_new_area: 'Dibujar nueva área',
|
||||
copy_to_all_pages: 'Copiar a todas las páginas',
|
||||
add_option: 'Agregar opción',
|
||||
option: 'Opción',
|
||||
first_party: 'Primera Parte',
|
||||
second_party: 'Segunda Parte',
|
||||
third_party: 'Tercera Parte',
|
||||
fourth_party: 'Cuarta Parte',
|
||||
fifth_party: 'Quinta Parte',
|
||||
sixth_party: 'Sexta Parte',
|
||||
seventh_party: 'Séptima Parte',
|
||||
eighth_party: 'Octava Parte',
|
||||
ninth_party: 'Novena Parte',
|
||||
tenth_party: 'Décima Parte',
|
||||
eleventh_party: 'Undécimo Partido',
|
||||
twelfth_party: 'Duodécimo Partido',
|
||||
thirteenth_party: 'Decimotercer Partido',
|
||||
fourteenth_party: 'Catorceavo Partido',
|
||||
fifteenth_party: 'Quinceavo Partido',
|
||||
sixteenth_party: 'Dieciséisavo Partido',
|
||||
seventeenth_party: 'Diecisieteavo Partido',
|
||||
eighteenth_party: 'Dieciochoavo Partido',
|
||||
nineteenth_party: 'Decimonovena Fiesta',
|
||||
twentieth_party: 'Vigésima Fiesta',
|
||||
draw: 'Dibujar',
|
||||
add: 'Agregar',
|
||||
text: 'Texto',
|
||||
signature: 'Firma',
|
||||
initials: 'Iniciales',
|
||||
date: 'Fecha',
|
||||
number: 'Número',
|
||||
image: 'Imagen',
|
||||
file: 'Archivo',
|
||||
select: 'Seleccionar',
|
||||
checkbox: 'Casilla',
|
||||
multiple: 'Múltiple',
|
||||
field: 'Campo',
|
||||
group: 'Grupo',
|
||||
radio: 'Radio',
|
||||
cells: 'Celdas',
|
||||
stamp: 'Sello',
|
||||
payment: 'Pago',
|
||||
phone: 'Teléfono',
|
||||
draw_a_text_field_on_the_page_with_a_mouse: 'Dibujar un campo de texto en la página con el mouse',
|
||||
drag_and_drop_any_other_field_type_on_the_page: 'Arrastra y suelta cualquier otro tipo de campo en la página',
|
||||
click_on_the_field_type_above_to_start_drawing_it: 'Haz clic en el tipo de campo de arriba para comenzar a dibujarlo',
|
||||
please_draw_fields_to_prepare_the_document: 'Por favor, dibuja los campos para preparar el documento.',
|
||||
only_pdf_and_images_are_supported: 'Solo se admiten PDF e imágenes.',
|
||||
unlock_sms_verified_phone_number_field_with_paid_plan_use_text_field_for_phone_numbers_without_verification: 'Desbloquea el campo de número de teléfono verificado por SMS con un plan pago. Usa el campo de texto para números de teléfono sin verificación.',
|
||||
available_only_in_pro: 'Disponible solo en Pro',
|
||||
failed_to_download_files: 'Error al descargar los archivos',
|
||||
signature_is_too_small_please_redraw: 'La firma es demasiado pequeña. Por favor, dibújala de nuevo.',
|
||||
please_add_fields_for_the_submitter_name_or_remove_the_submitter_name_if_not_needed: 'Por favor, añade campos para {submitter_name} o elimina {submitter_name} si no es necesario.',
|
||||
draw_field: 'Dibujar campo {field}',
|
||||
replace: 'Reemplazar',
|
||||
uploading_: 'Subiendo...',
|
||||
add_document: 'Subir',
|
||||
any: 'Cualquier',
|
||||
drawn: 'Dibujado',
|
||||
typed: 'Escrito',
|
||||
none: 'Ninguno',
|
||||
ssn: 'SSN',
|
||||
ein: 'EIN',
|
||||
email: 'Correo electrónico',
|
||||
url: 'URL',
|
||||
zip: 'ZIP',
|
||||
custom: 'Personalizado',
|
||||
numbers_only: 'Solo números',
|
||||
letters_only: 'Solo letras',
|
||||
regexp_validation: 'Validación de expresión regular',
|
||||
enter_pdf_password: 'Ingrese la contraseña del PDF',
|
||||
wrong_password: 'Contraseña incorrecta',
|
||||
currency: 'Moneda',
|
||||
save_and_preview: 'Guardar y previsualizar',
|
||||
preferences: 'Preferencias',
|
||||
available_in_pro: 'Disponible en Pro',
|
||||
some_fields_are_missing_in_the_formula: 'Faltan algunos campos en la fórmula.',
|
||||
learn_more: 'Aprende más'
|
||||
}
|
||||
|
||||
const it = {
|
||||
editable: 'Modificabile',
|
||||
search_field: 'Campo di ricerca',
|
||||
field_not_found: 'Campo non trovato',
|
||||
clear: 'Cancella',
|
||||
align: 'Allinea',
|
||||
add_all_required_fields_to_continue: 'Aggiungi tutti i campi obbligatori per continuare',
|
||||
uploaded_pdf_contains_form_fields_keep_or_remove_them: 'Il PDF caricato contiene campi del modulo. Mantenerli o rimuoverli?',
|
||||
keep: 'Mantieni',
|
||||
left: 'Sinistra',
|
||||
heading: 'Intestazione',
|
||||
validation: 'Validazione',
|
||||
add_blank_page: 'Aggiungi pagina vuota',
|
||||
right: 'Destra',
|
||||
center: 'Centro',
|
||||
description: 'Descrizione',
|
||||
display_title: 'Mostra titolo',
|
||||
with_logo: 'Con logo',
|
||||
unchecked: 'Non selezionato',
|
||||
price: 'Prezzo',
|
||||
type_value: 'Inserisci valore',
|
||||
equal: 'Uguale',
|
||||
not_equal: 'Non uguale',
|
||||
contains: 'Contiene',
|
||||
does_not_contain: 'Non contiene',
|
||||
not_empty: 'Non vuoto',
|
||||
empty: 'Vuoto',
|
||||
select_field_: 'Seleziona campo...',
|
||||
select_value_: 'Seleziona valore...',
|
||||
remove_condition: 'Rimuovi condizione',
|
||||
add_condition: 'Aggiungi condizione',
|
||||
are_you_sure: 'Sei sicuro?',
|
||||
sign_yourself: 'Firma te stesso',
|
||||
set_signing_date: 'Imposta data di firma',
|
||||
signing_date: 'Data di firma',
|
||||
send: 'Invia',
|
||||
remove: 'Rimuovi',
|
||||
edit: 'Modifica',
|
||||
settings: 'Impostazioni',
|
||||
up: 'Su',
|
||||
down: 'Giù',
|
||||
checked: 'Selezionato',
|
||||
save: 'Salva',
|
||||
cancel: 'Annulla',
|
||||
any: 'Qualsiasi',
|
||||
drawn: 'Disegnato',
|
||||
formula: 'Formula',
|
||||
typed: 'Digitato',
|
||||
draw_field_on_the_document: 'Disegna il campo {field} sul documento',
|
||||
click_to_upload: 'Clicca per caricare',
|
||||
or_drag_and_drop_files: 'o trascina e rilascia i file',
|
||||
uploading: 'Caricamento in corso',
|
||||
processing_: 'Elaborazione...',
|
||||
add_pdf_documents_or_images: 'Aggiungi documenti PDF o immagini',
|
||||
add_documents_or_images: 'Aggiungi documenti o immagini',
|
||||
required: 'Obbligatorio',
|
||||
default_value: 'Valore predefinito',
|
||||
format: 'Formato',
|
||||
read_only: 'Sola lettura',
|
||||
page: 'Pagina',
|
||||
draw_new_area: 'Disegna nuova area',
|
||||
copy_to_all_pages: 'Copia in tutte le pagine',
|
||||
add_option: 'Aggiungi opzione',
|
||||
option: 'Opzione',
|
||||
condition: 'Condizione',
|
||||
first_party: 'Prima parte',
|
||||
second_party: 'Seconda parte',
|
||||
third_party: 'Terza parte',
|
||||
fourth_party: 'Quarta parte',
|
||||
fifth_party: 'Quinta parte',
|
||||
sixth_party: 'Sesta parte',
|
||||
seventh_party: 'Settima parte',
|
||||
eighth_party: 'Ottava parte',
|
||||
ninth_party: 'Nona parte',
|
||||
tenth_party: 'Decima parte',
|
||||
eleventh_party: 'Undicesima parte',
|
||||
twelfth_party: 'Dodicesima parte',
|
||||
thirteenth_party: 'Tredicesima parte',
|
||||
fourteenth_party: 'Quattordicesima parte',
|
||||
fifteenth_party: 'Quindicesima parte',
|
||||
sixteenth_party: 'Sedicesima parte',
|
||||
seventeenth_party: 'Diciassettesima parte',
|
||||
eighteenth_party: 'Diciottesima parte',
|
||||
nineteenth_party: 'Diciannovesima parte',
|
||||
twentieth_party: 'Ventesima parte',
|
||||
draw: 'Disegna',
|
||||
add: 'Aggiungi',
|
||||
or_add_field_without_drawing: 'Oppure aggiungi campo senza disegno',
|
||||
text: 'Testo',
|
||||
number: 'Numero',
|
||||
signature: 'Firma',
|
||||
initials: 'Iniziali',
|
||||
date: 'Data',
|
||||
image: 'Immagine',
|
||||
file: 'File',
|
||||
select: 'Seleziona',
|
||||
checkbox: 'Casella di controllo',
|
||||
multiple: 'Multiplo',
|
||||
radio: 'Radio',
|
||||
cells: 'Celle',
|
||||
stamp: 'Timbro',
|
||||
payment: 'Pagamento',
|
||||
phone: 'Telefono',
|
||||
field: 'Campo',
|
||||
group: 'Gruppo',
|
||||
draw_a_text_field_on_the_page_with_a_mouse: 'Disegna un campo di testo sulla pagina con il mouse',
|
||||
drag_and_drop_any_other_field_type_on_the_page: 'Trascina e rilascia qualsiasi altro tipo di campo sulla pagina',
|
||||
click_on_the_field_type_above_to_start_drawing_it: 'Clicca sul tipo di campo sopra per iniziare a disegnarlo',
|
||||
please_draw_fields_to_prepare_the_document: 'Per favore, disegna i campi per preparare il documento.',
|
||||
only_pdf_and_images_are_supported: 'Sono supportati solo PDF e immagini.',
|
||||
unlock_sms_verified_phone_number_field_with_paid_plan_use_text_field_for_phone_numbers_without_verification: 'Sblocca il campo numero di telefono verificato tramite SMS con un piano a pagamento. Usa il campo di testo per numeri di telefono senza verifica.',
|
||||
available_only_in_pro: 'Disponibile solo in Pro',
|
||||
failed_to_download_files: 'Impossibile scaricare i file',
|
||||
signature_is_too_small_please_redraw: 'La firma è troppo piccola. Ridisegnala per favore.',
|
||||
please_add_fields_for_the_submitter_name_or_remove_the_submitter_name_if_not_needed: 'Aggiungi campi per {submitter_name} o rimuovi {submitter_name} se non necessario.',
|
||||
draw_field: 'Disegna il campo {field}',
|
||||
replace: 'Sostituisci',
|
||||
uploading_: 'Caricamento in corso...',
|
||||
add_document: 'Aggiungi',
|
||||
none: 'Nessuno',
|
||||
ssn: 'SSN',
|
||||
ein: 'EIN',
|
||||
email: 'Email',
|
||||
url: 'URL',
|
||||
zip: 'CAP',
|
||||
custom: 'Personalizzato',
|
||||
numbers_only: 'Solo numeri',
|
||||
letters_only: 'Solo lettere',
|
||||
regexp_validation: 'Validazione regexp',
|
||||
enter_pdf_password: 'Inserisci password PDF',
|
||||
wrong_password: 'Password errata',
|
||||
currency: 'Valuta',
|
||||
save_and_preview: 'Salva e Anteprima',
|
||||
preferences: 'Preferenze',
|
||||
available_in_pro: 'Disponibile in Pro',
|
||||
some_fields_are_missing_in_the_formula: 'Alcuni campi mancano nella formula.',
|
||||
learn_more: 'Scopri di più'
|
||||
}
|
||||
|
||||
const pt = {
|
||||
editable: 'Editável',
|
||||
search_field: 'Campo de busca',
|
||||
field_not_found: 'Campo não encontrado',
|
||||
clear: 'Limpar',
|
||||
type_value: 'Digite valor',
|
||||
add_all_required_fields_to_continue: 'Adicione todos os campos obrigatórios para continuar',
|
||||
uploaded_pdf_contains_form_fields_keep_or_remove_them: 'O PDF carregado contém campos. Manter ou removê-los?',
|
||||
keep: 'Manter',
|
||||
align: 'Alinhar',
|
||||
left: 'Esquerda',
|
||||
heading: 'Cabeçalho',
|
||||
validation: 'Validação',
|
||||
add_blank_page: 'Adicionar página em branco',
|
||||
right: 'Direita',
|
||||
center: 'Centro',
|
||||
with_logo: 'Com logotipo',
|
||||
description: 'Descrição',
|
||||
display_title: 'Título de exibição',
|
||||
signing_date: 'Data da Assinatura',
|
||||
unchecked: 'Não marcado',
|
||||
price: 'Preço',
|
||||
equal: 'Igual',
|
||||
not_equal: 'Não é igual',
|
||||
contains: 'Contém',
|
||||
does_not_contain: 'Não contém',
|
||||
not_empty: 'Não vazio',
|
||||
empty: 'Vazio',
|
||||
add_condition: 'Adicionar condição',
|
||||
select_field_: 'Selecionar campo...',
|
||||
select_value_: 'Selecionar valor...',
|
||||
remove_condition: 'Remover condição',
|
||||
condition: 'Condição',
|
||||
formula: 'Fórmula',
|
||||
edit: 'Editar',
|
||||
settings: 'Configurações',
|
||||
up: 'Para cima',
|
||||
down: 'Para baixo',
|
||||
set_signing_date: 'Definir data de assinatura',
|
||||
are_you_sure: 'Tem certeza?',
|
||||
sign_yourself: 'Assine você mesmo',
|
||||
checked: 'Marcado',
|
||||
send: 'Enviar',
|
||||
remove: 'Remover',
|
||||
save: 'Salvar',
|
||||
cancel: 'Cancelar',
|
||||
or_add_field_without_drawing: 'Ou adicione campo sem desenhar',
|
||||
draw_field_on_the_document: 'Desenhar campo {field} no documento',
|
||||
click_to_upload: 'Clique para enviar',
|
||||
or_drag_and_drop_files: 'ou arraste e solte arquivos',
|
||||
uploading: 'Carregando',
|
||||
processing_: 'Processando...',
|
||||
add_pdf_documents_or_images: 'Adicionar documentos PDF ou imagens',
|
||||
add_documents_or_images: 'Adicionar documentos ou imagens',
|
||||
required: 'Obrigatório',
|
||||
default_value: 'Valor padrão',
|
||||
format: 'Formato',
|
||||
read_only: 'Somente leitura',
|
||||
page: 'Página',
|
||||
draw_new_area: 'Desenhar nova área',
|
||||
copy_to_all_pages: 'Copiar para todas as páginas',
|
||||
add_option: 'Adicionar opção',
|
||||
option: 'Opção',
|
||||
first_party: 'Primeira Parte',
|
||||
second_party: 'Segunda Parte',
|
||||
third_party: 'Terceira Parte',
|
||||
fourth_party: 'Quarta Parte',
|
||||
fifth_party: 'Quinta Parte',
|
||||
sixth_party: 'Sexta Parte',
|
||||
seventh_party: 'Sétima Parte',
|
||||
eighth_party: 'Oitava Parte',
|
||||
ninth_party: 'Nona Parte',
|
||||
tenth_party: 'Décima Parte',
|
||||
eleventh_party: 'Décima Primeira Parte',
|
||||
twelfth_party: 'Décima Segunda Parte',
|
||||
thirteenth_party: 'Décima Terceira Parte',
|
||||
fourteenth_party: 'Décima Quarta Parte',
|
||||
fifteenth_party: 'Décima Quinta Parte',
|
||||
sixteenth_party: 'Décima Sexta Parte',
|
||||
seventeenth_party: 'Décima Sétima Parte',
|
||||
eighteenth_party: 'Décima Oitava Parte',
|
||||
nineteenth_party: 'Décima Nona Parte',
|
||||
twentieth_party: 'Vigésima Parte',
|
||||
draw: 'Desenhar',
|
||||
add: 'Adicionar',
|
||||
text: 'Texto',
|
||||
signature: 'Assinatura',
|
||||
initials: 'Rúbrica',
|
||||
date: 'Data',
|
||||
number: 'Número',
|
||||
image: 'Imagem',
|
||||
file: 'Arquivo',
|
||||
select: 'Selecionar',
|
||||
checkbox: 'Caixa',
|
||||
field: 'Campo',
|
||||
group: 'Grupo',
|
||||
multiple: 'Múltiplo',
|
||||
radio: 'Rádio',
|
||||
cells: 'Células',
|
||||
stamp: 'Carimbo',
|
||||
payment: 'Pagamento',
|
||||
phone: 'Telefone',
|
||||
draw_a_text_field_on_the_page_with_a_mouse: 'Desenhar um campo de texto na página com o mouse',
|
||||
drag_and_drop_any_other_field_type_on_the_page: 'Arraste e solte qualquer outro tipo de campo na página',
|
||||
click_on_the_field_type_above_to_start_drawing_it: 'Clique no tipo de campo acima para começar a desenhá-lo',
|
||||
please_draw_fields_to_prepare_the_document: 'Por favor, desenhe os campos para preparar o documento.',
|
||||
only_pdf_and_images_are_supported: 'Apenas PDFs e imagens são suportados.',
|
||||
unlock_sms_verified_phone_number_field_with_paid_plan_use_text_field_for_phone_numbers_without_verification: 'Desbloqueie o campo de número de telefone verificado por SMS com um plano pago. Use o campo de texto para números de telefone sem verificação.',
|
||||
available_only_in_pro: 'Disponível apenas no Pro',
|
||||
failed_to_download_files: 'Falha ao baixar arquivos',
|
||||
signature_is_too_small_please_redraw: 'A assinatura é muito pequena. Por favor, redesenhe.',
|
||||
please_add_fields_for_the_submitter_name_or_remove_the_submitter_name_if_not_needed: 'Adicione campos para {submitter_name} ou remova {submitter_name} se não for necessário.',
|
||||
draw_field: 'Desenhar campo {field}',
|
||||
replace: 'Substituir',
|
||||
uploading_: 'Carregando...',
|
||||
add_document: 'Enviar',
|
||||
any: 'Qualquer',
|
||||
drawn: 'Desenhado',
|
||||
typed: 'Digitado',
|
||||
none: 'Nenhum',
|
||||
ssn: 'SSN',
|
||||
ein: 'EIN',
|
||||
email: 'Email',
|
||||
url: 'URL',
|
||||
zip: 'ZIP',
|
||||
custom: 'Personalizado',
|
||||
numbers_only: 'Somente números',
|
||||
letters_only: 'Somente letras',
|
||||
regexp_validation: 'Validação de expressão regular',
|
||||
enter_pdf_password: 'Digite a senha do PDF',
|
||||
wrong_password: 'Senha incorreta',
|
||||
currency: 'Moeda',
|
||||
save_and_preview: 'Salvar e Pré-visualizar',
|
||||
preferences: 'Preferências',
|
||||
available_in_pro: 'Disponível no Pro',
|
||||
some_fields_are_missing_in_the_formula: 'Faltam alguns campos na fórmula.',
|
||||
learn_more: 'Saiba mais'
|
||||
}
|
||||
|
||||
const fr = {
|
||||
editable: 'Éditable',
|
||||
search_field: 'Champ de recherche',
|
||||
field_not_found: 'Champ non trouvé',
|
||||
clear: 'Effacer',
|
||||
type_value: 'Tapez la valeur',
|
||||
add_all_required_fields_to_continue: 'Ajoutez tous les champs obligatoires pour continuer',
|
||||
uploaded_pdf_contains_form_fields_keep_or_remove_them: 'Le PDF téléchargé contient des champs. Les conserver ou les supprimer?',
|
||||
keep: 'Conserver',
|
||||
align: 'Aligner',
|
||||
left: 'Gauche',
|
||||
heading: 'En-tête',
|
||||
validation: 'Validation',
|
||||
add_blank_page: 'Ajouter une page blanche',
|
||||
right: 'Droite',
|
||||
add_condition: 'Ajouter une condition',
|
||||
center: 'Centre',
|
||||
with_logo: 'Avec logo',
|
||||
description: 'Description',
|
||||
display_title: "Titre d'affichage",
|
||||
unchecked: 'Non coché',
|
||||
price: 'Prix',
|
||||
equal: 'Égal',
|
||||
not_equal: 'Non égal',
|
||||
contains: 'Contient',
|
||||
signing_date: 'Date de signature',
|
||||
does_not_contain: 'Ne contient pas',
|
||||
not_empty: 'Non vide',
|
||||
empty: 'Vide',
|
||||
select_field_: 'Sélectionner un champ...',
|
||||
select_value_: 'Sélectionner une valeur...',
|
||||
remove_condition: 'Supprimer la condition',
|
||||
condition: 'Condition',
|
||||
formula: 'Formule',
|
||||
edit: 'Éditer',
|
||||
settings: 'Paramètres',
|
||||
up: 'Haut',
|
||||
down: 'Bas',
|
||||
set_signing_date: 'Définir la date de signature',
|
||||
are_you_sure: 'Êtes-vous sûr ?',
|
||||
sign_yourself: 'Signez-vous',
|
||||
checked: 'Coché',
|
||||
send: 'Envoyer',
|
||||
remove: 'Supprimer',
|
||||
save: 'Enregistrer',
|
||||
cancel: 'Annuler',
|
||||
draw_field_on_the_document: 'Dessinez le champ {field} sur le document',
|
||||
click_to_upload: 'Cliquez pour télécharger',
|
||||
or_drag_and_drop_files: 'ou faites glisser-déposer des fichiers',
|
||||
uploading: 'Téléchargement en cours',
|
||||
processing_: 'Traitement en cours...',
|
||||
add_pdf_documents_or_images: 'Ajoutez des documents PDF ou des images',
|
||||
add_documents_or_images: 'Ajoutez des documents ou des images',
|
||||
required: 'Requis',
|
||||
default_value: 'Valeur par défaut',
|
||||
format: 'Format',
|
||||
read_only: 'Lecture seule',
|
||||
page: 'Page',
|
||||
draw_new_area: 'Dessiner une nouvelle zone',
|
||||
copy_to_all_pages: 'Copier sur toutes les pages',
|
||||
add_option: 'Ajouter une option',
|
||||
option: 'Option',
|
||||
first_party: 'Première partie',
|
||||
second_party: 'Deuxième partie',
|
||||
third_party: 'Troisième partie',
|
||||
fourth_party: 'Quatrième partie',
|
||||
fifth_party: 'Cinquième partie',
|
||||
sixth_party: 'Sixième partie',
|
||||
seventh_party: 'Septième partie',
|
||||
eighth_party: 'Huitième partie',
|
||||
ninth_party: 'Neuvième partie',
|
||||
tenth_party: 'Dixième partie',
|
||||
eleventh_party: 'Onzième Parti',
|
||||
twelfth_party: 'Douzième Parti',
|
||||
thirteenth_party: 'Treizième Parti',
|
||||
fourteenth_party: 'Quatorzième Parti',
|
||||
fifteenth_party: 'Quinzième Parti',
|
||||
sixteenth_party: 'Seizième Parti',
|
||||
seventeenth_party: 'Dix-septième Parti',
|
||||
eighteenth_party: 'Dix-huitième Parti',
|
||||
nineteenth_party: 'Dix-Neuvième Fête',
|
||||
twentieth_party: 'Vingtième Fête',
|
||||
draw: 'Dessiner',
|
||||
add: 'Ajouter',
|
||||
or_add_field_without_drawing: 'Ou ajoutez un champ sans dessiner',
|
||||
text: 'Texte',
|
||||
signature: 'Signature',
|
||||
initials: 'Initiales',
|
||||
date: 'Date',
|
||||
number: 'Numéro',
|
||||
image: 'Image',
|
||||
file: 'Fichier',
|
||||
select: 'Choisir',
|
||||
checkbox: 'Coche',
|
||||
multiple: 'Multiple',
|
||||
radio: 'Radio',
|
||||
cells: 'Cellules',
|
||||
stamp: 'Tampon',
|
||||
payment: 'Paiement',
|
||||
phone: 'Téléphone',
|
||||
field: 'Champ',
|
||||
group: 'Groupe',
|
||||
draw_a_text_field_on_the_page_with_a_mouse: 'Dessinez un champ texte sur la page avec une souris',
|
||||
drag_and_drop_any_other_field_type_on_the_page: 'Glissez et déposez tout autre type de champ sur la page',
|
||||
click_on_the_field_type_above_to_start_drawing_it: 'Cliquez sur le type de champ ci-dessus pour commencer à le dessiner',
|
||||
please_draw_fields_to_prepare_the_document: 'Veuillez dessiner les champs pour préparer le document.',
|
||||
only_pdf_and_images_are_supported: 'Seuls les PDF et les images sont pris en charge.',
|
||||
unlock_sms_verified_phone_number_field_with_paid_plan_use_text_field_for_phone_numbers_without_verification: 'Débloquez le champ de numéro de téléphone vérifié par SMS avec un plan payant. Utilisez un champ texte pour les numéros de téléphone sans vérification.',
|
||||
available_only_in_pro: 'Disponible uniquement en Pro',
|
||||
failed_to_download_files: 'Échec du téléchargement des fichiers',
|
||||
signature_is_too_small_please_redraw: 'La signature est trop petite. Veuillez la redessiner.',
|
||||
please_add_fields_for_the_submitter_name_or_remove_the_submitter_name_if_not_needed: 'Veuillez ajouter des champs pour {submitter_name} ou retirer {submitter_name} si ce n\'est pas nécessaire.',
|
||||
draw_field: 'Dessiner le champ {field}',
|
||||
replace: 'Remplacer',
|
||||
uploading_: 'Téléchargement en cours...',
|
||||
add_document: 'Télécharger',
|
||||
any: 'Tout',
|
||||
drawn: 'Dessiné',
|
||||
typed: 'Tapé',
|
||||
none: 'Aucun',
|
||||
ssn: 'SSN',
|
||||
ein: 'EIN',
|
||||
email: 'E-mail',
|
||||
url: 'URL',
|
||||
zip: 'ZIP',
|
||||
custom: 'Personnalisé',
|
||||
numbers_only: 'Chiffres uniquement',
|
||||
letters_only: 'Lettres uniquement',
|
||||
regexp_validation: 'Validation par expression régulière',
|
||||
enter_pdf_password: 'Entrez le mot de passe PDF',
|
||||
wrong_password: 'Mot de passe incorrect',
|
||||
currency: 'Devise',
|
||||
save_and_preview: 'Enregistrer et prévisualiser',
|
||||
preferences: 'Préférences',
|
||||
available_in_pro: 'Disponible en version Pro',
|
||||
some_fields_are_missing_in_the_formula: 'Certains champs manquent dans la formule.',
|
||||
learn_more: 'En savoir plus'
|
||||
}
|
||||
|
||||
const de = {
|
||||
editable: 'Bearbeitbar',
|
||||
search_field: 'Suchfeld',
|
||||
field_not_found: 'Feld nicht gefunden',
|
||||
clear: 'Löschen',
|
||||
type_value: 'Wert eingeben',
|
||||
add_all_required_fields_to_continue: 'Fügen Sie alle erforderlichen Felder hinzu, um fortzufahren',
|
||||
uploaded_pdf_contains_form_fields_keep_or_remove_them: 'Das hochgeladene PDF enthält Formularfelder. Behalten oder entfernen?',
|
||||
keep: 'Behalten',
|
||||
align: 'Ausrichten',
|
||||
left: 'Links',
|
||||
heading: 'Überschrift',
|
||||
validation: 'Validierung',
|
||||
add_blank_page: 'Leere Seite hinzufügen',
|
||||
right: 'Rechts',
|
||||
add_condition: 'Bedingung hinzufügen',
|
||||
center: 'Zentriert',
|
||||
with_logo: 'Mit Logo',
|
||||
description: 'Beschreibung',
|
||||
display_title: 'Anzeigetitel',
|
||||
unchecked: 'Nicht überprüft',
|
||||
price: 'Preis',
|
||||
equal: 'Gleich',
|
||||
not_equal: 'Ungleich',
|
||||
contains: 'Enthält',
|
||||
does_not_contain: 'Enthält nicht',
|
||||
not_empty: 'Nicht leer',
|
||||
empty: 'Leer',
|
||||
signing_date: 'Signaturdatum',
|
||||
select_field_: 'Feld auswählen...',
|
||||
select_value_: 'Wert auswählen...',
|
||||
remove_condition: 'Bedingung entfernen',
|
||||
condition: 'Bedingung',
|
||||
formula: 'Formel',
|
||||
edit: 'Bearbeiten',
|
||||
settings: 'Einstellungen',
|
||||
up: 'Nach oben',
|
||||
down: 'Nach unten',
|
||||
set_signing_date: 'Unterschriftdatum festlegen',
|
||||
are_you_sure: 'Bist du sicher?',
|
||||
sign_yourself: 'Unterschreiben Sie selbst',
|
||||
checked: 'Ausgewählt',
|
||||
send: 'Senden',
|
||||
remove: 'Entfernen',
|
||||
save: 'Speichern',
|
||||
cancel: 'Abbrechen',
|
||||
draw_field_on_the_document: 'Feld {field} auf dem Dokument zeichnen',
|
||||
click_to_upload: 'Klicken Sie zum Hochladen',
|
||||
or_drag_and_drop_files: 'oder Dateien hierher ziehen',
|
||||
uploading: 'Hochladen',
|
||||
processing_: 'Verarbeitung...',
|
||||
add_pdf_documents_or_images: 'PDF-Dokumente oder Bilder hinzufügen',
|
||||
add_documents_or_images: 'Dokumente oder Bilder hinzufügen',
|
||||
required: 'Erforderlich',
|
||||
default_value: 'Standardwert',
|
||||
format: 'Format',
|
||||
read_only: 'Nur lesen',
|
||||
page: 'Seite',
|
||||
draw_new_area: 'Neuen Bereich zeichnen',
|
||||
copy_to_all_pages: 'Auf alle Seiten kopieren',
|
||||
add_option: 'Option hinzufügen',
|
||||
option: 'Option',
|
||||
first_party: 'Erste Partei',
|
||||
second_party: 'Zweite Partei',
|
||||
third_party: 'Dritte Partei',
|
||||
fourth_party: 'Vierte Partei',
|
||||
fifth_party: 'Fünfte Partei',
|
||||
sixth_party: 'Sechste Partei',
|
||||
seventh_party: 'Siebte Partei',
|
||||
eighth_party: 'Achte Partei',
|
||||
ninth_party: 'Neunte Partei',
|
||||
tenth_party: 'Zehnte Partei',
|
||||
eleventh_party: 'Elfte Partei',
|
||||
twelfth_party: 'Zwölfte Partei',
|
||||
thirteenth_party: 'Dreizehnte Partei',
|
||||
fourteenth_party: 'Vierzehnte Partei',
|
||||
fifteenth_party: 'Fünfzehnte Partei',
|
||||
sixteenth_party: 'Sechzehnte Partei',
|
||||
seventeenth_party: 'Siebzehnte Partei',
|
||||
eighteenth_party: 'Achtzehnte Partei',
|
||||
nineteenth_party: 'Neunzehnte Party',
|
||||
twentieth_party: 'Zwanzigste Party',
|
||||
draw: 'Zeichnen',
|
||||
add: 'Hinzufügen',
|
||||
or_add_field_without_drawing: 'Oder Feld ohne Zeichnung hinzufügen',
|
||||
text: 'Text',
|
||||
signature: 'Unterschrift',
|
||||
initials: 'Initialen',
|
||||
date: 'Datum',
|
||||
number: 'Nummer',
|
||||
image: 'Bild',
|
||||
file: 'Datei',
|
||||
select: 'Auswählen',
|
||||
checkbox: 'Checkbox',
|
||||
multiple: 'Mehrere',
|
||||
radio: 'Radio',
|
||||
cells: 'Zellen',
|
||||
stamp: 'Stempel',
|
||||
payment: 'Zahlung',
|
||||
phone: 'Telefon',
|
||||
field: 'Feld',
|
||||
group: 'Gruppe',
|
||||
draw_a_text_field_on_the_page_with_a_mouse: 'Textfeld auf der Seite mit der Maus zeichnen',
|
||||
drag_and_drop_any_other_field_type_on_the_page: 'Ziehe und lasse einen anderen Feldtyp auf die Seite fallen',
|
||||
click_on_the_field_type_above_to_start_drawing_it: 'Klicke auf den Feldtyp oben, um mit dem Zeichnen zu beginnen',
|
||||
please_draw_fields_to_prepare_the_document: 'Bitte zeichne Felder, um das Dokument vorzubereiten.',
|
||||
only_pdf_and_images_are_supported: 'Nur PDFs und Bilder werden unterstützt.',
|
||||
unlock_sms_verified_phone_number_field_with_paid_plan_use_text_field_for_phone_numbers_without_verification: 'Schalte das SMS-verifizierte Telefonnummernfeld mit einem kostenpflichtigen Plan frei. Verwende das Textfeld für Telefonnummern ohne Verifizierung.',
|
||||
available_only_in_pro: 'Nur in Pro verfügbar',
|
||||
failed_to_download_files: 'Fehler beim Herunterladen der Dateien',
|
||||
signature_is_too_small_please_redraw: 'Die Unterschrift ist zu klein. Bitte erneut zeichnen.',
|
||||
please_add_fields_for_the_submitter_name_or_remove_the_submitter_name_if_not_needed: 'Bitte füge Felder für {submitter_name} hinzu oder entferne {submitter_name}, falls nicht erforderlich.',
|
||||
draw_field: 'Feld {field} zeichnen',
|
||||
replace: 'Ersetzen',
|
||||
uploading_: 'Hochladen...',
|
||||
add_document: 'Hochladen',
|
||||
any: 'Jede',
|
||||
drawn: 'Gezeichnet',
|
||||
typed: 'Getippt',
|
||||
none: 'Keine',
|
||||
ssn: 'SSN',
|
||||
ein: 'EIN',
|
||||
email: 'E-Mail',
|
||||
url: 'URL',
|
||||
zip: 'ZIP',
|
||||
custom: 'Benutzerdefiniert',
|
||||
numbers_only: 'Nur Zahlen',
|
||||
letters_only: 'Nur Buchstaben',
|
||||
regexp_validation: 'Regulärer Ausdruck Überprüfung',
|
||||
enter_pdf_password: 'Geben Sie das PDF-Passwort ein',
|
||||
wrong_password: 'Falsches Passwort',
|
||||
currency: 'Währung',
|
||||
save_and_preview: 'Speichern und Vorschau',
|
||||
preferences: 'Einstellungen',
|
||||
available_in_pro: 'In Pro verfügbar',
|
||||
some_fields_are_missing_in_the_formula: 'Einige Felder fehlen in der Formel.',
|
||||
learn_more: 'Erfahren Sie mehr'
|
||||
}
|
||||
|
||||
export { en, es, it, pt, fr, de }
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div v-if="selectedSheetIndex === null && spreadsheet">
|
||||
<form @submit.prevent="[selectedSheetIndex = $refs.selectWorksheet.value, buildDefaultMappings()]">
|
||||
<label class="label">
|
||||
Select Worksheet
|
||||
{{ t('select_worksheet') }}
|
||||
</label>
|
||||
<select
|
||||
ref="selectWorksheet"
|
||||
@@ -18,7 +18,7 @@
|
||||
</option>
|
||||
</select>
|
||||
<button class="base-button mt-4 w-full">
|
||||
Open
|
||||
{{ t('open') }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -36,10 +36,10 @@
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="relative w-full py-2 px-2 text-sm">
|
||||
Recipient field
|
||||
{{ t('recipient_field') }}
|
||||
</div>
|
||||
<div class="relative w-full py-2 pl-4 text-sm">
|
||||
Spreadsheet column
|
||||
{{ t('spreadsheet_column') }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -58,7 +58,7 @@
|
||||
value=""
|
||||
:selected="!mapping.field_name"
|
||||
>
|
||||
Select Field
|
||||
{{ t('select_field') }}
|
||||
</option>
|
||||
<option
|
||||
v-for="(field, index) in selectFieldsForSubmitter(submitter)"
|
||||
@@ -83,7 +83,7 @@
|
||||
value=""
|
||||
:selected="mapping.column_index == null"
|
||||
>
|
||||
Select Column
|
||||
{{ t('select_column') }}
|
||||
</option>
|
||||
<template
|
||||
v-for="(column, index) in columns"
|
||||
@@ -118,8 +118,8 @@
|
||||
</div>
|
||||
<div class="flex items-center pl-1">
|
||||
<span
|
||||
class="tooltip tooltip-top"
|
||||
data-tip="<%= t('remove') %>"
|
||||
class="tooltip tooltip-left"
|
||||
:data-tip="t('remove')"
|
||||
>
|
||||
<button
|
||||
:disabled="mappings.filter((m) => m.submitter_uuid === submitter.uuid).length < 2"
|
||||
@@ -138,7 +138,7 @@
|
||||
@click.prevent="addMapping(submitter)"
|
||||
>
|
||||
<IconPlus class="w-4 h-4" />
|
||||
New Field Mapping
|
||||
{{ t('new_field_mapping') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -152,7 +152,7 @@
|
||||
<div
|
||||
class="px-3 border-y py-2 border-base-300 text-center w-full text-sm font-semibold"
|
||||
>
|
||||
Total entries: {{ submissionsData.length }}
|
||||
{{ t('total_entries') }}: {{ submissionsData.length }}
|
||||
<template v-if="multitenant && submissionsData.length >= 1000">
|
||||
/ 1000
|
||||
</template>
|
||||
@@ -187,10 +187,10 @@
|
||||
<div
|
||||
class="font-medium text-lg mb-1"
|
||||
>
|
||||
Upload CSV or XLSX Spreadsheet
|
||||
{{ t('upload_csv_or_xlsx_spreadsheet') }}
|
||||
</div>
|
||||
<div class="text-sm">
|
||||
<span class="font-medium">Click to Upload</span> or drag and drop files.
|
||||
<span class="font-medium">{{ t('click_to_upload') }}</span> {{ t('or_drag_and_drop_files') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -210,11 +210,11 @@
|
||||
</label>
|
||||
</div>
|
||||
<div class="text-center mt-2">
|
||||
Or <a
|
||||
{{ t('or') }} <a
|
||||
:download="`${template.name}.csv`"
|
||||
:href="`data:text/csv;base64,${csvBase64}`"
|
||||
class="link font-medium"
|
||||
>download</a> a spreadsheet to fill and import
|
||||
>{{ t('download') }}</a> {{ t('a_sample_spreadsheet_to_fill_and_import') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -248,6 +248,11 @@ export default {
|
||||
type: String,
|
||||
required: false,
|
||||
default: ''
|
||||
},
|
||||
i18n: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data () {
|
||||
@@ -354,6 +359,9 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
t (key) {
|
||||
return this.i18n[key] || key
|
||||
},
|
||||
onDropFiles (e) {
|
||||
this.uploadFile(e.dataTransfer.files[0])
|
||||
},
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
class="absolute -top-1 left-2.5 px-1 h-4"
|
||||
style="font-size: 8px"
|
||||
>
|
||||
Price
|
||||
{{ t('price') }}
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
|
||||
@@ -23,21 +23,23 @@ class SubmitterMailer < ApplicationMailer
|
||||
|
||||
reply_to = build_submitter_reply_to(@submitter)
|
||||
|
||||
subject =
|
||||
if @email_config || @subject
|
||||
ReplaceEmailVariables.call(@subject || @email_config.value['subject'], submitter:)
|
||||
elsif @submitter.with_signature_fields?
|
||||
I18n.t(:you_are_invited_to_sign_a_document)
|
||||
else
|
||||
I18n.t(:you_are_invited_to_submit_a_form)
|
||||
end
|
||||
I18n.with_locale(@current_account.locale) do
|
||||
subject =
|
||||
if @email_config || @subject
|
||||
ReplaceEmailVariables.call(@subject || @email_config.value['subject'], submitter:)
|
||||
elsif @submitter.with_signature_fields?
|
||||
I18n.t(:you_are_invited_to_sign_a_document)
|
||||
else
|
||||
I18n.t(:you_are_invited_to_submit_a_form)
|
||||
end
|
||||
|
||||
mail(
|
||||
to: @submitter.friendly_name,
|
||||
from: from_address_for_submitter(submitter),
|
||||
subject:,
|
||||
reply_to:
|
||||
)
|
||||
mail(
|
||||
to: @submitter.friendly_name,
|
||||
from: from_address_for_submitter(submitter),
|
||||
subject:,
|
||||
reply_to:
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def completed_email(submitter, user, to: nil)
|
||||
@@ -66,13 +68,15 @@ class SubmitterMailer < ApplicationMailer
|
||||
|
||||
assign_message_metadata('submitter_completed', @submitter)
|
||||
|
||||
subject =
|
||||
ReplaceEmailVariables.call(@subject.presence || I18n.t(:template_name_has_been_completed_by_submitters),
|
||||
submitter:)
|
||||
I18n.with_locale(@current_account.locale) do
|
||||
subject =
|
||||
ReplaceEmailVariables.call(@subject.presence || I18n.t(:template_name_has_been_completed_by_submitters),
|
||||
submitter:)
|
||||
|
||||
mail(from: from_address_for_submitter(submitter),
|
||||
to: to || (user.role == 'integration' ? user.friendly_name.sub(/\+\w+@/, '@') : user.friendly_name),
|
||||
subject:)
|
||||
mail(from: from_address_for_submitter(submitter),
|
||||
to: to || normalize_user_email(user),
|
||||
subject:)
|
||||
end
|
||||
end
|
||||
|
||||
def declined_email(submitter, user)
|
||||
@@ -83,7 +87,7 @@ class SubmitterMailer < ApplicationMailer
|
||||
|
||||
assign_message_metadata('submitter_declined', @submitter)
|
||||
|
||||
I18n.with_locale(submitter.account.locale) do
|
||||
I18n.with_locale(@current_account.locale) do
|
||||
mail(from: from_address_for_submitter(submitter),
|
||||
to: user.role == 'integration' ? user.friendly_name.sub(/\+\w+@/, '@') : user.friendly_name,
|
||||
reply_to: @submitter.friendly_name,
|
||||
@@ -116,17 +120,19 @@ class SubmitterMailer < ApplicationMailer
|
||||
assign_message_metadata('submitter_documents_copy', @submitter)
|
||||
reply_to = build_submitter_reply_to(submitter)
|
||||
|
||||
subject =
|
||||
if @subject.present?
|
||||
ReplaceEmailVariables.call(@subject, submitter:)
|
||||
else
|
||||
I18n.t(:your_document_copy)
|
||||
end
|
||||
I18n.with_locale(@current_account.locale) do
|
||||
subject =
|
||||
if @subject.present?
|
||||
ReplaceEmailVariables.call(@subject, submitter:)
|
||||
else
|
||||
I18n.t(:your_document_copy)
|
||||
end
|
||||
|
||||
mail(from: from_address_for_submitter(submitter),
|
||||
to: to || @submitter.friendly_name,
|
||||
reply_to:,
|
||||
subject:)
|
||||
mail(from: from_address_for_submitter(submitter),
|
||||
to: to || @submitter.friendly_name,
|
||||
reply_to:,
|
||||
subject:)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
@@ -171,6 +177,10 @@ class SubmitterMailer < ApplicationMailer
|
||||
documents
|
||||
end
|
||||
|
||||
def normalize_user_email(user)
|
||||
user.role == 'integration' ? user.friendly_name.sub(/\+\w+@/, '@') : user.friendly_name
|
||||
end
|
||||
|
||||
def add_attachments_with_size_limit(storage_attachments, current_size)
|
||||
total_size = current_size
|
||||
|
||||
|
||||
@@ -86,11 +86,11 @@ class Submitter < ApplicationRecord
|
||||
end
|
||||
|
||||
def first_name
|
||||
name.split(/\s+/, 2).first
|
||||
name&.split(/\s+/, 2)&.first
|
||||
end
|
||||
|
||||
def last_name
|
||||
name.split(/\s+/, 2).last
|
||||
name&.split(/\s+/, 2)&.last
|
||||
end
|
||||
|
||||
def status_event_at
|
||||
|
||||
@@ -46,7 +46,7 @@ class Template < ApplicationRecord
|
||||
attribute :preferences, :string, default: -> { {} }
|
||||
attribute :fields, :string, default: -> { [] }
|
||||
attribute :schema, :string, default: -> { [] }
|
||||
attribute :submitters, :string, default: -> { [{ name: DEFAULT_SUBMITTER_NAME, uuid: SecureRandom.uuid }] }
|
||||
attribute :submitters, :string, default: -> { [{ name: I18n.t(:first_party), uuid: SecureRandom.uuid }] }
|
||||
attribute :slug, :string, default: -> { SecureRandom.base58(14) }
|
||||
attribute :source, :string, default: 'native'
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= ff.label :locale, t('time_format'), class: 'label' %>
|
||||
<%= ff.select :locale, options_for_select(controller.class::LOCALE_OPTIONS.invert, current_account.locale), {}, class: 'base-select' %>
|
||||
<%= ff.label :locale, t('language'), class: 'label' %>
|
||||
<%= ff.select :locale, options_for_select(AccountsController::LOCALE_OPTIONS.invert, current_account.locale), {}, class: 'base-select' %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<div class="flex flex-wrap space-y-4 md:flex-nowrap md:space-y-0 md:space-x-10">
|
||||
<%= render 'shared/settings_nav' %>
|
||||
<div class="flex-grow">
|
||||
<div class="flex justify-between">
|
||||
<h1 class="text-4xl font-bold mb-4">API</h1>
|
||||
<div class="flex flex-col gap-2 md:flex-row md:justify-between md:items-end mb-4">
|
||||
<h1 class="text-4xl font-bold">API</h1>
|
||||
<%= render 'shared/test_mode_toggle' %>
|
||||
</div>
|
||||
<div class="card bg-base-200">
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<tr scope="row" class="group">
|
||||
<td class="flex items-center space-x-1">
|
||||
<%= svg_icon('discount_check_filled', class: 'w-6 h-6 text-green-500') %>
|
||||
<span class="flex items-center">
|
||||
<%= t('docuseal_trusted_signature') %>
|
||||
<div class="tooltip ml-1" data-tip="<%= t('sign_documents_with_trusted_certificate_provided_by_docu_seal_your_documents_and_data_are_never_shared_with_docu_seal_p_d_f_checksum_is_provided_to_generate_a_trusted_signature') %>">
|
||||
<%= svg_icon('circle_question', class: 'w-4 h-4 stroke-1') %>
|
||||
</div>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<a href="<%= "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premise" }.to_query}" %>" class="btn btn-neutral btn-sm text-white">
|
||||
<%= t('unlock_with_docuseal_pro') %>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<div class="tooltip" data-tip="<%= t('unlock_with_docuseal_pro') %>">
|
||||
<%= button_to settings_esign_path, method: :put, params: { name: Docuseal::AATL_CERT_NAME }, class: 'btn btn-outline btn-neutral btn-xs whitespace-nowrap', title: t('make_default'), disabled: true do %>
|
||||
<%= t('make_default') %>
|
||||
<% end %>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -7,7 +7,7 @@
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.label :file, t('file'), class: 'label' %>
|
||||
<%= f.file_field :file, required: true %>
|
||||
<%= f.file_field :file, class: 'file-input file-input-bordered w-full', required: true %>
|
||||
<label class="label">
|
||||
<span class="label-text-alt">
|
||||
<%= t('use_a_valid_der_p12_or_pfx_file') %>
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
<% end %>
|
||||
<file-dropzone data-name="verify_attachments" data-submit-on-upload="true" class="w-full">
|
||||
<label for="file" class="w-full block h-32 relative bg-base-200 hover:bg-base-200/70 rounded-md border border-base-content border-dashed">
|
||||
<div class="absolute top-0 right-0 left-0 bottom-0 flex items-center justify-center">
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="absolute top-0 right-0 left-0 bottom-0 flex items-center justify-center p-2">
|
||||
<div class="flex flex-col items-center text-center">
|
||||
<span data-target="file-dropzone.icon">
|
||||
<%= svg_icon('cloud_upload', class: 'w-10 h-10') %>
|
||||
</span>
|
||||
@@ -40,7 +40,7 @@
|
||||
</file-dropzone>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="flex justify-between items-end mb-4 mt-8">
|
||||
<div class="flex flex-col md:flex-row gap-2 md:justify-between md:items-end mb-4 mt-8">
|
||||
<h2 class="text-3xl font-bold">
|
||||
<%= t('signing_certificates') %>
|
||||
</h2>
|
||||
@@ -71,6 +71,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @pkcs_list.each do |item| %>
|
||||
<% next if item['pkcs'].blank? %>
|
||||
<tr scope="row" class="group">
|
||||
<td>
|
||||
<%= item['name'] %>
|
||||
@@ -98,6 +99,9 @@
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% unless Docuseal.multitenant? %>
|
||||
<%= render 'default_signature_row' %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<path d="M12.01 2.011a3.2 3.2 0 0 1 2.113 .797l.154 .145l.698 .698a1.2 1.2 0 0 0 .71 .341l.135 .008h1a3.2 3.2 0 0 1 3.195 3.018l.005 .182v1c0 .27 .092 .533 .258 .743l.09 .1l.697 .698a3.2 3.2 0 0 1 .147 4.382l-.145 .154l-.698 .698a1.2 1.2 0 0 0 -.341 .71l-.008 .135v1a3.2 3.2 0 0 1 -3.018 3.195l-.182 .005h-1a1.2 1.2 0 0 0 -.743 .258l-.1 .09l-.698 .697a3.2 3.2 0 0 1 -4.382 .147l-.154 -.145l-.698 -.698a1.2 1.2 0 0 0 -.71 -.341l-.135 -.008h-1a3.2 3.2 0 0 1 -3.195 -3.018l-.005 -.182v-1a1.2 1.2 0 0 0 -.258 -.743l-.09 -.1l-.697 -.698a3.2 3.2 0 0 1 -.147 -4.382l.145 -.154l.698 -.698a1.2 1.2 0 0 0 .341 -.71l.008 -.135v-1l.005 -.182a3.2 3.2 0 0 1 3.013 -3.013l.182 -.005h1a1.2 1.2 0 0 0 .743 -.258l.1 -.09l.698 -.697a3.2 3.2 0 0 1 2.269 -.944zm3.697 7.282a1 1 0 0 0 -1.414 0l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.32 1.497l2 2l.094 .083a1 1 0 0 0 1.32 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z" stroke-width="0" fill="currentColor" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -6,7 +6,7 @@
|
||||
<span>
|
||||
<%= t('completed_documents_notification_bcc_address') %>
|
||||
</span>
|
||||
<span class="tooltip" data-tip="Send email copy with completed documents to a specified BCC address.">
|
||||
<span class="tooltip" data-tip="<%= t('send_email_copy_with_completed_documents_to_a_specified_bcc_address') %>">
|
||||
<%= svg_icon('info_circle', class: 'w-4 h-4') %>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
@@ -3,22 +3,22 @@
|
||||
<div class="form-control">
|
||||
<% record = Struct.new(:first_duration, :second_duration, :third_duration).new(*(f.object.value || {}).values_at('first_duration', 'second_duration', 'third_duration')) %>
|
||||
<% durations = (Docuseal.multitenant? ? AccountConfigs::REMINDER_DURATIONS.except('one_hour', 'two_hours') : AccountConfigs::REMINDER_DURATIONS).keys.map { |v| [t(v.underscore), v] } %>
|
||||
<div class="flex flex-col md:flex-row gap-4">
|
||||
<div class="flex flex-col md:flex-row gap-2">
|
||||
<div class="w-full">
|
||||
<%= f.fields_for :value, record do |ff| %>
|
||||
<%= ff.label :first_duration, t('first_reminder_in'), class: 'label' %>
|
||||
<%= ff.label :first_duration, t('first_reminder_in'), class: 'label truncate' %>
|
||||
<%= ff.select :first_duration, durations, { include_blank: 'None' }, class: 'base-select' %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<%= f.fields_for :value, record do |ff| %>
|
||||
<%= ff.label :second_duration, t('second_reminder_in'), class: 'label' %>
|
||||
<%= ff.label :second_duration, t('second_reminder_in'), class: 'label truncate' %>
|
||||
<%= ff.select :second_duration, durations, { include_blank: 'None' }, class: 'base-select' %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<%= f.fields_for :value, record do |ff| %>
|
||||
<%= ff.label :third_duration, t('third_reminder_in'), class: 'label' %>
|
||||
<%= ff.label :third_duration, t('third_reminder_in'), class: 'label truncate' %>
|
||||
<%= ff.select :third_duration, durations, { include_blank: 'None' }, class: 'base-select' %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<input type="checkbox">
|
||||
<div class="collapse-title text-xl font-medium capitalize">
|
||||
<div>
|
||||
<%= t('copleted_notification_email') %>
|
||||
<%= t('completed_notification_email') %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
|
||||
@@ -56,6 +56,12 @@
|
||||
<%= ff.text_field :value, required: true, class: 'base-input' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= fields_for @account do |ff| %>
|
||||
<div class="form-control">
|
||||
<%= ff.label :locale, t('language'), class: 'label' %>
|
||||
<%= ff.select :locale, options_for_select(AccountsController::LOCALE_OPTIONS.invert, @account.locale), {}, class: 'base-select' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.button button_title, class: 'base-button' %>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<span class="peer-checked:hidden flex items-center space-x-2">
|
||||
<%= svg_icon(local_assigns[:icon] || 'link', class: local_assigns[:icon_class] || 'w-6 h-6 text-white') %>
|
||||
<span class="hidden md:inline">
|
||||
<%= local_assigns[:copy_title] || 'Copy' %>
|
||||
<%= local_assigns[:copy_title] || t('copy') %>
|
||||
</span>
|
||||
<% if local_assigns[:copy_title_md] %>
|
||||
<span class="inline md:hidden">
|
||||
@@ -15,7 +15,7 @@
|
||||
<span class="hidden peer-checked:flex items-center space-x-2">
|
||||
<%= svg_icon(local_assigns[:copied_icon] || 'clipboard_copy', class: local_assigns[:icon_class] || 'w-6 h-6 text-white') %>
|
||||
<span class="hidden md:inline">
|
||||
<%= local_assigns[:copied_title] || 'Copied' %>
|
||||
<%= local_assigns[:copied_title] || t('copied') %>
|
||||
</span>
|
||||
<% if local_assigns[:copied_title_md] %>
|
||||
<span class="inline md:hidden">
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
<%= yield %>
|
||||
</div>
|
||||
</div>
|
||||
<label class="modal-backdrop" for="<%= uuid %>"><%= t('close') %></label>
|
||||
<label class="modal-backdrop" for="<%= uuid %>"></label>
|
||||
</div>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<label tabindex="0" class="cursor-pointer bg-base-content text-purple-300 rounded-full p-2 w-9 justify-center flex">
|
||||
<span class="text-sm align-text-top"><%= current_user.initials %></span>
|
||||
</label>
|
||||
<ul tabindex="0" class="z-10 dropdown-content p-2 mt-2 shadow menu text-base bg-base-100 rounded-box w-40 text-right">
|
||||
<ul tabindex="0" class="z-10 dropdown-content p-2 mt-2 shadow menu text-base bg-base-100 rounded-box min-w-[160px] text-right">
|
||||
<li>
|
||||
<%= link_to settings_profile_index_path, class: 'flex items-center' do %>
|
||||
<%= svg_icon('adjustments', class: 'w-5 h-5 flex-shrink-0 stroke-2') %>
|
||||
@@ -36,7 +36,7 @@
|
||||
<% if !Docuseal.demo? && can?(:manage, EncryptedConfig) %>
|
||||
<li>
|
||||
<%= link_to Docuseal.multitenant? ? console_redirect_index_path : Docuseal::CONSOLE_URL, data: { prefetch: false }, class: 'flex items-center' do %>
|
||||
<%= svg_icon('terminal', class: 'w-5 h-5 stroke-2') %>
|
||||
<%= svg_icon('terminal', class: 'w-5 h-5 flex-shrink-0 stroke-2') %>
|
||||
<%= t('console') %>
|
||||
<% end %>
|
||||
</li>
|
||||
@@ -44,15 +44,15 @@
|
||||
<% if can?(:read, EncryptedConfig.new(key: EncryptedConfig::ESIGN_CERTS_KEY, account: current_account)) %>
|
||||
<li>
|
||||
<%= link_to settings_esign_path, class: 'flex items-center' do %>
|
||||
<%= svg_icon('zoom_check', class: 'w-5 h-5 stroke-2') %>
|
||||
<span class="mr-1"><%= t('verify_pdf') %></span>
|
||||
<%= svg_icon('zoom_check', class: 'w-5 h-5 flex-shrink-0 stroke-2') %>
|
||||
<span class="mr-1 whitespace-nowrap"><%= t('verify_pdf') %></span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<li>
|
||||
<%= button_to destroy_user_session_path, method: :delete, data: { turbo: false }, class: 'flex items-center' do %>
|
||||
<%= svg_icon('logout', class: 'w-5 h-5 stroke-2 mr-2 inline') %>
|
||||
<span class="mr-1"><%= t('sign_out') %></span>
|
||||
<%= svg_icon('logout', class: 'w-5 h-5 flex-shrink-0 stroke-2 mr-2 inline') %>
|
||||
<span class="mr-1 whitespace-nowrap"><%= t('sign_out') %></span>
|
||||
<% end %>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
<% else %>
|
||||
<%= t('powered_by') %>
|
||||
<% end %>
|
||||
<a href="<%= Docuseal::PRODUCT_URL %><%= local_assigns[:link_path] %>" class="underline"><%= Docuseal.product_name %></a> - open source documents software
|
||||
<a href="<%= Docuseal::PRODUCT_URL %><%= local_assigns[:link_path] %>" class="underline"><%= Docuseal.product_name %></a> - <%= t('open_source_documents_software') %>
|
||||
</div>
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
<% end %>
|
||||
<% if params[:q].present? %>
|
||||
<div class="relative">
|
||||
<a href="<%= url_for(params.to_unsafe_h.except(:q)) %>" title="Clear" class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-auto text-neutral text-2xl font-extralight">
|
||||
<a href="<%= url_for(params.to_unsafe_h.except(:q)) %>" title="<%= t('clear') %>" class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-auto text-neutral text-2xl font-extralight">
|
||||
×
|
||||
</a>
|
||||
</div>
|
||||
<% end %>
|
||||
<search-input data-title="<%= local_assigns[:title_selector] || 'h1' %>">
|
||||
<input id="search" name="q" value="<%= params[:q] %>" class="input input-ghost text-lg pr-10 -mr-12 w-0 md:w-64 <%= 'pl-8 input-outlined w-64' if params[:q].present? %>" placeholder="<%= local_assigns[:placeholder] %>">
|
||||
<input id="search" name="q" value="<%= params[:q] %>" class="input text-lg pr-10 -mr-12 w-0 md:w-60 <%= 'pl-8 input-outlined w-60' if params[:q].present? %>" placeholder="<%= local_assigns[:placeholder] %>">
|
||||
</search-input>
|
||||
<button type="submit" title="Search" class="btn btn-ghost btn-circle" onclick="window.search.value || document.activeElement === window.search ? null : [event.preventDefault(), window.search.focus()]">
|
||||
<button type="submit" title="<%= t('search') %>" class="btn btn-ghost btn-circle" onclick="window.search.value || document.activeElement === window.search ? null : [event.preventDefault(), window.search.focus()]">
|
||||
<span class="enabled">
|
||||
<%= svg_icon('search', class: 'w-6 h-6 stroke-2') %>
|
||||
</span>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="block w-full md:w-52 flex-none">
|
||||
<menu-active>
|
||||
<ul class="menu px-0">
|
||||
<li class="menu-title py-0 !bg-transparent mb-3 -mt-5"><a href="<%= '/' %>" class="!bg-transparent !text-neutral font-medium">← Back</a></li>
|
||||
<li class="menu-title py-0 !bg-transparent mb-3 -mt-5"><a href="<%= '/' %>" class="!bg-transparent !text-neutral font-medium">← <%= t('back') %></a></li>
|
||||
<li class="menu-title py-0 !bg-transparent">
|
||||
<span class="!bg-transparent"><%= t('settings') %></span>
|
||||
</li>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<% if signed_in? && current_user != true_user && current_account.testing? %>
|
||||
<div class="alert py-1 text-sm font-medium gap-x-2 flex whitespace-nowrap">
|
||||
<div class="hidden md:flex alert py-1 text-sm font-medium gap-x-2 whitespace-nowrap">
|
||||
<a href="<%= testing_api_settings_path %>" data-turbo-frame="modal" class="link font-semibold flex">
|
||||
<%= svg_icon('code_circle', class: 'w-5 h-5 mr-1') %>
|
||||
<span><%= t('testing_environment') %></span>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<% if can?(:manage, EncryptedConfig) || (current_user != true_user && current_account.testing?) %>
|
||||
<%= form_for '', url: testing_account_path, method: current_account.testing? ? :delete : :get, html: { class: 'flex' } do |f| %>
|
||||
<label class="flex items-center justify-between py-2.5" for="testing_toggle">
|
||||
<label class="flex items-center justify-between" for="testing_toggle">
|
||||
<span class="mr-2 text-lg">
|
||||
<%= t('test_environment') %>
|
||||
</span>
|
||||
|
||||
@@ -20,18 +20,18 @@
|
||||
<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-slim w-full', placeholder: 'Name', required: index.zero?, value: (params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : '', dir: 'auto', id: "detailed_name_#{item['uuid']}" %>
|
||||
<%= tag.input type: 'text', name: 'submission[1][submitters][][name]', autocomplete: 'off', class: 'base-input !h-10 w-full', placeholder: t('name'), required: index.zero?, value: (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-slim mt-1.5 w-full" placeholder="Email (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 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>
|
||||
<submitters-autocomplete data-field="phone">
|
||||
<linked-input data-target-id="<%= "detailed_phone_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||
<input type="tel" pattern="^\+[0-9\s\-]+$" oninvalid="this.value ? this.setCustomValidity('Use internatioanl format: +1xxx...') : ''" oninput="this.setCustomValidity('')" name="submission[1][submitters][][phone]" autocomplete="off" class="base-input-slim mt-1.5 w-full" placeholder="Phone (optional)" id="detailed_phone_<%= item['uuid'] %>">
|
||||
<input type="tel" pattern="^\+[0-9\s\-]+$" oninvalid="this.value ? this.setCustomValidity('Use internatioanl 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')} (#{t('optional')})" %>" id="detailed_phone_<%= item['uuid'] %>">
|
||||
</linked-input>
|
||||
</submitters-autocomplete>
|
||||
</div>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<input type="hidden" name="submission[1][submitters][][uuid]" value="<%= item['uuid'] %>">
|
||||
<submitters-autocomplete data-field="email">
|
||||
<linked-input data-target-id="<%= "email_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||
<%= tag.input type: 'email', multiple: true, name: 'submission[1][submitters][][email]', autocomplete: 'off', class: 'base-input-slim w-full', placeholder: t('email'), required: index.zero?, value: item['email'].presence || ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.email : ''), id: "email_#{item['uuid']}" %>
|
||||
<%= tag.input type: 'email', multiple: true, name: 'submission[1][submitters][][email]', autocomplete: 'off', class: 'base-input !h-10 w-full', placeholder: t('email'), required: index.zero?, value: item['email'].presence || ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.email : ''), id: "email_#{item['uuid']}" %>
|
||||
</linked-input>
|
||||
</submitters-autocomplete>
|
||||
</submitter-item>
|
||||
|
||||
@@ -21,13 +21,13 @@
|
||||
<input type="hidden" name="submission[1][submitters][][uuid]" value="<%= item['uuid'] %>">
|
||||
<submitters-autocomplete data-field="phone">
|
||||
<linked-input data-target-id="<%= "phone_phone_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||
<%= tag.input type: 'tel', pattern: '^\+[0-9\s\-]+$', oninvalid: "this.value ? this.setCustomValidity('Use internatioanl format: +1xxx...') : ''", oninput: "this.setCustomValidity('')", name: 'submission[1][submitters][][phone]', autocomplete: 'off', class: 'base-input-slim w-full', placeholder: t('phone'), required: index.zero?, id: "phone_phone_#{item['uuid']}" %>
|
||||
<%= tag.input type: 'tel', pattern: '^\+[0-9\s\-]+$', oninvalid: "this.value ? this.setCustomValidity('Use internatioanl format: +1xxx...') : ''", oninput: "this.setCustomValidity('')", name: 'submission[1][submitters][][phone]', autocomplete: 'off', class: 'base-input !h-10 w-full', placeholder: t('phone'), required: index.zero?, id: "phone_phone_#{item['uuid']}" %>
|
||||
</linked-input>
|
||||
</submitters-autocomplete>
|
||||
<% if submitters.size > 1 %>
|
||||
<submitters-autocomplete data-field="name">
|
||||
<linked-input data-target-id="<%= "phone_name_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||
<input type="text" name="submission[1][submitters][][name]" autocomplete="off" class="base-input-slim mt-1.5 w-full" placeholder="<%= "#{t('name')} (#{t('optional')})" %>" value="<%= (params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : '' %>" dir="auto" id="phone_name_<%= item['uuid'] %>">
|
||||
<input type="text" name="submission[1][submitters][][name]" autocomplete="off" class="base-input !h-10 mt-1.5 w-full" placeholder="<%= "#{t('name')} (#{t('optional')})" %>" value="<%= (params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : '' %>" dir="auto" id="phone_name_<%= item['uuid'] %>">
|
||||
</linked-input>
|
||||
</submitters-autocomplete>
|
||||
<% end %>
|
||||
@@ -36,7 +36,7 @@
|
||||
<div class="form-control flex">
|
||||
<submitters-autocomplete data-field="name">
|
||||
<linked-input data-target-id="<%= "phone_name_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||
<input type="text" name="submission[1][submitters][][name]" autocomplete="off" class="base-input-slim w-full" placeholder="<%= "#{t('name')} (#{t('optional')})" %>" value="<%= (params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : '' %>" dir="auto" id="phone_name_<%= item['uuid'] %>">
|
||||
<input type="text" name="submission[1][submitters][][name]" autocomplete="off" class="base-input !h-10 w-full" placeholder="<%= "#{t('name')} (#{t('optional')})" %>" value="<%= (params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : '' %>" dir="auto" id="phone_name_<%= item['uuid'] %>">
|
||||
</linked-input>
|
||||
</submitters-autocomplete>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<% if template.submitters.size > 1 %>
|
||||
<% if template.preferences['submitters_order'] == 'preserved' %>
|
||||
<%= f.hidden_field :preserve_order, value: '1' %>
|
||||
<% elsif template.submitters.size > 1 %>
|
||||
<div class="form-control">
|
||||
<%= f.label :preserve_order, for: uuid = SecureRandom.uuid, class: 'flex items-center cursor-pointer' do %>
|
||||
<%= f.check_box :preserve_order, id: uuid, class: 'base-checkbox', checked: template.submissions.last&.submitters_order.in?(['preserved', nil]) %>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<%= render 'shared/turbo_modal_large', title: params[:selfsign] ? t('add_recipients') : t('add_new_recipients') do %>
|
||||
<% options = [['via Email', 'email'], ['via Phone', 'phone'], %w[Detailed detailed], ['Upload List', 'list']].compact %>
|
||||
<% options = [[t('via_email'), 'email'], [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="join">
|
||||
<div class="flex justify-center">
|
||||
<% options.each_with_index do |(label, value), index| %>
|
||||
<span>
|
||||
<div>
|
||||
<%= radio_button_tag 'option', value, value == 'email', class: 'peer hidden', data: { action: 'change:toggle-visible#trigger' } %>
|
||||
<label for="option_<%= value %>" class="<%= '!rounded-s-full' if index.zero? %> btn btn-focus btn-sm join-item md:w-28 peer-checked:btn-active normal-case">
|
||||
<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>
|
||||
</span>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</toggle-visible>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<% end %>
|
||||
</div>
|
||||
<% elsif @submission.submitters.to_a.size == 1 && !@submission.expired? && !@submission.submitters.to_a.first.declined_at? %>
|
||||
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: @submission.submitters.to_a.first.slug), class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy Share Link', copied_title: 'Copied to Clipboard' %>
|
||||
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: @submission.submitters.to_a.first.slug), class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: t('copy_share_link'), copied_title: t('copied_to_clipboard') %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -144,7 +144,7 @@
|
||||
<% if submitter&.declined_at? %>
|
||||
<%= t('declined_on_time', time: l(submitter.declined_at.in_time_zone(@submission.account.timezone), format: :short, locale: @submission.account.locale)) %>
|
||||
<% elsif submitter %>
|
||||
<%= submitter.completed_at? ? l(submitter.completed_at.in_time_zone(@submission.account.timezone), format: :long, locale: @submission.account.locale) : t('not_copleted_yet') %>
|
||||
<%= submitter.completed_at? ? l(submitter.completed_at.in_time_zone(@submission.account.timezone), format: :long, locale: @submission.account.locale) : t('not_completed_yet') %>
|
||||
<% else %>
|
||||
<%= t('not_invited_yet') %>
|
||||
<% end %>
|
||||
@@ -153,14 +153,14 @@
|
||||
<% if submitter&.declined_at? %>
|
||||
<div class="flex items-center space-x-1 mt-1">
|
||||
<span>
|
||||
<%= t('Reason') %>:
|
||||
<%= t('reason') %>:
|
||||
<%= simple_format(h(submitter.submission_events.find_by(event_type: :decline_form).data['reason'])) %>
|
||||
</span>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if signed_in? && submitter && submitter.email && !submitter.completed_at && !@submission.archived_at? && can?(:update, submitter) && Accounts.can_send_emails?(current_account) && !@submission.expired? && !submitter.declined_at? %>
|
||||
<div class="mt-2 mb-1">
|
||||
<%= button_to button_title(title: submitter.sent_at? ? 'Re-send Email' : 'Send Email', disabled_with: t('sending')), submitter_send_email_index_path(submitter_slug: submitter.slug), class: 'btn btn-sm btn-primary w-full' %>
|
||||
<%= button_to button_title(title: submitter.sent_at? ? t('re_send_email') : t('send_email'), disabled_with: t('sending')), submitter_send_email_index_path(submitter_slug: submitter.slug), class: 'btn btn-sm btn-primary w-full' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if signed_in? && submitter && submitter.phone && !submitter.completed_at && !@submission.archived_at? && can?(:update, submitter) && !@submission.expired? && !submitter.declined_at? %>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<% is_show_tabs = @pagy.count >= 5 || params[:status].present? %>
|
||||
<% if Docuseal.demo? %><%= render 'shared/demo_alert' %><% end %>
|
||||
<div class="flex justify-between mb-4 items-center">
|
||||
<div class="flex items-center">
|
||||
<div class="flex justify-between items-center w-full mb-4">
|
||||
<div class="flex items-center flex-grow min-w-0">
|
||||
<div class="mr-2">
|
||||
<%= render 'dashboard/toggle_view', selected: 'submissions' %>
|
||||
</div>
|
||||
<h1 class="text-2xl md:text-3xl sm:text-4xl font-bold md:block <%= 'hidden' if params[:q].present? %>">
|
||||
<h1 class="text-2xl truncate md:text-3xl sm:text-4xl font-bold md:block <%= 'hidden' if params[:q].present? %>">
|
||||
<%= t('submissions') %>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<%= render 'shared/turbo_modal', title: 'Export', close_after_submit: false do %>
|
||||
<%= render 'shared/turbo_modal', title: t('export'), close_after_submit: false do %>
|
||||
<div class="space-y-2">
|
||||
<%= button_to template_submissions_export_index_path(@template), params: { format: :xlsx }, method: :get, data: { turbo_frame: :_top } do %>
|
||||
<div class="flex items-center p-4 text-left rounded-2xl border border-neutral-300 hover:cursor-pointer hover:bg-neutral hover:text-gray-300">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<% 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 %>
|
||||
<% 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-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] %>"></submission-form>
|
||||
<submission-form data-is-demo="<%= Docuseal.demo? %>" 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>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<div class="max-w-md mx-auto px-2 mt-12 mb-4">
|
||||
<div class="space-y-6 mx-auto">
|
||||
<div class="space-y-6">
|
||||
<div class="flex items-center justify-center">
|
||||
<%= render 'start_form/banner' %>
|
||||
</div>
|
||||
<div class="flex items-center bg-base-200 rounded-xl p-4 mb-4">
|
||||
<div class="flex items-center">
|
||||
<div class="mr-3">
|
||||
<%= svg_icon('writing_sign', class: 'w-10 h-10') %>
|
||||
</div>
|
||||
<div dir="auto">
|
||||
<p class="text-lg font-bold mb-1"><%= @submitter.submission.template.name %></p>
|
||||
<p class="text-sm"><%= t('awaiting_completion_by_the_other_party') %></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%= render 'shared/attribution', link_path: '/start', account: @submitter.account %>
|
||||
@@ -4,10 +4,10 @@
|
||||
<span><%= t('home') %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="flex justify-between mb-4 items-center">
|
||||
<h1 class="text-4xl font-bold flex items-center space-x-2 md:flex <%= 'hidden' if params[:q].present? %>">
|
||||
<div class="flex justify-between items-center w-full mb-4">
|
||||
<h1 class="text-4xl font-bold flex flex-grow min-w-0 space-x-2 md:flex <%= 'hidden' if params[:q].present? %>">
|
||||
<%= svg_icon('folder', class: 'w-9 h-9 flex-shrink-0') %>
|
||||
<span class="peer">
|
||||
<span class="peer truncate">
|
||||
<%= @template_folder.name %>
|
||||
</span>
|
||||
<% if can?(:update, @template_folder) && @template_folder.name != TemplateFolder::DEFAULT_NAME %>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<button type="submit" class="hidden"></button>
|
||||
<file-dropzone data-submit-on-upload="true" class="w-full">
|
||||
<label for="file_dropzone_input" class="w-full block h-52 relative hover:bg-base-200/30 rounded-xl border border-2 border-base-300 border-dashed">
|
||||
<div class="absolute top-0 right-0 left-0 bottom-0 flex items-center justify-center">
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="absolute top-0 right-0 left-0 bottom-0 flex items-center justify-center p-2">
|
||||
<div class="flex flex-col items-center text-center">
|
||||
<span data-target="file-dropzone.icon" class="flex flex-col items-center">
|
||||
<span>
|
||||
<%= svg_icon('cloud_upload', class: 'w-10 h-10') %>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<% else %>
|
||||
<div class="tooltip flex" data-tip="<%= l(submitter.status_event_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %>">
|
||||
<span class="badge <%= status_badges[submitter.status] %> md:w-32 badge-lg bg-opacity-50 uppercase text-sm font-semibold">
|
||||
<%= submitter.status %>
|
||||
<%= t(submitter.status) %>
|
||||
</span>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -58,7 +58,7 @@
|
||||
<form onsubmit="event.preventDefault()" class="flex-1 md:flex-none">
|
||||
<button onclick="event.stopPropagation()" class="w-full md:w-fit">
|
||||
<download-button data-src="<%= submitter_download_index_path(submitter.slug) %>" class="btn btn-sm btn-neutral text-white w-full md:w-36">
|
||||
<span class="flex items-center justify-center space-x-1 md:space-x-2" data-target="download-button.defaultButton">
|
||||
<span class="flex items-center justify-center space-x-1 <%= 'md:space-x-2' if t('download').length < 11 %>" data-target="download-button.defaultButton">
|
||||
<%= svg_icon('download', class: 'w-5 h-5 stroke-2') %>
|
||||
<span class="inline"><%= t('download') %></span>
|
||||
</span>
|
||||
@@ -74,14 +74,16 @@
|
||||
<form data-turbo="false" method="get" action="<%= submit_form_url(slug: submitter.slug) %>" class="flex-1 md:flex-none">
|
||||
<button onclick="event.stopPropagation()" class="btn btn-sm btn-neutral btn-outline bg-white w-full md:w-36 flex">
|
||||
<span class="flex items-center justify-center space-x-1 md:space-x-2">
|
||||
<%= svg_icon('writing_sign', class: 'w-4 h-4 stroke-2') %>
|
||||
<% if t('sign_now').length < 12 %>
|
||||
<%= svg_icon('writing_sign', class: 'w-4 h-4 stroke-2') %>
|
||||
<% end %>
|
||||
<span class="inline shrink-0"><%= t('sign_now') %></span>
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
<% else %>
|
||||
<div class="flex-1 md:flex-none">
|
||||
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: submitter.slug), class: 'btn btn-sm btn-neutral text-white md:w-36 flex', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy Link', copy_title_md: t('copy'), copied_title_md: t('copied') %>
|
||||
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: submitter.slug), class: 'btn btn-sm btn-neutral text-white md:w-36 flex', icon_class: 'w-6 h-6 text-white', copy_title: t('copy_link').length < 10 ? t('copy_link') : t('copy'), copy_title_md: t('copy'), copied_title_md: t('copied') %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
@@ -106,7 +108,7 @@
|
||||
<% latest_submitter = submitters.select(&:completed_at?).max_by(&:completed_at) %>
|
||||
<div class="tooltip flex" data-tip="<%= l(latest_submitter.status_event_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %>">
|
||||
<span class="badge <%= status_badges[latest_submitter.status] %> md:w-32 bg-opacity-50 badge-lg uppercase text-sm font-semibold">
|
||||
<%= latest_submitter.status %>
|
||||
<%= t(latest_submitter.status) %>
|
||||
</span>
|
||||
</div>
|
||||
<% elsif submission.expired? %>
|
||||
@@ -123,7 +125,7 @@
|
||||
<% if !is_submission_completed && !submission.expired? %>
|
||||
<div class="tooltip flex" data-tip="<%= l(submitter.status_event_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %>">
|
||||
<span class="badge md:w-24 <%= status_badges[submitter.status] %> bg-opacity-50 uppercase text-xs font-semibold">
|
||||
<%= submitter.status %>
|
||||
<%= t(submitter.status) %>
|
||||
</span>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -152,13 +154,15 @@
|
||||
<form data-turbo="false" method="get" action="<%= submit_form_url(slug: submitter.slug) %>">
|
||||
<button onclick="event.stopPropagation()" class="absolute md:relative top-0 right-0 btn btn-xs btn-outline btn-neutral bg-white w-28 md:w-36">
|
||||
<span class="flex items-center justify-center space-x-1 md:space-x-2">
|
||||
<%= svg_icon('writing_sign', class: 'w-4 h-4 stroke-2') %>
|
||||
<% if t('sign_now').length < 12 %>
|
||||
<%= svg_icon('writing_sign', class: 'w-4 h-4 stroke-2') %>
|
||||
<% end %>
|
||||
<span class="inline shrink-0"><%= t('sign_now') %></span>
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
<% else %>
|
||||
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: submitter.slug), class: 'absolute md:relative top-0 right-0 btn btn-xs text-xs btn-neutral text-white w-28 md:w-36 flex', icon_class: 'w-4 h-4 text-white', copy_title: 'Copy Link', copy_title_md: 'Copy Link', copied_title_md: t('copied') %>
|
||||
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: submitter.slug), class: 'absolute md:relative top-0 right-0 btn btn-xs text-xs btn-neutral text-white w-28 md:w-36 flex', icon_class: 'w-4 h-4 text-white', copy_title: t('copy_link'), copy_title_md: t('copy_link').length < 10 ? t('copy_link') : t('copy'), copied_title_md: t('copied') %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -172,8 +176,8 @@
|
||||
<% latest_submitter = submitters.select(&:completed_at?).max_by(&:completed_at) %>
|
||||
<div class="flex-1 md:flex-none">
|
||||
<form onsubmit="event.preventDefault()" class="w-full md:w-fit">
|
||||
<button onclick="event.stopPropagation()">
|
||||
<download-button data-src="<%= submitter_download_index_path(latest_submitter.slug) %>" class="btn btn-sm btn-neutral text-white md:w-36">
|
||||
<button onclick="event.stopPropagation()" class="w-full">
|
||||
<download-button data-src="<%= submitter_download_index_path(latest_submitter.slug) %>" class="btn btn-sm btn-neutral text-white w-full md:w-36">
|
||||
<span class="flex items-center justify-center space-x-1 md:space-x-2" data-target="download-button.defaultButton">
|
||||
<%= svg_icon('download', class: 'w-5 h-5 stroke-2') %>
|
||||
<span class="inline"><%= t('download') %></span>
|
||||
|
||||
@@ -46,11 +46,11 @@
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= render 'shared/clipboard_copy', text: start_form_url(slug: @template.slug), class: 'absolute md:relative bottom-0 right-0 btn btn-xs md:btn-sm whitespace-nowrap btn-neutral text-white mt-1 px-2', icon_class: 'w-4 h-4 md:w-6 md:h-6 text-white', copy_title: 'Link', copied_title: t('copied'), copy_title_md: 'Link', copied_title_md: t('copied') %>
|
||||
<%= render 'shared/clipboard_copy', text: start_form_url(slug: @template.slug), class: 'absolute md:relative bottom-0 right-0 btn btn-xs md:btn-sm whitespace-nowrap btn-neutral text-white mt-1 px-2', icon_class: 'w-4 h-4 md:w-6 md:h-6 text-white', copy_title: t('link'), copied_title: t('copied'), copy_title_md: t('link'), copied_title_md: t('copied') %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="flex space-x-2 w-full md:w-fit md:justify-between md:flex-none md:pt-1">
|
||||
<div class="flex flex-wrap gap-2 w-full md:w-fit md:justify-between md:flex-none md:pt-1">
|
||||
<% if !template.archived_at? && can?(:destroy, template) %>
|
||||
<%= button_to button_title(title: t('archive'), disabled_with: t('archiving'), title_class: 'inline', icon: svg_icon('archive', class: 'w-6 h-6')), template_path(template), class: 'btn btn-outline btn-sm w-full', form_class: 'flex-1', method: :delete, data: { turbo_confirm: t('are_you_sure_') } %>
|
||||
<% end %>
|
||||
|
||||
@@ -1 +1 @@
|
||||
<template-builder class="grid" data-template="<%= @template_data %>" data-with-sign-yourself-button="<%= !@template.archived_at? %>" data-with-send-button="<%= !@template.archived_at? && can?(:create, @template.submissions.new(account: current_account)) %>" data-locale="<%= current_account.locale %>"></template-builder>
|
||||
<template-builder class="grid" data-template="<%= @template_data %>" data-with-sign-yourself-button="<%= !@template.archived_at? %>" data-with-send-button="<%= !@template.archived_at? && can?(:create, @template.submissions.new(account: current_account)) %>" data-locale="<%= I18n.locale %>"></template-builder>
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
<% if @base_template %>
|
||||
<%= hidden_field_tag :base_template_id, @base_template.id %>
|
||||
<% end %>
|
||||
<% if @base_template && (can?(:manage, :tenants) || true_user != current_user) && true_user.account.linked_accounts.active.exists? %>
|
||||
<% if @base_template && (can?(:manage, :tenants) || true_user != current_user) && true_user.account.linked_accounts.active.accessible_by(current_ability).exists? %>
|
||||
<div class="form-control -mb-2 mt-2">
|
||||
<%= select_tag :account_id, options_for_select([true_user.account, *true_user.account.linked_accounts.active].uniq.map { |e| [e.name, e.id] }, current_account.id), required: true, class: 'base-select' %>
|
||||
<%= select_tag :account_id, options_for_select([true_user.account, *true_user.account.linked_accounts.active.accessible_by(current_ability)].uniq.map { |e| [e.name, e.id] }, current_account.id), required: true, class: 'base-select' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="form-control mt-6">
|
||||
@@ -23,7 +23,7 @@
|
||||
</folder-autocomplete>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.button button_title(title: @base_template ? 'Submit' : 'Create', disabled_with: 'Creating'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: @base_template ? t('submit') : t('create'), disabled_with: t('creating')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="card bg-base-200">
|
||||
<div class="card-body text-center py-16">
|
||||
<div class="card-body text-center px-4 py-16">
|
||||
<div class="max-w-lg mx-auto">
|
||||
<p class="text-3xl font-bold text-base-content mb-4">
|
||||
<%= t('there_are_no_submissions') %>
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
<% has_archived = current_account.templates.where.not(archived_at: nil).exists? %>
|
||||
<% if Docuseal.demo? %><%= render 'shared/demo_alert' %><% end %>
|
||||
<div class="flex justify-between mb-4 items-center">
|
||||
<div class="flex items-center">
|
||||
<div class="flex justify-between items-center w-full mb-4">
|
||||
<div class="flex items-center flex-grow min-w-0">
|
||||
<% if has_archived || @pagy.count > 0 %>
|
||||
<div class="mr-2">
|
||||
<%= render 'dashboard/toggle_view', selected: 'templates' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<h1 class="text-2xl md:text-3xl sm:text-4xl font-bold md:block <%= 'hidden' if params[:q].present? %>"><%= t('document_templates_html') %></h1>
|
||||
<h1 class="text-2xl truncate md:text-3xl sm:text-4xl font-bold md:block <%= 'hidden' if params[:q].present? %>">
|
||||
<%= t('document_templates_html') %>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="flex space-x-2">
|
||||
<% if params[:q].present? || @pagy.pages > 1 || @template_folders.present? %>
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
<div class="collapse collapse-arrow join-item border border-base-300">
|
||||
<input type="checkbox" name="accordion">
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
<%= t('copleted_notification_email') %>
|
||||
<%= t('completed_notification_email') %>
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
<%= form_for @template, url: template_preferences_path(@template), method: :post, html: { autocomplete: 'off', class: 'mt-1' }, data: { close_on_submit: false } do |f| %>
|
||||
@@ -256,10 +256,20 @@
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="form-control mt-6 pb-2">
|
||||
<%= f.button button_title(title: t('save'), disabled_with: t('updating')), class: 'base-button' %>
|
||||
<% end %>
|
||||
<%= form_for @template, url: template_preferences_path(@template), method: :post, html: { autocomplete: 'off', class: 'mt-2' }, data: { close_on_submit: false } do |f| %>
|
||||
<div class="flex items-center pt-4 mt-4 justify-between border-t w-full">
|
||||
<span>
|
||||
<%= t('enforce_recipients_order') %>
|
||||
</span>
|
||||
<%= f.fields_for :preferences, Struct.new(:submitters_order).new(@template.preferences['submitters_order']) do |ff| %>
|
||||
<%= ff.check_box :submitters_order, { class: 'toggle', onchange: 'this.form.requestSubmit()' }, 'preserved', '' %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="form-control mt-5 pb-2">
|
||||
<%= button_tag button_title(title: t('save'), disabled_with: t('updating')), class: 'base-button', form: :submitters_form %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if show_api %>
|
||||
@@ -285,7 +295,7 @@
|
||||
<%= render 'templates_code_modal/placeholder' %>
|
||||
<%= render 'templates/embedding', template: @template %>
|
||||
<% if can?(:manage, TemplateSharing.new(template: @template)) %>
|
||||
<%= form_for '', url: template_sharings_testing_index_path, method: :post, html: { class: 'mt-1' } do |f| %>
|
||||
<%= form_for '', url: template_sharings_testing_index_path, method: :post, html: { class: 'mt-1' }, data: { close_on_submit: false } do |f| %>
|
||||
<%= f.hidden_field :template_id, value: @template.id %>
|
||||
<div class="flex items-center justify-between">
|
||||
<span>
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
<%= form_for @user_config, url: user_initials_path, method: :put, data: { turbo_frame: :_top }, html: { autocomplete: :off, enctype: 'multipart/form-data' } do |f| %>
|
||||
<file-dropzone data-submit-on-upload="true" class="w-full">
|
||||
<label for="file" class="w-full block h-32 relative bg-base-200 hover:bg-base-200/70 rounded-md border border-base-content border-dashed">
|
||||
<div class="absolute top-0 right-0 left-0 bottom-0 flex items-center justify-center">
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="absolute top-0 right-0 left-0 bottom-0 flex items-center justify-center p-2">
|
||||
<div class="flex flex-col items-center text-center">
|
||||
<span data-target="file-dropzone.icon">
|
||||
<%= svg_icon('cloud_upload', class: 'w-10 h-10') %>
|
||||
</span>
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
<%= form_for @user_config, url: user_signature_path, method: :put, data: { turbo_frame: :_top }, html: { autocomplete: :off, enctype: 'multipart/form-data' } do |f| %>
|
||||
<file-dropzone data-submit-on-upload="true" class="w-full">
|
||||
<label for="file" class="w-full block h-32 relative bg-base-200 hover:bg-base-200/70 rounded-md border border-base-content border-dashed">
|
||||
<div class="absolute top-0 right-0 left-0 bottom-0 flex items-center justify-center">
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="absolute top-0 right-0 left-0 bottom-0 flex items-center justify-center p-2">
|
||||
<div class="flex flex-col items-center text-center">
|
||||
<span data-target="file-dropzone.icon">
|
||||
<%= svg_icon('cloud_upload', class: 'w-10 h-10') %>
|
||||
</span>
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<div class="flex-wrap space-y-4 md:flex md:flex-nowrap md:space-y-0 md:space-x-10">
|
||||
<%= render 'shared/settings_nav' %>
|
||||
<div class="md:flex-grow">
|
||||
<div class="flex justify-between mb-4">
|
||||
<div class="flex flex-col md:flex-row gap-2 md:justify-between md:items-end mb-4">
|
||||
<h1 class="text-4xl font-bold">
|
||||
<%= t('status_users', status: params[:status].to_s.titleize) %>
|
||||
</h1>
|
||||
<div class="flex items-center space-x-4">
|
||||
<div class="flex flex-col md:flex-row gap-y-2 gap-x-4 md:items-center">
|
||||
<% if can?(:create, User.new(account: current_account)) %>
|
||||
<%= render 'users/extra_buttons' %>
|
||||
<% if content_for(:add_user_button) %>
|
||||
<%= content_for(:add_user_button) %>
|
||||
<% else %>
|
||||
<%= link_to new_user_path, class: 'btn btn-primary btn-md gap-2', data: { turbo_frame: 'modal' } do %>
|
||||
<%= link_to new_user_path, class: 'btn btn-primary btn-md gap-2 w-full md:w-fit', data: { turbo_frame: 'modal' } do %>
|
||||
<%= svg_icon('plus', class: 'w-6 h-6') %>
|
||||
<span><%= t('new_user') %></span>
|
||||
<% end %>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<div class="flex flex-wrap space-y-4 md:flex-nowrap md:space-y-0 md:space-x-10">
|
||||
<%= render 'shared/settings_nav' %>
|
||||
<div class="flex-grow">
|
||||
<div class="flex justify-between">
|
||||
<h1 class="text-4xl font-bold mb-4">Webhooks</h1>
|
||||
<div class="flex flex-col gap-2 md:flex-row md:justify-between md:items-end mb-4">
|
||||
<h1 class="text-4xl font-bold">Webhooks</h1>
|
||||
<%= render 'shared/test_mode_toggle' %>
|
||||
</div>
|
||||
<div class="card bg-base-200">
|
||||
@@ -19,7 +19,7 @@
|
||||
<% end %>
|
||||
<% preference = current_account.account_configs.find_by(key: AccountConfig::WEBHOOK_PREFERENCES_KEY)&.value || {} %>
|
||||
<% WebhookPreferencesController::EVENTS.group_by { |e| e.include?('form') }.each do |_, events| %>
|
||||
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 mt-2 gap-y-2">
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 mt-2 gap-y-2">
|
||||
<% events.each do |event| %>
|
||||
<%= form_for '', url: webhook_preferences_path, method: :post do |f| %>
|
||||
<%= f.hidden_field :event, value: event %>
|
||||
@@ -43,7 +43,7 @@
|
||||
<div class="space-y-4 mt-4">
|
||||
<div class="collapse collapse-open bg-base-200 px-1">
|
||||
<div class="p-4 text-xl font-medium">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<span>
|
||||
<%= t('submission_example_payload') %>
|
||||
</span>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+8
-2
@@ -118,7 +118,11 @@ module Accounts
|
||||
end
|
||||
|
||||
if (default_cert = cert_data['custom']&.find { |e| e['status'] == 'default' })
|
||||
OpenSSL::PKCS12.new(Base64.urlsafe_decode64(default_cert['data']), default_cert['password'].to_s)
|
||||
if default_cert['name'] == Docuseal::AATL_CERT_NAME
|
||||
Docuseal.default_pkcs
|
||||
else
|
||||
OpenSSL::PKCS12.new(Base64.urlsafe_decode64(default_cert['data']), default_cert['password'].to_s)
|
||||
end
|
||||
else
|
||||
GenerateCertificate.load_pkcs(cert_data)
|
||||
end
|
||||
@@ -153,7 +157,9 @@ module Accounts
|
||||
|
||||
default_pkcs = GenerateCertificate.load_pkcs(cert_data)
|
||||
|
||||
custom_certs = cert_data.fetch('custom', []).map do |e|
|
||||
custom_certs = cert_data.fetch('custom', []).filter_map do |e|
|
||||
next if e['data'].blank?
|
||||
|
||||
OpenSSL::PKCS12.new(Base64.urlsafe_decode64(e['data']), e['password'].to_s)
|
||||
end
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ module Docuseal
|
||||
CHATGPT_URL = 'https://chatgpt.com/g/g-9hg8AAw0r-docuseal'
|
||||
SUPPORT_EMAIL = 'support@docuseal.co'
|
||||
HOST = ENV.fetch('HOST', 'localhost')
|
||||
AATL_CERT_NAME = 'docuseal_aatl'
|
||||
CONSOLE_URL = if Rails.env.development?
|
||||
'http://console.localhost.io:3001'
|
||||
elsif ENV['MULTITENANT'] == 'true'
|
||||
|
||||
@@ -43,9 +43,11 @@ module Submissions
|
||||
|
||||
document.trailer.info[:Creator] = "#{Docuseal.product_name} (#{Docuseal::PRODUCT_URL})"
|
||||
|
||||
last_submitter = submission.submitters.select(&:completed_at).max_by(&:completed_at)
|
||||
|
||||
sign_params = {
|
||||
reason: sign_reason,
|
||||
**Submissions::GenerateResultAttachments.build_signing_params(pkcs, tsa_url)
|
||||
**Submissions::GenerateResultAttachments.build_signing_params(last_submitter, pkcs, tsa_url)
|
||||
}
|
||||
|
||||
document.sign(io, **sign_params)
|
||||
@@ -170,7 +172,7 @@ module Submissions
|
||||
|
||||
composer.draw_box(divider)
|
||||
|
||||
last_submitter = submission.submitters.where.not(completed_at: nil).order(:completed_at).last
|
||||
last_submitter = submission.submitters.select(&:completed_at).max_by(&:completed_at)
|
||||
|
||||
documents_data = Submitters.select_attachments_for_download(last_submitter).map do |document|
|
||||
original_documents = submission.template.documents.select do |e|
|
||||
|
||||
@@ -19,7 +19,7 @@ module Submissions
|
||||
|
||||
sign_params = {
|
||||
reason: sign_reason,
|
||||
**Submissions::GenerateResultAttachments.build_signing_params(pkcs, tsa_url)
|
||||
**Submissions::GenerateResultAttachments.build_signing_params(submitter, pkcs, tsa_url)
|
||||
}
|
||||
|
||||
pdf.sign(io, **sign_params)
|
||||
|
||||
@@ -454,7 +454,7 @@ module Submissions
|
||||
if sign_reason
|
||||
sign_params = {
|
||||
reason: sign_reason,
|
||||
**build_signing_params(pkcs, tsa_url)
|
||||
**build_signing_params(submitter, pkcs, tsa_url)
|
||||
}
|
||||
|
||||
begin
|
||||
@@ -491,7 +491,7 @@ module Submissions
|
||||
io
|
||||
end
|
||||
|
||||
def build_signing_params(pkcs, tsa_url)
|
||||
def build_signing_params(_submitter, pkcs, tsa_url)
|
||||
params = {
|
||||
certificate: pkcs.certificate,
|
||||
key: pkcs.key,
|
||||
|
||||
+11
-1
@@ -27,7 +27,7 @@ module Submitters
|
||||
return [submitter.submission.combined_document_attachment]
|
||||
end
|
||||
|
||||
original_documents = submitter.submission.template.documents.preload(:blob)
|
||||
original_documents = submitter.submission.template_schema_documents.preload(:blob)
|
||||
is_more_than_two_images = original_documents.count(&:image?) > 1
|
||||
|
||||
submitter.documents.preload(:blob).reject do |attachment|
|
||||
@@ -102,4 +102,14 @@ module Submitters
|
||||
SendSubmitterInvitationEmailJob.perform_async('submitter_id' => submitter.id)
|
||||
end
|
||||
end
|
||||
|
||||
def current_submitter_order?(submitter)
|
||||
submitter_items = submitter.submission.template_submitters || submitter.submission.template.submitters
|
||||
|
||||
before_items = submitter_items[0...(submitter_items.find_index { |e| e['uuid'] == submitter.uuid })]
|
||||
|
||||
before_items.reduce(true) do |acc, item|
|
||||
acc && submitter.submission.submitters.find { |e| e.uuid == item['uuid'] }&.completed_at?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -35,7 +35,7 @@ Capybara.register_driver(:headful_cuprite) do |app|
|
||||
js_errors: true)
|
||||
end
|
||||
|
||||
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
|
||||
Rails.root.glob('spec/support/**/*.rb').each { |f| require f }
|
||||
|
||||
begin
|
||||
ActiveRecord::Migration.maintain_test_schema!
|
||||
|
||||
@@ -16,7 +16,7 @@ RSpec.describe 'Account Settings' do
|
||||
expect(page).to have_content('Account')
|
||||
expect(page).to have_field('Company name', with: account.name)
|
||||
expect(page).to have_field('Time zone', with: account.timezone)
|
||||
expect(page).to have_field('Time format', with: account.locale)
|
||||
expect(page).to have_field('Language', with: account.locale)
|
||||
expect(page).to have_field('App URL', with: encrypted_config.value)
|
||||
end
|
||||
|
||||
@@ -24,7 +24,7 @@ RSpec.describe 'Account Settings' do
|
||||
fill_in 'Company name', with: 'New Company Name'
|
||||
fill_in 'App URL', with: 'https://example.com'
|
||||
select '(GMT+01:00) Berlin', from: 'Time zone'
|
||||
select 'Spanish (Spain)', from: 'Time format'
|
||||
select 'Español', from: 'Language'
|
||||
|
||||
click_button 'Update'
|
||||
|
||||
@@ -36,4 +36,21 @@ RSpec.describe 'Account Settings' do
|
||||
expect(account.locale).to eq('es-ES')
|
||||
expect(encrypted_config.value).to eq('https://example.com')
|
||||
end
|
||||
|
||||
it 'changes the account language' do
|
||||
select 'Deutsch', from: 'Language'
|
||||
|
||||
click_button 'Update'
|
||||
|
||||
account.reload
|
||||
encrypted_config.reload
|
||||
|
||||
expect(account.locale).to eq('de-DE')
|
||||
expect(page).to have_content('Konto')
|
||||
expect(page).to have_field('Firmenname', with: account.name)
|
||||
expect(page).to have_field('Zeitzone', with: account.timezone)
|
||||
expect(page).to have_field('Sprache', with: account.locale)
|
||||
expect(page).to have_field('App-URL', with: encrypted_config.value)
|
||||
expect(page).to have_button('Aktualisieren')
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user