mirror of
https://github.com/docusealco/docuseal
synced 2026-11-05 14:42:33 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9f314898b | ||
|
|
4fc7412cac | ||
|
|
9adbfc52c2 | ||
|
|
1ad8d9196a | ||
|
|
e9172392b5 | ||
|
|
d6d94de328 | ||
|
|
77261f457c | ||
|
|
c258915031 | ||
|
|
c1db8bdd3b | ||
|
|
c700484ce8 | ||
|
|
b62bd200ed | ||
|
|
a164fe8dd8 | ||
|
|
bb40e872b3 | ||
|
|
bab80e9488 | ||
|
|
d090d79ebf | ||
|
|
2299ba4e29 | ||
|
|
d6474f0e6e | ||
|
|
e0a297cf81 | ||
|
|
40f5fa4217 | ||
|
|
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
+2
-2
@@ -41,7 +41,7 @@ ENV OPENSSL_CONF=/app/openssl_legacy.cnf
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN apk add --no-cache sqlite-dev libpq-dev mariadb-dev vips-dev vips-poppler poppler-utils redis vips-heif gcompat ttf-freefont && mkdir /fonts && rm /usr/share/fonts/freefont/FreeSans.otf
|
RUN echo '@edge https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories && apk add --no-cache sqlite-dev libpq-dev mariadb-dev vips-dev vips-poppler poppler-utils redis libheif@edge vips-heif gcompat ttf-freefont && mkdir /fonts && rm /usr/share/fonts/freefont/FreeSans.otf
|
||||||
|
|
||||||
RUN echo $'.include = /etc/ssl/openssl.cnf\n\
|
RUN echo $'.include = /etc/ssl/openssl.cnf\n\
|
||||||
\n\
|
\n\
|
||||||
@@ -57,7 +57,7 @@ activate = 1' >> /app/openssl_legacy.cnf
|
|||||||
|
|
||||||
COPY ./Gemfile ./Gemfile.lock ./
|
COPY ./Gemfile ./Gemfile.lock ./
|
||||||
|
|
||||||
RUN apk add --no-cache build-base && bundle install && apk del build-base && rm -rf ~/.bundle /usr/local/bundle/cache && ruby -e "puts Dir['/usr/local/bundle/**/{spec,rdoc,resources/shared,resources/collation,resources/locales}']" | xargs rm -rf
|
RUN apk add --no-cache build-base && bundle install && apk del --no-cache build-base && rm -rf ~/.bundle /usr/local/bundle/cache && ruby -e "puts Dir['/usr/local/bundle/**/{spec,rdoc,resources/shared,resources/collation,resources/locales}']" | xargs rm -rf
|
||||||
|
|
||||||
COPY ./bin ./bin
|
COPY ./bin ./bin
|
||||||
COPY ./app ./app
|
COPY ./app ./app
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ class PreviewDocumentPageController < ActionController::API
|
|||||||
|
|
||||||
return head :not_found unless attachment
|
return head :not_found unless attachment
|
||||||
|
|
||||||
preview_image = attachment.preview_images.joins(:blob).find_by(blob: { filename: "#{params[:id]}#{FORMAT}" })
|
preview_image = attachment.preview_images.joins(:blob)
|
||||||
|
.find_by(blob: { filename: ["#{params[:id]}.png", "#{params[:id]}.jpg"] })
|
||||||
|
|
||||||
return redirect_to preview_image.url, allow_other_host: true if preview_image
|
return redirect_to preview_image.url, allow_other_host: true if preview_image
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -9,6 +9,13 @@ class SubmissionsController < ApplicationController
|
|||||||
def show
|
def show
|
||||||
@submission = Submissions.preload_with_pages(@submission)
|
@submission = Submissions.preload_with_pages(@submission)
|
||||||
|
|
||||||
|
unless @submission.submitters.all?(&:completed_at?)
|
||||||
|
ActiveRecord::Associations::Preloader.new(
|
||||||
|
records: [@submission],
|
||||||
|
associations: [submitters: :start_form_submission_events]
|
||||||
|
).call
|
||||||
|
end
|
||||||
|
|
||||||
render :show, layout: 'plain'
|
render :show, layout: 'plain'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,6 @@ class SubmissionsDashboardController < ApplicationController
|
|||||||
@submissions = @submissions.pending if params[:status] == 'pending'
|
@submissions = @submissions.pending if params[:status] == 'pending'
|
||||||
@submissions = @submissions.completed if params[:status] == 'completed'
|
@submissions = @submissions.completed if params[:status] == 'completed'
|
||||||
|
|
||||||
@pagy, @submissions = pagy(@submissions.preload(:submitters).order(id: :desc))
|
@pagy, @submissions = pagy(@submissions.preload(submitters: :start_form_submission_events).order(id: :desc))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class SubmittersController < ApplicationController
|
||||||
|
load_and_authorize_resource :submitter, only: %i[edit update]
|
||||||
|
|
||||||
|
def edit
|
||||||
|
@submitter_email_message =
|
||||||
|
if @submitter.preferences['email_message_uuid'].present?
|
||||||
|
@submitter.account.email_messages.find_by(uuid: @submitter.preferences['email_message_uuid'])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
submission = @submitter.submission
|
||||||
|
|
||||||
|
if @submitter.submission_events.exists?(event_type: 'start_form') || submission.archived_at? || submission.expired?
|
||||||
|
return redirect_back fallback_location: submission_path(submission), alert: I18n.t('submitter_cannot_be_updated')
|
||||||
|
end
|
||||||
|
|
||||||
|
if submitter_params.values.all?(&:blank?)
|
||||||
|
return redirect_back fallback_location: submission_path(submission),
|
||||||
|
alert: I18n.t('at_least_one_field_must_be_filled')
|
||||||
|
end
|
||||||
|
|
||||||
|
if params[:is_custom_message] != '1'
|
||||||
|
params.delete(:subject)
|
||||||
|
params.delete(:body)
|
||||||
|
end
|
||||||
|
|
||||||
|
submitter_preferences = Submitters.normalize_preferences(@submitter.account, current_user, params)
|
||||||
|
|
||||||
|
if submitter_preferences.key?('email_message_uuid')
|
||||||
|
@submitter.preferences['email_message_uuid'] = submitter_preferences['email_message_uuid']
|
||||||
|
end
|
||||||
|
|
||||||
|
assign_submitter_attrs(@submitter, submitter_params)
|
||||||
|
|
||||||
|
if @submitter.save
|
||||||
|
maybe_resend_email_sms(@submitter, params)
|
||||||
|
|
||||||
|
redirect_back fallback_location: submission_path(submission), notice: I18n.t('changes_have_been_saved')
|
||||||
|
else
|
||||||
|
redirect_back fallback_location: submission_path(submission), alert: I18n.t('unable_to_save')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def maybe_resend_email_sms(submitter, params)
|
||||||
|
if params[:send_email] == '1' && submitter.email.present?
|
||||||
|
is_sent_recently = Docuseal.multitenant? &&
|
||||||
|
EmailEvent.exists?(email: submitter.email,
|
||||||
|
tag: 'submitter_invitation',
|
||||||
|
emailable: submitter,
|
||||||
|
event_type: 'send',
|
||||||
|
created_at: 4.hours.ago..Time.current)
|
||||||
|
|
||||||
|
SendSubmitterInvitationEmailJob.perform_async('submitter_id' => submitter.id) unless is_sent_recently
|
||||||
|
end
|
||||||
|
|
||||||
|
return if submitter.phone.blank?
|
||||||
|
return unless params[:send_sms] == '1'
|
||||||
|
|
||||||
|
SendSubmitterInvitationSmsJob.perform_async('submitter_id' => submitter.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def assign_submitter_attrs(submitter, attrs)
|
||||||
|
submitter.phone = attrs[:phone].to_s.gsub(/[^0-9+]/, '') if attrs.key?(:phone)
|
||||||
|
|
||||||
|
submitter.email = Submissions.normalize_email(attrs[:email]) if attrs.key?(:email)
|
||||||
|
|
||||||
|
submitter.name = attrs[:name] if attrs.key?(:name)
|
||||||
|
|
||||||
|
submitter
|
||||||
|
end
|
||||||
|
|
||||||
|
def submitter_params
|
||||||
|
params.require(:submitter).permit(:email, :name, :phone).transform_values(&:strip)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -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
|
||||||
@@ -15,7 +15,7 @@ class TemplatesController < ApplicationController
|
|||||||
submissions = submissions.pending if params[:status] == 'pending'
|
submissions = submissions.pending if params[:status] == 'pending'
|
||||||
submissions = submissions.completed if params[:status] == 'completed'
|
submissions = submissions.completed if params[:status] == 'completed'
|
||||||
|
|
||||||
@pagy, @submissions = pagy(submissions.preload(:submitters).order(id: :desc))
|
@pagy, @submissions = pagy(submissions.preload(submitters: :start_form_submission_events).order(id: :desc))
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
redirect_to root_path
|
redirect_to root_path
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -134,7 +130,3 @@ button[disabled] .enabled {
|
|||||||
outline-offset: 3px;
|
outline-offset: 3px;
|
||||||
outline-color: hsl(var(--bc) / 0.2);
|
outline-color: hsl(var(--bc) / 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
select:required:invalid {
|
|
||||||
color: gray !important;
|
|
||||||
}
|
|
||||||
@@ -21,12 +21,14 @@ 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',
|
||||||
requireSigningReason: this.dataset.requireSigningReason === 'true',
|
requireSigningReason: this.dataset.requireSigningReason === 'true',
|
||||||
withConfetti: this.dataset.withConfetti !== 'false',
|
withConfetti: this.dataset.withConfetti !== 'false',
|
||||||
withDisclosure: this.dataset.withDisclosure === 'true',
|
withDisclosure: this.dataset.withDisclosure === 'true',
|
||||||
|
reuseSignature: this.dataset.reuseSignature !== 'false',
|
||||||
withTypedSignature: this.dataset.withTypedSignature !== 'false',
|
withTypedSignature: this.dataset.withTypedSignature !== 'false',
|
||||||
authenticityToken: document.querySelector('meta[name="csrf-token"]')?.content,
|
authenticityToken: document.querySelector('meta[name="csrf-token"]')?.content,
|
||||||
rememberSignature: this.dataset.rememberSignature === 'true',
|
rememberSignature: this.dataset.rememberSignature === 'true',
|
||||||
|
|||||||
@@ -31,10 +31,6 @@ button[disabled] .enabled {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
select:required:invalid {
|
|
||||||
@apply text-gray-300;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-bordered {
|
.input-bordered {
|
||||||
@apply border-base-content/20;
|
@apply border-base-content/20;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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'))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -115,7 +115,7 @@
|
|||||||
v-model="values[currentField.uuid]"
|
v-model="values[currentField.uuid]"
|
||||||
:show-field-names="showFieldNames"
|
:show-field-names="showFieldNames"
|
||||||
:field="currentField"
|
:field="currentField"
|
||||||
@submit="submitStep"
|
@submit="!isSubmitting && submitStep()"
|
||||||
@focus="scrollIntoField(currentField)"
|
@focus="scrollIntoField(currentField)"
|
||||||
/>
|
/>
|
||||||
<div v-else-if="currentField.type === 'select'">
|
<div v-else-if="currentField.type === 'select'">
|
||||||
@@ -152,6 +152,7 @@
|
|||||||
dir="auto"
|
dir="auto"
|
||||||
:required="currentField.required"
|
:required="currentField.required"
|
||||||
class="select base-input !text-2xl w-full text-center font-normal"
|
class="select base-input !text-2xl w-full text-center font-normal"
|
||||||
|
:class="{ 'text-gray-300': !values[currentField.uuid] }"
|
||||||
:name="`values[${currentField.uuid}]`"
|
:name="`values[${currentField.uuid}]`"
|
||||||
@change="values[currentField.uuid] = $event.target.value"
|
@change="values[currentField.uuid] = $event.target.value"
|
||||||
@focus="scrollIntoField(currentField)"
|
@focus="scrollIntoField(currentField)"
|
||||||
@@ -159,6 +160,7 @@
|
|||||||
<option
|
<option
|
||||||
value=""
|
value=""
|
||||||
:selected="!values[currentField.uuid]"
|
:selected="!values[currentField.uuid]"
|
||||||
|
class="text-gray-300"
|
||||||
>
|
>
|
||||||
{{ t('select_your_option') }}
|
{{ t('select_your_option') }}
|
||||||
</option>
|
</option>
|
||||||
@@ -167,6 +169,7 @@
|
|||||||
:key="option.uuid"
|
:key="option.uuid"
|
||||||
:selected="values[currentField.uuid] == option.value"
|
:selected="values[currentField.uuid] == option.value"
|
||||||
:value="option.value"
|
:value="option.value"
|
||||||
|
class="text-base-content"
|
||||||
>
|
>
|
||||||
{{ option.value }}
|
{{ option.value }}
|
||||||
</option>
|
</option>
|
||||||
@@ -392,7 +395,7 @@
|
|||||||
:default-value="submitter.phone"
|
:default-value="submitter.phone"
|
||||||
:submitter-slug="submitterSlug"
|
:submitter-slug="submitterSlug"
|
||||||
@focus="scrollIntoField(currentField)"
|
@focus="scrollIntoField(currentField)"
|
||||||
@submit="submitStep"
|
@submit="!isSubmitting && submitStep()"
|
||||||
/>
|
/>
|
||||||
<PaymentStep
|
<PaymentStep
|
||||||
v-else-if="currentField.type === 'payment'"
|
v-else-if="currentField.type === 'payment'"
|
||||||
@@ -404,7 +407,7 @@
|
|||||||
:values="values"
|
:values="values"
|
||||||
@attached="attachments.push($event)"
|
@attached="attachments.push($event)"
|
||||||
@focus="scrollIntoField(currentField)"
|
@focus="scrollIntoField(currentField)"
|
||||||
@submit="submitStep"
|
@submit="!isSubmitting && submitStep()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -897,7 +900,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) {
|
||||||
@@ -1142,13 +1145,15 @@ export default {
|
|||||||
async submitStep () {
|
async submitStep () {
|
||||||
this.isSubmitting = true
|
this.isSubmitting = true
|
||||||
|
|
||||||
|
const submitStep = this.currentStep
|
||||||
|
|
||||||
const stepPromise = ['signature', 'phone', 'initials', 'payment'].includes(this.currentField.type)
|
const stepPromise = ['signature', 'phone', 'initials', 'payment'].includes(this.currentField.type)
|
||||||
? this.$refs.currentStep.submit
|
? this.$refs.currentStep.submit
|
||||||
: () => Promise.resolve({})
|
: () => Promise.resolve({})
|
||||||
|
|
||||||
stepPromise().then(async () => {
|
stepPromise().then(async () => {
|
||||||
const emptyRequiredField = this.stepFields.find((fields, index) => {
|
const emptyRequiredField = this.stepFields.find((fields, index) => {
|
||||||
if (index >= this.currentStep) {
|
if (index >= submitStep) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1158,7 +1163,7 @@ export default {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const formData = new FormData(this.$refs.form)
|
const formData = new FormData(this.$refs.form)
|
||||||
const isLastStep = this.currentStep === this.stepFields.length - 1
|
const isLastStep = submitStep === this.stepFields.length - 1
|
||||||
|
|
||||||
if (isLastStep && !emptyRequiredField && !this.inviteSubmitters.length) {
|
if (isLastStep && !emptyRequiredField && !this.inviteSubmitters.length) {
|
||||||
formData.append('completed', 'true')
|
formData.append('completed', 'true')
|
||||||
@@ -1183,11 +1188,7 @@ export default {
|
|||||||
return Promise.reject(new Error(data.error))
|
return Promise.reject(new Error(data.error))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLastStep) {
|
const nextStep = (isLastStep && emptyRequiredField) || this.stepFields[submitStep + 1]
|
||||||
this.isSecondWalkthrough = true
|
|
||||||
}
|
|
||||||
|
|
||||||
const nextStep = (isLastStep && emptyRequiredField) || this.stepFields[this.currentStep + 1]
|
|
||||||
|
|
||||||
if (nextStep) {
|
if (nextStep) {
|
||||||
if (this.alwaysMinimize) {
|
if (this.alwaysMinimize) {
|
||||||
@@ -1211,7 +1212,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',
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -61,30 +61,55 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<div
|
||||||
v-show="!isCodeSent"
|
v-show="!isCodeSent"
|
||||||
:id="field.uuid"
|
class="flex w-full rounded-full outline-neutral-content outline-2 outline-offset-2 focus-within:outline"
|
||||||
ref="phone"
|
|
||||||
:value="modelValue || defaultValue"
|
|
||||||
:readonly="!!defaultValue"
|
|
||||||
class="base-input !text-2xl w-full"
|
|
||||||
autocomplete="tel"
|
|
||||||
pattern="^\+[0-9\s\-]+$"
|
|
||||||
type="tel"
|
|
||||||
inputmode="tel"
|
|
||||||
:required="field.required"
|
|
||||||
placeholder="+1 234 567-8900"
|
|
||||||
:name="`values[${field.uuid}]`"
|
|
||||||
@invalid="$event.target.value ? $event.target.setCustomValidity(`${t('use_international_format')}...`) : ''"
|
|
||||||
@input="[$event.target.setCustomValidity(''), $emit('update:model-value', $event.target.value)]"
|
|
||||||
@focus="$emit('focus')"
|
|
||||||
>
|
>
|
||||||
|
<div class="relative inline-block">
|
||||||
|
<div class="btn bg-base-200 border border-neutral-300 text-2xl whitespace-nowrap font-normal rounded-l-full">
|
||||||
|
{{ selectedCountry.flag }} +{{ selectedCountry.dial }}
|
||||||
|
</div>
|
||||||
|
<select
|
||||||
|
class="absolute top-0 bottom-0 right-0 left-0 opacity-0 w-full h-full cursor-pointer"
|
||||||
|
:disabled="!!defaultValue"
|
||||||
|
@change="onCountrySelect(countries.find((country) => country.flag === $event.target.value))"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-for="(country, index) in countries"
|
||||||
|
:key="index"
|
||||||
|
:value="country.flag"
|
||||||
|
>
|
||||||
|
{{ country.flag }} {{ country.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
:name="`values[${field.uuid}]`"
|
||||||
|
:value="fullInternationalPhoneValue"
|
||||||
|
hidden
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
:id="field.uuid"
|
||||||
|
ref="phone"
|
||||||
|
:value="phoneValue"
|
||||||
|
:readonly="!!defaultValue"
|
||||||
|
class="base-input !text-2xl !rounded-l-none !border-l-0 !outline-none w-full"
|
||||||
|
autocomplete="tel"
|
||||||
|
type="tel"
|
||||||
|
inputmode="tel"
|
||||||
|
:required="field.required"
|
||||||
|
placeholder="234 567-8900"
|
||||||
|
@input="onPhoneInput"
|
||||||
|
@focus="$emit('focus')"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import MarkdownContent from './markdown_content'
|
import MarkdownContent from './markdown_content'
|
||||||
|
import phoneData from './phone_data'
|
||||||
|
|
||||||
function throttle (func, delay) {
|
function throttle (func, delay) {
|
||||||
let lastCallTime = 0
|
let lastCallTime = 0
|
||||||
@@ -144,13 +169,73 @@ export default {
|
|||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
isCodeSent: false,
|
isCodeSent: false,
|
||||||
isResendLoading: false
|
isResendLoading: false,
|
||||||
|
phoneValue: this.modelValue || this.defaultValue || '',
|
||||||
|
selectedCountry: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
countries () {
|
||||||
|
return phoneData.map(([name, dial, flag, tz]) => {
|
||||||
|
return { name, dial, flag, tz }
|
||||||
|
})
|
||||||
|
},
|
||||||
|
countriesDialIndex () {
|
||||||
|
return this.countries.reduce((acc, item) => {
|
||||||
|
acc[item.dial] ||= item
|
||||||
|
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
},
|
||||||
|
dialCodesRegexp () {
|
||||||
|
const dialCodes = this.countries.map((country) => country.dial).sort((a, b) => b.length - a.length)
|
||||||
|
|
||||||
|
return new RegExp(`^\\+(${dialCodes.join('|')})`)
|
||||||
|
},
|
||||||
|
detectedPhoneValueDialCode () {
|
||||||
|
return (this.phoneValue || '').replace(/[^\d+]/g, '').match(this.dialCodesRegexp)?.[1]
|
||||||
|
},
|
||||||
|
fullInternationalPhoneValue () {
|
||||||
|
if (this.detectedPhoneValueDialCode) {
|
||||||
|
return this.phoneValue
|
||||||
|
} else if (this.phoneValue) {
|
||||||
|
return ['+', this.selectedCountry.dial, this.phoneValue].filter(Boolean).join('')
|
||||||
|
} else {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
const browserTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||||
|
|
||||||
|
if (this.detectedPhoneValueDialCode) {
|
||||||
|
this.selectedCountry = this.countriesDialIndex[this.detectedPhoneValueDialCode]
|
||||||
|
} else if (browserTimeZone) {
|
||||||
|
const tz = browserTimeZone.split('/')[1]
|
||||||
|
|
||||||
|
this.selectedCountry = this.countries.find((country) => country.tz.includes(tz)) || this.countries[0]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
emitSubmit: throttle(function (e) {
|
emitSubmit: throttle(function (e) {
|
||||||
this.$emit('submit')
|
this.$emit('submit')
|
||||||
}, 1000),
|
}, 1000),
|
||||||
|
onCountrySelect (country) {
|
||||||
|
if (this.selectedCountry.flag !== country.flag) {
|
||||||
|
this.phoneValue = this.phoneValue.replace(`+${this.selectedCountry.dial}`, `+${country.dial}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectedCountry = country
|
||||||
|
|
||||||
|
this.$refs.phone.focus()
|
||||||
|
},
|
||||||
|
onPhoneInput (e) {
|
||||||
|
this.phoneValue = e.target.value
|
||||||
|
|
||||||
|
if (this.detectedPhoneValueDialCode) {
|
||||||
|
this.selectedCountry = this.countriesDialIndex[this.detectedPhoneValueDialCode]
|
||||||
|
}
|
||||||
|
},
|
||||||
onInputCode (e) {
|
onInputCode (e) {
|
||||||
if (e.target.value.length === 6) {
|
if (e.target.value.length === 6) {
|
||||||
this.emitSubmit()
|
this.emitSubmit()
|
||||||
@@ -171,14 +256,14 @@ export default {
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
submitter_slug: this.submitterSlug,
|
submitter_slug: this.submitterSlug,
|
||||||
locale: this.locale,
|
locale: this.locale,
|
||||||
phone: this.$refs.phone.value
|
phone: this.fullInternationalPhoneValue
|
||||||
}),
|
}),
|
||||||
headers: { 'Content-Type': 'application/json' }
|
headers: { 'Content-Type': 'application/json' }
|
||||||
}).then(async (resp) => {
|
}).then(async (resp) => {
|
||||||
if (resp.status === 422) {
|
if (resp.status === 422) {
|
||||||
const data = await resp.json()
|
const data = await resp.json()
|
||||||
|
|
||||||
alert(this.t('number_phone_is_invalid').replace('{number}', this.$refs.phone.value))
|
alert(this.t('number_phone_is_invalid').replace('{number}', this.fullInternationalPhoneValue))
|
||||||
|
|
||||||
return Promise.reject(new Error(data.error))
|
return Promise.reject(new Error(data.error))
|
||||||
}
|
}
|
||||||
@@ -189,13 +274,13 @@ export default {
|
|||||||
return Promise.resolve({})
|
return Promise.resolve({})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.$refs.phone.value.toString().startsWith('+')) {
|
if (!this.fullInternationalPhoneValue.toString().startsWith('+')) {
|
||||||
alert(this.t('use_international_format'))
|
alert(this.t('use_international_format'))
|
||||||
|
|
||||||
return Promise.reject(new Error('phone invalid'))
|
return Promise.reject(new Error('phone invalid'))
|
||||||
} else if (!this.isCodeSent) {
|
} else if (!this.isCodeSent) {
|
||||||
return this.sendVerificationCode().then(() => {
|
return this.sendVerificationCode().then(() => {
|
||||||
this.$emit('update:model-value', this.$refs.phone.value)
|
this.$emit('update:model-value', this.fullInternationalPhoneValue)
|
||||||
|
|
||||||
this.isCodeSent = true
|
this.isCodeSent = true
|
||||||
|
|
||||||
|
|||||||
@@ -197,6 +197,7 @@
|
|||||||
<select
|
<select
|
||||||
v-if="requireSigningReason && !isOtherReason"
|
v-if="requireSigningReason && !isOtherReason"
|
||||||
class="select base-input !text-2xl w-full mt-6 text-center"
|
class="select base-input !text-2xl w-full mt-6 text-center"
|
||||||
|
:class="{ 'text-gray-300': !reason }"
|
||||||
required
|
required
|
||||||
:name="`values[${field.preferences.reason_field_uuid}]`"
|
:name="`values[${field.preferences.reason_field_uuid}]`"
|
||||||
@change="$event.target.value === 'other' ? [reason = '', isOtherReason = true] : $emit('update:reason', $event.target.value)"
|
@change="$event.target.value === 'other' ? [reason = '', isOtherReason = true] : $emit('update:reason', $event.target.value)"
|
||||||
@@ -205,6 +206,7 @@
|
|||||||
value=""
|
value=""
|
||||||
disabled
|
disabled
|
||||||
:selected="!reason"
|
:selected="!reason"
|
||||||
|
class="text-gray-300"
|
||||||
>
|
>
|
||||||
{{ t('select_a_reason') }}
|
{{ t('select_a_reason') }}
|
||||||
</option>
|
</option>
|
||||||
@@ -213,10 +215,14 @@
|
|||||||
:key="option"
|
:key="option"
|
||||||
:value="option"
|
:value="option"
|
||||||
:selected="reason === option"
|
:selected="reason === option"
|
||||||
|
class="text-base-content"
|
||||||
>
|
>
|
||||||
{{ label }}
|
{{ label }}
|
||||||
</option>
|
</option>
|
||||||
<option value="other">
|
<option
|
||||||
|
value="other"
|
||||||
|
class="text-base-content"
|
||||||
|
>
|
||||||
{{ t('other') }}
|
{{ t('other') }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<select
|
<select
|
||||||
class="select select-bordered select-sm w-full bg-white h-11 pl-4 text-base font-normal"
|
class="select select-bordered select-sm w-full bg-white h-11 pl-4 text-base font-normal"
|
||||||
|
:class="{ 'text-gray-300': !condition.field_uuid }"
|
||||||
required
|
required
|
||||||
@change="[
|
@change="[
|
||||||
condition.field_uuid = $event.target.value,
|
condition.field_uuid = $event.target.value,
|
||||||
@@ -68,6 +69,7 @@
|
|||||||
v-for="f in fields"
|
v-for="f in fields"
|
||||||
:key="f.uuid"
|
:key="f.uuid"
|
||||||
:value="f.uuid"
|
:value="f.uuid"
|
||||||
|
class="text-base-content"
|
||||||
:selected="condition.field_uuid === f.uuid"
|
:selected="condition.field_uuid === f.uuid"
|
||||||
>
|
>
|
||||||
{{ f.name || buildDefaultName(f, template.fields) }}
|
{{ f.name || buildDefaultName(f, template.fields) }}
|
||||||
@@ -90,6 +92,7 @@
|
|||||||
<select
|
<select
|
||||||
v-if="conditionField(condition)?.options?.length"
|
v-if="conditionField(condition)?.options?.length"
|
||||||
class="select select-bordered select-sm w-full bg-white h-11 pl-4 text-base font-normal"
|
class="select select-bordered select-sm w-full bg-white h-11 pl-4 text-base font-normal"
|
||||||
|
:class="{ 'text-gray-300': !condition.value }"
|
||||||
required
|
required
|
||||||
@change="condition.value = $event.target.value"
|
@change="condition.value = $event.target.value"
|
||||||
>
|
>
|
||||||
@@ -105,6 +108,7 @@
|
|||||||
:key="option.uuid"
|
:key="option.uuid"
|
||||||
:value="option.uuid"
|
:value="option.uuid"
|
||||||
:selected="condition.value === option.uuid"
|
:selected="condition.value === option.uuid"
|
||||||
|
class="text-base-content"
|
||||||
>
|
>
|
||||||
{{ option.value || `${t('option')} ${index + 1}` }}
|
{{ option.value || `${t('option')} ${index + 1}` }}
|
||||||
</option>
|
</option>
|
||||||
@@ -200,7 +204,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)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
const en = {
|
const en = {
|
||||||
editable: 'Editable',
|
editable: 'Editable',
|
||||||
|
recurrent: 'Recurrent',
|
||||||
|
one_off: 'One-off',
|
||||||
search_field: 'Search field',
|
search_field: 'Search field',
|
||||||
field_not_found: 'Field not found',
|
field_not_found: 'Field not found',
|
||||||
clear: 'Clear',
|
clear: 'Clear',
|
||||||
@@ -29,7 +31,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 +48,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 +103,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 +152,774 @@ const en = {
|
|||||||
learn_more: 'Learn more'
|
learn_more: 'Learn more'
|
||||||
}
|
}
|
||||||
|
|
||||||
export { en }
|
const es = {
|
||||||
|
recurrent: 'Recurrente',
|
||||||
|
one_off: 'Único',
|
||||||
|
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 = {
|
||||||
|
ricorrente: 'Ricorrente',
|
||||||
|
una_volta: 'Una volta',
|
||||||
|
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 = {
|
||||||
|
recurrent: 'Recurrente',
|
||||||
|
one_off: 'Único',
|
||||||
|
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 = {
|
||||||
|
recurrent: 'Récurrent',
|
||||||
|
one_off: 'Ponctuel',
|
||||||
|
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 = {
|
||||||
|
wiederkehrend: 'Wiederkehrend',
|
||||||
|
einmalig: 'Einmalig',
|
||||||
|
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
|
||||||
@@ -50,6 +50,7 @@
|
|||||||
<div class="flex">
|
<div class="flex">
|
||||||
<select
|
<select
|
||||||
class="base-select !select-sm !h-10"
|
class="base-select !select-sm !h-10"
|
||||||
|
:class="{ '!text-gray-300': !mapping.field_name }"
|
||||||
required
|
required
|
||||||
@change="mapping.field_name = $event.target.value"
|
@change="mapping.field_name = $event.target.value"
|
||||||
>
|
>
|
||||||
@@ -58,13 +59,14 @@
|
|||||||
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)"
|
||||||
:key="index"
|
:key="index"
|
||||||
:value="field.name"
|
:value="field.name"
|
||||||
:selected="mapping.field_name === field.name"
|
:selected="mapping.field_name === field.name"
|
||||||
|
class="text-base-content"
|
||||||
>
|
>
|
||||||
{{ field.name }}
|
{{ field.name }}
|
||||||
</option>
|
</option>
|
||||||
@@ -75,6 +77,7 @@
|
|||||||
<div class="w-full relative">
|
<div class="w-full relative">
|
||||||
<select
|
<select
|
||||||
class="base-select !select-sm !h-10"
|
class="base-select !select-sm !h-10"
|
||||||
|
:class="{ '!text-gray-300': !mapping.column_index }"
|
||||||
required
|
required
|
||||||
@change="mapping.column_index = parseInt($event.target.value)"
|
@change="mapping.column_index = parseInt($event.target.value)"
|
||||||
>
|
>
|
||||||
@@ -83,7 +86,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"
|
||||||
@@ -93,6 +96,7 @@
|
|||||||
v-if="column"
|
v-if="column"
|
||||||
:value="index"
|
:value="index"
|
||||||
:selected="index === mapping.column_index"
|
:selected="index === mapping.column_index"
|
||||||
|
class="text-base-content"
|
||||||
>
|
>
|
||||||
{{ column }}
|
{{ column }}
|
||||||
</option>
|
</option>
|
||||||
@@ -118,8 +122,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 +142,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 +156,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 +191,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 +214,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 +252,11 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
default: ''
|
default: ''
|
||||||
|
},
|
||||||
|
i18n: {
|
||||||
|
type: Object,
|
||||||
|
required: false,
|
||||||
|
default: () => ({})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
@@ -354,6 +363,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])
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
@click="closeDropdown"
|
@click="closeDropdown"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
v-if="!('price_id' in field.preferences)"
|
||||||
class="py-1.5 px-1 relative"
|
class="py-1.5 px-1 relative"
|
||||||
@click.stop
|
@click.stop
|
||||||
>
|
>
|
||||||
@@ -58,6 +59,13 @@
|
|||||||
class="input input-bordered input-xs w-full max-w-xs h-7 !outline-0"
|
class="input input-bordered input-xs w-full max-w-xs h-7 !outline-0"
|
||||||
@blur="save"
|
@blur="save"
|
||||||
>
|
>
|
||||||
|
<input
|
||||||
|
v-else-if="'price_id' in field.preferences"
|
||||||
|
v-model="field.preferences.price_id"
|
||||||
|
placeholder="Price ID: price_XXXXX"
|
||||||
|
class="input input-bordered input-xs w-full max-w-xs h-7 !outline-0"
|
||||||
|
@blur="save"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
v-else
|
v-else
|
||||||
v-model="field.preferences.price"
|
v-model="field.preferences.price"
|
||||||
@@ -72,8 +80,25 @@
|
|||||||
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 class="flex items-center justify-center">
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="hover:underline"
|
||||||
|
style="font-size: 11px"
|
||||||
|
:class="{'underline': !('price_id' in field.preferences)}"
|
||||||
|
@click="delete field.preferences.price_id"
|
||||||
|
>{{ t('one_off') }}</a>
|
||||||
|
<span class="h-2.5 border-l border-base-content mx-1" />
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="hover:underline"
|
||||||
|
style="font-size: 11px"
|
||||||
|
:class="{'underline': ('price_id' in field.preferences)}"
|
||||||
|
@click="field.preferences.price_id ??= ''"
|
||||||
|
>{{ t('recurrent') }}</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="!isConnected || isOauthSuccess"
|
v-if="!isConnected || isOauthSuccess"
|
||||||
@@ -158,7 +183,10 @@
|
|||||||
data-turbo="false"
|
data-turbo="false"
|
||||||
>{{ t('learn_more') }}</a>
|
>{{ t('learn_more') }}</a>
|
||||||
</div>
|
</div>
|
||||||
<li class="mb-1">
|
<li
|
||||||
|
v-if="!('price_id' in field.preferences)"
|
||||||
|
class="mb-1"
|
||||||
|
>
|
||||||
<label
|
<label
|
||||||
class="label-text cursor-pointer text-center w-full flex items-center"
|
class="label-text cursor-pointer text-center w-full flex items-center"
|
||||||
@click="$emit('click-formula')"
|
@click="$emit('click-formula')"
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class GeneratePreviewImagesJob
|
||||||
|
include Sidekiq::Job
|
||||||
|
|
||||||
|
sidekiq_options queue: :images
|
||||||
|
|
||||||
|
def perform(params = {})
|
||||||
|
attachment = ActiveStorage::Attachment.find(params['attachment_id'])
|
||||||
|
|
||||||
|
max_page = [attachment.metadata['pdf']['number_of_pages'].to_i - 1,
|
||||||
|
Templates::ProcessDocument::MAX_NUMBER_OF_PAGES_PROCESSED].min
|
||||||
|
|
||||||
|
Templates::ProcessDocument.generate_document_preview_images(attachment, attachment.download, (1..max_page),
|
||||||
|
concurrency: 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -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,7 +39,9 @@ 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'
|
||||||
|
REUSE_SIGNATURE_KEY = 'reuse_signature'
|
||||||
COMBINE_PDF_RESULT_KEY = 'combine_pdf_result_key'
|
COMBINE_PDF_RESULT_KEY = 'combine_pdf_result_key'
|
||||||
|
|
||||||
DEFAULT_VALUES = {
|
DEFAULT_VALUES = {
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ class Submitter < ApplicationRecord
|
|||||||
|
|
||||||
has_many :document_generation_events, dependent: :destroy
|
has_many :document_generation_events, dependent: :destroy
|
||||||
has_many :submission_events, dependent: :destroy
|
has_many :submission_events, dependent: :destroy
|
||||||
|
has_many :start_form_submission_events, -> { where(event_type: :start_form) },
|
||||||
|
class_name: 'SubmissionEvent', dependent: :destroy, inverse_of: :submitter
|
||||||
|
|
||||||
scope :completed, -> { where.not(completed_at: nil) }
|
scope :completed, -> { where.not(completed_at: nil) }
|
||||||
|
|
||||||
@@ -86,11 +88,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('<%= t('use_international_format_1xxx_') %>') : ''" oninput="this.setCustomValidity('')" name="submission[1][submitters][][phone]" autocomplete="off" class="base-input !h-10 mt-1.5 w-full" placeholder="<%= "#{t('phone')} (#{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('#{t('use_international_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>
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
<% can_send_emails = Accounts.can_send_emails?(current_account) %>
|
<% can_send_emails = Accounts.can_send_emails?(current_account) %>
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<%= f.label :send_email, for: uuid = SecureRandom.uuid, class: 'flex items-center cursor-pointer' do %>
|
<%= f.label :send_email, for: uuid = SecureRandom.uuid, class: 'flex items-center cursor-pointer' do %>
|
||||||
<%= f.check_box :send_email, id: uuid, class: 'base-checkbox', disabled: !can_send_emails, checked: can_send_emails %>
|
<%= f.check_box :send_email, id: uuid, class: 'base-checkbox', disabled: !can_send_emails, checked: can_send_emails && !local_assigns.key?(:resend_email) %>
|
||||||
<span class="label"><%= t('send_emails') %></span>
|
<span class="label"><%= local_assigns[:resend_email] ? t('re_send_email') : t('send_email') %></span>
|
||||||
<% end %>
|
<% end %>
|
||||||
<div>
|
<div>
|
||||||
<% if can_send_emails %>
|
<% if can_send_emails %>
|
||||||
<%= render 'email_stats' %>
|
<%= render 'submissions/email_stats' %>
|
||||||
<%= content_for(:edit_button) || capture do %>
|
<%= content_for(:edit_button) || capture do %>
|
||||||
<label>
|
<label>
|
||||||
<%= f.check_box :is_custom_message, onchange: "[this.form.querySelector('#message_field').classList.toggle('hidden', !event.currentTarget.checked)]", checked: false, class: 'hidden peer' %>
|
<%= f.check_box :is_custom_message, onchange: "[this.form.querySelector('#message_field').classList.toggle('hidden', !event.currentTarget.checked)]", checked: false, class: 'hidden peer' %>
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
<div class="form-control space-y-2">
|
<div class="form-control space-y-2">
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= f.label :subject, t('subject'), class: 'label' %>
|
<%= f.label :subject, t('subject'), class: 'label' %>
|
||||||
<%= f.text_field :subject, value: @template.preferences['request_email_subject'].presence || config.value['subject'], required: true, class: '!text-sm base-input w-full', dir: 'auto' %>
|
<%= f.text_field :subject, value: local_assigns[:submitter_email_message]&.subject.presence || template.preferences['request_email_subject'].presence || config.value['subject'], required: true, class: '!text-sm base-input w-full', dir: 'auto' %>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
@@ -49,14 +49,16 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<autoresize-textarea>
|
<autoresize-textarea>
|
||||||
<%= f.text_area :body, value: @template.preferences['request_email_body'].presence || config.value['body'], required: true, class: 'base-textarea w-full', rows: 10, dir: 'auto' %>
|
<%= f.text_area :body, value: local_assigns[:submitter_email_message]&.body.presence || template.preferences['request_email_body'].presence || config.value['body'], required: true, class: 'base-textarea w-full', rows: 10, dir: 'auto' %>
|
||||||
</autoresize-textarea>
|
</autoresize-textarea>
|
||||||
<label for="<%= uuid = SecureRandom.uuid %>" class="flex items-center cursor-pointer">
|
<% unless local_assigns.fetch(:disable_save_as_default_template_option, false) %>
|
||||||
<%= check_box_tag :save_message, id: uuid, class: 'base-checkbox', checked: false %>
|
<label for="<%= uuid = SecureRandom.uuid %>" class="flex items-center cursor-pointer">
|
||||||
<span class="label"><%= t('save_as_default_template_message') %></span>
|
<%= check_box_tag :save_message, id: uuid, class: 'base-checkbox', checked: false %>
|
||||||
</label>
|
<span class="label"><%= t('save_as_default_template_message') %></span>
|
||||||
|
</label>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<%= render 'message_fields' %>
|
<%= render 'submissions/message_fields' %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
||||||
@@ -107,12 +107,21 @@
|
|||||||
<% (@submission.template_submitters || @submission.template.submitters).each_with_index do |item, index| %>
|
<% (@submission.template_submitters || @submission.template.submitters).each_with_index do |item, index| %>
|
||||||
<% submitter = @submission.submitters.find { |e| e.uuid == item['uuid'] } %>
|
<% submitter = @submission.submitters.find { |e| e.uuid == item['uuid'] } %>
|
||||||
<div class="sticky -top-1 bg-base-100 pt-1 -mt-1">
|
<div class="sticky -top-1 bg-base-100 pt-1 -mt-1">
|
||||||
<div class="border border-base-300 rounded-md px-2 py-1 mb-1">
|
<div class="group border border-base-300 rounded-md px-2 py-1 mb-1">
|
||||||
<div class="flex items-center space-x-1">
|
<div class="flex items-center justify-between">
|
||||||
<span class="mx-1 w-3 h-3 rounded-full <%= colors[index] %>"></span>
|
<div class="flex items-center space-x-1">
|
||||||
<span class="text-lg" dir="auto">
|
<span class="mx-1 w-3 h-3 shrink-0 rounded-full <%= colors[index] %>"></span>
|
||||||
<%= (@submission.template_submitters || @submission.template.submitters).find { |e| e['uuid'] == submitter&.uuid }&.dig('name') || "#{(index + 1).ordinalize} Submitter" %>
|
<span class="text-lg" dir="auto">
|
||||||
</span>
|
<%= (@submission.template_submitters || @submission.template.submitters).find { |e| e['uuid'] == submitter&.uuid }&.dig('name') || "#{(index + 1).ordinalize} Submitter" %>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<% if signed_in? && can?(:update, submitter) && !submitter.completed_at? && !submitter.declined_at? && !@submission.archived_at? && !@submission.expired? && !submitter.start_form_submission_events.any? %>
|
||||||
|
<span class="tooltip tooltip-left" data-tip="<%= t('edit') %>">
|
||||||
|
<%= link_to edit_submitter_path(submitter), class: 'shrink-0 inline md:hidden md:group-hover:inline', data: { turbo_frame: 'modal' } do %>
|
||||||
|
<%= svg_icon('pencil', class: 'w-5 h-5') %>
|
||||||
|
<% end %>
|
||||||
|
</span>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% if submitter&.name.present? %>
|
<% if submitter&.name.present? %>
|
||||||
<div class="flex items-center space-x-1 mt-1">
|
<div class="flex items-center space-x-1 mt-1">
|
||||||
@@ -144,7 +153,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 +162,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 +191,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-reuse-signature="<%= configs[:reuse_signature] %>" 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 %>
|
||||||
@@ -21,12 +21,13 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<download-button data-src="<%= submit_form_download_index_path(@submitter.slug) %>" class="btn btn-neutral text-white btn-sm !px-4">
|
<download-button data-src="<%= submit_form_download_index_path(@submitter.slug) %>" class="btn btn-neutral text-white btn-sm !px-4">
|
||||||
<span class="flex items-center justify-center space-x-2" data-target="download-button.defaultButton">
|
<span class="flex items-center justify-center" data-target="download-button.defaultButton">
|
||||||
<span><%= t('download') %></span>
|
<%= svg_icon('download', class: 'w-6 h-6 inline md:hidden') %>
|
||||||
|
<span class="hidden md:inline"><%= t('download') %></span>
|
||||||
</span>
|
</span>
|
||||||
<span class="flex items-center justify-center space-x-2 hidden" data-target="download-button.loadingButton">
|
<span class="flex items-center justify-center space-x-2 hidden" data-target="download-button.loadingButton">
|
||||||
<%= svg_icon('loader', class: 'w-6 h-6 animate-spin') %>
|
<%= svg_icon('loader', class: 'w-6 h-6 animate-spin') %>
|
||||||
<span><%= t('downloading') %></span>
|
<span class="hidden md:inline"><%= t('downloading') %></span>
|
||||||
</span>
|
</span>
|
||||||
</download-button>
|
</download-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -59,7 +60,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= render 'shared/attribution', link_path: '/start', account: @submitter.account %>
|
<%= render 'shared/attribution', link_path: '/start', account: @submitter.account, with_style: false %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="w-full bg-white rounded-2xl border relative" style="height: 300px">
|
<div class="w-full bg-white rounded-2xl border relative" style="height: 300px">
|
||||||
<canvas class="w-full"></canvas>
|
<canvas class="w-full"></canvas>
|
||||||
<button aria-label="<%= t('clear') %>" class="btn btn-ghost btn-sm font-medium top-0 right-0 absolute mt-1 mr-1">
|
<button aria-label="Clear" class="btn btn-ghost btn-sm font-medium top-0 right-0 absolute mt-1 mr-1">
|
||||||
<%= svg_icon('reload', class: 'w-5 h-5') %>
|
<%= svg_icon('reload', class: 'w-5 h-5') %>
|
||||||
<span class="inline"><%= t('clear') %></span>
|
<span class="inline"><%= t('clear') %></span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<%= render 'shared/turbo_modal_large', title: t('edit_recipient') do %>
|
||||||
|
<div class="px-5 mb-5 mt-4">
|
||||||
|
<%= form_for '', url: submitter_path(@submitter), method: :patch, html: { autocomplete: 'off' }, data: { turbo_frame: :_top } do |f| %>
|
||||||
|
<div class="mb-2">
|
||||||
|
<submitter-item class="form-control">
|
||||||
|
<submitters-autocomplete data-field="name">
|
||||||
|
<%= text_field_tag 'submitter[name]', @submitter.name, autocomplete: 'off', class: 'base-input !h-10 w-full', placeholder: "#{t('name')} (#{t('optional')})", dir: 'auto' %>
|
||||||
|
</submitters-autocomplete>
|
||||||
|
<div class="grid md:grid-cols-2 gap-1.5 mt-1.5">
|
||||||
|
<submitters-autocomplete data-field="email">
|
||||||
|
<%= email_field_tag 'submitter[email]', @submitter.email, autocomplete: 'off', class: 'base-input !h-10 mt-1.5 w-full', placeholder: "#{t('email')} (#{t('optional')})" %>
|
||||||
|
</submitters-autocomplete>
|
||||||
|
<submitters-autocomplete data-field="phone">
|
||||||
|
<%= telephone_field_tag 'submitter[phone]', @submitter.phone, autocomplete: 'off', pattern: '^\+[0-9\s\-]+$', class: 'base-input !h-10 mt-1.5 w-full', placeholder: "#{t('phone')} (#{t('optional')})", oninvalid: "this.value ? this.setCustomValidity('#{t('use_international_format_1xxx_')}') : ''", oninput: "this.setCustomValidity('')" %>
|
||||||
|
</submitters-autocomplete>
|
||||||
|
</div>
|
||||||
|
</submitter-item>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<%= render 'submissions/send_email', f:, template: @submitter.template, submitter: @submitter, resend_email: @submitter.sent_at?, submitter_email_message: @submitter_email_message, disable_save_as_default_template_option: true %>
|
||||||
|
<%= render 'submissions/send_sms', f:, resend_sms: @submitter.sent_at? %>
|
||||||
|
</div>
|
||||||
|
<div class="form-control mt-4">
|
||||||
|
<%= f.button button_title(title: t('update_recipient'), disabled_with: t('updating')), class: 'base-button' %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<%= content_for(:modal_extra) %>
|
||||||
|
<% end %>
|
||||||
@@ -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') %>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
<a href="<%= submission_path(submission) %>" class="w-full flex flex-col md:flex-row space-y-4 md:space-y-0 md:justify-between px-5 md:px-6 pb-5 md:items-center pt-5">
|
<div class="w-full flex flex-col md:flex-row space-y-4 md:space-y-0 md:justify-between px-5 md:px-6 pb-5 md:items-center pt-5 relative cursor-pointer">
|
||||||
<% submitters = (submission.template_submitters || submission.template.submitters).filter_map { |item| submission.submitters.find { |e| e.uuid == item['uuid'] } } %>
|
<% submitters = (submission.template_submitters || submission.template.submitters).filter_map { |item| submission.submitters.find { |e| e.uuid == item['uuid'] } } %>
|
||||||
<% is_submission_completed = submitters.all?(&:completed_at?) && submitters.size.positive? %>
|
<% is_submission_completed = submitters.all?(&:completed_at?) && submitters.size.positive? %>
|
||||||
<% if submitters.size == 1 %>
|
<% if submitters.size == 1 %>
|
||||||
@@ -41,24 +41,33 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<% 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) %>">
|
<a href="<%= submission_path(submission) %>" class="flex z-[1]">
|
||||||
<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 tooltip" data-tip="<%= l(submitter.status_event_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %>">
|
||||||
<%= submitter.status %>
|
<%= t(submitter.status) %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
<span class="text-lg break-all flex items-center">
|
<span class="flex items-center z-[1]">
|
||||||
<%= submitter.name || submitter.email || submitter.phone %>
|
<a href="<%= submission_path(submission) %>" class="text-lg break-all peer">
|
||||||
|
<%= submitter.name || submitter.email || submitter.phone %>
|
||||||
|
</a>
|
||||||
|
<% if can?(:update, submitter) && !submitter.start_form_submission_events.any? && !submission.archived_at? && !submission.expired? %>
|
||||||
|
<span class="pl-0.5 tooltip tooltip-top md:opacity-0 md:hover:opacity-100 md:peer-hover:opacity-100" data-tip="<%= t('edit') %>">
|
||||||
|
<%= link_to edit_submitter_path(submitter), class: 'shrink-0', data: { turbo_frame: 'modal' } do %>
|
||||||
|
<%= svg_icon('pencil', class: 'w-5 h-5') %>
|
||||||
|
<% end %>
|
||||||
|
</span>
|
||||||
|
<% end %>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex space-x-2 items-center">
|
<div class="flex space-x-2 items-center z-[1]">
|
||||||
<% if submitter.completed_at? %>
|
<% if submitter.completed_at? %>
|
||||||
<form onsubmit="event.preventDefault()" class="flex-1 md:flex-none">
|
<div class="flex-1 md:flex-none">
|
||||||
<button onclick="event.stopPropagation()" class="w-full md:w-fit">
|
<div 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>
|
||||||
@@ -67,35 +76,39 @@
|
|||||||
<span class="inline"><%= t('download')[..-2] %>...</span>
|
<span class="inline"><%= t('download')[..-2] %>...</span>
|
||||||
</span>
|
</span>
|
||||||
</download-button>
|
</download-button>
|
||||||
</button>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
<% elsif !submission.archived_at? && !template.archived_at? && !submission.expired? && !submitter.declined_at? %>
|
<% elsif !submission.archived_at? && !template.archived_at? && !submission.expired? && !submitter.declined_at? %>
|
||||||
<% if current_user.email == submitter.email %>
|
<% if current_user.email == submitter.email %>
|
||||||
<form data-turbo="false" method="get" action="<%= submit_form_url(slug: submitter.slug) %>" class="flex-1 md:flex-none">
|
<div class="flex-1 md:flex-none md:w-36 flex">
|
||||||
<button onclick="event.stopPropagation()" class="btn btn-sm btn-neutral btn-outline bg-white w-full md:w-36 flex">
|
<a href="<%= submit_form_url(slug: submitter.slug) %>" data-turbo="false" target="_blank" class="btn btn-sm btn-neutral btn-outline bg-white w-full md:w-36 flex z-[1]">
|
||||||
<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>
|
</a>
|
||||||
</form>
|
</div>
|
||||||
<% 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 z-[1]', 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 %>
|
||||||
<div class="flex-1 md:flex-none">
|
<div class="flex-1 md:flex-none z-[1]">
|
||||||
<span class="btn btn-outline btn-sm w-full md:w-24"><%= t('view') %></span>
|
<a href="<%= submission_path(submission) %>" class="btn btn-outline btn-sm w-full md:w-24">
|
||||||
|
<%= t('view') %>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<% if !submission.archived_at? && !template.archived_at? && can?(:destroy, submission) %>
|
<% if !submission.archived_at? && !template.archived_at? && can?(:destroy, submission) %>
|
||||||
<span data-tip="<%= t('archive') %>" class="sm:tooltip tooltip-top">
|
<span data-tip="<%= t('archive') %>" class="sm:tooltip tooltip-top">
|
||||||
<%= button_to button_title(title: nil, disabled_with: t(:archive).first(4), icon: svg_icon('archive', class: 'w-6 h-6')), submission_path(submission), class: 'btn btn-outline btn-sm w-full md:w-fit', form: { class: 'flex' }, title: t('archive'), method: :delete, onclick: 'event.stopPropagation()' %>
|
<%= button_to button_title(title: nil, disabled_with: t(:archive).first(4), icon: svg_icon('archive', class: 'w-6 h-6')), submission_path(submission), class: 'btn btn-outline btn-sm w-full md:w-fit', form: { class: 'flex' }, title: t('archive'), method: :delete %>
|
||||||
</span>
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if local_assigns[:archived] && can?(:destroy, submission) %>
|
<% if local_assigns[:archived] && can?(:destroy, submission) %>
|
||||||
<span data-tip="<%= t('remove') %>" class="sm:tooltip tooltip-top">
|
<span data-tip="<%= t('remove') %>" class="sm:tooltip tooltip-top">
|
||||||
<%= button_to button_title(title: nil, disabled_with: t(:remove).first(3), icon: svg_icon('trash', class: 'w-6 h-6')), submission_path(submission, permanently: true), class: 'btn btn-outline btn-sm w-full md:w-fit', form: { class: 'flex' }, title: t('remove'), method: :delete, data: { turbo_confirm: t('submission_deletion_is_irreversible_and_will_permanently_remove_all_associated_signed_documents_with_it_are_you_sure_') }, onclick: 'event.stopPropagation()' %>
|
<%= button_to button_title(title: nil, disabled_with: t(:remove).first(3), icon: svg_icon('trash', class: 'w-6 h-6')), submission_path(submission, permanently: true), class: 'btn btn-outline btn-sm w-full md:w-fit', form: { class: 'flex' }, title: t('remove'), method: :delete, data: { turbo_confirm: t('submission_deletion_is_irreversible_and_will_permanently_remove_all_associated_signed_documents_with_it_are_you_sure_') } %>
|
||||||
</span>
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
@@ -104,11 +117,11 @@
|
|||||||
<div class="flex flex-col md:flex-row md:items-center gap-3">
|
<div class="flex flex-col md:flex-row md:items-center gap-3">
|
||||||
<% if is_submission_completed %>
|
<% if is_submission_completed %>
|
||||||
<% 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) %>">
|
<a href="<%= submission_path(submission) %>" class="z-[1] 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>
|
</a>
|
||||||
<% elsif submission.expired? %>
|
<% elsif submission.expired? %>
|
||||||
<div class="tooltip flex" data-tip="<%= l(submission.expire_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %>">
|
<div class="tooltip flex" data-tip="<%= l(submission.expire_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %>">
|
||||||
<span class="badge badge-error md:w-32 bg-opacity-50 badge-lg uppercase text-sm font-semibold">
|
<span class="badge badge-error md:w-32 bg-opacity-50 badge-lg uppercase text-sm font-semibold">
|
||||||
@@ -121,44 +134,49 @@
|
|||||||
<div class="relative flex justify-between items-start md:items-center space-x-3">
|
<div class="relative flex justify-between items-start md:items-center space-x-3">
|
||||||
<span class="flex flex-col md:flex-row md:items-center gap-2">
|
<span class="flex flex-col md:flex-row md:items-center gap-2">
|
||||||
<% 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) %>">
|
<a href="<%= submission_path(submission) %>" class="z-[1] 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>
|
</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
<span class="text-lg break-all">
|
<span class="flex items-center z-[1]">
|
||||||
<%= submitter.name || submitter.email || submitter.phone %>
|
<a href="<%= submission_path(submission) %>" class="text-lg break-all peer">
|
||||||
|
<%= submitter.name || submitter.email || submitter.phone %>
|
||||||
|
</a>
|
||||||
|
<% if can?(:update, submitter) && !submitter.start_form_submission_events.any? && !submission.archived_at? && !submission.expired? %>
|
||||||
|
<span class="pl-0.5 tooltip tooltip-top md:opacity-0 md:hover:opacity-100 md:peer-hover:opacity-100" data-tip="<%= t('edit') %>">
|
||||||
|
<%= link_to edit_submitter_path(submitter), class: 'shrink-0', data: { turbo_frame: 'modal' } do %>
|
||||||
|
<%= svg_icon('pencil', class: 'w-5 h-5') %>
|
||||||
|
<% end %>
|
||||||
|
</span>
|
||||||
|
<% end %>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<% if submitter.completed_at? && !is_submission_completed %>
|
<% if submitter.completed_at? && !is_submission_completed %>
|
||||||
<form onsubmit="event.preventDefault()">
|
<download-button data-src="<%= submitter_download_index_path(submitter.slug) %>" class="absolute md:relative top-0 right-0 btn btn-xs btn-neutral text-white md:w-36 z-[1]">
|
||||||
<button onclick="event.stopPropagation()">
|
<span class="flex items-center justify-center space-x-1 md:space-x-2" data-target="download-button.defaultButton">
|
||||||
<download-button data-src="<%= submitter_download_index_path(submitter.slug) %>" class="absolute md:relative top-0 right-0 btn btn-xs btn-neutral text-white md:w-36">
|
<%= svg_icon('download', class: 'w-4 h-4 stroke-2') %>
|
||||||
<span class="flex items-center justify-center space-x-1 md:space-x-2" data-target="download-button.defaultButton">
|
<span class="inline"><%= t('download') %></span>
|
||||||
<%= svg_icon('download', class: 'w-4 h-4 stroke-2') %>
|
</span>
|
||||||
<span class="inline"><%= t('download') %></span>
|
<span class="flex items-center justify-center space-x-1 md:space-x-2 hidden" data-target="download-button.loadingButton">
|
||||||
</span>
|
<%= svg_icon('loader', class: 'w-4 h-4 animate-spin') %>
|
||||||
<span class="flex items-center justify-center space-x-1 md:space-x-2 hidden" data-target="download-button.loadingButton">
|
<span class="inline"><%= t('download')[..-2] %>...</span>
|
||||||
<%= svg_icon('loader', class: 'w-4 h-4 animate-spin') %>
|
</span>
|
||||||
<span class="inline"><%= t('download')[..-2] %>...</span>
|
</download-button>
|
||||||
</span>
|
|
||||||
</download-button>
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
<% elsif !template.archived_at? && !submission.archived_at? && !is_submission_completed && !submission.expired? && !submitter.declined_at? %>
|
<% elsif !template.archived_at? && !submission.archived_at? && !is_submission_completed && !submission.expired? && !submitter.declined_at? %>
|
||||||
<div class="relative flex items-center space-x-3">
|
<div class="relative flex items-center space-x-3">
|
||||||
<% if current_user.email == submitter.email %>
|
<% if current_user.email == submitter.email %>
|
||||||
<form data-turbo="false" method="get" action="<%= submit_form_url(slug: submitter.slug) %>">
|
<a href="<%= submit_form_url(slug: submitter.slug) %>" data-turbo="false" target="_blank" class="absolute md:relative top-0 right-0 btn btn-xs btn-outline btn-neutral bg-white w-28 md:w-36 z-[1]">
|
||||||
<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">
|
<% if t('sign_now').length < 12 %>
|
||||||
<%= svg_icon('writing_sign', class: 'w-4 h-4 stroke-2') %>
|
<%= svg_icon('writing_sign', class: 'w-4 h-4 stroke-2') %>
|
||||||
<span class="inline shrink-0"><%= t('sign_now') %></span>
|
<% end %>
|
||||||
</span>
|
<span class="inline shrink-0"><%= t('sign_now') %></span>
|
||||||
</button>
|
</span>
|
||||||
</form>
|
</a>
|
||||||
<% 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 z-[1]', 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 %>
|
||||||
@@ -167,40 +185,41 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex space-x-1 md:space-x-2 items-center">
|
<div class="flex space-x-1 md:space-x-2 items-center z-[1]">
|
||||||
<% if is_submission_completed %>
|
<% if is_submission_completed %>
|
||||||
<% 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">
|
<div class="w-full md:w-fit">
|
||||||
<button onclick="event.stopPropagation()">
|
<download-button data-src="<%= submitter_download_index_path(latest_submitter.slug) %>" class="btn btn-sm btn-neutral text-white w-full md:w-36 z-[1]">
|
||||||
<download-button data-src="<%= submitter_download_index_path(latest_submitter.slug) %>" class="btn btn-sm btn-neutral text-white 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>
|
</span>
|
||||||
</span>
|
<span class="flex items-center justify-center space-x-1 md:space-x-2 hidden" data-target="download-button.loadingButton">
|
||||||
<span class="flex items-center justify-center space-x-1 md:space-x-2 hidden" data-target="download-button.loadingButton">
|
<%= svg_icon('loader', class: 'w-5 h-5 animate-spin') %>
|
||||||
<%= svg_icon('loader', class: 'w-5 h-5 animate-spin') %>
|
<span class="inline"><%= t('download')[..-2] %>...</span>
|
||||||
<span class="inline"><%= t('download')[..-2] %>...</span>
|
</span>
|
||||||
</span>
|
</download-button>
|
||||||
</download-button>
|
</div>
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<div class="flex-1 md:flex-none">
|
<div class="flex-1 md:flex-none z-[1]">
|
||||||
<span class="btn btn-outline btn-sm w-full md:w-24"><%= t('view') %></span>
|
<a href="<%= submission_path(submission) %>" class="btn btn-outline btn-sm w-full md:w-24">
|
||||||
|
<%= t('view') %>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<% if !submission.archived_at? && !template.archived_at? %>
|
<% if !submission.archived_at? && !template.archived_at? %>
|
||||||
<span data-tip="<%= t('archive') %>" class="sm:tooltip tooltip-top">
|
<span data-tip="<%= t('archive') %>" class="sm:tooltip tooltip-top">
|
||||||
<%= button_to button_title(title: nil, disabled_with: t(:archive).first(4), icon: svg_icon('archive', class: 'w-6 h-6')), submission_path(submission), class: 'btn btn-outline btn-sm w-full md:w-fit', form: { class: 'flex' }, title: t('archive'), method: :delete, onclick: 'event.stopPropagation()' %>
|
<%= button_to button_title(title: nil, disabled_with: t(:archive).first(4), icon: svg_icon('archive', class: 'w-6 h-6')), submission_path(submission), class: 'btn btn-outline btn-sm w-full md:w-fit', form: { class: 'flex' }, title: t('archive'), method: :delete %>
|
||||||
</span>
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if local_assigns[:archived] && can?(:destroy, submission) %>
|
<% if local_assigns[:archived] && can?(:destroy, submission) %>
|
||||||
<span data-tip="<%= t('remove') %>" class="sm:tooltip tooltip-top">
|
<span data-tip="<%= t('remove') %>" class="sm:tooltip tooltip-top">
|
||||||
<%= button_to button_title(title: nil, disabled_with: t(:remove).first(3), icon: svg_icon('trash', class: 'w-6 h-6')), submission_path(submission, permanently: true), class: 'btn btn-outline btn-sm w-full md:w-fit', form: { class: 'flex' }, title: t('remove'), method: :delete, data: { turbo_confirm: t('submission_deletion_is_irreversible_and_will_permanently_remove_all_associated_signed_documents_with_it_are_you_sure_') }, onclick: 'event.stopPropagation()' %>
|
<%= button_to button_title(title: nil, disabled_with: t(:remove).first(3), icon: svg_icon('trash', class: 'w-6 h-6')), submission_path(submission, permanently: true), class: 'btn btn-outline btn-sm w-full md:w-fit', form: { class: 'flex' }, title: t('remove'), method: :delete, data: { turbo_confirm: t('submission_deletion_is_irreversible_and_will_permanently_remove_all_associated_signed_documents_with_it_are_you_sure_') } %>
|
||||||
</span>
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</a>
|
<a href="<%= submission_path(submission) %>" class="top-0 bottom-0 left-0 right-0 absolute"></a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -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
|
||||||
|
|||||||
Loaded 100 of 123 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user