mirror of
https://github.com/docusealco/docuseal.git
synced 2026-08-07 07:14:43 +00:00
Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a6981185b2 | |||
| 0361fabb66 | |||
| 04e7f101be | |||
| 86d680cfdf | |||
| 7bc2152057 | |||
| 74ed9a5040 | |||
| 30115fc0dc | |||
| 8e8e5e0e29 | |||
| b58ce1b571 | |||
| df5c4e4210 | |||
| ba2e0999f1 | |||
| a1f5dd08c7 | |||
| c1123fef63 | |||
| 4dc6149530 | |||
| 1245ff2cce | |||
| 284204fd78 | |||
| f7be74eb73 | |||
| aeea619059 | |||
| ea2b7f20e7 | |||
| f40f1d25de | |||
| c04bb2d7cf | |||
| 4c1ccd65bf | |||
| 54e064b0fc | |||
| 9a8b72883c | |||
| 5d75ee2e47 | |||
| 7357fa4871 | |||
| f6850b5427 | |||
| 1e9a181e60 | |||
| 7224a1ccec | |||
| 9b935a8180 | |||
| c4a693846e | |||
| 02c7cdcd97 | |||
| 36bee92e8e | |||
| 6542804f44 | |||
| d805fd614c | |||
| 21299dc65f | |||
| 0df0946c2a | |||
| 1bb38d50a1 | |||
| 242987cb41 | |||
| 5456abde54 | |||
| 4a07427440 | |||
| cf60dae2ff | |||
| 659997c6c1 | |||
| 389a47a152 | |||
| b6b81ca487 | |||
| 719c1786f1 | |||
| 4685bac4b3 | |||
| a05275cc08 | |||
| 1abf1b1658 | |||
| 8893dc5698 | |||
| f8467b2da1 | |||
| f39b8b000e | |||
| 961036fa31 | |||
| 8b9056894e | |||
| 7f979e9396 | |||
| 8db1192d0e | |||
| 3bd515951a | |||
| 2bd5b9676b | |||
| 993698ec01 | |||
| fcdc44ddbe | |||
| 0cb6b0ae12 | |||
| 0388927c5b | |||
| 2c8f5d2129 | |||
| 2bffbf83c6 | |||
| ec01529014 | |||
| ea1abf5662 | |||
| fcd5263af1 | |||
| 1fa8616dbc |
+1
-1
@@ -50,7 +50,7 @@ ENV OPENSSL_CONF=/app/openssl_legacy.cnf
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN echo '@edge https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories && apk add --no-cache sqlite-dev libpq-dev mariadb-dev vips-dev@edge redis libheif@edge vips-heif@edge gcompat ttf-freefont && mkdir /fonts && rm /usr/share/fonts/freefont/FreeSans.otf
|
||||
RUN echo '@edge https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories && apk add --no-cache sqlite-dev libpq-dev mariadb-dev vips-dev@edge yaml-dev redis libheif@edge vips-heif@edge gcompat ttf-freefont && mkdir /fonts && rm /usr/share/fonts/freefont/FreeSans.otf
|
||||
|
||||
RUN echo $'.include = /etc/ssl/openssl.cnf\n\
|
||||
\n\
|
||||
|
||||
@@ -11,6 +11,7 @@ gem 'azure-storage-blob', require: false
|
||||
gem 'bootsnap', require: false
|
||||
gem 'cancancan'
|
||||
gem 'csv'
|
||||
gem 'csv-safe'
|
||||
gem 'devise'
|
||||
gem 'devise-two-factor'
|
||||
gem 'dotenv', require: false
|
||||
|
||||
+95
-82
@@ -1,29 +1,29 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (8.0.1)
|
||||
actionpack (= 8.0.1)
|
||||
activesupport (= 8.0.1)
|
||||
actioncable (8.0.2.1)
|
||||
actionpack (= 8.0.2.1)
|
||||
activesupport (= 8.0.2.1)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
zeitwerk (~> 2.6)
|
||||
actionmailbox (8.0.1)
|
||||
actionpack (= 8.0.1)
|
||||
activejob (= 8.0.1)
|
||||
activerecord (= 8.0.1)
|
||||
activestorage (= 8.0.1)
|
||||
activesupport (= 8.0.1)
|
||||
actionmailbox (8.0.2.1)
|
||||
actionpack (= 8.0.2.1)
|
||||
activejob (= 8.0.2.1)
|
||||
activerecord (= 8.0.2.1)
|
||||
activestorage (= 8.0.2.1)
|
||||
activesupport (= 8.0.2.1)
|
||||
mail (>= 2.8.0)
|
||||
actionmailer (8.0.1)
|
||||
actionpack (= 8.0.1)
|
||||
actionview (= 8.0.1)
|
||||
activejob (= 8.0.1)
|
||||
activesupport (= 8.0.1)
|
||||
actionmailer (8.0.2.1)
|
||||
actionpack (= 8.0.2.1)
|
||||
actionview (= 8.0.2.1)
|
||||
activejob (= 8.0.2.1)
|
||||
activesupport (= 8.0.2.1)
|
||||
mail (>= 2.8.0)
|
||||
rails-dom-testing (~> 2.2)
|
||||
actionpack (8.0.1)
|
||||
actionview (= 8.0.1)
|
||||
activesupport (= 8.0.1)
|
||||
actionpack (8.0.2.1)
|
||||
actionview (= 8.0.2.1)
|
||||
activesupport (= 8.0.2.1)
|
||||
nokogiri (>= 1.8.5)
|
||||
rack (>= 2.2.4)
|
||||
rack-session (>= 1.0.1)
|
||||
@@ -31,35 +31,35 @@ GEM
|
||||
rails-dom-testing (~> 2.2)
|
||||
rails-html-sanitizer (~> 1.6)
|
||||
useragent (~> 0.16)
|
||||
actiontext (8.0.1)
|
||||
actionpack (= 8.0.1)
|
||||
activerecord (= 8.0.1)
|
||||
activestorage (= 8.0.1)
|
||||
activesupport (= 8.0.1)
|
||||
actiontext (8.0.2.1)
|
||||
actionpack (= 8.0.2.1)
|
||||
activerecord (= 8.0.2.1)
|
||||
activestorage (= 8.0.2.1)
|
||||
activesupport (= 8.0.2.1)
|
||||
globalid (>= 0.6.0)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (8.0.1)
|
||||
activesupport (= 8.0.1)
|
||||
actionview (8.0.2.1)
|
||||
activesupport (= 8.0.2.1)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.11)
|
||||
rails-dom-testing (~> 2.2)
|
||||
rails-html-sanitizer (~> 1.6)
|
||||
activejob (8.0.1)
|
||||
activesupport (= 8.0.1)
|
||||
activejob (8.0.2.1)
|
||||
activesupport (= 8.0.2.1)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (8.0.1)
|
||||
activesupport (= 8.0.1)
|
||||
activerecord (8.0.1)
|
||||
activemodel (= 8.0.1)
|
||||
activesupport (= 8.0.1)
|
||||
activemodel (8.0.2.1)
|
||||
activesupport (= 8.0.2.1)
|
||||
activerecord (8.0.2.1)
|
||||
activemodel (= 8.0.2.1)
|
||||
activesupport (= 8.0.2.1)
|
||||
timeout (>= 0.4.0)
|
||||
activestorage (8.0.1)
|
||||
actionpack (= 8.0.1)
|
||||
activejob (= 8.0.1)
|
||||
activerecord (= 8.0.1)
|
||||
activesupport (= 8.0.1)
|
||||
activestorage (8.0.2.1)
|
||||
actionpack (= 8.0.2.1)
|
||||
activejob (= 8.0.2.1)
|
||||
activerecord (= 8.0.2.1)
|
||||
activesupport (= 8.0.2.1)
|
||||
marcel (~> 1.0)
|
||||
activesupport (8.0.1)
|
||||
activesupport (8.0.2.1)
|
||||
base64
|
||||
benchmark (>= 0.3)
|
||||
bigdecimal
|
||||
@@ -104,9 +104,9 @@ GEM
|
||||
faraday_middleware (~> 1.0, >= 1.0.0.rc1)
|
||||
net-http-persistent (~> 4.0)
|
||||
nokogiri (~> 1, >= 1.10.8)
|
||||
base64 (0.2.0)
|
||||
base64 (0.3.0)
|
||||
bcrypt (3.1.20)
|
||||
benchmark (0.4.0)
|
||||
benchmark (0.4.1)
|
||||
better_html (2.1.1)
|
||||
actionview (>= 6.0)
|
||||
activesupport (>= 6.0)
|
||||
@@ -114,7 +114,7 @@ GEM
|
||||
erubi (~> 1.4)
|
||||
parser (>= 2.4)
|
||||
smart_properties
|
||||
bigdecimal (3.1.8)
|
||||
bigdecimal (3.2.2)
|
||||
bindex (0.8.1)
|
||||
bootsnap (1.18.4)
|
||||
msgpack (~> 1.2)
|
||||
@@ -141,8 +141,8 @@ GEM
|
||||
cldr-plurals-runtime-rb (1.1.0)
|
||||
cmdparse (3.0.7)
|
||||
coderay (1.1.3)
|
||||
concurrent-ruby (1.3.4)
|
||||
connection_pool (2.4.1)
|
||||
concurrent-ruby (1.3.5)
|
||||
connection_pool (2.5.3)
|
||||
crack (1.0.0)
|
||||
bigdecimal
|
||||
rexml
|
||||
@@ -150,6 +150,8 @@ GEM
|
||||
css_parser (1.21.0)
|
||||
addressable
|
||||
csv (3.3.2)
|
||||
csv-safe (3.3.1)
|
||||
csv (~> 3.0)
|
||||
cuprite (0.15.1)
|
||||
capybara (~> 3.0)
|
||||
ferrum (~> 0.15.0)
|
||||
@@ -174,8 +176,9 @@ GEM
|
||||
rake (>= 12.0.0, < 14.0.0)
|
||||
docile (1.4.1)
|
||||
dotenv (3.1.7)
|
||||
drb (2.2.1)
|
||||
drb (2.2.3)
|
||||
email_typo (0.2.3)
|
||||
erb (5.0.2)
|
||||
erb_lint (0.7.0)
|
||||
activesupport
|
||||
better_html (>= 2.0.1)
|
||||
@@ -270,23 +273,25 @@ GEM
|
||||
os (>= 0.9, < 2.0)
|
||||
signet (>= 0.16, < 2.a)
|
||||
hashdiff (1.1.2)
|
||||
hexapdf (1.0.3)
|
||||
hexapdf (1.4.0)
|
||||
cmdparse (~> 3.0, >= 3.0.3)
|
||||
geom2d (~> 0.4, >= 0.4.1)
|
||||
openssl (>= 2.2.1)
|
||||
strscan (>= 3.1.2)
|
||||
htmlentities (4.3.4)
|
||||
httpclient (2.8.3)
|
||||
i18n (1.14.6)
|
||||
i18n (1.14.7)
|
||||
concurrent-ruby (~> 1.0)
|
||||
image_processing (1.13.0)
|
||||
mini_magick (>= 4.9.5, < 5)
|
||||
ruby-vips (>= 2.0.17, < 3)
|
||||
io-console (0.8.0)
|
||||
irb (1.14.3)
|
||||
io-console (0.8.1)
|
||||
irb (1.15.2)
|
||||
pp (>= 0.6.0)
|
||||
rdoc (>= 4.0.0)
|
||||
reline (>= 0.4.2)
|
||||
jmespath (1.6.2)
|
||||
json (2.9.1)
|
||||
json (2.13.2)
|
||||
jwt (2.9.3)
|
||||
base64
|
||||
language_server-protocol (3.17.0.3)
|
||||
@@ -300,13 +305,13 @@ GEM
|
||||
letter_opener (~> 1.9)
|
||||
railties (>= 6.1)
|
||||
rexml
|
||||
logger (1.6.4)
|
||||
logger (1.7.0)
|
||||
lograge (0.14.0)
|
||||
actionpack (>= 4)
|
||||
activesupport (>= 4)
|
||||
railties (>= 4)
|
||||
request_store (~> 1.0)
|
||||
loofah (2.23.1)
|
||||
loofah (2.24.1)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
mail (2.8.1)
|
||||
@@ -320,7 +325,7 @@ GEM
|
||||
mini_magick (4.13.2)
|
||||
mini_mime (1.1.5)
|
||||
mini_portile2 (2.8.9)
|
||||
minitest (5.25.4)
|
||||
minitest (5.25.5)
|
||||
msgpack (1.7.5)
|
||||
multi_json (1.15.0)
|
||||
multipart-post (2.4.1)
|
||||
@@ -328,14 +333,14 @@ GEM
|
||||
mysql2 (0.5.6)
|
||||
net-http-persistent (4.0.5)
|
||||
connection_pool (~> 2.2)
|
||||
net-imap (0.5.6)
|
||||
net-imap (0.5.9)
|
||||
date
|
||||
net-protocol
|
||||
net-pop (0.1.2)
|
||||
net-protocol
|
||||
net-protocol (0.2.2)
|
||||
timeout
|
||||
net-smtp (0.5.0)
|
||||
net-smtp (0.5.1)
|
||||
net-protocol
|
||||
nio4r (2.7.4)
|
||||
nokogiri (1.18.9)
|
||||
@@ -351,13 +356,13 @@ GEM
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.18.9-x86_64-linux-musl)
|
||||
racc (~> 1.4)
|
||||
oj (3.16.8)
|
||||
oj (3.16.11)
|
||||
bigdecimal (>= 3.0)
|
||||
ostruct (>= 0.2)
|
||||
openssl (3.3.0)
|
||||
orm_adapter (0.5.0)
|
||||
os (1.1.4)
|
||||
ostruct (0.6.1)
|
||||
ostruct (0.6.3)
|
||||
package_json (0.1.0)
|
||||
pagy (9.3.3)
|
||||
parallel (1.26.3)
|
||||
@@ -365,6 +370,8 @@ GEM
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
pg (1.5.9)
|
||||
pp (0.6.2)
|
||||
prettyprint
|
||||
premailer (1.27.0)
|
||||
addressable
|
||||
css_parser (>= 1.19.0)
|
||||
@@ -375,42 +382,44 @@ GEM
|
||||
premailer (~> 1.7, >= 1.7.9)
|
||||
pretender (0.5.0)
|
||||
actionpack (>= 6.1)
|
||||
prettyprint (0.2.0)
|
||||
pry (0.15.0)
|
||||
coderay (~> 1.1)
|
||||
method_source (~> 1.0)
|
||||
pry-rails (0.3.11)
|
||||
pry (>= 0.13.0)
|
||||
psych (5.2.2)
|
||||
psych (5.2.6)
|
||||
date
|
||||
stringio
|
||||
public_suffix (6.0.1)
|
||||
puma (6.5.0)
|
||||
nio4r (~> 2.0)
|
||||
racc (1.8.1)
|
||||
rack (3.1.16)
|
||||
rack (3.2.0)
|
||||
rack-proxy (0.7.7)
|
||||
rack
|
||||
rack-session (2.0.0)
|
||||
rack-session (2.1.1)
|
||||
base64 (>= 0.1.0)
|
||||
rack (>= 3.0.0)
|
||||
rack-test (2.1.0)
|
||||
rack-test (2.2.0)
|
||||
rack (>= 1.3)
|
||||
rackup (2.2.1)
|
||||
rack (>= 3)
|
||||
rails (8.0.1)
|
||||
actioncable (= 8.0.1)
|
||||
actionmailbox (= 8.0.1)
|
||||
actionmailer (= 8.0.1)
|
||||
actionpack (= 8.0.1)
|
||||
actiontext (= 8.0.1)
|
||||
actionview (= 8.0.1)
|
||||
activejob (= 8.0.1)
|
||||
activemodel (= 8.0.1)
|
||||
activerecord (= 8.0.1)
|
||||
activestorage (= 8.0.1)
|
||||
activesupport (= 8.0.1)
|
||||
rails (8.0.2.1)
|
||||
actioncable (= 8.0.2.1)
|
||||
actionmailbox (= 8.0.2.1)
|
||||
actionmailer (= 8.0.2.1)
|
||||
actionpack (= 8.0.2.1)
|
||||
actiontext (= 8.0.2.1)
|
||||
actionview (= 8.0.2.1)
|
||||
activejob (= 8.0.2.1)
|
||||
activemodel (= 8.0.2.1)
|
||||
activerecord (= 8.0.2.1)
|
||||
activestorage (= 8.0.2.1)
|
||||
activesupport (= 8.0.2.1)
|
||||
bundler (>= 1.15.0)
|
||||
railties (= 8.0.1)
|
||||
rails-dom-testing (2.2.0)
|
||||
railties (= 8.0.2.1)
|
||||
rails-dom-testing (2.3.0)
|
||||
activesupport (>= 5.0.0)
|
||||
minitest
|
||||
nokogiri (>= 1.6)
|
||||
@@ -424,22 +433,23 @@ GEM
|
||||
actionview (> 3.1)
|
||||
activesupport (> 3.1)
|
||||
railties (> 3.1)
|
||||
railties (8.0.1)
|
||||
actionpack (= 8.0.1)
|
||||
activesupport (= 8.0.1)
|
||||
railties (8.0.2.1)
|
||||
actionpack (= 8.0.2.1)
|
||||
activesupport (= 8.0.2.1)
|
||||
irb (~> 1.13)
|
||||
rackup (>= 1.0.0)
|
||||
rake (>= 12.2)
|
||||
thor (~> 1.0, >= 1.2.2)
|
||||
zeitwerk (~> 2.6)
|
||||
rainbow (3.1.1)
|
||||
rake (13.2.1)
|
||||
rdoc (6.10.0)
|
||||
rake (13.3.0)
|
||||
rdoc (6.14.2)
|
||||
erb
|
||||
psych (>= 4.0.0)
|
||||
redis-client (0.23.0)
|
||||
connection_pool
|
||||
regexp_parser (2.9.3)
|
||||
reline (0.6.0)
|
||||
reline (0.6.2)
|
||||
io-console (~> 0.5)
|
||||
representable (3.2.0)
|
||||
declarative (< 0.1.0)
|
||||
@@ -538,9 +548,10 @@ GEM
|
||||
sqlite3 (2.5.0-arm64-darwin)
|
||||
sqlite3 (2.5.0-x86_64-linux-gnu)
|
||||
sqlite3 (2.5.0-x86_64-linux-musl)
|
||||
stringio (3.1.2)
|
||||
stringio (3.1.7)
|
||||
strip_attributes (1.14.1)
|
||||
activemodel (>= 3.0, < 9.0)
|
||||
strscan (3.1.5)
|
||||
thor (1.4.0)
|
||||
timeout (0.4.3)
|
||||
trailblazer-option (0.1.2)
|
||||
@@ -574,12 +585,13 @@ GEM
|
||||
crack (>= 0.3.2)
|
||||
hashdiff (>= 0.4.0, < 2.0.0)
|
||||
webrick (1.9.1)
|
||||
websocket-driver (0.7.6)
|
||||
websocket-driver (0.8.0)
|
||||
base64
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.5)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
zeitwerk (2.7.1)
|
||||
zeitwerk (2.7.3)
|
||||
|
||||
PLATFORMS
|
||||
aarch64-linux
|
||||
@@ -602,6 +614,7 @@ DEPENDENCIES
|
||||
cancancan
|
||||
capybara
|
||||
csv
|
||||
csv-safe
|
||||
cuprite
|
||||
debug
|
||||
devise
|
||||
|
||||
@@ -15,6 +15,7 @@ class AccountConfigsController < ApplicationController
|
||||
AccountConfig::ESIGNING_PREFERENCE_KEY,
|
||||
AccountConfig::FORM_WITH_CONFETTI_KEY,
|
||||
AccountConfig::DOWNLOAD_LINKS_AUTH_KEY,
|
||||
AccountConfig::DOWNLOAD_LINKS_EXPIRE_KEY,
|
||||
AccountConfig::FORCE_SSO_AUTH_KEY,
|
||||
AccountConfig::FLATTEN_RESULT_PDF_KEY,
|
||||
AccountConfig::ENFORCE_SIGNING_ORDER_KEY,
|
||||
|
||||
@@ -27,7 +27,7 @@ class AccountsController < ApplicationController
|
||||
unless URI.parse(@encrypted_config.value.to_s).class.in?([URI::HTTP, URI::HTTPS])
|
||||
@encrypted_config.errors.add(:value, I18n.t('should_be_a_valid_url'))
|
||||
|
||||
return render :show, status: :unprocessable_entity
|
||||
return render :show, status: :unprocessable_content
|
||||
end
|
||||
|
||||
@encrypted_config.save!
|
||||
@@ -39,7 +39,7 @@ class AccountsController < ApplicationController
|
||||
redirect_to settings_account_path, notice: I18n.t('account_information_has_been_updated')
|
||||
end
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
render :show, status: :unprocessable_entity
|
||||
render :show, status: :unprocessable_content
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
||||
@@ -13,7 +13,7 @@ module Api
|
||||
def show
|
||||
blob_uuid, purp, exp = ApplicationRecord.signed_id_verifier.verified(params[:signed_uuid])
|
||||
|
||||
if blob_uuid.blank? || (purp.present? && purp != 'blob') || (exp && exp < Time.current.to_i)
|
||||
if blob_uuid.blank? || purp != 'blob'
|
||||
Rollbar.error('Blob not found') if defined?(Rollbar)
|
||||
|
||||
return head :not_found
|
||||
@@ -24,8 +24,9 @@ module Api
|
||||
attachment = blob.attachments.take
|
||||
|
||||
@record = attachment.record
|
||||
@record = @record.record if @record.is_a?(ActiveStorage::Attachment)
|
||||
|
||||
authorization_check!(attachment) if exp.blank?
|
||||
authorization_check!(attachment, @record, exp)
|
||||
|
||||
if request.headers['Range'].present?
|
||||
send_blob_byte_range_data blob, request.headers['Range']
|
||||
@@ -41,16 +42,22 @@ module Api
|
||||
|
||||
private
|
||||
|
||||
def authorization_check!(attachment)
|
||||
is_authorized = attachment.name.in?(%w[logo preview_images]) ||
|
||||
(current_user && attachment.record.account.id == current_user.account_id) ||
|
||||
(current_user && !Docuseal.multitenant? && current_user.role == 'superadmin') ||
|
||||
!attachment.record.account.account_configs
|
||||
.find_or_initialize_by(key: AccountConfig::DOWNLOAD_LINKS_AUTH_KEY).value
|
||||
def authorization_check!(attachment, record, exp)
|
||||
return if attachment.name == 'logo'
|
||||
return if exp.to_i >= Time.current.to_i
|
||||
return if current_user && current_ability.can?(:read, record)
|
||||
|
||||
return if is_authorized
|
||||
if exp.blank?
|
||||
configs = record.account.account_configs.where(key: [AccountConfig::DOWNLOAD_LINKS_AUTH_KEY,
|
||||
AccountConfig::DOWNLOAD_LINKS_EXPIRE_KEY])
|
||||
|
||||
Rollbar.error('Blob aunauthorized') if defined?(Rollbar)
|
||||
require_auth = configs.any? { |c| c.key == AccountConfig::DOWNLOAD_LINKS_AUTH_KEY && c.value }
|
||||
require_ttl = configs.none? { |c| c.key == AccountConfig::DOWNLOAD_LINKS_EXPIRE_KEY && c.value == false }
|
||||
|
||||
return if !require_ttl && !require_auth
|
||||
end
|
||||
|
||||
Rollbar.error('Blob unauthorized') if defined?(Rollbar)
|
||||
|
||||
raise CanCan::AccessDenied
|
||||
end
|
||||
|
||||
@@ -16,7 +16,7 @@ module Api
|
||||
check_authorization
|
||||
|
||||
rescue_from Params::BaseValidator::InvalidParameterError do |e|
|
||||
render json: { error: e.message }, status: :unprocessable_entity
|
||||
render json: { error: e.message }, status: :unprocessable_content
|
||||
end
|
||||
|
||||
rescue_from RateLimit::LimitApproached do |e|
|
||||
@@ -33,7 +33,7 @@ module Api
|
||||
rescue_from JSON::ParserError do |e|
|
||||
Rollbar.warning(e) if defined?(Rollbar)
|
||||
|
||||
render json: { error: "JSON parse error: #{e.message}" }, status: :unprocessable_entity
|
||||
render json: { error: "JSON parse error: #{e.message}" }, status: :unprocessable_content
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -16,14 +16,14 @@ module Api
|
||||
if ImageUtils.blank?(image)
|
||||
Rollbar.error("Empty signature: #{submitter.id}") if defined?(Rollbar)
|
||||
|
||||
return render json: { error: "#{params[:type]} is empty" }, status: :unprocessable_entity
|
||||
return render json: { error: "#{params[:type]} is empty" }, status: :unprocessable_content
|
||||
end
|
||||
|
||||
if ImageUtils.error?(image)
|
||||
Rollbar.error("Error signature: #{submitter.id}") if defined?(Rollbar)
|
||||
|
||||
return render json: { error: "#{params[:type]} error, try to sign on another device" },
|
||||
status: :unprocessable_entity
|
||||
status: :unprocessable_content
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -18,12 +18,14 @@ module Api
|
||||
field: :completed_at
|
||||
)
|
||||
|
||||
expires_at = Accounts.link_expires_at(current_account)
|
||||
|
||||
render json: {
|
||||
data: submitters.map do |s|
|
||||
{
|
||||
event_type: 'form.completed',
|
||||
timestamp: s.completed_at,
|
||||
data: Submitters::SerializeForWebhook.call(s)
|
||||
data: Submitters::SerializeForWebhook.call(s, expires_at:)
|
||||
}
|
||||
end,
|
||||
pagination: {
|
||||
|
||||
@@ -34,10 +34,12 @@ module Api
|
||||
associations: [:blob]
|
||||
).call
|
||||
|
||||
expires_at = Accounts.link_expires_at(current_account)
|
||||
|
||||
render json: {
|
||||
id: @submission.id,
|
||||
documents: documents.map do |attachment|
|
||||
{ name: attachment.filename.base, url: ActiveStorage::Blob.proxy_url(attachment.blob) }
|
||||
{ name: attachment.filename.base, url: ActiveStorage::Blob.proxy_url(attachment.blob, expires_at:) }
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
@@ -14,16 +14,19 @@ module Api
|
||||
:created_by_user, :submission_events,
|
||||
template: :folder,
|
||||
submitters: { documents_attachments: :blob, attachments_attachments: :blob },
|
||||
audit_trail_attachment: :blob
|
||||
audit_trail_attachment: :blob,
|
||||
combined_document_attachment: :blob
|
||||
),
|
||||
field: :completed_at)
|
||||
|
||||
expires_at = Accounts.link_expires_at(current_account)
|
||||
|
||||
render json: {
|
||||
data: submissions.map do |s|
|
||||
{
|
||||
event_type: 'submission.completed',
|
||||
timestamp: s.completed_at,
|
||||
data: Submissions::SerializeForApi.call(s, s.submitters)
|
||||
data: Submissions::SerializeForApi.call(s, s.submitters, expires_at:)
|
||||
}
|
||||
end,
|
||||
pagination: {
|
||||
|
||||
@@ -18,10 +18,12 @@ module Api
|
||||
combined_document_attachment: :blob,
|
||||
audit_trail_attachment: :blob))
|
||||
|
||||
expires_at = Accounts.link_expires_at(current_account)
|
||||
|
||||
render json: {
|
||||
data: submissions.map do |s|
|
||||
Submissions::SerializeForApi.call(s, s.submitters, params,
|
||||
with_events: false, with_documents: false, with_values: false)
|
||||
with_events: false, with_documents: false, with_values: false, expires_at:)
|
||||
end,
|
||||
pagination: {
|
||||
count: submissions.size,
|
||||
@@ -41,7 +43,7 @@ module Api
|
||||
end
|
||||
|
||||
if @submission.audit_trail_attachment.blank? && submitters.all?(&:completed_at?)
|
||||
@submission.audit_trail_attachment = Submissions::GenerateAuditTrail.call(@submission)
|
||||
@submission.audit_trail_attachment = Submissions::EnsureAuditGenerated.call(@submission)
|
||||
end
|
||||
|
||||
render json: Submissions::SerializeForApi.call(@submission, submitters, params)
|
||||
@@ -50,12 +52,12 @@ module Api
|
||||
def create
|
||||
Params::SubmissionCreateValidator.call(params)
|
||||
|
||||
return render json: { error: 'Template not found' }, status: :unprocessable_entity if @template.nil?
|
||||
return render json: { error: 'Template not found' }, status: :unprocessable_content if @template.nil?
|
||||
|
||||
if @template.fields.blank?
|
||||
Rollbar.warning("Template does not contain fields: #{@template.id}") if defined?(Rollbar)
|
||||
|
||||
return render json: { error: 'Template does not contain fields' }, status: :unprocessable_entity
|
||||
return render json: { error: 'Template does not contain fields' }, status: :unprocessable_content
|
||||
end
|
||||
|
||||
params[:send_email] = true unless params.key?(:send_email)
|
||||
@@ -82,7 +84,7 @@ module Api
|
||||
DownloadUtils::UnableToDownload => e
|
||||
Rollbar.warning(e) if defined?(Rollbar)
|
||||
|
||||
render json: { error: e.message }, status: :unprocessable_entity
|
||||
render json: { error: e.message }, status: :unprocessable_content
|
||||
end
|
||||
|
||||
def destroy
|
||||
@@ -182,6 +184,7 @@ module Api
|
||||
:send_email, :send_sms, :bcc_completed, :completed_redirect_url, :reply_to, :go_to_last,
|
||||
:require_phone_2fa, :expire_at, :name,
|
||||
{
|
||||
variables: {},
|
||||
message: %i[subject body],
|
||||
submitters: [[:send_email, :send_sms, :completed_redirect_url, :uuid, :name, :email, :role,
|
||||
:completed, :phone, :application_key, :external_id, :reply_to, :go_to_last,
|
||||
@@ -189,7 +192,7 @@ module Api
|
||||
{ metadata: {}, values: {}, roles: [], readonly_fields: [], message: %i[subject body],
|
||||
fields: [:name, :uuid, :default_value, :value, :title, :description,
|
||||
:readonly, :required, :validation_pattern, :invalid_message,
|
||||
{ default_value: [], value: [], preferences: {} }] }]]
|
||||
{ default_value: [], value: [], preferences: {}, validation: {} }] }]]
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -14,9 +14,11 @@ module Api
|
||||
documents_attachments: :blob, attachments_attachments: :blob)
|
||||
)
|
||||
|
||||
expires_at = Accounts.link_expires_at(current_account)
|
||||
|
||||
render json: {
|
||||
data: submitters.map do |s|
|
||||
Submitters::SerializeForApi.call(s, with_template: true, with_events: true, params:)
|
||||
Submitters::SerializeForApi.call(s, with_template: true, with_events: true, params:, expires_at:)
|
||||
end,
|
||||
pagination: {
|
||||
count: submitters.size,
|
||||
@@ -34,7 +36,7 @@ module Api
|
||||
|
||||
def update
|
||||
if @submitter.completed_at?
|
||||
return render json: { error: 'Submitter has already completed the submission.' }, status: :unprocessable_entity
|
||||
return render json: { error: 'Submitter has already completed the submission.' }, status: :unprocessable_content
|
||||
end
|
||||
|
||||
submission = @submitter.submission
|
||||
@@ -74,7 +76,7 @@ module Api
|
||||
rescue Submitters::NormalizeValues::BaseError, DownloadUtils::UnableToDownload => e
|
||||
Rollbar.warning(e) if defined?(Rollbar)
|
||||
|
||||
render json: { error: e.message }, status: :unprocessable_entity
|
||||
render json: { error: e.message }, status: :unprocessable_content
|
||||
end
|
||||
|
||||
def submitter_params
|
||||
|
||||
@@ -26,13 +26,15 @@ module Api
|
||||
original_template: @template,
|
||||
documents: params[:documents])
|
||||
|
||||
Templates.maybe_assign_access(cloned_template)
|
||||
|
||||
cloned_template.save!
|
||||
|
||||
WebhookUrls.enqueue_events(cloned_template, 'template.created')
|
||||
|
||||
SearchEntries.enqueue_reindex(cloned_template)
|
||||
|
||||
render json: Templates::SerializeForApi.call(cloned_template, schema_documents)
|
||||
render json: Templates::SerializeForApi.call(cloned_template, schema_documents:)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -24,13 +24,14 @@ module Api
|
||||
name: :preview_images)
|
||||
.preload(:blob)
|
||||
|
||||
expires_at = Accounts.link_expires_at(current_account)
|
||||
|
||||
render json: {
|
||||
data: templates.map do |t|
|
||||
Templates::SerializeForApi.call(
|
||||
t,
|
||||
schema_documents.select { |e| e.record_id == t.id },
|
||||
preview_image_attachments
|
||||
)
|
||||
Templates::SerializeForApi.call(t,
|
||||
schema_documents: schema_documents.select { |e| e.record_id == t.id },
|
||||
preview_image_attachments:,
|
||||
expires_at:)
|
||||
end,
|
||||
pagination: {
|
||||
count: templates.size,
|
||||
@@ -111,9 +112,10 @@ module Api
|
||||
:required, :readonly, :default_value,
|
||||
:title, :description, :prefillable,
|
||||
{ preferences: {},
|
||||
default_value: [],
|
||||
conditions: [%i[field_uuid value action operation]],
|
||||
options: [%i[value uuid]],
|
||||
validation: %i[message pattern],
|
||||
validation: %i[message pattern min max step],
|
||||
areas: [%i[x y w h cell_w attachment_uuid option_uuid page]] }]]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -7,8 +7,8 @@ module Api
|
||||
def merge
|
||||
files = params[:files] || []
|
||||
|
||||
return render json: { error: 'Files are required' }, status: :unprocessable_entity if files.blank?
|
||||
return render json: { error: 'At least 2 files are required' }, status: :unprocessable_entity if files.size < 2
|
||||
return render json: { error: 'Files are required' }, status: :unprocessable_content if files.blank?
|
||||
return render json: { error: 'At least 2 files are required' }, status: :unprocessable_content if files.size < 2
|
||||
|
||||
render json: {
|
||||
data: Base64.encode64(PdfUtils.merge(files.map { |base64| StringIO.new(Base64.decode64(base64)) }).string)
|
||||
@@ -35,7 +35,7 @@ module Api
|
||||
end
|
||||
}
|
||||
rescue HexaPDF::MalformedPDFError
|
||||
render json: { error: 'Malformed PDF' }, status: :unprocessable_entity
|
||||
render json: { error: 'Malformed PDF' }, status: :unprocessable_content
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,12 +15,12 @@ class EmailSmtpSettingsController < ApplicationController
|
||||
|
||||
redirect_to settings_email_index_path, notice: I18n.t('changes_have_been_saved')
|
||||
else
|
||||
render :index, status: :unprocessable_entity
|
||||
render :index, status: :unprocessable_content
|
||||
end
|
||||
rescue StandardError => e
|
||||
flash[:alert] = e.message
|
||||
|
||||
render :index, status: :unprocessable_entity
|
||||
render :index, status: :unprocessable_content
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -53,7 +53,7 @@ class EsignSettingsController < ApplicationController
|
||||
@cert_record.errors.add(:name, I18n.t('already_exists'))
|
||||
|
||||
return render turbo_stream: turbo_stream.replace(:modal, template: 'esign_settings/new'),
|
||||
status: :unprocessable_entity
|
||||
status: :unprocessable_content
|
||||
end
|
||||
|
||||
save_new_cert!(@encrypted_config, @cert_record)
|
||||
@@ -64,7 +64,7 @@ class EsignSettingsController < ApplicationController
|
||||
|
||||
@cert_record.errors.add(:password, e.message)
|
||||
|
||||
render turbo_stream: turbo_stream.replace(:modal, template: 'esign_settings/new'), status: :unprocessable_entity
|
||||
render turbo_stream: turbo_stream.replace(:modal, template: 'esign_settings/new'), status: :unprocessable_content
|
||||
end
|
||||
|
||||
def update
|
||||
|
||||
@@ -24,7 +24,7 @@ class MfaSetupController < ApplicationController
|
||||
|
||||
@error_message = I18n.t('code_is_invalid')
|
||||
|
||||
render turbo_stream: turbo_stream.replace(:mfa_form, partial: 'mfa_setup/form'), status: :unprocessable_entity
|
||||
render turbo_stream: turbo_stream.replace(:mfa_form, partial: 'mfa_setup/form'), status: :unprocessable_content
|
||||
end
|
||||
end
|
||||
|
||||
@@ -36,7 +36,7 @@ class MfaSetupController < ApplicationController
|
||||
else
|
||||
@error_message = I18n.t('code_is_invalid')
|
||||
|
||||
render turbo_stream: turbo_stream.replace(:modal, template: 'mfa_setup/edit'), status: :unprocessable_entity
|
||||
render turbo_stream: turbo_stream.replace(:modal, template: 'mfa_setup/edit'), status: :unprocessable_content
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class PasswordsController < Devise::PasswordsController
|
||||
# rubocop:disable Rails/LexicallyScopedActionFilter
|
||||
skip_before_action :require_no_authentication, only: %i[edit update]
|
||||
# rubocop:enable Rails/LexicallyScopedActionFilter
|
||||
|
||||
class Current < ActiveSupport::CurrentAttributes
|
||||
attribute :user
|
||||
end
|
||||
@@ -16,4 +20,10 @@ class PasswordsController < Devise::PasswordsController
|
||||
Current.user = resource
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def after_resetting_password_path_for(_)
|
||||
new_session_path(resource_name)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,16 +11,16 @@ class ProfileController < ApplicationController
|
||||
if current_user.update(contact_params)
|
||||
redirect_to settings_profile_index_path, notice: I18n.t('contact_information_has_been_update')
|
||||
else
|
||||
render :index, status: :unprocessable_entity
|
||||
render :index, status: :unprocessable_content
|
||||
end
|
||||
end
|
||||
|
||||
def update_password
|
||||
if current_user.update(password_params)
|
||||
if current_user.update_with_password(password_params)
|
||||
bypass_sign_in(current_user)
|
||||
redirect_to settings_profile_index_path, notice: I18n.t('password_has_been_changed')
|
||||
else
|
||||
render :index, status: :unprocessable_entity
|
||||
render :index, status: :unprocessable_content
|
||||
end
|
||||
end
|
||||
|
||||
@@ -31,6 +31,6 @@ class ProfileController < ApplicationController
|
||||
end
|
||||
|
||||
def password_params
|
||||
params.require(:user).permit(:password, :password_confirmation)
|
||||
params.require(:user).permit(:password, :password_confirmation, :current_password)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class RevealAccessTokenController < ApplicationController
|
||||
def show
|
||||
authorize!(:manage, current_user.access_token)
|
||||
end
|
||||
|
||||
def create
|
||||
authorize!(:manage, current_user.access_token)
|
||||
|
||||
if current_user.valid_password?(params[:password])
|
||||
render turbo_stream: turbo_stream.replace(:access_token_container,
|
||||
partial: 'reveal_access_token/access_token',
|
||||
locals: { token: current_user.access_token.token })
|
||||
else
|
||||
render turbo_stream: turbo_stream.replace(:modal, template: 'reveal_access_token/show',
|
||||
locals: { error_message: I18n.t('wrong_password') }),
|
||||
status: :unprocessable_content
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -16,7 +16,7 @@ class SessionsController < Devise::SessionsController
|
||||
end
|
||||
|
||||
if User.exists?(email:, otp_required_for_login: true) && sign_in_params[:otp_attempt].blank?
|
||||
return render :otp, locals: { resource: User.new(sign_in_params) }, status: :unprocessable_entity
|
||||
return render :otp, locals: { resource: User.new(sign_in_params) }, status: :unprocessable_content
|
||||
end
|
||||
|
||||
super
|
||||
|
||||
@@ -23,10 +23,10 @@ class SetupController < ApplicationController
|
||||
unless URI.parse(encrypted_config_params[:value].to_s).class.in?([URI::HTTP, URI::HTTPS])
|
||||
@encrypted_config.errors.add(:value, I18n.t('should_be_a_valid_url'))
|
||||
|
||||
return render :index, status: :unprocessable_entity
|
||||
return render :index, status: :unprocessable_content
|
||||
end
|
||||
|
||||
return render :index, status: :unprocessable_entity unless @account.valid?
|
||||
return render :index, status: :unprocessable_content unless @account.valid?
|
||||
|
||||
if @user.save
|
||||
encrypted_configs = [
|
||||
@@ -42,7 +42,7 @@ class SetupController < ApplicationController
|
||||
|
||||
redirect_to newsletter_path
|
||||
else
|
||||
render :index, status: :unprocessable_entity
|
||||
render :index, status: :unprocessable_content
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ class StartFormController < ApplicationController
|
||||
if filter_undefined_submitters(@template).size > 1 && @submitter.new_record?
|
||||
@error_message = multiple_submitters_error_message
|
||||
|
||||
return render :show, status: :unprocessable_entity
|
||||
return render :show, status: :unprocessable_content
|
||||
end
|
||||
|
||||
if (is_new_record = @submitter.new_record?)
|
||||
@@ -60,7 +60,7 @@ class StartFormController < ApplicationController
|
||||
|
||||
redirect_to submit_form_path(@submitter.slug)
|
||||
else
|
||||
render :show, status: :unprocessable_entity
|
||||
render :show, status: :unprocessable_content
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -206,7 +206,7 @@ class StartFormController < ApplicationController
|
||||
end
|
||||
|
||||
def handle_require_2fa(submitter, is_new_record:)
|
||||
return render :show, status: :unprocessable_entity if submitter.errors.present?
|
||||
return render :show, status: :unprocessable_content if submitter.errors.present?
|
||||
|
||||
is_otp_verified = Submitters.verify_link_otp!(params[:one_time_code], submitter)
|
||||
|
||||
@@ -223,7 +223,7 @@ class StartFormController < ApplicationController
|
||||
|
||||
redirect_to submit_form_path(submitter.slug)
|
||||
else
|
||||
render :show, status: :unprocessable_entity
|
||||
render :show, status: :unprocessable_content
|
||||
end
|
||||
else
|
||||
Submitters.send_shared_link_email_verification_code(submitter, request:)
|
||||
|
||||
@@ -13,7 +13,7 @@ class StorageSettingsController < ApplicationController
|
||||
|
||||
redirect_to settings_storage_index_path, notice: I18n.t('changes_have_been_saved')
|
||||
else
|
||||
render :index, status: :unprocessable_entity
|
||||
render :index, status: :unprocessable_content
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ class SubmissionsController < ApplicationController
|
||||
rescue Submissions::CreateFromSubmitters::BaseError => e
|
||||
render turbo_stream: turbo_stream.replace(:submitters_error, partial: 'submissions/error',
|
||||
locals: { error: e.message }),
|
||||
status: :unprocessable_entity
|
||||
status: :unprocessable_content
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
||||
@@ -70,7 +70,7 @@ class SubmissionsDownloadController < ApplicationController
|
||||
return if submitter.submission.submitters.order(:completed_at).last != submitter
|
||||
|
||||
attachment = submitter.submission.combined_document_attachment
|
||||
attachment ||= Submissions::GenerateCombinedAttachment.call(submitter)
|
||||
attachment ||= Submissions::EnsureCombinedGenerated.call(submitter)
|
||||
|
||||
filename_format = AccountConfig.find_or_initialize_by(account_id: submitter.account_id,
|
||||
key: AccountConfig::DOCUMENT_FILENAME_FORMAT_KEY)&.value
|
||||
|
||||
@@ -10,11 +10,16 @@ class SubmissionsExportController < ApplicationController
|
||||
attachments_attachments: :blob })
|
||||
.order(id: :asc)
|
||||
|
||||
submissions = Submissions.search(current_user, submissions, params[:q], search_values: true)
|
||||
submissions = Submissions::Filter.call(submissions, current_user, params)
|
||||
|
||||
expires_at = Accounts.link_expires_at(current_account)
|
||||
|
||||
if params[:format] == 'csv'
|
||||
send_data Submissions::GenerateExportFiles.call(submissions, format: params[:format]),
|
||||
send_data Submissions::GenerateExportFiles.call(submissions, format: params[:format], expires_at:),
|
||||
filename: "#{@template.name}.csv"
|
||||
elsif params[:format] == 'xlsx'
|
||||
send_data Submissions::GenerateExportFiles.call(submissions, format: params[:format]),
|
||||
send_data Submissions::GenerateExportFiles.call(submissions, format: params[:format], expires_at:),
|
||||
filename: "#{@template.name}.xlsx"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -48,20 +48,20 @@ class SubmitFormController < ApplicationController
|
||||
|
||||
def update
|
||||
if @submitter.completed_at?
|
||||
return render json: { error: I18n.t('form_has_been_completed_already') }, status: :unprocessable_entity
|
||||
return render json: { error: I18n.t('form_has_been_completed_already') }, status: :unprocessable_content
|
||||
end
|
||||
|
||||
if @submitter.submission.template&.archived_at? || @submitter.submission.archived_at?
|
||||
return render json: { error: I18n.t('form_has_been_archived') }, status: :unprocessable_entity
|
||||
return render json: { error: I18n.t('form_has_been_archived') }, status: :unprocessable_content
|
||||
end
|
||||
|
||||
if @submitter.submission.expired?
|
||||
return render json: { error: I18n.t('form_has_been_expired') }, status: :unprocessable_entity
|
||||
return render json: { error: I18n.t('form_has_been_expired') }, status: :unprocessable_content
|
||||
end
|
||||
|
||||
if @submitter.declined_at?
|
||||
return render json: { error: I18n.t('form_has_been_declined') },
|
||||
status: :unprocessable_entity
|
||||
status: :unprocessable_content
|
||||
end
|
||||
|
||||
Submitters::SubmitValues.call(@submitter, params, request)
|
||||
@@ -70,9 +70,9 @@ class SubmitFormController < ApplicationController
|
||||
rescue Submitters::SubmitValues::RequiredFieldError => e
|
||||
Rollbar.warning("Required field #{@submitter.id}: #{e.message}") if defined?(Rollbar)
|
||||
|
||||
render json: { field_uuid: e.message }, status: :unprocessable_entity
|
||||
render json: { field_uuid: e.message }, status: :unprocessable_content
|
||||
rescue Submitters::SubmitValues::ValidationError => e
|
||||
render json: { error: e.message }, status: :unprocessable_entity
|
||||
render json: { error: e.message }, status: :unprocessable_content
|
||||
end
|
||||
|
||||
def completed; end
|
||||
|
||||
@@ -11,13 +11,13 @@ class SubmitFormDownloadController < ApplicationController
|
||||
|
||||
return redirect_to submitter_download_index_path(@submitter.slug) if @submitter.completed_at?
|
||||
|
||||
return head :unprocessable_entity if @submitter.declined_at? ||
|
||||
@submitter.submission.archived_at? ||
|
||||
@submitter.submission.expired? ||
|
||||
@submitter.submission.template&.archived_at? ||
|
||||
AccountConfig.exists?(account_id: @submitter.account_id,
|
||||
key: AccountConfig::ALLOW_TO_PARTIAL_DOWNLOAD_KEY,
|
||||
value: false)
|
||||
return head :unprocessable_content if @submitter.declined_at? ||
|
||||
@submitter.submission.archived_at? ||
|
||||
@submitter.submission.expired? ||
|
||||
@submitter.submission.template&.archived_at? ||
|
||||
AccountConfig.exists?(account_id: @submitter.account_id,
|
||||
key: AccountConfig::ALLOW_TO_PARTIAL_DOWNLOAD_KEY,
|
||||
value: false)
|
||||
|
||||
last_completed_submitter = @submitter.submission.submitters
|
||||
.where.not(id: @submitter.id)
|
||||
|
||||
@@ -7,7 +7,7 @@ class SubmitFormInviteController < ApplicationController
|
||||
def create
|
||||
submitter = Submitter.find_by!(slug: params[:submit_form_slug])
|
||||
|
||||
return head :unprocessable_entity unless can_invite?(submitter)
|
||||
return head :unprocessable_content unless can_invite?(submitter)
|
||||
|
||||
invite_submitters = filter_invite_submitters(submitter, 'invite_by_uuid')
|
||||
optional_invite_submitters = filter_invite_submitters(submitter, 'optional_invite_by_uuid')
|
||||
@@ -34,7 +34,7 @@ class SubmitFormInviteController < ApplicationController
|
||||
|
||||
head :ok
|
||||
else
|
||||
head :unprocessable_entity
|
||||
head :unprocessable_content
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ class TemplateDocumentsController < ApplicationController
|
||||
|
||||
def create
|
||||
if params[:blobs].blank? && params[:files].blank?
|
||||
return render json: { error: I18n.t('file_is_missing') }, status: :unprocessable_entity
|
||||
return render json: { error: I18n.t('file_is_missing') }, status: :unprocessable_content
|
||||
end
|
||||
|
||||
old_fields_hash = @template.fields.hash
|
||||
@@ -28,6 +28,6 @@ class TemplateDocumentsController < ApplicationController
|
||||
)
|
||||
}
|
||||
rescue Templates::CreateAttachments::PdfEncrypted
|
||||
render json: { error: 'PDF encrypted', status: 'pdf_encrypted' }, status: :unprocessable_entity
|
||||
render json: { error: 'PDF encrypted', status: 'pdf_encrypted' }, status: :unprocessable_content
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@ class TemplatesCloneAndReplaceController < ApplicationController
|
||||
load_and_authorize_resource :template
|
||||
|
||||
def create
|
||||
return head :unprocessable_entity if params[:files].blank?
|
||||
return head :unprocessable_content if params[:files].blank?
|
||||
|
||||
ActiveRecord::Associations::Preloader.new(
|
||||
records: [@template],
|
||||
@@ -17,6 +17,8 @@ class TemplatesCloneAndReplaceController < ApplicationController
|
||||
|
||||
documents = Templates::ReplaceAttachments.call(cloned_template, params, extract_fields: true)
|
||||
|
||||
Templates.maybe_assign_access(cloned_template)
|
||||
|
||||
cloned_template.save!
|
||||
|
||||
Templates::CloneAttachments.call(template: cloned_template, original_template: @template,
|
||||
@@ -31,7 +33,7 @@ class TemplatesCloneAndReplaceController < ApplicationController
|
||||
rescue Templates::CreateAttachments::PdfEncrypted
|
||||
respond_to do |f|
|
||||
f.html { render turbo_stream: turbo_stream.append(params[:form_id], html: helpers.tag.prompt_password) }
|
||||
f.json { render json: { error: 'PDF encrypted', status: 'pdf_encrypted' }, status: :unprocessable_entity }
|
||||
f.json { render json: { error: 'PDF encrypted', status: 'pdf_encrypted' }, status: :unprocessable_content }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -69,6 +69,8 @@ class TemplatesController < ApplicationController
|
||||
@template.account = current_account
|
||||
end
|
||||
|
||||
Templates.maybe_assign_access(@template)
|
||||
|
||||
if @template.save
|
||||
Templates::CloneAttachments.call(template: @template, original_template: @base_template) if @base_template
|
||||
|
||||
@@ -78,7 +80,7 @@ class TemplatesController < ApplicationController
|
||||
|
||||
maybe_redirect_to_template(@template)
|
||||
else
|
||||
render turbo_stream: turbo_stream.replace(:modal, template: 'templates/new'), status: :unprocessable_entity
|
||||
render turbo_stream: turbo_stream.replace(:modal, template: 'templates/new'), status: :unprocessable_content
|
||||
end
|
||||
end
|
||||
|
||||
@@ -122,9 +124,10 @@ class TemplatesController < ApplicationController
|
||||
:required, :readonly, :default_value,
|
||||
:title, :description, :prefillable,
|
||||
{ preferences: {},
|
||||
default_value: [],
|
||||
conditions: [%i[field_uuid value action operation]],
|
||||
options: [%i[value uuid]],
|
||||
validation: %i[message pattern],
|
||||
validation: %i[message pattern min max step],
|
||||
areas: [%i[x y w h cell_w attachment_uuid option_uuid page]] }]] }
|
||||
)
|
||||
end
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
class TemplatesDebugController < ApplicationController
|
||||
load_and_authorize_resource :template
|
||||
|
||||
DEBUG_FILE = ''
|
||||
|
||||
def show
|
||||
attachment = @template.documents.first
|
||||
|
||||
@@ -16,6 +18,8 @@ class TemplatesDebugController < ApplicationController
|
||||
|
||||
@template.update!(fields: Templates::ProcessDocument.normalize_attachment_fields(@template, [attachment]))
|
||||
|
||||
debug_file if DEBUG_FILE.present?
|
||||
|
||||
ActiveRecord::Associations::Preloader.new(
|
||||
records: [@template],
|
||||
associations: [schema_documents: { preview_images_attachments: :blob }]
|
||||
@@ -31,4 +35,27 @@ class TemplatesDebugController < ApplicationController
|
||||
|
||||
render 'templates/edit', layout: 'plain'
|
||||
end
|
||||
|
||||
def debug_file
|
||||
tempfile = Tempfile.new
|
||||
tempfile.binmode
|
||||
tempfile.write(File.read(DEBUG_FILE))
|
||||
tempfile.rewind
|
||||
|
||||
filename = File.basename(DEBUG_FILE)
|
||||
|
||||
file = ActionDispatch::Http::UploadedFile.new(
|
||||
tempfile:,
|
||||
filename:,
|
||||
type: Marcel::MimeType.for(tempfile)
|
||||
)
|
||||
|
||||
params = { files: [file] }
|
||||
|
||||
documents = Templates::CreateAttachments.call(@template, params)
|
||||
|
||||
schema = documents.map { |doc| { attachment_uuid: doc.uuid, name: doc.filename.base } }
|
||||
|
||||
@template.update!(schema:)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -46,6 +46,8 @@ class TemplatesUploadsController < ApplicationController
|
||||
template.folder = TemplateFolders.find_or_create_by_name(current_user, params[:folder_name])
|
||||
template.name = File.basename((url_params || params)[:files].first.original_filename, '.*')
|
||||
|
||||
Templates.maybe_assign_access(template)
|
||||
|
||||
template.save!
|
||||
|
||||
template
|
||||
|
||||
@@ -27,9 +27,10 @@ class UsersController < ApplicationController
|
||||
if User.accessible_by(current_ability).exists?(email: @user.email)
|
||||
@user.errors.add(:email, I18n.t('already_exists'))
|
||||
|
||||
return render turbo_stream: turbo_stream.replace(:modal, template: 'users/new'), status: :unprocessable_entity
|
||||
return render turbo_stream: turbo_stream.replace(:modal, template: 'users/new'), status: :unprocessable_content
|
||||
end
|
||||
|
||||
@user.password = SecureRandom.hex if @user.password.blank?
|
||||
@user.role = User::ADMIN_ROLE unless role_valid?(@user.role)
|
||||
|
||||
if @user.save
|
||||
@@ -37,7 +38,7 @@ class UsersController < ApplicationController
|
||||
|
||||
redirect_back fallback_location: settings_users_path, notice: I18n.t('user_has_been_invited')
|
||||
else
|
||||
render turbo_stream: turbo_stream.replace(:modal, template: 'users/new'), status: :unprocessable_entity
|
||||
render turbo_stream: turbo_stream.replace(:modal, template: 'users/new'), status: :unprocessable_content
|
||||
end
|
||||
end
|
||||
|
||||
@@ -54,10 +55,10 @@ class UsersController < ApplicationController
|
||||
@user.account = account
|
||||
end
|
||||
|
||||
if @user.update(attrs.except(current_user == @user ? :role : nil))
|
||||
if @user.update(attrs.except(*(current_user == @user ? %i[password otp_required_for_login role] : %i[password])))
|
||||
redirect_back fallback_location: settings_users_path, notice: I18n.t('user_has_been_updated')
|
||||
else
|
||||
render turbo_stream: turbo_stream.replace(:modal, template: 'users/edit'), status: :unprocessable_entity
|
||||
render turbo_stream: turbo_stream.replace(:modal, template: 'users/edit'), status: :unprocessable_content
|
||||
end
|
||||
end
|
||||
|
||||
@@ -83,7 +84,7 @@ class UsersController < ApplicationController
|
||||
|
||||
def user_params
|
||||
if params.key?(:user)
|
||||
permitted_params = %i[email first_name last_name password archived_at]
|
||||
permitted_params = %i[email first_name last_name password archived_at otp_required_for_login]
|
||||
|
||||
permitted_params << :role if role_valid?(params.dig(:user, :role))
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class UsersSendResetPasswordController < ApplicationController
|
||||
load_and_authorize_resource :user
|
||||
|
||||
LIMIT_DURATION = 10.minutes
|
||||
|
||||
def update
|
||||
authorize!(:manage, @user)
|
||||
|
||||
if @user.reset_password_sent_at && @user.reset_password_sent_at > LIMIT_DURATION.ago
|
||||
redirect_back fallback_location: settings_users_path, notice: I18n.t('email_has_been_sent_already')
|
||||
else
|
||||
@user.send_reset_password_instructions
|
||||
|
||||
redirect_back fallback_location: settings_users_path,
|
||||
notice: I18n.t('an_email_with_password_reset_instructions_has_been_sent')
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -29,8 +29,15 @@
|
||||
{{ optionValue(option) }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ field.title || field.name || fieldNames[field.type] }}
|
||||
<template v-if="field.type === 'checkbox' && !field.name">
|
||||
<MarkdownContent
|
||||
v-if="field.title"
|
||||
:text-only="true"
|
||||
:string="field.title"
|
||||
/>
|
||||
<template v-else>
|
||||
{{ field.name || fieldNames[field.type] }}
|
||||
</template>
|
||||
<template v-if="field.type === 'checkbox' && !field.name && !field.title">
|
||||
{{ fieldIndex + 1 }}
|
||||
</template>
|
||||
<template v-else-if="!field.required && field.type !== 'checkbox'">
|
||||
@@ -222,12 +229,14 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MarkdownContent from './markdown_content'
|
||||
import { IconTextSize, IconWritingSign, IconCalendarEvent, IconPhoto, IconCheckbox, IconPaperclip, IconSelect, IconCircleDot, IconChecks, IconCheck, IconColumns3, IconPhoneCheck, IconLetterCaseUpper, IconCreditCard, IconRubberStamp, IconSquareNumber1, IconId } from '@tabler/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'FieldArea',
|
||||
components: {
|
||||
IconPaperclip,
|
||||
MarkdownContent,
|
||||
IconCheck
|
||||
},
|
||||
inject: ['t'],
|
||||
@@ -422,10 +431,14 @@ export default {
|
||||
},
|
||||
formattedDate () {
|
||||
if (this.field.type === 'date' && this.modelValue) {
|
||||
return this.formatDate(
|
||||
this.modelValue === '{{date}}' ? new Date() : new Date(this.modelValue),
|
||||
this.field.preferences?.format || (this.locale.endsWith('-US') ? 'MM/DD/YYYY' : 'DD/MM/YYYY')
|
||||
)
|
||||
try {
|
||||
return this.formatDate(
|
||||
this.modelValue === '{{date}}' ? new Date() : new Date(this.modelValue),
|
||||
this.field.preferences?.format || (this.locale.endsWith('-US') ? 'MM/DD/YYYY' : 'DD/MM/YYYY')
|
||||
)
|
||||
} catch {
|
||||
return this.modelValue
|
||||
}
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<div class="space-y-3 mt-5">
|
||||
<a
|
||||
v-if="completedButton.url"
|
||||
:href="sanitizeHref(completedButton.url)"
|
||||
:href="sanitizeUrl(completedButton.url)"
|
||||
rel="noopener noreferrer nofollow"
|
||||
class="white-button flex items-center w-full completed-form-completed-button"
|
||||
>
|
||||
@@ -102,6 +102,7 @@
|
||||
<script>
|
||||
import { IconCircleCheck, IconBrandGithub, IconMail, IconDownload, IconInnerShadowTop, IconLogin } from '@tabler/icons-vue'
|
||||
import MarkdownContent from './markdown_content'
|
||||
import { sanitizeUrl } from '@braintree/sanitize-url'
|
||||
|
||||
export default {
|
||||
name: 'FormCompleted',
|
||||
@@ -198,6 +199,7 @@ export default {
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
sanitizeUrl,
|
||||
sendCopyToEmail () {
|
||||
this.isSendingCopy = true
|
||||
|
||||
@@ -252,11 +254,6 @@ export default {
|
||||
this.isDownloading = false
|
||||
})
|
||||
},
|
||||
sanitizeHref (href) {
|
||||
if (href && href.trim().match(/^((?:https?:\/\/)|\/)/)) {
|
||||
return href.replace(/javascript:/g, '')
|
||||
}
|
||||
},
|
||||
downloadSafariIos (urls) {
|
||||
const fileRequests = urls.map((url) => {
|
||||
return fetch(url).then(async (resp) => {
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
</template>
|
||||
</label>
|
||||
<button
|
||||
v-if="withToday"
|
||||
class="btn btn-outline btn-sm !normal-case font-normal set-current-date-button"
|
||||
@click.prevent="[setCurrentDate(), $emit('focus')]"
|
||||
>
|
||||
@@ -46,6 +47,8 @@
|
||||
:id="field.uuid"
|
||||
ref="input"
|
||||
v-model="value"
|
||||
:min="validationMin"
|
||||
:max="validationMax"
|
||||
class="base-input !text-2xl text-center w-full"
|
||||
:required="field.required"
|
||||
type="date"
|
||||
@@ -89,6 +92,44 @@ export default {
|
||||
},
|
||||
emits: ['update:model-value', 'focus', 'submit'],
|
||||
computed: {
|
||||
dateNowString () {
|
||||
const today = new Date()
|
||||
|
||||
const yyyy = today.getFullYear()
|
||||
const mm = String(today.getMonth() + 1).padStart(2, '0')
|
||||
const dd = String(today.getDate()).padStart(2, '0')
|
||||
|
||||
return `${yyyy}-${mm}-${dd}`
|
||||
},
|
||||
validationMin () {
|
||||
if (this.field.validation?.min) {
|
||||
return ['{{date}}', '{date}'].includes(this.field.validation.min) ? this.dateNowString : this.field.validation.min
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
validationMax () {
|
||||
if (this.field.validation?.max) {
|
||||
return ['{{date}}', '{date}'].includes(this.field.validation.max) ? this.dateNowString : this.field.validation.max
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
withToday () {
|
||||
const todayDate = new Date().setHours(0, 0, 0, 0)
|
||||
|
||||
if (this.validationMin) {
|
||||
if (new Date(this.validationMin).setHours(0, 0, 0, 0) <= todayDate) {
|
||||
return this.validationMax ? (new Date(this.validationMax).setHours(0, 0, 0, 0) >= todayDate) : true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} else if (this.validationMax) {
|
||||
return new Date(this.validationMax).setHours(0, 0, 0, 0) >= todayDate
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
},
|
||||
value: {
|
||||
set (value) {
|
||||
this.$emit('update:model-value', value)
|
||||
|
||||
@@ -572,6 +572,7 @@ import FormCompleted from './completed'
|
||||
import { IconInnerShadowTop, IconArrowsDiagonal, IconWritingSign, IconArrowsDiagonalMinimize2 } from '@tabler/icons-vue'
|
||||
import AppearsOn from './appears_on'
|
||||
import i18n from './i18n'
|
||||
import { sanitizeUrl } from '@braintree/sanitize-url'
|
||||
|
||||
const isEmpty = (obj) => {
|
||||
if (obj == null) return true
|
||||
@@ -1014,7 +1015,11 @@ export default {
|
||||
const aArea = (fieldAreasIndex[aField.uuid] ||= [...(aField.areas || [])].sort(sortArea)[0])
|
||||
const bArea = (fieldAreasIndex[bField.uuid] ||= [...(bField.areas || [])].sort(sortArea)[0])
|
||||
|
||||
return sortArea(aArea, bArea)
|
||||
if (aArea && bArea) {
|
||||
return sortArea(aArea, bArea)
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1476,7 +1481,7 @@ export default {
|
||||
}
|
||||
|
||||
if (this.completedRedirectUrl) {
|
||||
window.location.href = this.completedRedirectUrl
|
||||
window.location.href = sanitizeUrl(this.completedRedirectUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,13 @@ export default {
|
||||
computed: {
|
||||
isInlineSize () {
|
||||
return CSS.supports('container-type: size')
|
||||
},
|
||||
fieldsUuidIndex () {
|
||||
return this.fields.reduce((acc, field) => {
|
||||
acc[field.uuid] = field
|
||||
|
||||
return acc
|
||||
}, {})
|
||||
}
|
||||
},
|
||||
async mounted () {
|
||||
@@ -96,8 +103,19 @@ export default {
|
||||
findPageElementForArea (area) {
|
||||
return (this.$root.$el?.parentNode?.getRootNode() || document).getElementById(`page-${area.attachment_uuid}-${area.page}`)
|
||||
},
|
||||
normalizeFormula (formula, depth = 0) {
|
||||
if (depth > 10) return formula
|
||||
|
||||
return formula.replace(/{{(.*?)}}/g, (match, uuid) => {
|
||||
if (this.fieldsUuidIndex[uuid]) {
|
||||
return `(${this.normalizeFormula(this.fieldsUuidIndex[uuid].preferences.formula, depth + 1)})`
|
||||
} else {
|
||||
return match
|
||||
}
|
||||
})
|
||||
},
|
||||
calculateFormula (field) {
|
||||
const transformedFormula = field.preferences.formula.replace(/{{(.*?)}}/g, (match, uuid) => {
|
||||
const transformedFormula = this.normalizeFormula(field.preferences.formula).replace(/{{(.*?)}}/g, (match, uuid) => {
|
||||
return this.readonlyValues[uuid] || this.values[uuid] || 0.0
|
||||
})
|
||||
|
||||
|
||||
@@ -1,35 +1,32 @@
|
||||
<template>
|
||||
<span>
|
||||
<template
|
||||
v-for="(item, index) in items"
|
||||
:key="index"
|
||||
>
|
||||
<a
|
||||
v-if="item.startsWith('<a') && item.endsWith('</a>')"
|
||||
:href="sanitizeHref(extractAttr(item, 'href'))"
|
||||
rel="noopener noreferrer nofollow"
|
||||
:class="extractAttr(item, 'class') || 'link'"
|
||||
target="_blank"
|
||||
>
|
||||
{{ extractText(item) }}
|
||||
</a>
|
||||
<b
|
||||
v-else-if="item.startsWith('<b>') || item.startsWith('<strong>')"
|
||||
>
|
||||
{{ extractText(item) }}
|
||||
</b>
|
||||
<i
|
||||
v-else-if="item.startsWith('<i>') || item.startsWith('<em>')"
|
||||
>
|
||||
{{ extractText(item) }}
|
||||
</i>
|
||||
<br
|
||||
v-else-if="item === '<br>' || item === '\n'"
|
||||
>
|
||||
<span v-if="textOnly">
|
||||
{{ dom.body.textContent }}
|
||||
</span>
|
||||
<template v-else>
|
||||
<template
|
||||
v-else
|
||||
v-for="(item, index) in nodes || dom.body.childNodes"
|
||||
:key="index"
|
||||
>
|
||||
{{ item }}
|
||||
<a
|
||||
v-if="item.tagName === 'A' && item.getAttribute('href') !== 'undefined'"
|
||||
:href="sanitizeUrl(item.getAttribute('href'))"
|
||||
rel="noopener noreferrer nofollow"
|
||||
:class="item.getAttribute('class') || 'link'"
|
||||
target="_blank"
|
||||
>
|
||||
<MarkdownContent :nodes="item.childNodes" />
|
||||
</a>
|
||||
<component
|
||||
:is="item.tagName"
|
||||
v-else-if="safeTags.includes(item.tagName)"
|
||||
>
|
||||
<MarkdownContent :nodes="item.childNodes" />
|
||||
</component>
|
||||
<br v-else-if="item.tagName === 'BR' || item.nodeValue === '\n'">
|
||||
<template v-else>
|
||||
{{ item.textContent }}
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</span>
|
||||
@@ -37,8 +34,7 @@
|
||||
|
||||
<script>
|
||||
import snarkdown from 'snarkdown'
|
||||
|
||||
const htmlSplitRegexp = /(<a.+?<\/a>|<i>.+?<\/i>|<b>.+?<\/b>|<em>.+?<\/em>|<strong>.+?<\/strong>|<br>)/
|
||||
import { sanitizeUrl } from '@braintree/sanitize-url'
|
||||
|
||||
export default {
|
||||
name: 'MarkdownContent',
|
||||
@@ -47,10 +43,23 @@ export default {
|
||||
type: String,
|
||||
required: false,
|
||||
default: ''
|
||||
},
|
||||
nodes: {
|
||||
type: [Array, Object],
|
||||
require: false,
|
||||
default: null
|
||||
},
|
||||
textOnly: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
items () {
|
||||
safeTags () {
|
||||
return ['UL', 'I', 'EM', 'B', 'STRONG', 'P']
|
||||
},
|
||||
dom () {
|
||||
const linkParts = this.string.split(/(https?:\/\/[^\s)]+)/g)
|
||||
|
||||
const text = linkParts.map((part, index) => {
|
||||
@@ -61,25 +70,11 @@ export default {
|
||||
}
|
||||
}).join('')
|
||||
|
||||
return snarkdown(text.replace(/\n/g, '<br>')).split(htmlSplitRegexp)
|
||||
return new DOMParser().parseFromString(snarkdown(text.replace(/\n/g, '<br>')), 'text/html')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
sanitizeHref (href) {
|
||||
if (href && href.trim().match(/^((?:https?:\/\/)|\/)/)) {
|
||||
return href.replace(/javascript:/g, '')
|
||||
}
|
||||
},
|
||||
extractAttr (text, attr) {
|
||||
if (text.includes(attr)) {
|
||||
return text.split(attr).pop().split('"')[1]
|
||||
}
|
||||
},
|
||||
extractText (text) {
|
||||
if (text) {
|
||||
return text.match(/>(.+?)</)?.[1]
|
||||
}
|
||||
}
|
||||
sanitizeUrl
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -39,8 +39,10 @@
|
||||
:id="field.uuid"
|
||||
v-model="number"
|
||||
type="number"
|
||||
:step="field.validation?.step || 'any'"
|
||||
:min="field.validation?.min"
|
||||
:max="field.validation?.max"
|
||||
class="base-input !text-2xl w-full"
|
||||
step="any"
|
||||
:required="field.required"
|
||||
:placeholder="`${t('type_here_')}${field.required ? '' : ` (${t('optional')})`}`"
|
||||
:name="`values[${field.uuid}]`"
|
||||
|
||||
@@ -72,11 +72,11 @@
|
||||
@blur="onNameBlur"
|
||||
>{{ optionIndexText }} {{ (defaultField ? (defaultField.title || field.title || field.name) : field.name) || defaultName }}</span>
|
||||
<div
|
||||
v-if="isSettingsFocus || (isValueInput && field.type !== 'heading') || (isNameFocus && !['checkbox', 'phone'].includes(field.type))"
|
||||
v-if="isSettingsFocus || isSelectInput || (isValueInput && field.type !== 'heading') || (isNameFocus && !['checkbox', 'phone'].includes(field.type))"
|
||||
class="flex items-center ml-1.5"
|
||||
>
|
||||
<input
|
||||
v-if="!isValueInput"
|
||||
v-if="!isValueInput && !isSelectInput"
|
||||
:id="`required-checkbox-${field.uuid}`"
|
||||
v-model="field.required"
|
||||
type="checkbox"
|
||||
@@ -84,14 +84,14 @@
|
||||
@mousedown.prevent
|
||||
>
|
||||
<label
|
||||
v-if="!isValueInput"
|
||||
v-if="!isValueInput && !isSelectInput"
|
||||
:for="`required-checkbox-${field.uuid}`"
|
||||
class="label text-xs"
|
||||
@click.prevent="field.required = !field.required"
|
||||
@mousedown.prevent
|
||||
>{{ t('required') }}</label>
|
||||
<input
|
||||
v-if="isValueInput"
|
||||
v-if="isValueInput || isSelectInput"
|
||||
:id="`readonly-checkbox-${field.uuid}`"
|
||||
type="checkbox"
|
||||
class="checkbox checkbox-xs no-animation rounded"
|
||||
@@ -100,7 +100,7 @@
|
||||
@mousedown.prevent
|
||||
>
|
||||
<label
|
||||
v-if="isValueInput"
|
||||
v-if="isValueInput || isSelectInput"
|
||||
:for="`readonly-checkbox-${field.uuid}`"
|
||||
class="label text-xs"
|
||||
@click.prevent="field.readonly = !(field.readonly ?? true)"
|
||||
@@ -164,30 +164,39 @@
|
||||
ref="touchValueTarget"
|
||||
class="flex h-full w-full field-area"
|
||||
dir="auto"
|
||||
:class="[isValueInput ? 'bg-opacity-50' : 'bg-opacity-80', field.type === 'heading' ? 'bg-gray-50' : bgColors[submitterIndex % bgColors.length], isDefaultValuePresent || isValueInput || (withFieldPlaceholder && field.areas) ? fontClasses : 'justify-center items-center']"
|
||||
:class="[isValueInput ? 'cursor-text' : '', isValueInput || isCheckboxInput || isSelectInput ? 'bg-opacity-50' : 'bg-opacity-80', field.type === 'heading' ? 'bg-gray-50' : bgColors[submitterIndex % bgColors.length], isDefaultValuePresent || isValueInput || (withFieldPlaceholder && field.areas) ? fontClasses : 'justify-center items-center']"
|
||||
@click="focusValueInput"
|
||||
>
|
||||
<span
|
||||
v-if="field"
|
||||
class="flex justify-center items-center space-x-1"
|
||||
:class="{ 'w-full': ['cells', 'checkbox'].includes(field.type), 'h-full': !isValueInput && !isDefaultValuePresent }"
|
||||
:class="{ 'w-full': isWFullType, 'h-full': !isValueInput && !isDefaultValuePresent }"
|
||||
>
|
||||
<div
|
||||
v-if="isDefaultValuePresent || isValueInput || (withFieldPlaceholder && field.areas && field.type !== 'checkbox')"
|
||||
:class="{ 'w-full h-full': ['cells', 'checkbox'].includes(field.type) }"
|
||||
v-if="isDefaultValuePresent || isValueInput || isSelectInput || (withFieldPlaceholder && field.areas && field.type !== 'checkbox')"
|
||||
:class="{ 'w-full h-full': isWFullType }"
|
||||
:style="fontStyle"
|
||||
>
|
||||
<div
|
||||
ref="textContainer"
|
||||
class="flex items-center px-0.5"
|
||||
:style="{ color: field.preferences?.color }"
|
||||
:class="{ 'w-full h-full': ['cells', 'checkbox'].includes(field.type) }"
|
||||
:class="{ 'w-full h-full': isWFullType }"
|
||||
>
|
||||
<IconCheck
|
||||
v-if="field.type == 'checkbox'"
|
||||
class="aspect-square mx-auto"
|
||||
:class="{ '!w-auto !h-full': area.w > area.h, '!w-full !h-auto': area.w <= area.h }"
|
||||
/>
|
||||
<template
|
||||
v-else-if="(field.type === 'radio' || field.type === 'multiple') && field?.areas?.length > 1"
|
||||
>
|
||||
<IconCheck
|
||||
v-if="field.type === 'multiple' ? field.default_value.includes(buildAreaOptionValue(area)) : buildAreaOptionValue(area) === field.default_value"
|
||||
class="aspect-square mx-auto"
|
||||
:class="{ '!w-auto !h-full': area.w > area.h, '!w-full !h-auto': area.w <= area.h }"
|
||||
/>
|
||||
</template>
|
||||
<span
|
||||
v-else-if="field.type === 'number' && !isValueInput && (field.default_value || field.default_value == 0)"
|
||||
class="whitespace-pre-wrap"
|
||||
@@ -210,14 +219,39 @@
|
||||
{{ char }}
|
||||
</div>
|
||||
</div>
|
||||
<select
|
||||
v-else-if="isSelectInput"
|
||||
ref="defaultValueSelect"
|
||||
class="bg-transparent outline-none focus:outline-none w-full"
|
||||
@change="[field.default_value = $event.target.value, field.readonly = !!field.default_value?.length, save()]"
|
||||
@focus="selectedAreaRef.value = area"
|
||||
@keydown.enter="onDefaultValueEnter"
|
||||
>
|
||||
<option
|
||||
:disabled="!field.default_value?.length"
|
||||
:selected="!field.default_value?.length"
|
||||
:value="''"
|
||||
>
|
||||
{{ t(field.default_value?.length ? 'none' : 'select') }}
|
||||
</option>
|
||||
<option
|
||||
v-for="(option, index) in field.options"
|
||||
:key="index"
|
||||
:selected="field.default_value === option.value"
|
||||
:value="option.value"
|
||||
>
|
||||
{{ option.value }}
|
||||
</option>
|
||||
</select>
|
||||
<span
|
||||
v-else
|
||||
ref="defaultValue"
|
||||
:contenteditable="isValueInput"
|
||||
class="whitespace-pre-wrap outline-none empty:before:content-[attr(placeholder)] before:text-gray-400"
|
||||
class="whitespace-pre-wrap outline-none empty:before:content-[attr(placeholder)] before:text-base-content/30"
|
||||
:class="{ 'cursor-text': isValueInput }"
|
||||
:placeholder="withFieldPlaceholder && !isValueInput ? defaultField?.title || field.title || field.name || defaultName : t('type_value')"
|
||||
:placeholder="withFieldPlaceholder && !isValueInput ? defaultField?.title || field.title || field.name || defaultName : (field.type === 'date' ? field.preferences?.format || t('type_value') : t('type_value'))"
|
||||
@blur="onDefaultValueBlur"
|
||||
@focus="selectedAreaRef.value = area"
|
||||
@paste.prevent="onPaste"
|
||||
@keydown.enter="onDefaultValueEnter"
|
||||
>{{ field.default_value }}</span>
|
||||
@@ -225,7 +259,7 @@
|
||||
</div>
|
||||
<component
|
||||
:is="fieldIcons[field.type]"
|
||||
v-else
|
||||
v-else-if="!isCheckboxInput"
|
||||
width="100%"
|
||||
height="100%"
|
||||
class="max-h-10 opacity-50"
|
||||
@@ -233,12 +267,12 @@
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="!isValueInput"
|
||||
v-if="!isValueInput && !isSelectInput"
|
||||
ref="touchTarget"
|
||||
class="absolute top-0 bottom-0 right-0 left-0"
|
||||
:class="isDragged ? 'cursor-grab' : 'cursor-pointer'"
|
||||
@dblclick="maybeToggleDefaultValue"
|
||||
@click="maybeToggleCheckboxValue"
|
||||
@click="inputMode && maybeToggleCheckboxValue()"
|
||||
/>
|
||||
<span
|
||||
v-if="field?.type && editable"
|
||||
@@ -253,6 +287,7 @@
|
||||
<FormulaModal
|
||||
:field="field"
|
||||
:editable="editable && !defaultField"
|
||||
:default-field="defaultField"
|
||||
:build-default-name="buildDefaultName"
|
||||
@close="isShowFormulaModal = false"
|
||||
/>
|
||||
@@ -264,6 +299,7 @@
|
||||
<FontModal
|
||||
:field="field"
|
||||
:editable="editable && !defaultField"
|
||||
:default-field="defaultField"
|
||||
:build-default-name="buildDefaultName"
|
||||
@close="isShowFontModal = false"
|
||||
/>
|
||||
@@ -275,6 +311,7 @@
|
||||
<ConditionsModal
|
||||
:item="field"
|
||||
:build-default-name="buildDefaultName"
|
||||
:default-field="defaultField"
|
||||
@close="isShowConditionsModal = false"
|
||||
/>
|
||||
</Teleport>
|
||||
@@ -285,6 +322,7 @@
|
||||
<DescriptionModal
|
||||
:field="field"
|
||||
:editable="editable && !defaultField"
|
||||
:default-field="defaultField"
|
||||
:build-default-name="buildDefaultName"
|
||||
@close="isShowDescriptionModal = false"
|
||||
/>
|
||||
@@ -398,6 +436,9 @@ export default {
|
||||
fieldNames: FieldType.computed.fieldNames,
|
||||
fieldLabels: FieldType.computed.fieldLabels,
|
||||
fieldIcons: FieldType.computed.fieldIcons,
|
||||
isWFullType () {
|
||||
return ['cells', 'checkbox', 'radio', 'multiple', 'select'].includes(this.field.type)
|
||||
},
|
||||
fontStyle () {
|
||||
let fontSize = ''
|
||||
|
||||
@@ -417,6 +458,13 @@ export default {
|
||||
|
||||
return { fontSize, lineHeight: `calc(${fontSize} * ${this.lineHeight})` }
|
||||
},
|
||||
optionsUuidIndex () {
|
||||
return this.field.options.reduce((acc, option) => {
|
||||
acc[option.uuid] = option
|
||||
|
||||
return acc
|
||||
}, {})
|
||||
},
|
||||
fontSizePx () {
|
||||
return parseInt(this.field?.preferences?.font_size || 11) * this.fontScale
|
||||
},
|
||||
@@ -427,14 +475,17 @@ export default {
|
||||
return 1040 / 612.0
|
||||
},
|
||||
isDefaultValuePresent () {
|
||||
if (this.field?.type === 'radio' && this.field?.areas?.length > 1) {
|
||||
return false
|
||||
} else {
|
||||
return this.field?.default_value || this.field?.default_value === 0
|
||||
}
|
||||
return this.field?.default_value || this.field?.default_value === 0
|
||||
},
|
||||
isSelectInput () {
|
||||
return this.inputMode && (this.field.type === 'select' || (this.field.type === 'radio' && this.field.areas?.length < 2))
|
||||
},
|
||||
isCheckboxInput () {
|
||||
return this.inputMode && (this.field.type === 'checkbox' || (['radio', 'multiple'].includes(this.field.type) && this.area.option_uuid))
|
||||
},
|
||||
isValueInput () {
|
||||
return (this.field.type === 'heading' && this.isHeadingSelected) || this.isContenteditable || (this.inputMode && ['text', 'number', 'date'].includes(this.field.type))
|
||||
return (this.field.type === 'heading' && this.isHeadingSelected) || this.isContenteditable ||
|
||||
(this.inputMode && (['text', 'number'].includes(this.field.type) || (this.field.type === 'date' && this.field.default_value !== '{{date}}')))
|
||||
},
|
||||
modalContainerEl () {
|
||||
return this.$el.getRootNode().querySelector('#docuseal_modal_container')
|
||||
@@ -549,6 +600,11 @@ export default {
|
||||
closeDropdown () {
|
||||
this.$el.getRootNode().activeElement.blur()
|
||||
},
|
||||
buildAreaOptionValue (area) {
|
||||
const option = this.optionsUuidIndex[area.option_uuid]
|
||||
|
||||
return option.value || `${this.t('option')} ${this.field.options.indexOf(option) + 1}`
|
||||
},
|
||||
maybeToggleDefaultValue () {
|
||||
if (!this.editable) {
|
||||
return
|
||||
@@ -558,22 +614,41 @@ export default {
|
||||
this.isContenteditable = true
|
||||
|
||||
this.focusValueInput()
|
||||
} else if (this.field.type === 'checkbox') {
|
||||
this.field.readonly = !this.field.readonly
|
||||
this.field.default_value === true ? delete this.field.default_value : this.field.default_value = true
|
||||
|
||||
this.save()
|
||||
} else if (this.field.type === 'date') {
|
||||
this.field.readonly = !this.field.readonly
|
||||
this.field.default_value === '{{date}}' ? delete this.field.default_value : this.field.default_value = '{{date}}'
|
||||
|
||||
this.save()
|
||||
} else {
|
||||
this.maybeToggleCheckboxValue()
|
||||
}
|
||||
},
|
||||
maybeToggleCheckboxValue () {
|
||||
if (this.inputMode && this.field.type === 'checkbox') {
|
||||
this.field.readonly = !this.field.readonly
|
||||
if (this.field.type === 'checkbox') {
|
||||
this.field.default_value === true ? delete this.field.default_value : this.field.default_value = true
|
||||
this.field.readonly = this.field.default_value === true
|
||||
|
||||
this.save()
|
||||
} else if (this.field.type === 'radio' && this.area.option_uuid) {
|
||||
const value = this.buildAreaOptionValue(this.area)
|
||||
|
||||
this.field.default_value === value ? delete this.field.default_value : this.field.default_value = value
|
||||
|
||||
this.field.readonly = !!this.field.default_value?.length
|
||||
|
||||
this.save()
|
||||
} else if (this.field.type === 'multiple' && this.area.option_uuid) {
|
||||
const value = this.buildAreaOptionValue(this.area)
|
||||
|
||||
if (this.field.default_value?.includes(value)) {
|
||||
this.field.default_value.splice(this.field.default_value.indexOf(value), 1)
|
||||
|
||||
if (!this.field.default_value?.length) delete this.field.default_value
|
||||
} else {
|
||||
Array.isArray(this.field.default_value) ? this.field.default_value.push(value) : this.field.default_value = [value]
|
||||
}
|
||||
|
||||
this.field.readonly = !!this.field.default_value?.length
|
||||
|
||||
this.save()
|
||||
}
|
||||
@@ -749,7 +824,7 @@ export default {
|
||||
}
|
||||
},
|
||||
drag (e) {
|
||||
if (e.target.id === 'mask') {
|
||||
if (e.target.id === 'mask' && this.editable) {
|
||||
this.isDragged = true
|
||||
|
||||
this.area.x = (e.offsetX - this.dragFrom.x) / e.target.clientWidth
|
||||
@@ -765,7 +840,9 @@ export default {
|
||||
|
||||
e.preventDefault()
|
||||
|
||||
this.isDragged = true
|
||||
if (this.editable) {
|
||||
this.isDragged = true
|
||||
}
|
||||
|
||||
const rect = e.target.getBoundingClientRect()
|
||||
|
||||
@@ -818,7 +895,9 @@ export default {
|
||||
|
||||
e.preventDefault()
|
||||
|
||||
this.isDragged = true
|
||||
if (this.editable) {
|
||||
this.isDragged = true
|
||||
}
|
||||
|
||||
const rect = e.target.getBoundingClientRect()
|
||||
|
||||
|
||||
@@ -660,7 +660,7 @@ export default {
|
||||
acceptFileTypes: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'image/*, application/pdf'
|
||||
default: 'image/*, application/pdf, application/zip'
|
||||
},
|
||||
baseUrl: {
|
||||
type: String,
|
||||
@@ -1065,7 +1065,7 @@ export default {
|
||||
}
|
||||
|
||||
if (['select', 'multiple', 'radio'].includes(type)) {
|
||||
field.options = [{ value: '', uuid: v4() }]
|
||||
field.options = [{ value: '', uuid: v4() }, { value: '', uuid: v4() }]
|
||||
}
|
||||
|
||||
if (type === 'stamp') {
|
||||
@@ -1109,7 +1109,7 @@ export default {
|
||||
}
|
||||
|
||||
if (['select', 'multiple', 'radio'].includes(type)) {
|
||||
field.options = [{ value: '', uuid: v4() }]
|
||||
field.options = [{ value: '', uuid: v4() }, { value: '', uuid: v4() }]
|
||||
}
|
||||
|
||||
if (type === 'stamp') {
|
||||
@@ -1265,24 +1265,31 @@ export default {
|
||||
if (!field.areas.length) {
|
||||
this.template.fields.splice(this.template.fields.indexOf(field), 1)
|
||||
|
||||
this.template.fields.forEach((f) => {
|
||||
(f.conditions || []).forEach((c) => {
|
||||
this.removeFieldConditions(field)
|
||||
}
|
||||
|
||||
this.save()
|
||||
},
|
||||
removeFieldConditions (field) {
|
||||
this.template.fields.forEach((f) => {
|
||||
if (f.conditions) {
|
||||
f.conditions.forEach((c) => {
|
||||
if (c.field_uuid === field.uuid) {
|
||||
f.conditions.splice(f.conditions.indexOf(c), 1)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
this.template.schema.forEach((item) => {
|
||||
(item.conditions || []).forEach((c) => {
|
||||
this.template.schema.forEach((item) => {
|
||||
if (item.conditions) {
|
||||
item.conditions.forEach((c) => {
|
||||
if (c.field_uuid === field.uuid) {
|
||||
item.conditions.splice(item.conditions.indexOf(c), 1)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
this.save()
|
||||
}
|
||||
})
|
||||
},
|
||||
pasteField () {
|
||||
const field = this.template.fields.find((f) => f.areas?.includes(this.copiedArea))
|
||||
@@ -1301,7 +1308,13 @@ export default {
|
||||
this.copiedArea.option_uuid ||= field.options[0].uuid
|
||||
area.option_uuid = v4()
|
||||
|
||||
field.options.push({ uuid: area.option_uuid })
|
||||
const lastOption = field.options[field.options.length - 1]
|
||||
|
||||
if (!field.areas.find((a) => lastOption.uuid === a.option_uuid)) {
|
||||
area.option_uuid = lastOption.uuid
|
||||
} else {
|
||||
field.options.push({ uuid: area.option_uuid })
|
||||
}
|
||||
|
||||
field.areas.push(area)
|
||||
} else {
|
||||
@@ -1477,7 +1490,7 @@ export default {
|
||||
if (this.dragField?.options?.length) {
|
||||
field.options = this.dragField.options.map(option => ({ value: option, uuid: v4() }))
|
||||
} else {
|
||||
field.options = [{ value: '', uuid: v4() }]
|
||||
field.options = [{ value: '', uuid: v4() }, { value: '', uuid: v4() }]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1709,8 +1722,15 @@ export default {
|
||||
})
|
||||
})
|
||||
|
||||
this.template.fields =
|
||||
this.template.fields.filter((f) => !removedFieldUuids.includes(f.uuid) || f.areas?.length)
|
||||
this.template.fields = this.template.fields.reduce((acc, f) => {
|
||||
if (removedFieldUuids.includes(f.uuid) && !f.areas?.length) {
|
||||
this.removeFieldConditions(f)
|
||||
} else {
|
||||
acc.push(f)
|
||||
}
|
||||
|
||||
return acc
|
||||
}, [])
|
||||
|
||||
this.save()
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="modal-box pt-4 pb-6 px-6 mt-20 max-h-none w-full max-w-xl">
|
||||
<div class="flex justify-between items-center border-b pb-2 mb-2 font-medium">
|
||||
<span class="modal-title">
|
||||
{{ t('condition') }} - {{ item.name || buildDefaultName(item, template.fields) }}
|
||||
{{ t('condition') }} - {{ (defaultField ? (defaultField.title || item.title || item.name) : item.name) || buildDefaultName(item, template.fields) }}
|
||||
</span>
|
||||
<a
|
||||
href="#"
|
||||
@@ -160,6 +160,11 @@ export default {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
defaultField: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
buildDefaultName: {
|
||||
type: Function,
|
||||
required: true
|
||||
|
||||
@@ -66,7 +66,7 @@ export default {
|
||||
acceptFileTypes: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'image/*, application/pdf'
|
||||
default: 'image/*, application/pdf, application/zip'
|
||||
},
|
||||
withReplaceButton: {
|
||||
type: Boolean,
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="modal-box pt-4 pb-6 px-6 mt-20 max-h-none w-full max-w-xl">
|
||||
<div class="flex justify-between items-center border-b pb-2 mb-2 font-medium">
|
||||
<span class="modal-title">
|
||||
{{ field.name || buildDefaultName(field, template.fields) }}
|
||||
{{ (defaultField ? (defaultField.title || field.title || field.name) : field.name) || buildDefaultName(field, template.fields) }}
|
||||
</span>
|
||||
<a
|
||||
href="#"
|
||||
@@ -73,6 +73,11 @@ export default {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
defaultField: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
editable: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
|
||||
@@ -107,7 +107,7 @@ export default {
|
||||
acceptFileTypes: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'image/*, application/pdf'
|
||||
default: 'image/*, application/pdf, application/zip'
|
||||
}
|
||||
},
|
||||
emits: ['success', 'error', 'loading'],
|
||||
@@ -131,7 +131,7 @@ export default {
|
||||
message () {
|
||||
if (this.isLoading) {
|
||||
return this.t('uploading')
|
||||
} else if (this.acceptFileTypes === 'image/*, application/pdf') {
|
||||
} else if (this.acceptFileTypes === 'image/*, application/pdf, application/zip') {
|
||||
return this.title || this.t('add_pdf_documents_or_images')
|
||||
} else {
|
||||
return this.title || this.t('add_documents_or_images')
|
||||
@@ -146,7 +146,7 @@ export default {
|
||||
methods: {
|
||||
upload: Upload.methods.upload,
|
||||
onDropFiles (e) {
|
||||
if (this.acceptFileTypes !== 'image/*, application/pdf' || [...e.dataTransfer.files].every((f) => f.type.match(/(?:image\/)|(?:application\/pdf)/))) {
|
||||
if (this.acceptFileTypes !== 'image/*, application/pdf, application/zip' || [...e.dataTransfer.files].every((f) => f.type.match(/(?:image\/)|(?:application\/pdf)|(?:application\/zip)/))) {
|
||||
this.$refs.input.files = e.dataTransfer.files
|
||||
|
||||
this.upload()
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="field.options && withOptions"
|
||||
v-if="field.options && withOptions && (isExpandOptions || field.options.length < 5)"
|
||||
ref="options"
|
||||
class="border-t border-base-300 mx-2 pt-2 space-y-1.5"
|
||||
draggable="true"
|
||||
@@ -216,12 +216,30 @@
|
||||
/>
|
||||
<button
|
||||
v-else-if="field.options && editable && !defaultField"
|
||||
class="text-center text-sm w-full pb-1"
|
||||
class="field-add-option text-center text-sm w-full pb-1"
|
||||
@click="addOption"
|
||||
>
|
||||
+ {{ t('add_option') }}
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="field.options && withOptions && !isExpandOptions && field.options.length > 4"
|
||||
class="border-t border-base-300 mx-2 space-y-1.5"
|
||||
>
|
||||
<button
|
||||
class="field-expand-options text-center text-sm w-full py-1 flex space-x-0.5 justify-center items-center"
|
||||
@click="isExpandOptions = true"
|
||||
>
|
||||
<span class="lowercase">
|
||||
{{ field.options.length }} {{ t('options') }}
|
||||
</span>
|
||||
<IconChevronDown
|
||||
class="ml-2 mr-2 mt-0.5"
|
||||
width="15"
|
||||
height="15"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<Teleport
|
||||
v-if="isShowFormulaModal"
|
||||
@@ -230,6 +248,7 @@
|
||||
<FormulaModal
|
||||
:field="field"
|
||||
:editable="editable && !defaultField"
|
||||
:default-field="defaultField"
|
||||
:build-default-name="buildDefaultName"
|
||||
@close="isShowFormulaModal = false"
|
||||
/>
|
||||
@@ -241,6 +260,7 @@
|
||||
<FontModal
|
||||
:field="field"
|
||||
:editable="editable && !defaultField"
|
||||
:default-field="defaultField"
|
||||
:build-default-name="buildDefaultName"
|
||||
@close="isShowFontModal = false"
|
||||
/>
|
||||
@@ -251,6 +271,7 @@
|
||||
>
|
||||
<ConditionsModal
|
||||
:item="field"
|
||||
:default-field="defaultField"
|
||||
:build-default-name="buildDefaultName"
|
||||
@close="isShowConditionsModal = false"
|
||||
/>
|
||||
@@ -262,6 +283,7 @@
|
||||
<DescriptionModal
|
||||
:field="field"
|
||||
:editable="editable && !defaultField"
|
||||
:default-field="defaultField"
|
||||
:build-default-name="buildDefaultName"
|
||||
@close="isShowDescriptionModal = false"
|
||||
/>
|
||||
@@ -278,7 +300,7 @@ import FormulaModal from './formula_modal'
|
||||
import FontModal from './font_modal'
|
||||
import ConditionsModal from './conditions_modal'
|
||||
import DescriptionModal from './description_modal'
|
||||
import { IconRouteAltLeft, IconMathFunction, IconNewSection, IconTrashX, IconSettings } from '@tabler/icons-vue'
|
||||
import { IconRouteAltLeft, IconMathFunction, IconNewSection, IconTrashX, IconSettings, IconChevronDown } from '@tabler/icons-vue'
|
||||
import { v4 } from 'uuid'
|
||||
|
||||
export default {
|
||||
@@ -288,6 +310,7 @@ export default {
|
||||
IconSettings,
|
||||
FieldSettings,
|
||||
PaymentSettings,
|
||||
IconChevronDown,
|
||||
IconNewSection,
|
||||
FormulaModal,
|
||||
FontModal,
|
||||
@@ -333,6 +356,7 @@ export default {
|
||||
emits: ['set-draw', 'remove', 'scroll-to'],
|
||||
data () {
|
||||
return {
|
||||
isExpandOptions: false,
|
||||
isNameFocus: false,
|
||||
showPaymentModal: false,
|
||||
isShowFormulaModal: false,
|
||||
@@ -427,6 +451,8 @@ export default {
|
||||
this.$el.getRootNode().activeElement.blur()
|
||||
},
|
||||
addOption () {
|
||||
this.isExpandOptions = true
|
||||
|
||||
this.field.options.push({ value: '', uuid: v4() })
|
||||
|
||||
this.$nextTick(() => {
|
||||
|
||||
@@ -1,31 +1,4 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="field.type === 'number'"
|
||||
class="py-1.5 px-1 relative"
|
||||
@click.stop
|
||||
>
|
||||
<select
|
||||
:placeholder="t('format')"
|
||||
class="select select-bordered select-xs font-normal w-full max-w-xs !h-7 !outline-0 bg-transparent"
|
||||
@change="[field.preferences ||= {}, field.preferences.format = $event.target.value, save()]"
|
||||
>
|
||||
<option
|
||||
v-for="format in numberFormats"
|
||||
:key="format"
|
||||
:value="format"
|
||||
:selected="format === field.preferences?.format || (format === 'none' && !field.preferences?.format)"
|
||||
>
|
||||
{{ formatNumber(123456789.567, format) }}
|
||||
</option>
|
||||
</select>
|
||||
<label
|
||||
:style="{ backgroundColor }"
|
||||
class="absolute -top-1 left-2.5 px-1 h-4"
|
||||
style="font-size: 8px"
|
||||
>
|
||||
{{ t('format') }}
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
v-if="field.type === 'verification'"
|
||||
class="py-1.5 px-1 relative"
|
||||
@@ -217,6 +190,77 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="field.type === 'number'"
|
||||
class="py-1.5 px-1 relative flex space-x-1"
|
||||
@click.stop
|
||||
>
|
||||
<div class="w-1/2 relative">
|
||||
<input
|
||||
:placeholder="t('min')"
|
||||
type="number"
|
||||
min="0"
|
||||
:value="field.validation?.min"
|
||||
class="input input-bordered w-full input-xs h-7 !outline-0 bg-transparent"
|
||||
@input="[field.validation ||= {}, $event.target.value ? field.validation.min = $event.target.value : delete field.validation.min]"
|
||||
@blur="save"
|
||||
>
|
||||
<label
|
||||
v-if="field.validation?.min"
|
||||
:style="{ backgroundColor }"
|
||||
class="absolute -top-2.5 left-1.5 px-1 h-4"
|
||||
style="font-size: 8px"
|
||||
>
|
||||
{{ t('min') }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="w-1/2 relative">
|
||||
<input
|
||||
:placeholder="t('max')"
|
||||
type="number"
|
||||
min="1"
|
||||
class="input input-bordered w-full input-xs h-7 !outline-0 bg-transparent"
|
||||
:value="field.validation?.max"
|
||||
@input="[field.validation ||= {}, $event.target.value ? field.validation.max = $event.target.value : delete field.validation.max]"
|
||||
@blur="save"
|
||||
>
|
||||
<label
|
||||
v-if="field.validation?.max"
|
||||
:style="{ backgroundColor }"
|
||||
class="absolute -top-2.5 left-1.5 px-1 h-4"
|
||||
style="font-size: 8px"
|
||||
>
|
||||
{{ t('max') }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="field.type === 'number'"
|
||||
class="py-1.5 px-1 relative"
|
||||
@click.stop
|
||||
>
|
||||
<select
|
||||
:placeholder="t('format')"
|
||||
class="select select-bordered select-xs font-normal w-full max-w-xs !h-7 !outline-0 bg-transparent"
|
||||
@change="[field.preferences ||= {}, field.preferences.format = $event.target.value, save()]"
|
||||
>
|
||||
<option
|
||||
v-for="format in numberFormats"
|
||||
:key="format"
|
||||
:value="format"
|
||||
:selected="format === field.preferences?.format || (format === 'none' && !field.preferences?.format)"
|
||||
>
|
||||
{{ formatNumber(123456789.567, format) }}
|
||||
</option>
|
||||
</select>
|
||||
<label
|
||||
:style="{ backgroundColor }"
|
||||
class="absolute -top-1 left-2.5 px-1 h-4"
|
||||
style="font-size: 8px"
|
||||
>
|
||||
{{ t('format') }}
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
v-if="['text', 'cells'].includes(field.type) && field.validation && !validations[field.validation.pattern] && !lengthValidation"
|
||||
class="py-1.5 px-1 relative"
|
||||
@@ -393,7 +437,7 @@
|
||||
</label>
|
||||
</li>
|
||||
<li
|
||||
v-if="['text', 'number'].includes(field.type) && !defaultField"
|
||||
v-if="['text', 'number'].includes(field.type)"
|
||||
@click.stop
|
||||
>
|
||||
<label class="cursor-pointer py-1.5">
|
||||
@@ -401,6 +445,7 @@
|
||||
v-model="field.readonly"
|
||||
type="checkbox"
|
||||
class="toggle toggle-xs"
|
||||
:disabled="!editable || (defaultField && [true, false].includes(defaultField.readonly))"
|
||||
@update:model-value="save"
|
||||
>
|
||||
<span class="label-text">{{ t('read_only') }}</span>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="modal-box pt-4 pb-6 px-6 mt-20 max-h-none w-full max-w-xl">
|
||||
<div class="flex justify-between items-center border-b pb-2 mb-2 font-medium">
|
||||
<span class="modal-title">
|
||||
{{ t('font') }} - {{ field.name || buildDefaultName(field, template.fields) }}
|
||||
{{ t('font') }} - {{ (defaultField ? (defaultField.title || field.title || field.name) : field.name) || buildDefaultName(field, template.fields) }}
|
||||
</span>
|
||||
<a
|
||||
href="#"
|
||||
@@ -202,6 +202,11 @@ export default {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
defaultField: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
editable: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="modal-box pt-4 pb-6 px-6 mt-20 max-h-none w-full max-w-xl">
|
||||
<div class="flex justify-between items-center border-b pb-2 mb-2 font-medium">
|
||||
<span class="modal-title">
|
||||
{{ t('formula') }} - {{ field.name || buildDefaultName(field, template.fields) }}
|
||||
{{ t('formula') }} - {{ (defaultField ? (defaultField.title || field.title || field.name) : field.name) || buildDefaultName(field, template.fields) }}
|
||||
</span>
|
||||
<a
|
||||
href="#"
|
||||
@@ -28,14 +28,21 @@
|
||||
class="link"
|
||||
>{{ t('available_in_pro') }}</a>
|
||||
</div>
|
||||
<div class="flex-inline mb-2 gap-2 space-y-1">
|
||||
<div class="flex flex-wrap mb-2 gap-y-1 pt-1">
|
||||
<button
|
||||
v-for="f in fields"
|
||||
:key="f.uuid"
|
||||
class="mr-1 btn btn-neutral btn-outline border-base-content/20 btn-sm normal-case font-normal bg-white !rounded-xl"
|
||||
class="mr-1 flex btn btn-neutral btn-outline border-base-content/20 btn-sm normal-case font-normal bg-white !rounded-xl"
|
||||
@click.prevent="insertTextUnderCursor(`{{${f.name || buildDefaultName(f, template.fields)}}}`)"
|
||||
>
|
||||
<IconMathFunction
|
||||
v-if="f.preferences?.formula"
|
||||
width="17"
|
||||
height="17"
|
||||
stroke-width="1.5"
|
||||
/>
|
||||
<IconCodePlus
|
||||
v-else
|
||||
width="20"
|
||||
height="20"
|
||||
stroke-width="1.5"
|
||||
@@ -57,7 +64,7 @@
|
||||
<div class="mb-3 mt-1">
|
||||
<div
|
||||
target="blank"
|
||||
class="text-sm mb-2 inline space-x-2"
|
||||
class="text-sm mb-2 inline space-x-2 font-mono"
|
||||
>
|
||||
<button
|
||||
class="bg-base-200 px-2 rounded-xl"
|
||||
@@ -83,12 +90,6 @@
|
||||
>
|
||||
/
|
||||
</button>
|
||||
<button
|
||||
class="bg-base-200 px-2 rounded-xl"
|
||||
@click="insertTextUnderCursor(' % ')"
|
||||
>
|
||||
%
|
||||
</button>
|
||||
<button
|
||||
class="bg-base-200 px-2 rounded-xl"
|
||||
@click="insertTextUnderCursor('^')"
|
||||
@@ -122,12 +123,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IconCodePlus } from '@tabler/icons-vue'
|
||||
import { IconCodePlus, IconMathFunction } from '@tabler/icons-vue'
|
||||
|
||||
export default {
|
||||
name: 'FormulaModal',
|
||||
components: {
|
||||
IconCodePlus
|
||||
IconCodePlus,
|
||||
IconMathFunction
|
||||
},
|
||||
inject: ['t', 'save', 'template', 'withFormula'],
|
||||
props: {
|
||||
@@ -135,6 +137,11 @@ export default {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
defaultField: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
editable: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
@@ -154,7 +161,7 @@ export default {
|
||||
computed: {
|
||||
fields () {
|
||||
return this.template.fields.reduce((acc, f) => {
|
||||
if (f !== this.field && ['number'].includes(f.type) && (!f.preferences?.formula || f.submitter_uuid !== this.field.submitter_uuid)) {
|
||||
if (f !== this.field && ['number'].includes(f.type) && (!f.preferences?.formula || !f.preferences.formula.includes(this.field.uuid))) {
|
||||
acc.push(f)
|
||||
}
|
||||
|
||||
@@ -224,9 +231,11 @@ export default {
|
||||
|
||||
this.formula = newText
|
||||
|
||||
textarea.setSelectionRange(cursorPos + textToInsert.length, cursorPos + textToInsert.length)
|
||||
this.$nextTick(() => {
|
||||
textarea.setSelectionRange(cursorPos + textToInsert.length, cursorPos + textToInsert.length)
|
||||
|
||||
textarea.focus()
|
||||
textarea.focus()
|
||||
})
|
||||
},
|
||||
resizeTextarea () {
|
||||
const textarea = this.$refs.textarea
|
||||
|
||||
@@ -78,7 +78,7 @@ export default {
|
||||
acceptFileTypes: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'image/*, application/pdf'
|
||||
default: 'image/*, application/pdf, application/zip'
|
||||
}
|
||||
},
|
||||
emits: ['add', 'replace', 'replace-and-clone', 'error'],
|
||||
|
||||
@@ -83,6 +83,7 @@ const en = {
|
||||
copy_to_all_pages: 'Copy to All Pages',
|
||||
add_option: 'Add option',
|
||||
option: 'Option',
|
||||
options: 'Options',
|
||||
condition: 'Condition',
|
||||
first_party: 'First Party',
|
||||
second_party: 'Second Party',
|
||||
@@ -255,6 +256,7 @@ const es = {
|
||||
copy_to_all_pages: 'Copiar a todas las páginas',
|
||||
add_option: 'Agregar opción',
|
||||
option: 'Opción',
|
||||
options: 'Opciones',
|
||||
first_party: 'Primera Parte',
|
||||
second_party: 'Segunda Parte',
|
||||
third_party: 'Tercera Parte',
|
||||
@@ -435,6 +437,7 @@ const it = {
|
||||
copy_to_all_pages: 'Copia in tutte le pagine',
|
||||
add_option: 'Aggiungi opzione',
|
||||
option: 'Opzione',
|
||||
options: 'Opzioni',
|
||||
condition: 'Condizione',
|
||||
first_party: 'Prima parte',
|
||||
second_party: 'Seconda parte',
|
||||
@@ -607,6 +610,7 @@ const pt = {
|
||||
copy_to_all_pages: 'Copiar para todas as páginas',
|
||||
add_option: 'Adicionar opção',
|
||||
option: 'Opção',
|
||||
options: 'Opções',
|
||||
first_party: 'Primeira Parte',
|
||||
second_party: 'Segunda Parte',
|
||||
third_party: 'Terceira Parte',
|
||||
@@ -782,6 +786,7 @@ const fr = {
|
||||
copy_to_all_pages: 'Copier sur toutes les pages',
|
||||
add_option: 'Ajouter une option',
|
||||
option: 'Option',
|
||||
options: 'Options',
|
||||
first_party: 'Première partie',
|
||||
second_party: 'Deuxième partie',
|
||||
third_party: 'Troisième partie',
|
||||
@@ -958,6 +963,7 @@ const de = {
|
||||
copy_to_all_pages: 'Auf alle Seiten kopieren',
|
||||
add_option: 'Option hinzufügen',
|
||||
option: 'Option',
|
||||
options: 'Options',
|
||||
first_party: 'Erste Partei',
|
||||
second_party: 'Zweite Partei',
|
||||
third_party: 'Dritte Partei',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
class="relative select-none mb-4 before:border before:rounded before:top-0 before:bottom-0 before:left-0 before:right-0 before:absolute"
|
||||
:class="{ 'cursor-crosshair': allowDraw, 'touch-none': !!drawField }"
|
||||
:class="{ 'cursor-crosshair': allowDraw && editable, 'touch-none': !!drawField }"
|
||||
style="container-type: size"
|
||||
:style="{ aspectRatio: `${width} / ${height}`}"
|
||||
>
|
||||
|
||||
@@ -157,7 +157,7 @@ export default {
|
||||
acceptFileTypes: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'image/*, application/pdf'
|
||||
default: 'image/*, application/pdf, application/zip'
|
||||
},
|
||||
withReplaceButton: {
|
||||
type: Boolean,
|
||||
|
||||
@@ -35,7 +35,7 @@ export default {
|
||||
acceptFileTypes: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'image/*, application/pdf'
|
||||
default: 'image/*, application/pdf, application/zip'
|
||||
}
|
||||
},
|
||||
emits: ['success'],
|
||||
|
||||
@@ -57,7 +57,7 @@ export default {
|
||||
acceptFileTypes: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'image/*, application/pdf'
|
||||
default: 'image/*, application/pdf, application/zip'
|
||||
}
|
||||
},
|
||||
emits: ['success', 'error'],
|
||||
|
||||
@@ -14,10 +14,10 @@ class ProcessSubmitterCompletionJob
|
||||
|
||||
if is_all_completed && submitter.completed_at == submitter.submission.submitters.maximum(:completed_at)
|
||||
if submitter.submission.account.account_configs.exists?(key: AccountConfig::COMBINE_PDF_RESULT_KEY, value: true)
|
||||
Submissions::GenerateCombinedAttachment.call(submitter)
|
||||
Submissions::EnsureCombinedGenerated.call(submitter)
|
||||
end
|
||||
|
||||
Submissions::GenerateAuditTrail.call(submitter.submission)
|
||||
Submissions::EnsureAuditGenerated.call(submitter.submission)
|
||||
|
||||
enqueue_completed_emails(submitter)
|
||||
end
|
||||
@@ -38,12 +38,19 @@ class ProcessSubmitterCompletionJob
|
||||
|
||||
submission = submitter.submission
|
||||
|
||||
complete_verification_events, sms_events =
|
||||
submitter.submission_events.where(event_type: %i[send_sms send_2fa_sms complete_verification])
|
||||
.partition { |e| e.event_type == 'complete_verification' }
|
||||
|
||||
complete_verification_event = complete_verification_events.first
|
||||
|
||||
completed_submitter.assign_attributes(
|
||||
submission_id: submitter.submission_id,
|
||||
account_id: submission.account_id,
|
||||
template_id: submission.template_id,
|
||||
source: submission.source,
|
||||
sms_count: submitter.submission_events.where(event_type: %w[send_sms send_2fa_sms]).count,
|
||||
sms_count: sms_events.sum { |e| e.data['segments'] || 1 },
|
||||
verification_method: complete_verification_event&.data&.dig('method'),
|
||||
completed_at: submitter.completed_at
|
||||
)
|
||||
|
||||
@@ -146,7 +153,8 @@ class ProcessSubmitterCompletionJob
|
||||
current_group_index = submitter_groups.find { |_, group| group.any? { |s| s['uuid'] == submitter.uuid } }&.first
|
||||
|
||||
if submitter_groups[current_group_index + 1] &&
|
||||
submitters_index.values_at(*submitter_groups[current_group_index].pluck('uuid')).all?(&:completed_at?)
|
||||
submitters_index.values_at(*submitter_groups[current_group_index].pluck('uuid'))
|
||||
.compact.all?(&:completed_at?)
|
||||
submitter_groups[current_group_index + 1]
|
||||
end
|
||||
else
|
||||
@@ -159,7 +167,7 @@ class ProcessSubmitterCompletionJob
|
||||
end
|
||||
end
|
||||
|
||||
next_submitters = submitters_index.values_at(*Array.wrap(next_submitter_items).pluck('uuid'))
|
||||
next_submitters = submitters_index.values_at(*Array.wrap(next_submitter_items).pluck('uuid')).compact
|
||||
|
||||
Submitters.send_signature_requests(next_submitters)
|
||||
end
|
||||
|
||||
@@ -38,9 +38,11 @@ class AccountConfig < ApplicationRecord
|
||||
FORM_PREFILL_SIGNATURE_KEY = 'form_prefill_signature'
|
||||
ESIGNING_PREFERENCE_KEY = 'esigning_preference'
|
||||
DOWNLOAD_LINKS_AUTH_KEY = 'download_links_auth'
|
||||
DOWNLOAD_LINKS_EXPIRE_KEY = 'download_links_expire'
|
||||
FORCE_SSO_AUTH_KEY = 'force_sso_auth'
|
||||
FLATTEN_RESULT_PDF_KEY = 'flatten_result_pdf'
|
||||
WITH_SIGNATURE_ID = 'with_signature_id'
|
||||
WITH_FILE_LINKS_KEY = 'with_file_links'
|
||||
WITH_SIGNATURE_ID_REASON_KEY = 'with_signature_id_reason'
|
||||
WITH_AUDIT_VALUES_KEY = 'with_audit_values'
|
||||
WITH_SUBMITTER_TIMEZONE_KEY = 'with_submitter_timezone'
|
||||
|
||||
@@ -4,16 +4,17 @@
|
||||
#
|
||||
# Table name: completed_submitters
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# completed_at :datetime not null
|
||||
# sms_count :integer not null
|
||||
# source :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :bigint not null
|
||||
# submission_id :bigint not null
|
||||
# submitter_id :bigint not null
|
||||
# template_id :bigint
|
||||
# id :bigint not null, primary key
|
||||
# completed_at :datetime not null
|
||||
# sms_count :integer not null
|
||||
# source :string not null
|
||||
# verification_method :string
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :bigint not null
|
||||
# submission_id :bigint not null
|
||||
# submitter_id :bigint not null
|
||||
# template_id :bigint
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
@@ -29,5 +30,5 @@ class CompletedSubmitter < ApplicationRecord
|
||||
has_many :completed_documents, dependent: :destroy,
|
||||
primary_key: :submitter_id,
|
||||
foreign_key: :submitter_id,
|
||||
inverse_of: :submitter
|
||||
inverse_of: :completed_submitter
|
||||
end
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: lock_events
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# event_name :string not null
|
||||
# key :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_lock_events_on_event_name_and_key (event_name,key) UNIQUE WHERE ((event_name)::text = ANY ((ARRAY['start'::character varying, 'complete'::character varying])::text[]))
|
||||
# index_lock_events_on_key (key)
|
||||
#
|
||||
class LockEvent < ApplicationRecord
|
||||
enum :event_name, {
|
||||
complete: 'complete',
|
||||
fail: 'fail',
|
||||
start: 'start',
|
||||
retry: 'retry'
|
||||
}, scope: false
|
||||
end
|
||||
@@ -15,6 +15,8 @@
|
||||
# template_fields :text
|
||||
# template_schema :text
|
||||
# template_submitters :text
|
||||
# variables :text
|
||||
# variables_schema :text
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :bigint not null
|
||||
@@ -50,6 +52,8 @@ class Submission < ApplicationRecord
|
||||
serialize :template_fields, coder: JSON
|
||||
serialize :template_schema, coder: JSON
|
||||
serialize :template_submitters, coder: JSON
|
||||
serialize :variables_schema, coder: JSON
|
||||
serialize :variables, coder: JSON
|
||||
serialize :preferences, coder: JSON
|
||||
|
||||
attribute :source, :string, default: 'link'
|
||||
@@ -114,16 +118,16 @@ class Submission < ApplicationRecord
|
||||
@fields_uuid_index ||= (template_fields || template.fields).index_by { |f| f['uuid'] }
|
||||
end
|
||||
|
||||
def audit_trail_url
|
||||
def audit_trail_url(expires_at: nil)
|
||||
return if audit_trail.blank?
|
||||
|
||||
ActiveStorage::Blob.proxy_url(audit_trail.blob)
|
||||
ActiveStorage::Blob.proxy_url(audit_trail.blob, expires_at:)
|
||||
end
|
||||
alias audit_log_url audit_trail_url
|
||||
|
||||
def combined_document_url
|
||||
def combined_document_url(expires_at: nil)
|
||||
return if combined_document.blank?
|
||||
|
||||
ActiveStorage::Blob.proxy_url(combined_document.blob)
|
||||
ActiveStorage::Blob.proxy_url(combined_document.blob, expires_at:)
|
||||
end
|
||||
end
|
||||
|
||||
+18
-16
@@ -4,22 +4,23 @@
|
||||
#
|
||||
# Table name: templates
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# archived_at :datetime
|
||||
# fields :text not null
|
||||
# name :string not null
|
||||
# preferences :text not null
|
||||
# schema :text not null
|
||||
# shared_link :boolean default(FALSE), not null
|
||||
# slug :string not null
|
||||
# source :text not null
|
||||
# submitters :text not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :bigint not null
|
||||
# author_id :bigint not null
|
||||
# external_id :string
|
||||
# folder_id :bigint not null
|
||||
# id :bigint not null, primary key
|
||||
# archived_at :datetime
|
||||
# fields :text not null
|
||||
# name :string not null
|
||||
# preferences :text not null
|
||||
# schema :text not null
|
||||
# shared_link :boolean default(FALSE), not null
|
||||
# slug :string not null
|
||||
# source :text not null
|
||||
# submitters :text not null
|
||||
# variables_schema :text
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :bigint not null
|
||||
# author_id :bigint not null
|
||||
# external_id :string
|
||||
# folder_id :bigint not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
@@ -57,6 +58,7 @@ class Template < ApplicationRecord
|
||||
|
||||
serialize :preferences, coder: JSON
|
||||
serialize :fields, coder: JSON
|
||||
serialize :variables_schema, coder: JSON
|
||||
serialize :schema, coder: JSON
|
||||
serialize :submitters, coder: JSON
|
||||
|
||||
|
||||
@@ -130,6 +130,18 @@
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% account_config = AccountConfig.find_or_initialize_by(account: current_account, key: AccountConfig::DOWNLOAD_LINKS_EXPIRE_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 py-2.5">
|
||||
<span>
|
||||
<%= t('expirable_file_download_links') %>
|
||||
</span>
|
||||
<%= f.check_box :value, class: 'toggle', checked: account_config.value != false, onchange: 'this.form.requestSubmit()' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% account_config = AccountConfig.find_or_initialize_by(account: current_account, key: AccountConfig::DOWNLOAD_LINKS_AUTH_KEY) %>
|
||||
<% if can?(:manage, account_config) %>
|
||||
<%= form_for account_config, url: account_configs_path, method: :post do |f| %>
|
||||
|
||||
@@ -11,10 +11,21 @@
|
||||
<div class="flex flex-col md:flex-row gap-4">
|
||||
<div class="flex w-full space-x-4">
|
||||
<% token = current_user.access_token.token %>
|
||||
<masked-input class="block w-full" data-token="<%= token %>">
|
||||
<input id="api_key" type="text" value="<%= token.sub(token[5..], '*' * token[5..].size) %>" class="input font-mono input-bordered w-full" autocomplete="off" readonly>
|
||||
</masked-input>
|
||||
<%= render 'shared/clipboard_copy', icon: 'copy', text: token, class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: t('copy'), copied_title: t('copied') %>
|
||||
<% obscured_token = current_user.access_token.token.sub(token[5..], '*' * token[5..].size) %>
|
||||
<% if current_account.testing? %>
|
||||
<masked-input class="block w-full" data-token="<%= token %>">
|
||||
<input id="api_key" type="text" value="<%= obscured_token %>" class="input font-mono input-bordered w-full" autocomplete="off" readonly>
|
||||
</masked-input>
|
||||
<%= render 'shared/clipboard_copy', icon: 'copy', text: token, class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: t('copy'), copied_title: t('copied') %>
|
||||
<% else %>
|
||||
<a id="access_token_container" href="<%= settings_reveal_access_token_path %>" data-turbo-frame="modal" class="flex w-full space-x-4">
|
||||
<input id="api_key" type="text" value="<%= obscured_token %>" class="input font-mono input-bordered w-full" autocomplete="off" readonly>
|
||||
<div class="base-button">
|
||||
<%= svg_icon('copy', class: 'w-6 h-6 text-white') %>
|
||||
<span class="hidden md:inline"><%= t('copy') %></span>
|
||||
</div>
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
<%= button_to button_title(title: t('rotate'), disabled_with: t('rotate'), icon: svg_icon('reload', class: 'w-6 h-6')), settings_api_index_path, class: 'white-button w-full', data: { turbo_confirm: t('remove_existing_api_token_and_generated_a_new_one_are_you_sure_') } %>
|
||||
</div>
|
||||
|
||||
@@ -2,15 +2,22 @@
|
||||
<h1 class="text-4xl font-bold text-center mt-8">
|
||||
<%= t('sign_in') %>
|
||||
</h1>
|
||||
<%= form_for(resource, as: resource_name, html: { class: 'space-y-6' }, data: { turbo: params[:redir].blank? }, url: session_path(resource_name)) do |f| %>
|
||||
<%= f.hidden_field :email %>
|
||||
<%= f.hidden_field :password %>
|
||||
<% if params[:redir].present? %>
|
||||
<%= hidden_field_tag :redir, params[:redir] %>
|
||||
<% end %>
|
||||
<%= render 'otp_form', **local_assigns %>
|
||||
<div class="form-control">
|
||||
<%= f.button button_title(title: t('sign_in'), disabled_with: t('signing_in')), class: 'base-button' %>
|
||||
<% if local_assigns[:access_error].present? %>
|
||||
<div class="alert mt-6">
|
||||
<%= svg_icon('x_circle', class: 'w-6 h-6 text-red-500') %>
|
||||
<span><%= local_assigns[:access_error] %></span>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= form_for(resource, as: resource_name, html: { class: 'space-y-6' }, data: { turbo: params[:redir].blank? }, url: session_path(resource_name)) do |f| %>
|
||||
<%= f.hidden_field :email %>
|
||||
<%= f.hidden_field :password %>
|
||||
<% if params[:redir].present? %>
|
||||
<%= hidden_field_tag :redir, params[:redir] %>
|
||||
<% end %>
|
||||
<%= render 'otp_form', **local_assigns %>
|
||||
<div class="form-control">
|
||||
<%= f.button button_title(title: t('sign_in'), disabled_with: t('signing_in')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -54,19 +54,29 @@
|
||||
<p class="text-2xl font-bold mt-8 mb-4">
|
||||
<%= t('change_password') %>
|
||||
</p>
|
||||
<%= form_for current_user, url: update_password_settings_profile_index_path, method: :patch, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
||||
<div class="form-control">
|
||||
<%= f.label :password, t('new_password'), class: 'label' %>
|
||||
<%= f.password_field :password, autocomplete: 'off', class: 'base-input' %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.label :password_confirmation, t('confirm_password'), class: 'label' %>
|
||||
<%= f.password_field :password_confirmation, autocomplete: 'off', class: 'base-input' %>
|
||||
</div>
|
||||
<div class="form-control pt-2">
|
||||
<%= f.button button_title(title: t('update'), disabled_with: t('updating')), class: 'base-button' %>
|
||||
<%= form_for current_user, url: update_password_settings_profile_index_path, method: :patch, html: { autocomplete: 'off' } do |f| %>
|
||||
<%= f.label :password, t('new_password'), class: 'label' %>
|
||||
<%= f.password_field :password, autocomplete: 'off', class: 'base-input peer w-full', required: true %>
|
||||
<div class="<%= 'peer-invalid:hidden' if current_user.errors.blank? %> space-y-4 mt-4">
|
||||
<div class="form-control">
|
||||
<%= f.label :password_confirmation, t('confirm_password'), class: 'label' %>
|
||||
<%= f.password_field :password_confirmation, autocomplete: 'off', class: 'base-input' %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.label :current_password, t('current_password'), class: 'label' %>
|
||||
<%= f.password_field :current_password, autocomplete: 'current-password', class: 'base-input' %>
|
||||
<% if Accounts.can_send_emails?(current_account) %>
|
||||
<span class="label-text-alt mt-1">
|
||||
<%= t('dont_remember_your_current_password_click_here_to_reset_it_html') %>
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.button button_title(title: t('update'), disabled_with: t('updating')), class: 'base-button' %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= button_to nil, user_send_reset_password_path(current_user), id: 'resend_password_button', method: :put, class: 'hidden', data: { turbo_confirm: t('are_you_sure_') } %>
|
||||
<p class="text-2xl font-bold mt-8 mb-4">
|
||||
<%= t('two_factor_authentication') %>
|
||||
</p>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"scope": "/",
|
||||
"orientation": "natural",
|
||||
"orientation": "any",
|
||||
"description": "<%= Docuseal.product_name %> is an open source platform that provides secure and efficient digital document signing and processing.",
|
||||
"categories": ["productivity", "utilities"],
|
||||
"theme_color": "#FAF7F4",
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
<input id="api_key" type="text" value="<%= token %>" class="input font-mono input-bordered w-full" autocomplete="off" readonly>
|
||||
<%= render 'shared/clipboard_copy', icon: 'copy', text: token, class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: t('copy'), copied_title: t('copied') %>
|
||||
@@ -0,0 +1,14 @@
|
||||
<%= render 'shared/turbo_modal', title: t('reveal_api_key') do %>
|
||||
<%= form_tag settings_reveal_access_token_path, enctype: 'multipart/form-data', data: { turbo_frame: :_top } do %>
|
||||
<div class="form-control">
|
||||
<%= label_tag :password, t('enter_your_password_to_reveal_the_api_key'), class: 'label' %>
|
||||
<%= password_field_tag :password, nil, class: 'base-input', autocomplete: 'current-password', required: true, autofocus: true, placeholder: t('password') %>
|
||||
<% if local_assigns[:error_message].present? %>
|
||||
<span class="label-text-alt text-red-400 mt-1"><%= local_assigns[:error_message] %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="form-control mt-4">
|
||||
<%= submit_tag t('submit'), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
@@ -56,6 +56,8 @@
|
||||
<%= link_to 'API', settings_api_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if Docuseal.demo? || !Docuseal.multitenant? || (current_user != true_user && !current_account.testing?) %>
|
||||
<% if can?(:read, WebhookUrl) %>
|
||||
<li>
|
||||
<%= link_to 'Webhooks', settings_webhooks_path, class: 'text-base hover:bg-base-300' %>
|
||||
@@ -70,7 +72,7 @@
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if !Docuseal.demo? && can?(:manage, EncryptedConfig) && (current_user != true_user || !current_account.testing?) %>
|
||||
<% if !Docuseal.demo? && can?(:manage, EncryptedConfig) && (current_user == true_user || current_account.testing?) %>
|
||||
<li>
|
||||
<%= link_to Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}#{'/test' if current_account.testing?}/api") : "#{Docuseal::CONSOLE_URL}/on_premises", class: 'text-base hover:bg-base-300', data: { prefetch: false } do %>
|
||||
<% if Docuseal.multitenant? %> API <% else %> <%= t('console') %> <% end %>
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
</div>
|
||||
<%= form_for '', url: start_form_path(@template.slug), method: :put, html: { class: 'space-y-4', id: 'code_form' } do |f| %>
|
||||
<div dir="auto" class="form-control !mt-0">
|
||||
<%= f.hidden_field 'resubmit', value: params[:resubmit] %>
|
||||
<%= f.hidden_field 'submitter[name]', value: params[:name] || @submitter&.name %>
|
||||
<%= f.hidden_field 'submitter[email]', value: params[:email] || @submitter&.email %>
|
||||
<%= f.hidden_field 'submitter[phone]', value: params[:phone] || @submitter&.phone %>
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
<%= render 'submissions/annotation', annot: %>
|
||||
<% end %>
|
||||
<% fields_index.dig(document.uuid, index)&.each do |(area, field)| %>
|
||||
<% value = values[field['uuid']] %>
|
||||
<% value = values[field['uuid']].presence || (field['default_value'] != '{{date}}' && field['readonly'] == true && field['conditions'].blank? && field['default_value'].present? ? Submitters::SubmitValues.template_default_value_for_submitter(field['default_value'], @submission.submitters.find { |e| e.uuid == field['submitter_uuid'] }, with_time: false) : nil) %>
|
||||
<% value ||= field['default_value'] if field['type'] == 'heading' %>
|
||||
<% next if value.blank? %>
|
||||
<% submitter = submitters_index[field['submitter_uuid']] %>
|
||||
@@ -238,7 +238,7 @@
|
||||
<div class="px-1.5 mb-4">
|
||||
<% submitter_fields_index[item['uuid']].to_a.each_with_index do |field, index| %>
|
||||
<% submitter_field_counters[field['type']] += 1 %>
|
||||
<% value = values[field['uuid']] %>
|
||||
<% value = values[field['uuid']].presence || (field['default_value'] != '{{date}}' && field['readonly'] == true && field['default_value'].present? ? Submitters::SubmitValues.template_default_value_for_submitter(field['default_value'], @submission.submitters.find { |e| e.uuid == field['submitter_uuid'] }, with_time: false) : nil) %>
|
||||
<% next if value.blank? %>
|
||||
<% next if field['type'] == 'heading' %>
|
||||
<div class="pt-2.5 border-b border-base-300">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<% filter_params = params.permit(:q, *Submissions::Filter::ALLOWED_PARAMS) %>
|
||||
<%= render 'shared/turbo_modal', title: t('export'), close_after_submit: false do %>
|
||||
<div class="space-y-2">
|
||||
<%= button_to template_submissions_export_index_path(@template), params: { format: :xlsx }, method: :get, data: { turbo_frame: :_top } do %>
|
||||
<%= button_to template_submissions_export_index_path(@template), params: { format: :xlsx, **filter_params }, method: :get, data: { turbo_frame: :_top } do %>
|
||||
<div class="flex items-center p-4 text-left rounded-2xl border border-neutral-300 hover:cursor-pointer hover:bg-neutral hover:text-gray-300">
|
||||
<div class="enabled">
|
||||
<%= svg_icon('download', class: 'w-12 h-12 stroke-2 mr-2') %>
|
||||
@@ -14,7 +15,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= button_to template_submissions_export_index_path(@template), params: { format: :csv }, method: :get, data: { turbo_frame: :_top } do %>
|
||||
<%= button_to template_submissions_export_index_path(@template), params: { format: :csv, **filter_params }, method: :get, data: { turbo_frame: :_top } do %>
|
||||
<div class="flex items-center text-left p-4 rounded-2xl border border-neutral-300 hover:cursor-pointer hover:bg-neutral hover:text-gray-300">
|
||||
<div class="enabled">
|
||||
<%= svg_icon('download', class: 'w-12 h-12 stroke-2 mr-2') %>
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
<%= render 'submit_form/annotations', annots: %>
|
||||
<% end %>
|
||||
<% fields_index.dig(document.uuid, index)&.each do |(area, field)| %>
|
||||
<% value = values[field['uuid']].presence || (field['default_value'].present? ? Submitters::SubmitValues.template_default_value_for_submitter(field['default_value'], @submitter.submission.submitters.find { |e| e.uuid == field['submitter_uuid'] }, with_time: false) : nil) %>
|
||||
<% value = values[field['uuid']].presence || (field['readonly'] == true && field['default_value'].present? ? Submitters::SubmitValues.template_default_value_for_submitter(field['default_value'], @submitter.submission.submitters.find { |e| e.uuid == field['submitter_uuid'] }, with_time: false) : nil) %>
|
||||
<% next if value.blank? %>
|
||||
<% next if !field['readonly'] && field['submitter_uuid'] == @submitter.uuid %>
|
||||
<% next if value == '{{date}}' && field['submitter_uuid'] != @submitter.uuid %>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
<input id="file_dropzone_input" name="files[]" class="hidden" data-action="change:file-dropzone#onSelectFiles" data-target="file-dropzone.input" type="file" accept="image/*, application/pdf<%= ', .docx, .doc, .xlsx, .xls, .odt, .rtf' if Docuseal.multitenant? %>" multiple>
|
||||
<input id="file_dropzone_input" name="files[]" class="hidden" data-action="change:file-dropzone#onSelectFiles" data-target="file-dropzone.input" type="file" accept="image/*, application/pdf, application/zip<%= ", #{Templates::CreateAttachments::DOCUMENT_EXTENSIONS.join(', ')}" if Docuseal.advanced_formats? %>" multiple>
|
||||
</div>
|
||||
</label>
|
||||
</file-dropzone>
|
||||
|
||||
@@ -14,6 +14,6 @@
|
||||
</span>
|
||||
</button>
|
||||
<input type="hidden" name="form_id" value="<%= form_id %>">
|
||||
<input id="upload_template" name="files[]" class="hidden" onchange="this.form.requestSubmit()" type="file" accept="image/*, application/pdf<%= ', .docx, .doc, .xlsx, .xls, .odt, .rtf' if Docuseal.advanced_formats? %>" multiple>
|
||||
<input id="upload_template" name="files[]" class="hidden" onchange="this.form.requestSubmit()" type="file" accept="image/*, application/pdf, application/zip<%= ", #{Templates::CreateAttachments::DOCUMENT_EXTENSIONS.join(', ')}" if Docuseal.advanced_formats? %>" multiple>
|
||||
<input hidden name="folder_name" value="<%= local_assigns[:folder_name] %>">
|
||||
<% end %>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<% if params[:q].present? || params[:status].present? || filter_params.present? || @pagy.pages > 1 %>
|
||||
<%= render 'shared/search_input', title_selector: 'h2' %>
|
||||
<% end %>
|
||||
<%= link_to new_template_submissions_export_path(@template), class: 'hidden md:flex btn btn-ghost text-base', data: { turbo_frame: 'modal' } do %>
|
||||
<%= link_to new_template_submissions_export_path(@template, params.permit(:q, *Submissions::Filter::ALLOWED_PARAMS)), class: 'hidden md:flex btn btn-ghost text-base', data: { turbo_frame: 'modal' } do %>
|
||||
<%= svg_icon('download', class: 'w-6 h-6 stroke-2') %>
|
||||
<span><%= t('export') %></span>
|
||||
<% end %>
|
||||
|
||||
@@ -1,22 +1,37 @@
|
||||
<%= form_for user, html: { class: 'space-y-4' }, data: { turbo_frame: :_top } do |f| %>
|
||||
<div class="space-y-2">
|
||||
<div class="form-control">
|
||||
<%= f.label :first_name, t('first_name'), class: 'label' %>
|
||||
<%= f.text_field :first_name, required: true, class: 'base-input', dir: 'auto' %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.label :last_name, t('last_name'), class: 'label' %>
|
||||
<%= f.text_field :last_name, required: true, class: 'base-input', dir: 'auto' %>
|
||||
<div class="flex space-x-4">
|
||||
<div class="w-full">
|
||||
<%= f.label :first_name, t('first_name'), class: 'label' %>
|
||||
<%= f.text_field :first_name, required: true, class: 'base-input w-full', dir: 'auto' %>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<%= f.label :last_name, t('last_name'), class: 'label' %>
|
||||
<%= f.text_field :last_name, required: true, class: 'base-input w-full', dir: 'auto' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.label :email, t('email'), class: 'label' %>
|
||||
<%= f.email_field :email, required: true, class: 'base-input' %>
|
||||
<% if user.persisted? && Accounts.can_send_emails?(current_account) %>
|
||||
<span class="label-text-alt mt-2 mx-1">
|
||||
<%= t('click_here_to_send_a_reset_password_email_html') %>
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.label :password, t('password'), class: 'label' %>
|
||||
<%= f.password_field :password, required: user.new_record?, class: 'base-input' %>
|
||||
</div>
|
||||
<% if user.new_record? && !Docuseal.multitenant? %>
|
||||
<div class="form-control">
|
||||
<%= f.label :password, t('password'), class: 'label' %>
|
||||
<%= f.password_field :password, class: 'base-input' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if f.object != current_user %>
|
||||
<% if user.otp_required_for_login %>
|
||||
<div class="form-control">
|
||||
<%= f.label :otp_required_for_login, t('two_factor_authentication'), class: 'label' %>
|
||||
<%= f.select :otp_required_for_login, [[t('enabled'), true], [t('disabled'), false]], { include_blank: false }, class: 'base-select' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= render 'role_select', f: %>
|
||||
<% end %>
|
||||
<% if local_assigns[:extra_fields_html].present? %>
|
||||
@@ -27,3 +42,6 @@
|
||||
<%= f.button button_title, class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if user.persisted? %>
|
||||
<%= button_to nil, user_send_reset_password_path(user), id: 'resend_password_button', method: :put, class: 'hidden', data: { turbo_confirm: t('are_you_sure_'), turbo_frame: :_top } %>
|
||||
<% end %>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="flex flex-col gap-2 md:flex-row md:justify-between md:items-center mb-4">
|
||||
<h1 class="text-4xl font-bold">Webhook</h1>
|
||||
<div class="flex flex-col gap-2 md:flex-row md:justify-between md:items-center">
|
||||
<% if params[:action] == 'index' %>
|
||||
<% if params[:action] == 'index' && (current_user == true_user || current_account.testing?) %>
|
||||
<%= render 'shared/test_mode_toggle' %>
|
||||
<% end %>
|
||||
<% if @webhook_url.persisted? && params[:action] == 'index' %>
|
||||
@@ -84,7 +84,7 @@
|
||||
<h2 id="log" class="text-3xl font-bold"><%= t('events_log') %></h2>
|
||||
<div class="tabs border-b mt-4">
|
||||
<%= link_to t('all'), url_for(params.to_unsafe_h.except(:status)), style: 'margin-bottom: -1px', class: "tab h-10 text-base #{params[:status].blank? ? 'tab-active tab-bordered' : 'pb-[3px]'}" %>
|
||||
<%= link_to t('successed'), url_for(params.to_unsafe_h.merge(status: 'success')), style: 'margin-bottom: -1px', class: "tab h-10 text-base #{params[:status] == 'success' ? 'tab-active tab-bordered' : 'pb-[3px]'}" %>
|
||||
<%= link_to t('succeeded'), url_for(params.to_unsafe_h.merge(status: 'success')), style: 'margin-bottom: -1px', class: "tab h-10 text-base #{params[:status] == 'success' ? 'tab-active tab-bordered' : 'pb-[3px]'}" %>
|
||||
<%= link_to t('failed'), url_for(params.to_unsafe_h.merge(status: 'error')), style: 'margin-bottom: -1px', class: "tab h-10 text-base #{params[:status] == 'error' ? 'tab-active tab-bordered' : 'pb-[3px]'}" %>
|
||||
</div>
|
||||
<% if @webhook_events.present? %>
|
||||
|
||||
@@ -321,7 +321,7 @@ Devise.setup do |config|
|
||||
# apps is `200 OK` and `302 Found respectively`, but new apps are generated with
|
||||
# these new defaults that match Hotwire/Turbo behavior.
|
||||
# Note: These might become the new default in future versions of Devise.
|
||||
config.responder.error_status = :unprocessable_entity
|
||||
config.responder.error_status = :unprocessable_content
|
||||
config.responder.redirect_status = :see_other
|
||||
|
||||
# ==> Configuration for :registerable
|
||||
|
||||
+122
-7
@@ -24,7 +24,12 @@ en: &en
|
||||
thanks: Thanks
|
||||
private: Private
|
||||
select: Select
|
||||
enabled: Enabled
|
||||
disabled: Disabled
|
||||
party: Party
|
||||
click_here_to_send_a_reset_password_email_html: '<label class="link" for="resend_password_button">Click here</label> to send a reset password email.'
|
||||
edit_order: Edit Order
|
||||
expirable_file_download_links: Expirable file download links
|
||||
invite_form_fields: Invite form fields
|
||||
default_parties: Default parties
|
||||
authenticate_embedded_form_preview_with_token: Authenticate embedded form preview with token
|
||||
@@ -35,13 +40,14 @@ en: &en
|
||||
bcc_recipients: BCC recipients
|
||||
resend_pending: Re-send pending
|
||||
always_enforce_signing_order: Always enforce the signing order
|
||||
create_templates_with_private_access_by_default: Create templates with private access by default
|
||||
ensure_unique_recipients: Ensure unique recipients
|
||||
edit_per_party: Edit per party
|
||||
reply_to: Reply to
|
||||
pending_by_me: Pending by me
|
||||
partially_completed: Partially completed
|
||||
require_phone_2fa_to_open: Require phone 2FA to open
|
||||
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_html: The sender has requested a two factor authentication via one time password sent to your <b>%{phone}</b> phone number.
|
||||
the_sender_has_requested_a_two_factor_authentication_via_one_time_password_sent_to_your_html: The sender has requested two-factor authentication via a one-time password sent to your <b>%{phone}</b> phone number.
|
||||
send_verification_code: Send verification code
|
||||
code_has_been_resent: Code has been re-sent
|
||||
invalid_code: Invalid code
|
||||
@@ -766,7 +772,7 @@ en: &en
|
||||
at_least_one_field_must_be_displayed_in_the_form: At least one field must be displayed in the form.
|
||||
this_template_has_multiple_parties_which_prevents_the_use_of_a_sharing_link: This template has multiple parties, which prevents the use of a shared link as it's unclear which party is responsible for specific fields. To resolve this, define the default party details.
|
||||
events_log: Events Log
|
||||
successed: Successed
|
||||
succeeded: Succeeded
|
||||
failed: Failed
|
||||
there_are_no_events: There are no events
|
||||
resend: Resend
|
||||
@@ -793,6 +799,17 @@ en: &en
|
||||
template_name_has_been_completed_by_submitters_html: '"<strong>{template.name}</strong>" has been completed by <strong>{submission.submitters}</strong>'
|
||||
please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Please check the copy of your "<strong>{template.name}</strong>" in the email attachments.'
|
||||
you_have_been_invited_to_sign_the_template_name_html: 'You have been invited to sign the "<strong>{template.name}</strong>".'
|
||||
reveal_api_key: Reveal API Key
|
||||
enter_your_password_to_reveal_the_api_key: Enter your password to reveal the API key
|
||||
wrong_password: Wrong password.
|
||||
current_password: Current password
|
||||
dont_remember_your_current_password_click_here_to_reset_it_html: 'Don''t remember your current password? <label class="link" for="resend_password_button">Click here</label> to reset it.'
|
||||
an_email_with_password_reset_instructions_has_been_sent: An email with password reset instructions has been sent.
|
||||
api_key_access_code: API key access code
|
||||
use_otp_code_to_access_the_api_key_html: Use <b>%{code}</b> code to access the API key.
|
||||
please_reply_to_this_email_if_you_dont_recognize_this_request: Please reply to this email if you don't recognize this request.
|
||||
your_user_account_has_been_archived_contact_your_administrator_to_restore_access_to_your_account: Your user account has been archived. Contact your administrator to restore access to your account.
|
||||
your_email_could_not_be_reached_this_may_happen_if_there_was_a_typo_in_your_address_or_if_your_mailbox_is_not_available_please_contact_support_email_to_log_in: Your email could not be reached. This may happen if there was a typo in your address or if your mailbox is not available. Please contact support@docuseal.com to log in.
|
||||
submission_sources:
|
||||
api: API
|
||||
bulk: Bulk Send
|
||||
@@ -899,6 +916,11 @@ en: &en
|
||||
range_without_total: "%{from}-%{to} events"
|
||||
|
||||
es: &es
|
||||
enabled: Habilitado
|
||||
disabled: Deshabilitado
|
||||
expirable_file_download_links: Enlaces de descarga de archivos con vencimiento
|
||||
create_templates_with_private_access_by_default: Crear plantillas con acceso privado por defecto
|
||||
party: Parte
|
||||
edit_order: Edita Pedido
|
||||
select: Seleccionar
|
||||
invite_form_fields: Invitar campos del formulario
|
||||
@@ -1645,7 +1667,7 @@ es: &es
|
||||
at_least_one_field_must_be_displayed_in_the_form: Al menos un campo debe mostrarse en el formulario.
|
||||
this_template_has_multiple_parties_which_prevents_the_use_of_a_sharing_link: Esta plantilla tiene varias partes, lo que impide el uso de un enlace compartido porque no está claro qué parte es responsable de campos específicos. Para resolverlo, define los detalles predeterminados de la parte.
|
||||
events_log: Registro de eventos
|
||||
successed: Exitoso
|
||||
succeeded: Exitoso
|
||||
failed: Fallido
|
||||
there_are_no_events: No hay eventos
|
||||
resend: Reenviar
|
||||
@@ -1672,6 +1694,17 @@ es: &es
|
||||
template_name_has_been_completed_by_submitters_html: '"<strong>{template.name}</strong>" ha sido completado por <strong>{submission.submitters}</strong>'
|
||||
please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Por favor, revisa la copia de tu "<strong>{template.name}</strong>" en los archivos adjuntos del correo electrónico.'
|
||||
you_have_been_invited_to_sign_the_template_name_html: 'Has sido invitado a firmar el "<strong>{template.name}</strong>".'
|
||||
reveal_api_key: Revelar clave API
|
||||
enter_your_password_to_reveal_the_api_key: Introduce tu contraseña para revelar la clave API
|
||||
wrong_password: Contraseña incorrecta.
|
||||
current_password: Contraseña actual
|
||||
dont_remember_your_current_password_click_here_to_reset_it_html: '¿No recuerdas tu contraseña actual? <label class="link" for="resend_password_button">Haz clic aquí</label> para restablecerla.'
|
||||
an_email_with_password_reset_instructions_has_been_sent: Se enviará un correo electrónico con las instrucciones para restablecer tu contraseña en unos minutos.
|
||||
api_key_access_code: Código de acceso de la clave API
|
||||
use_otp_code_to_access_the_api_key_html: Usa el código <b>%{code}</b> para acceder a la clave API.
|
||||
please_reply_to_this_email_if_you_dont_recognize_this_request: Responde a este correo si no reconoces esta solicitud.
|
||||
your_user_account_has_been_archived_contact_your_administrator_to_restore_access_to_your_account: Tu cuenta de usuario ha sido archivada. Contacta a tu administrador para restaurar el acceso a tu cuenta.
|
||||
your_email_could_not_be_reached_this_may_happen_if_there_was_a_typo_in_your_address_or_if_your_mailbox_is_not_available_please_contact_support_email_to_log_in: No se pudo acceder a tu correo electrónico. Esto puede ocurrir si hubo un error tipográfico en tu dirección o si tu buzón no está disponible. Por favor, contacta a support@docuseal.com para iniciar sesión.
|
||||
submission_sources:
|
||||
api: API
|
||||
bulk: Envío masivo
|
||||
@@ -1778,6 +1811,12 @@ es: &es
|
||||
range_without_total: "%{from}-%{to} eventos"
|
||||
|
||||
it: &it
|
||||
click_here_to_send_a_reset_password_email_html: '<label class="link" for="resend_password_button">Clicca qui</label> per inviare una email per reimpostare la password.'
|
||||
enabled: Abilitato
|
||||
disabled: Disabilitato
|
||||
expirable_file_download_links: Link di download di file con scadenza
|
||||
create_templates_with_private_access_by_default: Crea modelli con accesso privato per impostazione predefinita
|
||||
party: Parte
|
||||
edit_order: Modifica Ordine
|
||||
select: Seleziona
|
||||
invite_form_fields: Invita campi modulo
|
||||
@@ -2523,7 +2562,7 @@ it: &it
|
||||
at_least_one_field_must_be_displayed_in_the_form: Almeno un campo deve essere visualizzato nel modulo.
|
||||
this_template_has_multiple_parties_which_prevents_the_use_of_a_sharing_link: Questo modello ha più parti, il che impedisce l’uso di un link di condivisione perché non è chiaro quale parte sia responsabile di campi specifici. Per risolvere, definisci i dettagli predefiniti della parte.
|
||||
events_log: Registro eventi
|
||||
successed: Riuscito
|
||||
succeeded: Riuscito
|
||||
failed: Fallito
|
||||
there_are_no_events: Nessun evento
|
||||
resend: Invia di nuovo
|
||||
@@ -2551,6 +2590,17 @@ it: &it
|
||||
template_name_has_been_completed_by_submitters_html: '"<strong>{template.name}</strong>" è stato completato da <strong>{submission.submitters}</strong>'
|
||||
please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Per favore, controlla la copia del tuo "<strong>{template.name}</strong>" negli allegati dell''email.'
|
||||
you_have_been_invited_to_sign_the_template_name_html: 'Sei stato invitato a firmare il "<strong>{template.name}</strong>".'
|
||||
reveal_api_key: Mostra chiave API
|
||||
enter_your_password_to_reveal_the_api_key: Inserisci la tua password per mostrare la chiave API
|
||||
wrong_password: Password errata.
|
||||
current_password: Password attuale
|
||||
dont_remember_your_current_password_click_here_to_reset_it_html: 'Non ricordi la tua password attuale? <label class="link" for="resend_password_button">Clicca qui</label> per reimpostarla.'
|
||||
an_email_with_password_reset_instructions_has_been_sent: Un'email con le istruzioni per reimpostare la password ti è stata inviata e arriverà entro pochi minuti.
|
||||
api_key_access_code: Codice di accesso della chiave API
|
||||
use_otp_code_to_access_the_api_key_html: Usa il codice <b>%{code}</b> per accedere alla chiave API.
|
||||
please_reply_to_this_email_if_you_dont_recognize_this_request: Rispondi a questa email se non riconosci questa richiesta.
|
||||
your_user_account_has_been_archived_contact_your_administrator_to_restore_access_to_your_account: Il tuo account utente è stato archiviato. Contatta il tuo amministratore per ripristinare l'accesso al tuo account.
|
||||
your_email_could_not_be_reached_this_may_happen_if_there_was_a_typo_in_your_address_or_if_your_mailbox_is_not_available_please_contact_support_email_to_log_in: Non è stato possibile raggiungere la tua email. Questo può accadere se c'è stato un errore di digitazione nell'indirizzo o se la tua casella di posta non è disponibile. Contatta support@docuseal.com per accedere.
|
||||
submission_sources:
|
||||
api: API
|
||||
bulk: Invio massivo
|
||||
@@ -2657,6 +2707,12 @@ it: &it
|
||||
range_without_total: "%{from}-%{to} eventi"
|
||||
|
||||
fr: &fr
|
||||
click_here_to_send_a_reset_password_email_html: '<label class="link" for="resend_password_button">Cliquez ici</label> pour envoyer un e-mail de réinitialisation du mot de passe.'
|
||||
enabled: Activé
|
||||
disabled: Désactivé
|
||||
expirable_file_download_links: Liens de téléchargement de fichiers expirables
|
||||
create_templates_with_private_access_by_default: Créer des modèles avec un accès privé par défaut
|
||||
party: Partie
|
||||
edit_order: Modifier la commande
|
||||
select: Sélectionner
|
||||
invite_form_fields: Inviter des champs de formulaire
|
||||
@@ -3405,7 +3461,7 @@ fr: &fr
|
||||
at_least_one_field_must_be_displayed_in_the_form: Au moins un champ doit être affiché dans le formulaire.
|
||||
this_template_has_multiple_parties_which_prevents_the_use_of_a_sharing_link: Ce modèle contient plusieurs parties, ce qui empêche l’utilisation d’un lien de partage car il n’est pas clair quelle partie est responsable de certains champs. Pour résoudre cela, définissez les détails de la partie par défaut.
|
||||
events_log: Journal des événements
|
||||
successed: Réussi
|
||||
succeeded: Réussi
|
||||
failed: Échoué
|
||||
there_are_no_events: Aucun événement
|
||||
resend: Renvoyer
|
||||
@@ -3433,6 +3489,17 @@ fr: &fr
|
||||
template_name_has_been_completed_by_submitters_html: '"<strong>{template.name}</strong>" a été complété par <strong>{submission.submitters}</strong>'
|
||||
please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Veuillez vérifier la copie de votre "<strong>{template.name}</strong>" dans les pièces jointes de l’e-mail.'
|
||||
you_have_been_invited_to_sign_the_template_name_html: 'Vous avez été invité à signer le "<strong>{template.name}</strong>".'
|
||||
reveal_api_key: Révéler la clé API
|
||||
enter_your_password_to_reveal_the_api_key: Entrez votre mot de passe pour révéler la clé API
|
||||
wrong_password: Mot de passe incorrect.
|
||||
current_password: Mot de passe actuel
|
||||
dont_remember_your_current_password_click_here_to_reset_it_html: 'Vous ne vous souvenez plus de votre mot de passe actuel ? <label class="link" for="resend_password_button">Cliquez ici</label> pour le réinitialiser.'
|
||||
an_email_with_password_reset_instructions_has_been_sent: Un e-mail contenant les instructions pour réinitialiser votre mot de passe vous sera envoyé dans quelques minutes.
|
||||
api_key_access_code: Code d'accès de la clé API
|
||||
use_otp_code_to_access_the_api_key_html: Utilisez le code <b>%{code}</b> pour accéder à la clé API.
|
||||
please_reply_to_this_email_if_you_dont_recognize_this_request: Veuillez répondre à cet e-mail si vous ne reconnaissez pas cette demande.
|
||||
your_user_account_has_been_archived_contact_your_administrator_to_restore_access_to_your_account: Votre compte utilisateur a été archivé. Contactez votre administrateur pour rétablir l'accès à votre compte.
|
||||
your_email_could_not_be_reached_this_may_happen_if_there_was_a_typo_in_your_address_or_if_your_mailbox_is_not_available_please_contact_support_email_to_log_in: Votre e-mail n'a pas pu être atteint. Cela peut arriver s'il y a eu une faute de frappe dans votre adresse ou si votre boîte aux lettres n'est pas disponible. Veuillez contacter support@docuseal.com pour vous connecter.
|
||||
submission_sources:
|
||||
api: API
|
||||
bulk: Envoi en masse
|
||||
@@ -3539,6 +3606,12 @@ fr: &fr
|
||||
range_without_total: "%{from} à %{to} événements"
|
||||
|
||||
pt: &pt
|
||||
click_here_to_send_a_reset_password_email_html: '<label class="link" for="resend_password_button">Clique aqui</label> para enviar um e-mail de redefinição de senha.'
|
||||
enabled: Ativado
|
||||
disabled: Desativado
|
||||
expirable_file_download_links: Links de download de arquivos com expiração
|
||||
create_templates_with_private_access_by_default: Criar modelos com acesso privado por padrão
|
||||
party: Parte
|
||||
edit_order: Edita Pedido
|
||||
select: Selecionar
|
||||
invite_form_fields: Convidar campos do formulário
|
||||
@@ -4286,7 +4359,7 @@ pt: &pt
|
||||
at_least_one_field_must_be_displayed_in_the_form: Pelo menos um campo deve ser exibido no formulário.
|
||||
this_template_has_multiple_parties_which_prevents_the_use_of_a_sharing_link: Este modelo tem várias partes, o que impede o uso de um link de compartilhamento, pois não está claro qual parte é responsável por campos específicos. Para resolver isso, defina os detalhes padrão da parte.
|
||||
events_log: Registro de eventos
|
||||
successed: Sucesso
|
||||
succeeded: Sucesso
|
||||
failed: Falhou
|
||||
there_are_no_events: Nenhum evento
|
||||
resend: Reenviar
|
||||
@@ -4313,6 +4386,17 @@ pt: &pt
|
||||
template_name_has_been_completed_by_submitters_html: '"<strong>{template.name}</strong>" foi concluído por <strong>{submission.submitters}</strong>'
|
||||
please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Por favor, verifique a cópia do seu "<strong>{template.name}</strong>" nos anexos do e-mail.'
|
||||
you_have_been_invited_to_sign_the_template_name_html: 'Você foi convidado a assinar o "<strong>{template.name}</strong>".'
|
||||
reveal_api_key: Revelar chave API
|
||||
enter_your_password_to_reveal_the_api_key: Insira sua senha para revelar a chave API
|
||||
wrong_password: Senha incorreta.
|
||||
current_password: Senha atual
|
||||
dont_remember_your_current_password_click_here_to_reset_it_html: 'Não se lembra da sua senha atual? <label class="link" for="resend_password_button">Clique aqui</label> para redefini-la.'
|
||||
an_email_with_password_reset_instructions_has_been_sent: Um e-mail com instruções para redefinir sua senha será enviado em alguns minutos.
|
||||
api_key_access_code: Código de acesso da chave API
|
||||
use_otp_code_to_access_the_api_key_html: Use o código <b>%{code}</b> para acessar a chave API.
|
||||
please_reply_to_this_email_if_you_dont_recognize_this_request: Responda a este e-mail se você não reconhecer esta solicitação.
|
||||
your_user_account_has_been_archived_contact_your_administrator_to_restore_access_to_your_account: Sua conta de usuário foi arquivada. Entre em contato com o administrador para restaurar o acesso à sua conta.
|
||||
your_email_could_not_be_reached_this_may_happen_if_there_was_a_typo_in_your_address_or_if_your_mailbox_is_not_available_please_contact_support_email_to_log_in: Seu e-mail não pôde ser acessado. Isso pode acontecer se houve um erro de digitação no endereço ou se sua caixa de correio não estiver disponível. Entre em contato com support@docuseal.com para fazer login.
|
||||
submission_sources:
|
||||
api: API
|
||||
bulk: Envio em massa
|
||||
@@ -4419,6 +4503,12 @@ pt: &pt
|
||||
range_without_total: "%{from}-%{to} eventos"
|
||||
|
||||
de: &de
|
||||
click_here_to_send_a_reset_password_email_html: '<label class="link" for="resend_password_button">Klicken Sie hier</label>, um eine E-Mail zum Zurücksetzen des Passworts zu senden.'
|
||||
enabled: Aktiviert
|
||||
disabled: Deaktiviert
|
||||
expirable_file_download_links: Ablaufbare Datei-Download-Links
|
||||
create_templates_with_private_access_by_default: Vorlagen standardmäßig mit privatem Zugriff erstellen
|
||||
party: Partei
|
||||
edit_order: Bestellung bearbeiten
|
||||
select: Auswählen
|
||||
invite_form_fields: Formularfelder einladen
|
||||
@@ -5166,7 +5256,7 @@ de: &de
|
||||
at_least_one_field_must_be_displayed_in_the_form: Mindestens ein Feld muss im Formular angezeigt werden.
|
||||
this_template_has_multiple_parties_which_prevents_the_use_of_a_sharing_link: Diese Vorlage enthält mehrere Parteien, was die Verwendung eines Freigabelinks verhindert, da unklar ist, welche Partei für bestimmte Felder verantwortlich ist. Um dies zu beheben, definieren Sie die Standardparteidetails.
|
||||
events_log: Ereignisprotokoll
|
||||
successed: Erfolgreich
|
||||
succeeded: Erfolgreich
|
||||
failed: Fehlgeschlagen
|
||||
there_are_no_events: Keine Ereignisse vorhanden
|
||||
resend: Erneut senden
|
||||
@@ -5193,6 +5283,15 @@ de: &de
|
||||
template_name_has_been_completed_by_submitters_html: '"<strong>{template.name}</strong>" wurde von <strong>{submission.submitters}</strong> abgeschlossen'
|
||||
please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Bitte prüfen Sie die Kopie Ihres "<strong>{template.name}</strong>" in den E-Mail-Anhängen.'
|
||||
you_have_been_invited_to_sign_the_template_name_html: 'Du wurdest eingeladen, "<strong>{template.name}</strong>" zu unterschreiben.'
|
||||
reveal_api_key: API-Schlüssel anzeigen
|
||||
enter_your_password_to_reveal_the_api_key: Gib dein Passwort ein, um den API-Schlüssel anzuzeigen
|
||||
wrong_password: Falsches Passwort.
|
||||
current_password: Aktuelles Passwort
|
||||
dont_remember_your_current_password_click_here_to_reset_it_html: 'Sie erinnern sich nicht an Ihr aktuelles Passwort? <label class="link" for="resend_password_button">Klicken Sie hier</label>, um es zurückzusetzen.'
|
||||
an_email_with_password_reset_instructions_has_been_sent: Eine E-Mail mit Anweisungen zum Zurücksetzen Ihres Passworts wurde Ihnen in wenigen Minuten zugesendet.
|
||||
api_key_access_code: API-Schlüssel-Zugangscode
|
||||
use_otp_code_to_access_the_api_key_html: Verwenden Sie den Code <b>%{code}</b>, um auf den API-Schlüssel zuzugreifen.
|
||||
please_reply_to_this_email_if_you_dont_recognize_this_request: Bitte antworten Sie auf diese E-Mail, wenn Sie diese Anfrage nicht erkennen.
|
||||
submission_sources:
|
||||
api: API
|
||||
bulk: Massenversand
|
||||
@@ -5386,6 +5485,8 @@ pl:
|
||||
email_verification: Weryfikacja e-mail
|
||||
your_verification_code_to_access_the_name: 'Twój kod weryfikacyjny do uzyskania dostępu do "%{name}":'
|
||||
please_reply_to_this_email_if_you_didnt_request_this: Odpowiedz na ten e-mail, jeśli nie prosiłeś o to.
|
||||
your_user_account_has_been_archived_contact_your_administrator_to_restore_access_to_your_account: Twoje konto użytkownika zostało zarchiwizowane. Skontaktuj się z administratorem, aby przywrócić dostęp do konta.
|
||||
your_email_could_not_be_reached_this_may_happen_if_there_was_a_typo_in_your_address_or_if_your_mailbox_is_not_available_please_contact_support_email_to_log_in: Nie udało się uzyskać dostępu do Twojego adresu e-mail. Może to być spowodowane literówką w adresie lub niedostępnością skrzynki. Skontaktuj się z support@docuseal.com, aby się zalogować.
|
||||
|
||||
uk:
|
||||
require_phone_2fa_to_open: Вимагати двофакторну автентифікацію через телефон для відкриття
|
||||
@@ -5475,6 +5576,8 @@ uk:
|
||||
email_verification: Підтвердження електронної пошти
|
||||
your_verification_code_to_access_the_name: 'Ваш код доступу до "%{name}":'
|
||||
please_reply_to_this_email_if_you_didnt_request_this: Відповідайте на цей лист, якщо ви цього не запитували.
|
||||
your_user_account_has_been_archived_contact_your_administrator_to_restore_access_to_your_account: Ваш обліковий запис було архівовано. Зверніться до адміністратора, щоб відновити доступ.
|
||||
your_email_could_not_be_reached_this_may_happen_if_there_was_a_typo_in_your_address_or_if_your_mailbox_is_not_available_please_contact_support_email_to_log_in: Не вдалося отримати доступ до вашої електронної пошти. Це може статися, якщо була допущена помилка в адресі або ваша скринька недоступна. Зверніться до support@docuseal.com, щоб увійти.
|
||||
|
||||
cs:
|
||||
require_phone_2fa_to_open: Vyžadovat otevření pomocí telefonního 2FA
|
||||
@@ -5564,6 +5667,8 @@ cs:
|
||||
email_verification: Ověření e-mailu
|
||||
your_verification_code_to_access_the_name: 'Váš ověřovací kód pro přístup k "%{name}":'
|
||||
please_reply_to_this_email_if_you_didnt_request_this: Odpovězte na tento e-mail, pokud jste o to nežádali.
|
||||
your_user_account_has_been_archived_contact_your_administrator_to_restore_access_to_your_account: Váš uživatelský účet byl archivován. Kontaktujte svého administrátora pro obnovení přístupu.
|
||||
your_email_could_not_be_reached_this_may_happen_if_there_was_a_typo_in_your_address_or_if_your_mailbox_is_not_available_please_contact_support_email_to_log_in: Nepodařilo se dosáhnout na váš e-mail. To se může stát, pokud je v adrese překlep nebo vaše schránka není dostupná. Kontaktujte support@docuseal.com pro přihlášení.
|
||||
|
||||
he:
|
||||
require_phone_2fa_to_open: דרוש אימות דו-שלבי באמצעות טלפון לפתיחה
|
||||
@@ -5653,6 +5758,8 @@ he:
|
||||
email_verification: 'אימות דוא"ל'
|
||||
your_verification_code_to_access_the_name: 'קוד האימות שלך לגישה ל-%{name}:'
|
||||
please_reply_to_this_email_if_you_didnt_request_this: 'השב למייל זה אם לא ביקשת זאת.'
|
||||
your_user_account_has_been_archived_contact_your_administrator_to_restore_access_to_your_account: החשבון שלך הועבר לארכיון. פנה למנהל המערכת כדי לשחזר את הגישה.
|
||||
your_email_could_not_be_reached_this_may_happen_if_there_was_a_typo_in_your_address_or_if_your_mailbox_is_not_available_please_contact_support_email_to_log_in: לא ניתן היה לגשת לדוא"ל שלך. ייתכן שזה קרה עקב שגיאת כתיב בכתובת או אם תיבת הדואר אינה זמינה. אנא פנה ל־support@docuseal.com כדי להתחבר.
|
||||
|
||||
nl:
|
||||
require_phone_2fa_to_open: Vereis telefoon 2FA om te openen
|
||||
@@ -5742,6 +5849,8 @@ nl:
|
||||
email_verification: E-mailverificatie
|
||||
your_verification_code_to_access_the_name: 'Je verificatiecode voor toegang tot "%{name}":'
|
||||
please_reply_to_this_email_if_you_didnt_request_this: Reageer op deze e-mail als je dit niet hebt aangevraagd.
|
||||
your_user_account_has_been_archived_contact_your_administrator_to_restore_access_to_your_account: Je gebruikersaccount is gearchiveerd. Neem contact op met je beheerder om de toegang te herstellen.
|
||||
your_email_could_not_be_reached_this_may_happen_if_there_was_a_typo_in_your_address_or_if_your_mailbox_is_not_available_please_contact_support_email_to_log_in: Je e-mailadres kon niet worden bereikt. Dit kan gebeuren door een typefout in je adres of als je mailbox niet beschikbaar is. Neem contact op met support@docuseal.com om in te loggen.
|
||||
|
||||
ar:
|
||||
require_phone_2fa_to_open: "تطلب فتح عبر تحقق الهاتف ذو العاملين"
|
||||
@@ -5831,6 +5940,8 @@ ar:
|
||||
email_verification: 'التحقق من البريد الإلكتروني'
|
||||
your_verification_code_to_access_the_name: 'رمز التحقق الخاص بك للوصول إلى "%{name}":'
|
||||
please_reply_to_this_email_if_you_didnt_request_this: 'يرجى الرد على هذا البريد إذا لم تطلب ذلك.'
|
||||
your_user_account_has_been_archived_contact_your_administrator_to_restore_access_to_your_account: تم أرشفة حسابك. يرجى التواصل مع المسؤول لاستعادة الوصول إلى حسابك.
|
||||
your_email_could_not_be_reached_this_may_happen_if_there_was_a_typo_in_your_address_or_if_your_mailbox_is_not_available_please_contact_support_email_to_log_in: تعذّر الوصول إلى بريدك الإلكتروني. قد يحدث هذا في حال وجود خطأ في العنوان أو إذا كانت صندوق البريد غير متاح. يرجى التواصل مع support@docuseal.com لتسجيل الدخول.
|
||||
|
||||
ko:
|
||||
require_phone_2fa_to_open: 휴대폰 2FA를 열 때 요구함
|
||||
@@ -5920,6 +6031,8 @@ ko:
|
||||
email_verification: 이메일 인증
|
||||
your_verification_code_to_access_the_name: '"%{name}"에 액세스하기 위한 인증 코드:'
|
||||
please_reply_to_this_email_if_you_didnt_request_this: 요청하지 않았다면 이 이메일에 회신하세요.
|
||||
your_user_account_has_been_archived_contact_your_administrator_to_restore_access_to_your_account: 사용자 계정이 보관되었습니다. 계정 접근을 복원하려면 관리자에게 문의하세요.
|
||||
your_email_could_not_be_reached_this_may_happen_if_there_was_a_typo_in_your_address_or_if_your_mailbox_is_not_available_please_contact_support_email_to_log_in: 이메일에 접근할 수 없습니다. 주소에 오타가 있거나 메일박스가 사용 불가능한 경우 발생할 수 있습니다. 로그인하려면 support@docuseal.com에 문의하세요.
|
||||
|
||||
ja:
|
||||
require_phone_2fa_to_open: 電話による2段階認証が必要です
|
||||
@@ -6009,6 +6122,8 @@ ja:
|
||||
email_verification: メール認証
|
||||
your_verification_code_to_access_the_name: '"%{name}"へのアクセスコード:'
|
||||
please_reply_to_this_email_if_you_didnt_request_this: このリクエストを行っていない場合は、このメールに返信してください。
|
||||
your_user_account_has_been_archived_contact_your_administrator_to_restore_access_to_your_account: あなたのユーザーアカウントはアーカイブされました。アクセスを復元するには管理者に連絡してください。
|
||||
your_email_could_not_be_reached_this_may_happen_if_there_was_a_typo_in_your_address_or_if_your_mailbox_is_not_available_please_contact_support_email_to_log_in: メールにアクセスできませんでした。アドレスの入力ミスやメールボックスが利用できない場合に発生することがあります。ログインするには support@docuseal.com に連絡してください。
|
||||
|
||||
en-US:
|
||||
<<: *en
|
||||
|
||||
+4
-1
@@ -65,7 +65,9 @@ Rails.application.routes.draw do
|
||||
resources :setup, only: %i[index create]
|
||||
resource :newsletter, only: %i[show update]
|
||||
resources :enquiries, only: %i[create]
|
||||
resources :users, only: %i[new create edit update destroy]
|
||||
resources :users, only: %i[new create edit update destroy] do
|
||||
resource :send_reset_password, only: %i[update], controller: 'users_send_reset_password'
|
||||
end
|
||||
resource :user_signature, only: %i[edit update destroy]
|
||||
resource :user_initials, only: %i[edit update destroy]
|
||||
resources :submissions_archived, only: %i[index], path: 'submissions/archived'
|
||||
@@ -179,6 +181,7 @@ Rails.application.routes.draw do
|
||||
defaults: { status: :integration }
|
||||
resource :personalization, only: %i[show create], controller: 'personalization_settings'
|
||||
resources :api, only: %i[index create], controller: 'api_settings'
|
||||
resource :reveal_access_token, only: %i[show create], controller: 'reveal_access_token'
|
||||
resources :webhooks, only: %i[index show new create update destroy], controller: 'webhook_settings' do
|
||||
post :resend
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
disk:
|
||||
service: Disk
|
||||
root: <%= ENV['WORKDIR'] || '.' %>/attachments
|
||||
public: true
|
||||
public: <%= ENV['ACTIVE_STORAGE_PUBLIC'] == 'true' %>
|
||||
|
||||
aws_s3:
|
||||
service: S3
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class PopulateExpireLinkConfigs < ActiveRecord::Migration[8.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
class MigrationAccount < ActiveRecord::Base
|
||||
self.table_name = 'accounts'
|
||||
end
|
||||
|
||||
class MigrationAccountConfig < ActiveRecord::Base
|
||||
self.table_name = 'account_configs'
|
||||
|
||||
serialize :value, coder: JSON
|
||||
end
|
||||
|
||||
def up
|
||||
MigrationAccount.find_each do |account|
|
||||
config = MigrationAccountConfig.find_or_initialize_by(key: 'download_links_expire', account_id: account.id)
|
||||
|
||||
next if config.persisted?
|
||||
|
||||
config.value = false
|
||||
config.save!
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
nil
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AddVerificationMethodToCompletedSubmitters < ActiveRecord::Migration[8.0]
|
||||
def change
|
||||
add_column :completed_submitters, :verification_method, :string
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,9 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AddTemplateVariables < ActiveRecord::Migration[8.0]
|
||||
def change
|
||||
add_column :templates, :variables_schema, :text
|
||||
add_column :submissions, :variables_schema, :text
|
||||
add_column :submissions, :variables, :text
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,14 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class CreateLockEvents < ActiveRecord::Migration[8.0]
|
||||
def change
|
||||
create_table :lock_events do |t|
|
||||
t.string :key, index: true, null: false
|
||||
t.string :event_name, null: false
|
||||
|
||||
t.index %i[event_name key], unique: true, where: "event_name IN ('start', 'complete')"
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
||||
+14
-1
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[8.0].define(version: 2025_07_18_121133) do
|
||||
ActiveRecord::Schema[8.0].define(version: 2025_09_15_060548) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "btree_gin"
|
||||
enable_extension "plpgsql"
|
||||
@@ -117,6 +117,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_07_18_121133) do
|
||||
t.datetime "completed_at", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "verification_method"
|
||||
t.index ["account_id"], name: "index_completed_submitters_on_account_id"
|
||||
t.index ["submitter_id"], name: "index_completed_submitters_on_submitter_id", unique: true
|
||||
end
|
||||
@@ -216,6 +217,15 @@ ActiveRecord::Schema[8.0].define(version: 2025_07_18_121133) do
|
||||
t.index ["user_id"], name: "index_encrypted_user_configs_on_user_id"
|
||||
end
|
||||
|
||||
create_table "lock_events", force: :cascade do |t|
|
||||
t.string "key", null: false
|
||||
t.string "event_name", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["event_name", "key"], name: "index_lock_events_on_event_name_and_key", unique: true, where: "((event_name)::text = ANY ((ARRAY['start'::character varying, 'complete'::character varying])::text[]))"
|
||||
t.index ["key"], name: "index_lock_events_on_key"
|
||||
end
|
||||
|
||||
create_table "oauth_access_grants", force: :cascade do |t|
|
||||
t.bigint "resource_owner_id", null: false
|
||||
t.bigint "application_id", null: false
|
||||
@@ -304,6 +314,8 @@ ActiveRecord::Schema[8.0].define(version: 2025_07_18_121133) do
|
||||
t.bigint "account_id", null: false
|
||||
t.datetime "expire_at"
|
||||
t.text "name"
|
||||
t.text "variables_schema"
|
||||
t.text "variables"
|
||||
t.index ["account_id", "id"], name: "index_submissions_on_account_id_and_id"
|
||||
t.index ["account_id", "template_id", "id"], name: "index_submissions_on_account_id_and_template_id_and_id", where: "(archived_at IS NULL)"
|
||||
t.index ["account_id", "template_id", "id"], name: "index_submissions_on_account_id_and_template_id_and_id_archived", where: "(archived_at IS NOT NULL)"
|
||||
@@ -388,6 +400,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_07_18_121133) do
|
||||
t.string "external_id"
|
||||
t.text "preferences", null: false
|
||||
t.boolean "shared_link", default: false, null: false
|
||||
t.text "variables_schema"
|
||||
t.index ["account_id", "folder_id", "id"], name: "index_templates_on_account_id_and_folder_id_and_id", where: "(archived_at IS NULL)"
|
||||
t.index ["account_id", "id"], name: "index_templates_on_account_id_and_id_archived", where: "(archived_at IS NOT NULL)"
|
||||
t.index ["account_id"], name: "index_templates_on_account_id"
|
||||
|
||||
+703
-37
@@ -523,6 +523,15 @@ var response = client.Execute(request);
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -598,14 +607,45 @@ var response = client.Execute(request);
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -1025,10 +1065,6 @@ var response = client.Execute(request);
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails."
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"completed": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `true` to mark submitter as completed and auto-signed via API."
|
||||
@@ -1038,6 +1074,15 @@ var response = client.Execute(request);
|
||||
"description": "Metadata object with additional submitter information.",
|
||||
"example": "{ \"customField\": \"value\" }"
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -1105,14 +1150,45 @@ var response = client.Execute(request);
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make the field required."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -1775,6 +1851,46 @@ var response = client.Execute(request);
|
||||
"Option B"
|
||||
]
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -2253,7 +2369,7 @@ var response = client.Execute(request);
|
||||
|
||||
### Create a submission from PDF
|
||||
|
||||
The API endpoint provides the functionality to create one-off submission request from a PDF or DOCX file. Use <code>{{Field Name;role=Signer1;type=date}}</code> text tags to define fillable fields in the document. See <a href="https://www.docuseal.com/examples/fieldtags.pdf" target="_blank" class="link font-bold">https://www.docuseal.com/examples/fieldtags.pdf</a> for more text tag formats. Or specify the exact pixel coordinates of the document fields using `fields` param.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
The API endpoint provides the functionality to create one-off submission request from a PDF. Use <code>{{Field Name;role=Signer1;type=date}}</code> text tags to define fillable fields in the document. See <a href="https://www.docuseal.com/examples/fieldtags.pdf" target="_blank" class="link font-bold">https://www.docuseal.com/examples/fieldtags.pdf</a> for more text tag formats. Or specify the exact pixel coordinates of the document fields using `fields` param.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
|
||||
|
||||
```csharp
|
||||
@@ -2531,6 +2647,15 @@ var response = client.Execute(request);
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
@@ -2593,14 +2718,45 @@ var response = client.Execute(request);
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -2946,6 +3102,15 @@ var response = client.Execute(request);
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
@@ -3008,14 +3173,45 @@ var response = client.Execute(request);
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -3323,6 +3519,46 @@ var response = client.Execute(request);
|
||||
"Option B"
|
||||
]
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -3439,3 +3675,433 @@ var response = client.Execute(request);
|
||||
}
|
||||
```
|
||||
|
||||
### Create a submission from DOCX
|
||||
|
||||
The API endpoint provides functionality to create a one-off submission request from a DOCX file with dynamic content variables. Use <code>[[variable_name]]</code> text tags to define dynamic content variables in the document. See <a href="https://www.docuseal.com/examples/demo_template.docx" target="_blank" class="link font-bold">https://www.docuseal.com/examples/demo_template.docx</a> for the specific text variable syntax, including dynamic content tables and list. You can also use the <code>{{signature}}</code> fillable field syntax to define fillable fields, as in a PDF.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
|
||||
```csharp
|
||||
var client = new RestClient("https://api.docuseal.com/submissions/docx");
|
||||
var request = new RestRequest("", Method.Post);
|
||||
request.AddHeader("X-Auth-Token", "API_KEY");
|
||||
request.AddHeader("content-type", "application/json");
|
||||
request.AddParameter("application/json", "{\"name\":\"Test Submission Document\",\"variables\":{\"variable_name\":\"value\"},\"documents\":[{\"name\":\"string\",\"file\":\"base64\"}],\"submitters\":[{\"role\":\"First Party\",\"email\":\"john.doe@example.com\"}]}", ParameterType.RequestBody);
|
||||
var response = client.Execute(request);
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"security": [
|
||||
{
|
||||
"AuthToken": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Submissions"
|
||||
],
|
||||
"summary": "Create a submission from DOCX",
|
||||
"operationId": "createSubmissionFromDocx",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"documents",
|
||||
"submitters"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the document submission.",
|
||||
"example": "Test Submission Document"
|
||||
},
|
||||
"send_email": {
|
||||
"type": "boolean",
|
||||
"description": "Set `false` to disable signature request emails sending.",
|
||||
"default": true
|
||||
},
|
||||
"send_sms": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to send signature request via phone number and SMS.",
|
||||
"default": false
|
||||
},
|
||||
"variables": {
|
||||
"type": "object",
|
||||
"description": "Dynamic content variables object",
|
||||
"example": {
|
||||
"variable_name": "value"
|
||||
}
|
||||
},
|
||||
"order": {
|
||||
"type": "string",
|
||||
"description": "Pass 'random' to send signature request emails to all parties right away. The order is 'preserved' by default so the second party will receive a signature request email only after the document is signed by the first party.",
|
||||
"default": "preserved",
|
||||
"enum": [
|
||||
"preserved",
|
||||
"random"
|
||||
]
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Specify URL to redirect to after the submission completion."
|
||||
},
|
||||
"bcc_completed": {
|
||||
"type": "string",
|
||||
"description": "Specify BCC address to send signed documents to after the completion."
|
||||
},
|
||||
"reply_to": {
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails."
|
||||
},
|
||||
"expire_at": {
|
||||
"type": "string",
|
||||
"description": "Specify the expiration date and time after which the submission becomes unavailable for signature.",
|
||||
"example": "2024-09-01 12:00:00 UTC"
|
||||
},
|
||||
"template_ids": {
|
||||
"type": "array",
|
||||
"description": "An optional array of template IDs to use in the submission along with the provided documents. This can be used to create multi-document submissions when some of the required documents exist within templates.",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"description": "The ID of the template to use for the submission."
|
||||
}
|
||||
},
|
||||
"documents": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"file"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the document."
|
||||
},
|
||||
"file": {
|
||||
"example": "base64",
|
||||
"type": "string",
|
||||
"format": "base64",
|
||||
"description": "Base64-encoded content of the PDF or DOCX file or downloadable file URL."
|
||||
},
|
||||
"position": {
|
||||
"type": "integer",
|
||||
"description": "Document position in the submission. If not specified, the document will be added in the order it appears in the documents array."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"submitters": {
|
||||
"type": "array",
|
||||
"description": "The list of submitters for the submission.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"email"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the submitter."
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
"description": "The role name or title of the submitter.",
|
||||
"example": "First Party"
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "The email address of the submitter.",
|
||||
"format": "email",
|
||||
"example": "john.doe@example.com"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"description": "The phone number of the submitter, formatted according to the E.164 standard.",
|
||||
"example": "+1234567890"
|
||||
},
|
||||
"values": {
|
||||
"type": "object",
|
||||
"description": "An object with pre-filled values for the submission. Use field names for keys of the object. For more configurations see `fields` param."
|
||||
},
|
||||
"external_id": {
|
||||
"type": "string",
|
||||
"description": "Your application-specific unique string key to identify this submitter within your app."
|
||||
},
|
||||
"completed": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `true` to mark submitter as completed and auto-signed via API."
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"description": "Metadata object with additional submitter information.",
|
||||
"example": "{ \"customField\": \"value\" }"
|
||||
},
|
||||
"send_email": {
|
||||
"type": "boolean",
|
||||
"description": "Set `false` to disable signature request emails sending only for this submitter.",
|
||||
"default": true
|
||||
},
|
||||
"send_sms": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to send signature request via phone number and SMS.",
|
||||
"default": false
|
||||
},
|
||||
"reply_to": {
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails for this submitter."
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Document field name.",
|
||||
"example": "First Name"
|
||||
},
|
||||
"default_value": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"description": "Default value of the field. Use base64 encoded file or a public URL to the image file to set default signature or image fields.",
|
||||
"example": "Acme"
|
||||
},
|
||||
"readonly": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make it impossible for the submitter to edit predefined field value.",
|
||||
"default": false
|
||||
},
|
||||
"required": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make the field required."
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Field title displayed to the user instead of the name, shown on the signing form. Supports Markdown."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"font_size": {
|
||||
"type": "integer",
|
||||
"description": "Font size of the field value in pixels.",
|
||||
"example": 12
|
||||
},
|
||||
"font_type": {
|
||||
"type": "string",
|
||||
"description": "Font type of the field value.",
|
||||
"enum": [
|
||||
"bold",
|
||||
"italic",
|
||||
"bold_italic"
|
||||
]
|
||||
},
|
||||
"font": {
|
||||
"type": "string",
|
||||
"description": "Font family of the field value.",
|
||||
"enum": [
|
||||
"Times",
|
||||
"Helvetica",
|
||||
"Courier"
|
||||
]
|
||||
},
|
||||
"color": {
|
||||
"type": "string",
|
||||
"description": "Font color of the field value.",
|
||||
"enum": [
|
||||
"black",
|
||||
"white",
|
||||
"blue"
|
||||
],
|
||||
"default": "black"
|
||||
},
|
||||
"align": {
|
||||
"type": "string",
|
||||
"description": "Horizontal alignment of the field text value.",
|
||||
"enum": [
|
||||
"left",
|
||||
"center",
|
||||
"right"
|
||||
],
|
||||
"default": "left"
|
||||
},
|
||||
"valign": {
|
||||
"type": "string",
|
||||
"description": "Vertical alignment of the field text value.",
|
||||
"enum": [
|
||||
"top",
|
||||
"center",
|
||||
"bottom"
|
||||
],
|
||||
"default": "center"
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"description": "The data format for different field types.<br>- Date field: accepts formats such as DD/MM/YYYY (default: MM/DD/YYYY).<br>- Signature field: accepts drawn, typed, drawn_or_typed (default), or upload.<br>- Number field: accepts currency formats such as usd, eur, gbp.",
|
||||
"example": "DD/MM/YYYY"
|
||||
},
|
||||
"price": {
|
||||
"type": "number",
|
||||
"description": "Price value of the payment field. Only for payment fields.",
|
||||
"example": 99.99
|
||||
},
|
||||
"currency": {
|
||||
"type": "string",
|
||||
"description": "Currency value of the payment field. Only for payment fields.",
|
||||
"enum": [
|
||||
"USD",
|
||||
"EUR",
|
||||
"GBP",
|
||||
"CAD",
|
||||
"AUD"
|
||||
],
|
||||
"default": "USD"
|
||||
},
|
||||
"mask": {
|
||||
"description": "Set `true` to make sensitive data masked on the document.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"roles": {
|
||||
"type": "array",
|
||||
"description": "A list of roles for the submitter. Use this param to merge multiple roles into one submitter.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subject": {
|
||||
"type": "string",
|
||||
"description": "Custom signature request email subject."
|
||||
},
|
||||
"body": {
|
||||
"type": "string",
|
||||
"description": "Custom signature request email body. Can include the following variables: {{submission.name}}, {{submitter.link}}, {{account.name}}."
|
||||
}
|
||||
}
|
||||
},
|
||||
"merge_documents": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to merge the documents into a single PDF file.",
|
||||
"default": false
|
||||
},
|
||||
"remove_tags": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `false` to disable the removal of {{text}} tags from the PDF. This can be used along with transparent text tags for faster and more robust PDF processing.",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
+726
-37
@@ -653,6 +653,15 @@ func main() {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -728,14 +737,45 @@ func main() {
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -1285,10 +1325,6 @@ func main() {
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails."
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"completed": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `true` to mark submitter as completed and auto-signed via API."
|
||||
@@ -1298,6 +1334,15 @@ func main() {
|
||||
"description": "Metadata object with additional submitter information.",
|
||||
"example": "{ \"customField\": \"value\" }"
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -1365,14 +1410,45 @@ func main() {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make the field required."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -2148,6 +2224,46 @@ func main() {
|
||||
"Option B"
|
||||
]
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -2672,7 +2788,7 @@ func main() {
|
||||
|
||||
### Create a submission from PDF
|
||||
|
||||
The API endpoint provides the functionality to create one-off submission request from a PDF or DOCX file. Use <code>{{Field Name;role=Signer1;type=date}}</code> text tags to define fillable fields in the document. See <a href="https://www.docuseal.com/examples/fieldtags.pdf" target="_blank" class="link font-bold">https://www.docuseal.com/examples/fieldtags.pdf</a> for more text tag formats. Or specify the exact pixel coordinates of the document fields using `fields` param.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
The API endpoint provides the functionality to create one-off submission request from a PDF. Use <code>{{Field Name;role=Signer1;type=date}}</code> text tags to define fillable fields in the document. See <a href="https://www.docuseal.com/examples/fieldtags.pdf" target="_blank" class="link font-bold">https://www.docuseal.com/examples/fieldtags.pdf</a> for more text tag formats. Or specify the exact pixel coordinates of the document fields using `fields` param.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
|
||||
|
||||
```go
|
||||
@@ -2973,6 +3089,15 @@ func main() {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
@@ -3035,14 +3160,45 @@ func main() {
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -3411,6 +3567,15 @@ func main() {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
@@ -3473,14 +3638,45 @@ func main() {
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -3811,6 +4007,46 @@ func main() {
|
||||
"Option B"
|
||||
]
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -3927,3 +4163,456 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### Create a submission from DOCX
|
||||
|
||||
The API endpoint provides functionality to create a one-off submission request from a DOCX file with dynamic content variables. Use <code>[[variable_name]]</code> text tags to define dynamic content variables in the document. See <a href="https://www.docuseal.com/examples/demo_template.docx" target="_blank" class="link font-bold">https://www.docuseal.com/examples/demo_template.docx</a> for the specific text variable syntax, including dynamic content tables and list. You can also use the <code>{{signature}}</code> fillable field syntax to define fillable fields, as in a PDF.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"net/http"
|
||||
"io"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
url := "https://api.docuseal.com/submissions/docx"
|
||||
|
||||
payload := strings.NewReader("{\"name\":\"Test Submission Document\",\"variables\":{\"variable_name\":\"value\"},\"documents\":[{\"name\":\"string\",\"file\":\"base64\"}],\"submitters\":[{\"role\":\"First Party\",\"email\":\"john.doe@example.com\"}]}")
|
||||
|
||||
req, _ := http.NewRequest("POST", url, payload)
|
||||
|
||||
req.Header.Add("X-Auth-Token", "API_KEY")
|
||||
req.Header.Add("content-type", "application/json")
|
||||
|
||||
res, _ := http.DefaultClient.Do(req)
|
||||
|
||||
defer res.Body.Close()
|
||||
body, _ := io.ReadAll(res.Body)
|
||||
|
||||
fmt.Println(res)
|
||||
fmt.Println(string(body))
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"security": [
|
||||
{
|
||||
"AuthToken": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Submissions"
|
||||
],
|
||||
"summary": "Create a submission from DOCX",
|
||||
"operationId": "createSubmissionFromDocx",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"documents",
|
||||
"submitters"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the document submission.",
|
||||
"example": "Test Submission Document"
|
||||
},
|
||||
"send_email": {
|
||||
"type": "boolean",
|
||||
"description": "Set `false` to disable signature request emails sending.",
|
||||
"default": true
|
||||
},
|
||||
"send_sms": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to send signature request via phone number and SMS.",
|
||||
"default": false
|
||||
},
|
||||
"variables": {
|
||||
"type": "object",
|
||||
"description": "Dynamic content variables object",
|
||||
"example": {
|
||||
"variable_name": "value"
|
||||
}
|
||||
},
|
||||
"order": {
|
||||
"type": "string",
|
||||
"description": "Pass 'random' to send signature request emails to all parties right away. The order is 'preserved' by default so the second party will receive a signature request email only after the document is signed by the first party.",
|
||||
"default": "preserved",
|
||||
"enum": [
|
||||
"preserved",
|
||||
"random"
|
||||
]
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Specify URL to redirect to after the submission completion."
|
||||
},
|
||||
"bcc_completed": {
|
||||
"type": "string",
|
||||
"description": "Specify BCC address to send signed documents to after the completion."
|
||||
},
|
||||
"reply_to": {
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails."
|
||||
},
|
||||
"expire_at": {
|
||||
"type": "string",
|
||||
"description": "Specify the expiration date and time after which the submission becomes unavailable for signature.",
|
||||
"example": "2024-09-01 12:00:00 UTC"
|
||||
},
|
||||
"template_ids": {
|
||||
"type": "array",
|
||||
"description": "An optional array of template IDs to use in the submission along with the provided documents. This can be used to create multi-document submissions when some of the required documents exist within templates.",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"description": "The ID of the template to use for the submission."
|
||||
}
|
||||
},
|
||||
"documents": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"file"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the document."
|
||||
},
|
||||
"file": {
|
||||
"example": "base64",
|
||||
"type": "string",
|
||||
"format": "base64",
|
||||
"description": "Base64-encoded content of the PDF or DOCX file or downloadable file URL."
|
||||
},
|
||||
"position": {
|
||||
"type": "integer",
|
||||
"description": "Document position in the submission. If not specified, the document will be added in the order it appears in the documents array."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"submitters": {
|
||||
"type": "array",
|
||||
"description": "The list of submitters for the submission.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"email"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the submitter."
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
"description": "The role name or title of the submitter.",
|
||||
"example": "First Party"
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "The email address of the submitter.",
|
||||
"format": "email",
|
||||
"example": "john.doe@example.com"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"description": "The phone number of the submitter, formatted according to the E.164 standard.",
|
||||
"example": "+1234567890"
|
||||
},
|
||||
"values": {
|
||||
"type": "object",
|
||||
"description": "An object with pre-filled values for the submission. Use field names for keys of the object. For more configurations see `fields` param."
|
||||
},
|
||||
"external_id": {
|
||||
"type": "string",
|
||||
"description": "Your application-specific unique string key to identify this submitter within your app."
|
||||
},
|
||||
"completed": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `true` to mark submitter as completed and auto-signed via API."
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"description": "Metadata object with additional submitter information.",
|
||||
"example": "{ \"customField\": \"value\" }"
|
||||
},
|
||||
"send_email": {
|
||||
"type": "boolean",
|
||||
"description": "Set `false` to disable signature request emails sending only for this submitter.",
|
||||
"default": true
|
||||
},
|
||||
"send_sms": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to send signature request via phone number and SMS.",
|
||||
"default": false
|
||||
},
|
||||
"reply_to": {
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails for this submitter."
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Document field name.",
|
||||
"example": "First Name"
|
||||
},
|
||||
"default_value": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"description": "Default value of the field. Use base64 encoded file or a public URL to the image file to set default signature or image fields.",
|
||||
"example": "Acme"
|
||||
},
|
||||
"readonly": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make it impossible for the submitter to edit predefined field value.",
|
||||
"default": false
|
||||
},
|
||||
"required": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make the field required."
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Field title displayed to the user instead of the name, shown on the signing form. Supports Markdown."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"font_size": {
|
||||
"type": "integer",
|
||||
"description": "Font size of the field value in pixels.",
|
||||
"example": 12
|
||||
},
|
||||
"font_type": {
|
||||
"type": "string",
|
||||
"description": "Font type of the field value.",
|
||||
"enum": [
|
||||
"bold",
|
||||
"italic",
|
||||
"bold_italic"
|
||||
]
|
||||
},
|
||||
"font": {
|
||||
"type": "string",
|
||||
"description": "Font family of the field value.",
|
||||
"enum": [
|
||||
"Times",
|
||||
"Helvetica",
|
||||
"Courier"
|
||||
]
|
||||
},
|
||||
"color": {
|
||||
"type": "string",
|
||||
"description": "Font color of the field value.",
|
||||
"enum": [
|
||||
"black",
|
||||
"white",
|
||||
"blue"
|
||||
],
|
||||
"default": "black"
|
||||
},
|
||||
"align": {
|
||||
"type": "string",
|
||||
"description": "Horizontal alignment of the field text value.",
|
||||
"enum": [
|
||||
"left",
|
||||
"center",
|
||||
"right"
|
||||
],
|
||||
"default": "left"
|
||||
},
|
||||
"valign": {
|
||||
"type": "string",
|
||||
"description": "Vertical alignment of the field text value.",
|
||||
"enum": [
|
||||
"top",
|
||||
"center",
|
||||
"bottom"
|
||||
],
|
||||
"default": "center"
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"description": "The data format for different field types.<br>- Date field: accepts formats such as DD/MM/YYYY (default: MM/DD/YYYY).<br>- Signature field: accepts drawn, typed, drawn_or_typed (default), or upload.<br>- Number field: accepts currency formats such as usd, eur, gbp.",
|
||||
"example": "DD/MM/YYYY"
|
||||
},
|
||||
"price": {
|
||||
"type": "number",
|
||||
"description": "Price value of the payment field. Only for payment fields.",
|
||||
"example": 99.99
|
||||
},
|
||||
"currency": {
|
||||
"type": "string",
|
||||
"description": "Currency value of the payment field. Only for payment fields.",
|
||||
"enum": [
|
||||
"USD",
|
||||
"EUR",
|
||||
"GBP",
|
||||
"CAD",
|
||||
"AUD"
|
||||
],
|
||||
"default": "USD"
|
||||
},
|
||||
"mask": {
|
||||
"description": "Set `true` to make sensitive data masked on the document.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"roles": {
|
||||
"type": "array",
|
||||
"description": "A list of roles for the submitter. Use this param to merge multiple roles into one submitter.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subject": {
|
||||
"type": "string",
|
||||
"description": "Custom signature request email subject."
|
||||
},
|
||||
"body": {
|
||||
"type": "string",
|
||||
"description": "Custom signature request email body. Can include the following variables: {{submission.name}}, {{submitter.link}}, {{account.name}}."
|
||||
}
|
||||
}
|
||||
},
|
||||
"merge_documents": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to merge the documents into a single PDF file.",
|
||||
"default": false
|
||||
},
|
||||
"remove_tags": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `false` to disable the removal of {{text}} tags from the PDF. This can be used along with transparent text tags for faster and more robust PDF processing.",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
+702
-37
@@ -517,6 +517,15 @@ HttpResponse<String> response = Unirest.post("https://api.docuseal.com/submissio
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -592,14 +601,45 @@ HttpResponse<String> response = Unirest.post("https://api.docuseal.com/submissio
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -1013,10 +1053,6 @@ HttpResponse<String> response = Unirest.put("https://api.docuseal.com/submitters
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails."
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"completed": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `true` to mark submitter as completed and auto-signed via API."
|
||||
@@ -1026,6 +1062,15 @@ HttpResponse<String> response = Unirest.put("https://api.docuseal.com/submitters
|
||||
"description": "Metadata object with additional submitter information.",
|
||||
"example": "{ \"customField\": \"value\" }"
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -1093,14 +1138,45 @@ HttpResponse<String> response = Unirest.put("https://api.docuseal.com/submitters
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make the field required."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -1758,6 +1834,46 @@ HttpResponse<String> response = Unirest.post("https://api.docuseal.com/templates
|
||||
"Option B"
|
||||
]
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -2234,7 +2350,7 @@ HttpResponse<String> response = Unirest.post("https://api.docuseal.com/templates
|
||||
|
||||
### Create a submission from PDF
|
||||
|
||||
The API endpoint provides the functionality to create one-off submission request from a PDF or DOCX file. Use <code>{{Field Name;role=Signer1;type=date}}</code> text tags to define fillable fields in the document. See <a href="https://www.docuseal.com/examples/fieldtags.pdf" target="_blank" class="link font-bold">https://www.docuseal.com/examples/fieldtags.pdf</a> for more text tag formats. Or specify the exact pixel coordinates of the document fields using `fields` param.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
The API endpoint provides the functionality to create one-off submission request from a PDF. Use <code>{{Field Name;role=Signer1;type=date}}</code> text tags to define fillable fields in the document. See <a href="https://www.docuseal.com/examples/fieldtags.pdf" target="_blank" class="link font-bold">https://www.docuseal.com/examples/fieldtags.pdf</a> for more text tag formats. Or specify the exact pixel coordinates of the document fields using `fields` param.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
|
||||
|
||||
```java
|
||||
@@ -2511,6 +2627,15 @@ HttpResponse<String> response = Unirest.post("https://api.docuseal.com/submissio
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
@@ -2573,14 +2698,45 @@ HttpResponse<String> response = Unirest.post("https://api.docuseal.com/submissio
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -2925,6 +3081,15 @@ HttpResponse<String> response = Unirest.post("https://api.docuseal.com/submissio
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
@@ -2987,14 +3152,45 @@ HttpResponse<String> response = Unirest.post("https://api.docuseal.com/submissio
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -3301,6 +3497,46 @@ HttpResponse<String> response = Unirest.post("https://api.docuseal.com/templates
|
||||
"Option B"
|
||||
]
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -3417,3 +3653,432 @@ HttpResponse<String> response = Unirest.post("https://api.docuseal.com/templates
|
||||
}
|
||||
```
|
||||
|
||||
### Create a submission from DOCX
|
||||
|
||||
The API endpoint provides functionality to create a one-off submission request from a DOCX file with dynamic content variables. Use <code>[[variable_name]]</code> text tags to define dynamic content variables in the document. See <a href="https://www.docuseal.com/examples/demo_template.docx" target="_blank" class="link font-bold">https://www.docuseal.com/examples/demo_template.docx</a> for the specific text variable syntax, including dynamic content tables and list. You can also use the <code>{{signature}}</code> fillable field syntax to define fillable fields, as in a PDF.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
|
||||
```java
|
||||
HttpResponse<String> response = Unirest.post("https://api.docuseal.com/submissions/docx")
|
||||
.header("X-Auth-Token", "API_KEY")
|
||||
.header("content-type", "application/json")
|
||||
.body("{\"name\":\"Test Submission Document\",\"variables\":{\"variable_name\":\"value\"},\"documents\":[{\"name\":\"string\",\"file\":\"base64\"}],\"submitters\":[{\"role\":\"First Party\",\"email\":\"john.doe@example.com\"}]}")
|
||||
.asString();
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"security": [
|
||||
{
|
||||
"AuthToken": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Submissions"
|
||||
],
|
||||
"summary": "Create a submission from DOCX",
|
||||
"operationId": "createSubmissionFromDocx",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"documents",
|
||||
"submitters"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the document submission.",
|
||||
"example": "Test Submission Document"
|
||||
},
|
||||
"send_email": {
|
||||
"type": "boolean",
|
||||
"description": "Set `false` to disable signature request emails sending.",
|
||||
"default": true
|
||||
},
|
||||
"send_sms": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to send signature request via phone number and SMS.",
|
||||
"default": false
|
||||
},
|
||||
"variables": {
|
||||
"type": "object",
|
||||
"description": "Dynamic content variables object",
|
||||
"example": {
|
||||
"variable_name": "value"
|
||||
}
|
||||
},
|
||||
"order": {
|
||||
"type": "string",
|
||||
"description": "Pass 'random' to send signature request emails to all parties right away. The order is 'preserved' by default so the second party will receive a signature request email only after the document is signed by the first party.",
|
||||
"default": "preserved",
|
||||
"enum": [
|
||||
"preserved",
|
||||
"random"
|
||||
]
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Specify URL to redirect to after the submission completion."
|
||||
},
|
||||
"bcc_completed": {
|
||||
"type": "string",
|
||||
"description": "Specify BCC address to send signed documents to after the completion."
|
||||
},
|
||||
"reply_to": {
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails."
|
||||
},
|
||||
"expire_at": {
|
||||
"type": "string",
|
||||
"description": "Specify the expiration date and time after which the submission becomes unavailable for signature.",
|
||||
"example": "2024-09-01 12:00:00 UTC"
|
||||
},
|
||||
"template_ids": {
|
||||
"type": "array",
|
||||
"description": "An optional array of template IDs to use in the submission along with the provided documents. This can be used to create multi-document submissions when some of the required documents exist within templates.",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"description": "The ID of the template to use for the submission."
|
||||
}
|
||||
},
|
||||
"documents": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"file"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the document."
|
||||
},
|
||||
"file": {
|
||||
"example": "base64",
|
||||
"type": "string",
|
||||
"format": "base64",
|
||||
"description": "Base64-encoded content of the PDF or DOCX file or downloadable file URL."
|
||||
},
|
||||
"position": {
|
||||
"type": "integer",
|
||||
"description": "Document position in the submission. If not specified, the document will be added in the order it appears in the documents array."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"submitters": {
|
||||
"type": "array",
|
||||
"description": "The list of submitters for the submission.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"email"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the submitter."
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
"description": "The role name or title of the submitter.",
|
||||
"example": "First Party"
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "The email address of the submitter.",
|
||||
"format": "email",
|
||||
"example": "john.doe@example.com"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"description": "The phone number of the submitter, formatted according to the E.164 standard.",
|
||||
"example": "+1234567890"
|
||||
},
|
||||
"values": {
|
||||
"type": "object",
|
||||
"description": "An object with pre-filled values for the submission. Use field names for keys of the object. For more configurations see `fields` param."
|
||||
},
|
||||
"external_id": {
|
||||
"type": "string",
|
||||
"description": "Your application-specific unique string key to identify this submitter within your app."
|
||||
},
|
||||
"completed": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `true` to mark submitter as completed and auto-signed via API."
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"description": "Metadata object with additional submitter information.",
|
||||
"example": "{ \"customField\": \"value\" }"
|
||||
},
|
||||
"send_email": {
|
||||
"type": "boolean",
|
||||
"description": "Set `false` to disable signature request emails sending only for this submitter.",
|
||||
"default": true
|
||||
},
|
||||
"send_sms": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to send signature request via phone number and SMS.",
|
||||
"default": false
|
||||
},
|
||||
"reply_to": {
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails for this submitter."
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Document field name.",
|
||||
"example": "First Name"
|
||||
},
|
||||
"default_value": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"description": "Default value of the field. Use base64 encoded file or a public URL to the image file to set default signature or image fields.",
|
||||
"example": "Acme"
|
||||
},
|
||||
"readonly": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make it impossible for the submitter to edit predefined field value.",
|
||||
"default": false
|
||||
},
|
||||
"required": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make the field required."
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Field title displayed to the user instead of the name, shown on the signing form. Supports Markdown."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"font_size": {
|
||||
"type": "integer",
|
||||
"description": "Font size of the field value in pixels.",
|
||||
"example": 12
|
||||
},
|
||||
"font_type": {
|
||||
"type": "string",
|
||||
"description": "Font type of the field value.",
|
||||
"enum": [
|
||||
"bold",
|
||||
"italic",
|
||||
"bold_italic"
|
||||
]
|
||||
},
|
||||
"font": {
|
||||
"type": "string",
|
||||
"description": "Font family of the field value.",
|
||||
"enum": [
|
||||
"Times",
|
||||
"Helvetica",
|
||||
"Courier"
|
||||
]
|
||||
},
|
||||
"color": {
|
||||
"type": "string",
|
||||
"description": "Font color of the field value.",
|
||||
"enum": [
|
||||
"black",
|
||||
"white",
|
||||
"blue"
|
||||
],
|
||||
"default": "black"
|
||||
},
|
||||
"align": {
|
||||
"type": "string",
|
||||
"description": "Horizontal alignment of the field text value.",
|
||||
"enum": [
|
||||
"left",
|
||||
"center",
|
||||
"right"
|
||||
],
|
||||
"default": "left"
|
||||
},
|
||||
"valign": {
|
||||
"type": "string",
|
||||
"description": "Vertical alignment of the field text value.",
|
||||
"enum": [
|
||||
"top",
|
||||
"center",
|
||||
"bottom"
|
||||
],
|
||||
"default": "center"
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"description": "The data format for different field types.<br>- Date field: accepts formats such as DD/MM/YYYY (default: MM/DD/YYYY).<br>- Signature field: accepts drawn, typed, drawn_or_typed (default), or upload.<br>- Number field: accepts currency formats such as usd, eur, gbp.",
|
||||
"example": "DD/MM/YYYY"
|
||||
},
|
||||
"price": {
|
||||
"type": "number",
|
||||
"description": "Price value of the payment field. Only for payment fields.",
|
||||
"example": 99.99
|
||||
},
|
||||
"currency": {
|
||||
"type": "string",
|
||||
"description": "Currency value of the payment field. Only for payment fields.",
|
||||
"enum": [
|
||||
"USD",
|
||||
"EUR",
|
||||
"GBP",
|
||||
"CAD",
|
||||
"AUD"
|
||||
],
|
||||
"default": "USD"
|
||||
},
|
||||
"mask": {
|
||||
"description": "Set `true` to make sensitive data masked on the document.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"roles": {
|
||||
"type": "array",
|
||||
"description": "A list of roles for the submitter. Use this param to merge multiple roles into one submitter.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subject": {
|
||||
"type": "string",
|
||||
"description": "Custom signature request email subject."
|
||||
},
|
||||
"body": {
|
||||
"type": "string",
|
||||
"description": "Custom signature request email body. Can include the following variables: {{submission.name}}, {{submitter.link}}, {{account.name}}."
|
||||
}
|
||||
}
|
||||
},
|
||||
"merge_documents": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to merge the documents into a single PDF file.",
|
||||
"default": false
|
||||
},
|
||||
"remove_tags": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `false` to disable the removal of {{text}} tags from the PDF. This can be used along with transparent text tags for faster and more robust PDF processing.",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
+719
-37
@@ -537,6 +537,15 @@ const submission = await docuseal.createSubmission({
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -612,14 +621,45 @@ const submission = await docuseal.createSubmission({
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -1052,10 +1092,6 @@ const submitter = await docuseal.updateSubmitter(500001, {
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails."
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"completed": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `true` to mark submitter as completed and auto-signed via API."
|
||||
@@ -1065,6 +1101,15 @@ const submitter = await docuseal.updateSubmitter(500001, {
|
||||
"description": "Metadata object with additional submitter information.",
|
||||
"example": "{ \"customField\": \"value\" }"
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -1132,14 +1177,45 @@ const submitter = await docuseal.updateSubmitter(500001, {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make the field required."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -1826,6 +1902,46 @@ const template = await docuseal.createTemplateFromDocx({
|
||||
"Option B"
|
||||
]
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -2330,7 +2446,7 @@ const template = await docuseal.mergeTemplates({
|
||||
|
||||
### Create a submission from PDF
|
||||
|
||||
The API endpoint provides the functionality to create one-off submission request from a PDF or DOCX file. Use <code>{{Field Name;role=Signer1;type=date}}</code> text tags to define fillable fields in the document. See <a href="https://www.docuseal.com/examples/fieldtags.pdf" target="_blank" class="link font-bold">https://www.docuseal.com/examples/fieldtags.pdf</a> for more text tag formats. Or specify the exact pixel coordinates of the document fields using `fields` param.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
The API endpoint provides the functionality to create one-off submission request from a PDF. Use <code>{{Field Name;role=Signer1;type=date}}</code> text tags to define fillable fields in the document. See <a href="https://www.docuseal.com/examples/fieldtags.pdf" target="_blank" class="link font-bold">https://www.docuseal.com/examples/fieldtags.pdf</a> for more text tag formats. Or specify the exact pixel coordinates of the document fields using `fields` param.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
|
||||
|
||||
```javascript
|
||||
@@ -2635,6 +2751,15 @@ const submission = await docuseal.createSubmissionFromPdf({
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
@@ -2697,14 +2822,45 @@ const submission = await docuseal.createSubmissionFromPdf({
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -3071,6 +3227,15 @@ and typesetting industry</p>
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
@@ -3133,14 +3298,45 @@ and typesetting industry</p>
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -3469,6 +3665,46 @@ const template = await docuseal.createTemplateFromPdf({
|
||||
"Option B"
|
||||
]
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -3585,3 +3821,449 @@ const template = await docuseal.createTemplateFromPdf({
|
||||
}
|
||||
```
|
||||
|
||||
### Create a submission from DOCX
|
||||
|
||||
The API endpoint provides functionality to create a one-off submission request from a DOCX file with dynamic content variables. Use <code>[[variable_name]]</code> text tags to define dynamic content variables in the document. See <a href="https://www.docuseal.com/examples/demo_template.docx" target="_blank" class="link font-bold">https://www.docuseal.com/examples/demo_template.docx</a> for the specific text variable syntax, including dynamic content tables and list. You can also use the <code>{{signature}}</code> fillable field syntax to define fillable fields, as in a PDF.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
|
||||
```javascript
|
||||
const docuseal = require("@docuseal/api");
|
||||
|
||||
docuseal.configure({ key: "API_KEY", url: "https://api.docuseal.com" });
|
||||
|
||||
const submission = await docuseal.createSubmissionFromDocx({
|
||||
name: "Test Submission Document",
|
||||
variables: {
|
||||
variable_name: "value"
|
||||
},
|
||||
documents: [
|
||||
{
|
||||
name: "string",
|
||||
file: "base64"
|
||||
}
|
||||
],
|
||||
submitters: [
|
||||
{
|
||||
role: "First Party",
|
||||
email: "john.doe@example.com"
|
||||
}
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"security": [
|
||||
{
|
||||
"AuthToken": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Submissions"
|
||||
],
|
||||
"summary": "Create a submission from DOCX",
|
||||
"operationId": "createSubmissionFromDocx",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"documents",
|
||||
"submitters"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the document submission.",
|
||||
"example": "Test Submission Document"
|
||||
},
|
||||
"send_email": {
|
||||
"type": "boolean",
|
||||
"description": "Set `false` to disable signature request emails sending.",
|
||||
"default": true
|
||||
},
|
||||
"send_sms": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to send signature request via phone number and SMS.",
|
||||
"default": false
|
||||
},
|
||||
"variables": {
|
||||
"type": "object",
|
||||
"description": "Dynamic content variables object",
|
||||
"example": {
|
||||
"variable_name": "value"
|
||||
}
|
||||
},
|
||||
"order": {
|
||||
"type": "string",
|
||||
"description": "Pass 'random' to send signature request emails to all parties right away. The order is 'preserved' by default so the second party will receive a signature request email only after the document is signed by the first party.",
|
||||
"default": "preserved",
|
||||
"enum": [
|
||||
"preserved",
|
||||
"random"
|
||||
]
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Specify URL to redirect to after the submission completion."
|
||||
},
|
||||
"bcc_completed": {
|
||||
"type": "string",
|
||||
"description": "Specify BCC address to send signed documents to after the completion."
|
||||
},
|
||||
"reply_to": {
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails."
|
||||
},
|
||||
"expire_at": {
|
||||
"type": "string",
|
||||
"description": "Specify the expiration date and time after which the submission becomes unavailable for signature.",
|
||||
"example": "2024-09-01 12:00:00 UTC"
|
||||
},
|
||||
"template_ids": {
|
||||
"type": "array",
|
||||
"description": "An optional array of template IDs to use in the submission along with the provided documents. This can be used to create multi-document submissions when some of the required documents exist within templates.",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"description": "The ID of the template to use for the submission."
|
||||
}
|
||||
},
|
||||
"documents": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"file"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the document."
|
||||
},
|
||||
"file": {
|
||||
"example": "base64",
|
||||
"type": "string",
|
||||
"format": "base64",
|
||||
"description": "Base64-encoded content of the PDF or DOCX file or downloadable file URL."
|
||||
},
|
||||
"position": {
|
||||
"type": "integer",
|
||||
"description": "Document position in the submission. If not specified, the document will be added in the order it appears in the documents array."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"submitters": {
|
||||
"type": "array",
|
||||
"description": "The list of submitters for the submission.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"email"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the submitter."
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
"description": "The role name or title of the submitter.",
|
||||
"example": "First Party"
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "The email address of the submitter.",
|
||||
"format": "email",
|
||||
"example": "john.doe@example.com"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"description": "The phone number of the submitter, formatted according to the E.164 standard.",
|
||||
"example": "+1234567890"
|
||||
},
|
||||
"values": {
|
||||
"type": "object",
|
||||
"description": "An object with pre-filled values for the submission. Use field names for keys of the object. For more configurations see `fields` param."
|
||||
},
|
||||
"external_id": {
|
||||
"type": "string",
|
||||
"description": "Your application-specific unique string key to identify this submitter within your app."
|
||||
},
|
||||
"completed": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `true` to mark submitter as completed and auto-signed via API."
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"description": "Metadata object with additional submitter information.",
|
||||
"example": "{ \"customField\": \"value\" }"
|
||||
},
|
||||
"send_email": {
|
||||
"type": "boolean",
|
||||
"description": "Set `false` to disable signature request emails sending only for this submitter.",
|
||||
"default": true
|
||||
},
|
||||
"send_sms": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to send signature request via phone number and SMS.",
|
||||
"default": false
|
||||
},
|
||||
"reply_to": {
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails for this submitter."
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Document field name.",
|
||||
"example": "First Name"
|
||||
},
|
||||
"default_value": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"description": "Default value of the field. Use base64 encoded file or a public URL to the image file to set default signature or image fields.",
|
||||
"example": "Acme"
|
||||
},
|
||||
"readonly": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make it impossible for the submitter to edit predefined field value.",
|
||||
"default": false
|
||||
},
|
||||
"required": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make the field required."
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Field title displayed to the user instead of the name, shown on the signing form. Supports Markdown."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"font_size": {
|
||||
"type": "integer",
|
||||
"description": "Font size of the field value in pixels.",
|
||||
"example": 12
|
||||
},
|
||||
"font_type": {
|
||||
"type": "string",
|
||||
"description": "Font type of the field value.",
|
||||
"enum": [
|
||||
"bold",
|
||||
"italic",
|
||||
"bold_italic"
|
||||
]
|
||||
},
|
||||
"font": {
|
||||
"type": "string",
|
||||
"description": "Font family of the field value.",
|
||||
"enum": [
|
||||
"Times",
|
||||
"Helvetica",
|
||||
"Courier"
|
||||
]
|
||||
},
|
||||
"color": {
|
||||
"type": "string",
|
||||
"description": "Font color of the field value.",
|
||||
"enum": [
|
||||
"black",
|
||||
"white",
|
||||
"blue"
|
||||
],
|
||||
"default": "black"
|
||||
},
|
||||
"align": {
|
||||
"type": "string",
|
||||
"description": "Horizontal alignment of the field text value.",
|
||||
"enum": [
|
||||
"left",
|
||||
"center",
|
||||
"right"
|
||||
],
|
||||
"default": "left"
|
||||
},
|
||||
"valign": {
|
||||
"type": "string",
|
||||
"description": "Vertical alignment of the field text value.",
|
||||
"enum": [
|
||||
"top",
|
||||
"center",
|
||||
"bottom"
|
||||
],
|
||||
"default": "center"
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"description": "The data format for different field types.<br>- Date field: accepts formats such as DD/MM/YYYY (default: MM/DD/YYYY).<br>- Signature field: accepts drawn, typed, drawn_or_typed (default), or upload.<br>- Number field: accepts currency formats such as usd, eur, gbp.",
|
||||
"example": "DD/MM/YYYY"
|
||||
},
|
||||
"price": {
|
||||
"type": "number",
|
||||
"description": "Price value of the payment field. Only for payment fields.",
|
||||
"example": 99.99
|
||||
},
|
||||
"currency": {
|
||||
"type": "string",
|
||||
"description": "Currency value of the payment field. Only for payment fields.",
|
||||
"enum": [
|
||||
"USD",
|
||||
"EUR",
|
||||
"GBP",
|
||||
"CAD",
|
||||
"AUD"
|
||||
],
|
||||
"default": "USD"
|
||||
},
|
||||
"mask": {
|
||||
"description": "Set `true` to make sensitive data masked on the document.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"roles": {
|
||||
"type": "array",
|
||||
"description": "A list of roles for the submitter. Use this param to merge multiple roles into one submitter.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subject": {
|
||||
"type": "string",
|
||||
"description": "Custom signature request email subject."
|
||||
},
|
||||
"body": {
|
||||
"type": "string",
|
||||
"description": "Custom signature request email body. Can include the following variables: {{submission.name}}, {{submitter.link}}, {{account.name}}."
|
||||
}
|
||||
}
|
||||
},
|
||||
"merge_documents": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to merge the documents into a single PDF file.",
|
||||
"default": false
|
||||
},
|
||||
"remove_tags": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `false` to disable the removal of {{text}} tags from the PDF. This can be used along with transparent text tags for faster and more robust PDF processing.",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
+725
-37
@@ -569,6 +569,15 @@ const submitters = await resp.json();
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -644,14 +653,45 @@ const submitters = await resp.json();
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -1116,10 +1156,6 @@ const submitter = await resp.json();
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails."
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"completed": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `true` to mark submitter as completed and auto-signed via API."
|
||||
@@ -1129,6 +1165,15 @@ const submitter = await resp.json();
|
||||
"description": "Metadata object with additional submitter information.",
|
||||
"example": "{ \"customField\": \"value\" }"
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -1196,14 +1241,45 @@ const submitter = await resp.json();
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make the field required."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -1919,6 +1995,46 @@ const template = await resp.json();
|
||||
"Option B"
|
||||
]
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -2435,7 +2551,7 @@ const template = await resp.json();
|
||||
|
||||
### Create a submission from PDF
|
||||
|
||||
The API endpoint provides the functionality to create one-off submission request from a PDF or DOCX file. Use <code>{{Field Name;role=Signer1;type=date}}</code> text tags to define fillable fields in the document. See <a href="https://www.docuseal.com/examples/fieldtags.pdf" target="_blank" class="link font-bold">https://www.docuseal.com/examples/fieldtags.pdf</a> for more text tag formats. Or specify the exact pixel coordinates of the document fields using `fields` param.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
The API endpoint provides the functionality to create one-off submission request from a PDF. Use <code>{{Field Name;role=Signer1;type=date}}</code> text tags to define fillable fields in the document. See <a href="https://www.docuseal.com/examples/fieldtags.pdf" target="_blank" class="link font-bold">https://www.docuseal.com/examples/fieldtags.pdf</a> for more text tag formats. Or specify the exact pixel coordinates of the document fields using `fields` param.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
|
||||
|
||||
```nodejs
|
||||
@@ -2746,6 +2862,15 @@ const submission = await resp.json();
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
@@ -2808,14 +2933,45 @@ const submission = await resp.json();
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -3188,6 +3344,15 @@ const submission = await resp.json();
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
@@ -3250,14 +3415,45 @@ const submission = await resp.json();
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -3592,6 +3788,46 @@ const template = await resp.json();
|
||||
"Option B"
|
||||
]
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -3708,3 +3944,455 @@ const template = await resp.json();
|
||||
}
|
||||
```
|
||||
|
||||
### Create a submission from DOCX
|
||||
|
||||
The API endpoint provides functionality to create a one-off submission request from a DOCX file with dynamic content variables. Use <code>[[variable_name]]</code> text tags to define dynamic content variables in the document. See <a href="https://www.docuseal.com/examples/demo_template.docx" target="_blank" class="link font-bold">https://www.docuseal.com/examples/demo_template.docx</a> for the specific text variable syntax, including dynamic content tables and list. You can also use the <code>{{signature}}</code> fillable field syntax to define fillable fields, as in a PDF.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
|
||||
```nodejs
|
||||
const fetch = require("node-fetch");
|
||||
|
||||
const resp = await fetch("https://api.docuseal.com/submissions/docx", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"X-Auth-Token": "API_KEY"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: "Test Submission Document",
|
||||
variables: {
|
||||
variable_name: "value"
|
||||
},
|
||||
documents: [
|
||||
{
|
||||
name: "string",
|
||||
file: "base64"
|
||||
}
|
||||
],
|
||||
submitters: [
|
||||
{
|
||||
role: "First Party",
|
||||
email: "john.doe@example.com"
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
||||
|
||||
const submitters = await resp.json();
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"security": [
|
||||
{
|
||||
"AuthToken": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Submissions"
|
||||
],
|
||||
"summary": "Create a submission from DOCX",
|
||||
"operationId": "createSubmissionFromDocx",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"documents",
|
||||
"submitters"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the document submission.",
|
||||
"example": "Test Submission Document"
|
||||
},
|
||||
"send_email": {
|
||||
"type": "boolean",
|
||||
"description": "Set `false` to disable signature request emails sending.",
|
||||
"default": true
|
||||
},
|
||||
"send_sms": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to send signature request via phone number and SMS.",
|
||||
"default": false
|
||||
},
|
||||
"variables": {
|
||||
"type": "object",
|
||||
"description": "Dynamic content variables object",
|
||||
"example": {
|
||||
"variable_name": "value"
|
||||
}
|
||||
},
|
||||
"order": {
|
||||
"type": "string",
|
||||
"description": "Pass 'random' to send signature request emails to all parties right away. The order is 'preserved' by default so the second party will receive a signature request email only after the document is signed by the first party.",
|
||||
"default": "preserved",
|
||||
"enum": [
|
||||
"preserved",
|
||||
"random"
|
||||
]
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Specify URL to redirect to after the submission completion."
|
||||
},
|
||||
"bcc_completed": {
|
||||
"type": "string",
|
||||
"description": "Specify BCC address to send signed documents to after the completion."
|
||||
},
|
||||
"reply_to": {
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails."
|
||||
},
|
||||
"expire_at": {
|
||||
"type": "string",
|
||||
"description": "Specify the expiration date and time after which the submission becomes unavailable for signature.",
|
||||
"example": "2024-09-01 12:00:00 UTC"
|
||||
},
|
||||
"template_ids": {
|
||||
"type": "array",
|
||||
"description": "An optional array of template IDs to use in the submission along with the provided documents. This can be used to create multi-document submissions when some of the required documents exist within templates.",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"description": "The ID of the template to use for the submission."
|
||||
}
|
||||
},
|
||||
"documents": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"file"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the document."
|
||||
},
|
||||
"file": {
|
||||
"example": "base64",
|
||||
"type": "string",
|
||||
"format": "base64",
|
||||
"description": "Base64-encoded content of the PDF or DOCX file or downloadable file URL."
|
||||
},
|
||||
"position": {
|
||||
"type": "integer",
|
||||
"description": "Document position in the submission. If not specified, the document will be added in the order it appears in the documents array."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"submitters": {
|
||||
"type": "array",
|
||||
"description": "The list of submitters for the submission.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"email"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the submitter."
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
"description": "The role name or title of the submitter.",
|
||||
"example": "First Party"
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "The email address of the submitter.",
|
||||
"format": "email",
|
||||
"example": "john.doe@example.com"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"description": "The phone number of the submitter, formatted according to the E.164 standard.",
|
||||
"example": "+1234567890"
|
||||
},
|
||||
"values": {
|
||||
"type": "object",
|
||||
"description": "An object with pre-filled values for the submission. Use field names for keys of the object. For more configurations see `fields` param."
|
||||
},
|
||||
"external_id": {
|
||||
"type": "string",
|
||||
"description": "Your application-specific unique string key to identify this submitter within your app."
|
||||
},
|
||||
"completed": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `true` to mark submitter as completed and auto-signed via API."
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"description": "Metadata object with additional submitter information.",
|
||||
"example": "{ \"customField\": \"value\" }"
|
||||
},
|
||||
"send_email": {
|
||||
"type": "boolean",
|
||||
"description": "Set `false` to disable signature request emails sending only for this submitter.",
|
||||
"default": true
|
||||
},
|
||||
"send_sms": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to send signature request via phone number and SMS.",
|
||||
"default": false
|
||||
},
|
||||
"reply_to": {
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails for this submitter."
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Document field name.",
|
||||
"example": "First Name"
|
||||
},
|
||||
"default_value": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"description": "Default value of the field. Use base64 encoded file or a public URL to the image file to set default signature or image fields.",
|
||||
"example": "Acme"
|
||||
},
|
||||
"readonly": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make it impossible for the submitter to edit predefined field value.",
|
||||
"default": false
|
||||
},
|
||||
"required": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make the field required."
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Field title displayed to the user instead of the name, shown on the signing form. Supports Markdown."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"font_size": {
|
||||
"type": "integer",
|
||||
"description": "Font size of the field value in pixels.",
|
||||
"example": 12
|
||||
},
|
||||
"font_type": {
|
||||
"type": "string",
|
||||
"description": "Font type of the field value.",
|
||||
"enum": [
|
||||
"bold",
|
||||
"italic",
|
||||
"bold_italic"
|
||||
]
|
||||
},
|
||||
"font": {
|
||||
"type": "string",
|
||||
"description": "Font family of the field value.",
|
||||
"enum": [
|
||||
"Times",
|
||||
"Helvetica",
|
||||
"Courier"
|
||||
]
|
||||
},
|
||||
"color": {
|
||||
"type": "string",
|
||||
"description": "Font color of the field value.",
|
||||
"enum": [
|
||||
"black",
|
||||
"white",
|
||||
"blue"
|
||||
],
|
||||
"default": "black"
|
||||
},
|
||||
"align": {
|
||||
"type": "string",
|
||||
"description": "Horizontal alignment of the field text value.",
|
||||
"enum": [
|
||||
"left",
|
||||
"center",
|
||||
"right"
|
||||
],
|
||||
"default": "left"
|
||||
},
|
||||
"valign": {
|
||||
"type": "string",
|
||||
"description": "Vertical alignment of the field text value.",
|
||||
"enum": [
|
||||
"top",
|
||||
"center",
|
||||
"bottom"
|
||||
],
|
||||
"default": "center"
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"description": "The data format for different field types.<br>- Date field: accepts formats such as DD/MM/YYYY (default: MM/DD/YYYY).<br>- Signature field: accepts drawn, typed, drawn_or_typed (default), or upload.<br>- Number field: accepts currency formats such as usd, eur, gbp.",
|
||||
"example": "DD/MM/YYYY"
|
||||
},
|
||||
"price": {
|
||||
"type": "number",
|
||||
"description": "Price value of the payment field. Only for payment fields.",
|
||||
"example": 99.99
|
||||
},
|
||||
"currency": {
|
||||
"type": "string",
|
||||
"description": "Currency value of the payment field. Only for payment fields.",
|
||||
"enum": [
|
||||
"USD",
|
||||
"EUR",
|
||||
"GBP",
|
||||
"CAD",
|
||||
"AUD"
|
||||
],
|
||||
"default": "USD"
|
||||
},
|
||||
"mask": {
|
||||
"description": "Set `true` to make sensitive data masked on the document.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"roles": {
|
||||
"type": "array",
|
||||
"description": "A list of roles for the submitter. Use this param to merge multiple roles into one submitter.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subject": {
|
||||
"type": "string",
|
||||
"description": "Custom signature request email subject."
|
||||
},
|
||||
"body": {
|
||||
"type": "string",
|
||||
"description": "Custom signature request email body. Can include the following variables: {{submission.name}}, {{submitter.link}}, {{account.name}}."
|
||||
}
|
||||
}
|
||||
},
|
||||
"merge_documents": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to merge the documents into a single PDF file.",
|
||||
"default": false
|
||||
},
|
||||
"remove_tags": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `false` to disable the removal of {{text}} tags from the PDF. This can be used along with transparent text tags for faster and more robust PDF processing.",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
+717
-37
@@ -525,6 +525,15 @@ $docuseal->createSubmission([
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -600,14 +609,45 @@ $docuseal->createSubmission([
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -1028,10 +1068,6 @@ $docuseal->updateSubmitter(500001, [
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails."
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"completed": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `true` to mark submitter as completed and auto-signed via API."
|
||||
@@ -1041,6 +1077,15 @@ $docuseal->updateSubmitter(500001, [
|
||||
"description": "Metadata object with additional submitter information.",
|
||||
"example": "{ \"customField\": \"value\" }"
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -1108,14 +1153,45 @@ $docuseal->updateSubmitter(500001, [
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make the field required."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -1792,6 +1868,46 @@ $docuseal->createTemplateFromDocx([
|
||||
"Option B"
|
||||
]
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -2292,7 +2408,7 @@ $docuseal->mergeTemplates([
|
||||
|
||||
### Create a submission from PDF
|
||||
|
||||
The API endpoint provides the functionality to create one-off submission request from a PDF or DOCX file. Use <code>{{Field Name;role=Signer1;type=date}}</code> text tags to define fillable fields in the document. See <a href="https://www.docuseal.com/examples/fieldtags.pdf" target="_blank" class="link font-bold">https://www.docuseal.com/examples/fieldtags.pdf</a> for more text tag formats. Or specify the exact pixel coordinates of the document fields using `fields` param.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
The API endpoint provides the functionality to create one-off submission request from a PDF. Use <code>{{Field Name;role=Signer1;type=date}}</code> text tags to define fillable fields in the document. See <a href="https://www.docuseal.com/examples/fieldtags.pdf" target="_blank" class="link font-bold">https://www.docuseal.com/examples/fieldtags.pdf</a> for more text tag formats. Or specify the exact pixel coordinates of the document fields using `fields` param.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
|
||||
|
||||
```php
|
||||
@@ -2595,6 +2711,15 @@ $docuseal->createSubmissionFromPdf([
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
@@ -2657,14 +2782,45 @@ $docuseal->createSubmissionFromPdf([
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -3029,6 +3185,15 @@ and typesetting industry</p>
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
@@ -3091,14 +3256,45 @@ and typesetting industry</p>
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation_pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"invalid_message": {
|
||||
"type": "string",
|
||||
"description": "A custom message to display on pattern validation failure."
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
@@ -3425,6 +3621,46 @@ $docuseal->createTemplateFromPdf([
|
||||
"Option B"
|
||||
]
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -3541,3 +3777,447 @@ $docuseal->createTemplateFromPdf([
|
||||
}
|
||||
```
|
||||
|
||||
### Create a submission from DOCX
|
||||
|
||||
The API endpoint provides functionality to create a one-off submission request from a DOCX file with dynamic content variables. Use <code>[[variable_name]]</code> text tags to define dynamic content variables in the document. See <a href="https://www.docuseal.com/examples/demo_template.docx" target="_blank" class="link font-bold">https://www.docuseal.com/examples/demo_template.docx</a> for the specific text variable syntax, including dynamic content tables and list. You can also use the <code>{{signature}}</code> fillable field syntax to define fillable fields, as in a PDF.<br><b>Related Guides</b><br><a href="https://www.docuseal.com/guides/use-embedded-text-field-tags-in-the-pdf-to-create-a-fillable-form" class="link">Use embedded text field tags to create a fillable form</a>
|
||||
|
||||
```php
|
||||
$docuseal = new \Docuseal\Api('API_KEY', 'https://api.docuseal.com');
|
||||
|
||||
$docuseal->createSubmissionFromDocx([
|
||||
'name' => 'Test Submission Document',
|
||||
'variables' => [
|
||||
'variable_name' => 'value'
|
||||
],
|
||||
'documents' => [
|
||||
[
|
||||
'name' => 'string',
|
||||
'file' => 'base64'
|
||||
]
|
||||
],
|
||||
'submitters' => [
|
||||
[
|
||||
'role' => 'First Party',
|
||||
'email' => 'john.doe@example.com'
|
||||
]
|
||||
]
|
||||
]);
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"security": [
|
||||
{
|
||||
"AuthToken": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Submissions"
|
||||
],
|
||||
"summary": "Create a submission from DOCX",
|
||||
"operationId": "createSubmissionFromDocx",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"documents",
|
||||
"submitters"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the document submission.",
|
||||
"example": "Test Submission Document"
|
||||
},
|
||||
"send_email": {
|
||||
"type": "boolean",
|
||||
"description": "Set `false` to disable signature request emails sending.",
|
||||
"default": true
|
||||
},
|
||||
"send_sms": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to send signature request via phone number and SMS.",
|
||||
"default": false
|
||||
},
|
||||
"variables": {
|
||||
"type": "object",
|
||||
"description": "Dynamic content variables object",
|
||||
"example": {
|
||||
"variable_name": "value"
|
||||
}
|
||||
},
|
||||
"order": {
|
||||
"type": "string",
|
||||
"description": "Pass 'random' to send signature request emails to all parties right away. The order is 'preserved' by default so the second party will receive a signature request email only after the document is signed by the first party.",
|
||||
"default": "preserved",
|
||||
"enum": [
|
||||
"preserved",
|
||||
"random"
|
||||
]
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Specify URL to redirect to after the submission completion."
|
||||
},
|
||||
"bcc_completed": {
|
||||
"type": "string",
|
||||
"description": "Specify BCC address to send signed documents to after the completion."
|
||||
},
|
||||
"reply_to": {
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails."
|
||||
},
|
||||
"expire_at": {
|
||||
"type": "string",
|
||||
"description": "Specify the expiration date and time after which the submission becomes unavailable for signature.",
|
||||
"example": "2024-09-01 12:00:00 UTC"
|
||||
},
|
||||
"template_ids": {
|
||||
"type": "array",
|
||||
"description": "An optional array of template IDs to use in the submission along with the provided documents. This can be used to create multi-document submissions when some of the required documents exist within templates.",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"description": "The ID of the template to use for the submission."
|
||||
}
|
||||
},
|
||||
"documents": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"file"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Name of the document."
|
||||
},
|
||||
"file": {
|
||||
"example": "base64",
|
||||
"type": "string",
|
||||
"format": "base64",
|
||||
"description": "Base64-encoded content of the PDF or DOCX file or downloadable file URL."
|
||||
},
|
||||
"position": {
|
||||
"type": "integer",
|
||||
"description": "Document position in the submission. If not specified, the document will be added in the order it appears in the documents array."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"submitters": {
|
||||
"type": "array",
|
||||
"description": "The list of submitters for the submission.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"email"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of the submitter."
|
||||
},
|
||||
"role": {
|
||||
"type": "string",
|
||||
"description": "The role name or title of the submitter.",
|
||||
"example": "First Party"
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"description": "The email address of the submitter.",
|
||||
"format": "email",
|
||||
"example": "john.doe@example.com"
|
||||
},
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"description": "The phone number of the submitter, formatted according to the E.164 standard.",
|
||||
"example": "+1234567890"
|
||||
},
|
||||
"values": {
|
||||
"type": "object",
|
||||
"description": "An object with pre-filled values for the submission. Use field names for keys of the object. For more configurations see `fields` param."
|
||||
},
|
||||
"external_id": {
|
||||
"type": "string",
|
||||
"description": "Your application-specific unique string key to identify this submitter within your app."
|
||||
},
|
||||
"completed": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `true` to mark submitter as completed and auto-signed via API."
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"description": "Metadata object with additional submitter information.",
|
||||
"example": "{ \"customField\": \"value\" }"
|
||||
},
|
||||
"send_email": {
|
||||
"type": "boolean",
|
||||
"description": "Set `false` to disable signature request emails sending only for this submitter.",
|
||||
"default": true
|
||||
},
|
||||
"send_sms": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to send signature request via phone number and SMS.",
|
||||
"default": false
|
||||
},
|
||||
"reply_to": {
|
||||
"type": "string",
|
||||
"description": "Specify Reply-To address to use in the notification emails for this submitter."
|
||||
},
|
||||
"completed_redirect_url": {
|
||||
"type": "string",
|
||||
"description": "Submitter specific URL to redirect to after the submission completion."
|
||||
},
|
||||
"order": {
|
||||
"type": "integer",
|
||||
"description": "The order of the submitter in the workflow (e.g., 0 for the first signer, 1 for the second, etc.). Use the same order number to create order groups. By default, submitters are ordered as in the submitters array."
|
||||
},
|
||||
"require_phone_2fa": {
|
||||
"type": "boolean",
|
||||
"description": "Set to `true` to require phone 2FA verification via a one-time code sent to the phone number in order to access the documents.",
|
||||
"default": false
|
||||
},
|
||||
"fields": {
|
||||
"type": "array",
|
||||
"description": "A list of configurations for document form fields.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "Document field name.",
|
||||
"example": "First Name"
|
||||
},
|
||||
"default_value": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"description": "Default value of the field. Use base64 encoded file or a public URL to the image file to set default signature or image fields.",
|
||||
"example": "Acme"
|
||||
},
|
||||
"readonly": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make it impossible for the submitter to edit predefined field value.",
|
||||
"default": false
|
||||
},
|
||||
"required": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to make the field required."
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Field title displayed to the user instead of the name, shown on the signing form. Supports Markdown."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Field description displayed on the signing form. Supports Markdown."
|
||||
},
|
||||
"validation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"description": "HTML field validation pattern string based on https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern specification.",
|
||||
"example": "[A-Z]{4}"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "A custom error message to display on validation failure."
|
||||
},
|
||||
"min": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Minimum allowed number value or date depending on field type."
|
||||
},
|
||||
"max": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"description": "Maximum allowed number value or date depending on field type."
|
||||
},
|
||||
"step": {
|
||||
"type": "number",
|
||||
"description": "Increment step for number field. Pass 1 to accept only integers, or 0.01 to accept decimal currency."
|
||||
}
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"font_size": {
|
||||
"type": "integer",
|
||||
"description": "Font size of the field value in pixels.",
|
||||
"example": 12
|
||||
},
|
||||
"font_type": {
|
||||
"type": "string",
|
||||
"description": "Font type of the field value.",
|
||||
"enum": [
|
||||
"bold",
|
||||
"italic",
|
||||
"bold_italic"
|
||||
]
|
||||
},
|
||||
"font": {
|
||||
"type": "string",
|
||||
"description": "Font family of the field value.",
|
||||
"enum": [
|
||||
"Times",
|
||||
"Helvetica",
|
||||
"Courier"
|
||||
]
|
||||
},
|
||||
"color": {
|
||||
"type": "string",
|
||||
"description": "Font color of the field value.",
|
||||
"enum": [
|
||||
"black",
|
||||
"white",
|
||||
"blue"
|
||||
],
|
||||
"default": "black"
|
||||
},
|
||||
"align": {
|
||||
"type": "string",
|
||||
"description": "Horizontal alignment of the field text value.",
|
||||
"enum": [
|
||||
"left",
|
||||
"center",
|
||||
"right"
|
||||
],
|
||||
"default": "left"
|
||||
},
|
||||
"valign": {
|
||||
"type": "string",
|
||||
"description": "Vertical alignment of the field text value.",
|
||||
"enum": [
|
||||
"top",
|
||||
"center",
|
||||
"bottom"
|
||||
],
|
||||
"default": "center"
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"description": "The data format for different field types.<br>- Date field: accepts formats such as DD/MM/YYYY (default: MM/DD/YYYY).<br>- Signature field: accepts drawn, typed, drawn_or_typed (default), or upload.<br>- Number field: accepts currency formats such as usd, eur, gbp.",
|
||||
"example": "DD/MM/YYYY"
|
||||
},
|
||||
"price": {
|
||||
"type": "number",
|
||||
"description": "Price value of the payment field. Only for payment fields.",
|
||||
"example": 99.99
|
||||
},
|
||||
"currency": {
|
||||
"type": "string",
|
||||
"description": "Currency value of the payment field. Only for payment fields.",
|
||||
"enum": [
|
||||
"USD",
|
||||
"EUR",
|
||||
"GBP",
|
||||
"CAD",
|
||||
"AUD"
|
||||
],
|
||||
"default": "USD"
|
||||
},
|
||||
"mask": {
|
||||
"description": "Set `true` to make sensitive data masked on the document.",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"default": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"roles": {
|
||||
"type": "array",
|
||||
"description": "A list of roles for the submitter. Use this param to merge multiple roles into one submitter.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"message": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"subject": {
|
||||
"type": "string",
|
||||
"description": "Custom signature request email subject."
|
||||
},
|
||||
"body": {
|
||||
"type": "string",
|
||||
"description": "Custom signature request email body. Can include the following variables: {{submission.name}}, {{submitter.link}}, {{account.name}}."
|
||||
}
|
||||
}
|
||||
},
|
||||
"merge_documents": {
|
||||
"type": "boolean",
|
||||
"description": "Set `true` to merge the documents into a single PDF file.",
|
||||
"default": false
|
||||
},
|
||||
"remove_tags": {
|
||||
"type": "boolean",
|
||||
"description": "Pass `false` to disable the removal of {{text}} tags from the PDF. This can be used along with transparent text tags for faster and more robust PDF processing.",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user