mirror of
https://github.com/docusealco/docuseal
synced 2026-11-05 06:42:32 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94e552d170 | ||
|
|
cf1b0a4c16 | ||
|
|
9aa0a8ecbf | ||
|
|
fd4bef1706 | ||
|
|
d32b0e6d20 | ||
|
|
4a846be214 | ||
|
|
3dd3877ea9 | ||
|
|
b4dba0d809 | ||
|
|
dea80a82d8 | ||
|
|
eefa994724 | ||
|
|
35cce24539 | ||
|
|
e6c8203959 | ||
|
|
9479771fc8 | ||
|
|
711427521c | ||
|
|
5dae742361 | ||
|
|
d8ccd4beee | ||
|
|
c532a0115d | ||
|
|
c9c3364764 | ||
|
|
1ff23d7c40 | ||
|
|
95e9b34033 | ||
|
|
6b42dcf91b | ||
|
|
28962c949b | ||
|
|
4ecbbf8410 | ||
|
|
990b35be18 | ||
|
|
8002764855 | ||
|
|
b80982658c | ||
|
|
443ac23c29 | ||
|
|
37bb987e3e | ||
|
|
c7b08e8d30 | ||
|
|
dd502e8cef | ||
|
|
a554182e57 | ||
|
|
0c039ee64f | ||
|
|
c6b004f107 | ||
|
|
2fcb08d27d | ||
|
|
75fe5ce381 | ||
|
|
fd7d0eaf53 | ||
|
|
7e537e4232 | ||
|
|
a892975010 | ||
|
|
05ec92186b |
No files matched your search
@@ -23,7 +23,6 @@ gem 'image_processing'
|
|||||||
gem 'jwt'
|
gem 'jwt'
|
||||||
gem 'lograge'
|
gem 'lograge'
|
||||||
gem 'mysql2', require: false
|
gem 'mysql2', require: false
|
||||||
gem 'net-smtp', '0.4.0'
|
|
||||||
gem 'oj'
|
gem 'oj'
|
||||||
gem 'pagy'
|
gem 'pagy'
|
||||||
gem 'pg', require: false
|
gem 'pg', require: false
|
||||||
@@ -40,7 +39,7 @@ gem 'ruby-vips'
|
|||||||
gem 'rubyXL'
|
gem 'rubyXL'
|
||||||
gem 'shakapacker'
|
gem 'shakapacker'
|
||||||
gem 'sidekiq'
|
gem 'sidekiq'
|
||||||
gem 'sqlite3', require: false, force_ruby_platform: true
|
gem 'sqlite3', require: false
|
||||||
gem 'strip_attributes'
|
gem 'strip_attributes'
|
||||||
gem 'turbo-rails'
|
gem 'turbo-rails'
|
||||||
gem 'twitter_cldr', require: false
|
gem 'twitter_cldr', require: false
|
||||||
|
|||||||
+174
-171
@@ -1,105 +1,101 @@
|
|||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
actioncable (7.1.3.4)
|
actioncable (7.2.1)
|
||||||
actionpack (= 7.1.3.4)
|
actionpack (= 7.2.1)
|
||||||
activesupport (= 7.1.3.4)
|
activesupport (= 7.2.1)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
websocket-driver (>= 0.6.1)
|
websocket-driver (>= 0.6.1)
|
||||||
zeitwerk (~> 2.6)
|
zeitwerk (~> 2.6)
|
||||||
actionmailbox (7.1.3.4)
|
actionmailbox (7.2.1)
|
||||||
actionpack (= 7.1.3.4)
|
actionpack (= 7.2.1)
|
||||||
activejob (= 7.1.3.4)
|
activejob (= 7.2.1)
|
||||||
activerecord (= 7.1.3.4)
|
activerecord (= 7.2.1)
|
||||||
activestorage (= 7.1.3.4)
|
activestorage (= 7.2.1)
|
||||||
activesupport (= 7.1.3.4)
|
activesupport (= 7.2.1)
|
||||||
mail (>= 2.7.1)
|
mail (>= 2.8.0)
|
||||||
net-imap
|
actionmailer (7.2.1)
|
||||||
net-pop
|
actionpack (= 7.2.1)
|
||||||
net-smtp
|
actionview (= 7.2.1)
|
||||||
actionmailer (7.1.3.4)
|
activejob (= 7.2.1)
|
||||||
actionpack (= 7.1.3.4)
|
activesupport (= 7.2.1)
|
||||||
actionview (= 7.1.3.4)
|
mail (>= 2.8.0)
|
||||||
activejob (= 7.1.3.4)
|
|
||||||
activesupport (= 7.1.3.4)
|
|
||||||
mail (~> 2.5, >= 2.5.4)
|
|
||||||
net-imap
|
|
||||||
net-pop
|
|
||||||
net-smtp
|
|
||||||
rails-dom-testing (~> 2.2)
|
rails-dom-testing (~> 2.2)
|
||||||
actionpack (7.1.3.4)
|
actionpack (7.2.1)
|
||||||
actionview (= 7.1.3.4)
|
actionview (= 7.2.1)
|
||||||
activesupport (= 7.1.3.4)
|
activesupport (= 7.2.1)
|
||||||
nokogiri (>= 1.8.5)
|
nokogiri (>= 1.8.5)
|
||||||
racc
|
racc
|
||||||
rack (>= 2.2.4)
|
rack (>= 2.2.4, < 3.2)
|
||||||
rack-session (>= 1.0.1)
|
rack-session (>= 1.0.1)
|
||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
rails-dom-testing (~> 2.2)
|
rails-dom-testing (~> 2.2)
|
||||||
rails-html-sanitizer (~> 1.6)
|
rails-html-sanitizer (~> 1.6)
|
||||||
actiontext (7.1.3.4)
|
useragent (~> 0.16)
|
||||||
actionpack (= 7.1.3.4)
|
actiontext (7.2.1)
|
||||||
activerecord (= 7.1.3.4)
|
actionpack (= 7.2.1)
|
||||||
activestorage (= 7.1.3.4)
|
activerecord (= 7.2.1)
|
||||||
activesupport (= 7.1.3.4)
|
activestorage (= 7.2.1)
|
||||||
|
activesupport (= 7.2.1)
|
||||||
globalid (>= 0.6.0)
|
globalid (>= 0.6.0)
|
||||||
nokogiri (>= 1.8.5)
|
nokogiri (>= 1.8.5)
|
||||||
actionview (7.1.3.4)
|
actionview (7.2.1)
|
||||||
activesupport (= 7.1.3.4)
|
activesupport (= 7.2.1)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubi (~> 1.11)
|
erubi (~> 1.11)
|
||||||
rails-dom-testing (~> 2.2)
|
rails-dom-testing (~> 2.2)
|
||||||
rails-html-sanitizer (~> 1.6)
|
rails-html-sanitizer (~> 1.6)
|
||||||
activejob (7.1.3.4)
|
activejob (7.2.1)
|
||||||
activesupport (= 7.1.3.4)
|
activesupport (= 7.2.1)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemodel (7.1.3.4)
|
activemodel (7.2.1)
|
||||||
activesupport (= 7.1.3.4)
|
activesupport (= 7.2.1)
|
||||||
activerecord (7.1.3.4)
|
activerecord (7.2.1)
|
||||||
activemodel (= 7.1.3.4)
|
activemodel (= 7.2.1)
|
||||||
activesupport (= 7.1.3.4)
|
activesupport (= 7.2.1)
|
||||||
timeout (>= 0.4.0)
|
timeout (>= 0.4.0)
|
||||||
activestorage (7.1.3.4)
|
activestorage (7.2.1)
|
||||||
actionpack (= 7.1.3.4)
|
actionpack (= 7.2.1)
|
||||||
activejob (= 7.1.3.4)
|
activejob (= 7.2.1)
|
||||||
activerecord (= 7.1.3.4)
|
activerecord (= 7.2.1)
|
||||||
activesupport (= 7.1.3.4)
|
activesupport (= 7.2.1)
|
||||||
marcel (~> 1.0)
|
marcel (~> 1.0)
|
||||||
activesupport (7.1.3.4)
|
activesupport (7.2.1)
|
||||||
base64
|
base64
|
||||||
bigdecimal
|
bigdecimal
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.3.1)
|
||||||
connection_pool (>= 2.2.5)
|
connection_pool (>= 2.2.5)
|
||||||
drb
|
drb
|
||||||
i18n (>= 1.6, < 2)
|
i18n (>= 1.6, < 2)
|
||||||
|
logger (>= 1.4.2)
|
||||||
minitest (>= 5.1)
|
minitest (>= 5.1)
|
||||||
mutex_m
|
securerandom (>= 0.3)
|
||||||
tzinfo (~> 2.0)
|
tzinfo (~> 2.0, >= 2.0.5)
|
||||||
addressable (2.8.6)
|
addressable (2.8.7)
|
||||||
public_suffix (>= 2.0.2, < 6.0)
|
public_suffix (>= 2.0.2, < 7.0)
|
||||||
annotate (3.2.0)
|
annotate (3.2.0)
|
||||||
activerecord (>= 3.2, < 8.0)
|
activerecord (>= 3.2, < 8.0)
|
||||||
rake (>= 10.4, < 14.0)
|
rake (>= 10.4, < 14.0)
|
||||||
arabic-letter-connector (0.1.1)
|
arabic-letter-connector (0.1.1)
|
||||||
ast (2.4.2)
|
ast (2.4.2)
|
||||||
aws-eventstream (1.3.0)
|
aws-eventstream (1.3.0)
|
||||||
aws-partitions (1.913.0)
|
aws-partitions (1.985.0)
|
||||||
aws-sdk-core (3.191.6)
|
aws-sdk-core (3.209.1)
|
||||||
aws-eventstream (~> 1, >= 1.3.0)
|
aws-eventstream (~> 1, >= 1.3.0)
|
||||||
aws-partitions (~> 1, >= 1.651.0)
|
aws-partitions (~> 1, >= 1.651.0)
|
||||||
aws-sigv4 (~> 1.8)
|
aws-sigv4 (~> 1.9)
|
||||||
jmespath (~> 1, >= 1.6.1)
|
jmespath (~> 1, >= 1.6.1)
|
||||||
aws-sdk-kms (1.79.0)
|
aws-sdk-kms (1.94.0)
|
||||||
aws-sdk-core (~> 3, >= 3.191.0)
|
aws-sdk-core (~> 3, >= 3.207.0)
|
||||||
aws-sigv4 (~> 1.1)
|
aws-sigv4 (~> 1.5)
|
||||||
aws-sdk-s3 (1.146.1)
|
aws-sdk-s3 (1.167.0)
|
||||||
aws-sdk-core (~> 3, >= 3.191.0)
|
aws-sdk-core (~> 3, >= 3.207.0)
|
||||||
aws-sdk-kms (~> 1)
|
aws-sdk-kms (~> 1)
|
||||||
aws-sigv4 (~> 1.8)
|
aws-sigv4 (~> 1.5)
|
||||||
aws-sdk-secretsmanager (1.91.0)
|
aws-sdk-secretsmanager (1.108.0)
|
||||||
aws-sdk-core (~> 3, >= 3.191.0)
|
aws-sdk-core (~> 3, >= 3.207.0)
|
||||||
aws-sigv4 (~> 1.1)
|
aws-sigv4 (~> 1.5)
|
||||||
aws-sigv4 (1.8.0)
|
aws-sigv4 (1.10.0)
|
||||||
aws-eventstream (~> 1, >= 1.0.2)
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
azure-storage-blob (2.0.3)
|
azure-storage-blob (2.0.3)
|
||||||
azure-storage-common (~> 2.0)
|
azure-storage-common (~> 2.0)
|
||||||
@@ -120,14 +116,14 @@ GEM
|
|||||||
smart_properties
|
smart_properties
|
||||||
bigdecimal (3.1.8)
|
bigdecimal (3.1.8)
|
||||||
bindex (0.8.1)
|
bindex (0.8.1)
|
||||||
bootsnap (1.18.3)
|
bootsnap (1.18.4)
|
||||||
msgpack (~> 1.2)
|
msgpack (~> 1.2)
|
||||||
builder (3.3.0)
|
builder (3.3.0)
|
||||||
bullet (7.1.6)
|
bullet (7.2.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
uniform_notifier (~> 1.11)
|
uniform_notifier (~> 1.11)
|
||||||
camertron-eprun (1.1.1)
|
camertron-eprun (1.1.1)
|
||||||
cancancan (3.5.0)
|
cancancan (3.6.1)
|
||||||
capybara (3.40.0)
|
capybara (3.40.0)
|
||||||
addressable
|
addressable
|
||||||
matrix
|
matrix
|
||||||
@@ -137,7 +133,8 @@ GEM
|
|||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
regexp_parser (>= 1.5, < 3.0)
|
regexp_parser (>= 1.5, < 3.0)
|
||||||
xpath (~> 3.2)
|
xpath (~> 3.2)
|
||||||
childprocess (5.0.0)
|
childprocess (5.1.0)
|
||||||
|
logger (~> 1.5)
|
||||||
chunky_png (1.4.0)
|
chunky_png (1.4.0)
|
||||||
cldr-plurals-runtime-rb (1.1.0)
|
cldr-plurals-runtime-rb (1.1.0)
|
||||||
cmdparse (3.0.7)
|
cmdparse (3.0.7)
|
||||||
@@ -148,12 +145,12 @@ GEM
|
|||||||
bigdecimal
|
bigdecimal
|
||||||
rexml
|
rexml
|
||||||
crass (1.0.6)
|
crass (1.0.6)
|
||||||
css_parser (1.17.1)
|
css_parser (1.19.0)
|
||||||
addressable
|
addressable
|
||||||
csv (3.3.0)
|
csv (3.3.0)
|
||||||
cuprite (0.15)
|
cuprite (0.15.1)
|
||||||
capybara (~> 3.0)
|
capybara (~> 3.0)
|
||||||
ferrum (~> 0.14.0)
|
ferrum (~> 0.15.0)
|
||||||
date (3.3.4)
|
date (3.3.4)
|
||||||
debug (1.9.2)
|
debug (1.9.2)
|
||||||
irb (~> 1.10)
|
irb (~> 1.10)
|
||||||
@@ -173,26 +170,26 @@ GEM
|
|||||||
diff-lcs (1.5.1)
|
diff-lcs (1.5.1)
|
||||||
digest-crc (0.6.5)
|
digest-crc (0.6.5)
|
||||||
rake (>= 12.0.0, < 14.0.0)
|
rake (>= 12.0.0, < 14.0.0)
|
||||||
docile (1.4.0)
|
docile (1.4.1)
|
||||||
dotenv (3.1.0)
|
dotenv (3.1.4)
|
||||||
drb (2.2.1)
|
drb (2.2.1)
|
||||||
email_typo (0.2.3)
|
email_typo (0.2.3)
|
||||||
erb_lint (0.5.0)
|
erb_lint (0.6.0)
|
||||||
activesupport
|
activesupport
|
||||||
better_html (>= 2.0.1)
|
better_html (>= 2.0.1)
|
||||||
parser (>= 2.7.1.4)
|
parser (>= 2.7.1.4)
|
||||||
rainbow
|
rainbow
|
||||||
rubocop
|
rubocop (>= 1)
|
||||||
smart_properties
|
smart_properties
|
||||||
erubi (1.13.0)
|
erubi (1.13.0)
|
||||||
factory_bot (6.4.6)
|
factory_bot (6.5.0)
|
||||||
activesupport (>= 5.0.0)
|
activesupport (>= 5.0.0)
|
||||||
factory_bot_rails (6.4.3)
|
factory_bot_rails (6.4.3)
|
||||||
factory_bot (~> 6.4)
|
factory_bot (~> 6.4)
|
||||||
railties (>= 5.0.0)
|
railties (>= 5.0.0)
|
||||||
faker (3.3.1)
|
faker (3.4.2)
|
||||||
i18n (>= 1.8.11, < 2)
|
i18n (>= 1.8.11, < 2)
|
||||||
faraday (1.10.3)
|
faraday (1.10.4)
|
||||||
faraday-em_http (~> 1.0)
|
faraday-em_http (~> 1.0)
|
||||||
faraday-em_synchrony (~> 1.0)
|
faraday-em_synchrony (~> 1.0)
|
||||||
faraday-excon (~> 1.1)
|
faraday-excon (~> 1.1)
|
||||||
@@ -212,58 +209,60 @@ GEM
|
|||||||
faraday-httpclient (1.0.1)
|
faraday-httpclient (1.0.1)
|
||||||
faraday-multipart (1.0.4)
|
faraday-multipart (1.0.4)
|
||||||
multipart-post (~> 2)
|
multipart-post (~> 2)
|
||||||
faraday-net_http (1.0.1)
|
faraday-net_http (1.0.2)
|
||||||
faraday-net_http_persistent (1.2.0)
|
faraday-net_http_persistent (1.2.0)
|
||||||
faraday-patron (1.0.0)
|
faraday-patron (1.0.0)
|
||||||
faraday-rack (1.0.0)
|
faraday-rack (1.0.0)
|
||||||
faraday-retry (1.0.3)
|
faraday-retry (1.0.3)
|
||||||
faraday_middleware (1.2.0)
|
faraday_middleware (1.2.1)
|
||||||
faraday (~> 1.0)
|
faraday (~> 1.0)
|
||||||
ferrum (0.14)
|
ferrum (0.15)
|
||||||
addressable (~> 2.5)
|
addressable (~> 2.5)
|
||||||
concurrent-ruby (~> 1.1)
|
concurrent-ruby (~> 1.1)
|
||||||
webrick (~> 1.7)
|
webrick (~> 1.7)
|
||||||
websocket-driver (>= 0.6, < 0.8)
|
websocket-driver (~> 0.7)
|
||||||
ffi (1.16.3)
|
ffi (1.17.0)
|
||||||
|
ffi (1.17.0-aarch64-linux-gnu)
|
||||||
|
ffi (1.17.0-x86_64-linux-gnu)
|
||||||
geom2d (0.4.1)
|
geom2d (0.4.1)
|
||||||
globalid (1.2.1)
|
globalid (1.2.1)
|
||||||
activesupport (>= 6.1)
|
activesupport (>= 6.1)
|
||||||
google-apis-core (0.14.1)
|
google-apis-core (0.15.1)
|
||||||
addressable (~> 2.5, >= 2.5.1)
|
addressable (~> 2.5, >= 2.5.1)
|
||||||
googleauth (~> 1.9)
|
googleauth (~> 1.9)
|
||||||
httpclient (>= 2.8.1, < 3.a)
|
httpclient (>= 2.8.3, < 3.a)
|
||||||
mini_mime (~> 1.0)
|
mini_mime (~> 1.0)
|
||||||
|
mutex_m
|
||||||
representable (~> 3.0)
|
representable (~> 3.0)
|
||||||
retriable (>= 2.0, < 4.a)
|
retriable (>= 2.0, < 4.a)
|
||||||
rexml
|
google-apis-iamcredentials_v1 (0.21.0)
|
||||||
google-apis-iamcredentials_v1 (0.20.0)
|
google-apis-core (>= 0.15.0, < 2.a)
|
||||||
google-apis-core (>= 0.14.0, < 2.a)
|
google-apis-storage_v1 (0.46.0)
|
||||||
google-apis-storage_v1 (0.37.0)
|
google-apis-core (>= 0.15.0, < 2.a)
|
||||||
google-apis-core (>= 0.14.0, < 2.a)
|
google-cloud-core (1.7.1)
|
||||||
google-cloud-core (1.7.0)
|
|
||||||
google-cloud-env (>= 1.0, < 3.a)
|
google-cloud-env (>= 1.0, < 3.a)
|
||||||
google-cloud-errors (~> 1.0)
|
google-cloud-errors (~> 1.0)
|
||||||
google-cloud-env (2.1.1)
|
google-cloud-env (2.2.1)
|
||||||
faraday (>= 1.0, < 3.a)
|
faraday (>= 1.0, < 3.a)
|
||||||
google-cloud-errors (1.4.0)
|
google-cloud-errors (1.4.0)
|
||||||
google-cloud-storage (1.49.0)
|
google-cloud-storage (1.52.0)
|
||||||
addressable (~> 2.8)
|
addressable (~> 2.8)
|
||||||
digest-crc (~> 0.4)
|
digest-crc (~> 0.4)
|
||||||
google-apis-core (~> 0.13)
|
google-apis-core (~> 0.13)
|
||||||
google-apis-iamcredentials_v1 (~> 0.18)
|
google-apis-iamcredentials_v1 (~> 0.18)
|
||||||
google-apis-storage_v1 (~> 0.33)
|
google-apis-storage_v1 (~> 0.38)
|
||||||
google-cloud-core (~> 1.6)
|
google-cloud-core (~> 1.6)
|
||||||
googleauth (~> 1.9)
|
googleauth (~> 1.9)
|
||||||
mini_mime (~> 1.0)
|
mini_mime (~> 1.0)
|
||||||
googleauth (1.11.0)
|
googleauth (1.11.1)
|
||||||
faraday (>= 1.0, < 3.a)
|
faraday (>= 1.0, < 3.a)
|
||||||
google-cloud-env (~> 2.1)
|
google-cloud-env (~> 2.1)
|
||||||
jwt (>= 1.4, < 3.0)
|
jwt (>= 1.4, < 3.0)
|
||||||
multi_json (~> 1.11)
|
multi_json (~> 1.11)
|
||||||
os (>= 0.9, < 2.0)
|
os (>= 0.9, < 2.0)
|
||||||
signet (>= 0.16, < 2.a)
|
signet (>= 0.16, < 2.a)
|
||||||
hashdiff (1.1.0)
|
hashdiff (1.1.1)
|
||||||
hexapdf (0.42.0)
|
hexapdf (0.47.0)
|
||||||
cmdparse (~> 3.0, >= 3.0.3)
|
cmdparse (~> 3.0, >= 3.0.3)
|
||||||
geom2d (~> 0.4, >= 0.4.1)
|
geom2d (~> 0.4, >= 0.4.1)
|
||||||
openssl (>= 2.2.1)
|
openssl (>= 2.2.1)
|
||||||
@@ -271,28 +270,29 @@ GEM
|
|||||||
httpclient (2.8.3)
|
httpclient (2.8.3)
|
||||||
i18n (1.14.6)
|
i18n (1.14.6)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
image_processing (1.12.2)
|
image_processing (1.13.0)
|
||||||
mini_magick (>= 4.9.5, < 5)
|
mini_magick (>= 4.9.5, < 5)
|
||||||
ruby-vips (>= 2.0.17, < 3)
|
ruby-vips (>= 2.0.17, < 3)
|
||||||
io-console (0.7.2)
|
io-console (0.7.2)
|
||||||
irb (1.14.0)
|
irb (1.14.1)
|
||||||
rdoc (>= 4.0.0)
|
rdoc (>= 4.0.0)
|
||||||
reline (>= 0.4.2)
|
reline (>= 0.4.2)
|
||||||
jmespath (1.6.2)
|
jmespath (1.6.2)
|
||||||
json (2.7.2)
|
json (2.7.2)
|
||||||
jwt (2.8.1)
|
jwt (2.9.3)
|
||||||
base64
|
base64
|
||||||
language_server-protocol (3.17.0.3)
|
language_server-protocol (3.17.0.3)
|
||||||
launchy (3.0.0)
|
launchy (3.0.1)
|
||||||
addressable (~> 2.8)
|
addressable (~> 2.8)
|
||||||
childprocess (~> 5.0)
|
childprocess (~> 5.0)
|
||||||
letter_opener (1.10.0)
|
letter_opener (1.10.0)
|
||||||
launchy (>= 2.2, < 4)
|
launchy (>= 2.2, < 4)
|
||||||
letter_opener_web (2.0.0)
|
letter_opener_web (3.0.0)
|
||||||
actionmailer (>= 5.2)
|
actionmailer (>= 6.1)
|
||||||
letter_opener (~> 1.7)
|
letter_opener (~> 1.9)
|
||||||
railties (>= 5.2)
|
railties (>= 6.1)
|
||||||
rexml
|
rexml
|
||||||
|
logger (1.6.1)
|
||||||
lograge (0.14.0)
|
lograge (0.14.0)
|
||||||
actionpack (>= 4)
|
actionpack (>= 4)
|
||||||
activesupport (>= 4)
|
activesupport (>= 4)
|
||||||
@@ -309,25 +309,25 @@ GEM
|
|||||||
marcel (1.0.4)
|
marcel (1.0.4)
|
||||||
matrix (0.4.2)
|
matrix (0.4.2)
|
||||||
method_source (1.1.0)
|
method_source (1.1.0)
|
||||||
mini_magick (4.12.0)
|
mini_magick (4.13.2)
|
||||||
mini_mime (1.1.5)
|
mini_mime (1.1.5)
|
||||||
mini_portile2 (2.8.7)
|
mini_portile2 (2.8.7)
|
||||||
minitest (5.25.1)
|
minitest (5.25.1)
|
||||||
msgpack (1.7.2)
|
msgpack (1.7.3)
|
||||||
multi_json (1.15.0)
|
multi_json (1.15.0)
|
||||||
multipart-post (2.4.0)
|
multipart-post (2.4.1)
|
||||||
mutex_m (0.2.0)
|
mutex_m (0.2.0)
|
||||||
mysql2 (0.5.6)
|
mysql2 (0.5.6)
|
||||||
net-http-persistent (4.0.2)
|
net-http-persistent (4.0.4)
|
||||||
connection_pool (~> 2.2)
|
connection_pool (~> 2.2)
|
||||||
net-imap (0.4.14)
|
net-imap (0.4.16)
|
||||||
date
|
date
|
||||||
net-protocol
|
net-protocol
|
||||||
net-pop (0.1.2)
|
net-pop (0.1.2)
|
||||||
net-protocol
|
net-protocol
|
||||||
net-protocol (0.2.2)
|
net-protocol (0.2.2)
|
||||||
timeout
|
timeout
|
||||||
net-smtp (0.4.0)
|
net-smtp (0.5.0)
|
||||||
net-protocol
|
net-protocol
|
||||||
nio4r (2.7.3)
|
nio4r (2.7.3)
|
||||||
nokogiri (1.16.7)
|
nokogiri (1.16.7)
|
||||||
@@ -337,21 +337,23 @@ GEM
|
|||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.16.7-x86_64-linux)
|
nokogiri (1.16.7-x86_64-linux)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
oj (3.16.3)
|
oj (3.16.6)
|
||||||
bigdecimal (>= 3.0)
|
bigdecimal (>= 3.0)
|
||||||
|
ostruct (>= 0.2)
|
||||||
openssl (3.2.0)
|
openssl (3.2.0)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
os (1.1.4)
|
os (1.1.4)
|
||||||
|
ostruct (0.6.0)
|
||||||
package_json (0.1.0)
|
package_json (0.1.0)
|
||||||
pagy (8.1.2)
|
pagy (9.1.0)
|
||||||
parallel (1.25.1)
|
parallel (1.26.3)
|
||||||
parser (3.3.4.0)
|
parser (3.3.5.0)
|
||||||
ast (~> 2.4.1)
|
ast (~> 2.4.1)
|
||||||
racc
|
racc
|
||||||
pg (1.5.6)
|
pg (1.5.8)
|
||||||
premailer (1.23.0)
|
premailer (1.27.0)
|
||||||
addressable
|
addressable
|
||||||
css_parser (>= 1.12.0)
|
css_parser (>= 1.19.0)
|
||||||
htmlentities (>= 4.0.0)
|
htmlentities (>= 4.0.0)
|
||||||
premailer-rails (1.12.0)
|
premailer-rails (1.12.0)
|
||||||
actionmailer (>= 3)
|
actionmailer (>= 3)
|
||||||
@@ -362,11 +364,11 @@ GEM
|
|||||||
pry (0.14.2)
|
pry (0.14.2)
|
||||||
coderay (~> 1.1)
|
coderay (~> 1.1)
|
||||||
method_source (~> 1.0)
|
method_source (~> 1.0)
|
||||||
pry-rails (0.3.9)
|
pry-rails (0.3.11)
|
||||||
pry (>= 0.10.4)
|
pry (>= 0.13.0)
|
||||||
psych (5.1.2)
|
psych (5.1.2)
|
||||||
stringio
|
stringio
|
||||||
public_suffix (5.0.5)
|
public_suffix (6.0.1)
|
||||||
puma (6.4.3)
|
puma (6.4.3)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
racc (1.8.1)
|
racc (1.8.1)
|
||||||
@@ -380,20 +382,20 @@ GEM
|
|||||||
rackup (2.1.0)
|
rackup (2.1.0)
|
||||||
rack (>= 3)
|
rack (>= 3)
|
||||||
webrick (~> 1.8)
|
webrick (~> 1.8)
|
||||||
rails (7.1.3.4)
|
rails (7.2.1)
|
||||||
actioncable (= 7.1.3.4)
|
actioncable (= 7.2.1)
|
||||||
actionmailbox (= 7.1.3.4)
|
actionmailbox (= 7.2.1)
|
||||||
actionmailer (= 7.1.3.4)
|
actionmailer (= 7.2.1)
|
||||||
actionpack (= 7.1.3.4)
|
actionpack (= 7.2.1)
|
||||||
actiontext (= 7.1.3.4)
|
actiontext (= 7.2.1)
|
||||||
actionview (= 7.1.3.4)
|
actionview (= 7.2.1)
|
||||||
activejob (= 7.1.3.4)
|
activejob (= 7.2.1)
|
||||||
activemodel (= 7.1.3.4)
|
activemodel (= 7.2.1)
|
||||||
activerecord (= 7.1.3.4)
|
activerecord (= 7.2.1)
|
||||||
activestorage (= 7.1.3.4)
|
activestorage (= 7.2.1)
|
||||||
activesupport (= 7.1.3.4)
|
activesupport (= 7.2.1)
|
||||||
bundler (>= 1.15.0)
|
bundler (>= 1.15.0)
|
||||||
railties (= 7.1.3.4)
|
railties (= 7.2.1)
|
||||||
rails-dom-testing (2.2.0)
|
rails-dom-testing (2.2.0)
|
||||||
activesupport (>= 5.0.0)
|
activesupport (>= 5.0.0)
|
||||||
minitest
|
minitest
|
||||||
@@ -408,10 +410,10 @@ GEM
|
|||||||
actionview (> 3.1)
|
actionview (> 3.1)
|
||||||
activesupport (> 3.1)
|
activesupport (> 3.1)
|
||||||
railties (> 3.1)
|
railties (> 3.1)
|
||||||
railties (7.1.3.4)
|
railties (7.2.1)
|
||||||
actionpack (= 7.1.3.4)
|
actionpack (= 7.2.1)
|
||||||
activesupport (= 7.1.3.4)
|
activesupport (= 7.2.1)
|
||||||
irb
|
irb (~> 1.13)
|
||||||
rackup (>= 1.0.0)
|
rackup (>= 1.0.0)
|
||||||
rake (>= 12.2)
|
rake (>= 12.2)
|
||||||
thor (~> 1.0, >= 1.2.2)
|
thor (~> 1.0, >= 1.2.2)
|
||||||
@@ -429,79 +431,80 @@ GEM
|
|||||||
declarative (< 0.1.0)
|
declarative (< 0.1.0)
|
||||||
trailblazer-option (>= 0.1.1, < 0.2.0)
|
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||||
uber (< 0.2.0)
|
uber (< 0.2.0)
|
||||||
request_store (1.6.0)
|
request_store (1.7.0)
|
||||||
rack (>= 1.4)
|
rack (>= 1.4)
|
||||||
responders (3.1.1)
|
responders (3.1.1)
|
||||||
actionpack (>= 5.2)
|
actionpack (>= 5.2)
|
||||||
railties (>= 5.2)
|
railties (>= 5.2)
|
||||||
retriable (3.1.2)
|
retriable (3.1.2)
|
||||||
rexml (3.3.6)
|
rexml (3.3.8)
|
||||||
strscan
|
|
||||||
rotp (6.3.0)
|
rotp (6.3.0)
|
||||||
rqrcode (2.2.0)
|
rqrcode (2.2.0)
|
||||||
chunky_png (~> 1.0)
|
chunky_png (~> 1.0)
|
||||||
rqrcode_core (~> 1.0)
|
rqrcode_core (~> 1.0)
|
||||||
rqrcode_core (1.2.0)
|
rqrcode_core (1.2.0)
|
||||||
rspec-core (3.13.0)
|
rspec-core (3.13.1)
|
||||||
rspec-support (~> 3.13.0)
|
rspec-support (~> 3.13.0)
|
||||||
rspec-expectations (3.13.0)
|
rspec-expectations (3.13.3)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.13.0)
|
rspec-support (~> 3.13.0)
|
||||||
rspec-mocks (3.13.0)
|
rspec-mocks (3.13.2)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.13.0)
|
rspec-support (~> 3.13.0)
|
||||||
rspec-rails (6.1.2)
|
rspec-rails (7.0.1)
|
||||||
actionpack (>= 6.1)
|
actionpack (>= 7.0)
|
||||||
activesupport (>= 6.1)
|
activesupport (>= 7.0)
|
||||||
railties (>= 6.1)
|
railties (>= 7.0)
|
||||||
rspec-core (~> 3.13)
|
rspec-core (~> 3.13)
|
||||||
rspec-expectations (~> 3.13)
|
rspec-expectations (~> 3.13)
|
||||||
rspec-mocks (~> 3.13)
|
rspec-mocks (~> 3.13)
|
||||||
rspec-support (~> 3.13)
|
rspec-support (~> 3.13)
|
||||||
rspec-support (3.13.1)
|
rspec-support (3.13.1)
|
||||||
rubocop (1.65.0)
|
rubocop (1.66.1)
|
||||||
json (~> 2.3)
|
json (~> 2.3)
|
||||||
language_server-protocol (>= 3.17.0)
|
language_server-protocol (>= 3.17.0)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
parser (>= 3.3.0.2)
|
parser (>= 3.3.0.2)
|
||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
regexp_parser (>= 2.4, < 3.0)
|
regexp_parser (>= 2.4, < 3.0)
|
||||||
rexml (>= 3.2.5, < 4.0)
|
rubocop-ast (>= 1.32.2, < 2.0)
|
||||||
rubocop-ast (>= 1.31.1, < 2.0)
|
|
||||||
ruby-progressbar (~> 1.7)
|
ruby-progressbar (~> 1.7)
|
||||||
unicode-display_width (>= 2.4.0, < 3.0)
|
unicode-display_width (>= 2.4.0, < 3.0)
|
||||||
rubocop-ast (1.31.3)
|
rubocop-ast (1.32.3)
|
||||||
parser (>= 3.3.1.0)
|
parser (>= 3.3.1.0)
|
||||||
rubocop-performance (1.21.0)
|
rubocop-performance (1.22.1)
|
||||||
rubocop (>= 1.48.1, < 2.0)
|
rubocop (>= 1.48.1, < 2.0)
|
||||||
rubocop-ast (>= 1.31.1, < 2.0)
|
rubocop-ast (>= 1.31.1, < 2.0)
|
||||||
rubocop-rails (2.24.1)
|
rubocop-rails (2.26.2)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
rack (>= 1.1)
|
rack (>= 1.1)
|
||||||
rubocop (>= 1.33.0, < 2.0)
|
rubocop (>= 1.52.0, < 2.0)
|
||||||
rubocop-ast (>= 1.31.1, < 2.0)
|
rubocop-ast (>= 1.31.1, < 2.0)
|
||||||
rubocop-rspec (3.0.3)
|
rubocop-rspec (3.1.0)
|
||||||
rubocop (~> 1.61)
|
rubocop (~> 1.61)
|
||||||
ruby-progressbar (1.13.0)
|
ruby-progressbar (1.13.0)
|
||||||
ruby-vips (2.2.1)
|
ruby-vips (2.2.2)
|
||||||
ffi (~> 1.12)
|
ffi (~> 1.12)
|
||||||
|
logger
|
||||||
ruby2_keywords (0.0.5)
|
ruby2_keywords (0.0.5)
|
||||||
rubyXL (3.4.27)
|
rubyXL (3.4.27)
|
||||||
nokogiri (>= 1.10.8)
|
nokogiri (>= 1.10.8)
|
||||||
rubyzip (>= 1.3.0)
|
rubyzip (>= 1.3.0)
|
||||||
rubyzip (2.3.2)
|
rubyzip (2.3.2)
|
||||||
|
securerandom (0.3.1)
|
||||||
semantic_range (3.0.0)
|
semantic_range (3.0.0)
|
||||||
shakapacker (8.0.0)
|
shakapacker (8.0.2)
|
||||||
activesupport (>= 5.2)
|
activesupport (>= 5.2)
|
||||||
package_json
|
package_json
|
||||||
rack-proxy (>= 0.6.1)
|
rack-proxy (>= 0.6.1)
|
||||||
railties (>= 5.2)
|
railties (>= 5.2)
|
||||||
semantic_range (>= 2.3.0)
|
semantic_range (>= 2.3.0)
|
||||||
sidekiq (7.2.4)
|
sidekiq (7.3.2)
|
||||||
concurrent-ruby (< 2)
|
concurrent-ruby (< 2)
|
||||||
connection_pool (>= 2.3.0)
|
connection_pool (>= 2.3.0)
|
||||||
|
logger
|
||||||
rack (>= 2.2.4)
|
rack (>= 2.2.4)
|
||||||
redis-client (>= 0.19.0)
|
redis-client (>= 0.22.2)
|
||||||
signet (0.19.0)
|
signet (0.19.0)
|
||||||
addressable (~> 2.8)
|
addressable (~> 2.8)
|
||||||
faraday (>= 0.17.5, < 3.a)
|
faraday (>= 0.17.5, < 3.a)
|
||||||
@@ -511,33 +514,34 @@ GEM
|
|||||||
docile (~> 1.1)
|
docile (~> 1.1)
|
||||||
simplecov-html (~> 0.11)
|
simplecov-html (~> 0.11)
|
||||||
simplecov_json_formatter (~> 0.1)
|
simplecov_json_formatter (~> 0.1)
|
||||||
simplecov-html (0.12.3)
|
simplecov-html (0.13.1)
|
||||||
simplecov_json_formatter (0.1.4)
|
simplecov_json_formatter (0.1.4)
|
||||||
smart_properties (1.17.0)
|
smart_properties (1.17.0)
|
||||||
sqlite3 (1.7.3)
|
sqlite3 (2.1.0)
|
||||||
mini_portile2 (~> 2.8.0)
|
mini_portile2 (~> 2.8.0)
|
||||||
|
sqlite3 (2.1.0-aarch64-linux-gnu)
|
||||||
|
sqlite3 (2.1.0-x86_64-linux-gnu)
|
||||||
stringio (3.1.1)
|
stringio (3.1.1)
|
||||||
strip_attributes (1.13.0)
|
strip_attributes (1.13.0)
|
||||||
activemodel (>= 3.0, < 8.0)
|
activemodel (>= 3.0, < 8.0)
|
||||||
strscan (3.1.0)
|
|
||||||
thor (1.3.2)
|
thor (1.3.2)
|
||||||
timeout (0.4.1)
|
timeout (0.4.1)
|
||||||
trailblazer-option (0.1.2)
|
trailblazer-option (0.1.2)
|
||||||
turbo-rails (2.0.5)
|
turbo-rails (2.0.10)
|
||||||
actionpack (>= 6.0.0)
|
actionpack (>= 6.0.0)
|
||||||
activejob (>= 6.0.0)
|
|
||||||
railties (>= 6.0.0)
|
railties (>= 6.0.0)
|
||||||
twitter_cldr (6.12.0)
|
twitter_cldr (6.12.1)
|
||||||
camertron-eprun
|
camertron-eprun
|
||||||
cldr-plurals-runtime-rb (~> 1.1)
|
cldr-plurals-runtime-rb (~> 1.1)
|
||||||
tzinfo
|
tzinfo
|
||||||
tzinfo (2.0.6)
|
tzinfo (2.0.6)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
tzinfo-data (1.2024.1)
|
tzinfo-data (1.2024.2)
|
||||||
tzinfo (>= 1.0.0)
|
tzinfo (>= 1.0.0)
|
||||||
uber (0.1.0)
|
uber (0.1.0)
|
||||||
unicode-display_width (2.5.0)
|
unicode-display_width (2.6.0)
|
||||||
uniform_notifier (1.16.0)
|
uniform_notifier (1.16.0)
|
||||||
|
useragent (0.16.10)
|
||||||
warden (1.2.9)
|
warden (1.2.9)
|
||||||
rack (>= 2.0.9)
|
rack (>= 2.0.9)
|
||||||
web-console (4.2.1)
|
web-console (4.2.1)
|
||||||
@@ -545,11 +549,11 @@ GEM
|
|||||||
activemodel (>= 6.0.0)
|
activemodel (>= 6.0.0)
|
||||||
bindex (>= 0.4.0)
|
bindex (>= 0.4.0)
|
||||||
railties (>= 6.0.0)
|
railties (>= 6.0.0)
|
||||||
webmock (3.23.0)
|
webmock (3.24.0)
|
||||||
addressable (>= 2.8.0)
|
addressable (>= 2.8.0)
|
||||||
crack (>= 0.3.2)
|
crack (>= 0.3.2)
|
||||||
hashdiff (>= 0.4.0, < 2.0.0)
|
hashdiff (>= 0.4.0, < 2.0.0)
|
||||||
webrick (1.8.1)
|
webrick (1.8.2)
|
||||||
websocket-driver (0.7.6)
|
websocket-driver (0.7.6)
|
||||||
websocket-extensions (>= 0.1.0)
|
websocket-extensions (>= 0.1.0)
|
||||||
websocket-extensions (0.1.5)
|
websocket-extensions (0.1.5)
|
||||||
@@ -592,7 +596,6 @@ DEPENDENCIES
|
|||||||
letter_opener_web
|
letter_opener_web
|
||||||
lograge
|
lograge
|
||||||
mysql2
|
mysql2
|
||||||
net-smtp (= 0.4.0)
|
|
||||||
oj
|
oj
|
||||||
pagy
|
pagy
|
||||||
pg
|
pg
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ DocuSeal is an open source platform that provides secure and efficient digital d
|
|||||||
- PDF signature verification
|
- PDF signature verification
|
||||||
- Users management
|
- Users management
|
||||||
- Mobile-optimized
|
- Mobile-optimized
|
||||||
- Signing available in 13 languages
|
- 6 UI languages with signing available in 13 languages
|
||||||
- API and Webhooks for integrations
|
- API and Webhooks for integrations
|
||||||
- Easy to deploy in minutes
|
- Easy to deploy in minutes
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ class AccountsController < ApplicationController
|
|||||||
LOCALE_OPTIONS = {
|
LOCALE_OPTIONS = {
|
||||||
'en-US' => 'English (United States)',
|
'en-US' => 'English (United States)',
|
||||||
'en-GB' => 'English (United Kingdom)',
|
'en-GB' => 'English (United Kingdom)',
|
||||||
'fr-FR' => 'French (France)',
|
'fr-FR' => 'Français',
|
||||||
'es-ES' => 'Spanish (Spain)',
|
'es-ES' => 'Español',
|
||||||
'pt-PT' => 'Portuguese (Portugal)',
|
'pt-PT' => 'Português',
|
||||||
'de-DE' => 'German (Germany)',
|
'de-DE' => 'Deutsch',
|
||||||
'it-IT' => 'Italian (Italy)'
|
'it-IT' => 'Italiano'
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
before_action :load_account
|
before_action :load_account
|
||||||
@@ -19,21 +19,25 @@ class AccountsController < ApplicationController
|
|||||||
def update
|
def update
|
||||||
current_account.update!(account_params)
|
current_account.update!(account_params)
|
||||||
|
|
||||||
@encrypted_config = EncryptedConfig.find_or_initialize_by(account: current_account,
|
unless Docuseal.multitenant?
|
||||||
key: EncryptedConfig::APP_URL_KEY)
|
@encrypted_config = EncryptedConfig.find_or_initialize_by(account: current_account,
|
||||||
@encrypted_config.assign_attributes(app_url_params)
|
key: EncryptedConfig::APP_URL_KEY)
|
||||||
|
@encrypted_config.assign_attributes(app_url_params)
|
||||||
|
|
||||||
unless URI.parse(@encrypted_config.value.to_s).class.in?([URI::HTTP, URI::HTTPS])
|
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'))
|
@encrypted_config.errors.add(:value, I18n.t('should_be_a_valid_url'))
|
||||||
|
|
||||||
return render :show, status: :unprocessable_entity
|
return render :show, status: :unprocessable_entity
|
||||||
|
end
|
||||||
|
|
||||||
|
@encrypted_config.save!
|
||||||
|
|
||||||
|
Docuseal.refresh_default_url_options!
|
||||||
end
|
end
|
||||||
|
|
||||||
@encrypted_config.save!
|
with_locale do
|
||||||
|
redirect_to settings_account_path, notice: I18n.t('account_information_has_been_updated')
|
||||||
Docuseal.refresh_default_url_options!
|
end
|
||||||
|
|
||||||
redirect_to settings_account_path, notice: I18n.t('account_information_has_been_updated')
|
|
||||||
rescue ActiveRecord::RecordInvalid
|
rescue ActiveRecord::RecordInvalid
|
||||||
render :show, status: :unprocessable_entity
|
render :show, status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -38,12 +38,12 @@ module Api
|
|||||||
private
|
private
|
||||||
|
|
||||||
def authorization_check!(blob)
|
def authorization_check!(blob)
|
||||||
is_authorized =
|
attachment = blob.attachments.take
|
||||||
blob.attachments.all? do |a|
|
|
||||||
a.name.in?(%w[logo preview_images]) ||
|
is_authorized = attachment.name.in?(%w[logo preview_images]) ||
|
||||||
(current_user && a.record.account.id == current_user.account_id) ||
|
(current_user && attachment.record.account.id == current_user.account_id) ||
|
||||||
!a.record.account.account_configs.find_or_initialize_by(key: AccountConfig::DOWNLOAD_LINKS_AUTH_KEY).value
|
!attachment.record.account.account_configs
|
||||||
end
|
.find_or_initialize_by(key: AccountConfig::DOWNLOAD_LINKS_AUTH_KEY).value
|
||||||
|
|
||||||
return if is_authorized
|
return if is_authorized
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ class ApplicationController < ActionController::Base
|
|||||||
|
|
||||||
check_authorization unless: :devise_controller?
|
check_authorization unless: :devise_controller?
|
||||||
|
|
||||||
|
around_action :with_locale
|
||||||
before_action :sign_in_for_demo, if: -> { Docuseal.demo? }
|
before_action :sign_in_for_demo, if: -> { Docuseal.demo? }
|
||||||
before_action :maybe_redirect_to_setup, unless: :signed_in?
|
before_action :maybe_redirect_to_setup, unless: :signed_in?
|
||||||
before_action :authenticate_user!, unless: :devise_controller?
|
before_action :authenticate_user!, unless: :devise_controller?
|
||||||
@@ -51,7 +52,18 @@ class ApplicationController < ActionController::Base
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def with_locale(&)
|
||||||
|
return yield unless current_account
|
||||||
|
|
||||||
|
locale = params[:lang].presence if Rails.env.development?
|
||||||
|
locale ||= current_account.locale
|
||||||
|
|
||||||
|
I18n.with_locale(locale, &)
|
||||||
|
end
|
||||||
|
|
||||||
def with_browser_locale(&)
|
def with_browser_locale(&)
|
||||||
|
return yield if I18n.locale != :'en-US' && I18n.locale != :en
|
||||||
|
|
||||||
locale = params[:lang].presence
|
locale = params[:lang].presence
|
||||||
locale ||= request.env['HTTP_ACCEPT_LANGUAGE'].to_s[BROWSER_LOCALE_REGEXP].to_s
|
locale ||= request.env['HTTP_ACCEPT_LANGUAGE'].to_s[BROWSER_LOCALE_REGEXP].to_s
|
||||||
|
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ class EsignSettingsController < ApplicationController
|
|||||||
default_pkcs = GenerateCertificate.load_pkcs(cert_data) if cert_data['cert'].present?
|
default_pkcs = GenerateCertificate.load_pkcs(cert_data) if cert_data['cert'].present?
|
||||||
|
|
||||||
custom_pkcs_list = (cert_data['custom'] || []).map do |e|
|
custom_pkcs_list = (cert_data['custom'] || []).map do |e|
|
||||||
{ 'pkcs' => OpenSSL::PKCS12.new(Base64.urlsafe_decode64(e['data']), e['password'].to_s),
|
pkcs = e['data'].present? ? OpenSSL::PKCS12.new(Base64.urlsafe_decode64(e['data']), e['password'].to_s) : nil
|
||||||
'name' => e['name'],
|
|
||||||
'status' => e['status'] }
|
{ 'pkcs' => pkcs, 'name' => e['name'], 'status' => e['status'] }
|
||||||
end
|
end
|
||||||
|
|
||||||
@pkcs_list = [
|
@pkcs_list = [
|
||||||
@@ -56,7 +56,7 @@ class EsignSettingsController < ApplicationController
|
|||||||
|
|
||||||
save_new_cert!(@encrypted_config, @cert_record)
|
save_new_cert!(@encrypted_config, @cert_record)
|
||||||
|
|
||||||
redirect_to settings_esign_path, notice: I18n.t('certificate_has_been_successfully_added_')
|
redirect_to settings_esign_path, notice: I18n.t('certificate_has_been_successfully_added')
|
||||||
rescue OpenSSL::PKCS12::PKCS12Error => e
|
rescue OpenSSL::PKCS12::PKCS12Error => e
|
||||||
Rollbar.error(e) if defined?(Rollbar)
|
Rollbar.error(e) if defined?(Rollbar)
|
||||||
|
|
||||||
@@ -66,10 +66,16 @@ class EsignSettingsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@encrypted_config.value['custom'].each { |e| e['status'] = 'validate' }
|
@encrypted_config.value['custom'].to_a.each { |e| e['status'] = 'validate' }
|
||||||
|
|
||||||
custom_cert_data = @encrypted_config.value['custom'].find { |e| e['name'] == params[:name] }
|
custom_cert_data = @encrypted_config.value['custom'].to_a.find { |e| e['name'] == params[:name] }
|
||||||
custom_cert_data['status'] = 'default' if custom_cert_data
|
|
||||||
|
if custom_cert_data
|
||||||
|
custom_cert_data['status'] = 'default'
|
||||||
|
elsif params[:name] == Docuseal::AATL_CERT_NAME
|
||||||
|
@encrypted_config.value['custom'] ||= []
|
||||||
|
@encrypted_config.value['custom'] << { 'name' => params[:name], 'status' => 'default' }
|
||||||
|
end
|
||||||
|
|
||||||
@encrypted_config.save!
|
@encrypted_config.save!
|
||||||
|
|
||||||
@@ -81,7 +87,7 @@ class EsignSettingsController < ApplicationController
|
|||||||
|
|
||||||
@encrypted_config.save!
|
@encrypted_config.save!
|
||||||
|
|
||||||
redirect_to settings_esign_path, notice: I18m.t('certificate_has_been_removed')
|
redirect_to settings_esign_path, notice: I18n.t('certificate_has_been_removed')
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class SetupController < ApplicationController
|
|||||||
def account_params
|
def account_params
|
||||||
return {} unless params[:account]
|
return {} unless params[:account]
|
||||||
|
|
||||||
params.require(:account).permit(:name, :timezone)
|
params.require(:account).permit(:name, :timezone, :locale)
|
||||||
end
|
end
|
||||||
|
|
||||||
def encrypted_config_params
|
def encrypted_config_params
|
||||||
|
|||||||
@@ -12,16 +12,20 @@ class SubmitFormController < ApplicationController
|
|||||||
def show
|
def show
|
||||||
@submitter = Submitter.find_by!(slug: params[:slug])
|
@submitter = Submitter.find_by!(slug: params[:slug])
|
||||||
|
|
||||||
|
submission = @submitter.submission
|
||||||
|
|
||||||
return redirect_to submit_form_completed_path(@submitter.slug) if @submitter.completed_at?
|
return redirect_to submit_form_completed_path(@submitter.slug) if @submitter.completed_at?
|
||||||
return render :archived if @submitter.submission.template.archived_at? || @submitter.submission.archived_at?
|
return render :archived if submission.template.archived_at? || submission.archived_at?
|
||||||
return render :expired if @submitter.submission.expired?
|
return render :expired if submission.expired?
|
||||||
return render :declined if @submitter.declined_at?
|
return render :declined if @submitter.declined_at?
|
||||||
|
return render :awaiting if submission.template.preferences['submitters_order'] == 'preserved' &&
|
||||||
|
!Submitters.current_submitter_order?(@submitter)
|
||||||
|
|
||||||
Submitters.preload_with_pages(@submitter)
|
Submitters.preload_with_pages(@submitter)
|
||||||
|
|
||||||
Submitters::MaybeUpdateDefaultValues.call(@submitter, current_user)
|
Submitters::MaybeUpdateDefaultValues.call(@submitter, current_user)
|
||||||
|
|
||||||
@attachments_index = ActiveStorage::Attachment.where(record: @submitter.submission.submitters, name: :attachments)
|
@attachments_index = ActiveStorage::Attachment.where(record: submission.submitters, name: :attachments)
|
||||||
.preload(:blob).index_by(&:uuid)
|
.preload(:blob).index_by(&:uuid)
|
||||||
|
|
||||||
@form_configs = Submitters::FormConfigs.call(@submitter, CONFIG_KEYS)
|
@form_configs = Submitters::FormConfigs.call(@submitter, CONFIG_KEYS)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ class TemplateFoldersController < ApplicationController
|
|||||||
@templates = @template_folder.templates.active.preload(:author).order(id: :desc)
|
@templates = @template_folder.templates.active.preload(:author).order(id: :desc)
|
||||||
@templates = Templates.search(@templates, params[:q])
|
@templates = Templates.search(@templates, params[:q])
|
||||||
|
|
||||||
@pagy, @templates = pagy(@templates, items: 12)
|
@pagy, @templates = pagy(@templates, limit: 12)
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit; end
|
def edit; end
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ class TemplatesArchivedController < ApplicationController
|
|||||||
@templates = @templates.where.not(archived_at: nil).preload(:author, :folder).order(id: :desc)
|
@templates = @templates.where.not(archived_at: nil).preload(:author, :folder).order(id: :desc)
|
||||||
@templates = Templates.search(@templates, params[:q])
|
@templates = Templates.search(@templates, params[:q])
|
||||||
|
|
||||||
@pagy, @templates = pagy(@templates, items: 12)
|
@pagy, @templates = pagy(@templates, limit: 12)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -116,7 +116,8 @@ class TemplatesController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def authorized_clone_account_id?(account_id)
|
def authorized_clone_account_id?(account_id)
|
||||||
true_user.account_id.to_s == account_id.to_s || true_user.account.linked_accounts.exists?(id: account_id)
|
true_user.account_id.to_s == account_id.to_s ||
|
||||||
|
true_user.account.linked_accounts.accessible_by(current_ability).exists?(id: account_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def maybe_redirect_to_template(template)
|
def maybe_redirect_to_template(template)
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ class TemplatesDashboardController < ApplicationController
|
|||||||
@template_folders = @template_folders.reject { |e| e.name == TemplateFolder::DEFAULT_NAME }
|
@template_folders = @template_folders.reject { |e| e.name == TemplateFolder::DEFAULT_NAME }
|
||||||
@templates = filter_templates(@templates)
|
@templates = filter_templates(@templates)
|
||||||
|
|
||||||
items =
|
limit =
|
||||||
if @template_folders.size < 4
|
if @template_folders.size < 4
|
||||||
TEMPLATES_PER_PAGE
|
TEMPLATES_PER_PAGE
|
||||||
else
|
else
|
||||||
(@template_folders.size < 7 ? 9 : 6)
|
(@template_folders.size < 7 ? 9 : 6)
|
||||||
end
|
end
|
||||||
|
|
||||||
@pagy, @templates = pagy(@templates, items:)
|
@pagy, @templates = pagy(@templates, limit:)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ class TemplatesPreferencesController < ApplicationController
|
|||||||
documents_copy_email_enabled documents_copy_email_attach_audit
|
documents_copy_email_enabled documents_copy_email_attach_audit
|
||||||
completed_notification_email_attach_documents
|
completed_notification_email_attach_documents
|
||||||
completed_redirect_url
|
completed_redirect_url
|
||||||
|
submitters_order
|
||||||
completed_notification_email_subject completed_notification_email_body
|
completed_notification_email_subject completed_notification_email_body
|
||||||
completed_notification_email_enabled completed_notification_email_attach_audit] +
|
completed_notification_email_enabled completed_notification_email_attach_audit] +
|
||||||
[completed_message: %i[title body]]
|
[completed_message: %i[title body]]
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class UserSignaturesController < ApplicationController
|
|||||||
def update
|
def update
|
||||||
file = params[:file]
|
file = params[:file]
|
||||||
|
|
||||||
return redirect_to settings_profile_index_path, notice: I18n.t('Unable to save signature') if file.blank?
|
return redirect_to settings_profile_index_path, notice: I18n.t('unable_to_save_signature') if file.blank?
|
||||||
|
|
||||||
blob = ActiveStorage::Blob.create_and_upload!(io: file.open,
|
blob = ActiveStorage::Blob.create_and_upload!(io: file.open,
|
||||||
filename: file.original_filename,
|
filename: file.original_filename,
|
||||||
@@ -24,7 +24,7 @@ class UserSignaturesController < ApplicationController
|
|||||||
if @user_config.update(value: attachment.uuid)
|
if @user_config.update(value: attachment.uuid)
|
||||||
redirect_to settings_profile_index_path, notice: I18n.t('signature_has_been_saved')
|
redirect_to settings_profile_index_path, notice: I18n.t('signature_has_been_saved')
|
||||||
else
|
else
|
||||||
redirect_to settings_profile_index_path, notice: I18n.t('Unable to save signature')
|
redirect_to settings_profile_index_path, notice: I18n.t('unable_to_save_signature')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -150,7 +150,8 @@ safeRegisterElement('import-list', class extends HTMLElement {
|
|||||||
this.app = createApp(ImportList, {
|
this.app = createApp(ImportList, {
|
||||||
template: JSON.parse(this.dataset.template),
|
template: JSON.parse(this.dataset.template),
|
||||||
multitenant: this.dataset.multitenant === 'true',
|
multitenant: this.dataset.multitenant === 'true',
|
||||||
authenticityToken: document.querySelector('meta[name="csrf-token"]')?.content
|
authenticityToken: document.querySelector('meta[name="csrf-token"]')?.content,
|
||||||
|
i18n: JSON.parse(this.dataset.i18n || '{}')
|
||||||
})
|
})
|
||||||
|
|
||||||
this.app.mount(this.appElem)
|
this.app.mount(this.appElem)
|
||||||
|
|||||||
@@ -51,10 +51,6 @@ button[disabled] .enabled {
|
|||||||
@apply input input-bordered bg-white;
|
@apply input input-bordered bg-white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.base-input-slim {
|
|
||||||
@apply input input-bordered bg-white h-10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.base-textarea {
|
.base-textarea {
|
||||||
@apply textarea textarea-bordered bg-white rounded-3xl;
|
@apply textarea textarea-bordered bg-white rounded-3xl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ safeRegisterElement('submission-form', class extends HTMLElement {
|
|||||||
isDemo: this.dataset.isDemo === 'true',
|
isDemo: this.dataset.isDemo === 'true',
|
||||||
attribution: this.dataset.attribution !== 'false',
|
attribution: this.dataset.attribution !== 'false',
|
||||||
scrollPadding: this.dataset.scrollPadding || '-80px',
|
scrollPadding: this.dataset.scrollPadding || '-80px',
|
||||||
|
language: this.dataset.language,
|
||||||
dryRun: this.dataset.dryRun === 'true',
|
dryRun: this.dataset.dryRun === 'true',
|
||||||
expand: ['true', 'false'].includes(this.dataset.expand) ? this.dataset.expand === 'true' : null,
|
expand: ['true', 'false'].includes(this.dataset.expand) ? this.dataset.expand === 'true' : null,
|
||||||
withSignatureId: this.dataset.withSignatureId === 'true',
|
withSignatureId: this.dataset.withSignatureId === 'true',
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
|
id="form_completed"
|
||||||
class="mx-auto max-w-md flex flex-col"
|
class="mx-auto max-w-md flex flex-col"
|
||||||
dir="auto"
|
dir="auto"
|
||||||
>
|
>
|
||||||
@@ -222,7 +223,7 @@ export default {
|
|||||||
this.downloadUrls(urls)
|
this.downloadUrls(urls)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert('Failed to download files')
|
alert(this.t('failed_to_download_files'))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -897,7 +897,7 @@ export default {
|
|||||||
mounted () {
|
mounted () {
|
||||||
this.submittedValues = JSON.parse(JSON.stringify(this.values))
|
this.submittedValues = JSON.parse(JSON.stringify(this.values))
|
||||||
|
|
||||||
screen?.orientation.addEventListener('change', this.onOrientationChange)
|
screen?.orientation?.addEventListener('change', this.onOrientationChange)
|
||||||
|
|
||||||
this.fields.forEach((field) => {
|
this.fields.forEach((field) => {
|
||||||
if (field.default_value && !field.readonly) {
|
if (field.default_value && !field.readonly) {
|
||||||
@@ -1183,10 +1183,6 @@ export default {
|
|||||||
return Promise.reject(new Error(data.error))
|
return Promise.reject(new Error(data.error))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLastStep) {
|
|
||||||
this.isSecondWalkthrough = true
|
|
||||||
}
|
|
||||||
|
|
||||||
const nextStep = (isLastStep && emptyRequiredField) || this.stepFields[this.currentStep + 1]
|
const nextStep = (isLastStep && emptyRequiredField) || this.stepFields[this.currentStep + 1]
|
||||||
|
|
||||||
if (nextStep) {
|
if (nextStep) {
|
||||||
@@ -1211,7 +1207,7 @@ export default {
|
|||||||
})
|
})
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
if (error?.message === 'Image too small') {
|
if (error?.message === 'Image too small') {
|
||||||
alert('Signature is too small - please redraw.')
|
alert(this.t('signature_is_too_small_please_redraw'))
|
||||||
} else {
|
} else {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ const it = {
|
|||||||
pay: 'Pagamento',
|
pay: 'Pagamento',
|
||||||
file: 'File',
|
file: 'File',
|
||||||
select: 'Seleziona',
|
select: 'Seleziona',
|
||||||
checkbox: 'Casella di controllo',
|
checkbox: 'Checkbox',
|
||||||
multiple: 'Multiplo',
|
multiple: 'Multiplo',
|
||||||
radio: 'Radio',
|
radio: 'Radio',
|
||||||
cells: 'Celle',
|
cells: 'Celle',
|
||||||
|
|||||||
@@ -360,6 +360,7 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
fieldNames: FieldType.computed.fieldNames,
|
fieldNames: FieldType.computed.fieldNames,
|
||||||
|
fieldLabels: FieldType.computed.fieldLabels,
|
||||||
fieldIcons: FieldType.computed.fieldIcons,
|
fieldIcons: FieldType.computed.fieldIcons,
|
||||||
isDefaultValuePresent () {
|
isDefaultValuePresent () {
|
||||||
if (this.field?.type === 'radio' && this.field?.areas?.length > 1) {
|
if (this.field?.type === 'radio' && this.field?.areas?.length > 1) {
|
||||||
|
|||||||
@@ -332,7 +332,7 @@
|
|||||||
>
|
>
|
||||||
<div class="bg-base-200 rounded-lg p-5 text-center space-y-4">
|
<div class="bg-base-200 rounded-lg p-5 text-center space-y-4">
|
||||||
<p>
|
<p>
|
||||||
{{ t('draw_field_on_the_document').replace('{field}', drawField?.name || '') }}
|
{{ t('draw_field_on_the_document') }}
|
||||||
</p>
|
</p>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
@@ -418,7 +418,7 @@ import MobileFields from './mobile_fields'
|
|||||||
import { IconPlus, IconUsersPlus, IconDeviceFloppy, IconChevronDown, IconEye, IconWritingSign, IconInnerShadowTop, IconInfoCircle, IconAdjustments } from '@tabler/icons-vue'
|
import { IconPlus, IconUsersPlus, IconDeviceFloppy, IconChevronDown, IconEye, IconWritingSign, IconInnerShadowTop, IconInfoCircle, IconAdjustments } from '@tabler/icons-vue'
|
||||||
import { v4 } from 'uuid'
|
import { v4 } from 'uuid'
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import { en as i18nEn } from './i18n'
|
import * as i18n from './i18n'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TemplateBuilder',
|
name: 'TemplateBuilder',
|
||||||
@@ -679,6 +679,9 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
selectedAreaRef: () => ref(),
|
selectedAreaRef: () => ref(),
|
||||||
fieldsDragFieldRef: () => ref(),
|
fieldsDragFieldRef: () => ref(),
|
||||||
|
language () {
|
||||||
|
return this.locale.split('-')[0].toLowerCase()
|
||||||
|
},
|
||||||
defaultDateFormat () {
|
defaultDateFormat () {
|
||||||
const isUsBrowser = Intl.DateTimeFormat().resolvedOptions().locale.endsWith('-US')
|
const isUsBrowser = Intl.DateTimeFormat().resolvedOptions().locale.endsWith('-US')
|
||||||
const isUsTimezone = new Intl.DateTimeFormat('en-US', { timeZoneName: 'short' }).format(new Date()).match(/\s(?:CST|CDT|PST|PDT|EST|EDT)$/)
|
const isUsTimezone = new Intl.DateTimeFormat('en-US', { timeZoneName: 'short' }).format(new Date()).match(/\s(?:CST|CDT|PST|PDT|EST|EDT)$/)
|
||||||
@@ -786,7 +789,7 @@ export default {
|
|||||||
document.activeElement.blur()
|
document.activeElement.blur()
|
||||||
},
|
},
|
||||||
t (key) {
|
t (key) {
|
||||||
return this.i18n[key] || i18nEn[key] || key
|
return this.i18n[key] || i18n[this.language]?.[key] || i18n.en[key] || key
|
||||||
},
|
},
|
||||||
removePendingFields () {
|
removePendingFields () {
|
||||||
this.template.fields = this.template.fields.filter((f) => {
|
this.template.fields = this.template.fields.filter((f) => {
|
||||||
@@ -1352,7 +1355,7 @@ export default {
|
|||||||
this.save()
|
this.save()
|
||||||
},
|
},
|
||||||
onDocumentRemove (item) {
|
onDocumentRemove (item) {
|
||||||
if (window.confirm(this.t('are_you_sure'))) {
|
if (window.confirm(this.t('are_you_sure_'))) {
|
||||||
this.template.schema.splice(this.template.schema.indexOf(item), 1)
|
this.template.schema.splice(this.template.schema.indexOf(item), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1451,7 +1454,7 @@ export default {
|
|||||||
if (!this.template.fields.length) {
|
if (!this.template.fields.length) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
alert('Please draw fields to prepare the document.')
|
alert(this.t('please_draw_fields_to_prepare_the_document'))
|
||||||
} else {
|
} else {
|
||||||
const submitterWithoutFields =
|
const submitterWithoutFields =
|
||||||
this.template.submitters.find((submitter) => !this.template.fields.some((f) => f.submitter_uuid === submitter.uuid))
|
this.template.submitters.find((submitter) => !this.template.fields.some((f) => f.submitter_uuid === submitter.uuid))
|
||||||
@@ -1459,7 +1462,7 @@ export default {
|
|||||||
if (submitterWithoutFields) {
|
if (submitterWithoutFields) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
alert(`Please add fields for the ${submitterWithoutFields.name}. Or, remove the ${submitterWithoutFields.name} if not needed.`)
|
alert(this.t('please_add_fields_for_the_submitter_name_or_remove_the_submitter_name_if_not_needed').replaceAll('{submitter_name}', submitterWithoutFields.name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1475,13 +1478,13 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this.template.fields.length) {
|
if (!this.template.fields.length) {
|
||||||
alert('Please draw fields to prepare the document.')
|
alert(this.t('please_draw_fields_to_prepare_the_document'))
|
||||||
} else {
|
} else {
|
||||||
const submitterWithoutFields =
|
const submitterWithoutFields =
|
||||||
this.template.submitters.find((submitter) => !this.template.fields.some((f) => f.submitter_uuid === submitter.uuid))
|
this.template.submitters.find((submitter) => !this.template.fields.some((f) => f.submitter_uuid === submitter.uuid))
|
||||||
|
|
||||||
if (submitterWithoutFields) {
|
if (submitterWithoutFields) {
|
||||||
alert(`Please add fields for the ${submitterWithoutFields.name}. Or, remove the ${submitterWithoutFields.name} if not needed.`)
|
alert(this.t('please_add_fields_for_the_submitter_name_or_remove_the_submitter_name_if_not_needed').replaceAll('{submitter_name}', submitterWithoutFields.name))
|
||||||
} else {
|
} else {
|
||||||
this.isSaving = true
|
this.isSaving = true
|
||||||
|
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ export default {
|
|||||||
},
|
},
|
||||||
validateSaveAndClose () {
|
validateSaveAndClose () {
|
||||||
if (!this.withConditions) {
|
if (!this.withConditions) {
|
||||||
return alert('Available only in Pro')
|
return alert(this.t('available_only_in_pro'))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.conditions.find((f) => f.field_uuid)) {
|
if (this.conditions.find((f) => f.field_uuid)) {
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export default {
|
|||||||
|
|
||||||
this.upload()
|
this.upload()
|
||||||
} else {
|
} else {
|
||||||
alert('Only PDF and images are supported.')
|
alert(this.t('only_pdf_and_images_are_supported'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -312,6 +312,7 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
fieldNames: FieldType.computed.fieldNames,
|
fieldNames: FieldType.computed.fieldNames,
|
||||||
|
fieldLabels: FieldType.computed.fieldLabels,
|
||||||
dropdownBgColor () {
|
dropdownBgColor () {
|
||||||
return ['', null, 'transparent'].includes(this.backgroundColor) ? 'white' : this.backgroundColor
|
return ['', null, 'transparent'].includes(this.backgroundColor) ? 'white' : this.backgroundColor
|
||||||
},
|
},
|
||||||
@@ -367,8 +368,7 @@ export default {
|
|||||||
if (this.field.type === 'heading') {
|
if (this.field.type === 'heading') {
|
||||||
return `${this.fieldNames[field.type]} ${typeIndex + 1}`
|
return `${this.fieldNames[field.type]} ${typeIndex + 1}`
|
||||||
} else {
|
} else {
|
||||||
const suffix = { multiple: this.t('select'), radio: this.t('group') }[field.type] || this.t('field')
|
return `${this.fieldLabels[field.type]} ${typeIndex + 1}`
|
||||||
return `${this.fieldNames[field.type]} ${suffix} ${typeIndex + 1}`
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -330,7 +330,7 @@ export default {
|
|||||||
this.$emit('update:model-value', submitter.uuid)
|
this.$emit('update:model-value', submitter.uuid)
|
||||||
},
|
},
|
||||||
remove (submitter) {
|
remove (submitter) {
|
||||||
if (window.confirm(this.t('are_you_sure'))) {
|
if (window.confirm(this.t('are_you_sure_'))) {
|
||||||
this.$emit('remove', submitter)
|
this.$emit('remove', submitter)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -114,6 +114,25 @@ export default {
|
|||||||
phone: this.t('phone')
|
phone: this.t('phone')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
fieldLabels () {
|
||||||
|
return {
|
||||||
|
text: this.t('text_field'),
|
||||||
|
signature: this.t('signature_field'),
|
||||||
|
initials: this.t('initials_field'),
|
||||||
|
date: this.t('date_field'),
|
||||||
|
number: this.t('number_field'),
|
||||||
|
image: this.t('image_field'),
|
||||||
|
file: this.t('file_field'),
|
||||||
|
select: this.t('select_field'),
|
||||||
|
checkbox: this.t('checkbox_field'),
|
||||||
|
multiple: this.t('multiple_field'),
|
||||||
|
radio: this.t('radio_field'),
|
||||||
|
cells: this.t('cells_field'),
|
||||||
|
stamp: this.t('stamp_field'),
|
||||||
|
payment: this.t('payment_field'),
|
||||||
|
phone: this.t('phone_field')
|
||||||
|
}
|
||||||
|
},
|
||||||
fieldIcons () {
|
fieldIcons () {
|
||||||
return {
|
return {
|
||||||
heading: IconHeading,
|
heading: IconHeading,
|
||||||
|
|||||||
@@ -137,7 +137,7 @@
|
|||||||
v-else-if="type == 'phone' && (fieldTypes.length === 0 || fieldTypes.includes(type))"
|
v-else-if="type == 'phone' && (fieldTypes.length === 0 || fieldTypes.includes(type))"
|
||||||
class="tooltip tooltip-bottom flex"
|
class="tooltip tooltip-bottom flex"
|
||||||
:class="{'tooltip-bottom-end': withPayment, 'tooltip-bottom': !withPayment }"
|
:class="{'tooltip-bottom-end': withPayment, 'tooltip-bottom': !withPayment }"
|
||||||
data-tip="Unlock SMS-verified phone number field with paid plan. Use text field for phone numbers without verification."
|
:data-tip="t('unlock_sms_verified_phone_number_field_with_paid_plan_use_text_field_for_phone_numbers_without_verification')"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
href="https://www.docuseal.co/pricing"
|
href="https://www.docuseal.co/pricing"
|
||||||
@@ -168,13 +168,13 @@
|
|||||||
>
|
>
|
||||||
<ul class="list-disc list-outside ml-3">
|
<ul class="list-disc list-outside ml-3">
|
||||||
<li>
|
<li>
|
||||||
Draw a text field on the page with a mouse
|
{{ t('draw_a_text_field_on_the_page_with_a_mouse') }}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Drag & drop any other field type on the page
|
{{ t('drag_and_drop_any_other_field_type_on_the_page') }}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Click on the field type above to start drawing it
|
{{ t('click_on_the_field_type_above_to_start_drawing_it') }}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ export default {
|
|||||||
},
|
},
|
||||||
validateSaveAndClose () {
|
validateSaveAndClose () {
|
||||||
if (!this.withFormula) {
|
if (!this.withFormula) {
|
||||||
return alert('Available only in Pro')
|
return alert(this.t('available_only_in_pro'))
|
||||||
}
|
}
|
||||||
|
|
||||||
const normalizedFormula = this.normalizeFormula(this.formula)
|
const normalizedFormula = this.normalizeFormula(this.formula)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const en = {
|
|||||||
select_value_: 'Select value...',
|
select_value_: 'Select value...',
|
||||||
remove_condition: 'Remove condition',
|
remove_condition: 'Remove condition',
|
||||||
add_condition: 'Add condition',
|
add_condition: 'Add condition',
|
||||||
are_you_sure: 'Are you sure?',
|
are_you_sure_: 'Are you sure?',
|
||||||
sign_yourself: 'Sign Yourself',
|
sign_yourself: 'Sign Yourself',
|
||||||
set_signing_date: 'Set signing date',
|
set_signing_date: 'Set signing date',
|
||||||
signing_date: 'Signing Date',
|
signing_date: 'Signing Date',
|
||||||
@@ -46,7 +46,7 @@ const en = {
|
|||||||
drawn: 'Drawn',
|
drawn: 'Drawn',
|
||||||
formula: 'Formula',
|
formula: 'Formula',
|
||||||
typed: 'Typed',
|
typed: 'Typed',
|
||||||
draw_field_on_the_document: 'Draw {field} field on the document',
|
draw_field_on_the_document: 'Draw a field on the document',
|
||||||
click_to_upload: 'Click to upload',
|
click_to_upload: 'Click to upload',
|
||||||
or_drag_and_drop_files: 'or drag and drop files',
|
or_drag_and_drop_files: 'or drag and drop files',
|
||||||
uploading: 'Uploading',
|
uploading: 'Uploading',
|
||||||
@@ -101,9 +101,31 @@ const en = {
|
|||||||
stamp: 'Stamp',
|
stamp: 'Stamp',
|
||||||
payment: 'Payment',
|
payment: 'Payment',
|
||||||
phone: 'Phone',
|
phone: 'Phone',
|
||||||
field: 'Field',
|
text_field: 'Text Field',
|
||||||
group: 'Group',
|
signature_field: 'Signature Field',
|
||||||
|
initials_field: 'Initials Field',
|
||||||
|
date_field: 'Date Field',
|
||||||
|
number_field: 'Number Field',
|
||||||
|
image_field: 'Image Field',
|
||||||
|
file_field: 'File Field',
|
||||||
|
select_field: 'Select Field',
|
||||||
|
checkbox_field: 'Checkbox Field',
|
||||||
|
multiple_field: 'Multiple Select Field',
|
||||||
|
radio_field: 'Radio Group Field',
|
||||||
|
cells_field: 'Cells Field',
|
||||||
|
stamp_field: 'Stamp Field',
|
||||||
|
payment_field: 'Payment Field',
|
||||||
|
phone_field: 'Phone Field',
|
||||||
draw_a_text_field_on_the_page_with_a_mouse: 'Draw a text field on the page with a mouse',
|
draw_a_text_field_on_the_page_with_a_mouse: 'Draw a text field on the page with a mouse',
|
||||||
|
drag_and_drop_any_other_field_type_on_the_page: 'Drag & drop any other field type on the page',
|
||||||
|
click_on_the_field_type_above_to_start_drawing_it: 'Click on the field type above to start drawing it',
|
||||||
|
please_draw_fields_to_prepare_the_document: 'Please draw fields to prepare the document.',
|
||||||
|
only_pdf_and_images_are_supported: 'Only PDF and images are supported.',
|
||||||
|
unlock_sms_verified_phone_number_field_with_paid_plan_use_text_field_for_phone_numbers_without_verification: 'Unlock SMS-verified phone number field with paid plan. Use text field for phone numbers without verification.',
|
||||||
|
available_only_in_pro: 'Available only in Pro',
|
||||||
|
failed_to_download_files: 'Failed to download files',
|
||||||
|
signature_is_too_small_please_redraw: 'Signature is too small - please redraw.',
|
||||||
|
please_add_fields_for_the_submitter_name_or_remove_the_submitter_name_if_not_needed: 'Please add fields for the {submitter_name}. Or, remove the {submitter_name} if not needed.',
|
||||||
draw_field: 'Draw {field} Field',
|
draw_field: 'Draw {field} Field',
|
||||||
replace: 'Replace',
|
replace: 'Replace',
|
||||||
uploading_: 'Uploading...',
|
uploading_: 'Uploading...',
|
||||||
@@ -128,4 +150,764 @@ const en = {
|
|||||||
learn_more: 'Learn more'
|
learn_more: 'Learn more'
|
||||||
}
|
}
|
||||||
|
|
||||||
export { en }
|
const es = {
|
||||||
|
editable: 'Editable',
|
||||||
|
search_field: 'Campo de búsqueda',
|
||||||
|
field_not_found: 'Campo no encontrado',
|
||||||
|
clear: 'Borrar',
|
||||||
|
type_value: 'Escriba valor',
|
||||||
|
align: 'Alinear',
|
||||||
|
add_all_required_fields_to_continue: 'Agregar todos los campos requeridos para continuar',
|
||||||
|
uploaded_pdf_contains_form_fields_keep_or_remove_them: 'El PDF cargado tiene campos. ¿Mantenerlos o eliminarlos?',
|
||||||
|
keep: 'Mantener',
|
||||||
|
left: 'Izquierda',
|
||||||
|
heading: 'Encabezado',
|
||||||
|
validation: 'Validación',
|
||||||
|
add_blank_page: 'Agregar página en blanco',
|
||||||
|
right: 'Derecha',
|
||||||
|
center: 'Centro',
|
||||||
|
with_logo: 'Con logotipo',
|
||||||
|
description: 'Descripción',
|
||||||
|
signing_date: 'Fecha de Firma',
|
||||||
|
display_title: 'Título de visualización',
|
||||||
|
unchecked: 'No marcado',
|
||||||
|
price: 'Precio',
|
||||||
|
equal: 'Igual',
|
||||||
|
not_equal: 'No es igual',
|
||||||
|
contains: 'Contiene',
|
||||||
|
does_not_contain: 'No contiene',
|
||||||
|
not_empty: 'No vacío',
|
||||||
|
empty: 'Vacío',
|
||||||
|
select_field_: 'Seleccionar campo...',
|
||||||
|
select_value_: 'Seleccionar valor...',
|
||||||
|
remove_condition: 'Eliminar condición',
|
||||||
|
add_condition: 'Agregar condición',
|
||||||
|
condition: 'Condición',
|
||||||
|
formula: 'Fórmula',
|
||||||
|
edit: 'Editar',
|
||||||
|
settings: 'Configuración',
|
||||||
|
up: 'Arriba',
|
||||||
|
down: 'Abajo',
|
||||||
|
set_signing_date: 'Establecer fecha de firma',
|
||||||
|
are_you_sure_: '¿Estás seguro?',
|
||||||
|
sign_yourself: 'Firma tú mismo',
|
||||||
|
checked: 'Seleccionado',
|
||||||
|
send: 'Enviar',
|
||||||
|
remove: 'Eliminar',
|
||||||
|
save: 'Guardar',
|
||||||
|
cancel: 'Cancelar',
|
||||||
|
or_add_field_without_drawing: 'O añadir campo sin dibujar',
|
||||||
|
draw_field_on_the_document: 'Dibujar un campo en el documento',
|
||||||
|
click_to_upload: 'Haz clic para cargar',
|
||||||
|
or_drag_and_drop_files: 'o arrastra y suelta archivos',
|
||||||
|
uploading: 'Subiendo',
|
||||||
|
processing_: 'Procesando...',
|
||||||
|
add_pdf_documents_or_images: 'Agregar documentos PDF o imágenes',
|
||||||
|
add_documents_or_images: 'Agregar documentos o imágenes',
|
||||||
|
required: 'Requerido',
|
||||||
|
default_value: 'Valor predeterminado',
|
||||||
|
format: 'Formato',
|
||||||
|
read_only: 'Solo lectura',
|
||||||
|
page: 'Página',
|
||||||
|
draw_new_area: 'Dibujar nueva área',
|
||||||
|
copy_to_all_pages: 'Copiar a todas las páginas',
|
||||||
|
add_option: 'Agregar opción',
|
||||||
|
option: 'Opción',
|
||||||
|
first_party: 'Primera Parte',
|
||||||
|
second_party: 'Segunda Parte',
|
||||||
|
third_party: 'Tercera Parte',
|
||||||
|
fourth_party: 'Cuarta Parte',
|
||||||
|
fifth_party: 'Quinta Parte',
|
||||||
|
sixth_party: 'Sexta Parte',
|
||||||
|
seventh_party: 'Séptima Parte',
|
||||||
|
eighth_party: 'Octava Parte',
|
||||||
|
ninth_party: 'Novena Parte',
|
||||||
|
tenth_party: 'Décima Parte',
|
||||||
|
eleventh_party: 'Undécimo Partido',
|
||||||
|
twelfth_party: 'Duodécimo Partido',
|
||||||
|
thirteenth_party: 'Decimotercer Partido',
|
||||||
|
fourteenth_party: 'Catorceavo Partido',
|
||||||
|
fifteenth_party: 'Quinceavo Partido',
|
||||||
|
sixteenth_party: 'Dieciséisavo Partido',
|
||||||
|
seventeenth_party: 'Diecisieteavo Partido',
|
||||||
|
eighteenth_party: 'Dieciochoavo Partido',
|
||||||
|
nineteenth_party: 'Decimonovena Fiesta',
|
||||||
|
twentieth_party: 'Vigésima Fiesta',
|
||||||
|
draw: 'Dibujar',
|
||||||
|
add: 'Agregar',
|
||||||
|
text: 'Texto',
|
||||||
|
signature: 'Firma',
|
||||||
|
initials: 'Iniciales',
|
||||||
|
date: 'Fecha',
|
||||||
|
number: 'Número',
|
||||||
|
image: 'Imagen',
|
||||||
|
file: 'Archivo',
|
||||||
|
select: 'Seleccionar',
|
||||||
|
checkbox: 'Casilla',
|
||||||
|
multiple: 'Múltiple',
|
||||||
|
radio: 'Radio',
|
||||||
|
cells: 'Celdas',
|
||||||
|
stamp: 'Sello',
|
||||||
|
payment: 'Pago',
|
||||||
|
phone: 'Teléfono',
|
||||||
|
text_field: 'Campo de Texto',
|
||||||
|
signature_field: 'Campo de Firma',
|
||||||
|
initials_field: 'Campo de Iniciales',
|
||||||
|
date_field: 'Campo de Fecha',
|
||||||
|
number_field: 'Campo de Número',
|
||||||
|
image_field: 'Campo de Imagen',
|
||||||
|
file_field: 'Campo de Archivo',
|
||||||
|
select_field: 'Campo de Selección',
|
||||||
|
checkbox_field: 'Campo de Casilla',
|
||||||
|
multiple_field: 'Campo Múltiple',
|
||||||
|
radio_field: 'Campo de Grupo Radio',
|
||||||
|
cells_field: 'Campo de Celdas',
|
||||||
|
stamp_field: 'Campo de Sello',
|
||||||
|
payment_field: 'Campo de Pago',
|
||||||
|
phone_field: 'Campo de Teléfono',
|
||||||
|
draw_a_text_field_on_the_page_with_a_mouse: 'Dibujar un campo de texto en la página con el mouse',
|
||||||
|
drag_and_drop_any_other_field_type_on_the_page: 'Arrastra y suelta cualquier otro tipo de campo en la página',
|
||||||
|
click_on_the_field_type_above_to_start_drawing_it: 'Haz clic en el tipo de campo de arriba para comenzar a dibujarlo',
|
||||||
|
please_draw_fields_to_prepare_the_document: 'Por favor, dibuja los campos para preparar el documento.',
|
||||||
|
only_pdf_and_images_are_supported: 'Solo se admiten PDF e imágenes.',
|
||||||
|
unlock_sms_verified_phone_number_field_with_paid_plan_use_text_field_for_phone_numbers_without_verification: 'Desbloquea el campo de número de teléfono verificado por SMS con un plan pago. Usa el campo de texto para números de teléfono sin verificación.',
|
||||||
|
available_only_in_pro: 'Disponible solo en Pro',
|
||||||
|
failed_to_download_files: 'Error al descargar los archivos',
|
||||||
|
signature_is_too_small_please_redraw: 'La firma es demasiado pequeña. Por favor, dibújala de nuevo.',
|
||||||
|
please_add_fields_for_the_submitter_name_or_remove_the_submitter_name_if_not_needed: 'Por favor, añade campos para {submitter_name} o elimina {submitter_name} si no es necesario.',
|
||||||
|
draw_field: 'Dibujar campo {field}',
|
||||||
|
replace: 'Reemplazar',
|
||||||
|
uploading_: 'Subiendo...',
|
||||||
|
add_document: 'Subir',
|
||||||
|
any: 'Cualquier',
|
||||||
|
drawn: 'Dibujado',
|
||||||
|
typed: 'Escrito',
|
||||||
|
none: 'Ninguno',
|
||||||
|
ssn: 'SSN',
|
||||||
|
ein: 'EIN',
|
||||||
|
email: 'Correo electrónico',
|
||||||
|
url: 'URL',
|
||||||
|
zip: 'ZIP',
|
||||||
|
custom: 'Personalizado',
|
||||||
|
numbers_only: 'Solo números',
|
||||||
|
letters_only: 'Solo letras',
|
||||||
|
regexp_validation: 'Validación de expresión regular',
|
||||||
|
enter_pdf_password: 'Ingrese la contraseña del PDF',
|
||||||
|
wrong_password: 'Contraseña incorrecta',
|
||||||
|
currency: 'Moneda',
|
||||||
|
save_and_preview: 'Guardar y previsualizar',
|
||||||
|
preferences: 'Preferencias',
|
||||||
|
available_in_pro: 'Disponible en Pro',
|
||||||
|
some_fields_are_missing_in_the_formula: 'Faltan algunos campos en la fórmula.',
|
||||||
|
learn_more: 'Aprende más'
|
||||||
|
}
|
||||||
|
|
||||||
|
const it = {
|
||||||
|
editable: 'Modificabile',
|
||||||
|
search_field: 'Campo di ricerca',
|
||||||
|
field_not_found: 'Campo non trovato',
|
||||||
|
clear: 'Cancella',
|
||||||
|
align: 'Allinea',
|
||||||
|
add_all_required_fields_to_continue: 'Aggiungi tutti i campi obbligatori per continuare',
|
||||||
|
uploaded_pdf_contains_form_fields_keep_or_remove_them: 'Il PDF caricato contiene campi del modulo. Mantenerli o rimuoverli?',
|
||||||
|
keep: 'Mantieni',
|
||||||
|
left: 'Sinistra',
|
||||||
|
heading: 'Intestazione',
|
||||||
|
validation: 'Validazione',
|
||||||
|
add_blank_page: 'Aggiungi pagina vuota',
|
||||||
|
right: 'Destra',
|
||||||
|
center: 'Centro',
|
||||||
|
description: 'Descrizione',
|
||||||
|
display_title: 'Mostra titolo',
|
||||||
|
with_logo: 'Con logo',
|
||||||
|
unchecked: 'Non selezionato',
|
||||||
|
price: 'Prezzo',
|
||||||
|
type_value: 'Inserisci valore',
|
||||||
|
equal: 'Uguale',
|
||||||
|
not_equal: 'Non uguale',
|
||||||
|
contains: 'Contiene',
|
||||||
|
does_not_contain: 'Non contiene',
|
||||||
|
not_empty: 'Non vuoto',
|
||||||
|
empty: 'Vuoto',
|
||||||
|
select_field_: 'Seleziona campo...',
|
||||||
|
select_value_: 'Seleziona valore...',
|
||||||
|
remove_condition: 'Rimuovi condizione',
|
||||||
|
add_condition: 'Aggiungi condizione',
|
||||||
|
are_you_sure_: 'Sei sicuro?',
|
||||||
|
sign_yourself: 'Firma te stesso',
|
||||||
|
set_signing_date: 'Imposta data di firma',
|
||||||
|
signing_date: 'Data di firma',
|
||||||
|
send: 'Invia',
|
||||||
|
remove: 'Rimuovi',
|
||||||
|
edit: 'Modifica',
|
||||||
|
settings: 'Impostazioni',
|
||||||
|
up: 'Su',
|
||||||
|
down: 'Giù',
|
||||||
|
checked: 'Selezionato',
|
||||||
|
save: 'Salva',
|
||||||
|
cancel: 'Annulla',
|
||||||
|
any: 'Qualsiasi',
|
||||||
|
drawn: 'Disegnato',
|
||||||
|
formula: 'Formula',
|
||||||
|
typed: 'Digitato',
|
||||||
|
draw_field_on_the_document: 'Disegnare un campo sul documento',
|
||||||
|
click_to_upload: 'Clicca per caricare',
|
||||||
|
or_drag_and_drop_files: 'o trascina e rilascia i file',
|
||||||
|
uploading: 'Caricamento in corso',
|
||||||
|
processing_: 'Elaborazione...',
|
||||||
|
add_pdf_documents_or_images: 'Aggiungi documenti PDF o immagini',
|
||||||
|
add_documents_or_images: 'Aggiungi documenti o immagini',
|
||||||
|
required: 'Obbligatorio',
|
||||||
|
default_value: 'Valore predefinito',
|
||||||
|
format: 'Formato',
|
||||||
|
read_only: 'Sola lettura',
|
||||||
|
page: 'Pagina',
|
||||||
|
draw_new_area: 'Disegna nuova area',
|
||||||
|
copy_to_all_pages: 'Copia in tutte le pagine',
|
||||||
|
add_option: 'Aggiungi opzione',
|
||||||
|
option: 'Opzione',
|
||||||
|
condition: 'Condizione',
|
||||||
|
first_party: 'Prima parte',
|
||||||
|
second_party: 'Seconda parte',
|
||||||
|
third_party: 'Terza parte',
|
||||||
|
fourth_party: 'Quarta parte',
|
||||||
|
fifth_party: 'Quinta parte',
|
||||||
|
sixth_party: 'Sesta parte',
|
||||||
|
seventh_party: 'Settima parte',
|
||||||
|
eighth_party: 'Ottava parte',
|
||||||
|
ninth_party: 'Nona parte',
|
||||||
|
tenth_party: 'Decima parte',
|
||||||
|
eleventh_party: 'Undicesima parte',
|
||||||
|
twelfth_party: 'Dodicesima parte',
|
||||||
|
thirteenth_party: 'Tredicesima parte',
|
||||||
|
fourteenth_party: 'Quattordicesima parte',
|
||||||
|
fifteenth_party: 'Quindicesima parte',
|
||||||
|
sixteenth_party: 'Sedicesima parte',
|
||||||
|
seventeenth_party: 'Diciassettesima parte',
|
||||||
|
eighteenth_party: 'Diciottesima parte',
|
||||||
|
nineteenth_party: 'Diciannovesima parte',
|
||||||
|
twentieth_party: 'Ventesima parte',
|
||||||
|
draw: 'Disegna',
|
||||||
|
add: 'Aggiungi',
|
||||||
|
or_add_field_without_drawing: 'Oppure aggiungi campo senza disegno',
|
||||||
|
text: 'Testo',
|
||||||
|
number: 'Numero',
|
||||||
|
signature: 'Firma',
|
||||||
|
initials: 'Iniziali',
|
||||||
|
date: 'Data',
|
||||||
|
image: 'Immagine',
|
||||||
|
file: 'File',
|
||||||
|
select: 'Seleziona',
|
||||||
|
checkbox: 'Checkbox',
|
||||||
|
multiple: 'Multiplo',
|
||||||
|
radio: 'Radio',
|
||||||
|
cells: 'Celle',
|
||||||
|
stamp: 'Timbro',
|
||||||
|
payment: 'Pagamento',
|
||||||
|
phone: 'Telefono',
|
||||||
|
text_field: 'Campo di Testo',
|
||||||
|
signature_field: 'Campo di Firma',
|
||||||
|
initials_field: 'Campo di Iniziali',
|
||||||
|
date_field: 'Campo Data',
|
||||||
|
number_field: 'Campo Numero',
|
||||||
|
image_field: 'Campo Immagine',
|
||||||
|
file_field: 'Campo File',
|
||||||
|
select_field: 'Campo di Selezione',
|
||||||
|
checkbox_field: 'Campo di Checkbox',
|
||||||
|
multiple_field: 'Campo Selezione Multipla',
|
||||||
|
radio_field: 'Campo di Gruppo Radio',
|
||||||
|
cells_field: 'Campo Celle',
|
||||||
|
stamp_field: 'Campo Timbro',
|
||||||
|
payment_field: 'Campo Pagamento',
|
||||||
|
phone_field: 'Campo Telefono',
|
||||||
|
draw_a_text_field_on_the_page_with_a_mouse: 'Disegna un campo di testo sulla pagina con il mouse',
|
||||||
|
drag_and_drop_any_other_field_type_on_the_page: 'Trascina e rilascia qualsiasi altro tipo di campo sulla pagina',
|
||||||
|
click_on_the_field_type_above_to_start_drawing_it: 'Clicca sul tipo di campo sopra per iniziare a disegnarlo',
|
||||||
|
please_draw_fields_to_prepare_the_document: 'Per favore, disegna i campi per preparare il documento.',
|
||||||
|
only_pdf_and_images_are_supported: 'Sono supportati solo PDF e immagini.',
|
||||||
|
unlock_sms_verified_phone_number_field_with_paid_plan_use_text_field_for_phone_numbers_without_verification: 'Sblocca il campo numero di telefono verificato tramite SMS con un piano a pagamento. Usa il campo di testo per numeri di telefono senza verifica.',
|
||||||
|
available_only_in_pro: 'Disponibile solo in Pro',
|
||||||
|
failed_to_download_files: 'Impossibile scaricare i file',
|
||||||
|
signature_is_too_small_please_redraw: 'La firma è troppo piccola. Ridisegnala per favore.',
|
||||||
|
please_add_fields_for_the_submitter_name_or_remove_the_submitter_name_if_not_needed: 'Aggiungi campi per {submitter_name} o rimuovi {submitter_name} se non necessario.',
|
||||||
|
draw_field: 'Disegna il campo {field}',
|
||||||
|
replace: 'Sostituisci',
|
||||||
|
uploading_: 'Caricamento in corso...',
|
||||||
|
add_document: 'Aggiungi',
|
||||||
|
none: 'Nessuno',
|
||||||
|
ssn: 'SSN',
|
||||||
|
ein: 'EIN',
|
||||||
|
email: 'Email',
|
||||||
|
url: 'URL',
|
||||||
|
zip: 'CAP',
|
||||||
|
custom: 'Personalizzato',
|
||||||
|
numbers_only: 'Solo numeri',
|
||||||
|
letters_only: 'Solo lettere',
|
||||||
|
regexp_validation: 'Validazione regexp',
|
||||||
|
enter_pdf_password: 'Inserisci password PDF',
|
||||||
|
wrong_password: 'Password errata',
|
||||||
|
currency: 'Valuta',
|
||||||
|
save_and_preview: 'Salva e Anteprima',
|
||||||
|
preferences: 'Preferenze',
|
||||||
|
available_in_pro: 'Disponibile in Pro',
|
||||||
|
some_fields_are_missing_in_the_formula: 'Alcuni campi mancano nella formula.',
|
||||||
|
learn_more: 'Scopri di più'
|
||||||
|
}
|
||||||
|
|
||||||
|
const pt = {
|
||||||
|
editable: 'Editável',
|
||||||
|
search_field: 'Campo de busca',
|
||||||
|
field_not_found: 'Campo não encontrado',
|
||||||
|
clear: 'Limpar',
|
||||||
|
type_value: 'Digite valor',
|
||||||
|
add_all_required_fields_to_continue: 'Adicione todos os campos obrigatórios para continuar',
|
||||||
|
uploaded_pdf_contains_form_fields_keep_or_remove_them: 'O PDF carregado contém campos. Manter ou removê-los?',
|
||||||
|
keep: 'Manter',
|
||||||
|
align: 'Alinhar',
|
||||||
|
left: 'Esquerda',
|
||||||
|
heading: 'Cabeçalho',
|
||||||
|
validation: 'Validação',
|
||||||
|
add_blank_page: 'Adicionar página em branco',
|
||||||
|
right: 'Direita',
|
||||||
|
center: 'Centro',
|
||||||
|
with_logo: 'Com logotipo',
|
||||||
|
description: 'Descrição',
|
||||||
|
display_title: 'Título de exibição',
|
||||||
|
signing_date: 'Data da Assinatura',
|
||||||
|
unchecked: 'Não marcado',
|
||||||
|
price: 'Preço',
|
||||||
|
equal: 'Igual',
|
||||||
|
not_equal: 'Não é igual',
|
||||||
|
contains: 'Contém',
|
||||||
|
does_not_contain: 'Não contém',
|
||||||
|
not_empty: 'Não vazio',
|
||||||
|
empty: 'Vazio',
|
||||||
|
add_condition: 'Adicionar condição',
|
||||||
|
select_field_: 'Selecionar campo...',
|
||||||
|
select_value_: 'Selecionar valor...',
|
||||||
|
remove_condition: 'Remover condição',
|
||||||
|
condition: 'Condição',
|
||||||
|
formula: 'Fórmula',
|
||||||
|
edit: 'Editar',
|
||||||
|
settings: 'Configurações',
|
||||||
|
up: 'Para cima',
|
||||||
|
down: 'Para baixo',
|
||||||
|
set_signing_date: 'Definir data de assinatura',
|
||||||
|
are_you_sure_: 'Tem certeza?',
|
||||||
|
sign_yourself: 'Assine você mesmo',
|
||||||
|
checked: 'Marcado',
|
||||||
|
send: 'Enviar',
|
||||||
|
remove: 'Remover',
|
||||||
|
save: 'Salvar',
|
||||||
|
cancel: 'Cancelar',
|
||||||
|
or_add_field_without_drawing: 'Ou adicione campo sem desenhar',
|
||||||
|
draw_field_on_the_document: 'Desenhar um campo no documento',
|
||||||
|
click_to_upload: 'Clique para enviar',
|
||||||
|
or_drag_and_drop_files: 'ou arraste e solte arquivos',
|
||||||
|
uploading: 'Carregando',
|
||||||
|
processing_: 'Processando...',
|
||||||
|
add_pdf_documents_or_images: 'Adicionar documentos PDF ou imagens',
|
||||||
|
add_documents_or_images: 'Adicionar documentos ou imagens',
|
||||||
|
required: 'Obrigatório',
|
||||||
|
default_value: 'Valor padrão',
|
||||||
|
format: 'Formato',
|
||||||
|
read_only: 'Somente leitura',
|
||||||
|
page: 'Página',
|
||||||
|
draw_new_area: 'Desenhar nova área',
|
||||||
|
copy_to_all_pages: 'Copiar para todas as páginas',
|
||||||
|
add_option: 'Adicionar opção',
|
||||||
|
option: 'Opção',
|
||||||
|
first_party: 'Primeira Parte',
|
||||||
|
second_party: 'Segunda Parte',
|
||||||
|
third_party: 'Terceira Parte',
|
||||||
|
fourth_party: 'Quarta Parte',
|
||||||
|
fifth_party: 'Quinta Parte',
|
||||||
|
sixth_party: 'Sexta Parte',
|
||||||
|
seventh_party: 'Sétima Parte',
|
||||||
|
eighth_party: 'Oitava Parte',
|
||||||
|
ninth_party: 'Nona Parte',
|
||||||
|
tenth_party: 'Décima Parte',
|
||||||
|
eleventh_party: 'Décima Primeira Parte',
|
||||||
|
twelfth_party: 'Décima Segunda Parte',
|
||||||
|
thirteenth_party: 'Décima Terceira Parte',
|
||||||
|
fourteenth_party: 'Décima Quarta Parte',
|
||||||
|
fifteenth_party: 'Décima Quinta Parte',
|
||||||
|
sixteenth_party: 'Décima Sexta Parte',
|
||||||
|
seventeenth_party: 'Décima Sétima Parte',
|
||||||
|
eighteenth_party: 'Décima Oitava Parte',
|
||||||
|
nineteenth_party: 'Décima Nona Parte',
|
||||||
|
twentieth_party: 'Vigésima Parte',
|
||||||
|
draw: 'Desenhar',
|
||||||
|
add: 'Adicionar',
|
||||||
|
text: 'Texto',
|
||||||
|
signature: 'Assinatura',
|
||||||
|
initials: 'Rúbrica',
|
||||||
|
date: 'Data',
|
||||||
|
number: 'Número',
|
||||||
|
image: 'Imagem',
|
||||||
|
file: 'Arquivo',
|
||||||
|
select: 'Selecionar',
|
||||||
|
checkbox: 'Caixa',
|
||||||
|
multiple: 'Múltiplo',
|
||||||
|
radio: 'Rádio',
|
||||||
|
cells: 'Células',
|
||||||
|
stamp: 'Carimbo',
|
||||||
|
payment: 'Pagamento',
|
||||||
|
phone: 'Telefone',
|
||||||
|
text_field: 'Campo de Texto',
|
||||||
|
signature_field: 'Campo de Assinatura',
|
||||||
|
initials_field: 'Campo de Rúbrica',
|
||||||
|
date_field: 'Campo de Data',
|
||||||
|
number_field: 'Campo de Número',
|
||||||
|
image_field: 'Campo de Imagem',
|
||||||
|
file_field: 'Campo de Arquivo',
|
||||||
|
select_field: 'Campo de Seleção',
|
||||||
|
checkbox_field: 'Campo de Caixa',
|
||||||
|
multiple_field: 'Campo de Opção Múltipla',
|
||||||
|
radio_field: 'Campo de Grupo Rádio',
|
||||||
|
cells_field: 'Campo de Células',
|
||||||
|
stamp_field: 'Campo de Carimbo',
|
||||||
|
payment_field: 'Campo de Pagamento',
|
||||||
|
phone_field: 'Campo de Telefone',
|
||||||
|
draw_a_text_field_on_the_page_with_a_mouse: 'Desenhar um campo de texto na página com o mouse',
|
||||||
|
drag_and_drop_any_other_field_type_on_the_page: 'Arraste e solte qualquer outro tipo de campo na página',
|
||||||
|
click_on_the_field_type_above_to_start_drawing_it: 'Clique no tipo de campo acima para começar a desenhá-lo',
|
||||||
|
please_draw_fields_to_prepare_the_document: 'Por favor, desenhe os campos para preparar o documento.',
|
||||||
|
only_pdf_and_images_are_supported: 'Apenas PDFs e imagens são suportados.',
|
||||||
|
unlock_sms_verified_phone_number_field_with_paid_plan_use_text_field_for_phone_numbers_without_verification: 'Desbloqueie o campo de número de telefone verificado por SMS com um plano pago. Use o campo de texto para números de telefone sem verificação.',
|
||||||
|
available_only_in_pro: 'Disponível apenas no Pro',
|
||||||
|
failed_to_download_files: 'Falha ao baixar arquivos',
|
||||||
|
signature_is_too_small_please_redraw: 'A assinatura é muito pequena. Por favor, redesenhe.',
|
||||||
|
please_add_fields_for_the_submitter_name_or_remove_the_submitter_name_if_not_needed: 'Adicione campos para {submitter_name} ou remova {submitter_name} se não for necessário.',
|
||||||
|
draw_field: 'Desenhar campo {field}',
|
||||||
|
replace: 'Substituir',
|
||||||
|
uploading_: 'Carregando...',
|
||||||
|
add_document: 'Enviar',
|
||||||
|
any: 'Qualquer',
|
||||||
|
drawn: 'Desenhado',
|
||||||
|
typed: 'Digitado',
|
||||||
|
none: 'Nenhum',
|
||||||
|
ssn: 'SSN',
|
||||||
|
ein: 'EIN',
|
||||||
|
email: 'Email',
|
||||||
|
url: 'URL',
|
||||||
|
zip: 'ZIP',
|
||||||
|
custom: 'Personalizado',
|
||||||
|
numbers_only: 'Somente números',
|
||||||
|
letters_only: 'Somente letras',
|
||||||
|
regexp_validation: 'Validação de expressão regular',
|
||||||
|
enter_pdf_password: 'Digite a senha do PDF',
|
||||||
|
wrong_password: 'Senha incorreta',
|
||||||
|
currency: 'Moeda',
|
||||||
|
save_and_preview: 'Salvar e Pré-visualizar',
|
||||||
|
preferences: 'Preferências',
|
||||||
|
available_in_pro: 'Disponível no Pro',
|
||||||
|
some_fields_are_missing_in_the_formula: 'Faltam alguns campos na fórmula.',
|
||||||
|
learn_more: 'Saiba mais'
|
||||||
|
}
|
||||||
|
|
||||||
|
const fr = {
|
||||||
|
editable: 'Éditable',
|
||||||
|
search_field: 'Champ de recherche',
|
||||||
|
field_not_found: 'Champ non trouvé',
|
||||||
|
clear: 'Effacer',
|
||||||
|
type_value: 'Tapez la valeur',
|
||||||
|
add_all_required_fields_to_continue: 'Ajoutez tous les champs obligatoires pour continuer',
|
||||||
|
uploaded_pdf_contains_form_fields_keep_or_remove_them: 'Le PDF téléchargé contient des champs. Les conserver ou les supprimer?',
|
||||||
|
keep: 'Conserver',
|
||||||
|
align: 'Aligner',
|
||||||
|
left: 'Gauche',
|
||||||
|
heading: 'En-tête',
|
||||||
|
validation: 'Validation',
|
||||||
|
add_blank_page: 'Ajouter une page blanche',
|
||||||
|
right: 'Droite',
|
||||||
|
add_condition: 'Ajouter une condition',
|
||||||
|
center: 'Centre',
|
||||||
|
with_logo: 'Avec logo',
|
||||||
|
description: 'Description',
|
||||||
|
display_title: "Titre d'affichage",
|
||||||
|
unchecked: 'Non coché',
|
||||||
|
price: 'Prix',
|
||||||
|
equal: 'Égal',
|
||||||
|
not_equal: 'Non égal',
|
||||||
|
contains: 'Contient',
|
||||||
|
signing_date: 'Date de signature',
|
||||||
|
does_not_contain: 'Ne contient pas',
|
||||||
|
not_empty: 'Non vide',
|
||||||
|
empty: 'Vide',
|
||||||
|
select_field_: 'Sélectionner un champ...',
|
||||||
|
select_value_: 'Sélectionner une valeur...',
|
||||||
|
remove_condition: 'Supprimer la condition',
|
||||||
|
condition: 'Condition',
|
||||||
|
formula: 'Formule',
|
||||||
|
edit: 'Éditer',
|
||||||
|
settings: 'Paramètres',
|
||||||
|
up: 'Haut',
|
||||||
|
down: 'Bas',
|
||||||
|
set_signing_date: 'Définir la date de signature',
|
||||||
|
are_you_sure_: 'Êtes-vous sûr?',
|
||||||
|
sign_yourself: 'Signez-vous',
|
||||||
|
checked: 'Coché',
|
||||||
|
send: 'Envoyer',
|
||||||
|
remove: 'Supprimer',
|
||||||
|
save: 'Enregistrer',
|
||||||
|
cancel: 'Annuler',
|
||||||
|
draw_field_on_the_document: 'Dessiner un champ sur le document',
|
||||||
|
click_to_upload: 'Cliquez pour télécharger',
|
||||||
|
or_drag_and_drop_files: 'ou faites glisser-déposer des fichiers',
|
||||||
|
uploading: 'Téléchargement en cours',
|
||||||
|
processing_: 'Traitement en cours...',
|
||||||
|
add_pdf_documents_or_images: 'Ajoutez des documents PDF ou des images',
|
||||||
|
add_documents_or_images: 'Ajoutez des documents ou des images',
|
||||||
|
required: 'Requis',
|
||||||
|
default_value: 'Valeur par défaut',
|
||||||
|
format: 'Format',
|
||||||
|
read_only: 'Lecture seule',
|
||||||
|
page: 'Page',
|
||||||
|
draw_new_area: 'Dessiner une nouvelle zone',
|
||||||
|
copy_to_all_pages: 'Copier sur toutes les pages',
|
||||||
|
add_option: 'Ajouter une option',
|
||||||
|
option: 'Option',
|
||||||
|
first_party: 'Première partie',
|
||||||
|
second_party: 'Deuxième partie',
|
||||||
|
third_party: 'Troisième partie',
|
||||||
|
fourth_party: 'Quatrième partie',
|
||||||
|
fifth_party: 'Cinquième partie',
|
||||||
|
sixth_party: 'Sixième partie',
|
||||||
|
seventh_party: 'Septième partie',
|
||||||
|
eighth_party: 'Huitième partie',
|
||||||
|
ninth_party: 'Neuvième partie',
|
||||||
|
tenth_party: 'Dixième partie',
|
||||||
|
eleventh_party: 'Onzième Parti',
|
||||||
|
twelfth_party: 'Douzième Parti',
|
||||||
|
thirteenth_party: 'Treizième Parti',
|
||||||
|
fourteenth_party: 'Quatorzième Parti',
|
||||||
|
fifteenth_party: 'Quinzième Parti',
|
||||||
|
sixteenth_party: 'Seizième Parti',
|
||||||
|
seventeenth_party: 'Dix-septième Parti',
|
||||||
|
eighteenth_party: 'Dix-huitième Parti',
|
||||||
|
nineteenth_party: 'Dix-Neuvième Fête',
|
||||||
|
twentieth_party: 'Vingtième Fête',
|
||||||
|
draw: 'Dessiner',
|
||||||
|
add: 'Ajouter',
|
||||||
|
or_add_field_without_drawing: 'Ou ajoutez un champ sans dessiner',
|
||||||
|
text: 'Texte',
|
||||||
|
signature: 'Signature',
|
||||||
|
initials: 'Initiales',
|
||||||
|
date: 'Date',
|
||||||
|
number: 'Numéro',
|
||||||
|
image: 'Image',
|
||||||
|
file: 'Fichier',
|
||||||
|
select: 'Choisir',
|
||||||
|
checkbox: 'Coche',
|
||||||
|
multiple: 'Multiple',
|
||||||
|
radio: 'Radio',
|
||||||
|
cells: 'Cellules',
|
||||||
|
stamp: 'Tampon',
|
||||||
|
payment: 'Paiement',
|
||||||
|
phone: 'Téléphone',
|
||||||
|
text_field: 'Champ de Texte',
|
||||||
|
signature_field: 'Champ de Signature',
|
||||||
|
initials_field: "Champ d'Initiales",
|
||||||
|
date_field: 'Champ de Date',
|
||||||
|
number_field: 'Champ de Numéro',
|
||||||
|
image_field: "Champ d'Image",
|
||||||
|
file_field: 'Champ de Fichier',
|
||||||
|
select_field: 'Champ de Choix',
|
||||||
|
checkbox_field: 'Champ de Coche',
|
||||||
|
multiple_field: 'Champ de Choix Multiple',
|
||||||
|
radio_field: 'Champ de Groupe Radio',
|
||||||
|
cells_field: 'Champ de Cellules',
|
||||||
|
stamp_field: 'Champ de Tampon',
|
||||||
|
payment_field: 'Champ de Paiement',
|
||||||
|
phone_field: 'Champ de Téléphone',
|
||||||
|
draw_a_text_field_on_the_page_with_a_mouse: 'Dessinez un champ texte sur la page avec une souris',
|
||||||
|
drag_and_drop_any_other_field_type_on_the_page: 'Glissez et déposez tout autre type de champ sur la page',
|
||||||
|
click_on_the_field_type_above_to_start_drawing_it: 'Cliquez sur le type de champ ci-dessus pour commencer à le dessiner',
|
||||||
|
please_draw_fields_to_prepare_the_document: 'Veuillez dessiner les champs pour préparer le document.',
|
||||||
|
only_pdf_and_images_are_supported: 'Seuls les PDF et les images sont pris en charge.',
|
||||||
|
unlock_sms_verified_phone_number_field_with_paid_plan_use_text_field_for_phone_numbers_without_verification: 'Débloquez le champ de numéro de téléphone vérifié par SMS avec un plan payant. Utilisez un champ texte pour les numéros de téléphone sans vérification.',
|
||||||
|
available_only_in_pro: 'Disponible uniquement en Pro',
|
||||||
|
failed_to_download_files: 'Échec du téléchargement des fichiers',
|
||||||
|
signature_is_too_small_please_redraw: 'La signature est trop petite. Veuillez la redessiner.',
|
||||||
|
please_add_fields_for_the_submitter_name_or_remove_the_submitter_name_if_not_needed: 'Veuillez ajouter des champs pour {submitter_name} ou retirer {submitter_name} si ce n\'est pas nécessaire.',
|
||||||
|
draw_field: 'Dessiner le champ {field}',
|
||||||
|
replace: 'Remplacer',
|
||||||
|
uploading_: 'Téléchargement en cours...',
|
||||||
|
add_document: 'Télécharger',
|
||||||
|
any: 'Tout',
|
||||||
|
drawn: 'Dessiné',
|
||||||
|
typed: 'Tapé',
|
||||||
|
none: 'Aucun',
|
||||||
|
ssn: 'SSN',
|
||||||
|
ein: 'EIN',
|
||||||
|
email: 'E-mail',
|
||||||
|
url: 'URL',
|
||||||
|
zip: 'ZIP',
|
||||||
|
custom: 'Personnalisé',
|
||||||
|
numbers_only: 'Chiffres uniquement',
|
||||||
|
letters_only: 'Lettres uniquement',
|
||||||
|
regexp_validation: 'Validation par expression régulière',
|
||||||
|
enter_pdf_password: 'Entrez le mot de passe PDF',
|
||||||
|
wrong_password: 'Mot de passe incorrect',
|
||||||
|
currency: 'Devise',
|
||||||
|
save_and_preview: 'Enregistrer et prévisualiser',
|
||||||
|
preferences: 'Préférences',
|
||||||
|
available_in_pro: 'Disponible en version Pro',
|
||||||
|
some_fields_are_missing_in_the_formula: 'Certains champs manquent dans la formule.',
|
||||||
|
learn_more: 'En savoir plus'
|
||||||
|
}
|
||||||
|
|
||||||
|
const de = {
|
||||||
|
editable: 'Bearbeitbar',
|
||||||
|
search_field: 'Suchfeld',
|
||||||
|
field_not_found: 'Feld nicht gefunden',
|
||||||
|
clear: 'Löschen',
|
||||||
|
type_value: 'Wert eingeben',
|
||||||
|
add_all_required_fields_to_continue: 'Fügen Sie alle erforderlichen Felder hinzu, um fortzufahren',
|
||||||
|
uploaded_pdf_contains_form_fields_keep_or_remove_them: 'Das hochgeladene PDF enthält Formularfelder. Behalten oder entfernen?',
|
||||||
|
keep: 'Behalten',
|
||||||
|
align: 'Ausrichten',
|
||||||
|
left: 'Links',
|
||||||
|
heading: 'Überschrift',
|
||||||
|
validation: 'Validierung',
|
||||||
|
add_blank_page: 'Leere Seite hinzufügen',
|
||||||
|
right: 'Rechts',
|
||||||
|
add_condition: 'Bedingung hinzufügen',
|
||||||
|
center: 'Zentriert',
|
||||||
|
with_logo: 'Mit Logo',
|
||||||
|
description: 'Beschreibung',
|
||||||
|
display_title: 'Anzeigetitel',
|
||||||
|
unchecked: 'Nicht überprüft',
|
||||||
|
price: 'Preis',
|
||||||
|
equal: 'Gleich',
|
||||||
|
not_equal: 'Ungleich',
|
||||||
|
contains: 'Enthält',
|
||||||
|
does_not_contain: 'Enthält nicht',
|
||||||
|
not_empty: 'Nicht leer',
|
||||||
|
empty: 'Leer',
|
||||||
|
signing_date: 'Signaturdatum',
|
||||||
|
select_field_: 'Feld auswählen...',
|
||||||
|
select_value_: 'Wert auswählen...',
|
||||||
|
remove_condition: 'Bedingung entfernen',
|
||||||
|
condition: 'Bedingung',
|
||||||
|
formula: 'Formel',
|
||||||
|
edit: 'Bearbeiten',
|
||||||
|
settings: 'Einstellungen',
|
||||||
|
up: 'Nach oben',
|
||||||
|
down: 'Nach unten',
|
||||||
|
set_signing_date: 'Unterschriftdatum festlegen',
|
||||||
|
are_you_sure_: 'Bist du sicher?',
|
||||||
|
sign_yourself: 'Unterschreiben Sie selbst',
|
||||||
|
checked: 'Ausgewählt',
|
||||||
|
send: 'Senden',
|
||||||
|
remove: 'Entfernen',
|
||||||
|
save: 'Speichern',
|
||||||
|
cancel: 'Abbrechen',
|
||||||
|
draw_field_on_the_document: 'Ein Feld auf dem Dokument zeichnen',
|
||||||
|
click_to_upload: 'Klicken Sie zum Hochladen',
|
||||||
|
or_drag_and_drop_files: 'oder Dateien hierher ziehen',
|
||||||
|
uploading: 'Hochladen',
|
||||||
|
processing_: 'Verarbeitung...',
|
||||||
|
add_pdf_documents_or_images: 'PDF-Dokumente oder Bilder hinzufügen',
|
||||||
|
add_documents_or_images: 'Dokumente oder Bilder hinzufügen',
|
||||||
|
required: 'Erforderlich',
|
||||||
|
default_value: 'Standardwert',
|
||||||
|
format: 'Format',
|
||||||
|
read_only: 'Nur lesen',
|
||||||
|
page: 'Seite',
|
||||||
|
draw_new_area: 'Neuen Bereich zeichnen',
|
||||||
|
copy_to_all_pages: 'Auf alle Seiten kopieren',
|
||||||
|
add_option: 'Option hinzufügen',
|
||||||
|
option: 'Option',
|
||||||
|
first_party: 'Erste Partei',
|
||||||
|
second_party: 'Zweite Partei',
|
||||||
|
third_party: 'Dritte Partei',
|
||||||
|
fourth_party: 'Vierte Partei',
|
||||||
|
fifth_party: 'Fünfte Partei',
|
||||||
|
sixth_party: 'Sechste Partei',
|
||||||
|
seventh_party: 'Siebte Partei',
|
||||||
|
eighth_party: 'Achte Partei',
|
||||||
|
ninth_party: 'Neunte Partei',
|
||||||
|
tenth_party: 'Zehnte Partei',
|
||||||
|
eleventh_party: 'Elfte Partei',
|
||||||
|
twelfth_party: 'Zwölfte Partei',
|
||||||
|
thirteenth_party: 'Dreizehnte Partei',
|
||||||
|
fourteenth_party: 'Vierzehnte Partei',
|
||||||
|
fifteenth_party: 'Fünfzehnte Partei',
|
||||||
|
sixteenth_party: 'Sechzehnte Partei',
|
||||||
|
seventeenth_party: 'Siebzehnte Partei',
|
||||||
|
eighteenth_party: 'Achtzehnte Partei',
|
||||||
|
nineteenth_party: 'Neunzehnte Party',
|
||||||
|
twentieth_party: 'Zwanzigste Party',
|
||||||
|
draw: 'Zeichnen',
|
||||||
|
add: 'Hinzufügen',
|
||||||
|
or_add_field_without_drawing: 'Oder Feld ohne Zeichnung hinzufügen',
|
||||||
|
text: 'Text',
|
||||||
|
signature: 'Unterschrift',
|
||||||
|
initials: 'Initialen',
|
||||||
|
date: 'Datum',
|
||||||
|
number: 'Nummer',
|
||||||
|
image: 'Bild',
|
||||||
|
file: 'Datei',
|
||||||
|
select: 'Auswählen',
|
||||||
|
checkbox: 'Checkbox',
|
||||||
|
multiple: 'Mehrere',
|
||||||
|
radio: 'Radio',
|
||||||
|
cells: 'Zellen',
|
||||||
|
stamp: 'Stempel',
|
||||||
|
payment: 'Zahlung',
|
||||||
|
phone: 'Telefon',
|
||||||
|
text_field: 'Textfeld',
|
||||||
|
signature_field: 'Unterschriftsfeld',
|
||||||
|
initials_field: 'Initialenfeld',
|
||||||
|
date_field: 'Datumsfeld',
|
||||||
|
number_field: 'Zahlenfeld',
|
||||||
|
image_field: 'Bildfeld',
|
||||||
|
file_field: 'Dateifeld',
|
||||||
|
select_field: 'Auswahlfeld',
|
||||||
|
checkbox_field: 'Checkbox-Feld',
|
||||||
|
multiple_field: 'Mehrfach-Auswahlfeld',
|
||||||
|
radio_field: 'Radio-Gruppenfeld',
|
||||||
|
cells_field: 'Zellenfeld',
|
||||||
|
stamp_field: 'Stempelfeld',
|
||||||
|
payment_field: 'Zahlungsfeld',
|
||||||
|
phone_field: 'Telefonfeld',
|
||||||
|
draw_a_text_field_on_the_page_with_a_mouse: 'Textfeld auf der Seite mit der Maus zeichnen',
|
||||||
|
drag_and_drop_any_other_field_type_on_the_page: 'Ziehe und lasse einen anderen Feldtyp auf die Seite fallen',
|
||||||
|
click_on_the_field_type_above_to_start_drawing_it: 'Klicke auf den Feldtyp oben, um mit dem Zeichnen zu beginnen',
|
||||||
|
please_draw_fields_to_prepare_the_document: 'Bitte zeichne Felder, um das Dokument vorzubereiten.',
|
||||||
|
only_pdf_and_images_are_supported: 'Nur PDFs und Bilder werden unterstützt.',
|
||||||
|
unlock_sms_verified_phone_number_field_with_paid_plan_use_text_field_for_phone_numbers_without_verification: 'Schalte das SMS-verifizierte Telefonnummernfeld mit einem kostenpflichtigen Plan frei. Verwende das Textfeld für Telefonnummern ohne Verifizierung.',
|
||||||
|
available_only_in_pro: 'Nur in Pro verfügbar',
|
||||||
|
failed_to_download_files: 'Fehler beim Herunterladen der Dateien',
|
||||||
|
signature_is_too_small_please_redraw: 'Die Unterschrift ist zu klein. Bitte erneut zeichnen.',
|
||||||
|
please_add_fields_for_the_submitter_name_or_remove_the_submitter_name_if_not_needed: 'Bitte füge Felder für {submitter_name} hinzu oder entferne {submitter_name}, falls nicht erforderlich.',
|
||||||
|
draw_field: 'Feld {field} zeichnen',
|
||||||
|
replace: 'Ersetzen',
|
||||||
|
uploading_: 'Hochladen...',
|
||||||
|
add_document: 'Hochladen',
|
||||||
|
any: 'Jede',
|
||||||
|
drawn: 'Gezeichnet',
|
||||||
|
typed: 'Getippt',
|
||||||
|
none: 'Keine',
|
||||||
|
ssn: 'SSN',
|
||||||
|
ein: 'EIN',
|
||||||
|
email: 'E-Mail',
|
||||||
|
url: 'URL',
|
||||||
|
zip: 'ZIP',
|
||||||
|
custom: 'Benutzerdefiniert',
|
||||||
|
numbers_only: 'Nur Zahlen',
|
||||||
|
letters_only: 'Nur Buchstaben',
|
||||||
|
regexp_validation: 'Regulärer Ausdruck Überprüfung',
|
||||||
|
enter_pdf_password: 'Geben Sie das PDF-Passwort ein',
|
||||||
|
wrong_password: 'Falsches Passwort',
|
||||||
|
currency: 'Währung',
|
||||||
|
save_and_preview: 'Speichern und Vorschau',
|
||||||
|
preferences: 'Einstellungen',
|
||||||
|
available_in_pro: 'In Pro verfügbar',
|
||||||
|
some_fields_are_missing_in_the_formula: 'Einige Felder fehlen in der Formel.',
|
||||||
|
learn_more: 'Erfahren Sie mehr'
|
||||||
|
}
|
||||||
|
|
||||||
|
export { en, es, it, pt, fr, de }
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<div v-if="selectedSheetIndex === null && spreadsheet">
|
<div v-if="selectedSheetIndex === null && spreadsheet">
|
||||||
<form @submit.prevent="[selectedSheetIndex = $refs.selectWorksheet.value, buildDefaultMappings()]">
|
<form @submit.prevent="[selectedSheetIndex = $refs.selectWorksheet.value, buildDefaultMappings()]">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
Select Worksheet
|
{{ t('select_worksheet') }}
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
ref="selectWorksheet"
|
ref="selectWorksheet"
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<button class="base-button mt-4 w-full">
|
<button class="base-button mt-4 w-full">
|
||||||
Open
|
{{ t('open') }}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@@ -36,10 +36,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div class="relative w-full py-2 px-2 text-sm">
|
<div class="relative w-full py-2 px-2 text-sm">
|
||||||
Recipient field
|
{{ t('recipient_field') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="relative w-full py-2 pl-4 text-sm">
|
<div class="relative w-full py-2 pl-4 text-sm">
|
||||||
Spreadsheet column
|
{{ t('spreadsheet_column') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
value=""
|
value=""
|
||||||
:selected="!mapping.field_name"
|
:selected="!mapping.field_name"
|
||||||
>
|
>
|
||||||
Select Field
|
{{ t('select_field') }}
|
||||||
</option>
|
</option>
|
||||||
<option
|
<option
|
||||||
v-for="(field, index) in selectFieldsForSubmitter(submitter)"
|
v-for="(field, index) in selectFieldsForSubmitter(submitter)"
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
value=""
|
value=""
|
||||||
:selected="mapping.column_index == null"
|
:selected="mapping.column_index == null"
|
||||||
>
|
>
|
||||||
Select Column
|
{{ t('select_column') }}
|
||||||
</option>
|
</option>
|
||||||
<template
|
<template
|
||||||
v-for="(column, index) in columns"
|
v-for="(column, index) in columns"
|
||||||
@@ -118,8 +118,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex items-center pl-1">
|
<div class="flex items-center pl-1">
|
||||||
<span
|
<span
|
||||||
class="tooltip tooltip-top"
|
class="tooltip tooltip-left"
|
||||||
data-tip="<%= t('remove') %>"
|
:data-tip="t('remove')"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
:disabled="mappings.filter((m) => m.submitter_uuid === submitter.uuid).length < 2"
|
:disabled="mappings.filter((m) => m.submitter_uuid === submitter.uuid).length < 2"
|
||||||
@@ -138,7 +138,7 @@
|
|||||||
@click.prevent="addMapping(submitter)"
|
@click.prevent="addMapping(submitter)"
|
||||||
>
|
>
|
||||||
<IconPlus class="w-4 h-4" />
|
<IconPlus class="w-4 h-4" />
|
||||||
New Field Mapping
|
{{ t('new_field_mapping') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -152,7 +152,7 @@
|
|||||||
<div
|
<div
|
||||||
class="px-3 border-y py-2 border-base-300 text-center w-full text-sm font-semibold"
|
class="px-3 border-y py-2 border-base-300 text-center w-full text-sm font-semibold"
|
||||||
>
|
>
|
||||||
Total entries: {{ submissionsData.length }}
|
{{ t('total_entries') }}: {{ submissionsData.length }}
|
||||||
<template v-if="multitenant && submissionsData.length >= 1000">
|
<template v-if="multitenant && submissionsData.length >= 1000">
|
||||||
/ 1000
|
/ 1000
|
||||||
</template>
|
</template>
|
||||||
@@ -187,10 +187,10 @@
|
|||||||
<div
|
<div
|
||||||
class="font-medium text-lg mb-1"
|
class="font-medium text-lg mb-1"
|
||||||
>
|
>
|
||||||
Upload CSV or XLSX Spreadsheet
|
{{ t('upload_csv_or_xlsx_spreadsheet') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm">
|
<div class="text-sm">
|
||||||
<span class="font-medium">Click to Upload</span> or drag and drop files.
|
<span class="font-medium">{{ t('click_to_upload') }}</span> {{ t('or_drag_and_drop_files') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -210,11 +210,11 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-center mt-2">
|
<div class="text-center mt-2">
|
||||||
Or <a
|
{{ t('or') }} <a
|
||||||
:download="`${template.name}.csv`"
|
:download="`${template.name}.csv`"
|
||||||
:href="`data:text/csv;base64,${csvBase64}`"
|
:href="`data:text/csv;base64,${csvBase64}`"
|
||||||
class="link font-medium"
|
class="link font-medium"
|
||||||
>download</a> a spreadsheet to fill and import
|
>{{ t('download') }}</a> {{ t('a_sample_spreadsheet_to_fill_and_import') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -248,6 +248,11 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
default: ''
|
default: ''
|
||||||
|
},
|
||||||
|
i18n: {
|
||||||
|
type: Object,
|
||||||
|
required: false,
|
||||||
|
default: () => ({})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
@@ -354,6 +359,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
t (key) {
|
||||||
|
return this.i18n[key] || key
|
||||||
|
},
|
||||||
onDropFiles (e) {
|
onDropFiles (e) {
|
||||||
this.uploadFile(e.dataTransfer.files[0])
|
this.uploadFile(e.dataTransfer.files[0])
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -72,7 +72,7 @@
|
|||||||
class="absolute -top-1 left-2.5 px-1 h-4"
|
class="absolute -top-1 left-2.5 px-1 h-4"
|
||||||
style="font-size: 8px"
|
style="font-size: 8px"
|
||||||
>
|
>
|
||||||
Price
|
{{ t('price') }}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -23,21 +23,23 @@ class SubmitterMailer < ApplicationMailer
|
|||||||
|
|
||||||
reply_to = build_submitter_reply_to(@submitter)
|
reply_to = build_submitter_reply_to(@submitter)
|
||||||
|
|
||||||
subject =
|
I18n.with_locale(@current_account.locale) do
|
||||||
if @email_config || @subject
|
subject =
|
||||||
ReplaceEmailVariables.call(@subject || @email_config.value['subject'], submitter:)
|
if @email_config || @subject
|
||||||
elsif @submitter.with_signature_fields?
|
ReplaceEmailVariables.call(@subject || @email_config.value['subject'], submitter:)
|
||||||
I18n.t(:you_are_invited_to_sign_a_document)
|
elsif @submitter.with_signature_fields?
|
||||||
else
|
I18n.t(:you_are_invited_to_sign_a_document)
|
||||||
I18n.t(:you_are_invited_to_submit_a_form)
|
else
|
||||||
end
|
I18n.t(:you_are_invited_to_submit_a_form)
|
||||||
|
end
|
||||||
|
|
||||||
mail(
|
mail(
|
||||||
to: @submitter.friendly_name,
|
to: @submitter.friendly_name,
|
||||||
from: from_address_for_submitter(submitter),
|
from: from_address_for_submitter(submitter),
|
||||||
subject:,
|
subject:,
|
||||||
reply_to:
|
reply_to:
|
||||||
)
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def completed_email(submitter, user, to: nil)
|
def completed_email(submitter, user, to: nil)
|
||||||
@@ -66,13 +68,15 @@ class SubmitterMailer < ApplicationMailer
|
|||||||
|
|
||||||
assign_message_metadata('submitter_completed', @submitter)
|
assign_message_metadata('submitter_completed', @submitter)
|
||||||
|
|
||||||
subject =
|
I18n.with_locale(@current_account.locale) do
|
||||||
ReplaceEmailVariables.call(@subject.presence || I18n.t(:template_name_has_been_completed_by_submitters),
|
subject =
|
||||||
submitter:)
|
ReplaceEmailVariables.call(@subject.presence || I18n.t(:template_name_has_been_completed_by_submitters),
|
||||||
|
submitter:)
|
||||||
|
|
||||||
mail(from: from_address_for_submitter(submitter),
|
mail(from: from_address_for_submitter(submitter),
|
||||||
to: to || (user.role == 'integration' ? user.friendly_name.sub(/\+\w+@/, '@') : user.friendly_name),
|
to: to || normalize_user_email(user),
|
||||||
subject:)
|
subject:)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def declined_email(submitter, user)
|
def declined_email(submitter, user)
|
||||||
@@ -83,7 +87,7 @@ class SubmitterMailer < ApplicationMailer
|
|||||||
|
|
||||||
assign_message_metadata('submitter_declined', @submitter)
|
assign_message_metadata('submitter_declined', @submitter)
|
||||||
|
|
||||||
I18n.with_locale(submitter.account.locale) do
|
I18n.with_locale(@current_account.locale) do
|
||||||
mail(from: from_address_for_submitter(submitter),
|
mail(from: from_address_for_submitter(submitter),
|
||||||
to: user.role == 'integration' ? user.friendly_name.sub(/\+\w+@/, '@') : user.friendly_name,
|
to: user.role == 'integration' ? user.friendly_name.sub(/\+\w+@/, '@') : user.friendly_name,
|
||||||
reply_to: @submitter.friendly_name,
|
reply_to: @submitter.friendly_name,
|
||||||
@@ -116,17 +120,19 @@ class SubmitterMailer < ApplicationMailer
|
|||||||
assign_message_metadata('submitter_documents_copy', @submitter)
|
assign_message_metadata('submitter_documents_copy', @submitter)
|
||||||
reply_to = build_submitter_reply_to(submitter)
|
reply_to = build_submitter_reply_to(submitter)
|
||||||
|
|
||||||
subject =
|
I18n.with_locale(@current_account.locale) do
|
||||||
if @subject.present?
|
subject =
|
||||||
ReplaceEmailVariables.call(@subject, submitter:)
|
if @subject.present?
|
||||||
else
|
ReplaceEmailVariables.call(@subject, submitter:)
|
||||||
I18n.t(:your_document_copy)
|
else
|
||||||
end
|
I18n.t(:your_document_copy)
|
||||||
|
end
|
||||||
|
|
||||||
mail(from: from_address_for_submitter(submitter),
|
mail(from: from_address_for_submitter(submitter),
|
||||||
to: to || @submitter.friendly_name,
|
to: to || @submitter.friendly_name,
|
||||||
reply_to:,
|
reply_to:,
|
||||||
subject:)
|
subject:)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -171,6 +177,10 @@ class SubmitterMailer < ApplicationMailer
|
|||||||
documents
|
documents
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def normalize_user_email(user)
|
||||||
|
user.role == 'integration' ? user.friendly_name.sub(/\+\w+@/, '@') : user.friendly_name
|
||||||
|
end
|
||||||
|
|
||||||
def add_attachments_with_size_limit(storage_attachments, current_size)
|
def add_attachments_with_size_limit(storage_attachments, current_size)
|
||||||
total_size = current_size
|
total_size = current_size
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ class UserMailer < ApplicationMailer
|
|||||||
|
|
||||||
assign_message_metadata('user_invitation', @user)
|
assign_message_metadata('user_invitation', @user)
|
||||||
|
|
||||||
mail(to: @user.friendly_name,
|
I18n.with_locale(@current_account.locale) do
|
||||||
subject: "You are invited to #{Docuseal.product_name}")
|
mail(to: @user.friendly_name,
|
||||||
|
subject: I18n.t('you_are_invited_to_product_name', product_name: Docuseal.product_name))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -39,6 +39,7 @@ class AccountConfig < ApplicationRecord
|
|||||||
FORCE_SSO_AUTH_KEY = 'force_sso_auth'
|
FORCE_SSO_AUTH_KEY = 'force_sso_auth'
|
||||||
FLATTEN_RESULT_PDF_KEY = 'flatten_result_pdf'
|
FLATTEN_RESULT_PDF_KEY = 'flatten_result_pdf'
|
||||||
WITH_SIGNATURE_ID = 'with_signature_id'
|
WITH_SIGNATURE_ID = 'with_signature_id'
|
||||||
|
WITH_AUDIT_VALUES_KEY = 'with_audit_values'
|
||||||
REQUIRE_SIGNING_REASON_KEY = 'require_signing_reason'
|
REQUIRE_SIGNING_REASON_KEY = 'require_signing_reason'
|
||||||
COMBINE_PDF_RESULT_KEY = 'combine_pdf_result_key'
|
COMBINE_PDF_RESULT_KEY = 'combine_pdf_result_key'
|
||||||
|
|
||||||
|
|||||||
@@ -86,11 +86,11 @@ class Submitter < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def first_name
|
def first_name
|
||||||
name.split(/\s+/, 2).first
|
name&.split(/\s+/, 2)&.first
|
||||||
end
|
end
|
||||||
|
|
||||||
def last_name
|
def last_name
|
||||||
name.split(/\s+/, 2).last
|
name&.split(/\s+/, 2)&.last
|
||||||
end
|
end
|
||||||
|
|
||||||
def status_event_at
|
def status_event_at
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class Template < ApplicationRecord
|
|||||||
attribute :preferences, :string, default: -> { {} }
|
attribute :preferences, :string, default: -> { {} }
|
||||||
attribute :fields, :string, default: -> { [] }
|
attribute :fields, :string, default: -> { [] }
|
||||||
attribute :schema, :string, default: -> { [] }
|
attribute :schema, :string, default: -> { [] }
|
||||||
attribute :submitters, :string, default: -> { [{ name: DEFAULT_SUBMITTER_NAME, uuid: SecureRandom.uuid }] }
|
attribute :submitters, :string, default: -> { [{ name: I18n.t(:first_party), uuid: SecureRandom.uuid }] }
|
||||||
attribute :slug, :string, default: -> { SecureRandom.base58(14) }
|
attribute :slug, :string, default: -> { SecureRandom.base58(14) }
|
||||||
attribute :source, :string, default: 'native'
|
attribute :source, :string, default: 'native'
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= ff.label :locale, t('time_format'), class: 'label' %>
|
<%= ff.label :locale, t('language'), class: 'label' %>
|
||||||
<%= ff.select :locale, options_for_select(controller.class::LOCALE_OPTIONS.invert, current_account.locale), {}, class: 'base-select' %>
|
<%= ff.select :locale, options_for_select(AccountsController::LOCALE_OPTIONS.invert, current_account.locale), {}, class: 'base-select' %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<div class="flex flex-wrap space-y-4 md:flex-nowrap md:space-y-0 md:space-x-10">
|
<div class="flex flex-wrap space-y-4 md:flex-nowrap md:space-y-0 md:space-x-10">
|
||||||
<%= render 'shared/settings_nav' %>
|
<%= render 'shared/settings_nav' %>
|
||||||
<div class="flex-grow">
|
<div class="flex-grow">
|
||||||
<div class="flex justify-between">
|
<div class="flex flex-col gap-2 md:flex-row md:justify-between md:items-end mb-4">
|
||||||
<h1 class="text-4xl font-bold mb-4">API</h1>
|
<h1 class="text-4xl font-bold">API</h1>
|
||||||
<%= render 'shared/test_mode_toggle' %>
|
<%= render 'shared/test_mode_toggle' %>
|
||||||
</div>
|
</div>
|
||||||
<div class="card bg-base-200">
|
<div class="card bg-base-200">
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= ff.label :security_label, 'SMTP Security', class: 'label' %>
|
<%= ff.label :security_label, 'SMTP Security', class: 'label' %>
|
||||||
<div class="flex items-center space-x-6">
|
<div class="flex items-center space-x-6">
|
||||||
<% [%w[Auto none], %w[SSL ssl], %w[TLS tls]].each do |(label, val)| %>
|
<% [%w[Auto none], %w[SSL ssl], %w[TLS tls], %w[Noverify noverify]].each do |(label, val)| %>
|
||||||
<%= ff.label :security, value: val, for: "#{val}_radio", class: 'label' do %>
|
<%= ff.label :security, value: val, for: "#{val}_radio", class: 'label' do %>
|
||||||
<%= ff.radio_button :security, val, checked: (value['security'].blank? && val == 'none') || value['security'] == val, id: "#{val}_radio", class: 'base-radio mr-2' %>
|
<%= ff.radio_button :security, val, checked: (value['security'].blank? && val == 'none') || value['security'] == val, id: "#{val}_radio", class: 'base-radio mr-2' %>
|
||||||
<%= label %>
|
<%= label %>
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<tr scope="row" class="group">
|
||||||
|
<td class="flex items-center space-x-1">
|
||||||
|
<%= svg_icon('discount_check_filled', class: 'w-6 h-6 text-green-500') %>
|
||||||
|
<span class="flex items-center">
|
||||||
|
<%= t('docuseal_trusted_signature') %>
|
||||||
|
<div class="tooltip ml-1" data-tip="<%= t('sign_documents_with_trusted_certificate_provided_by_docu_seal_your_documents_and_data_are_never_shared_with_docu_seal_p_d_f_checksum_is_provided_to_generate_a_trusted_signature') %>">
|
||||||
|
<%= svg_icon('circle_question', class: 'w-4 h-4 stroke-1') %>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="<%= "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premise" }.to_query}" %>" class="btn btn-neutral btn-sm text-white">
|
||||||
|
<%= t('unlock_with_docuseal_pro') %>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="tooltip" data-tip="<%= t('unlock_with_docuseal_pro') %>">
|
||||||
|
<%= button_to settings_esign_path, method: :put, params: { name: Docuseal::AATL_CERT_NAME }, class: 'btn btn-outline btn-neutral btn-xs whitespace-nowrap', title: t('make_default'), disabled: true do %>
|
||||||
|
<%= t('make_default') %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= f.label :file, t('file'), class: 'label' %>
|
<%= f.label :file, t('file'), class: 'label' %>
|
||||||
<%= f.file_field :file, required: true %>
|
<%= f.file_field :file, class: 'file-input file-input-bordered w-full', required: true %>
|
||||||
<label class="label">
|
<label class="label">
|
||||||
<span class="label-text-alt">
|
<span class="label-text-alt">
|
||||||
<%= t('use_a_valid_der_p12_or_pfx_file') %>
|
<%= t('use_a_valid_der_p12_or_pfx_file') %>
|
||||||
|
|||||||
@@ -19,8 +19,8 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
<file-dropzone data-name="verify_attachments" data-submit-on-upload="true" class="w-full">
|
<file-dropzone data-name="verify_attachments" data-submit-on-upload="true" class="w-full">
|
||||||
<label for="file" class="w-full block h-32 relative bg-base-200 hover:bg-base-200/70 rounded-md border border-base-content border-dashed">
|
<label for="file" class="w-full block h-32 relative bg-base-200 hover:bg-base-200/70 rounded-md border border-base-content border-dashed">
|
||||||
<div class="absolute top-0 right-0 left-0 bottom-0 flex items-center justify-center">
|
<div class="absolute top-0 right-0 left-0 bottom-0 flex items-center justify-center p-2">
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center text-center">
|
||||||
<span data-target="file-dropzone.icon">
|
<span data-target="file-dropzone.icon">
|
||||||
<%= svg_icon('cloud_upload', class: 'w-10 h-10') %>
|
<%= svg_icon('cloud_upload', class: 'w-10 h-10') %>
|
||||||
</span>
|
</span>
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
</file-dropzone>
|
</file-dropzone>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between items-end mb-4 mt-8">
|
<div class="flex flex-col md:flex-row gap-2 md:justify-between md:items-end mb-4 mt-8">
|
||||||
<h2 class="text-3xl font-bold">
|
<h2 class="text-3xl font-bold">
|
||||||
<%= t('signing_certificates') %>
|
<%= t('signing_certificates') %>
|
||||||
</h2>
|
</h2>
|
||||||
@@ -71,6 +71,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<% @pkcs_list.each do |item| %>
|
<% @pkcs_list.each do |item| %>
|
||||||
|
<% next if item['pkcs'].blank? %>
|
||||||
<tr scope="row" class="group">
|
<tr scope="row" class="group">
|
||||||
<td>
|
<td>
|
||||||
<%= item['name'] %>
|
<%= item['name'] %>
|
||||||
@@ -98,6 +99,9 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<% unless Docuseal.multitenant? %>
|
||||||
|
<%= render 'default_signature_row' %>
|
||||||
|
<% end %>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path d="M12.01 2.011a3.2 3.2 0 0 1 2.113 .797l.154 .145l.698 .698a1.2 1.2 0 0 0 .71 .341l.135 .008h1a3.2 3.2 0 0 1 3.195 3.018l.005 .182v1c0 .27 .092 .533 .258 .743l.09 .1l.697 .698a3.2 3.2 0 0 1 .147 4.382l-.145 .154l-.698 .698a1.2 1.2 0 0 0 -.341 .71l-.008 .135v1a3.2 3.2 0 0 1 -3.018 3.195l-.182 .005h-1a1.2 1.2 0 0 0 -.743 .258l-.1 .09l-.698 .697a3.2 3.2 0 0 1 -4.382 .147l-.154 -.145l-.698 -.698a1.2 1.2 0 0 0 -.71 -.341l-.135 -.008h-1a3.2 3.2 0 0 1 -3.195 -3.018l-.005 -.182v-1a1.2 1.2 0 0 0 -.258 -.743l-.09 -.1l-.697 -.698a3.2 3.2 0 0 1 -.147 -4.382l.145 -.154l.698 -.698a1.2 1.2 0 0 0 .341 -.71l.008 -.135v-1l.005 -.182a3.2 3.2 0 0 1 3.013 -3.013l.182 -.005h1a1.2 1.2 0 0 0 .743 -.258l.1 -.09l.698 -.697a3.2 3.2 0 0 1 2.269 -.944zm3.697 7.282a1 1 0 0 0 -1.414 0l-3.293 3.292l-1.293 -1.292l-.094 -.083a1 1 0 0 0 -1.32 1.497l2 2l.094 .083a1 1 0 0 0 1.32 -.083l4 -4l.083 -.094a1 1 0 0 0 -.083 -1.32z" stroke-width="0" fill="currentColor" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -6,7 +6,7 @@
|
|||||||
<span>
|
<span>
|
||||||
<%= t('completed_documents_notification_bcc_address') %>
|
<%= t('completed_documents_notification_bcc_address') %>
|
||||||
</span>
|
</span>
|
||||||
<span class="tooltip" data-tip="Send email copy with completed documents to a specified BCC address.">
|
<span class="tooltip" data-tip="<%= t('send_email_copy_with_completed_documents_to_a_specified_bcc_address') %>">
|
||||||
<%= svg_icon('info_circle', class: 'w-4 h-4') %>
|
<%= svg_icon('info_circle', class: 'w-4 h-4') %>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -3,22 +3,22 @@
|
|||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<% record = Struct.new(:first_duration, :second_duration, :third_duration).new(*(f.object.value || {}).values_at('first_duration', 'second_duration', 'third_duration')) %>
|
<% record = Struct.new(:first_duration, :second_duration, :third_duration).new(*(f.object.value || {}).values_at('first_duration', 'second_duration', 'third_duration')) %>
|
||||||
<% durations = (Docuseal.multitenant? ? AccountConfigs::REMINDER_DURATIONS.except('one_hour', 'two_hours') : AccountConfigs::REMINDER_DURATIONS).keys.map { |v| [t(v.underscore), v] } %>
|
<% durations = (Docuseal.multitenant? ? AccountConfigs::REMINDER_DURATIONS.except('one_hour', 'two_hours') : AccountConfigs::REMINDER_DURATIONS).keys.map { |v| [t(v.underscore), v] } %>
|
||||||
<div class="flex flex-col md:flex-row gap-4">
|
<div class="flex flex-col md:flex-row gap-2">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<%= f.fields_for :value, record do |ff| %>
|
<%= f.fields_for :value, record do |ff| %>
|
||||||
<%= ff.label :first_duration, t('first_reminder_in'), class: 'label' %>
|
<%= ff.label :first_duration, t('first_reminder_in'), class: 'label truncate' %>
|
||||||
<%= ff.select :first_duration, durations, { include_blank: 'None' }, class: 'base-select' %>
|
<%= ff.select :first_duration, durations, { include_blank: 'None' }, class: 'base-select' %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<%= f.fields_for :value, record do |ff| %>
|
<%= f.fields_for :value, record do |ff| %>
|
||||||
<%= ff.label :second_duration, t('second_reminder_in'), class: 'label' %>
|
<%= ff.label :second_duration, t('second_reminder_in'), class: 'label truncate' %>
|
||||||
<%= ff.select :second_duration, durations, { include_blank: 'None' }, class: 'base-select' %>
|
<%= ff.select :second_duration, durations, { include_blank: 'None' }, class: 'base-select' %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<%= f.fields_for :value, record do |ff| %>
|
<%= f.fields_for :value, record do |ff| %>
|
||||||
<%= ff.label :third_duration, t('third_reminder_in'), class: 'label' %>
|
<%= ff.label :third_duration, t('third_reminder_in'), class: 'label truncate' %>
|
||||||
<%= ff.select :third_duration, durations, { include_blank: 'None' }, class: 'base-select' %>
|
<%= ff.select :third_duration, durations, { include_blank: 'None' }, class: 'base-select' %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
<div class="collapse-title text-xl font-medium capitalize">
|
<div class="collapse-title text-xl font-medium capitalize">
|
||||||
<div>
|
<div>
|
||||||
<%= t('copleted_notification_email') %>
|
<%= t('completed_notification_email') %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse-content">
|
<div class="collapse-content">
|
||||||
|
|||||||
@@ -56,6 +56,12 @@
|
|||||||
<%= ff.text_field :value, required: true, class: 'base-input' %>
|
<%= ff.text_field :value, required: true, class: 'base-input' %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<%= fields_for @account do |ff| %>
|
||||||
|
<div class="form-control">
|
||||||
|
<%= ff.label :locale, t('language'), class: 'label' %>
|
||||||
|
<%= ff.select :locale, options_for_select(AccountsController::LOCALE_OPTIONS.invert, @account.locale), {}, class: 'base-select' %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= f.button button_title, class: 'base-button' %>
|
<%= f.button button_title, class: 'base-button' %>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<span class="peer-checked:hidden flex items-center space-x-2">
|
<span class="peer-checked:hidden flex items-center space-x-2">
|
||||||
<%= svg_icon(local_assigns[:icon] || 'link', class: local_assigns[:icon_class] || 'w-6 h-6 text-white') %>
|
<%= svg_icon(local_assigns[:icon] || 'link', class: local_assigns[:icon_class] || 'w-6 h-6 text-white') %>
|
||||||
<span class="hidden md:inline">
|
<span class="hidden md:inline">
|
||||||
<%= local_assigns[:copy_title] || 'Copy' %>
|
<%= local_assigns[:copy_title] || t('copy') %>
|
||||||
</span>
|
</span>
|
||||||
<% if local_assigns[:copy_title_md] %>
|
<% if local_assigns[:copy_title_md] %>
|
||||||
<span class="inline md:hidden">
|
<span class="inline md:hidden">
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
<span class="hidden peer-checked:flex items-center space-x-2">
|
<span class="hidden peer-checked:flex items-center space-x-2">
|
||||||
<%= svg_icon(local_assigns[:copied_icon] || 'clipboard_copy', class: local_assigns[:icon_class] || 'w-6 h-6 text-white') %>
|
<%= svg_icon(local_assigns[:copied_icon] || 'clipboard_copy', class: local_assigns[:icon_class] || 'w-6 h-6 text-white') %>
|
||||||
<span class="hidden md:inline">
|
<span class="hidden md:inline">
|
||||||
<%= local_assigns[:copied_title] || 'Copied' %>
|
<%= local_assigns[:copied_title] || t('copied') %>
|
||||||
</span>
|
</span>
|
||||||
<% if local_assigns[:copied_title_md] %>
|
<% if local_assigns[:copied_title_md] %>
|
||||||
<span class="inline md:hidden">
|
<span class="inline md:hidden">
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
---
|
---
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Sent using <a href="<%= Docuseal::PRODUCT_URL %>/start"><%= Docuseal.product_name %></a> free document signing.
|
<%= t('sent_using_product_name_free_document_signing_html', product_url: "#{Docuseal::PRODUCT_URL}/start", product_name: Docuseal.product_name) %>
|
||||||
</p>
|
</p>
|
||||||
@@ -15,5 +15,5 @@
|
|||||||
<%= yield %>
|
<%= yield %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<label class="modal-backdrop" for="<%= uuid %>"><%= t('close') %></label>
|
<label class="modal-backdrop" for="<%= uuid %>"></label>
|
||||||
</div>
|
</div>
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
<label tabindex="0" class="cursor-pointer bg-base-content text-purple-300 rounded-full p-2 w-9 justify-center flex">
|
<label tabindex="0" class="cursor-pointer bg-base-content text-purple-300 rounded-full p-2 w-9 justify-center flex">
|
||||||
<span class="text-sm align-text-top"><%= current_user.initials %></span>
|
<span class="text-sm align-text-top"><%= current_user.initials %></span>
|
||||||
</label>
|
</label>
|
||||||
<ul tabindex="0" class="z-10 dropdown-content p-2 mt-2 shadow menu text-base bg-base-100 rounded-box w-40 text-right">
|
<ul tabindex="0" class="z-10 dropdown-content p-2 mt-2 shadow menu text-base bg-base-100 rounded-box min-w-[160px] text-right">
|
||||||
<li>
|
<li>
|
||||||
<%= link_to settings_profile_index_path, class: 'flex items-center' do %>
|
<%= link_to settings_profile_index_path, class: 'flex items-center' do %>
|
||||||
<%= svg_icon('adjustments', class: 'w-5 h-5 flex-shrink-0 stroke-2') %>
|
<%= svg_icon('adjustments', class: 'w-5 h-5 flex-shrink-0 stroke-2') %>
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
<% if !Docuseal.demo? && can?(:manage, EncryptedConfig) %>
|
<% if !Docuseal.demo? && can?(:manage, EncryptedConfig) %>
|
||||||
<li>
|
<li>
|
||||||
<%= link_to Docuseal.multitenant? ? console_redirect_index_path : Docuseal::CONSOLE_URL, data: { prefetch: false }, class: 'flex items-center' do %>
|
<%= link_to Docuseal.multitenant? ? console_redirect_index_path : Docuseal::CONSOLE_URL, data: { prefetch: false }, class: 'flex items-center' do %>
|
||||||
<%= svg_icon('terminal', class: 'w-5 h-5 stroke-2') %>
|
<%= svg_icon('terminal', class: 'w-5 h-5 flex-shrink-0 stroke-2') %>
|
||||||
<%= t('console') %>
|
<%= t('console') %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</li>
|
</li>
|
||||||
@@ -44,15 +44,15 @@
|
|||||||
<% if can?(:read, EncryptedConfig.new(key: EncryptedConfig::ESIGN_CERTS_KEY, account: current_account)) %>
|
<% if can?(:read, EncryptedConfig.new(key: EncryptedConfig::ESIGN_CERTS_KEY, account: current_account)) %>
|
||||||
<li>
|
<li>
|
||||||
<%= link_to settings_esign_path, class: 'flex items-center' do %>
|
<%= link_to settings_esign_path, class: 'flex items-center' do %>
|
||||||
<%= svg_icon('zoom_check', class: 'w-5 h-5 stroke-2') %>
|
<%= svg_icon('zoom_check', class: 'w-5 h-5 flex-shrink-0 stroke-2') %>
|
||||||
<span class="mr-1"><%= t('verify_pdf') %></span>
|
<span class="mr-1 whitespace-nowrap"><%= t('verify_pdf') %></span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
<li>
|
<li>
|
||||||
<%= button_to destroy_user_session_path, method: :delete, data: { turbo: false }, class: 'flex items-center' do %>
|
<%= button_to destroy_user_session_path, method: :delete, data: { turbo: false }, class: 'flex items-center' do %>
|
||||||
<%= svg_icon('logout', class: 'w-5 h-5 stroke-2 mr-2 inline') %>
|
<%= svg_icon('logout', class: 'w-5 h-5 flex-shrink-0 stroke-2 mr-2 inline') %>
|
||||||
<span class="mr-1"><%= t('sign_out') %></span>
|
<span class="mr-1 whitespace-nowrap"><%= t('sign_out') %></span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -9,5 +9,5 @@
|
|||||||
<% else %>
|
<% else %>
|
||||||
<%= t('powered_by') %>
|
<%= t('powered_by') %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<a href="<%= Docuseal::PRODUCT_URL %><%= local_assigns[:link_path] %>" class="underline"><%= Docuseal.product_name %></a> - open source documents software
|
<a href="<%= Docuseal::PRODUCT_URL %><%= local_assigns[:link_path] %>" class="underline"><%= Docuseal.product_name %></a> - <%= t('open_source_documents_software') %>
|
||||||
</div>
|
</div>
|
||||||
@@ -4,15 +4,15 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
<% if params[:q].present? %>
|
<% if params[:q].present? %>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<a href="<%= url_for(params.to_unsafe_h.except(:q)) %>" title="Clear" class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-auto text-neutral text-2xl font-extralight">
|
<a href="<%= url_for(params.to_unsafe_h.except(:q)) %>" title="<%= t('clear') %>" class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-auto text-neutral text-2xl font-extralight">
|
||||||
×
|
×
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<search-input data-title="<%= local_assigns[:title_selector] || 'h1' %>">
|
<search-input data-title="<%= local_assigns[:title_selector] || 'h1' %>">
|
||||||
<input id="search" name="q" value="<%= params[:q] %>" class="input input-ghost text-lg pr-10 -mr-12 w-0 md:w-64 <%= 'pl-8 input-outlined w-64' if params[:q].present? %>" placeholder="<%= local_assigns[:placeholder] %>">
|
<input id="search" name="q" value="<%= params[:q] %>" class="input text-lg pr-10 -mr-12 w-0 md:w-60 <%= 'pl-8 input-outlined w-60' if params[:q].present? %>" placeholder="<%= local_assigns[:placeholder] %>">
|
||||||
</search-input>
|
</search-input>
|
||||||
<button type="submit" title="Search" class="btn btn-ghost btn-circle" onclick="window.search.value || document.activeElement === window.search ? null : [event.preventDefault(), window.search.focus()]">
|
<button type="submit" title="<%= t('search') %>" class="btn btn-ghost btn-circle" onclick="window.search.value || document.activeElement === window.search ? null : [event.preventDefault(), window.search.focus()]">
|
||||||
<span class="enabled">
|
<span class="enabled">
|
||||||
<%= svg_icon('search', class: 'w-6 h-6 stroke-2') %>
|
<%= svg_icon('search', class: 'w-6 h-6 stroke-2') %>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<div class="block w-full md:w-52 flex-none">
|
<div class="block w-full md:w-52 flex-none">
|
||||||
<menu-active>
|
<menu-active>
|
||||||
<ul class="menu px-0">
|
<ul class="menu px-0">
|
||||||
<li class="menu-title py-0 !bg-transparent mb-3 -mt-5"><a href="<%= '/' %>" class="!bg-transparent !text-neutral font-medium">← Back</a></li>
|
<li class="menu-title py-0 !bg-transparent mb-3 -mt-5"><a href="<%= '/' %>" class="!bg-transparent !text-neutral font-medium">← <%= t('back') %></a></li>
|
||||||
<li class="menu-title py-0 !bg-transparent">
|
<li class="menu-title py-0 !bg-transparent">
|
||||||
<span class="!bg-transparent"><%= t('settings') %></span>
|
<span class="!bg-transparent"><%= t('settings') %></span>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<% if signed_in? && current_user != true_user && current_account.testing? %>
|
<% if signed_in? && current_user != true_user && current_account.testing? %>
|
||||||
<div class="alert py-1 text-sm font-medium gap-x-2 flex whitespace-nowrap">
|
<div class="hidden md:flex alert py-1 text-sm font-medium gap-x-2 whitespace-nowrap">
|
||||||
<a href="<%= testing_api_settings_path %>" data-turbo-frame="modal" class="link font-semibold flex">
|
<a href="<%= testing_api_settings_path %>" data-turbo-frame="modal" class="link font-semibold flex">
|
||||||
<%= svg_icon('code_circle', class: 'w-5 h-5 mr-1') %>
|
<%= svg_icon('code_circle', class: 'w-5 h-5 mr-1') %>
|
||||||
<span><%= t('testing_environment') %></span>
|
<span><%= t('testing_environment') %></span>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<% if can?(:manage, EncryptedConfig) || (current_user != true_user && current_account.testing?) %>
|
<% if can?(:manage, EncryptedConfig) || (current_user != true_user && current_account.testing?) %>
|
||||||
<%= form_for '', url: testing_account_path, method: current_account.testing? ? :delete : :get, html: { class: 'flex' } do |f| %>
|
<%= form_for '', url: testing_account_path, method: current_account.testing? ? :delete : :get, html: { class: 'flex' } do |f| %>
|
||||||
<label class="flex items-center justify-between py-2.5" for="testing_toggle">
|
<label class="flex items-center justify-between" for="testing_toggle">
|
||||||
<span class="mr-2 text-lg">
|
<span class="mr-2 text-lg">
|
||||||
<%= t('test_environment') %>
|
<%= t('test_environment') %>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -20,18 +20,18 @@
|
|||||||
<input type="hidden" name="submission[1][submitters][][uuid]" value="<%= item['uuid'] %>">
|
<input type="hidden" name="submission[1][submitters][][uuid]" value="<%= item['uuid'] %>">
|
||||||
<submitters-autocomplete data-field="name">
|
<submitters-autocomplete data-field="name">
|
||||||
<linked-input data-target-id="<%= "detailed_name_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
<linked-input data-target-id="<%= "detailed_name_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||||
<%= tag.input type: 'text', name: 'submission[1][submitters][][name]', autocomplete: 'off', class: 'base-input-slim w-full', placeholder: 'Name', required: index.zero?, value: (params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : '', dir: 'auto', id: "detailed_name_#{item['uuid']}" %>
|
<%= tag.input type: 'text', name: 'submission[1][submitters][][name]', autocomplete: 'off', class: 'base-input !h-10 w-full', placeholder: t('name'), required: index.zero?, value: (params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : '', dir: 'auto', id: "detailed_name_#{item['uuid']}" %>
|
||||||
</linked-input>
|
</linked-input>
|
||||||
</submitters-autocomplete>
|
</submitters-autocomplete>
|
||||||
<div class="grid <%= 'md:grid-cols-2 gap-1' if submitters.size == 1 %>">
|
<div class="grid <%= 'md:grid-cols-2 gap-1' if submitters.size == 1 %>">
|
||||||
<submitters-autocomplete data-field="email">
|
<submitters-autocomplete data-field="email">
|
||||||
<linked-input data-target-id="<%= "detailed_email_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
<linked-input data-target-id="<%= "detailed_email_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||||
<input type="email" multiple name="submission[1][submitters][][email]" autocomplete="off" class="base-input-slim mt-1.5 w-full" placeholder="Email (optional)" value="<%= item['email'].presence || ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.email : '') %>" id="detailed_email_<%= item['uuid'] %>">
|
<input type="email" multiple name="submission[1][submitters][][email]" autocomplete="off" class="base-input !h-10 mt-1.5 w-full" placeholder="<%= "#{t('email')} (#{t('optional')})" %>" value="<%= item['email'].presence || ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.email : '') %>" id="detailed_email_<%= item['uuid'] %>">
|
||||||
</linked-input>
|
</linked-input>
|
||||||
</submitters-autocomplete>
|
</submitters-autocomplete>
|
||||||
<submitters-autocomplete data-field="phone">
|
<submitters-autocomplete data-field="phone">
|
||||||
<linked-input data-target-id="<%= "detailed_phone_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
<linked-input data-target-id="<%= "detailed_phone_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||||
<input type="tel" pattern="^\+[0-9\s\-]+$" oninvalid="this.value ? this.setCustomValidity('Use internatioanl format: +1xxx...') : ''" oninput="this.setCustomValidity('')" name="submission[1][submitters][][phone]" autocomplete="off" class="base-input-slim mt-1.5 w-full" placeholder="Phone (optional)" id="detailed_phone_<%= item['uuid'] %>">
|
<input type="tel" pattern="^\+[0-9\s\-]+$" oninvalid="this.value ? this.setCustomValidity('Use internatioanl format: +1xxx...') : ''" oninput="this.setCustomValidity('')" name="submission[1][submitters][][phone]" autocomplete="off" class="base-input !h-10 mt-1.5 w-full" placeholder="<%= "#{t('phone')} (#{t('optional')})" %>" id="detailed_phone_<%= item['uuid'] %>">
|
||||||
</linked-input>
|
</linked-input>
|
||||||
</submitters-autocomplete>
|
</submitters-autocomplete>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
<input type="hidden" name="submission[1][submitters][][uuid]" value="<%= item['uuid'] %>">
|
<input type="hidden" name="submission[1][submitters][][uuid]" value="<%= item['uuid'] %>">
|
||||||
<submitters-autocomplete data-field="email">
|
<submitters-autocomplete data-field="email">
|
||||||
<linked-input data-target-id="<%= "email_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
<linked-input data-target-id="<%= "email_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||||
<%= tag.input type: 'email', multiple: true, name: 'submission[1][submitters][][email]', autocomplete: 'off', class: 'base-input-slim w-full', placeholder: t('email'), required: index.zero?, value: item['email'].presence || ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.email : ''), id: "email_#{item['uuid']}" %>
|
<%= tag.input type: 'email', multiple: true, name: 'submission[1][submitters][][email]', autocomplete: 'off', class: 'base-input !h-10 w-full', placeholder: t('email'), required: index.zero?, value: item['email'].presence || ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.email : ''), id: "email_#{item['uuid']}" %>
|
||||||
</linked-input>
|
</linked-input>
|
||||||
</submitters-autocomplete>
|
</submitters-autocomplete>
|
||||||
</submitter-item>
|
</submitter-item>
|
||||||
|
|||||||
@@ -21,13 +21,13 @@
|
|||||||
<input type="hidden" name="submission[1][submitters][][uuid]" value="<%= item['uuid'] %>">
|
<input type="hidden" name="submission[1][submitters][][uuid]" value="<%= item['uuid'] %>">
|
||||||
<submitters-autocomplete data-field="phone">
|
<submitters-autocomplete data-field="phone">
|
||||||
<linked-input data-target-id="<%= "phone_phone_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
<linked-input data-target-id="<%= "phone_phone_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||||
<%= tag.input type: 'tel', pattern: '^\+[0-9\s\-]+$', oninvalid: "this.value ? this.setCustomValidity('Use internatioanl format: +1xxx...') : ''", oninput: "this.setCustomValidity('')", name: 'submission[1][submitters][][phone]', autocomplete: 'off', class: 'base-input-slim w-full', placeholder: t('phone'), required: index.zero?, id: "phone_phone_#{item['uuid']}" %>
|
<%= tag.input type: 'tel', pattern: '^\+[0-9\s\-]+$', oninvalid: "this.value ? this.setCustomValidity('Use internatioanl format: +1xxx...') : ''", oninput: "this.setCustomValidity('')", name: 'submission[1][submitters][][phone]', autocomplete: 'off', class: 'base-input !h-10 w-full', placeholder: t('phone'), required: index.zero?, id: "phone_phone_#{item['uuid']}" %>
|
||||||
</linked-input>
|
</linked-input>
|
||||||
</submitters-autocomplete>
|
</submitters-autocomplete>
|
||||||
<% if submitters.size > 1 %>
|
<% if submitters.size > 1 %>
|
||||||
<submitters-autocomplete data-field="name">
|
<submitters-autocomplete data-field="name">
|
||||||
<linked-input data-target-id="<%= "phone_name_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
<linked-input data-target-id="<%= "phone_name_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||||
<input type="text" name="submission[1][submitters][][name]" autocomplete="off" class="base-input-slim mt-1.5 w-full" placeholder="<%= "#{t('name')} (#{t('optional')})" %>" value="<%= (params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : '' %>" dir="auto" id="phone_name_<%= item['uuid'] %>">
|
<input type="text" name="submission[1][submitters][][name]" autocomplete="off" class="base-input !h-10 mt-1.5 w-full" placeholder="<%= "#{t('name')} (#{t('optional')})" %>" value="<%= (params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : '' %>" dir="auto" id="phone_name_<%= item['uuid'] %>">
|
||||||
</linked-input>
|
</linked-input>
|
||||||
</submitters-autocomplete>
|
</submitters-autocomplete>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
<div class="form-control flex">
|
<div class="form-control flex">
|
||||||
<submitters-autocomplete data-field="name">
|
<submitters-autocomplete data-field="name">
|
||||||
<linked-input data-target-id="<%= "phone_name_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
<linked-input data-target-id="<%= "phone_name_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||||
<input type="text" name="submission[1][submitters][][name]" autocomplete="off" class="base-input-slim w-full" placeholder="<%= "#{t('name')} (#{t('optional')})" %>" value="<%= (params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : '' %>" dir="auto" id="phone_name_<%= item['uuid'] %>">
|
<input type="text" name="submission[1][submitters][][name]" autocomplete="off" class="base-input !h-10 w-full" placeholder="<%= "#{t('name')} (#{t('optional')})" %>" value="<%= (params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : '' %>" dir="auto" id="phone_name_<%= item['uuid'] %>">
|
||||||
</linked-input>
|
</linked-input>
|
||||||
</submitters-autocomplete>
|
</submitters-autocomplete>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<% if template.submitters.size > 1 %>
|
<% if template.preferences['submitters_order'] == 'preserved' %>
|
||||||
|
<%= f.hidden_field :preserve_order, value: '1' %>
|
||||||
|
<% elsif template.submitters.size > 1 %>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= f.label :preserve_order, for: uuid = SecureRandom.uuid, class: 'flex items-center cursor-pointer' do %>
|
<%= f.label :preserve_order, for: uuid = SecureRandom.uuid, class: 'flex items-center cursor-pointer' do %>
|
||||||
<%= f.check_box :preserve_order, id: uuid, class: 'base-checkbox', checked: template.submissions.last&.submitters_order.in?(['preserved', nil]) %>
|
<%= f.check_box :preserve_order, id: uuid, class: 'base-checkbox', checked: template.submissions.last&.submitters_order.in?(['preserved', nil]) %>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<%= render 'shared/turbo_modal_large', title: params[:selfsign] ? t('add_recipients') : t('add_new_recipients') do %>
|
<%= render 'shared/turbo_modal_large', title: params[:selfsign] ? t('add_recipients') : t('add_new_recipients') do %>
|
||||||
<% options = [['via Email', 'email'], ['via Phone', 'phone'], %w[Detailed detailed], ['Upload List', 'list']].compact %>
|
<% options = [[t('via_email'), 'email'], [t('via_phone'), 'phone'], [t('detailed'), 'detailed'], [t('upload_list'), 'list']].compact %>
|
||||||
<toggle-visible data-element-ids="<%= options.map(&:last).to_json %>" class="relative text-center px-2 mt-4 block">
|
<toggle-visible data-element-ids="<%= options.map(&:last).to_json %>" class="relative text-center px-2 mt-4 block">
|
||||||
<div class="join">
|
<div class="flex justify-center">
|
||||||
<% options.each_with_index do |(label, value), index| %>
|
<% options.each_with_index do |(label, value), index| %>
|
||||||
<span>
|
<div>
|
||||||
<%= radio_button_tag 'option', value, value == 'email', class: 'peer hidden', data: { action: 'change:toggle-visible#trigger' } %>
|
<%= radio_button_tag 'option', value, value == 'email', class: 'peer hidden', data: { action: 'change:toggle-visible#trigger' } %>
|
||||||
<label for="option_<%= value %>" class="<%= '!rounded-s-full' if index.zero? %> btn btn-focus btn-sm join-item md:w-28 peer-checked:btn-active normal-case">
|
<label for="option_<%= value %>" class="block bg-base-200 md:min-w-[112px] text-sm font-semibold whitespace-nowrap py-1.5 px-4 peer-checked:bg-base-300 <%= 'hidden sm:inline-block' if value == 'list' %> <%= 'rounded-l-3xl' if index.zero? %> <%= 'rounded-r-3xl sm:rounded-r-none' if value == 'detailed' %> <%= 'rounded-r-3xl' if index == options.size - 1 %>">
|
||||||
<%= label %>
|
<%= label %>
|
||||||
</label>
|
</label>
|
||||||
</span>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</toggle-visible>
|
</toggle-visible>
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% elsif @submission.submitters.to_a.size == 1 && !@submission.expired? && !@submission.submitters.to_a.first.declined_at? %>
|
<% elsif @submission.submitters.to_a.size == 1 && !@submission.expired? && !@submission.submitters.to_a.first.declined_at? %>
|
||||||
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: @submission.submitters.to_a.first.slug), class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy Share Link', copied_title: 'Copied to Clipboard' %>
|
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: @submission.submitters.to_a.first.slug), class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: t('copy_share_link'), copied_title: t('copied_to_clipboard') %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
<% if submitter&.declined_at? %>
|
<% if submitter&.declined_at? %>
|
||||||
<%= t('declined_on_time', time: l(submitter.declined_at.in_time_zone(@submission.account.timezone), format: :short, locale: @submission.account.locale)) %>
|
<%= t('declined_on_time', time: l(submitter.declined_at.in_time_zone(@submission.account.timezone), format: :short, locale: @submission.account.locale)) %>
|
||||||
<% elsif submitter %>
|
<% elsif submitter %>
|
||||||
<%= submitter.completed_at? ? l(submitter.completed_at.in_time_zone(@submission.account.timezone), format: :long, locale: @submission.account.locale) : t('not_copleted_yet') %>
|
<%= submitter.completed_at? ? l(submitter.completed_at.in_time_zone(@submission.account.timezone), format: :long, locale: @submission.account.locale) : t('not_completed_yet') %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= t('not_invited_yet') %>
|
<%= t('not_invited_yet') %>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -153,14 +153,14 @@
|
|||||||
<% if submitter&.declined_at? %>
|
<% if submitter&.declined_at? %>
|
||||||
<div class="flex items-center space-x-1 mt-1">
|
<div class="flex items-center space-x-1 mt-1">
|
||||||
<span>
|
<span>
|
||||||
<%= t('Reason') %>:
|
<%= t('reason') %>:
|
||||||
<%= simple_format(h(submitter.submission_events.find_by(event_type: :decline_form).data['reason'])) %>
|
<%= simple_format(h(submitter.submission_events.find_by(event_type: :decline_form).data['reason'])) %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if signed_in? && submitter && submitter.email && !submitter.completed_at && !@submission.archived_at? && can?(:update, submitter) && Accounts.can_send_emails?(current_account) && !@submission.expired? && !submitter.declined_at? %>
|
<% if signed_in? && submitter && submitter.email && !submitter.completed_at && !@submission.archived_at? && can?(:update, submitter) && Accounts.can_send_emails?(current_account) && !@submission.expired? && !submitter.declined_at? %>
|
||||||
<div class="mt-2 mb-1">
|
<div class="mt-2 mb-1">
|
||||||
<%= button_to button_title(title: submitter.sent_at? ? 'Re-send Email' : 'Send Email', disabled_with: t('sending')), submitter_send_email_index_path(submitter_slug: submitter.slug), class: 'btn btn-sm btn-primary w-full' %>
|
<%= button_to button_title(title: submitter.sent_at? ? t('re_send_email') : t('send_email'), disabled_with: t('sending')), submitter_send_email_index_path(submitter_slug: submitter.slug), class: 'btn btn-sm btn-primary w-full' %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if signed_in? && submitter && submitter.phone && !submitter.completed_at && !@submission.archived_at? && can?(:update, submitter) && !@submission.expired? && !submitter.declined_at? %>
|
<% if signed_in? && submitter && submitter.phone && !submitter.completed_at && !@submission.archived_at? && can?(:update, submitter) && !@submission.expired? && !submitter.declined_at? %>
|
||||||
@@ -182,7 +182,7 @@
|
|||||||
<% next if value.blank? %>
|
<% next if value.blank? %>
|
||||||
<div class="pt-2.5 border-b border-base-300">
|
<div class="pt-2.5 border-b border-base-300">
|
||||||
<div class="text-xs font-medium uppercase mb-0.5" dir="auto">
|
<div class="text-xs font-medium uppercase mb-0.5" dir="auto">
|
||||||
<%= field['name'].presence || "#{field['type'].titleize} Field #{submitter_field_counters[field['type']]}" %>
|
<%= field['name'].presence || "#{t("#{field['type']}_field")} #{submitter_field_counters[field['type']]}" %>
|
||||||
</div>
|
</div>
|
||||||
<div dir="auto">
|
<div dir="auto">
|
||||||
<% if field['type'].in?(%w[signature initials]) %>
|
<% if field['type'].in?(%w[signature initials]) %>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<% is_show_tabs = @pagy.count >= 5 || params[:status].present? %>
|
<% is_show_tabs = @pagy.count >= 5 || params[:status].present? %>
|
||||||
<% if Docuseal.demo? %><%= render 'shared/demo_alert' %><% end %>
|
<% if Docuseal.demo? %><%= render 'shared/demo_alert' %><% end %>
|
||||||
<div class="flex justify-between mb-4 items-center">
|
<div class="flex justify-between items-center w-full mb-4">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center flex-grow min-w-0">
|
||||||
<div class="mr-2">
|
<div class="mr-2">
|
||||||
<%= render 'dashboard/toggle_view', selected: 'submissions' %>
|
<%= render 'dashboard/toggle_view', selected: 'submissions' %>
|
||||||
</div>
|
</div>
|
||||||
<h1 class="text-2xl md:text-3xl sm:text-4xl font-bold md:block <%= 'hidden' if params[:q].present? %>">
|
<h1 class="text-2xl truncate md:text-3xl sm:text-4xl font-bold md:block <%= 'hidden' if params[:q].present? %>">
|
||||||
<%= t('submissions') %>
|
<%= t('submissions') %>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<%= render 'shared/turbo_modal', title: 'Export', close_after_submit: false do %>
|
<%= render 'shared/turbo_modal', title: t('export'), close_after_submit: false do %>
|
||||||
<div class="space-y-2">
|
<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 }, 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="flex items-center p-4 text-left rounded-2xl border border-neutral-300 hover:cursor-pointer hover:bg-neutral hover:text-gray-300">
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<% data_attachments = attachments_index.values.select { |e| e.record_id == submitter.id }.to_json(only: %i[uuid created_at], methods: %i[url filename content_type]) %>
|
<% data_attachments = attachments_index.values.select { |e| e.record_id == submitter.id }.to_json(only: %i[uuid created_at], methods: %i[url filename content_type]) %>
|
||||||
<% data_fields = (submitter.submission.template_fields || submitter.submission.template.fields).select { |f| f['submitter_uuid'] == submitter.uuid }.to_json %>
|
<% data_fields = (submitter.submission.template_fields || submitter.submission.template.fields).select { |f| f['submitter_uuid'] == submitter.uuid }.to_json %>
|
||||||
<% invite_submitters = (submitter.submission.template_submitters || submitter.submission.template.submitters).select { |s| s['invite_by_uuid'] == submitter.uuid && submitter.submission.submitters.none? { |e| e.uuid == s['uuid'] } }.to_json %>
|
<% invite_submitters = (submitter.submission.template_submitters || submitter.submission.template.submitters).select { |s| s['invite_by_uuid'] == submitter.uuid && submitter.submission.submitters.none? { |e| e.uuid == s['uuid'] } }.to_json %>
|
||||||
<submission-form data-is-demo="<%= Docuseal.demo? %>" data-require-signing-reason="<%= configs[:require_signing_reason] %>" data-with-signature-id="<%= configs[:with_signature_id] %>" data-with-confetti="<%= configs[:with_confetti] %>" data-completed-redirect-url="<%= submitter.preferences['completed_redirect_url'].presence || submitter.submission.template.preferences['completed_redirect_url'] %>" data-completed-message="<%= (configs[:completed_message]&.compact_blank.presence || submitter.submission.template.preferences['completed_message'] || {}).to_json %>" data-completed-button="<%= configs[:completed_button].to_json %>" data-go-to-last="<%= submitter.preferences.key?('go_to_last') ? submitter.preferences['go_to_last'] : submitter.opened_at? %>" data-submitter="<%= submitter.to_json(only: %i[uuid slug name phone email]) %>" data-can-send-email="<%= Accounts.can_send_emails?(submitter.submission.account) %>" data-invite-submitters="<%= invite_submitters %>" data-attachments="<%= data_attachments %>" data-fields="<%= data_fields %>" data-values="<%= submitter.values.to_json %>" data-with-typed-signature="<%= configs[:with_typed_signature] %>" data-previous-signature-value="<%= local_assigns[:signature_attachment]&.uuid %>" data-remember-signature="<%= configs[:prefill_signature] %>" data-dry-run="<%= local_assigns[:dry_run] %>" data-expand="<%= local_assigns[:expand] %>" data-scroll-padding="<%= local_assigns[:scroll_padding] %>"></submission-form>
|
<submission-form data-is-demo="<%= Docuseal.demo? %>" data-require-signing-reason="<%= configs[:require_signing_reason] %>" data-with-signature-id="<%= configs[:with_signature_id] %>" data-with-confetti="<%= configs[:with_confetti] %>" data-completed-redirect-url="<%= submitter.preferences['completed_redirect_url'].presence || submitter.submission.template.preferences['completed_redirect_url'] %>" data-completed-message="<%= (configs[:completed_message]&.compact_blank.presence || submitter.submission.template.preferences['completed_message'] || {}).to_json %>" data-completed-button="<%= configs[:completed_button].to_json %>" data-go-to-last="<%= submitter.preferences.key?('go_to_last') ? submitter.preferences['go_to_last'] : submitter.opened_at? %>" data-submitter="<%= submitter.to_json(only: %i[uuid slug name phone email]) %>" data-can-send-email="<%= Accounts.can_send_emails?(submitter.submission.account) %>" data-invite-submitters="<%= invite_submitters %>" data-attachments="<%= data_attachments %>" data-fields="<%= data_fields %>" data-values="<%= submitter.values.to_json %>" data-with-typed-signature="<%= configs[:with_typed_signature] %>" data-previous-signature-value="<%= local_assigns[:signature_attachment]&.uuid %>" data-remember-signature="<%= configs[:prefill_signature] %>" data-dry-run="<%= local_assigns[:dry_run] %>" data-expand="<%= local_assigns[:expand] %>" data-scroll-padding="<%= local_assigns[:scroll_padding] %>" data-language="<%= I18n.locale.to_s.split('-').first %>"></submission-form>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<div class="max-w-md mx-auto px-2 mt-12 mb-4">
|
||||||
|
<div class="space-y-6 mx-auto">
|
||||||
|
<div class="space-y-6">
|
||||||
|
<div class="flex items-center justify-center">
|
||||||
|
<%= render 'start_form/banner' %>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center bg-base-200 rounded-xl p-4 mb-4">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="mr-3">
|
||||||
|
<%= svg_icon('writing_sign', class: 'w-10 h-10') %>
|
||||||
|
</div>
|
||||||
|
<div dir="auto">
|
||||||
|
<p class="text-lg font-bold mb-1"><%= @submitter.submission.template.name %></p>
|
||||||
|
<p class="text-sm"><%= t('awaiting_completion_by_the_other_party') %></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<%= render 'shared/attribution', link_path: '/start', account: @submitter.account %>
|
||||||
@@ -4,10 +4,10 @@
|
|||||||
<span><%= t('home') %></span>
|
<span><%= t('home') %></span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between mb-4 items-center">
|
<div class="flex justify-between items-center w-full mb-4">
|
||||||
<h1 class="text-4xl font-bold flex items-center space-x-2 md:flex <%= 'hidden' if params[:q].present? %>">
|
<h1 class="text-4xl font-bold flex flex-grow min-w-0 space-x-2 md:flex <%= 'hidden' if params[:q].present? %>">
|
||||||
<%= svg_icon('folder', class: 'w-9 h-9 flex-shrink-0') %>
|
<%= svg_icon('folder', class: 'w-9 h-9 flex-shrink-0') %>
|
||||||
<span class="peer">
|
<span class="peer truncate">
|
||||||
<%= @template_folder.name %>
|
<%= @template_folder.name %>
|
||||||
</span>
|
</span>
|
||||||
<% if can?(:update, @template_folder) && @template_folder.name != TemplateFolder::DEFAULT_NAME %>
|
<% if can?(:update, @template_folder) && @template_folder.name != TemplateFolder::DEFAULT_NAME %>
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
<button type="submit" class="hidden"></button>
|
<button type="submit" class="hidden"></button>
|
||||||
<file-dropzone data-submit-on-upload="true" class="w-full">
|
<file-dropzone data-submit-on-upload="true" class="w-full">
|
||||||
<label for="file_dropzone_input" class="w-full block h-52 relative hover:bg-base-200/30 rounded-xl border border-2 border-base-300 border-dashed">
|
<label for="file_dropzone_input" class="w-full block h-52 relative hover:bg-base-200/30 rounded-xl border border-2 border-base-300 border-dashed">
|
||||||
<div class="absolute top-0 right-0 left-0 bottom-0 flex items-center justify-center">
|
<div class="absolute top-0 right-0 left-0 bottom-0 flex items-center justify-center p-2">
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center text-center">
|
||||||
<span data-target="file-dropzone.icon" class="flex flex-col items-center">
|
<span data-target="file-dropzone.icon" class="flex flex-col items-center">
|
||||||
<span>
|
<span>
|
||||||
<%= svg_icon('cloud_upload', class: 'w-10 h-10') %>
|
<%= svg_icon('cloud_upload', class: 'w-10 h-10') %>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
<% else %>
|
<% else %>
|
||||||
<div class="tooltip flex" data-tip="<%= l(submitter.status_event_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %>">
|
<div class="tooltip flex" data-tip="<%= l(submitter.status_event_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %>">
|
||||||
<span class="badge <%= status_badges[submitter.status] %> md:w-32 badge-lg bg-opacity-50 uppercase text-sm font-semibold">
|
<span class="badge <%= status_badges[submitter.status] %> md:w-32 badge-lg bg-opacity-50 uppercase text-sm font-semibold">
|
||||||
<%= submitter.status %>
|
<%= t(submitter.status) %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
<form onsubmit="event.preventDefault()" class="flex-1 md:flex-none">
|
<form onsubmit="event.preventDefault()" class="flex-1 md:flex-none">
|
||||||
<button onclick="event.stopPropagation()" class="w-full md:w-fit">
|
<button onclick="event.stopPropagation()" class="w-full md:w-fit">
|
||||||
<download-button data-src="<%= submitter_download_index_path(submitter.slug) %>" class="btn btn-sm btn-neutral text-white w-full md:w-36">
|
<download-button data-src="<%= submitter_download_index_path(submitter.slug) %>" class="btn btn-sm btn-neutral text-white w-full md:w-36">
|
||||||
<span class="flex items-center justify-center space-x-1 md:space-x-2" data-target="download-button.defaultButton">
|
<span class="flex items-center justify-center space-x-1 <%= 'md:space-x-2' if t('download').length < 11 %>" data-target="download-button.defaultButton">
|
||||||
<%= svg_icon('download', class: 'w-5 h-5 stroke-2') %>
|
<%= svg_icon('download', class: 'w-5 h-5 stroke-2') %>
|
||||||
<span class="inline"><%= t('download') %></span>
|
<span class="inline"><%= t('download') %></span>
|
||||||
</span>
|
</span>
|
||||||
@@ -74,14 +74,16 @@
|
|||||||
<form data-turbo="false" method="get" action="<%= submit_form_url(slug: submitter.slug) %>" class="flex-1 md:flex-none">
|
<form data-turbo="false" method="get" action="<%= submit_form_url(slug: submitter.slug) %>" class="flex-1 md:flex-none">
|
||||||
<button onclick="event.stopPropagation()" class="btn btn-sm btn-neutral btn-outline bg-white w-full md:w-36 flex">
|
<button onclick="event.stopPropagation()" class="btn btn-sm btn-neutral btn-outline bg-white w-full md:w-36 flex">
|
||||||
<span class="flex items-center justify-center space-x-1 md:space-x-2">
|
<span class="flex items-center justify-center space-x-1 md:space-x-2">
|
||||||
<%= svg_icon('writing_sign', class: 'w-4 h-4 stroke-2') %>
|
<% if t('sign_now').length < 12 %>
|
||||||
|
<%= svg_icon('writing_sign', class: 'w-4 h-4 stroke-2') %>
|
||||||
|
<% end %>
|
||||||
<span class="inline shrink-0"><%= t('sign_now') %></span>
|
<span class="inline shrink-0"><%= t('sign_now') %></span>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<% else %>
|
<% else %>
|
||||||
<div class="flex-1 md:flex-none">
|
<div class="flex-1 md:flex-none">
|
||||||
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: submitter.slug), class: 'btn btn-sm btn-neutral text-white md:w-36 flex', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy Link', copy_title_md: t('copy'), copied_title_md: t('copied') %>
|
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: submitter.slug), class: 'btn btn-sm btn-neutral text-white md:w-36 flex', icon_class: 'w-6 h-6 text-white', copy_title: t('copy_link').length < 10 ? t('copy_link') : t('copy'), copy_title_md: t('copy'), copied_title_md: t('copied') %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -106,7 +108,7 @@
|
|||||||
<% latest_submitter = submitters.select(&:completed_at?).max_by(&:completed_at) %>
|
<% latest_submitter = submitters.select(&:completed_at?).max_by(&:completed_at) %>
|
||||||
<div class="tooltip flex" data-tip="<%= l(latest_submitter.status_event_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %>">
|
<div class="tooltip flex" data-tip="<%= l(latest_submitter.status_event_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %>">
|
||||||
<span class="badge <%= status_badges[latest_submitter.status] %> md:w-32 bg-opacity-50 badge-lg uppercase text-sm font-semibold">
|
<span class="badge <%= status_badges[latest_submitter.status] %> md:w-32 bg-opacity-50 badge-lg uppercase text-sm font-semibold">
|
||||||
<%= latest_submitter.status %>
|
<%= t(latest_submitter.status) %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<% elsif submission.expired? %>
|
<% elsif submission.expired? %>
|
||||||
@@ -123,7 +125,7 @@
|
|||||||
<% if !is_submission_completed && !submission.expired? %>
|
<% if !is_submission_completed && !submission.expired? %>
|
||||||
<div class="tooltip flex" data-tip="<%= l(submitter.status_event_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %>">
|
<div class="tooltip flex" data-tip="<%= l(submitter.status_event_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %>">
|
||||||
<span class="badge md:w-24 <%= status_badges[submitter.status] %> bg-opacity-50 uppercase text-xs font-semibold">
|
<span class="badge md:w-24 <%= status_badges[submitter.status] %> bg-opacity-50 uppercase text-xs font-semibold">
|
||||||
<%= submitter.status %>
|
<%= t(submitter.status) %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -152,13 +154,15 @@
|
|||||||
<form data-turbo="false" method="get" action="<%= submit_form_url(slug: submitter.slug) %>">
|
<form data-turbo="false" method="get" action="<%= submit_form_url(slug: submitter.slug) %>">
|
||||||
<button onclick="event.stopPropagation()" class="absolute md:relative top-0 right-0 btn btn-xs btn-outline btn-neutral bg-white w-28 md:w-36">
|
<button onclick="event.stopPropagation()" class="absolute md:relative top-0 right-0 btn btn-xs btn-outline btn-neutral bg-white w-28 md:w-36">
|
||||||
<span class="flex items-center justify-center space-x-1 md:space-x-2">
|
<span class="flex items-center justify-center space-x-1 md:space-x-2">
|
||||||
<%= svg_icon('writing_sign', class: 'w-4 h-4 stroke-2') %>
|
<% if t('sign_now').length < 12 %>
|
||||||
|
<%= svg_icon('writing_sign', class: 'w-4 h-4 stroke-2') %>
|
||||||
|
<% end %>
|
||||||
<span class="inline shrink-0"><%= t('sign_now') %></span>
|
<span class="inline shrink-0"><%= t('sign_now') %></span>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: submitter.slug), class: 'absolute md:relative top-0 right-0 btn btn-xs text-xs btn-neutral text-white w-28 md:w-36 flex', icon_class: 'w-4 h-4 text-white', copy_title: 'Copy Link', copy_title_md: 'Copy Link', copied_title_md: t('copied') %>
|
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: submitter.slug), class: 'absolute md:relative top-0 right-0 btn btn-xs text-xs btn-neutral text-white w-28 md:w-36 flex', icon_class: 'w-4 h-4 text-white', copy_title: t('copy_link'), copy_title_md: t('copy_link').length < 10 ? t('copy_link') : t('copy'), copied_title_md: t('copied') %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -172,8 +176,8 @@
|
|||||||
<% latest_submitter = submitters.select(&:completed_at?).max_by(&:completed_at) %>
|
<% latest_submitter = submitters.select(&:completed_at?).max_by(&:completed_at) %>
|
||||||
<div class="flex-1 md:flex-none">
|
<div class="flex-1 md:flex-none">
|
||||||
<form onsubmit="event.preventDefault()" class="w-full md:w-fit">
|
<form onsubmit="event.preventDefault()" class="w-full md:w-fit">
|
||||||
<button onclick="event.stopPropagation()">
|
<button onclick="event.stopPropagation()" class="w-full">
|
||||||
<download-button data-src="<%= submitter_download_index_path(latest_submitter.slug) %>" class="btn btn-sm btn-neutral text-white md:w-36">
|
<download-button data-src="<%= submitter_download_index_path(latest_submitter.slug) %>" class="btn btn-sm btn-neutral text-white w-full md:w-36">
|
||||||
<span class="flex items-center justify-center space-x-1 md:space-x-2" data-target="download-button.defaultButton">
|
<span class="flex items-center justify-center space-x-1 md:space-x-2" data-target="download-button.defaultButton">
|
||||||
<%= svg_icon('download', class: 'w-5 h-5 stroke-2') %>
|
<%= svg_icon('download', class: 'w-5 h-5 stroke-2') %>
|
||||||
<span class="inline"><%= t('download') %></span>
|
<span class="inline"><%= t('download') %></span>
|
||||||
|
|||||||
@@ -46,11 +46,11 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= render 'shared/clipboard_copy', text: start_form_url(slug: @template.slug), class: 'absolute md:relative bottom-0 right-0 btn btn-xs md:btn-sm whitespace-nowrap btn-neutral text-white mt-1 px-2', icon_class: 'w-4 h-4 md:w-6 md:h-6 text-white', copy_title: 'Link', copied_title: t('copied'), copy_title_md: 'Link', copied_title_md: t('copied') %>
|
<%= render 'shared/clipboard_copy', text: start_form_url(slug: @template.slug), class: 'absolute md:relative bottom-0 right-0 btn btn-xs md:btn-sm whitespace-nowrap btn-neutral text-white mt-1 px-2', icon_class: 'w-4 h-4 md:w-6 md:h-6 text-white', copy_title: t('link'), copied_title: t('copied'), copy_title_md: t('link'), copied_title_md: t('copied') %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex space-x-2 w-full md:w-fit md:justify-between md:flex-none md:pt-1">
|
<div class="flex flex-wrap gap-2 w-full md:w-fit md:justify-between md:flex-none md:pt-1">
|
||||||
<% if !template.archived_at? && can?(:destroy, template) %>
|
<% if !template.archived_at? && can?(:destroy, template) %>
|
||||||
<%= button_to button_title(title: t('archive'), disabled_with: t('archiving'), title_class: 'inline', icon: svg_icon('archive', class: 'w-6 h-6')), template_path(template), class: 'btn btn-outline btn-sm w-full', form_class: 'flex-1', method: :delete, data: { turbo_confirm: t('are_you_sure_') } %>
|
<%= button_to button_title(title: t('archive'), disabled_with: t('archiving'), title_class: 'inline', icon: svg_icon('archive', class: 'w-6 h-6')), template_path(template), class: 'btn btn-outline btn-sm w-full', form_class: 'flex-1', method: :delete, data: { turbo_confirm: t('are_you_sure_') } %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<template-builder class="grid" data-template="<%= @template_data %>" data-with-sign-yourself-button="<%= !@template.archived_at? %>" data-with-send-button="<%= !@template.archived_at? && can?(:create, @template.submissions.new(account: current_account)) %>" data-locale="<%= current_account.locale %>"></template-builder>
|
<template-builder class="grid" data-template="<%= @template_data %>" data-with-sign-yourself-button="<%= !@template.archived_at? %>" data-with-send-button="<%= !@template.archived_at? && can?(:create, @template.submissions.new(account: current_account)) %>" data-locale="<%= I18n.locale %>"></template-builder>
|
||||||
@@ -3,9 +3,9 @@
|
|||||||
<% if @base_template %>
|
<% if @base_template %>
|
||||||
<%= hidden_field_tag :base_template_id, @base_template.id %>
|
<%= hidden_field_tag :base_template_id, @base_template.id %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if @base_template && (can?(:manage, :tenants) || true_user != current_user) && true_user.account.linked_accounts.active.exists? %>
|
<% if @base_template && (can?(:manage, :tenants) || true_user != current_user) && true_user.account.linked_accounts.active.accessible_by(current_ability).exists? %>
|
||||||
<div class="form-control -mb-2 mt-2">
|
<div class="form-control -mb-2 mt-2">
|
||||||
<%= select_tag :account_id, options_for_select([true_user.account, *true_user.account.linked_accounts.active].uniq.map { |e| [e.name, e.id] }, current_account.id), required: true, class: 'base-select' %>
|
<%= select_tag :account_id, options_for_select([true_user.account, *true_user.account.linked_accounts.active.accessible_by(current_ability)].uniq.map { |e| [e.name, e.id] }, current_account.id), required: true, class: 'base-select' %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<div class="form-control mt-6">
|
<div class="form-control mt-6">
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
</folder-autocomplete>
|
</folder-autocomplete>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= f.button button_title(title: @base_template ? 'Submit' : 'Create', disabled_with: 'Creating'), class: 'base-button' %>
|
<%= f.button button_title(title: @base_template ? t('submit') : t('create'), disabled_with: t('creating')), class: 'base-button' %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
<div class="card bg-base-200">
|
<div class="card bg-base-200">
|
||||||
<div class="card-body text-center py-16">
|
<div class="card-body text-center px-4 py-16">
|
||||||
<div class="max-w-lg mx-auto">
|
<div class="max-w-lg mx-auto">
|
||||||
<p class="text-3xl font-bold text-base-content mb-4">
|
<p class="text-3xl font-bold text-base-content mb-4">
|
||||||
<%= t('there_are_no_submissions') %>
|
<%= t('there_are_no_submissions') %>
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
<% has_archived = current_account.templates.where.not(archived_at: nil).exists? %>
|
<% has_archived = current_account.templates.where.not(archived_at: nil).exists? %>
|
||||||
<% if Docuseal.demo? %><%= render 'shared/demo_alert' %><% end %>
|
<% if Docuseal.demo? %><%= render 'shared/demo_alert' %><% end %>
|
||||||
<div class="flex justify-between mb-4 items-center">
|
<div class="flex justify-between items-center w-full mb-4">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center flex-grow min-w-0">
|
||||||
<% if has_archived || @pagy.count > 0 %>
|
<% if has_archived || @pagy.count > 0 %>
|
||||||
<div class="mr-2">
|
<div class="mr-2">
|
||||||
<%= render 'dashboard/toggle_view', selected: 'templates' %>
|
<%= render 'dashboard/toggle_view', selected: 'templates' %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<h1 class="text-2xl md:text-3xl sm:text-4xl font-bold md:block <%= 'hidden' if params[:q].present? %>"><%= t('document_templates_html') %></h1>
|
<h1 class="text-2xl truncate md:text-3xl sm:text-4xl font-bold md:block <%= 'hidden' if params[:q].present? %>">
|
||||||
|
<%= t('document_templates_html') %>
|
||||||
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex space-x-2">
|
<div class="flex space-x-2">
|
||||||
<% if params[:q].present? || @pagy.pages > 1 || @template_folders.present? %>
|
<% if params[:q].present? || @pagy.pages > 1 || @template_folders.present? %>
|
||||||
|
|||||||
@@ -158,7 +158,7 @@
|
|||||||
<div class="collapse collapse-arrow join-item border border-base-300">
|
<div class="collapse collapse-arrow join-item border border-base-300">
|
||||||
<input type="checkbox" name="accordion">
|
<input type="checkbox" name="accordion">
|
||||||
<div class="collapse-title text-xl font-medium">
|
<div class="collapse-title text-xl font-medium">
|
||||||
<%= t('copleted_notification_email') %>
|
<%= t('completed_notification_email') %>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse-content">
|
<div class="collapse-content">
|
||||||
<%= form_for @template, url: template_preferences_path(@template), method: :post, html: { autocomplete: 'off', class: 'mt-1' }, data: { close_on_submit: false } do |f| %>
|
<%= form_for @template, url: template_preferences_path(@template), method: :post, html: { autocomplete: 'off', class: 'mt-1' }, data: { close_on_submit: false } do |f| %>
|
||||||
@@ -256,10 +256,20 @@
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control mt-6 pb-2">
|
<% end %>
|
||||||
<%= f.button button_title(title: t('save'), disabled_with: t('updating')), class: 'base-button' %>
|
<%= form_for @template, url: template_preferences_path(@template), method: :post, html: { autocomplete: 'off', class: 'mt-2' }, data: { close_on_submit: false } do |f| %>
|
||||||
|
<div class="flex items-center pt-4 mt-4 justify-between border-t w-full">
|
||||||
|
<span>
|
||||||
|
<%= t('enforce_recipients_order') %>
|
||||||
|
</span>
|
||||||
|
<%= f.fields_for :preferences, Struct.new(:submitters_order).new(@template.preferences['submitters_order']) do |ff| %>
|
||||||
|
<%= ff.check_box :submitters_order, { class: 'toggle', onchange: 'this.form.requestSubmit()' }, 'preserved', '' %>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<div class="form-control mt-5 pb-2">
|
||||||
|
<%= button_tag button_title(title: t('save'), disabled_with: t('updating')), class: 'base-button', form: :submitters_form %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if show_api %>
|
<% if show_api %>
|
||||||
@@ -285,7 +295,7 @@
|
|||||||
<%= render 'templates_code_modal/placeholder' %>
|
<%= render 'templates_code_modal/placeholder' %>
|
||||||
<%= render 'templates/embedding', template: @template %>
|
<%= render 'templates/embedding', template: @template %>
|
||||||
<% if can?(:manage, TemplateSharing.new(template: @template)) %>
|
<% if can?(:manage, TemplateSharing.new(template: @template)) %>
|
||||||
<%= form_for '', url: template_sharings_testing_index_path, method: :post, html: { class: 'mt-1' } do |f| %>
|
<%= form_for '', url: template_sharings_testing_index_path, method: :post, html: { class: 'mt-1' }, data: { close_on_submit: false } do |f| %>
|
||||||
<%= f.hidden_field :template_id, value: @template.id %>
|
<%= f.hidden_field :template_id, value: @template.id %>
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<span>
|
<span>
|
||||||
|
|||||||
@@ -28,8 +28,8 @@
|
|||||||
<%= form_for @user_config, url: user_initials_path, method: :put, data: { turbo_frame: :_top }, html: { autocomplete: :off, enctype: 'multipart/form-data' } do |f| %>
|
<%= form_for @user_config, url: user_initials_path, method: :put, data: { turbo_frame: :_top }, html: { autocomplete: :off, enctype: 'multipart/form-data' } do |f| %>
|
||||||
<file-dropzone data-submit-on-upload="true" class="w-full">
|
<file-dropzone data-submit-on-upload="true" class="w-full">
|
||||||
<label for="file" class="w-full block h-32 relative bg-base-200 hover:bg-base-200/70 rounded-md border border-base-content border-dashed">
|
<label for="file" class="w-full block h-32 relative bg-base-200 hover:bg-base-200/70 rounded-md border border-base-content border-dashed">
|
||||||
<div class="absolute top-0 right-0 left-0 bottom-0 flex items-center justify-center">
|
<div class="absolute top-0 right-0 left-0 bottom-0 flex items-center justify-center p-2">
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center text-center">
|
||||||
<span data-target="file-dropzone.icon">
|
<span data-target="file-dropzone.icon">
|
||||||
<%= svg_icon('cloud_upload', class: 'w-10 h-10') %>
|
<%= svg_icon('cloud_upload', class: 'w-10 h-10') %>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<p>Hello <%= @user.first_name %>,</p>
|
<p><%= @user.first_name.present? ? t('hello_name', name: @user.first_name) : t('hi_there') %>,</p>
|
||||||
<p>You have been invited to <%= @user.account.name %> <%= Docuseal.product_name %>. Please sign up using the link below:</p>
|
<p><%= t('you_have_been_invited_to_account_name_product_name_please_sign_up_using_the_link_below_', account_name: @user.account.name, product_name: Docuseal.product_name) %></p>
|
||||||
<p><%= link_to 'Sign up', invitation_url(reset_password_token: @token) %></p>
|
<p><%= link_to t('sign_up'), invitation_url(reset_password_token: @token) %></p>
|
||||||
<p>Please contact us by replying to this email if you didn't request this.</p>
|
<p><%= t('please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this') %></p>
|
||||||
<p>
|
<p>
|
||||||
Thanks,<br><%= @current_account.name %>
|
<%= t('thanks') %>,<br><%= @current_account.name %>
|
||||||
</p>
|
</p>
|
||||||
@@ -28,8 +28,8 @@
|
|||||||
<%= form_for @user_config, url: user_signature_path, method: :put, data: { turbo_frame: :_top }, html: { autocomplete: :off, enctype: 'multipart/form-data' } do |f| %>
|
<%= form_for @user_config, url: user_signature_path, method: :put, data: { turbo_frame: :_top }, html: { autocomplete: :off, enctype: 'multipart/form-data' } do |f| %>
|
||||||
<file-dropzone data-submit-on-upload="true" class="w-full">
|
<file-dropzone data-submit-on-upload="true" class="w-full">
|
||||||
<label for="file" class="w-full block h-32 relative bg-base-200 hover:bg-base-200/70 rounded-md border border-base-content border-dashed">
|
<label for="file" class="w-full block h-32 relative bg-base-200 hover:bg-base-200/70 rounded-md border border-base-content border-dashed">
|
||||||
<div class="absolute top-0 right-0 left-0 bottom-0 flex items-center justify-center">
|
<div class="absolute top-0 right-0 left-0 bottom-0 flex items-center justify-center p-2">
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center text-center">
|
||||||
<span data-target="file-dropzone.icon">
|
<span data-target="file-dropzone.icon">
|
||||||
<%= svg_icon('cloud_upload', class: 'w-10 h-10') %>
|
<%= svg_icon('cloud_upload', class: 'w-10 h-10') %>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<div class="flex-wrap space-y-4 md:flex md:flex-nowrap md:space-y-0 md:space-x-10">
|
<div class="flex-wrap space-y-4 md:flex md:flex-nowrap md:space-y-0 md:space-x-10">
|
||||||
<%= render 'shared/settings_nav' %>
|
<%= render 'shared/settings_nav' %>
|
||||||
<div class="md:flex-grow">
|
<div class="md:flex-grow">
|
||||||
<div class="flex justify-between mb-4">
|
<div class="flex flex-col md:flex-row gap-2 md:justify-between md:items-end mb-4">
|
||||||
<h1 class="text-4xl font-bold">
|
<h1 class="text-4xl font-bold">
|
||||||
<%= t('status_users', status: params[:status].to_s.titleize) %>
|
<%= t('status_users', status: params[:status].to_s.titleize) %>
|
||||||
</h1>
|
</h1>
|
||||||
<div class="flex items-center space-x-4">
|
<div class="flex flex-col md:flex-row gap-y-2 gap-x-4 md:items-center">
|
||||||
<% if can?(:create, User.new(account: current_account)) %>
|
<% if can?(:create, User.new(account: current_account)) %>
|
||||||
<%= render 'users/extra_buttons' %>
|
<%= render 'users/extra_buttons' %>
|
||||||
<% if content_for(:add_user_button) %>
|
<% if content_for(:add_user_button) %>
|
||||||
<%= content_for(:add_user_button) %>
|
<%= content_for(:add_user_button) %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= link_to new_user_path, class: 'btn btn-primary btn-md gap-2', data: { turbo_frame: 'modal' } do %>
|
<%= link_to new_user_path, class: 'btn btn-primary btn-md gap-2 w-full md:w-fit', data: { turbo_frame: 'modal' } do %>
|
||||||
<%= svg_icon('plus', class: 'w-6 h-6') %>
|
<%= svg_icon('plus', class: 'w-6 h-6') %>
|
||||||
<span><%= t('new_user') %></span>
|
<span><%= t('new_user') %></span>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<div class="flex flex-wrap space-y-4 md:flex-nowrap md:space-y-0 md:space-x-10">
|
<div class="flex flex-wrap space-y-4 md:flex-nowrap md:space-y-0 md:space-x-10">
|
||||||
<%= render 'shared/settings_nav' %>
|
<%= render 'shared/settings_nav' %>
|
||||||
<div class="flex-grow">
|
<div class="flex-grow">
|
||||||
<div class="flex justify-between">
|
<div class="flex flex-col gap-2 md:flex-row md:justify-between md:items-end mb-4">
|
||||||
<h1 class="text-4xl font-bold mb-4">Webhooks</h1>
|
<h1 class="text-4xl font-bold">Webhooks</h1>
|
||||||
<%= render 'shared/test_mode_toggle' %>
|
<%= render 'shared/test_mode_toggle' %>
|
||||||
</div>
|
</div>
|
||||||
<div class="card bg-base-200">
|
<div class="card bg-base-200">
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
<% preference = current_account.account_configs.find_by(key: AccountConfig::WEBHOOK_PREFERENCES_KEY)&.value || {} %>
|
<% preference = current_account.account_configs.find_by(key: AccountConfig::WEBHOOK_PREFERENCES_KEY)&.value || {} %>
|
||||||
<% WebhookPreferencesController::EVENTS.group_by { |e| e.include?('form') }.each do |_, events| %>
|
<% WebhookPreferencesController::EVENTS.group_by { |e| e.include?('form') }.each do |_, events| %>
|
||||||
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 mt-2 gap-y-2">
|
<div class="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 mt-2 gap-y-2">
|
||||||
<% events.each do |event| %>
|
<% events.each do |event| %>
|
||||||
<%= form_for '', url: webhook_preferences_path, method: :post do |f| %>
|
<%= form_for '', url: webhook_preferences_path, method: :post do |f| %>
|
||||||
<%= f.hidden_field :event, value: event %>
|
<%= f.hidden_field :event, value: event %>
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
<div class="space-y-4 mt-4">
|
<div class="space-y-4 mt-4">
|
||||||
<div class="collapse collapse-open bg-base-200 px-1">
|
<div class="collapse collapse-open bg-base-200 px-1">
|
||||||
<div class="p-4 text-xl font-medium">
|
<div class="p-4 text-xl font-medium">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between gap-2">
|
||||||
<span>
|
<span>
|
||||||
<%= t('submission_example_payload') %>
|
<%= t('submission_example_payload') %>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ Bundler.require(*Rails.groups)
|
|||||||
|
|
||||||
module DocuSeal
|
module DocuSeal
|
||||||
class Application < Rails::Application
|
class Application < Rails::Application
|
||||||
config.load_defaults 7.1
|
config.load_defaults 7.2
|
||||||
|
|
||||||
config.autoload_lib(ignore: %w[assets tasks puma])
|
config.autoload_lib(ignore: %w[assets tasks puma])
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ Rails.application.configure do
|
|||||||
domain: ENV.fetch('SMTP_DOMAIN', nil),
|
domain: ENV.fetch('SMTP_DOMAIN', nil),
|
||||||
user_name: ENV.fetch('SMTP_USERNAME', nil),
|
user_name: ENV.fetch('SMTP_USERNAME', nil),
|
||||||
password: ENV.fetch('SMTP_PASSWORD', nil),
|
password: ENV.fetch('SMTP_PASSWORD', nil),
|
||||||
authentication: ENV.fetch('SMTP_AUTHENTICATION', 'plain'),
|
authentication: ENV.fetch('SMTP_PASSWORD', nil).present? ? ENV.fetch('SMTP_AUTHENTICATION', 'plain') : nil,
|
||||||
enable_starttls_auto: ENV['SMTP_ENABLE_STARTTLS_AUTO'] != 'false'
|
enable_starttls_auto: ENV['SMTP_ENABLE_STARTTLS_AUTO'] != 'false'
|
||||||
}.compact
|
}.compact
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,19 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module HexaPDF
|
module HexaPDF
|
||||||
|
module DigitalSignature
|
||||||
|
class Signatures
|
||||||
|
private
|
||||||
|
|
||||||
|
def generate_field_name
|
||||||
|
index = (@document.acro_form.each_field
|
||||||
|
.map { |field| field.full_field_name.to_s.scan(/\ASignature(\d+)/).first&.first.to_i }
|
||||||
|
.max || 0) + 1
|
||||||
|
"Signature#{index}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
module Encryption
|
module Encryption
|
||||||
class SecurityHandler
|
class SecurityHandler
|
||||||
def encrypt_string(str, obj)
|
def encrypt_string(str, obj)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
Pagy::DEFAULT[:items] = 10
|
Pagy::DEFAULT[:limit] = 10
|
||||||
Pagy::DEFAULT.freeze
|
Pagy::DEFAULT.freeze
|
||||||
|
|
||||||
ActiveSupport.on_load(:action_view) do
|
ActiveSupport.on_load(:action_view) do
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+8
-2
@@ -118,7 +118,11 @@ module Accounts
|
|||||||
end
|
end
|
||||||
|
|
||||||
if (default_cert = cert_data['custom']&.find { |e| e['status'] == 'default' })
|
if (default_cert = cert_data['custom']&.find { |e| e['status'] == 'default' })
|
||||||
OpenSSL::PKCS12.new(Base64.urlsafe_decode64(default_cert['data']), default_cert['password'].to_s)
|
if default_cert['name'] == Docuseal::AATL_CERT_NAME
|
||||||
|
Docuseal.default_pkcs
|
||||||
|
else
|
||||||
|
OpenSSL::PKCS12.new(Base64.urlsafe_decode64(default_cert['data']), default_cert['password'].to_s)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
GenerateCertificate.load_pkcs(cert_data)
|
GenerateCertificate.load_pkcs(cert_data)
|
||||||
end
|
end
|
||||||
@@ -153,7 +157,9 @@ module Accounts
|
|||||||
|
|
||||||
default_pkcs = GenerateCertificate.load_pkcs(cert_data)
|
default_pkcs = GenerateCertificate.load_pkcs(cert_data)
|
||||||
|
|
||||||
custom_certs = cert_data.fetch('custom', []).map do |e|
|
custom_certs = cert_data.fetch('custom', []).filter_map do |e|
|
||||||
|
next if e['data'].blank?
|
||||||
|
|
||||||
OpenSSL::PKCS12.new(Base64.urlsafe_decode64(e['data']), e['password'].to_s)
|
OpenSSL::PKCS12.new(Base64.urlsafe_decode64(e['data']), e['password'].to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ module ActionMailerConfigsInterceptor
|
|||||||
address: value['host'],
|
address: value['host'],
|
||||||
port: value['port'],
|
port: value['port'],
|
||||||
domain: value['domain'],
|
domain: value['domain'],
|
||||||
openssl_verify_mode: OpenSSL::SSL::VERIFY_NONE,
|
openssl_verify_mode: value['security'] == 'noverify' ? OpenSSL::SSL::VERIFY_NONE : nil,
|
||||||
authentication: value.fetch('authentication', 'plain'),
|
authentication: value['password'].present? ? value.fetch('authentication', 'plain') : nil,
|
||||||
enable_starttls_auto: true,
|
enable_starttls_auto: value['security'] != 'tls',
|
||||||
open_timeout: OPEN_TIMEOUT,
|
open_timeout: OPEN_TIMEOUT,
|
||||||
read_timeout: READ_TIMEOUT,
|
read_timeout: READ_TIMEOUT,
|
||||||
ssl: value['security'] == 'ssl',
|
ssl: value['security'] == 'ssl',
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ module Docuseal
|
|||||||
CHATGPT_URL = 'https://chatgpt.com/g/g-9hg8AAw0r-docuseal'
|
CHATGPT_URL = 'https://chatgpt.com/g/g-9hg8AAw0r-docuseal'
|
||||||
SUPPORT_EMAIL = 'support@docuseal.co'
|
SUPPORT_EMAIL = 'support@docuseal.co'
|
||||||
HOST = ENV.fetch('HOST', 'localhost')
|
HOST = ENV.fetch('HOST', 'localhost')
|
||||||
|
AATL_CERT_NAME = 'docuseal_aatl'
|
||||||
CONSOLE_URL = if Rails.env.development?
|
CONSOLE_URL = if Rails.env.development?
|
||||||
'http://console.localhost.io:3001'
|
'http://console.localhost.io:3001'
|
||||||
elsif ENV['MULTITENANT'] == 'true'
|
elsif ENV['MULTITENANT'] == 'true'
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ module ReplaceEmailVariables
|
|||||||
|
|
||||||
# rubocop:disable Metrics
|
# rubocop:disable Metrics
|
||||||
def call(text, submitter:, tracking_event_type: 'click_email', html_escape: false, sig: nil)
|
def call(text, submitter:, tracking_event_type: 'click_email', html_escape: false, sig: nil)
|
||||||
text = replace(text, TEMPLATE_NAME, html_escape:) { submitter.template.name }
|
text = replace(text, TEMPLATE_NAME, html_escape:) { (submitter.template || submitter.submission.template).name }
|
||||||
text = replace(text, TEMPLATE_ID, html_escape:) { submitter.template.id }
|
text = replace(text, TEMPLATE_ID, html_escape:) { submitter.template.id }
|
||||||
text = replace(text, SUBMITTER_ID, html_escape:) { submitter.id }
|
text = replace(text, SUBMITTER_ID, html_escape:) { submitter.id }
|
||||||
text = replace(text, SUBMITTER_SLUG, html_escape:) { submitter.slug }
|
text = replace(text, SUBMITTER_SLUG, html_escape:) { submitter.slug }
|
||||||
|
|||||||
@@ -3,22 +3,6 @@
|
|||||||
module SubmissionEvents
|
module SubmissionEvents
|
||||||
TRACKING_PARAM_LENGTH = 6
|
TRACKING_PARAM_LENGTH = 6
|
||||||
|
|
||||||
EVENT_NAMES = {
|
|
||||||
send_email: 'Email sent',
|
|
||||||
send_reminder_email: 'Reminder email sent',
|
|
||||||
send_sms: 'SMS sent',
|
|
||||||
send_2fa_sms: 'Verification SMS sent',
|
|
||||||
open_email: 'Email opened',
|
|
||||||
click_email: 'Email link clicked',
|
|
||||||
click_sms: 'SMS link clicked',
|
|
||||||
phone_verified: 'Phone verified',
|
|
||||||
start_form: 'Submission started',
|
|
||||||
view_form: 'Form viewed',
|
|
||||||
invite_party: 'Invited',
|
|
||||||
complete_form: 'Submission completed',
|
|
||||||
api_complete_form: 'Submission completed via API'
|
|
||||||
}.freeze
|
|
||||||
|
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
def build_tracking_param(submitter, event_type = 'click_email')
|
def build_tracking_param(submitter, event_type = 'click_email')
|
||||||
|
|||||||
@@ -111,6 +111,9 @@ module Submissions
|
|||||||
return email.downcase if email.to_s.include?('.mm')
|
return email.downcase if email.to_s.include?('.mm')
|
||||||
return email.downcase if email.to_s.include?('.cm')
|
return email.downcase if email.to_s.include?('.cm')
|
||||||
return email.downcase if email.to_s.include?('.et')
|
return email.downcase if email.to_s.include?('.et')
|
||||||
|
return email.downcase if email.to_s.include?('.mo')
|
||||||
|
return email.downcase if email.to_s.include?('.nz')
|
||||||
|
return email.downcase if email.to_s.include?('.za')
|
||||||
return email.downcase unless email.to_s.include?('.')
|
return email.downcase unless email.to_s.include?('.')
|
||||||
|
|
||||||
fixed_email = EmailTypo.call(email.delete_prefix('<'))
|
fixed_email = EmailTypo.call(email.delete_prefix('<'))
|
||||||
|
|||||||
@@ -12,9 +12,6 @@ module Submissions
|
|||||||
'Helvetica'
|
'Helvetica'
|
||||||
end
|
end
|
||||||
|
|
||||||
VERIFIED_TEXT = 'Verified'
|
|
||||||
UNVERIFIED_TEXT = 'Unverified'
|
|
||||||
|
|
||||||
CURRENCY_SYMBOLS = {
|
CURRENCY_SYMBOLS = {
|
||||||
'USD' => '$',
|
'USD' => '$',
|
||||||
'EUR' => '€',
|
'EUR' => '€',
|
||||||
@@ -32,33 +29,37 @@ module Submissions
|
|||||||
|
|
||||||
# rubocop:disable Metrics
|
# rubocop:disable Metrics
|
||||||
def call(submission)
|
def call(submission)
|
||||||
document = build_audit_trail(submission)
|
|
||||||
|
|
||||||
account = submission.account
|
account = submission.account
|
||||||
|
|
||||||
pkcs = Accounts.load_signing_pkcs(account)
|
I18n.with_locale(account.locale) do
|
||||||
tsa_url = Accounts.load_timeserver_url(account)
|
document = build_audit_trail(submission)
|
||||||
|
|
||||||
io = StringIO.new
|
pkcs = Accounts.load_signing_pkcs(account)
|
||||||
|
tsa_url = Accounts.load_timeserver_url(account)
|
||||||
|
|
||||||
document.trailer.info[:Creator] = "#{Docuseal.product_name} (#{Docuseal::PRODUCT_URL})"
|
io = StringIO.new
|
||||||
|
|
||||||
sign_params = {
|
document.trailer.info[:Creator] = "#{Docuseal.product_name} (#{Docuseal::PRODUCT_URL})"
|
||||||
reason: sign_reason,
|
|
||||||
**Submissions::GenerateResultAttachments.build_signing_params(pkcs, tsa_url)
|
|
||||||
}
|
|
||||||
|
|
||||||
document.sign(io, **sign_params)
|
last_submitter = submission.submitters.select(&:completed_at).max_by(&:completed_at)
|
||||||
|
|
||||||
Submissions::GenerateResultAttachments.maybe_enable_ltv(io, sign_params)
|
sign_params = {
|
||||||
|
reason: sign_reason,
|
||||||
|
**Submissions::GenerateResultAttachments.build_signing_params(last_submitter, pkcs, tsa_url)
|
||||||
|
}
|
||||||
|
|
||||||
ActiveStorage::Attachment.create!(
|
document.sign(io, **sign_params)
|
||||||
blob: ActiveStorage::Blob.create_and_upload!(
|
|
||||||
io: io.tap(&:rewind), filename: "Audit Log - #{submission.template.name}.pdf"
|
Submissions::GenerateResultAttachments.maybe_enable_ltv(io, sign_params)
|
||||||
),
|
|
||||||
name: 'audit_trail',
|
ActiveStorage::Attachment.create!(
|
||||||
record: submission
|
blob: ActiveStorage::Blob.create_and_upload!(
|
||||||
)
|
io: io.tap(&:rewind), filename: "#{I18n.t('audit_log')} - #{submission.template.name}.pdf"
|
||||||
|
),
|
||||||
|
name: 'audit_trail',
|
||||||
|
record: submission
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_audit_trail(submission)
|
def build_audit_trail(submission)
|
||||||
@@ -97,6 +98,12 @@ module Submissions
|
|||||||
height: 1
|
height: 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
configs = submission.account.account_configs.where(key: [AccountConfig::WITH_AUDIT_VALUES_KEY,
|
||||||
|
AccountConfig::WITH_SIGNATURE_ID])
|
||||||
|
|
||||||
|
with_signature_id = configs.find { |c| c.key == AccountConfig::WITH_SIGNATURE_ID }&.value == true
|
||||||
|
with_audit_values = configs.find { |c| c.key == AccountConfig::WITH_AUDIT_VALUES_KEY }&.value != false
|
||||||
|
|
||||||
composer.page_style(:default, page_size:) do |canvas, style|
|
composer.page_style(:default, page_size:) do |canvas, style|
|
||||||
box = canvas.context.box(:media)
|
box = canvas.context.box(:media)
|
||||||
canvas.save_graphics_state do
|
canvas.save_graphics_state do
|
||||||
@@ -108,9 +115,6 @@ module Submissions
|
|||||||
maybe_add_background(canvas, submission, page_size)
|
maybe_add_background(canvas, submission, page_size)
|
||||||
end
|
end
|
||||||
|
|
||||||
with_signature_id = submission.account.account_configs
|
|
||||||
.exists?(key: AccountConfig::WITH_SIGNATURE_ID, value: true)
|
|
||||||
|
|
||||||
if with_signature_id || submission.account.testing?
|
if with_signature_id || submission.account.testing?
|
||||||
canvas.save_graphics_state do
|
canvas.save_graphics_state do
|
||||||
document_id = Digest::MD5.hexdigest(submission.slug).upcase
|
document_id = Digest::MD5.hexdigest(submission.slug).upcase
|
||||||
@@ -125,7 +129,7 @@ module Submissions
|
|||||||
TESTING_FOOTER
|
TESTING_FOOTER
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
"Document ID: #{document_id}"
|
"#{I18n.t('document_id')}: #{document_id}"
|
||||||
end
|
end
|
||||||
|
|
||||||
text = HexaPDF::Layout::TextFragment.create(
|
text = HexaPDF::Layout::TextFragment.create(
|
||||||
@@ -153,24 +157,26 @@ module Submissions
|
|||||||
composer.column(columns: 1) do |column|
|
composer.column(columns: 1) do |column|
|
||||||
add_logo(column, submission)
|
add_logo(column, submission)
|
||||||
|
|
||||||
column.text(account.testing? ? 'Testing Log - Not for Production Use' : 'Audit Log',
|
column.text(account.testing? ? I18n.t('testing_log_not_for_production_use') : I18n.t('audit_log'),
|
||||||
font_size: 16,
|
font_size: 16,
|
||||||
padding: [10, 0, 0, 0],
|
padding: [10, 0, 0, 0],
|
||||||
position: :float, text_align: :right)
|
position: :float, text_align: :right)
|
||||||
end
|
end
|
||||||
|
|
||||||
composer.column(columns: 1) do |column|
|
composer.column(columns: 1) do |column|
|
||||||
column.text("Envelope ID: #{submission.id}", font_size: 12, padding: [15, 0, 8, 0], position: :float)
|
column.text("#{I18n.t('envelope_id')}: #{submission.id}", font_size: 12,
|
||||||
|
padding: [15, 0, 8, 0],
|
||||||
|
position: :float)
|
||||||
|
|
||||||
unless submission.source.in?(%w[embed api])
|
unless submission.source.in?(%w[embed api])
|
||||||
column.formatted_text([{ link: verify_url, text: 'Verify', style: :link }],
|
column.formatted_text([{ link: verify_url, text: I18n.t('verify'), style: :link }],
|
||||||
font_size: 9, padding: [15, 0, 10, 0], position: :float, text_align: :right)
|
font_size: 9, padding: [15, 0, 10, 0], position: :float, text_align: :right)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
composer.draw_box(divider)
|
composer.draw_box(divider)
|
||||||
|
|
||||||
last_submitter = submission.submitters.where.not(completed_at: nil).order(:completed_at).last
|
last_submitter = submission.submitters.select(&:completed_at).max_by(&:completed_at)
|
||||||
|
|
||||||
documents_data = Submitters.select_attachments_for_download(last_submitter).map do |document|
|
documents_data = Submitters.select_attachments_for_download(last_submitter).map do |document|
|
||||||
original_documents = submission.template.documents.select do |e|
|
original_documents = submission.template.documents.select do |e|
|
||||||
@@ -183,22 +189,19 @@ module Submissions
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
link =
|
|
||||||
ActiveStorage::Blob.proxy_url(document.blob)
|
|
||||||
|
|
||||||
[
|
[
|
||||||
composer.document.layout.formatted_text_box(
|
composer.document.layout.formatted_text_box(
|
||||||
[{ text: document.filename.to_s, link: }]
|
[{ text: document.filename.to_s }]
|
||||||
),
|
),
|
||||||
composer.document.layout.formatted_text_box(
|
composer.document.layout.formatted_text_box(
|
||||||
[
|
[
|
||||||
{ text: "Original SHA256:\n", font: [FONT_NAME, { variant: :bold }] },
|
{ text: "#{I18n.t('original_sha256')}:\n", font: [FONT_NAME, { variant: :bold }] },
|
||||||
original_documents.map { |d| d.metadata['sha256'] || d.checksum }.join("\n"),
|
original_documents.map { |d| d.metadata['sha256'] || d.checksum }.join("\n"),
|
||||||
"\n",
|
"\n",
|
||||||
{ text: "Result SHA256:\n", font: [FONT_NAME, { variant: :bold }] },
|
{ text: "#{I18n.t('result_sha256')}:\n", font: [FONT_NAME, { variant: :bold }] },
|
||||||
document.metadata['sha256'] || document.checksum,
|
document.metadata['sha256'] || document.checksum,
|
||||||
"\n",
|
"\n",
|
||||||
{ text: 'Generated at: ', font: [FONT_NAME, { variant: :bold }] },
|
{ text: "#{I18n.t('generated_at')}: ", font: [FONT_NAME, { variant: :bold }] },
|
||||||
"#{I18n.l(document.created_at.in_time_zone(account.timezone), format: :long, locale: account.locale)} " \
|
"#{I18n.l(document.created_at.in_time_zone(account.timezone), format: :long, locale: account.locale)} " \
|
||||||
"#{TimeUtils.timezone_abbr(account.timezone, document.created_at)}"
|
"#{TimeUtils.timezone_abbr(account.timezone, document.created_at)}"
|
||||||
], line_spacing: 1.3
|
], line_spacing: 1.3
|
||||||
@@ -245,13 +248,13 @@ module Submissions
|
|||||||
composer.document.layout.formatted_text_box(
|
composer.document.layout.formatted_text_box(
|
||||||
[
|
[
|
||||||
submitter.email && click_email_event && {
|
submitter.email && click_email_event && {
|
||||||
text: "Email verification: #{VERIFIED_TEXT}\n"
|
text: "#{I18n.t('email_verification')}: #{I18n.t('verified')}\n"
|
||||||
},
|
},
|
||||||
submitter.phone && is_phone_verified && {
|
submitter.phone && is_phone_verified && {
|
||||||
text: "Phone verification: #{VERIFIED_TEXT}\n"
|
text: "#{I18n.t('phone_verification')}: #{I18n.t('verified')}\n"
|
||||||
},
|
},
|
||||||
completed_event.data['ip'] && { text: "IP: #{completed_event.data['ip']}\n" },
|
completed_event.data['ip'] && { text: "IP: #{completed_event.data['ip']}\n" },
|
||||||
completed_event.data['sid'] && { text: "Session ID: #{completed_event.data['sid']}\n" },
|
completed_event.data['sid'] && { text: "#{I18n.t('session_id')}: #{completed_event.data['sid']}\n" },
|
||||||
completed_event.data['ua'] && { text: "User agent: #{completed_event.data['ua']}\n" },
|
completed_event.data['ua'] && { text: "User agent: #{completed_event.data['ua']}\n" },
|
||||||
"\n"
|
"\n"
|
||||||
].compact_blank, line_spacing: 1.3, padding: [10, 20, 20, 0]
|
].compact_blank, line_spacing: 1.3, padding: [10, 20, 20, 0]
|
||||||
@@ -264,6 +267,7 @@ module Submissions
|
|||||||
submission.template_fields.filter_map do |field|
|
submission.template_fields.filter_map do |field|
|
||||||
next if field['submitter_uuid'] != submitter.uuid
|
next if field['submitter_uuid'] != submitter.uuid
|
||||||
next if field['type'] == 'heading'
|
next if field['type'] == 'heading'
|
||||||
|
next if !with_audit_values && !field['type'].in?(%w[signature initials])
|
||||||
|
|
||||||
submitter_field_counters[field['type']] += 1
|
submitter_field_counters[field['type']] += 1
|
||||||
|
|
||||||
@@ -278,7 +282,7 @@ module Submissions
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
text: TextUtils.maybe_rtl_reverse(field_name).upcase.presence ||
|
text: TextUtils.maybe_rtl_reverse(field_name).upcase.presence ||
|
||||||
"#{field['type']} Field #{submitter_field_counters[field['type']]}\n".upcase,
|
"#{I18n.t("#{field['type']}_field")} #{submitter_field_counters[field['type']]}\n".upcase,
|
||||||
font_size: 6
|
font_size: 6
|
||||||
}
|
}
|
||||||
].compact_blank,
|
].compact_blank,
|
||||||
@@ -310,7 +314,8 @@ module Submissions
|
|||||||
|
|
||||||
price = ApplicationController.helpers.number_to_currency(field['preferences']['price'], unit:)
|
price = ApplicationController.helpers.number_to_currency(field['preferences']['price'], unit:)
|
||||||
|
|
||||||
composer.formatted_text_box([{ text: "Paid #{price}\n" }], padding: [0, 0, 10, 0])
|
composer.formatted_text_box([{ text: "#{I18n.t('paid_price', price:)}\n" }],
|
||||||
|
padding: [0, 0, 10, 0])
|
||||||
end
|
end
|
||||||
|
|
||||||
composer.formatted_text_box(
|
composer.formatted_text_box(
|
||||||
@@ -330,7 +335,10 @@ module Submissions
|
|||||||
value = TimeUtils.format_date_string(value, field.dig('preferences', 'format'), account.locale)
|
value = TimeUtils.format_date_string(value, field.dig('preferences', 'format'), account.locale)
|
||||||
end
|
end
|
||||||
|
|
||||||
value = NumberUtils.format_number(value, field.dig('preferences', 'format')) if field['type'] == 'number'
|
if field['type'] == 'number'
|
||||||
|
value = NumberUtils.format_number(value,
|
||||||
|
field.dig('preferences', 'format'))
|
||||||
|
end
|
||||||
|
|
||||||
value = value.join(', ') if value.is_a?(Array)
|
value = value.join(', ') if value.is_a?(Array)
|
||||||
|
|
||||||
@@ -340,37 +348,42 @@ module Submissions
|
|||||||
end
|
end
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
composer.draw_box(divider)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
composer.text('Event Log', font_size: 12, padding: [10, 0, 20, 0])
|
composer.draw_box(divider)
|
||||||
|
|
||||||
|
composer.text(I18n.t('event_log'), font_size: 12, padding: [10, 0, 20, 0])
|
||||||
|
|
||||||
events_data = submission.submission_events.sort_by(&:event_timestamp).map do |event|
|
events_data = submission.submission_events.sort_by(&:event_timestamp).map do |event|
|
||||||
submitter = submission.submitters.find { |e| e.id == event.submitter_id }
|
submitter = submission.submitters.find { |e| e.id == event.submitter_id }
|
||||||
|
submitter_name =
|
||||||
|
if event.event_type.include?('sms') || event.event_type.include?('phone')
|
||||||
|
event.data['phone'] || submitter.phone
|
||||||
|
else
|
||||||
|
submitter.name || submitter.email || submitter.phone
|
||||||
|
end
|
||||||
|
|
||||||
text = SubmissionEvents::EVENT_NAMES[event.event_type.to_sym]
|
text =
|
||||||
|
if event.event_type == 'invite_party' &&
|
||||||
|
(invited_submitter = submission.submitters.find { |e| e.uuid == event.data['uuid'] }) &&
|
||||||
|
(name = submission.template_submitters.find { |e| e['uuid'] == event.data['uuid'] }&.dig('name'))
|
||||||
|
invited_submitter_name = [invited_submitter.name || invited_submitter.email || invited_submitter.phone,
|
||||||
|
name].join(' ')
|
||||||
|
I18n.t('submission_event_names.invite_party_by_html', invited_submitter_name:,
|
||||||
|
submitter_name:)
|
||||||
|
elsif event.event_type.include?('send_')
|
||||||
|
I18n.t("submission_event_names.#{event.event_type}_to_html", submitter_name:)
|
||||||
|
else
|
||||||
|
I18n.t("submission_event_names.#{event.event_type}_by_html", submitter_name:)
|
||||||
|
end
|
||||||
|
|
||||||
if event.event_type == 'invite_party' &&
|
bold_text, normal_text = text.match(%r{<b>(.*?)</b>(.*)}).captures
|
||||||
(invited_submitter = submission.submitters.find { |e| e.uuid == event.data['uuid'] }) &&
|
|
||||||
(name = submission.template_submitters.find { |e| e['uuid'] == event.data['uuid'] }&.dig('name'))
|
|
||||||
text += ['', invited_submitter.name || invited_submitter.email || invited_submitter.phone, name].join(' ')
|
|
||||||
end
|
|
||||||
|
|
||||||
[
|
[
|
||||||
"#{I18n.l(event.event_timestamp.in_time_zone(account.timezone), format: :long, locale: account.locale)} " \
|
"#{I18n.l(event.event_timestamp.in_time_zone(account.timezone), format: :long, locale: account.locale)} " \
|
||||||
"#{TimeUtils.timezone_abbr(account.timezone, event.event_timestamp)}",
|
"#{TimeUtils.timezone_abbr(account.timezone, event.event_timestamp)}",
|
||||||
composer.document.layout.formatted_text_box(
|
composer.document.layout.formatted_text_box([{ text: bold_text, font: [FONT_NAME, { variant: :bold }] },
|
||||||
[
|
normal_text])
|
||||||
{ text:, font: [FONT_NAME, { variant: :bold }] },
|
|
||||||
event.event_type.include?('send_') ? ' to ' : ' by ',
|
|
||||||
if event.event_type.include?('sms') || event.event_type.include?('phone')
|
|
||||||
event.data['phone'] || submitter.phone
|
|
||||||
else
|
|
||||||
submitter.name || submitter.email || submitter.phone
|
|
||||||
end
|
|
||||||
]
|
|
||||||
)
|
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ module Submissions
|
|||||||
pdf.trailer.info[:Creator] = "#{Docuseal.product_name} (#{Docuseal::PRODUCT_URL})"
|
pdf.trailer.info[:Creator] = "#{Docuseal.product_name} (#{Docuseal::PRODUCT_URL})"
|
||||||
|
|
||||||
sign_params = {
|
sign_params = {
|
||||||
reason: sign_reason,
|
reason: Submissions::GenerateResultAttachments.single_sign_reason(submitter),
|
||||||
**Submissions::GenerateResultAttachments.build_signing_params(pkcs, tsa_url)
|
**Submissions::GenerateResultAttachments.build_signing_params(submitter, pkcs, tsa_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
pdf.sign(io, **sign_params)
|
pdf.sign(io, **sign_params)
|
||||||
@@ -38,7 +38,9 @@ module Submissions
|
|||||||
def build_combined_pdf(submitter)
|
def build_combined_pdf(submitter)
|
||||||
pdfs_index = Submissions::GenerateResultAttachments.generate_pdfs(submitter)
|
pdfs_index = Submissions::GenerateResultAttachments.generate_pdfs(submitter)
|
||||||
|
|
||||||
audit_trail = Submissions::GenerateAuditTrail.build_audit_trail(submitter.submission)
|
audit_trail = I18n.with_locale(submitter.account.locale) do
|
||||||
|
Submissions::GenerateAuditTrail.build_audit_trail(submitter.submission)
|
||||||
|
end
|
||||||
|
|
||||||
audit_trail.dispatch_message(:complete_objects)
|
audit_trail.dispatch_message(:complete_objects)
|
||||||
|
|
||||||
@@ -56,9 +58,5 @@ module Submissions
|
|||||||
|
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
def sign_reason
|
|
||||||
'Signed with DocuSeal.co'
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -21,7 +21,7 @@ module Submissions
|
|||||||
def rows_to_xlsx(rows)
|
def rows_to_xlsx(rows)
|
||||||
workbook = RubyXL::Workbook.new
|
workbook = RubyXL::Workbook.new
|
||||||
worksheet = workbook[0]
|
worksheet = workbook[0]
|
||||||
worksheet.sheet_name = I18n.l(Time.current.to_date)
|
worksheet.sheet_name = Time.current.to_date.to_s
|
||||||
|
|
||||||
headers = build_headers(rows)
|
headers = build_headers(rows)
|
||||||
headers.each_with_index do |column_name, column_index|
|
headers.each_with_index do |column_name, column_index|
|
||||||
@@ -79,7 +79,7 @@ module Submissions
|
|||||||
|
|
||||||
submission_data += submitter.documents.map.with_index(1) do |attachment, index|
|
submission_data += submitter.documents.map.with_index(1) do |attachment, index|
|
||||||
{
|
{
|
||||||
name: "Document #{index}",
|
name: "#{I18n.t('document')} #{index}",
|
||||||
value: ActiveStorage::Blob.proxy_url(attachment.blob)
|
value: ActiveStorage::Blob.proxy_url(attachment.blob)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
@@ -92,20 +92,20 @@ module Submissions
|
|||||||
def build_submission_data(submitter, submitter_name, submitters_count)
|
def build_submission_data(submitter, submitter_name, submitters_count)
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
name: column_name('Name', submitter_name, submitters_count),
|
name: column_name(I18n.t('name'), submitter_name, submitters_count),
|
||||||
value: submitter.name
|
value: submitter.name
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: column_name('Email', submitter_name, submitters_count),
|
name: column_name(I18n.t('email'), submitter_name, submitters_count),
|
||||||
value: submitter.email
|
value: submitter.email
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: column_name('Phone', submitter_name, submitters_count),
|
name: column_name(I18n.t('phone'), submitter_name, submitters_count),
|
||||||
value: submitter.phone
|
value: submitter.phone
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: column_name('Completed At', submitter_name, submitters_count),
|
name: column_name(I18n.t('completed_at'), submitter_name, submitters_count),
|
||||||
value: submitter.completed_at
|
value: submitter.completed_at.to_s
|
||||||
}
|
}
|
||||||
].reject { |e| e[:value].blank? }
|
].reject { |e| e[:value].blank? }
|
||||||
end
|
end
|
||||||
@@ -127,7 +127,8 @@ module Submissions
|
|||||||
template_field_type = template_field['type']
|
template_field_type = template_field['type']
|
||||||
template_field_counters[template_field_type] += 1
|
template_field_counters[template_field_type] += 1
|
||||||
template_field_name = template_field['name'].presence
|
template_field_name = template_field['name'].presence
|
||||||
template_field_name ||= "#{template_field_type.titleize} Field #{template_field_counters[template_field_type]}"
|
template_field_name ||=
|
||||||
|
"#{I18n.t("#{template_field_type}_field")} #{template_field_counters[template_field_type]}"
|
||||||
|
|
||||||
value =
|
value =
|
||||||
if template_field_type.in?(%w[image signature])
|
if template_field_type.in?(%w[image signature])
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ module Submissions
|
|||||||
TESTING_FOOTER
|
TESTING_FOOTER
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
"Document ID: #{document_id}"
|
"#{I18n.t('document_id', locale: submitter.account.locale)}: #{document_id}"
|
||||||
end
|
end
|
||||||
|
|
||||||
text = HexaPDF::Layout::TextFragment.create(
|
text = HexaPDF::Layout::TextFragment.create(
|
||||||
@@ -224,11 +224,12 @@ module Submissions
|
|||||||
reason_value = submitter.values[field.dig('preferences', 'reason_field_uuid')].presence
|
reason_value = submitter.values[field.dig('preferences', 'reason_field_uuid')].presence
|
||||||
|
|
||||||
reason_string =
|
reason_string =
|
||||||
"#{I18n.t('reason')}: #{reason_value || I18n.t('digitally_signed_by')} " \
|
I18n.with_locale(submitter.account.locale) do
|
||||||
"#{submitter.name}#{submitter.email.present? ? " <#{submitter.email}>" : ''}\n" \
|
"#{I18n.t('reason')}: #{reason_value || I18n.t('digitally_signed_by')} " \
|
||||||
"#{I18n.l(attachment.created_at.in_time_zone(submitter.account.timezone),
|
"#{submitter.name}#{submitter.email.present? ? " <#{submitter.email}>" : ''}\n" \
|
||||||
format: :long, locale: submitter.account.locale)} " \
|
"#{I18n.l(attachment.created_at.in_time_zone(submitter.account.timezone), format: :long)} " \
|
||||||
"#{TimeUtils.timezone_abbr(submitter.account.timezone, attachment.created_at)}"
|
"#{TimeUtils.timezone_abbr(submitter.account.timezone, attachment.created_at)}"
|
||||||
|
end
|
||||||
|
|
||||||
reason_text = HexaPDF::Layout::TextFragment.create(reason_string,
|
reason_text = HexaPDF::Layout::TextFragment.create(reason_string,
|
||||||
font:,
|
font:,
|
||||||
@@ -340,7 +341,8 @@ module Submissions
|
|||||||
if field['type'].in?(%w[multiple radio])
|
if field['type'].in?(%w[multiple radio])
|
||||||
option = field['options']&.find { |o| o['uuid'] == area['option_uuid'] }
|
option = field['options']&.find { |o| o['uuid'] == area['option_uuid'] }
|
||||||
|
|
||||||
option_name = option['value'].presence || "Option #{field['options'].index(option) + 1}"
|
option_name = option['value'].presence
|
||||||
|
option_name ||= "#{I18n.t('option', locale: account.locale)} #{field['options'].index(option) + 1}"
|
||||||
|
|
||||||
value = Array.wrap(value).include?(option_name)
|
value = Array.wrap(value).include?(option_name)
|
||||||
end
|
end
|
||||||
@@ -454,7 +456,7 @@ module Submissions
|
|||||||
if sign_reason
|
if sign_reason
|
||||||
sign_params = {
|
sign_params = {
|
||||||
reason: sign_reason,
|
reason: sign_reason,
|
||||||
**build_signing_params(pkcs, tsa_url)
|
**build_signing_params(submitter, pkcs, tsa_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@@ -491,7 +493,7 @@ module Submissions
|
|||||||
io
|
io
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_signing_params(pkcs, tsa_url)
|
def build_signing_params(_submitter, pkcs, tsa_url)
|
||||||
params = {
|
params = {
|
||||||
certificate: pkcs.certificate,
|
certificate: pkcs.certificate,
|
||||||
key: pkcs.key,
|
key: pkcs.key,
|
||||||
|
|||||||
+11
-1
@@ -27,7 +27,7 @@ module Submitters
|
|||||||
return [submitter.submission.combined_document_attachment]
|
return [submitter.submission.combined_document_attachment]
|
||||||
end
|
end
|
||||||
|
|
||||||
original_documents = submitter.submission.template.documents.preload(:blob)
|
original_documents = submitter.submission.template_schema_documents.preload(:blob)
|
||||||
is_more_than_two_images = original_documents.count(&:image?) > 1
|
is_more_than_two_images = original_documents.count(&:image?) > 1
|
||||||
|
|
||||||
submitter.documents.preload(:blob).reject do |attachment|
|
submitter.documents.preload(:blob).reject do |attachment|
|
||||||
@@ -102,4 +102,14 @@ module Submitters
|
|||||||
SendSubmitterInvitationEmailJob.perform_async('submitter_id' => submitter.id)
|
SendSubmitterInvitationEmailJob.perform_async('submitter_id' => submitter.id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def current_submitter_order?(submitter)
|
||||||
|
submitter_items = submitter.submission.template_submitters || submitter.submission.template.submitters
|
||||||
|
|
||||||
|
before_items = submitter_items[0...(submitter_items.find_index { |e| e['uuid'] == submitter.uuid })]
|
||||||
|
|
||||||
|
before_items.reduce(true) do |acc, item|
|
||||||
|
acc && submitter.submission.submitters.find { |e| e.uuid == item['uuid'] }&.completed_at?
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
class UserMailerPreview < ActionMailer::Preview
|
class UserMailerPreview < ActionMailer::Preview
|
||||||
def invitation_email
|
def invitation_email
|
||||||
UserMailer.invitation_email(User.last)
|
user = User.first
|
||||||
|
user.account.locale = I18n.locale
|
||||||
|
UserMailer.invitation_email(user)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Loaded 100 of 103 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user