Merge from docusealco/wip

pull/555/merge 2.4.2
Alex Turchyn 1 month ago committed by GitHub
commit 4486f8040e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -10,7 +10,7 @@ RUN apk --no-cache add fontforge wget && \
wget https://github.com/Maxattax97/gnu-freefont/raw/master/ttf/FreeSans.ttf && \ wget https://github.com/Maxattax97/gnu-freefont/raw/master/ttf/FreeSans.ttf && \
wget https://github.com/impallari/DancingScript/raw/master/OFL.txt && \ wget https://github.com/impallari/DancingScript/raw/master/OFL.txt && \
wget -O /model.onnx "https://github.com/docusealco/fields-detection/releases/download/2.0.0/model_704_int8.onnx" && \ wget -O /model.onnx "https://github.com/docusealco/fields-detection/releases/download/2.0.0/model_704_int8.onnx" && \
wget -O pdfium-linux.tgz "https://github.com/docusealco/pdfium-binaries/releases/latest/download/pdfium-linux-$(uname -m | sed 's/x86_64/x64/;s/aarch64/arm64/').tgz" && \ wget -O pdfium-linux.tgz "https://github.com/bblanchon/pdfium-binaries/releases/latest/download/pdfium-linux-musl-$(uname -m | sed 's/x86_64/x64/;s/aarch64/arm64/').tgz" && \
mkdir -p /pdfium-linux && \ mkdir -p /pdfium-linux && \
tar -xzf pdfium-linux.tgz -C /pdfium-linux tar -xzf pdfium-linux.tgz -C /pdfium-linux
@ -47,13 +47,11 @@ FROM ruby:4.0.1-alpine AS app
ENV RAILS_ENV=production ENV RAILS_ENV=production
ENV BUNDLE_WITHOUT="development:test" ENV BUNDLE_WITHOUT="development:test"
ENV LD_PRELOAD=/lib/libgcompat.so.0
ENV OPENSSL_CONF=/etc/openssl_legacy.cnf ENV OPENSSL_CONF=/etc/openssl_legacy.cnf
ENV VIPS_MAX_COORD=15000
WORKDIR /app WORKDIR /app
RUN apk add --no-cache sqlite-dev libpq-dev vips-dev yaml-dev redis libheif vips-heif gcompat ttf-freefont onnxruntime && mkdir /fonts && rm /usr/share/fonts/freefont/FreeSans.otf RUN apk add --no-cache libpq vips redis vips-heif ttf-freefont onnxruntime && mkdir /fonts && rm /usr/share/fonts/freefont/FreeSans.otf
RUN addgroup -g 2000 docuseal && adduser -u 2000 -G docuseal -s /bin/sh -D -h /home/docuseal docuseal RUN addgroup -g 2000 docuseal && adduser -u 2000 -G docuseal -s /bin/sh -D -h /home/docuseal docuseal
@ -71,7 +69,7 @@ activate = 1' >> /etc/openssl_legacy.cnf
COPY --chown=docuseal:docuseal ./Gemfile ./Gemfile.lock ./ COPY --chown=docuseal:docuseal ./Gemfile ./Gemfile.lock ./
RUN apk add --no-cache build-base git && bundle install && apk del --no-cache build-base git && rm -rf ~/.bundle /usr/local/bundle/cache && ruby -e "puts Dir['/usr/local/bundle/**/{spec,rdoc,resources/shared,resources/collation,resources/locales}']" | xargs rm -rf && ln -sf /usr/lib/libonnxruntime.so.1 $(ruby -e "print Dir[Gem::Specification.find_by_name('onnxruntime').gem_dir + '/vendor/*.so'].first") RUN apk add --no-cache build-base git libpq-dev yaml-dev && bundle install && apk del --no-cache build-base git libpq-dev yaml-dev && rm -rf ~/.bundle /usr/local/bundle/cache && ruby -e "puts Dir['/usr/local/bundle/**/{spec,rdoc,resources/shared,resources/collation,resources/locales,resources/unicode_data/properties}'] + Dir['/usr/local/bundle/gems/*/{test,tests,examples,sample,misc,doc,docs}'] + Dir['/usr/local/bundle/gems/*/ext/**/*.{c,h,o,S}']" | xargs rm -rf && ln -sf /usr/lib/libonnxruntime.so.1 $(ruby -e "print Dir[Gem::Specification.find_by_name('onnxruntime').gem_dir + '/vendor/*.so'].first")
COPY --chown=docuseal:docuseal ./bin ./bin COPY --chown=docuseal:docuseal ./bin ./bin
COPY --chown=docuseal:docuseal ./app ./app COPY --chown=docuseal:docuseal ./app ./app
@ -98,6 +96,7 @@ RUN ln -s /fonts /app/public/fonts && \
WORKDIR /data/docuseal WORKDIR /data/docuseal
ENV HOME=/home/docuseal ENV HOME=/home/docuseal
ENV WORKDIR=/data/docuseal ENV WORKDIR=/data/docuseal
ENV VIPS_MAX_COORD=17000
EXPOSE 3000 EXPOSE 3000
CMD ["/app/bin/bundle", "exec", "puma", "-C", "/app/config/puma.rb", "--dir", "/app"] CMD ["/app/bin/bundle", "exec", "puma", "-C", "/app/config/puma.rb", "--dir", "/app"]

@ -1,31 +1,31 @@
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
action_text-trix (2.1.16) action_text-trix (2.1.17)
railties railties
actioncable (8.1.2) actioncable (8.1.3)
actionpack (= 8.1.2) actionpack (= 8.1.3)
activesupport (= 8.1.2) activesupport (= 8.1.3)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6) zeitwerk (~> 2.6)
actionmailbox (8.1.2) actionmailbox (8.1.3)
actionpack (= 8.1.2) actionpack (= 8.1.3)
activejob (= 8.1.2) activejob (= 8.1.3)
activerecord (= 8.1.2) activerecord (= 8.1.3)
activestorage (= 8.1.2) activestorage (= 8.1.3)
activesupport (= 8.1.2) activesupport (= 8.1.3)
mail (>= 2.8.0) mail (>= 2.8.0)
actionmailer (8.1.2) actionmailer (8.1.3)
actionpack (= 8.1.2) actionpack (= 8.1.3)
actionview (= 8.1.2) actionview (= 8.1.3)
activejob (= 8.1.2) activejob (= 8.1.3)
activesupport (= 8.1.2) activesupport (= 8.1.3)
mail (>= 2.8.0) mail (>= 2.8.0)
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
actionpack (8.1.2) actionpack (8.1.3)
actionview (= 8.1.2) actionview (= 8.1.3)
activesupport (= 8.1.2) activesupport (= 8.1.3)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
rack (>= 2.2.4) rack (>= 2.2.4)
rack-session (>= 1.0.1) rack-session (>= 1.0.1)
@ -33,36 +33,36 @@ GEM
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6) rails-html-sanitizer (~> 1.6)
useragent (~> 0.16) useragent (~> 0.16)
actiontext (8.1.2) actiontext (8.1.3)
action_text-trix (~> 2.1.15) action_text-trix (~> 2.1.15)
actionpack (= 8.1.2) actionpack (= 8.1.3)
activerecord (= 8.1.2) activerecord (= 8.1.3)
activestorage (= 8.1.2) activestorage (= 8.1.3)
activesupport (= 8.1.2) activesupport (= 8.1.3)
globalid (>= 0.6.0) globalid (>= 0.6.0)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
actionview (8.1.2) actionview (8.1.3)
activesupport (= 8.1.2) activesupport (= 8.1.3)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.11) erubi (~> 1.11)
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6) rails-html-sanitizer (~> 1.6)
activejob (8.1.2) activejob (8.1.3)
activesupport (= 8.1.2) activesupport (= 8.1.3)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (8.1.2) activemodel (8.1.3)
activesupport (= 8.1.2) activesupport (= 8.1.3)
activerecord (8.1.2) activerecord (8.1.3)
activemodel (= 8.1.2) activemodel (= 8.1.3)
activesupport (= 8.1.2) activesupport (= 8.1.3)
timeout (>= 0.4.0) timeout (>= 0.4.0)
activestorage (8.1.2) activestorage (8.1.3)
actionpack (= 8.1.2) actionpack (= 8.1.3)
activejob (= 8.1.2) activejob (= 8.1.3)
activerecord (= 8.1.2) activerecord (= 8.1.3)
activesupport (= 8.1.2) activesupport (= 8.1.3)
marcel (~> 1.0) marcel (~> 1.0)
activesupport (8.1.2) activesupport (8.1.3)
base64 base64
bigdecimal bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1) concurrent-ruby (~> 1.0, >= 1.3.1)
@ -318,7 +318,7 @@ GEM
multi_json (1.19.1) multi_json (1.19.1)
net-http (0.9.1) net-http (0.9.1)
uri (>= 0.11.1) uri (>= 0.11.1)
net-imap (0.6.2) net-imap (0.6.3)
date date
net-protocol net-protocol
net-pop (0.1.2) net-pop (0.1.2)
@ -394,20 +394,20 @@ GEM
rack (>= 1.3) rack (>= 1.3)
rackup (2.3.1) rackup (2.3.1)
rack (>= 3) rack (>= 3)
rails (8.1.2) rails (8.1.3)
actioncable (= 8.1.2) actioncable (= 8.1.3)
actionmailbox (= 8.1.2) actionmailbox (= 8.1.3)
actionmailer (= 8.1.2) actionmailer (= 8.1.3)
actionpack (= 8.1.2) actionpack (= 8.1.3)
actiontext (= 8.1.2) actiontext (= 8.1.3)
actionview (= 8.1.2) actionview (= 8.1.3)
activejob (= 8.1.2) activejob (= 8.1.3)
activemodel (= 8.1.2) activemodel (= 8.1.3)
activerecord (= 8.1.2) activerecord (= 8.1.3)
activestorage (= 8.1.2) activestorage (= 8.1.3)
activesupport (= 8.1.2) activesupport (= 8.1.3)
bundler (>= 1.15.0) bundler (>= 1.15.0)
railties (= 8.1.2) railties (= 8.1.3)
rails-dom-testing (2.3.0) rails-dom-testing (2.3.0)
activesupport (>= 5.0.0) activesupport (>= 5.0.0)
minitest minitest
@ -418,9 +418,9 @@ GEM
rails-i18n (8.1.0) rails-i18n (8.1.0)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
railties (>= 8.0.0, < 9) railties (>= 8.0.0, < 9)
railties (8.1.2) railties (8.1.3)
actionpack (= 8.1.2) actionpack (= 8.1.3)
activesupport (= 8.1.2) activesupport (= 8.1.3)
irb (~> 1.13) irb (~> 1.13)
rackup (>= 1.0.0) rackup (>= 1.0.0)
rake (>= 12.2) rake (>= 12.2)
@ -543,7 +543,7 @@ GEM
activemodel (>= 3.0, < 9.0) activemodel (>= 3.0, < 9.0)
strscan (3.1.7) strscan (3.1.7)
thor (1.5.0) thor (1.5.0)
timeout (0.6.0) timeout (0.6.1)
trailblazer-option (0.1.2) trailblazer-option (0.1.2)
trilogy (2.10.0) trilogy (2.10.0)
bigdecimal bigdecimal

@ -11,6 +11,7 @@ class AccountConfigsController < ApplicationController
AccountConfig::FORCE_MFA, AccountConfig::FORCE_MFA,
AccountConfig::ALLOW_TO_RESUBMIT, AccountConfig::ALLOW_TO_RESUBMIT,
AccountConfig::ALLOW_TO_DECLINE_KEY, AccountConfig::ALLOW_TO_DECLINE_KEY,
AccountConfig::ALLOW_TO_DELEGATE_KEY,
AccountConfig::FORM_PREFILL_SIGNATURE_KEY, AccountConfig::FORM_PREFILL_SIGNATURE_KEY,
AccountConfig::ESIGNING_PREFERENCE_KEY, AccountConfig::ESIGNING_PREFERENCE_KEY,
AccountConfig::FORM_WITH_CONFETTI_KEY, AccountConfig::FORM_WITH_CONFETTI_KEY,
@ -36,7 +37,7 @@ class AccountConfigsController < ApplicationController
end end
def destroy def destroy
raise InvalidKey unless ALLOWED_KEYS.include?(@account_config.key) raise InvalidKey unless allowed_keys.include?(@account_config.key)
@account_config.destroy! @account_config.destroy!
@ -45,8 +46,12 @@ class AccountConfigsController < ApplicationController
private private
def allowed_keys
ALLOWED_KEYS
end
def load_account_config def load_account_config
raise InvalidKey unless ALLOWED_KEYS.include?(account_config_params[:key]) raise InvalidKey unless allowed_keys.include?(account_config_params[:key])
@account_config = @account_config =
AccountConfig.find_or_initialize_by(account: current_account, key: account_config_params[:key]) AccountConfig.find_or_initialize_by(account: current_account, key: account_config_params[:key])

@ -40,7 +40,7 @@ class ErrorsController < ActionController::Base
render json: { status: error_status_code, error: }.compact, status: error_status_code render json: { status: error_status_code, error: }.compact, status: error_status_code
end end
f.html { render error_status_code.to_s, status: error_status_code } f.any { render error_status_code.to_s, status: error_status_code }
end end
end end
@ -51,7 +51,7 @@ class ErrorsController < ActionController::Base
headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, PATCH, DELETE, OPTIONS' headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, PATCH, DELETE, OPTIONS'
headers['Access-Control-Allow-Headers'] = '*' headers['Access-Control-Allow-Headers'] = '*'
headers['Access-Control-Max-Age'] = '1728000' headers['Access-Control-Max-Age'] = '1728000'
headers['Access-Control-Allow-Credentials'] = true headers['Access-Control-Allow-Credentials'] = 'true'
end end
def error_status_code def error_status_code

@ -16,6 +16,7 @@ class SubmissionEventsController < ApplicationController
'email_verified' => 'email_check', 'email_verified' => 'email_check',
'click_sms' => 'hand_click', 'click_sms' => 'hand_click',
'decline_form' => 'x', 'decline_form' => 'x',
'delegate_form' => 'user_share',
'start_verification' => 'player_play', 'start_verification' => 'player_play',
'complete_verification' => 'check', 'complete_verification' => 'check',
'invite_party' => 'user_plus' 'invite_party' => 'user_plus'

@ -3,11 +3,12 @@
class SubmitFormController < ApplicationController class SubmitFormController < ApplicationController
layout 'form' layout 'form'
around_action :with_browser_locale, only: %i[show completed success] around_action :with_browser_locale, only: %i[show completed success delegated]
skip_before_action :authenticate_user! skip_before_action :authenticate_user!
skip_authorization_check skip_authorization_check
before_action :load_submitter, only: %i[show update completed] before_action :load_submitter, only: %i[show update completed]
before_action :maybe_redirect_delegated, only: %i[show completed]
before_action :maybe_render_locked_page, only: :show before_action :maybe_render_locked_page, only: :show
before_action :maybe_require_link_2fa, only: %i[show] before_action :maybe_require_link_2fa, only: %i[show]
@ -91,6 +92,12 @@ class SubmitFormController < ApplicationController
def success; end def success; end
def delegated
submitter_version = SubmitterVersion.find_by!(slug: params[:slug] || params[:submit_form_slug])
@submitter = submitter_version.submitter
end
private private
def maybe_require_link_2fa def maybe_require_link_2fa
@ -108,8 +115,18 @@ class SubmitFormController < ApplicationController
render :declined if @submitter.declined_at? render :declined if @submitter.declined_at?
end end
def maybe_redirect_delegated
return if @submitter
submitter_version = SubmitterVersion.find_by!(slug: params[:slug] || params[:submit_form_slug])
submitter_version.submitter.submission_events.find_by!(event_type: :delegate_form)
redirect_to submit_form_delegated_path(submitter_version.slug)
end
def load_submitter def load_submitter
@submitter = Submitter.find_by!(slug: params[:slug] || params[:submit_form_slug]) @submitter = Submitter.find_by(slug: params[:slug] || params[:submit_form_slug])
end end
def build_attachments_index(submission) def build_attachments_index(submission)

@ -4,31 +4,38 @@ class SubmitFormDeclineController < ApplicationController
skip_before_action :authenticate_user! skip_before_action :authenticate_user!
skip_authorization_check skip_authorization_check
def create before_action :load_submitter
submitter = Submitter.find_by!(slug: params[:submit_form_slug])
return redirect_to submit_form_path(submitter.slug) if submitter.declined_at? || def create
submitter.completed_at? || return redirect_to submit_form_path(@submitter.slug) if @submitter.declined_at? ||
submitter.submission.archived_at? || @submitter.completed_at? ||
submitter.submission.expired? || @submitter.submission.archived_at? ||
submitter.submission.template&.archived_at? || @submitter.submission.expired? ||
!Submitters::AuthorizedForForm.call(submitter, current_user, @submitter.submission.template&.archived_at? ||
request) !Submitters::AuthorizedForForm.call(@submitter,
current_user,
request)
ApplicationRecord.transaction do ApplicationRecord.transaction do
submitter.update!(declined_at: Time.current) @submitter.update!(declined_at: Time.current)
SubmissionEvents.create_with_tracking_data(submitter, 'decline_form', request, { reason: params[:reason] }) SubmissionEvents.create_with_tracking_data(@submitter, 'decline_form', request, { reason: params[:reason] })
end end
user = submitter.submission.created_by_user || submitter.template.author user = @submitter.submission.created_by_user || @submitter.template.author
if user.user_configs.find_by(key: UserConfig::RECEIVE_DECLINED_EMAIL)&.value != false if user.user_configs.find_by(key: UserConfig::RECEIVE_DECLINED_EMAIL)&.value != false
SubmitterMailer.declined_email(submitter, user).deliver_later! SubmitterMailer.declined_email(@submitter, user).deliver_later!
end end
WebhookUrls.enqueue_events(submitter, 'form.declined') WebhookUrls.enqueue_events(@submitter, 'form.declined')
redirect_to submit_form_path(@submitter.slug)
end
private
redirect_to submit_form_path(submitter.slug) def load_submitter
@submitter = Submitter.find_by!(slug: params[:submit_form_slug])
end end
end end

@ -0,0 +1,47 @@
# frozen_string_literal: true
class SubmitFormDelegateController < ApplicationController
skip_before_action :authenticate_user!
skip_authorization_check
before_action :load_submitter
def create
return redirect_to submit_form_path(@submitter.slug) if @submitter.declined_at? ||
@submitter.completed_at? ||
@submitter.submission.archived_at? ||
@submitter.submission.expired? ||
@submitter.submission.template&.archived_at? ||
!Submitters::AuthorizedForForm.call(@submitter,
current_user,
request)
@submitter.account.account_configs.find_by!(key: AccountConfig::ALLOW_TO_DELEGATE_KEY, value: true)
email = Submissions.normalize_email(params[:email])
return redirect_to submit_form_path(@submitter.slug) if email.blank?
old_slug = @submitter.slug
ApplicationRecord.transaction do
@submitter.submitter_versions.create!(slug: old_slug, email: @submitter.email,
name: @submitter.name, phone: @submitter.phone)
SubmissionEvents.create_with_tracking_data(@submitter, 'delegate_form', request,
{ old_email: @submitter.email, email: })
@submitter.update!(email:, phone: nil, name: nil, slug: SecureRandom.base58(14))
end
SendSubmitterInvitationEmailJob.perform_async('submitter_id' => @submitter.id)
redirect_to submit_form_delegated_path(old_slug)
end
private
def load_submitter
@submitter = Submitter.find_by!(slug: params[:submit_form_slug])
end
end

@ -36,7 +36,7 @@ safeRegisterElement('submission-form', class extends HTMLElement {
expand: ['true', 'false'].includes(this.dataset.expand) ? this.dataset.expand === 'true' : null, expand: ['true', 'false'].includes(this.dataset.expand) ? this.dataset.expand === 'true' : null,
withSignatureId: this.dataset.withSignatureId === 'true', withSignatureId: this.dataset.withSignatureId === 'true',
requireSigningReason: this.dataset.requireSigningReason === 'true', requireSigningReason: this.dataset.requireSigningReason === 'true',
withConfetti: this.dataset.withConfetti !== 'false', withConfetti: this.dataset.withConfetti === 'true',
withFieldLabels: this.dataset.withFieldLabels !== 'false', withFieldLabels: this.dataset.withFieldLabels !== 'false',
withDisclosure: this.dataset.withDisclosure === 'true', withDisclosure: this.dataset.withDisclosure === 'true',
reuseSignature: this.dataset.reuseSignature !== 'false', reuseSignature: this.dataset.reuseSignature !== 'false',

@ -30,6 +30,7 @@ class AccountConfig < ApplicationRecord
ALLOW_TYPED_SIGNATURE = 'allow_typed_signature' ALLOW_TYPED_SIGNATURE = 'allow_typed_signature'
ALLOW_TO_RESUBMIT = 'allow_to_resubmit' ALLOW_TO_RESUBMIT = 'allow_to_resubmit'
ALLOW_TO_DECLINE_KEY = 'allow_to_decline' ALLOW_TO_DECLINE_KEY = 'allow_to_decline'
ALLOW_TO_DELEGATE_KEY = 'allow_to_delegate'
ALLOW_TO_PARTIAL_DOWNLOAD_KEY = 'allow_to_partial_download' ALLOW_TO_PARTIAL_DOWNLOAD_KEY = 'allow_to_partial_download'
SUBMITTER_REMINDERS = 'submitter_reminders' SUBMITTER_REMINDERS = 'submitter_reminders'
ENFORCE_SIGNING_ORDER_KEY = 'enforce_signing_order' ENFORCE_SIGNING_ORDER_KEY = 'enforce_signing_order'

@ -64,6 +64,7 @@ class SubmissionEvent < ApplicationRecord
invite_party: 'invite_party', invite_party: 'invite_party',
complete_form: 'complete_form', complete_form: 'complete_form',
decline_form: 'decline_form', decline_form: 'decline_form',
delegate_form: 'delegate_form',
api_complete_form: 'api_complete_form' api_complete_form: 'api_complete_form'
}, scope: false }, scope: false

@ -44,6 +44,7 @@ class Submitter < ApplicationRecord
belongs_to :account belongs_to :account
has_one :template, through: :submission has_one :template, through: :submission
has_one :search_entry, as: :record, inverse_of: :record, dependent: :destroy if SearchEntry.table_exists? has_one :search_entry, as: :record, inverse_of: :record, dependent: :destroy if SearchEntry.table_exists?
has_many :submitter_versions, dependent: :destroy
attribute :values, :string, default: -> { {} } attribute :values, :string, default: -> { {} }
attribute :preferences, :string, default: -> { {} } attribute :preferences, :string, default: -> { {} }

@ -0,0 +1,27 @@
# frozen_string_literal: true
# == Schema Information
#
# Table name: submitter_versions
#
# id :bigint not null, primary key
# email :string
# name :string
# phone :string
# slug :string not null
# created_at :datetime not null
# updated_at :datetime not null
# submitter_id :bigint not null
#
# Indexes
#
# index_submitter_versions_on_slug (slug)
# index_submitter_versions_on_submitter_id (submitter_id)
#
# Foreign Keys
#
# fk_rails_... (submitter_id => submitters.id)
#
class SubmitterVersion < ApplicationRecord
belongs_to :submitter
end

@ -131,23 +131,50 @@
</div> </div>
<% end %> <% end %>
<% end %> <% end %>
<% if !Docuseal.multitenant? || can?(:manage, :disable_decline) %> <% account_config = AccountConfig.find_or_initialize_by(account: current_account, key: AccountConfig::ALLOW_TO_DECLINE_KEY) %>
<% account_config = AccountConfig.find_or_initialize_by(account: current_account, key: AccountConfig::ALLOW_TO_DECLINE_KEY) %> <% if can?(:manage, account_config) %>
<% if can?(:manage, account_config) %> <%= form_for account_config, url: account_configs_path, method: :post do |f| %>
<%= form_for account_config, url: account_configs_path, method: :post do |f| %> <%= f.hidden_field :key %>
<%= f.hidden_field :key %> <div class="flex items-center justify-between gap-4 py-2.5">
<div class="flex items-center justify-between gap-4 py-2.5"> <div class="flex items-center space-x-1">
<div class="flex items-center space-x-1"> <span class="text-left"><%= t('allow_to_decline_documents') %></span>
<span class="text-left"><%= t('allow_to_decline_documents') %></span> <span class="tooltip tooltip-top flex cursor-pointer" data-tip="<%= t('allow_recipients_to_decline_signing_a_document_the_decline_reason_notification_will_be_sent_to_the_signature_requester') %>">
<span class="tooltip tooltip-top flex cursor-pointer" data-tip="<%= t('allow_recipients_to_decline_signing_a_document_the_decline_reason_notification_will_be_sent_to_the_signature_requester') %>"> <%= svg_icon('info_circle', class: 'hidden md:inline-block w-4 h-4 shrink-0') %>
<%= svg_icon('info_circle', class: 'hidden md:inline-block w-4 h-4 shrink-0') %> </span>
</span> </div>
</div> <% if !Docuseal.multitenant? || can?(:manage, :disable_decline) %>
<submit-form data-on="change" class="flex"> <submit-form data-on="change" class="flex">
<%= f.check_box :value, class: 'toggle', checked: account_config.value != false %> <%= f.check_box :value, class: 'toggle', checked: account_config.value != false %>
</submit-form> </submit-form>
<% else %>
<a href="<%= console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") %>" data-turbo="false" data-tip="<%= I18n.t('unlock_with_docuseal_pro') %>" data-on="change" class="flex tooltip">
<%= f.check_box :value, class: 'toggle pointer-events-none', checked: account_config.value != false, disabled: true %>
</a>
<% end %>
</div>
<% end %>
<% end %>
<% account_config = AccountConfig.find_or_initialize_by(account: current_account, key: AccountConfig::ALLOW_TO_DELEGATE_KEY) %>
<% if can?(:manage, account_config) %>
<%= form_for account_config, url: account_configs_path, method: :post do |f| %>
<%= f.hidden_field :key %>
<div class="flex items-center justify-between gap-4 py-2.5">
<div class="flex items-center space-x-1">
<span class="text-left"><%= t('allow_to_delegate_documents') %></span>
<span class="tooltip tooltip-top flex cursor-pointer" data-tip="<%= t('allow_recipients_to_delegate_documents') %>">
<%= svg_icon('info_circle', class: 'hidden md:inline-block w-4 h-4 shrink-0') %>
</span>
</div> </div>
<% end %> <% if !Docuseal.multitenant? || can?(:manage, :delegate_form) %>
<submit-form data-on="change" class="flex">
<%= f.check_box :value, class: 'toggle', checked: account_config.value == true %>
</submit-form>
<% else %>
<a href="<%= console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") %>" data-turbo="false" data-tip="<%= I18n.t('unlock_with_docuseal_pro') %>" class="flex tooltip">
<%= f.check_box :value, class: 'toggle pointer-events-none', checked: account_config.value == true, disabled: true %>
</a>
<% end %>
</div>
<% end %> <% end %>
<% end %> <% end %>
<% account_config = AccountConfig.find_or_initialize_by(account: current_account, key: AccountConfig::FORM_PREFILL_SIGNATURE_KEY) %> <% account_config = AccountConfig.find_or_initialize_by(account: current_account, key: AccountConfig::FORM_PREFILL_SIGNATURE_KEY) %>

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="<%= local_assigns[:class] %>"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0" /><path d="M6 21v-2a4 4 0 0 1 4 -4h3" /><path d="M16 22l5 -5" /><path d="M21 21.5v-4.5h-4.5" /></svg>

After

Width:  |  Height:  |  Size: 416 B

@ -1,4 +1,4 @@
<% account_config = AccountConfig.where(account: current_account, key: AccountConfig::FORM_WITH_CONFETTI_KEY).first_or_initialize(value: true) %> <% account_config = AccountConfig.where(account: current_account, key: AccountConfig::FORM_WITH_CONFETTI_KEY).first_or_initialize(value: false) %>
<% if can?(:manage, account_config) %> <% if can?(:manage, account_config) %>
<div class="px-1 mt-2"> <div class="px-1 mt-2">
<%= form_for account_config, url: account_configs_path, method: :post do |f| %> <%= form_for account_config, url: account_configs_path, method: :post do |f| %>
@ -8,7 +8,7 @@
<%= t('show_confetti_on_successful_completion') %> <%= t('show_confetti_on_successful_completion') %>
</span> </span>
<submit-form data-on="change" class="flex"> <submit-form data-on="change" class="flex">
<%= f.check_box :value, { class: 'toggle', checked: account_config.value != false }, '1', '0' %> <%= f.check_box :value, { class: 'toggle', checked: account_config.value == true }, '1', '0' %>
</submit-form> </submit-form>
</div> </div>
<% end %> <% end %>

@ -20,10 +20,13 @@
<% end %> <% end %>
</p> </p>
</li> </li>
<% submitter_versions_index = @submission.submitters.preload(:submitter_versions).each_with_object({}) { |s, h| h[s.id] = s.submitter_versions.to_a.sort_by(&:created_at) } %>
<% @submission.submission_events.order(:event_timestamp).each do |event| %> <% @submission.submission_events.order(:event_timestamp).each do |event| %>
<% submitter = @submission.submitters.find { |e| e.id == event.submitter_id } %> <% submitter = @submission.submitters.find { |e| e.id == event.submitter_id } %>
<% bg_class = event_colors[submitters_uuids.index(submitter.uuid) % event_colors.length] %> <% bg_class = event_colors[submitters_uuids.index(submitter.uuid) % event_colors.length] %>
<% submitter_name = event.event_type.include?('sms') || event.event_type.include?('phone') ? (event.data['phone'] || submitter.phone) : (submitter.name || submitter.email || submitter.phone) %> <% versions = submitter_versions_index[submitter.id] || [] %>
<% active_version = versions.find { |v| v.created_at > event.event_timestamp } %>
<% submitter_name = event.event_type.include?('sms') || event.event_type.include?('phone') ? (event.data['phone'] || active_version&.phone || submitter.phone) : (active_version&.name || active_version&.email || active_version&.phone || submitter.name || submitter.email || submitter.phone) %>
<li class="ml-7"> <li class="ml-7">
<span class="absolute flex items-center justify-center w-7 h-7 rounded-full -start-3.5 ring-8 ring-base-100 text-base-content <%= bg_class %>"> <span class="absolute flex items-center justify-center w-7 h-7 rounded-full -start-3.5 ring-8 ring-base-100 text-base-content <%= bg_class %>">
<%= svg_icon(SubmissionEventsController::SUBMISSION_EVENT_ICONS.fetch(event.event_type, 'circle_dot'), class: 'w-4 h-4') %> <%= svg_icon(SubmissionEventsController::SUBMISSION_EVENT_ICONS.fetch(event.event_type, 'circle_dot'), class: 'w-4 h-4') %>
@ -43,6 +46,9 @@
<%= t('submission_event_names.complete_verification_by_html', provider: event.data['method'], submitter_name:) %> <%= t('submission_event_names.complete_verification_by_html', provider: event.data['method'], submitter_name:) %>
<% elsif event.event_type == 'invite_party' && (invited_submitter = @submission.submitters.find { |e| e.uuid == event.data['uuid'] }) && (name = @submission.template_submitters.find { |e| e['uuid'] == event.data['uuid'] }&.dig('name')) %> <% elsif event.event_type == 'invite_party' && (invited_submitter = @submission.submitters.find { |e| e.uuid == event.data['uuid'] }) && (name = @submission.template_submitters.find { |e| e['uuid'] == event.data['uuid'] }&.dig('name')) %>
<%= t('submission_event_names.invite_party_by_html', invited_submitter_name: [invited_submitter.name || invited_submitter.email || invited_submitter.phone, name].join(' '), submitter_name:) %> <%= t('submission_event_names.invite_party_by_html', invited_submitter_name: [invited_submitter.name || invited_submitter.email || invited_submitter.phone, name].join(' '), submitter_name:) %>
<% elsif event.event_type == 'delegate_form' %>
<% delegate_from = event.data['old_email'].presence || (versions.reverse.find { |v| v.created_at <= event.event_timestamp }&.then { |v| v.name || v.phone }) %>
<%= t('submission_event_names.delegate_form_by_html', from: delegate_from, to: event.data['email']) %>
<% elsif event.event_type.include?('send_') %> <% elsif event.event_type.include?('send_') %>
<%= t("submission_event_names.#{event.event_type}_to_html", submitter_name:) %> <%= t("submission_event_names.#{event.event_type}_to_html", submitter_name:) %>
<% elsif event.event_type.start_with?('bounce_') || event.event_type.start_with?('complaint_') %> <% elsif event.event_type.start_with?('bounce_') || event.event_type.start_with?('complaint_') %>

@ -3,7 +3,7 @@
<% submitters = template.submitters.reject { |e| e['invite_by_uuid'].present? || e['optional_invite_by_uuid'].present? || e['invite_via_field_uuid'].present? } %> <% submitters = template.submitters.reject { |e| e['invite_by_uuid'].present? || e['optional_invite_by_uuid'].present? || e['invite_via_field_uuid'].present? } %>
<dynamic-list class="space-y-4"> <dynamic-list class="space-y-4">
<div class="space-y-4"> <div class="space-y-4">
<div class="<%= 'p-4 rounded-xl bg-base-300/40' unless local_assigns[:variables_form] %>" data-targets="dynamic-list.items"> <div class="relative <%= 'p-4 rounded-xl bg-base-300/40' unless local_assigns[:variables_form] %>" data-targets="dynamic-list.items">
<div> <div>
<div class="absolute right-4 top-5"> <div class="absolute right-4 top-5">
<a href="#" data-action="click:dynamic-list#removeItem" class="<%= submitters.size == 1 ? 'right-2 top-1' : '-top-3' %> relative block w-6 h-6 rounded-lg text-neutral-700 text-center bg-base-300 p-1 hidden hover:bg-neutral hover:text-white"> <a href="#" data-action="click:dynamic-list#removeItem" class="<%= submitters.size == 1 ? 'right-2 top-1' : '-top-3' %> relative block w-6 h-6 rounded-lg text-neutral-700 text-center bg-base-300 p-1 hidden hover:bg-neutral hover:text-white">

@ -34,7 +34,7 @@
<% else %> <% else %>
<dynamic-list class="space-y-4"> <dynamic-list class="space-y-4">
<div class="space-y-4"> <div class="space-y-4">
<div class="<%= 'p-4 rounded-xl bg-base-300/40' unless local_assigns[:variables_form] %>" data-targets="dynamic-list.items"> <div class="relative <%= 'p-4 rounded-xl bg-base-300/40' unless local_assigns[:variables_form] %>" data-targets="dynamic-list.items">
<div> <div>
<div class="absolute right-4 top-5"> <div class="absolute right-4 top-5">
<a href="#" data-action="click:dynamic-list#removeItem" class="-top-3 relative block w-6 h-6 rounded-lg text-neutral-700 text-center bg-base-300 p-1 hidden hover:bg-neutral hover:text-white"> <a href="#" data-action="click:dynamic-list#removeItem" class="-top-3 relative block w-6 h-6 rounded-lg text-neutral-700 text-center bg-base-300 p-1 hidden hover:bg-neutral hover:text-white">

@ -2,7 +2,7 @@
<% submitters = template.submitters.reject { |e| e['invite_by_uuid'].present? || e['optional_invite_by_uuid'].present? || e['invite_via_field_uuid'].present? } %> <% submitters = template.submitters.reject { |e| e['invite_by_uuid'].present? || e['optional_invite_by_uuid'].present? || e['invite_via_field_uuid'].present? } %>
<dynamic-list class="space-y-4"> <dynamic-list class="space-y-4">
<div class="space-y-4"> <div class="space-y-4">
<div class="<%= 'p-4 rounded-xl bg-base-300/40' unless local_assigns[:variables_form] %>" data-targets="dynamic-list.items"> <div class="relative <%= 'p-4 rounded-xl bg-base-300/40' unless local_assigns[:variables_form] %>" data-targets="dynamic-list.items">
<div> <div>
<div class="absolute right-4 top-5"> <div class="absolute right-4 top-5">
<a href="#" data-action="click:dynamic-list#removeItem" class="<%= submitters.size == 1 ? 'right-2 top-1' : '-top-3' %> relative block w-6 h-6 rounded-lg text-neutral-700 text-center bg-base-300 p-1 hidden hover:bg-neutral hover:text-white"> <a href="#" data-action="click:dynamic-list#removeItem" class="<%= submitters.size == 1 ? 'right-2 top-1' : '-top-3' %> relative block w-6 h-6 rounded-lg text-neutral-700 text-center bg-base-300 p-1 hidden hover:bg-neutral hover:text-white">

@ -1,4 +1,4 @@
<% if template.preferences['submitters_order'] == 'preserved' || template.submitters.any? { |s| s['order'] } %> <% if template.preferences['submitters_order'] == 'preserved' || template.submitters.any? { |s| s['order'] } || (template.submitters.size > 1 && template.fields.any? { |f| f['type'] == 'verification' }) %>
<%= f.hidden_field :preserve_order, value: '1' %> <%= f.hidden_field :preserve_order, value: '1' %>
<% elsif template.submitters.size > 1 %> <% elsif template.submitters.size > 1 %>
<div class="form-control"> <div class="form-control">

@ -0,0 +1,9 @@
<%= form_for '', url: submit_form_delegate_index_path(submitter.slug), method: :post do |f| %>
<div class="form-control mt-2">
<%= f.label :email, t(:enter_the_email_address_of_the_person_you_want_to_delegate_to), class: 'label' %>
<%= f.email_field :email, required: true, class: 'base-input w-full', dir: 'auto', placeholder: t('email') %>
</div>
<toggle-submit dir="auto" class="form-control mt-4">
<%= f.button button_title(title: t(:delegate)), class: 'base-button' %>
</toggle-submit>
<% end %>

@ -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('user_share', class: 'w-10 h-10') %>
</div>
<div dir="auto">
<p class="text-lg font-bold mb-1"><%= @submitter.submission.name || @submitter.submission.template.name %></p>
<p class="text-sm"><%= t('document_has_been_delegated_on_html', time: l(@submitter.submission_events.order(event_timestamp: :desc).find_by!(event_type: :delegate_form).event_timestamp, format: :long)) %></p>
</div>
</div>
</div>
</div>
</div>
</div>
<%= render 'shared/attribution', link_path: '/start', account: @submitter.account %>

@ -9,6 +9,7 @@
<% schema = Submissions.filtered_conditions_schema(@submitter.submission, values:, include_submitter_uuid: @submitter.uuid) %> <% schema = Submissions.filtered_conditions_schema(@submitter.submission, values:, include_submitter_uuid: @submitter.uuid) %>
<% font_scale = 1000.0 / PdfUtils::US_LETTER_W %> <% font_scale = 1000.0 / PdfUtils::US_LETTER_W %>
<% decline_modal_checkbox_uuid = nil %> <% decline_modal_checkbox_uuid = nil %>
<% delegate_modal_checkbox_uuid = nil %>
<div style="max-height: -webkit-fill-available;"> <div style="max-height: -webkit-fill-available;">
<div id="scrollbox"> <div id="scrollbox">
<div class="mx-auto block pb-72" style="max-width: 1000px"> <div class="mx-auto block pb-72" style="max-width: 1000px">
@ -20,42 +21,85 @@
<%= @submitter.submission.name || @submitter.submission.template.name %> <%= @submitter.submission.name || @submitter.submission.template.name %>
</div> </div>
<div class="flex items-center space-x-2" style="margin-left: 20px; flex-shrink: 0"> <div class="flex items-center space-x-2" style="margin-left: 20px; flex-shrink: 0">
<% if @form_configs[:with_decline] %> <% if @form_configs[:with_delegate] %>
<label id="decline_button" for="<%= decline_modal_checkbox_uuid = SecureRandom.uuid %>" class="btn btn-sm !px-5"><%= t(:decline) %></label> <label id="delegate_button" for="<%= delegate_modal_checkbox_uuid = SecureRandom.uuid %>" class="btn btn-sm !px-5"><%= t(:delegate) %></label>
<% end %> <% if @form_configs[:with_decline] %>
<% if @form_configs[:with_partial_download] %> <label id="decline_button" for="<%= decline_modal_checkbox_uuid = SecureRandom.uuid %>" class="btn btn-sm px-2" title="<%= t(:decline) %>">
<download-button data-src="<%= submit_form_download_index_path(@submitter.slug) %>" class="btn btn-neutral text-white btn-sm !px-4"> <%= svg_icon('x', class: 'w-5 h-5') %>
<span class="flex items-center justify-center" data-target="download-button.defaultButton"> </label>
<%= svg_icon('download', class: 'w-6 h-6 inline md:hidden') %> <% end %>
<span class="hidden md:inline"><%= t('download') %></span> <% if @form_configs[:with_partial_download] %>
</span> <download-button data-src="<%= submit_form_download_index_path(@submitter.slug) %>" class="btn btn-neutral text-white btn-sm px-2" title="<%= t('download') %>">
<span class="flex items-center justify-center space-x-2 hidden" data-target="download-button.loadingButton"> <span data-target="download-button.defaultButton">
<%= svg_icon('loader', class: 'w-6 h-6 animate-spin') %> <%= svg_icon('download', class: 'w-5 h-5') %>
<span class="hidden md:inline"><%= t('downloading') %></span> </span>
</span> <span class="hidden" data-target="download-button.loadingButton">
</download-button> <%= svg_icon('loader', class: 'w-5 h-5 animate-spin') %>
</span>
</download-button>
<% end %>
<% else %>
<% if @form_configs[:with_decline] %>
<label id="decline_button" for="<%= decline_modal_checkbox_uuid = SecureRandom.uuid %>" class="btn btn-sm !px-5"><%= t(:decline) %></label>
<% end %>
<% if @form_configs[:with_partial_download] %>
<download-button data-src="<%= submit_form_download_index_path(@submitter.slug) %>" class="btn btn-neutral text-white btn-sm !px-4">
<span class="flex items-center justify-center" data-target="download-button.defaultButton">
<%= svg_icon('download', class: 'w-6 h-6 inline md:hidden') %>
<span class="hidden md:inline"><%= t('download') %></span>
</span>
<span class="flex items-center justify-center space-x-2 hidden" data-target="download-button.loadingButton">
<%= svg_icon('loader', class: 'w-6 h-6 animate-spin') %>
<span class="hidden md:inline"><%= t('downloading') %></span>
</span>
</download-button>
<% end %>
<% end %> <% end %>
</div> </div>
</div> </div>
<scroll-buttons class="fixed right-5 top-2 hidden md:flex gap-1 z-50 ease-in-out opacity-0 -translate-y-10"> <scroll-buttons class="fixed right-5 top-2 hidden md:flex gap-1 z-50 ease-in-out opacity-0 -translate-y-10">
<% if @form_configs[:with_decline] %> <% if @form_configs[:with_delegate] %>
<label id="decline_button" for="<%= decline_modal_checkbox_uuid %>" class="btn btn-sm px-0"> <label id="delegate_button" for="<%= delegate_modal_checkbox_uuid %>" class="btn btn-sm px-0">
<span class="min-[1366px]:inline hidden px-3"> <span class="min-[1366px]:inline hidden px-3">
<%= t(:decline) %> <%= t(:delegate) %>
</span> </span>
<span class="inline min-[1366px]:hidden px-2"> <span class="inline min-[1366px]:hidden px-2">
<%= svg_icon('x', class: 'w-5 h-5') %> <%= svg_icon('user_share', class: 'w-5 h-5') %>
</span> </span>
</label> </label>
<% if @form_configs[:with_decline] %>
<label id="decline_button" for="<%= decline_modal_checkbox_uuid %>" class="btn btn-sm px-2">
<%= svg_icon('x', class: 'w-5 h-5') %>
</label>
<% end %>
<download-button data-src="<%= submit_form_download_index_path(@submitter.slug) %>" class="btn btn-neutral text-white btn-sm px-2">
<span data-target="download-button.defaultButton">
<%= svg_icon('download', class: 'w-5 h-5') %>
</span>
<span class="hidden" data-target="download-button.loadingButton">
<%= svg_icon('loader', class: 'w-5 h-5 animate-spin') %>
</span>
</download-button>
<% else %>
<% if @form_configs[:with_decline] %>
<label id="decline_button" for="<%= decline_modal_checkbox_uuid %>" class="btn btn-sm px-0">
<span class="min-[1366px]:inline hidden px-3">
<%= t(:decline) %>
</span>
<span class="inline min-[1366px]:hidden px-2">
<%= svg_icon('x', class: 'w-5 h-5') %>
</span>
</label>
<% end %>
<download-button data-src="<%= submit_form_download_index_path(@submitter.slug) %>" class="btn btn-neutral text-white btn-sm px-2">
<span data-target="download-button.defaultButton">
<%= svg_icon('download', class: 'w-5 h-5') %>
</span>
<span class="hidden" data-target="download-button.loadingButton">
<%= svg_icon('loader', class: 'w-5 h-5 animate-spin') %>
</span>
</download-button>
<% end %> <% end %>
<download-button data-src="<%= submit_form_download_index_path(@submitter.slug) %>" class="btn btn-neutral text-white btn-sm px-2">
<span data-target="download-button.defaultButton">
<%= svg_icon('download', class: 'w-5 h-5') %>
</span>
<span class="hidden" data-target="download-button.loadingButton">
<%= svg_icon('loader', class: 'w-5 h-5 animate-spin') %>
</span>
</download-button>
</scroll-buttons> </scroll-buttons>
<% end %> <% end %>
<% schema.each do |item| %> <% schema.each do |item| %>
@ -110,4 +154,9 @@
<%= render 'submit_form/decline_form', submitter: @submitter %> <%= render 'submit_form/decline_form', submitter: @submitter %>
<% end %> <% end %>
<% end %> <% end %>
<% if @form_configs[:with_delegate] %>
<%= render 'shared/html_modal', title: t(:delegate), uuid: delegate_modal_checkbox_uuid do %>
<%= render 'submit_form/delegate_form', submitter: @submitter %>
<% end %>
<% end %>
<%= render 'scripts/autosize_field' %> <%= render 'scripts/autosize_field' %>

@ -49,7 +49,7 @@
<% end %> <% end %>
</div> </div>
<% end %> <% end %>
<%= link_to template_share_link_path(template), class: "absolute md:relative bottom-0 right-0 btn btn-xs md:btn-sm whitespace-nowrap btn-neutral text-white mt-1 px-2 #{'btn-disabled text-base-100' if template.variables_schema.present?}", data: { turbo_frame: :modal } do %> <%= link_to template_share_link_path(template), class: "absolute md:relative bottom-0 right-0 btn btn-xs md:btn-sm whitespace-nowrap btn-neutral text-white mt-1 px-2", data: { turbo_frame: :modal } do %>
<span class="flex items-center justify-center space-x-2"> <span class="flex items-center justify-center space-x-2">
<%= svg_icon('link', class: 'w-4 h-4 md:w-6 md:h-6') %> <%= svg_icon('link', class: 'w-4 h-4 md:w-6 md:h-6') %>
<span><%= t('link') %></span> <span><%= t('link') %></span>

@ -2,6 +2,12 @@
<% enough_defined_submitters = Templates.filter_undefined_submitters(@template.submitters).size < 2 %> <% enough_defined_submitters = Templates.filter_undefined_submitters(@template.submitters).size < 2 %>
<%= render 'shared/turbo_modal_large', title: t('share_link') do %> <%= render 'shared/turbo_modal_large', title: t('share_link') do %>
<div class="mt-2 mb-4 px-5"> <div class="mt-2 mb-4 px-5">
<% if @template.variables_schema.present? %>
<div class="alert items-start bg-base-100 border-base-300 mt-4">
<%= svg_icon('info_circle', class: 'stroke-current shrink-0 h-6 w-6') %>
<div><%= t('dynamic_template_with_variables_cannot_be_used_via_shared_link') %></div>
</div>
<% end %>
<%= form_for @template, url: template_share_link_path(@template), method: :post, html: { id: 'shared_link_form', autocomplete: 'off', class: 'mt-3' }, data: { close_on_submit: false } do |f| %> <%= form_for @template, url: template_share_link_path(@template), method: :post, html: { id: 'shared_link_form', autocomplete: 'off', class: 'mt-3' }, data: { close_on_submit: false } do |f| %>
<% if @template.preferences&.dig('require_email_2fa') || @template.preferences&.dig('require_phone_2fa') %> <% if @template.preferences&.dig('require_email_2fa') || @template.preferences&.dig('require_phone_2fa') %>
<label for="template_shared_link" class="tooltip tooltip-bottom flex items-center my-4 justify-between gap-1 alert bg-base-100 border-base-300" data-tip="<%= t(:templates_that_require_email_or_phone_2fa_cannot_be_used_via_a_shared_link) %>"> <label for="template_shared_link" class="tooltip tooltip-bottom flex items-center my-4 justify-between gap-1 alert bg-base-100 border-base-300" data-tip="<%= t(:templates_that_require_email_or_phone_2fa_cannot_be_used_via_a_shared_link) %>">
@ -12,7 +18,7 @@
<label for="template_shared_link" class="flex items-center my-4 justify-between gap-1 alert bg-base-100 border-base-300"> <label for="template_shared_link" class="flex items-center my-4 justify-between gap-1 alert bg-base-100 border-base-300">
<span><%= t('enable_shared_link') %></span> <span><%= t('enable_shared_link') %></span>
<submit-form data-on="change" class="flex"> <submit-form data-on="change" class="flex">
<%= f.check_box :shared_link, { disabled: !can?(:update, @template), class: 'toggle' }, 'true', 'false' %> <%= f.check_box :shared_link, { disabled: !can?(:update, @template) || @template.variables_schema.present?, class: 'toggle' }, 'true', 'false' %>
</submit-form> </submit-form>
</label> </label>
<% end %> <% end %>
@ -23,7 +29,7 @@
</check-on-click> </check-on-click>
</div> </div>
<% end %> <% end %>
<% if multiple_submitters && !enough_defined_submitters %> <% if multiple_submitters && !enough_defined_submitters && @template.variables_schema.blank? %>
<div class="alert items-start bg-base-100 border-base-300 mt-4"> <div class="alert items-start bg-base-100 border-base-300 mt-4">
<%= svg_icon('info_circle', class: 'stroke-current shrink-0 h-6 w-6 mt-1') %> <%= svg_icon('info_circle', class: 'stroke-current shrink-0 h-6 w-6 mt-1') %>
<div><%= t('this_template_has_multiple_parties_which_prevents_the_use_of_a_sharing_link') %></div> <div><%= t('this_template_has_multiple_parties_which_prevents_the_use_of_a_sharing_link') %></div>

@ -0,0 +1,11 @@
# frozen_string_literal: true
module SilenceErrors
def log_error(request, wrapper)
return if wrapper.status_code == 404
super
end
end
ActionDispatch::DebugExceptions.prepend(SilenceErrors)

@ -163,10 +163,13 @@ en: &en
download: Download download: Download
decline: Decline decline: Decline
declined: Declined declined: Declined
delegate: Delegate
enter_the_email_address_of_the_person_you_want_to_delegate_to: Enter the email address of the person you want to delegate to
decline_reason: Decline reason decline_reason: Decline reason
provide_a_reason: Provide a reason provide_a_reason: Provide a reason
notify_the_sender_with_the_reason_you_declined: Notify the sender with the reason you declined notify_the_sender_with_the_reason_you_declined: Notify the sender with the reason you declined
form_has_been_declined_on_html: 'Form has been declined on <span class="font-semibold">%{time}</span>' form_has_been_declined_on_html: 'Form has been declined on <span class="font-semibold">%{time}</span>'
document_has_been_delegated_on_html: 'Document has been delegated on <span class="font-semibold">%{time}</span>'
name_declined_by_submitter: '"%{name}" declined by %{submitter}' name_declined_by_submitter: '"%{name}" declined by %{submitter}'
name_declined_by_submitter_with_the_following_reason: '"%{name}" has been declined by %{submitter} with the following reason:' name_declined_by_submitter_with_the_following_reason: '"%{name}" has been declined by %{submitter} with the following reason:'
completed_successfully: Completed Successfully completed_successfully: Completed Successfully
@ -201,6 +204,7 @@ en: &en
allow_typed_text_signatures: Allow typed text signatures allow_typed_text_signatures: Allow typed text signatures
allow_to_resubmit_completed_forms: Allow to resubmit completed forms allow_to_resubmit_completed_forms: Allow to resubmit completed forms
allow_to_decline_documents: Allow to decline documents allow_to_decline_documents: Allow to decline documents
allow_to_delegate_documents: Allow to delegate documents
remember_and_pre_fill_signatures: Remember and pre-fill signatures remember_and_pre_fill_signatures: Remember and pre-fill signatures
require_authentication_for_file_download_links: Require authentication for file download links require_authentication_for_file_download_links: Require authentication for file download links
combine_completed_documents_and_audit_log: Combine completed documents and Audit Log combine_completed_documents_and_audit_log: Combine completed documents and Audit Log
@ -787,6 +791,7 @@ en: &en
share_link: Share link share_link: Share link
enable_shared_link: Enable shared link enable_shared_link: Enable shared link
share_link_is_currently_disabled: Share link is currently disabled share_link_is_currently_disabled: Share link is currently disabled
dynamic_template_with_variables_cannot_be_used_via_shared_link: Dynamic template with variables can't be used via a shared link
select_data_residency: Select data residency select_data_residency: Select data residency
account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: '%{account_name} has invited you to fill and sign documents online effortlessly with a secure, fast, and user-friendly digital document signing solution.' account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: '%{account_name} has invited you to fill and sign documents online effortlessly with a secure, fast, and user-friendly digital document signing solution.'
review_or_download_completed_documents_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: Review or download completed documents. Fill and sign documents online effortlessly with a secure, fast, and user-friendly digital document signing solution. review_or_download_completed_documents_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: Review or download completed documents. Fill and sign documents online effortlessly with a secure, fast, and user-friendly digital document signing solution.
@ -841,6 +846,7 @@ en: &en
allow_signers_to_create_signatures_by_typing_their_name_instead_of_drawing_or_uploading_one: Allow signers to create signatures by typing their name instead of drawing or uploading one. allow_signers_to_create_signatures_by_typing_their_name_instead_of_drawing_or_uploading_one: Allow signers to create signatures by typing their name instead of drawing or uploading one.
allow_signers_to_resubmit_forms_after_completion_useful_when_corrections_or_multiple_submissions_are_needed: Allow signers to resubmit forms after completion, useful when corrections or multiple submissions are needed. allow_signers_to_resubmit_forms_after_completion_useful_when_corrections_or_multiple_submissions_are_needed: Allow signers to resubmit forms after completion, useful when corrections or multiple submissions are needed.
allow_recipients_to_decline_signing_a_document_the_decline_reason_notification_will_be_sent_to_the_signature_requester: Allow recipients to decline signing a document. The decline reason notification will be sent to the signature requester. allow_recipients_to_decline_signing_a_document_the_decline_reason_notification_will_be_sent_to_the_signature_requester: Allow recipients to decline signing a document. The decline reason notification will be sent to the signature requester.
allow_recipients_to_delegate_documents: Allow recipients to delegate documents to a different person via email. This can be useful when the original recipient needs to pass the document to the authorized signer.
save_a_users_signature_and_automatically_pre_fill_it_in_future_signing_sessions: "Save a user's signature and automatically pre-fill it in future signing sessions." save_a_users_signature_and_automatically_pre_fill_it_in_future_signing_sessions: "Save a user's signature and automatically pre-fill it in future signing sessions."
make_document_download_links_expire_after_40_minutes_to_prevent_long_term_access_and_enhance_security: Make document download links expire after 40 minutes to prevent long-term access and enhance security. make_document_download_links_expire_after_40_minutes_to_prevent_long_term_access_and_enhance_security: Make document download links expire after 40 minutes to prevent long-term access and enhance security.
require_authentication_with_user_login_or_api_key_to_access_the_document_download_links: Require authentication with user login or API key to access the document download links. require_authentication_with_user_login_or_api_key_to_access_the_document_download_links: Require authentication with user login or API key to access the document download links.
@ -954,6 +960,8 @@ en: &en
complete_kba_by_html: '<b>KBA completed</b> by %{submitter_name}' complete_kba_by_html: '<b>KBA completed</b> by %{submitter_name}'
fail_kba_by_html: '<b>KBA failed</b> by %{submitter_name}' fail_kba_by_html: '<b>KBA failed</b> by %{submitter_name}'
api_complete_form_by_html: '<b>Submission completed via API</b> by %{submitter_name}' api_complete_form_by_html: '<b>Submission completed via API</b> by %{submitter_name}'
decline_form_by_html: '<b>Form declined</b> by %{submitter_name}'
delegate_form_by_html: '<b>Delegated</b> from %{from} to %{to}'
import_list: import_list:
select_worksheet: Select Worksheet select_worksheet: Select Worksheet
open: Open open: Open
@ -1192,11 +1200,14 @@ es: &es
downloading: Descargando downloading: Descargando
download: Descargar download: Descargar
decline: Rechazar decline: Rechazar
delegate: Delegar
enter_the_email_address_of_the_person_you_want_to_delegate_to: Ingrese la dirección de correo electrónico de la persona a quien desea delegar
declined: Rechazado declined: Rechazado
decline_reason: Motivo de rechazo decline_reason: Motivo de rechazo
provide_a_reason: Proporcione un motivo provide_a_reason: Proporcione un motivo
notify_the_sender_with_the_reason_you_declined: Notifique al remitente con el motivo por el que rechazó notify_the_sender_with_the_reason_you_declined: Notifique al remitente con el motivo por el que rechazó
form_has_been_declined_on_html: 'El formulario ha sido rechazado el <span class="font-semibold">%{time}</span>' form_has_been_declined_on_html: 'El formulario ha sido rechazado el <span class="font-semibold">%{time}</span>'
document_has_been_delegated_on_html: 'El documento ha sido delegado el <span class="font-semibold">%{time}</span>'
name_declined_by_submitter: '"%{name}" rechazado por %{submitter}' name_declined_by_submitter: '"%{name}" rechazado por %{submitter}'
name_declined_by_submitter_with_the_following_reason: '"%{name}" ha sido rechazado por %{submitter} con el siguiente motivo:' name_declined_by_submitter_with_the_following_reason: '"%{name}" ha sido rechazado por %{submitter} con el siguiente motivo:'
completed_successfully: Completado exitosamente completed_successfully: Completado exitosamente
@ -1231,6 +1242,7 @@ es: &es
allow_typed_text_signatures: Permitir firmas de texto mecanografiadas allow_typed_text_signatures: Permitir firmas de texto mecanografiadas
allow_to_resubmit_completed_forms: Permitir reenviar formularios completados allow_to_resubmit_completed_forms: Permitir reenviar formularios completados
allow_to_decline_documents: Permitir rechazar documentos allow_to_decline_documents: Permitir rechazar documentos
allow_to_delegate_documents: Permitir delegar documentos
remember_and_pre_fill_signatures: Recordar y prellenar firmas remember_and_pre_fill_signatures: Recordar y prellenar firmas
require_authentication_for_file_download_links: Requerir autenticación para enlaces de descarga de archivos require_authentication_for_file_download_links: Requerir autenticación para enlaces de descarga de archivos
combine_completed_documents_and_audit_log: Combinar documentos completados y Registro de Auditoría combine_completed_documents_and_audit_log: Combinar documentos completados y Registro de Auditoría
@ -1814,6 +1826,7 @@ es: &es
share_link: Enlace para compartir share_link: Enlace para compartir
enable_shared_link: Habilitar enlace compartido enable_shared_link: Habilitar enlace compartido
share_link_is_currently_disabled: El enlace compartido está deshabilitado actualmente share_link_is_currently_disabled: El enlace compartido está deshabilitado actualmente
dynamic_template_with_variables_cannot_be_used_via_shared_link: La plantilla dinámica con variables no se puede usar mediante un enlace compartido
select_data_residency: Seleccionar ubicación de datos select_data_residency: Seleccionar ubicación de datos
account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: '%{account_name} te ha invitado a completar y firmar documentos en línea fácilmente con una solución de firma digital segura, rápida y fácil de usar.' account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: '%{account_name} te ha invitado a completar y firmar documentos en línea fácilmente con una solución de firma digital segura, rápida y fácil de usar.'
review_or_download_completed_documents_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: Revisa o descarga los documentos completados. Completa y firma documentos en línea fácilmente con una solución de firma digital segura, rápida y fácil de usar. review_or_download_completed_documents_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: Revisa o descarga los documentos completados. Completa y firma documentos en línea fácilmente con una solución de firma digital segura, rápida y fácil de usar.
@ -1868,6 +1881,7 @@ es: &es
allow_signers_to_create_signatures_by_typing_their_name_instead_of_drawing_or_uploading_one: Permitir que los firmantes creen firmas escribiendo su nombre en lugar de dibujar o subir una. allow_signers_to_create_signatures_by_typing_their_name_instead_of_drawing_or_uploading_one: Permitir que los firmantes creen firmas escribiendo su nombre en lugar de dibujar o subir una.
allow_signers_to_resubmit_forms_after_completion_useful_when_corrections_or_multiple_submissions_are_needed: Permitir que los firmantes vuelvan a enviar formularios después de completarlos, útil cuando se necesitan correcciones o múltiples envíos. allow_signers_to_resubmit_forms_after_completion_useful_when_corrections_or_multiple_submissions_are_needed: Permitir que los firmantes vuelvan a enviar formularios después de completarlos, útil cuando se necesitan correcciones o múltiples envíos.
allow_recipients_to_decline_signing_a_document_the_decline_reason_notification_will_be_sent_to_the_signature_requester: Permitir que los destinatarios rechacen firmar un documento. La notificación del motivo del rechazo se enviará al solicitante de la firma. allow_recipients_to_decline_signing_a_document_the_decline_reason_notification_will_be_sent_to_the_signature_requester: Permitir que los destinatarios rechacen firmar un documento. La notificación del motivo del rechazo se enviará al solicitante de la firma.
allow_recipients_to_delegate_documents: Permitir que los destinatarios deleguen documentos a otra persona por correo electrónico. Esto puede ser útil cuando el destinatario original necesita pasar el documento al firmante autorizado.
save_a_users_signature_and_automatically_pre_fill_it_in_future_signing_sessions: Guardar la firma de un usuario y rellenarla automáticamente en futuras sesiones de firma. save_a_users_signature_and_automatically_pre_fill_it_in_future_signing_sessions: Guardar la firma de un usuario y rellenarla automáticamente en futuras sesiones de firma.
make_document_download_links_expire_after_40_minutes_to_prevent_long_term_access_and_enhance_security: Hacer que los enlaces de descarga de documentos caduquen después de 40 minutos para evitar el acceso a largo plazo y mejorar la seguridad. make_document_download_links_expire_after_40_minutes_to_prevent_long_term_access_and_enhance_security: Hacer que los enlaces de descarga de documentos caduquen después de 40 minutos para evitar el acceso a largo plazo y mejorar la seguridad.
require_authentication_with_user_login_or_api_key_to_access_the_document_download_links: Requerir autenticación con inicio de sesión de usuario o clave API para acceder a los enlaces de descarga de documentos. require_authentication_with_user_login_or_api_key_to_access_the_document_download_links: Requerir autenticación con inicio de sesión de usuario o clave API para acceder a los enlaces de descarga de documentos.
@ -1976,6 +1990,8 @@ es: &es
invite_party_by_html: '<b>Invitado</b> %{invited_submitter_name} por %{submitter_name}' invite_party_by_html: '<b>Invitado</b> %{invited_submitter_name} por %{submitter_name}'
complete_form_by_html: '<b>Envío completado</b> por %{submitter_name}' complete_form_by_html: '<b>Envío completado</b> por %{submitter_name}'
api_complete_form_by_html: '<b>Envío completado vía API</b> por %{submitter_name}' api_complete_form_by_html: '<b>Envío completado vía API</b> por %{submitter_name}'
decline_form_by_html: '<b>Formulario rechazado</b> por %{submitter_name}'
delegate_form_by_html: '<b>Delegado</b> de %{from} a %{to}'
start_verification_by_html: '<b>Verificación de identidad iniciada</b> por %{submitter_name}' start_verification_by_html: '<b>Verificación de identidad iniciada</b> por %{submitter_name}'
complete_verification_by_html: '<b>Verificación de identidad completada</b> por %{submitter_name} con %{provider}' complete_verification_by_html: '<b>Verificación de identidad completada</b> por %{submitter_name} con %{provider}'
start_kba_by_html: '<b>KBA iniciado</b> por %{submitter_name}' start_kba_by_html: '<b>KBA iniciado</b> por %{submitter_name}'
@ -2219,11 +2235,14 @@ it: &it
downloading: Scaricamento downloading: Scaricamento
download: Scarica download: Scarica
decline: Rifiuta decline: Rifiuta
delegate: Delega
enter_the_email_address_of_the_person_you_want_to_delegate_to: Inserisci l'indirizzo email della persona a cui vuoi delegare
declined: Rifiutato declined: Rifiutato
decline_reason: Motivo del rifiuto decline_reason: Motivo del rifiuto
provide_a_reason: Fornisci un motivo provide_a_reason: Fornisci un motivo
notify_the_sender_with_the_reason_you_declined: Informare il mittente del motivo per cui hai rifiutato notify_the_sender_with_the_reason_you_declined: Informare il mittente del motivo per cui hai rifiutato
form_has_been_declined_on_html: 'Il modulo è stato rifiutato il <span class="font-semibold">%{time}</span>' form_has_been_declined_on_html: 'Il modulo è stato rifiutato il <span class="font-semibold">%{time}</span>'
document_has_been_delegated_on_html: 'Il documento è stato delegato il <span class="font-semibold">%{time}</span>'
name_declined_by_submitter: '"%{name}" rifiutato da %{submitter}' name_declined_by_submitter: '"%{name}" rifiutato da %{submitter}'
name_declined_by_submitter_with_the_following_reason: '"%{name}" è stato rifiutato da %{submitter} per il seguente motivo:' name_declined_by_submitter_with_the_following_reason: '"%{name}" è stato rifiutato da %{submitter} per il seguente motivo:'
completed_successfully: Completato con successo completed_successfully: Completato con successo
@ -2258,6 +2277,7 @@ it: &it
allow_typed_text_signatures: Permettere firme con testo digitato allow_typed_text_signatures: Permettere firme con testo digitato
allow_to_resubmit_completed_forms: Permettere di reinviare i moduli completati allow_to_resubmit_completed_forms: Permettere di reinviare i moduli completati
allow_to_decline_documents: Permettere di rifiutare i documenti allow_to_decline_documents: Permettere di rifiutare i documenti
allow_to_delegate_documents: Permettere di delegare i documenti
remember_and_pre_fill_signatures: Ricordare e precompilare le firme remember_and_pre_fill_signatures: Ricordare e precompilare le firme
require_authentication_for_file_download_links: "Richiedere l'autenticazione per i link di download dei file" require_authentication_for_file_download_links: "Richiedere l'autenticazione per i link di download dei file"
combine_completed_documents_and_audit_log: Combinare i documenti completati e il Registro di Audit combine_completed_documents_and_audit_log: Combinare i documenti completati e il Registro di Audit
@ -2841,6 +2861,7 @@ it: &it
share_link: Link di condivisione share_link: Link di condivisione
enable_shared_link: Abilita link condiviso enable_shared_link: Abilita link condiviso
share_link_is_currently_disabled: Il link condiviso è attualmente disabilitato share_link_is_currently_disabled: Il link condiviso è attualmente disabilitato
dynamic_template_with_variables_cannot_be_used_via_shared_link: Il template dinamico con variabili non può essere utilizzato tramite link condiviso
select_data_residency: Seleziona la residenza dei dati select_data_residency: Seleziona la residenza dei dati
account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: '%{account_name} ti ha invitato a compilare e firmare documenti online con facilità utilizzando una soluzione di firma digitale sicura, veloce e facile da usare.' account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: '%{account_name} ti ha invitato a compilare e firmare documenti online con facilità utilizzando una soluzione di firma digitale sicura, veloce e facile da usare.'
review_or_download_completed_documents_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: Rivedi o scarica i documenti completati. Compila e firma documenti online facilmente con una soluzione di firma digitale sicura, veloce e facile da usare. review_or_download_completed_documents_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: Rivedi o scarica i documenti completati. Compila e firma documenti online facilmente con una soluzione di firma digitale sicura, veloce e facile da usare.
@ -2896,6 +2917,7 @@ it: &it
allow_signers_to_create_signatures_by_typing_their_name_instead_of_drawing_or_uploading_one: Consentire ai firmatari di creare firme digitando il proprio nome invece di disegnarle o caricarle. allow_signers_to_create_signatures_by_typing_their_name_instead_of_drawing_or_uploading_one: Consentire ai firmatari di creare firme digitando il proprio nome invece di disegnarle o caricarle.
allow_signers_to_resubmit_forms_after_completion_useful_when_corrections_or_multiple_submissions_are_needed: Consentire ai firmatari di reinviare i moduli dopo il completamento, utile quando sono necessarie correzioni o più invii. allow_signers_to_resubmit_forms_after_completion_useful_when_corrections_or_multiple_submissions_are_needed: Consentire ai firmatari di reinviare i moduli dopo il completamento, utile quando sono necessarie correzioni o più invii.
allow_recipients_to_decline_signing_a_document_the_decline_reason_notification_will_be_sent_to_the_signature_requester: Consentire ai destinatari di rifiutare di firmare un documento. La notifica del motivo del rifiuto verrà inviata al richiedente della firma. allow_recipients_to_decline_signing_a_document_the_decline_reason_notification_will_be_sent_to_the_signature_requester: Consentire ai destinatari di rifiutare di firmare un documento. La notifica del motivo del rifiuto verrà inviata al richiedente della firma.
allow_recipients_to_delegate_documents: Consentire ai destinatari di delegare i documenti a un'altra persona tramite e-mail. Ciò può essere utile quando il destinatario originale deve passare il documento al firmatario autorizzato.
save_a_users_signature_and_automatically_pre_fill_it_in_future_signing_sessions: Salvare la firma di un utente e compilarla automaticamente nelle future sessioni di firma. save_a_users_signature_and_automatically_pre_fill_it_in_future_signing_sessions: Salvare la firma di un utente e compilarla automaticamente nelle future sessioni di firma.
make_document_download_links_expire_after_40_minutes_to_prevent_long_term_access_and_enhance_security: "Fare in modo che i link di download dei documenti scadano dopo 40 minuti per prevenire l'accesso a lungo termine e migliorare la sicurezza." make_document_download_links_expire_after_40_minutes_to_prevent_long_term_access_and_enhance_security: "Fare in modo che i link di download dei documenti scadano dopo 40 minuti per prevenire l'accesso a lungo termine e migliorare la sicurezza."
require_authentication_with_user_login_or_api_key_to_access_the_document_download_links: "Richiedere l'autenticazione con login utente o chiave API per accedere ai link di download dei documenti." require_authentication_with_user_login_or_api_key_to_access_the_document_download_links: "Richiedere l'autenticazione con login utente o chiave API per accedere ai link di download dei documenti."
@ -3004,6 +3026,8 @@ it: &it
invite_party_by_html: '<b>Invitato</b> %{invited_submitter_name} da %{submitter_name}' invite_party_by_html: '<b>Invitato</b> %{invited_submitter_name} da %{submitter_name}'
complete_form_by_html: '<b>Invio completato</b> da %{submitter_name}' complete_form_by_html: '<b>Invio completato</b> da %{submitter_name}'
api_complete_form_by_html: '<b>Invio completato tramite API</b> da %{submitter_name}' api_complete_form_by_html: '<b>Invio completato tramite API</b> da %{submitter_name}'
decline_form_by_html: '<b>Modulo rifiutato</b> da %{submitter_name}'
delegate_form_by_html: '<b>Delegato</b> da %{from} a %{to}'
start_verification_by_html: "<b>Verifica dell'identità iniziata</b> da %{submitter_name}" start_verification_by_html: "<b>Verifica dell'identità iniziata</b> da %{submitter_name}"
complete_verification_by_html: "<b>Verifica dell'identità completata</b> da %{submitter_name} con %{provider}" complete_verification_by_html: "<b>Verifica dell'identità completata</b> da %{submitter_name} con %{provider}"
start_kba_by_html: "<b>KBA avviata</b> da %{submitter_name}" start_kba_by_html: "<b>KBA avviata</b> da %{submitter_name}"
@ -3247,11 +3271,14 @@ fr: &fr
downloading: Téléchargement downloading: Téléchargement
download: Télécharger download: Télécharger
decline: Refuser decline: Refuser
delegate: Déléguer
enter_the_email_address_of_the_person_you_want_to_delegate_to: Saisissez l'adresse e-mail de la personne à qui vous souhaitez déléguer
declined: Refusé declined: Refusé
decline_reason: Motif du refus decline_reason: Motif du refus
provide_a_reason: Fournissez un motif provide_a_reason: Fournissez un motif
notify_the_sender_with_the_reason_you_declined: Notifier lexpéditeur avec le motif du refus notify_the_sender_with_the_reason_you_declined: Notifier lexpéditeur avec le motif du refus
form_has_been_declined_on_html: Le formulaire a été refusé le <span class="font-semibold">%{time}</span> form_has_been_declined_on_html: Le formulaire a été refusé le <span class="font-semibold">%{time}</span>
document_has_been_delegated_on_html: Le document a été délégué le <span class="font-semibold">%{time}</span>
name_declined_by_submitter: '"%{name}" refusé par %{submitter}' name_declined_by_submitter: '"%{name}" refusé par %{submitter}'
name_declined_by_submitter_with_the_following_reason: '"%{name}" a été refusé par %{submitter} pour le motif suivant :' name_declined_by_submitter_with_the_following_reason: '"%{name}" a été refusé par %{submitter} pour le motif suivant :'
completed_successfully: Terminé avec succès completed_successfully: Terminé avec succès
@ -3286,6 +3313,7 @@ fr: &fr
allow_typed_text_signatures: Autoriser les signatures tapées allow_typed_text_signatures: Autoriser les signatures tapées
allow_to_resubmit_completed_forms: Autoriser la nouvelle soumission des formulaires complétés allow_to_resubmit_completed_forms: Autoriser la nouvelle soumission des formulaires complétés
allow_to_decline_documents: Autoriser le refus de documents allow_to_decline_documents: Autoriser le refus de documents
allow_to_delegate_documents: Autoriser la délégation de documents
remember_and_pre_fill_signatures: Mémoriser et pré-remplir les signatures remember_and_pre_fill_signatures: Mémoriser et pré-remplir les signatures
require_authentication_for_file_download_links: Exiger une authentification pour les liens de téléchargement require_authentication_for_file_download_links: Exiger une authentification pour les liens de téléchargement
combine_completed_documents_and_audit_log: Combiner les documents complétés et le journal daudit combine_completed_documents_and_audit_log: Combiner les documents complétés et le journal daudit
@ -3866,6 +3894,7 @@ fr: &fr
share_link: Lien de partage share_link: Lien de partage
enable_shared_link: Activer le lien partagé enable_shared_link: Activer le lien partagé
share_link_is_currently_disabled: Le lien de partage est actuellement désactivé share_link_is_currently_disabled: Le lien de partage est actuellement désactivé
dynamic_template_with_variables_cannot_be_used_via_shared_link: Le modèle dynamique avec des variables ne peut pas être utilisé via un lien partagé
select_data_residency: Sélectionner la résidence des données select_data_residency: Sélectionner la résidence des données
account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: "%{account_name} vous a invité à remplir et signer des documents en ligne facilement, grâce à une solution de signature numérique sécurisée, rapide et conviviale." account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: "%{account_name} vous a invité à remplir et signer des documents en ligne facilement, grâce à une solution de signature numérique sécurisée, rapide et conviviale."
review_or_download_completed_documents_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: Consultez ou téléchargez les documents complétés. Remplissez et signez des documents en ligne facilement, grâce à une solution de signature numérique sécurisée, rapide et conviviale. review_or_download_completed_documents_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: Consultez ou téléchargez les documents complétés. Remplissez et signez des documents en ligne facilement, grâce à une solution de signature numérique sécurisée, rapide et conviviale.
@ -3919,6 +3948,7 @@ fr: &fr
allow_signers_to_create_signatures_by_typing_their_name_instead_of_drawing_or_uploading_one: Autoriser les signataires à créer des signatures en tapant leur nom au lieu de dessiner ou téléverser une signature. allow_signers_to_create_signatures_by_typing_their_name_instead_of_drawing_or_uploading_one: Autoriser les signataires à créer des signatures en tapant leur nom au lieu de dessiner ou téléverser une signature.
allow_signers_to_resubmit_forms_after_completion_useful_when_corrections_or_multiple_submissions_are_needed: Autoriser les signataires à soumettre à nouveau les formulaires après finalisation, utile pour des corrections ou soumissions multiples. allow_signers_to_resubmit_forms_after_completion_useful_when_corrections_or_multiple_submissions_are_needed: Autoriser les signataires à soumettre à nouveau les formulaires après finalisation, utile pour des corrections ou soumissions multiples.
allow_recipients_to_decline_signing_a_document_the_decline_reason_notification_will_be_sent_to_the_signature_requester: Autoriser les destinataires à refuser de signer un document. Le motif du refus sera notifié au demandeur de signature. allow_recipients_to_decline_signing_a_document_the_decline_reason_notification_will_be_sent_to_the_signature_requester: Autoriser les destinataires à refuser de signer un document. Le motif du refus sera notifié au demandeur de signature.
allow_recipients_to_delegate_documents: Autoriser les destinataires à déléguer des documents à une autre personne par e-mail. Cela peut être utile lorsque le destinataire d'origine doit transmettre le document au signataire autorisé.
save_a_users_signature_and_automatically_pre_fill_it_in_future_signing_sessions: Mémoriser la signature dun utilisateur et la préremplir automatiquement lors de futures sessions de signature. save_a_users_signature_and_automatically_pre_fill_it_in_future_signing_sessions: Mémoriser la signature dun utilisateur et la préremplir automatiquement lors de futures sessions de signature.
make_document_download_links_expire_after_40_minutes_to_prevent_long_term_access_and_enhance_security: Faire expirer les liens de téléchargement des documents après 40 minutes pour éviter un accès à long terme et renforcer la sécurité. make_document_download_links_expire_after_40_minutes_to_prevent_long_term_access_and_enhance_security: Faire expirer les liens de téléchargement des documents après 40 minutes pour éviter un accès à long terme et renforcer la sécurité.
require_authentication_with_user_login_or_api_key_to_access_the_document_download_links: Exiger une authentification par connexion utilisateur ou clé API pour accéder aux liens de téléchargement des documents. require_authentication_with_user_login_or_api_key_to_access_the_document_download_links: Exiger une authentification par connexion utilisateur ou clé API pour accéder aux liens de téléchargement des documents.
@ -4030,6 +4060,8 @@ fr: &fr
start_verification_by_html: "<b>Vérification didentité démarrée</b> par %{submitter_name}" start_verification_by_html: "<b>Vérification didentité démarrée</b> par %{submitter_name}"
complete_verification_by_html: "<b>Vérification didentité terminée</b> par %{submitter_name} avec %{provider}" complete_verification_by_html: "<b>Vérification didentité terminée</b> par %{submitter_name} avec %{provider}"
api_complete_form_by_html: "<b>Soumission terminée via API</b> par %{submitter_name}" api_complete_form_by_html: "<b>Soumission terminée via API</b> par %{submitter_name}"
decline_form_by_html: "<b>Formulaire refusé</b> par %{submitter_name}"
delegate_form_by_html: "<b>Délégué</b> de %{from} à %{to}"
start_kba_by_html: "<b>KBA démarré</b> par %{submitter_name}" start_kba_by_html: "<b>KBA démarré</b> par %{submitter_name}"
complete_kba_by_html: "<b>KBA terminé</b> par %{submitter_name}" complete_kba_by_html: "<b>KBA terminé</b> par %{submitter_name}"
fail_kba_by_html: "<b>KBA échoué</b> par %{submitter_name}" fail_kba_by_html: "<b>KBA échoué</b> par %{submitter_name}"
@ -4271,11 +4303,14 @@ pt: &pt
downloading: Baixando downloading: Baixando
download: Baixar download: Baixar
decline: Recusar decline: Recusar
delegate: Delegar
enter_the_email_address_of_the_person_you_want_to_delegate_to: Insira o endereço de e-mail da pessoa para quem deseja delegar
declined: Recusado declined: Recusado
decline_reason: Motivo da recusa decline_reason: Motivo da recusa
provide_a_reason: Forneça um motivo provide_a_reason: Forneça um motivo
notify_the_sender_with_the_reason_you_declined: Notifique o remetente com o motivo da sua recusa notify_the_sender_with_the_reason_you_declined: Notifique o remetente com o motivo da sua recusa
form_has_been_declined_on_html: "O formulário foi recusado em <span class='font-semibold'>%{time}</span>" form_has_been_declined_on_html: "O formulário foi recusado em <span class='font-semibold'>%{time}</span>"
document_has_been_delegated_on_html: "O documento foi delegado em <span class='font-semibold'>%{time}</span>"
name_declined_by_submitter: '"%{name}" foi recusado por %{submitter}' name_declined_by_submitter: '"%{name}" foi recusado por %{submitter}'
name_declined_by_submitter_with_the_following_reason: '"%{name}" foi recusado por %{submitter} com o seguinte motivo:' name_declined_by_submitter_with_the_following_reason: '"%{name}" foi recusado por %{submitter} com o seguinte motivo:'
completed_successfully: Concluído com sucesso completed_successfully: Concluído com sucesso
@ -4310,6 +4345,7 @@ pt: &pt
allow_typed_text_signatures: Permitir assinaturas digitadas allow_typed_text_signatures: Permitir assinaturas digitadas
allow_to_resubmit_completed_forms: Permitir reenviar formulários concluídos allow_to_resubmit_completed_forms: Permitir reenviar formulários concluídos
allow_to_decline_documents: Permitir recusar documentos allow_to_decline_documents: Permitir recusar documentos
allow_to_delegate_documents: Permitir delegar documentos
remember_and_pre_fill_signatures: Lembrar e preencher assinaturas automaticamente remember_and_pre_fill_signatures: Lembrar e preencher assinaturas automaticamente
require_authentication_for_file_download_links: Requerer autenticação para links de download de arquivos require_authentication_for_file_download_links: Requerer autenticação para links de download de arquivos
combine_completed_documents_and_audit_log: Combinar documentos concluídos e log de auditoria combine_completed_documents_and_audit_log: Combinar documentos concluídos e log de auditoria
@ -4893,6 +4929,7 @@ pt: &pt
share_link: Link de compartilhamento share_link: Link de compartilhamento
enable_shared_link: Ativar link compartilhado enable_shared_link: Ativar link compartilhado
share_link_is_currently_disabled: O link compartilhado está desativado no momento share_link_is_currently_disabled: O link compartilhado está desativado no momento
dynamic_template_with_variables_cannot_be_used_via_shared_link: O template dinâmico com variáveis não pode ser usado por meio de link compartilhado
select_data_residency: Selecionar local dos dados select_data_residency: Selecionar local dos dados
account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: '%{account_name} convidou você para preencher e assinar documentos online com facilidade usando uma solução de assinatura digital segura, rápida e fácil de usar.' account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: '%{account_name} convidou você para preencher e assinar documentos online com facilidade usando uma solução de assinatura digital segura, rápida e fácil de usar.'
review_or_download_completed_documents_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: Reveja ou baixe os documentos concluídos. Preencha e assine documentos online com facilidade usando uma solução de assinatura digital segura, rápida e fácil de usar. review_or_download_completed_documents_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: Reveja ou baixe os documentos concluídos. Preencha e assine documentos online com facilidade usando uma solução de assinatura digital segura, rápida e fácil de usar.
@ -4947,6 +4984,7 @@ pt: &pt
allow_signers_to_create_signatures_by_typing_their_name_instead_of_drawing_or_uploading_one: Permitir que os signatários criem assinaturas digitando seu nome em vez de desenhá-las ou carregá-las. allow_signers_to_create_signatures_by_typing_their_name_instead_of_drawing_or_uploading_one: Permitir que os signatários criem assinaturas digitando seu nome em vez de desenhá-las ou carregá-las.
allow_signers_to_resubmit_forms_after_completion_useful_when_corrections_or_multiple_submissions_are_needed: Permitir que os signatários reenviem formulários após o término, útil quando são necessárias correções ou múltiplos envios. allow_signers_to_resubmit_forms_after_completion_useful_when_corrections_or_multiple_submissions_are_needed: Permitir que os signatários reenviem formulários após o término, útil quando são necessárias correções ou múltiplos envios.
allow_recipients_to_decline_signing_a_document_the_decline_reason_notification_will_be_sent_to_the_signature_requester: Permitir que os destinatários recusem assinar um documento. A notificação do motivo da recusa será enviada ao solicitante da assinatura. allow_recipients_to_decline_signing_a_document_the_decline_reason_notification_will_be_sent_to_the_signature_requester: Permitir que os destinatários recusem assinar um documento. A notificação do motivo da recusa será enviada ao solicitante da assinatura.
allow_recipients_to_delegate_documents: Permitir que os destinatários deleguem documentos a outra pessoa por e-mail. Isso pode ser útil quando o destinatário original precisa passar o documento ao signatário autorizado.
save_a_users_signature_and_automatically_pre_fill_it_in_future_signing_sessions: Salvar a assinatura de um usuário e preenchê-la automaticamente em futuras sessões de assinatura. save_a_users_signature_and_automatically_pre_fill_it_in_future_signing_sessions: Salvar a assinatura de um usuário e preenchê-la automaticamente em futuras sessões de assinatura.
make_document_download_links_expire_after_40_minutes_to_prevent_long_term_access_and_enhance_security: Fazer os links de download de documentos expirarem após 40 minutos para evitar o acesso prolongado e aumentar a segurança. make_document_download_links_expire_after_40_minutes_to_prevent_long_term_access_and_enhance_security: Fazer os links de download de documentos expirarem após 40 minutos para evitar o acesso prolongado e aumentar a segurança.
require_authentication_with_user_login_or_api_key_to_access_the_document_download_links: Exigir autenticação com login do usuário ou chave API para acessar os links de download de documentos. require_authentication_with_user_login_or_api_key_to_access_the_document_download_links: Exigir autenticação com login do usuário ou chave API para acessar os links de download de documentos.
@ -5057,6 +5095,8 @@ pt: &pt
start_verification_by_html: '<b>Verificação de identidade iniciada</b> por %{submitter_name}' start_verification_by_html: '<b>Verificação de identidade iniciada</b> por %{submitter_name}'
complete_verification_by_html: '<b>Verificação de identidade concluída</b> por %{submitter_name} com %{provider}' complete_verification_by_html: '<b>Verificação de identidade concluída</b> por %{submitter_name} com %{provider}'
api_complete_form_by_html: '<b>Submissão concluída via API</b> por %{submitter_name}' api_complete_form_by_html: '<b>Submissão concluída via API</b> por %{submitter_name}'
decline_form_by_html: '<b>Formulário recusado</b> por %{submitter_name}'
delegate_form_by_html: '<b>Delegado</b> de %{from} para %{to}'
start_kba_by_html: '<b>KBA iniciada</b> por %{submitter_name}' start_kba_by_html: '<b>KBA iniciada</b> por %{submitter_name}'
complete_kba_by_html: '<b>KBA concluída</b> por %{submitter_name}' complete_kba_by_html: '<b>KBA concluída</b> por %{submitter_name}'
fail_kba_by_html: '<b>KBA reprovada</b> por %{submitter_name}' fail_kba_by_html: '<b>KBA reprovada</b> por %{submitter_name}'
@ -5298,11 +5338,14 @@ de: &de
downloading: Wird heruntergeladen downloading: Wird heruntergeladen
download: Download download: Download
decline: Ablehnen decline: Ablehnen
delegate: Delegieren
enter_the_email_address_of_the_person_you_want_to_delegate_to: Geben Sie die E-Mail-Adresse der Person ein, an die Sie delegieren möchten
declined: Abgelehnt declined: Abgelehnt
decline_reason: Ablehnungsgrund decline_reason: Ablehnungsgrund
provide_a_reason: Geben Sie einen Grund an provide_a_reason: Geben Sie einen Grund an
notify_the_sender_with_the_reason_you_declined: Den Absender über den Grund Ihrer Ablehnung benachrichtigen notify_the_sender_with_the_reason_you_declined: Den Absender über den Grund Ihrer Ablehnung benachrichtigen
form_has_been_declined_on_html: "Das Formular wurde am <span class='font-semibold'>%{time}</span> abgelehnt" form_has_been_declined_on_html: "Das Formular wurde am <span class='font-semibold'>%{time}</span> abgelehnt"
document_has_been_delegated_on_html: "Das Dokument wurde am <span class='font-semibold'>%{time}</span> delegiert"
name_declined_by_submitter: '"%{name}" wurde von %{submitter} abgelehnt' name_declined_by_submitter: '"%{name}" wurde von %{submitter} abgelehnt'
name_declined_by_submitter_with_the_following_reason: '"%{name}" wurde von %{submitter} mit folgendem Grund abgelehnt:' name_declined_by_submitter_with_the_following_reason: '"%{name}" wurde von %{submitter} mit folgendem Grund abgelehnt:'
completed_successfully: Erfolgreich abgeschlossen completed_successfully: Erfolgreich abgeschlossen
@ -5337,6 +5380,7 @@ de: &de
allow_typed_text_signatures: Getippte Unterschriften zulassen allow_typed_text_signatures: Getippte Unterschriften zulassen
allow_to_resubmit_completed_forms: Erneutes Einreichen abgeschlossener Formulare zulassen allow_to_resubmit_completed_forms: Erneutes Einreichen abgeschlossener Formulare zulassen
allow_to_decline_documents: Ablehnen von Dokumenten erlauben allow_to_decline_documents: Ablehnen von Dokumenten erlauben
allow_to_delegate_documents: Delegieren von Dokumenten erlauben
remember_and_pre_fill_signatures: Signaturen merken und vorab ausfüllen remember_and_pre_fill_signatures: Signaturen merken und vorab ausfüllen
require_authentication_for_file_download_links: Authentifizierung für Dateidownload-Links erforderlich require_authentication_for_file_download_links: Authentifizierung für Dateidownload-Links erforderlich
combine_completed_documents_and_audit_log: Abgeschlossene Dokumente und Prüfprotokoll kombinieren combine_completed_documents_and_audit_log: Abgeschlossene Dokumente und Prüfprotokoll kombinieren
@ -5920,6 +5964,7 @@ de: &de
share_link: Freigabelink share_link: Freigabelink
enable_shared_link: Freigabelink aktivieren enable_shared_link: Freigabelink aktivieren
share_link_is_currently_disabled: Freigabelink ist derzeit deaktiviert share_link_is_currently_disabled: Freigabelink ist derzeit deaktiviert
dynamic_template_with_variables_cannot_be_used_via_shared_link: Dynamische Vorlage mit Variablen kann nicht über einen Freigabelink verwendet werden
select_data_residency: Datenstandort auswählen select_data_residency: Datenstandort auswählen
account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: '%{account_name} hat Sie eingeladen, Dokumente mühelos online mit einer sicheren, schnellen und benutzerfreundlichen digitalen Signaturlösung auszufüllen und zu unterschreiben.' account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: '%{account_name} hat Sie eingeladen, Dokumente mühelos online mit einer sicheren, schnellen und benutzerfreundlichen digitalen Signaturlösung auszufüllen und zu unterschreiben.'
review_or_download_completed_documents_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: Überprüfen oder laden Sie abgeschlossene Dokumente herunter. Füllen und unterschreiben Sie Dokumente mühelos online mit einer sicheren, schnellen und benutzerfreundlichen digitalen Signaturlösung. review_or_download_completed_documents_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: Überprüfen oder laden Sie abgeschlossene Dokumente herunter. Füllen und unterschreiben Sie Dokumente mühelos online mit einer sicheren, schnellen und benutzerfreundlichen digitalen Signaturlösung.
@ -5974,6 +6019,7 @@ de: &de
allow_signers_to_create_signatures_by_typing_their_name_instead_of_drawing_or_uploading_one: Unterzeichner dürfen Signaturen erstellen, indem sie ihren Namen eingeben, statt eine Signatur zu zeichnen oder hochzuladen. allow_signers_to_create_signatures_by_typing_their_name_instead_of_drawing_or_uploading_one: Unterzeichner dürfen Signaturen erstellen, indem sie ihren Namen eingeben, statt eine Signatur zu zeichnen oder hochzuladen.
allow_signers_to_resubmit_forms_after_completion_useful_when_corrections_or_multiple_submissions_are_needed: Unterzeichner dürfen Formulare nach Abschluss erneut einreichen nützlich für Korrekturen oder mehrere Einreichungen. allow_signers_to_resubmit_forms_after_completion_useful_when_corrections_or_multiple_submissions_are_needed: Unterzeichner dürfen Formulare nach Abschluss erneut einreichen nützlich für Korrekturen oder mehrere Einreichungen.
allow_recipients_to_decline_signing_a_document_the_decline_reason_notification_will_be_sent_to_the_signature_requester: Empfänger dürfen die Unterzeichnung eines Dokuments ablehnen. Die Benachrichtigung mit dem Ablehnungsgrund wird an den Anforderer der Signatur gesendet. allow_recipients_to_decline_signing_a_document_the_decline_reason_notification_will_be_sent_to_the_signature_requester: Empfänger dürfen die Unterzeichnung eines Dokuments ablehnen. Die Benachrichtigung mit dem Ablehnungsgrund wird an den Anforderer der Signatur gesendet.
allow_recipients_to_delegate_documents: Empfängern erlauben, Dokumente per E-Mail an eine andere Person weiterzuleiten. Dies kann nützlich sein, wenn der ursprüngliche Empfänger das Dokument an den autorisierten Unterzeichner weiterleiten muss.
save_a_users_signature_and_automatically_pre_fill_it_in_future_signing_sessions: Die Signatur eines Benutzers speichern und sie in zukünftigen Signatursitzungen automatisch vorausfüllen. save_a_users_signature_and_automatically_pre_fill_it_in_future_signing_sessions: Die Signatur eines Benutzers speichern und sie in zukünftigen Signatursitzungen automatisch vorausfüllen.
make_document_download_links_expire_after_40_minutes_to_prevent_long_term_access_and_enhance_security: Download-Links für Dokumente nach 40 Minuten ablaufen lassen, um langfristigen Zugriff zu verhindern und die Sicherheit zu erhöhen. make_document_download_links_expire_after_40_minutes_to_prevent_long_term_access_and_enhance_security: Download-Links für Dokumente nach 40 Minuten ablaufen lassen, um langfristigen Zugriff zu verhindern und die Sicherheit zu erhöhen.
require_authentication_with_user_login_or_api_key_to_access_the_document_download_links: Authentifizierung mit Benutzeranmeldung oder API-Schlüssel erforderlich, um auf die Download-Links für Dokumente zuzugreifen. require_authentication_with_user_login_or_api_key_to_access_the_document_download_links: Authentifizierung mit Benutzeranmeldung oder API-Schlüssel erforderlich, um auf die Download-Links für Dokumente zuzugreifen.
@ -6084,6 +6130,8 @@ de: &de
start_verification_by_html: '<b>Identitätsüberprüfung gestartet</b> von %{submitter_name}' start_verification_by_html: '<b>Identitätsüberprüfung gestartet</b> von %{submitter_name}'
complete_verification_by_html: '<b>Identitätsüberprüfung abgeschlossen</b> von %{submitter_name} mit %{provider}' complete_verification_by_html: '<b>Identitätsüberprüfung abgeschlossen</b> von %{submitter_name} mit %{provider}'
api_complete_form_by_html: '<b>Einreichung über API abgeschlossen</b> von %{submitter_name}' api_complete_form_by_html: '<b>Einreichung über API abgeschlossen</b> von %{submitter_name}'
decline_form_by_html: '<b>Formular abgelehnt</b> von %{submitter_name}'
delegate_form_by_html: '<b>Delegiert</b> von %{from} an %{to}'
start_kba_by_html: '<b>KBA gestartet</b> von %{submitter_name}' start_kba_by_html: '<b>KBA gestartet</b> von %{submitter_name}'
complete_kba_by_html: '<b>KBA abgeschlossen</b> von %{submitter_name}' complete_kba_by_html: '<b>KBA abgeschlossen</b> von %{submitter_name}'
fail_kba_by_html: '<b>KBA fehlgeschlagen</b> von %{submitter_name}' fail_kba_by_html: '<b>KBA fehlgeschlagen</b> von %{submitter_name}'
@ -6190,11 +6238,14 @@ pl:
hi_there: Cześć, hi_there: Cześć,
download: Pobierz download: Pobierz
decline: Odrzuć decline: Odrzuć
delegate: Deleguj
enter_the_email_address_of_the_person_you_want_to_delegate_to: Wprowadź adres e-mail osoby, do której chcesz delegować
declined: Odrzucono declined: Odrzucono
decline_reason: Powód odrzucenia decline_reason: Powód odrzucenia
provide_a_reason: Podaj powód provide_a_reason: Podaj powód
notify_the_sender_with_the_reason_you_declined: Powiadom nadawcę o powodzie, dla którego odrzuciłeś notify_the_sender_with_the_reason_you_declined: Powiadom nadawcę o powodzie, dla którego odrzuciłeś
form_has_been_declined_on_html: 'Formularz został odrzucony o <span class="font-semibold">%{time}</span>' form_has_been_declined_on_html: 'Formularz został odrzucony o <span class="font-semibold">%{time}</span>'
document_has_been_delegated_on_html: 'Dokument został oddelegowany o <span class="font-semibold">%{time}</span>'
name_declined_by_submitter: '"%{name}" odrzucono przez %{submitter}' name_declined_by_submitter: '"%{name}" odrzucono przez %{submitter}'
name_declined_by_submitter_with_the_following_reason: '"%{name}" został odrzucony przez %{submitter} z następującym powodem:' name_declined_by_submitter_with_the_following_reason: '"%{name}" został odrzucony przez %{submitter} z następującym powodem:'
email: E-mail email: E-mail
@ -6287,11 +6338,14 @@ uk:
hi_there: Привіт, hi_there: Привіт,
download: Завантажити download: Завантажити
decline: Відхилити decline: Відхилити
delegate: Делегувати
enter_the_email_address_of_the_person_you_want_to_delegate_to: Введіть адресу електронної пошти особи, якій ви хочете делегувати
declined: Відхилено declined: Відхилено
decline_reason: Причина відхилення decline_reason: Причина відхилення
provide_a_reason: Надайте причину provide_a_reason: Надайте причину
notify_the_sender_with_the_reason_you_declined: Повідомте відправника про причину, з якої ви відхилили notify_the_sender_with_the_reason_you_declined: Повідомте відправника про причину, з якої ви відхилили
form_has_been_declined_on_html: 'Форму було відхилено о <span class="font-semibold">%{time}</span>' form_has_been_declined_on_html: 'Форму було відхилено о <span class="font-semibold">%{time}</span>'
document_has_been_delegated_on_html: 'Документ було делеговано о <span class="font-semibold">%{time}</span>'
name_declined_by_submitter: '"%{name}" відхилено %{submitter}' name_declined_by_submitter: '"%{name}" відхилено %{submitter}'
name_declined_by_submitter_with_the_following_reason: '"%{name}" було відхилено %{submitter} з такою причиною:' name_declined_by_submitter_with_the_following_reason: '"%{name}" було відхилено %{submitter} з такою причиною:'
email: E-mail email: E-mail
@ -6384,11 +6438,14 @@ cs:
hi_there: Ahoj, hi_there: Ahoj,
download: Stáhnout download: Stáhnout
decline: Odmítnout decline: Odmítnout
delegate: Delegovat
enter_the_email_address_of_the_person_you_want_to_delegate_to: Zadejte e-mailovou adresu osoby, na kterou chcete delegovat
declined: Odmítnuto declined: Odmítnuto
decline_reason: Důvod odmítnutí decline_reason: Důvod odmítnutí
provide_a_reason: Uveďte důvod provide_a_reason: Uveďte důvod
notify_the_sender_with_the_reason_you_declined: Informujte odesílatele o důvodu odmítnutí notify_the_sender_with_the_reason_you_declined: Informujte odesílatele o důvodu odmítnutí
form_has_been_declined_on_html: 'Formulář byl odmítnut dne <span class="font-semibold">%{time}</span>' form_has_been_declined_on_html: 'Formulář byl odmítnut dne <span class="font-semibold">%{time}</span>'
document_has_been_delegated_on_html: 'Dokument byl delegován dne <span class="font-semibold">%{time}</span>'
name_declined_by_submitter: '"%{name}" odmítnuto %{submitter}' name_declined_by_submitter: '"%{name}" odmítnuto %{submitter}'
name_declined_by_submitter_with_the_following_reason: '"%{name}" bylo odmítnuto %{submitter} s následujícím důvodem:' name_declined_by_submitter_with_the_following_reason: '"%{name}" bylo odmítnuto %{submitter} s následujícím důvodem:'
email: E-mail email: E-mail
@ -6481,11 +6538,14 @@ he:
hi_there: שלום, hi_there: שלום,
download: הורד download: הורד
decline: דחייה decline: דחייה
delegate: הואלה
enter_the_email_address_of_the_person_you_want_to_delegate_to: הזן את כתובת הדוא"ל של האדם שברצונך להאציל אליו
declined: דחוי declined: דחוי
decline_reason: סיבת דחייה decline_reason: סיבת דחייה
provide_a_reason: אנא ספק סיבה provide_a_reason: אנא ספק סיבה
notify_the_sender_with_the_reason_you_declined: הודע לשולח על הסיבה לדחייה notify_the_sender_with_the_reason_you_declined: הודע לשולח על הסיבה לדחייה
form_has_been_declined_on_html: 'הטופס נדחה בתאריך <span class="font-semibold">%{time}</span>' form_has_been_declined_on_html: 'הטופס נדחה בתאריך <span class="font-semibold">%{time}</span>'
document_has_been_delegated_on_html: 'המסמך הועבר בתאריך <span class="font-semibold">%{time}</span>'
name_declined_by_submitter: '"%{name}" נדחה על ידי %{submitter}' name_declined_by_submitter: '"%{name}" נדחה על ידי %{submitter}'
name_declined_by_submitter_with_the_following_reason: '"%{name}" נדחה על ידי %{submitter} עם הסיבה הבאה:' name_declined_by_submitter_with_the_following_reason: '"%{name}" נדחה על ידי %{submitter} עם הסיבה הבאה:'
email: דוא"ל email: דוא"ל
@ -6714,11 +6774,14 @@ nl: &nl
downloading: Downloaden downloading: Downloaden
download: Downloaden download: Downloaden
decline: Weigeren decline: Weigeren
delegate: Delegeren
enter_the_email_address_of_the_person_you_want_to_delegate_to: Voer het e-mailadres in van de persoon aan wie u wilt delegeren
declined: Geweigerd declined: Geweigerd
decline_reason: Reden van weigering decline_reason: Reden van weigering
provide_a_reason: Geef een reden op provide_a_reason: Geef een reden op
notify_the_sender_with_the_reason_you_declined: Informeer de verzender over de reden van uw weigering notify_the_sender_with_the_reason_you_declined: Informeer de verzender over de reden van uw weigering
form_has_been_declined_on_html: Formulier is geweigerd op <span class="font-semibold">%{time}</span> form_has_been_declined_on_html: Formulier is geweigerd op <span class="font-semibold">%{time}</span>
document_has_been_delegated_on_html: Document is gedelegeerd op <span class="font-semibold">%{time}</span>
name_declined_by_submitter: '"%{name}" geweigerd door %{submitter}' name_declined_by_submitter: '"%{name}" geweigerd door %{submitter}'
name_declined_by_submitter_with_the_following_reason: '"%{name}" is geweigerd door %{submitter} met de volgende reden:' name_declined_by_submitter_with_the_following_reason: '"%{name}" is geweigerd door %{submitter} met de volgende reden:'
completed_successfully: Succesvol voltooid completed_successfully: Succesvol voltooid
@ -6753,6 +6816,7 @@ nl: &nl
allow_typed_text_signatures: Handtekeningen met getypte tekst toestaan allow_typed_text_signatures: Handtekeningen met getypte tekst toestaan
allow_to_resubmit_completed_forms: Opnieuw indienen van voltooide formulieren toestaan allow_to_resubmit_completed_forms: Opnieuw indienen van voltooide formulieren toestaan
allow_to_decline_documents: Weigeren van documenten toestaan allow_to_decline_documents: Weigeren van documenten toestaan
allow_to_delegate_documents: Delegeren van documenten toestaan
remember_and_pre_fill_signatures: Handtekeningen onthouden en vooraf invullen remember_and_pre_fill_signatures: Handtekeningen onthouden en vooraf invullen
require_authentication_for_file_download_links: Authenticatie vereisen voor links naar bestandsdownloads require_authentication_for_file_download_links: Authenticatie vereisen voor links naar bestandsdownloads
combine_completed_documents_and_audit_log: Voltooide documenten en auditlogboek combineren combine_completed_documents_and_audit_log: Voltooide documenten en auditlogboek combineren
@ -7333,6 +7397,7 @@ nl: &nl
share_link: Deellink share_link: Deellink
enable_shared_link: Deellink inschakelen enable_shared_link: Deellink inschakelen
share_link_is_currently_disabled: Deellink is momenteel uitgeschakeld share_link_is_currently_disabled: Deellink is momenteel uitgeschakeld
dynamic_template_with_variables_cannot_be_used_via_shared_link: Dynamisch sjabloon met variabelen kan niet worden gebruikt via een deellink
select_data_residency: Gegevensresidentie selecteren select_data_residency: Gegevensresidentie selecteren
account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: "%{account_name} heeft u uitgenodigd om documenten online moeiteloos in te vullen en te ondertekenen met een veilige, snelle en gebruiksvriendelijke digitale ondertekenoplossing." account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: "%{account_name} heeft u uitgenodigd om documenten online moeiteloos in te vullen en te ondertekenen met een veilige, snelle en gebruiksvriendelijke digitale ondertekenoplossing."
review_or_download_completed_documents_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: Bekijk of download voltooide documenten. Vul en onderteken documenten online moeiteloos met een veilige, snelle en gebruiksvriendelijke digitale ondertekenoplossing. review_or_download_completed_documents_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution: Bekijk of download voltooide documenten. Vul en onderteken documenten online moeiteloos met een veilige, snelle en gebruiksvriendelijke digitale ondertekenoplossing.
@ -7386,6 +7451,7 @@ nl: &nl
allow_signers_to_create_signatures_by_typing_their_name_instead_of_drawing_or_uploading_one: Sta ondertekenaars toe handtekeningen te maken door hun naam te typen in plaats van te tekenen of te uploaden. allow_signers_to_create_signatures_by_typing_their_name_instead_of_drawing_or_uploading_one: Sta ondertekenaars toe handtekeningen te maken door hun naam te typen in plaats van te tekenen of te uploaden.
allow_signers_to_resubmit_forms_after_completion_useful_when_corrections_or_multiple_submissions_are_needed: Sta ondertekenaars toe formulieren na voltooiing opnieuw in te dienen; nuttig wanneer correcties of meerdere inzendingen nodig zijn. allow_signers_to_resubmit_forms_after_completion_useful_when_corrections_or_multiple_submissions_are_needed: Sta ondertekenaars toe formulieren na voltooiing opnieuw in te dienen; nuttig wanneer correcties of meerdere inzendingen nodig zijn.
allow_recipients_to_decline_signing_a_document_the_decline_reason_notification_will_be_sent_to_the_signature_requester: Sta ontvangers toe het ondertekenen van een document te weigeren. De melding met de reden van weigering wordt naar de aanvrager van de handtekening gestuurd. allow_recipients_to_decline_signing_a_document_the_decline_reason_notification_will_be_sent_to_the_signature_requester: Sta ontvangers toe het ondertekenen van een document te weigeren. De melding met de reden van weigering wordt naar de aanvrager van de handtekening gestuurd.
allow_recipients_to_delegate_documents: Sta ontvangers toe documenten per e-mail te delegeren aan een andere persoon. Dit kan handig zijn wanneer de oorspronkelijke ontvanger het document moet doorgeven aan de gemachtigde ondertekenaar.
save_a_users_signature_and_automatically_pre_fill_it_in_future_signing_sessions: Sla de handtekening van een gebruiker op en vul deze automatisch vooraf in bij toekomstige ondertekeningssessies. save_a_users_signature_and_automatically_pre_fill_it_in_future_signing_sessions: Sla de handtekening van een gebruiker op en vul deze automatisch vooraf in bij toekomstige ondertekeningssessies.
make_document_download_links_expire_after_40_minutes_to_prevent_long_term_access_and_enhance_security: Laat links voor het downloaden van documenten na 40 minuten verlopen om langdurige toegang te voorkomen en de beveiliging te verbeteren. make_document_download_links_expire_after_40_minutes_to_prevent_long_term_access_and_enhance_security: Laat links voor het downloaden van documenten na 40 minuten verlopen om langdurige toegang te voorkomen en de beveiliging te verbeteren.
require_authentication_with_user_login_or_api_key_to_access_the_document_download_links: Authenticatie met gebruikerslogin of API-sleutel vereisen om toegang te krijgen tot de documentdownloadlinks. require_authentication_with_user_login_or_api_key_to_access_the_document_download_links: Authenticatie met gebruikerslogin of API-sleutel vereisen om toegang te krijgen tot de documentdownloadlinks.
@ -7496,6 +7562,8 @@ nl: &nl
start_verification_by_html: "<b>Identiteitsverificatie gestart</b> door %{submitter_name}" start_verification_by_html: "<b>Identiteitsverificatie gestart</b> door %{submitter_name}"
complete_verification_by_html: "<b>Identiteitsverificatie voltooid</b> door %{submitter_name} met %{provider}" complete_verification_by_html: "<b>Identiteitsverificatie voltooid</b> door %{submitter_name} met %{provider}"
api_complete_form_by_html: "<b>Inzending via API voltooid</b> door %{submitter_name}" api_complete_form_by_html: "<b>Inzending via API voltooid</b> door %{submitter_name}"
decline_form_by_html: "<b>Formulier geweigerd</b> door %{submitter_name}"
delegate_form_by_html: "<b>Gedelegeerd</b> van %{from} naar %{to}"
start_kba_by_html: "<b>KBA gestart</b> door %{submitter_name}" start_kba_by_html: "<b>KBA gestart</b> door %{submitter_name}"
complete_kba_by_html: "<b>KBA voltooid</b> door %{submitter_name}" complete_kba_by_html: "<b>KBA voltooid</b> door %{submitter_name}"
fail_kba_by_html: "<b>KBA mislukt</b> door %{submitter_name}" fail_kba_by_html: "<b>KBA mislukt</b> door %{submitter_name}"
@ -7602,11 +7670,14 @@ ar:
hi_there: مرحبا, hi_there: مرحبا,
download: تحميل download: تحميل
decline: رفض decline: رفض
delegate: تفويض
enter_the_email_address_of_the_person_you_want_to_delegate_to: أدخل عنوان البريد الإلكتروني للشخص الذي تريد التفويض إليه
declined: مرفوض declined: مرفوض
decline_reason: سبب الرفض decline_reason: سبب الرفض
provide_a_reason: قدم سببًا provide_a_reason: قدم سببًا
notify_the_sender_with_the_reason_you_declined: أخطر المرسل بسبب الرفض notify_the_sender_with_the_reason_you_declined: أخطر المرسل بسبب الرفض
form_has_been_declined_on_html: 'تم رفض النموذج في <span class="font-semibold">%{time}</span>' form_has_been_declined_on_html: 'تم رفض النموذج في <span class="font-semibold">%{time}</span>'
document_has_been_delegated_on_html: 'تم تفويض المستند في <span class="font-semibold">%{time}</span>'
name_declined_by_submitter: '"%{name}" مرفوض بواسطة %{submitter}' name_declined_by_submitter: '"%{name}" مرفوض بواسطة %{submitter}'
name_declined_by_submitter_with_the_following_reason: '"%{name}" تم رفضه بواسطة %{submitter} مع السبب التالي:' name_declined_by_submitter_with_the_following_reason: '"%{name}" تم رفضه بواسطة %{submitter} مع السبب التالي:'
email: البريد الإلكتروني email: البريد الإلكتروني
@ -7699,11 +7770,14 @@ ko:
hi_there: 안녕하세요, hi_there: 안녕하세요,
download: 다운로드 download: 다운로드
decline: 거절 decline: 거절
delegate: 위임
enter_the_email_address_of_the_person_you_want_to_delegate_to: 위임할 사람의 이메일 주소를 입력하세요
declined: 거절됨 declined: 거절됨
decline_reason: 거절 사유 decline_reason: 거절 사유
provide_a_reason: 사유를 제공하세요 provide_a_reason: 사유를 제공하세요
notify_the_sender_with_the_reason_you_declined: 거절한 이유로 발신자에게 알리기 notify_the_sender_with_the_reason_you_declined: 거절한 이유로 발신자에게 알리기
form_has_been_declined_on_html: '양식이 <span class="font-semibold">%{time}</span>에 거절되었습니다.' form_has_been_declined_on_html: '양식이 <span class="font-semibold">%{time}</span>에 거절되었습니다.'
document_has_been_delegated_on_html: '문서가 <span class="font-semibold">%{time}</span>에 위임되었습니다.'
name_declined_by_submitter: '"%{name}"이(가) %{submitter}에 의해 거절되었습니다.' name_declined_by_submitter: '"%{name}"이(가) %{submitter}에 의해 거절되었습니다.'
name_declined_by_submitter_with_the_following_reason: '"%{name}"이(가) %{submitter}에 의해 다음과 같은 사유로 거절되었습니다:' name_declined_by_submitter_with_the_following_reason: '"%{name}"이(가) %{submitter}에 의해 다음과 같은 사유로 거절되었습니다:'
email: 이메일 email: 이메일
@ -7796,11 +7870,14 @@ ja:
hi_there: こんにちは hi_there: こんにちは
download: ダウンロード download: ダウンロード
decline: 辞退 decline: 辞退
delegate: 委任
enter_the_email_address_of_the_person_you_want_to_delegate_to: 委任したい人のメールアドレスを入力してください
declined: 辞退済み declined: 辞退済み
decline_reason: 辞退の理由 decline_reason: 辞退の理由
provide_a_reason: 理由を入力してください provide_a_reason: 理由を入力してください
notify_the_sender_with_the_reason_you_declined: 辞退理由を送信者に通知してください notify_the_sender_with_the_reason_you_declined: 辞退理由を送信者に通知してください
form_has_been_declined_on_html: '<span class="font-semibold">%{time}</span> にフォームが辞退されました' form_has_been_declined_on_html: '<span class="font-semibold">%{time}</span> にフォームが辞退されました'
document_has_been_delegated_on_html: '<span class="font-semibold">%{time}</span> にドキュメントが委任されました'
name_declined_by_submitter: '"%{name}" は %{submitter} により辞退されました' name_declined_by_submitter: '"%{name}" は %{submitter} により辞退されました'
name_declined_by_submitter_with_the_following_reason: '"%{name}" は %{submitter} により次の理由で辞退されました:' name_declined_by_submitter_with_the_following_reason: '"%{name}" は %{submitter} により次の理由で辞退されました:'
email: メール email: メール

@ -145,8 +145,10 @@ Rails.application.routes.draw do
resources :values, only: %i[index], controller: 'submit_form_values' resources :values, only: %i[index], controller: 'submit_form_values'
resources :download, only: %i[index], controller: 'submit_form_download' resources :download, only: %i[index], controller: 'submit_form_download'
resources :decline, only: %i[create], controller: 'submit_form_decline' resources :decline, only: %i[create], controller: 'submit_form_decline'
resources :delegate, only: %i[create], controller: 'submit_form_delegate'
resources :invite, only: %i[create], controller: 'submit_form_invite' resources :invite, only: %i[create], controller: 'submit_form_invite'
get :completed get :completed
get :delegated
end end
resources :submit_form_draw_signature, only: %i[show], path: 'p', param: 'slug' resources :submit_form_draw_signature, only: %i[show], path: 'p', param: 'slug'

@ -0,0 +1,17 @@
# frozen_string_literal: true
class CreateSubmitterVersions < ActiveRecord::Migration[8.1]
def change
create_table :submitter_versions do |t|
t.references :submitter, null: false, foreign_key: true
t.string :slug, null: false
t.string :email
t.string :name
t.string :phone
t.timestamps
end
add_index :submitter_versions, :slug
end
end

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.1].define(version: 2026_02_26_193537) do ActiveRecord::Schema[8.1].define(version: 2026_03_27_100000) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "btree_gin" enable_extension "btree_gin"
enable_extension "plpgsql" enable_extension "plpgsql"
@ -364,6 +364,18 @@ ActiveRecord::Schema[8.1].define(version: 2026_02_26_193537) do
t.index ["template_id"], name: "index_submissions_on_template_id" t.index ["template_id"], name: "index_submissions_on_template_id"
end end
create_table "submitter_versions", force: :cascade do |t|
t.datetime "created_at", null: false
t.string "email"
t.string "name"
t.string "phone"
t.string "slug", null: false
t.bigint "submitter_id", null: false
t.datetime "updated_at", null: false
t.index ["slug"], name: "index_submitter_versions_on_slug"
t.index ["submitter_id"], name: "index_submitter_versions_on_submitter_id"
end
create_table "submitters", force: :cascade do |t| create_table "submitters", force: :cascade do |t|
t.bigint "submission_id", null: false t.bigint "submission_id", null: false
t.string "uuid", null: false t.string "uuid", null: false
@ -541,12 +553,14 @@ ActiveRecord::Schema[8.1].define(version: 2026_02_26_193537) do
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
add_foreign_key "document_generation_events", "submitters" add_foreign_key "document_generation_events", "submitters"
add_foreign_key "dynamic_document_versions", "dynamic_documents"
add_foreign_key "dynamic_documents", "templates" add_foreign_key "dynamic_documents", "templates"
add_foreign_key "email_events", "accounts" add_foreign_key "email_events", "accounts"
add_foreign_key "email_messages", "accounts" add_foreign_key "email_messages", "accounts"
add_foreign_key "email_messages", "users", column: "author_id" add_foreign_key "email_messages", "users", column: "author_id"
add_foreign_key "encrypted_configs", "accounts" add_foreign_key "encrypted_configs", "accounts"
add_foreign_key "encrypted_user_configs", "users" add_foreign_key "encrypted_user_configs", "users"
add_foreign_key "mcp_tokens", "users"
add_foreign_key "oauth_access_grants", "oauth_applications", column: "application_id" add_foreign_key "oauth_access_grants", "oauth_applications", column: "application_id"
add_foreign_key "oauth_access_grants", "users", column: "resource_owner_id" add_foreign_key "oauth_access_grants", "users", column: "resource_owner_id"
add_foreign_key "oauth_access_tokens", "oauth_applications", column: "application_id" add_foreign_key "oauth_access_tokens", "oauth_applications", column: "application_id"
@ -556,6 +570,7 @@ ActiveRecord::Schema[8.1].define(version: 2026_02_26_193537) do
add_foreign_key "submission_events", "submitters" add_foreign_key "submission_events", "submitters"
add_foreign_key "submissions", "templates" add_foreign_key "submissions", "templates"
add_foreign_key "submissions", "users", column: "created_by_user_id" add_foreign_key "submissions", "users", column: "created_by_user_id"
add_foreign_key "submitter_versions", "submitters"
add_foreign_key "submitters", "submissions" add_foreign_key "submitters", "submissions"
add_foreign_key "template_accesses", "templates" add_foreign_key "template_accesses", "templates"
add_foreign_key "template_folders", "accounts" add_foreign_key "template_folders", "accounts"

@ -175,6 +175,7 @@ module Accounts
def can_send_emails?(_account, **_params) def can_send_emails?(_account, **_params)
return true if Docuseal.multitenant? return true if Docuseal.multitenant?
return true if Rails.env.development?
return true if ENV['SMTP_ADDRESS'].present? return true if ENV['SMTP_ADDRESS'].present?
EncryptedConfig.exists?(key: EncryptedConfig::EMAIL_SMTP_KEY) EncryptedConfig.exists?(key: EncryptedConfig::EMAIL_SMTP_KEY)

@ -20,7 +20,7 @@ module EmailVerificationCodes
def build_totp_secret(value) def build_totp_secret(value)
ROTP::Base32.encode( ROTP::Base32.encode(
Digest::SHA1.digest( Digest::SHA1.digest(
[Rails.application.secret_key_base, value].join(':') [Rails.application.secret_key_base, 'form_email_2fa', value].join(':')
) )
) )
end end

@ -2,6 +2,7 @@
module LoadIco module LoadIco
BI_RGB = 0 BI_RGB = 0
PNG_SIGNATURE = "\x89PNG".b
module_function module_function
@ -42,6 +43,8 @@ module LoadIco
raise ArgumentError, 'Unable to load' unless image_data_bytes && image_data_bytes.bytesize == best_entry[:size] raise ArgumentError, 'Unable to load' unless image_data_bytes && image_data_bytes.bytesize == best_entry[:size]
return Vips::Image.new_from_buffer(image_data_bytes, '') if image_data_bytes.start_with?(PNG_SIGNATURE)
image = load_image_entry(image_data_bytes, best_entry[:width], best_entry[:height]) image = load_image_entry(image_data_bytes, best_entry[:width], best_entry[:height])
raise ArgumentError, 'Unable to load' unless image raise ArgumentError, 'Unable to load' unless image

@ -246,33 +246,25 @@ module Submissions
next if submitter.blank? next if submitter.blank?
completed_event = submission_events = submission.submission_events.select { |e| e.submitter_id == submitter.id }
submission.submission_events.find { |e| e.submitter_id == submitter.id && e.complete_form? } ||
SubmissionEvent.new
click_email_event = delegated_event = submission_events.select(&:delegate_form?).max_by(&:event_timestamp)
submission.submission_events.find { |e| e.submitter_id == submitter.id && e.click_email? }
verify_email_event = if delegated_event
submission.submission_events.find { |e| e.submitter_id == submitter.id && e.email_verified? } submission_events = submission_events.select { |e| e.event_timestamp > delegated_event.event_timestamp }
end
is_phone_verified = completed_event = submission_events.find(&:complete_form?) || SubmissionEvent.new
submission.template_fields.any? do |e|
e['type'] == 'phone' && e['submitter_uuid'] == submitter.uuid && submitter.values[e['uuid']].present?
end
verify_phone_event = click_email_event = submission_events.find(&:click_email?)
submission.submission_events.find { |e| e.submitter_id == submitter.id && e.phone_verified? }
is_id_verified = verify_email_event = submission_events.find(&:email_verified?)
submission.template_fields.any? do |e|
e['type'] == 'verification' && e['submitter_uuid'] == submitter.uuid && submitter.values[e['uuid']].present?
end
is_kba_passed = verify_phone_event = submission_events.find(&:phone_verified?)
submission.template_fields.any? do |e|
e['type'] == 'kba' && e['submitter_uuid'] == submitter.uuid && submitter.values[e['uuid']].present? is_id_verified = submission_events.any?(&:complete_verification?)
end
is_kba_passed = submission_events.any?(&:complete_kba?)
info_rows = [ info_rows = [
[ [
@ -291,7 +283,7 @@ module Submissions
submitter.email && (click_email_event || verify_email_event) && { submitter.email && (click_email_event || verify_email_event) && {
text: "#{I18n.t('email_verification')}: #{I18n.t('verified')}\n" text: "#{I18n.t('email_verification')}: #{I18n.t('verified')}\n"
}, },
submitter.phone && (is_phone_verified || verify_phone_event) && { submitter.phone && verify_phone_event && {
text: "#{I18n.t('phone_verification')}: #{I18n.t('verified')}\n" text: "#{I18n.t('phone_verification')}: #{I18n.t('verified')}\n"
}, },
is_id_verified && { is_id_verified && {
@ -446,15 +438,23 @@ module Submissions
composer.text(I18n.t('event_log'), font_size: 12, padding: [10, 0, 20, 0]) composer.text(I18n.t('event_log'), font_size: 12, padding: [10, 0, 20, 0])
submitter_versions_index = submission.submitters.preload(:submitter_versions).each_with_object({}) do |s, h|
h[s.id] = s.submitter_versions.to_a.sort_by(&:created_at)
end
events_data = submission.submission_events.sort_by(&:event_timestamp).filter_map do |event| events_data = submission.submission_events.sort_by(&:event_timestamp).filter_map do |event|
next if event.event_type.in?(%w[bounce_email complaint_email]) next if event.event_type.in?(%w[bounce_email complaint_email])
submitter = submission.submitters.find { |e| e.id == event.submitter_id } submitter = submission.submitters.find { |e| e.id == event.submitter_id }
versions = submitter_versions_index[submitter.id] || []
active_version = versions.find { |v| v.created_at > event.event_timestamp }
submitter_name = submitter_name =
if event.event_type.include?('sms') || event.event_type.include?('phone') if event.event_type.include?('sms') || event.event_type.include?('phone')
event.data['phone'] || submitter.phone event.data['phone'] || active_version&.phone || submitter.phone
else else
submitter.name || submitter.email || submitter.phone active_version&.name || active_version&.email || active_version&.phone ||
submitter.name || submitter.email || submitter.phone
end end
text = text =
@ -473,6 +473,10 @@ module Submissions
I18n.t("submission_event_names.#{event.event_type}_to_html", submitter_name:), I18n.t("submission_event_names.#{event.event_type}_to_html", submitter_name:),
"<b>#{I18n.t(:from)}</b> #{submission.created_by_user.full_name} #{submission.created_by_user.email}" "<b>#{I18n.t(:from)}</b> #{submission.created_by_user.full_name} #{submission.created_by_user.email}"
].join("\n") ].join("\n")
elsif event.event_type == 'delegate_form'
from = event.data['old_email'].presence ||
versions.reverse.find { |v| v.created_at <= event.event_timestamp }&.then { |v| v.name || v.phone }
I18n.t('submission_event_names.delegate_form_by_html', from:, to: event.data['email'])
elsif event.event_type.include?('send_') elsif event.event_type.include?('send_')
I18n.t("submission_event_names.#{event.event_type}_to_html", submitter_name:) I18n.t("submission_event_names.#{event.event_type}_to_html", submitter_name:)
else else

@ -8,6 +8,7 @@ module Submitters
AccountConfig::FORM_PREFILL_SIGNATURE_KEY, AccountConfig::FORM_PREFILL_SIGNATURE_KEY,
AccountConfig::WITH_SIGNATURE_ID, AccountConfig::WITH_SIGNATURE_ID,
AccountConfig::ALLOW_TO_DECLINE_KEY, AccountConfig::ALLOW_TO_DECLINE_KEY,
AccountConfig::ALLOW_TO_DELEGATE_KEY,
AccountConfig::ENFORCE_SIGNING_ORDER_KEY, AccountConfig::ENFORCE_SIGNING_ORDER_KEY,
AccountConfig::REQUIRE_SIGNING_REASON_KEY, AccountConfig::REQUIRE_SIGNING_REASON_KEY,
AccountConfig::REUSE_SIGNATURE_KEY, AccountConfig::REUSE_SIGNATURE_KEY,
@ -27,10 +28,11 @@ module Submitters
completed_button = find_safe_value(configs, AccountConfig::FORM_COMPLETED_BUTTON_KEY) || {} completed_button = find_safe_value(configs, AccountConfig::FORM_COMPLETED_BUTTON_KEY) || {}
completed_message = find_safe_value(configs, AccountConfig::FORM_COMPLETED_MESSAGE_KEY) || {} completed_message = find_safe_value(configs, AccountConfig::FORM_COMPLETED_MESSAGE_KEY) || {}
with_typed_signature = find_safe_value(configs, AccountConfig::ALLOW_TYPED_SIGNATURE) != false with_typed_signature = find_safe_value(configs, AccountConfig::ALLOW_TYPED_SIGNATURE) != false
with_confetti = find_safe_value(configs, AccountConfig::FORM_WITH_CONFETTI_KEY) != false with_confetti = find_safe_value(configs, AccountConfig::FORM_WITH_CONFETTI_KEY) == true
prefill_signature = find_safe_value(configs, AccountConfig::FORM_PREFILL_SIGNATURE_KEY) != false prefill_signature = find_safe_value(configs, AccountConfig::FORM_PREFILL_SIGNATURE_KEY) != false
reuse_signature = find_safe_value(configs, AccountConfig::REUSE_SIGNATURE_KEY) != false reuse_signature = find_safe_value(configs, AccountConfig::REUSE_SIGNATURE_KEY) != false
with_decline = find_safe_value(configs, AccountConfig::ALLOW_TO_DECLINE_KEY) != false with_decline = find_safe_value(configs, AccountConfig::ALLOW_TO_DECLINE_KEY) != false
with_delegate = find_safe_value(configs, AccountConfig::ALLOW_TO_DELEGATE_KEY) == true
with_partial_download = find_safe_value(configs, AccountConfig::ALLOW_TO_PARTIAL_DOWNLOAD_KEY) != false with_partial_download = find_safe_value(configs, AccountConfig::ALLOW_TO_PARTIAL_DOWNLOAD_KEY) != false
with_signature_id = find_safe_value(configs, AccountConfig::WITH_SIGNATURE_ID) == true with_signature_id = find_safe_value(configs, AccountConfig::WITH_SIGNATURE_ID) == true
require_signing_reason = find_safe_value(configs, AccountConfig::REQUIRE_SIGNING_REASON_KEY) == true require_signing_reason = find_safe_value(configs, AccountConfig::REQUIRE_SIGNING_REASON_KEY) == true
@ -42,7 +44,7 @@ module Submitters
policy_links = find_safe_value(configs, AccountConfig::POLICY_LINKS_KEY) policy_links = find_safe_value(configs, AccountConfig::POLICY_LINKS_KEY)
attrs = { completed_button:, with_typed_signature:, with_confetti:, attrs = { completed_button:, with_typed_signature:, with_confetti:,
reuse_signature:, with_decline:, with_partial_download:, reuse_signature:, with_decline:, with_delegate:, with_partial_download:,
policy_links:, enforce_signing_order:, completed_message:, policy_links:, enforce_signing_order:, completed_message:,
require_signing_reason:, prefill_signature:, with_submitter_timezone:, require_signing_reason:, prefill_signature:, with_submitter_timezone:,
with_signature_id_reason:, with_signature_id:, with_field_labels:, with_timestamp_seconds: } with_signature_id_reason:, with_signature_id:, with_field_labels:, with_timestamp_seconds: }

@ -1159,6 +1159,50 @@ RSpec.describe 'Signing Form' do
end end
end end
context 'when decline is enabled' do
let(:template) { create(:template, account:, author:, only_field_types: %w[text]) }
let(:submission) { create(:submission, template:) }
let(:submitter) { create(:submitter, submission:, uuid: template.submitters.first['uuid'], account:) }
it 'declines the form and shows the declined page' do
visit submit_form_path(slug: submitter.slug)
find('#decline_button').click
fill_in 'reason', with: 'I do not agree with the terms'
click_button 'Decline'
expect(page).to have_content('Form has been declined')
submitter.reload
expect(submitter.declined_at).to be_present
end
end
context 'when delegate is enabled' do
let(:template) { create(:template, account:, author:, only_field_types: %w[text]) }
let(:submission) { create(:submission, template:) }
let(:submitter) { create(:submitter, submission:, uuid: template.submitters.first['uuid'], account:) }
before do
create(:account_config, account:, key: AccountConfig::ALLOW_TO_DELEGATE_KEY, value: true)
end
it 'delegates the form to another email and shows the delegated page' do
visit submit_form_path(slug: submitter.slug)
find('#delegate_button').click
fill_in 'email', with: 'delegate@example.com'
click_button 'Delegate'
expect(page).to have_content('Document has been delegated')
submitter.reload
expect(submitter.email).to eq('delegate@example.com')
end
end
context 'when the 2FA email verification is enabled', sidekiq: :inline do context 'when the 2FA email verification is enabled', sidekiq: :inline do
let(:template) { create(:template, account:, author:, only_field_types: %w[text]) } let(:template) { create(:template, account:, author:, only_field_types: %w[text]) }
let(:submission) { create(:submission, template:) } let(:submission) { create(:submission, template:) }

Loading…
Cancel
Save