mirror of
https://github.com/docusealco/docuseal.git
synced 2026-08-07 23:32:07 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b035f80b3 | |||
| c717293306 | |||
| b3f3cf2aa6 | |||
| 7406334f77 | |||
| 3e1350a221 | |||
| 961e0a1c89 | |||
| 2ce9bbecb9 | |||
| 704da3a2ec | |||
| 2f530ccfca | |||
| e6c20f5ff6 | |||
| d267978437 | |||
| e9d728fa4a | |||
| 3c60fb4ee6 | |||
| f1e494b669 | |||
| f7a8e4102b | |||
| 311c2b0e34 | |||
| 5dd59f4f7c | |||
| 571f5d8221 | |||
| 136b0eb5ed |
+11
-11
@@ -165,7 +165,7 @@ GEM
|
||||
railties (>= 4.1.0)
|
||||
responders
|
||||
warden (~> 1.2.3)
|
||||
devise-two-factor (5.0.0)
|
||||
devise-two-factor (6.0.0)
|
||||
activesupport (~> 7.0)
|
||||
devise (~> 4.0)
|
||||
railties (~> 7.0)
|
||||
@@ -269,13 +269,13 @@ GEM
|
||||
openssl (>= 2.2.1)
|
||||
htmlentities (4.3.4)
|
||||
httpclient (2.8.3)
|
||||
i18n (1.14.5)
|
||||
i18n (1.14.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
image_processing (1.12.2)
|
||||
mini_magick (>= 4.9.5, < 5)
|
||||
ruby-vips (>= 2.0.17, < 3)
|
||||
io-console (0.7.2)
|
||||
irb (1.13.1)
|
||||
irb (1.14.0)
|
||||
rdoc (>= 4.0.0)
|
||||
reline (>= 0.4.2)
|
||||
jmespath (1.6.2)
|
||||
@@ -312,7 +312,7 @@ GEM
|
||||
mini_magick (4.12.0)
|
||||
mini_mime (1.1.5)
|
||||
mini_portile2 (2.8.7)
|
||||
minitest (5.24.1)
|
||||
minitest (5.25.1)
|
||||
msgpack (1.7.2)
|
||||
multi_json (1.15.0)
|
||||
multipart-post (2.4.0)
|
||||
@@ -329,7 +329,7 @@ GEM
|
||||
timeout
|
||||
net-smtp (0.4.0)
|
||||
net-protocol
|
||||
nio4r (2.7.1)
|
||||
nio4r (2.7.3)
|
||||
nokogiri (1.16.7)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
@@ -367,7 +367,7 @@ GEM
|
||||
psych (5.1.2)
|
||||
stringio
|
||||
public_suffix (5.0.5)
|
||||
puma (6.4.2)
|
||||
puma (6.4.3)
|
||||
nio4r (~> 2.0)
|
||||
racc (1.8.1)
|
||||
rack (3.1.7)
|
||||
@@ -418,12 +418,12 @@ GEM
|
||||
zeitwerk (~> 2.6)
|
||||
rainbow (3.1.1)
|
||||
rake (13.2.1)
|
||||
rdoc (6.6.3.1)
|
||||
rdoc (6.7.0)
|
||||
psych (>= 4.0.0)
|
||||
redis-client (0.22.2)
|
||||
connection_pool
|
||||
regexp_parser (2.9.2)
|
||||
reline (0.5.7)
|
||||
reline (0.5.10)
|
||||
io-console (~> 0.5)
|
||||
representable (3.2.0)
|
||||
declarative (< 0.1.0)
|
||||
@@ -516,11 +516,11 @@ GEM
|
||||
smart_properties (1.17.0)
|
||||
sqlite3 (1.7.3)
|
||||
mini_portile2 (~> 2.8.0)
|
||||
stringio (3.1.0)
|
||||
stringio (3.1.1)
|
||||
strip_attributes (1.13.0)
|
||||
activemodel (>= 3.0, < 8.0)
|
||||
strscan (3.1.0)
|
||||
thor (1.3.1)
|
||||
thor (1.3.2)
|
||||
timeout (0.4.1)
|
||||
trailblazer-option (0.1.2)
|
||||
turbo-rails (2.0.5)
|
||||
@@ -555,7 +555,7 @@ GEM
|
||||
websocket-extensions (0.1.5)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
zeitwerk (2.6.14)
|
||||
zeitwerk (2.6.18)
|
||||
|
||||
PLATFORMS
|
||||
aarch64-linux
|
||||
|
||||
@@ -24,7 +24,7 @@ class AccountsController < ApplicationController
|
||||
@encrypted_config.assign_attributes(app_url_params)
|
||||
|
||||
unless URI.parse(@encrypted_config.value.to_s).class.in?([URI::HTTP, URI::HTTPS])
|
||||
@encrypted_config.errors.add(:value, 'should be a valid URL')
|
||||
@encrypted_config.errors.add(:value, I18n.t('should_be_a_valid_url'))
|
||||
|
||||
return render :show, status: :unprocessable_entity
|
||||
end
|
||||
@@ -33,7 +33,7 @@ class AccountsController < ApplicationController
|
||||
|
||||
Docuseal.refresh_default_url_options!
|
||||
|
||||
redirect_to settings_account_path, notice: 'Account information has been updated'
|
||||
redirect_to settings_account_path, notice: I18n.t('account_information_has_been_updated')
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
render :show, status: :unprocessable_entity
|
||||
end
|
||||
@@ -43,11 +43,12 @@ class AccountsController < ApplicationController
|
||||
|
||||
true_user.update!(locked_at: Time.current)
|
||||
|
||||
# rubocop:disable Layout/LineLength
|
||||
render turbo_stream: turbo_stream.replace(
|
||||
:account_delete_button,
|
||||
html: helpers.tag.p('Your account removal request will be processed within 2 weeks. ' \
|
||||
'Please contact us if you want to keep your account.')
|
||||
html: helpers.tag.p(I18n.t('your_account_removal_request_will_be_processed_within_2_weeks_please_contact_us_if_you_want_to_keep_your_account'))
|
||||
)
|
||||
# rubocop:enable Layout/LineLength
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -97,7 +97,7 @@ module Api
|
||||
:name,
|
||||
:external_id,
|
||||
{
|
||||
submitters: [%i[name uuid is_requester invite_by_uuid invite_by_uuid linked_to_uuid email]],
|
||||
submitters: [%i[name uuid is_requester invite_by_uuid linked_to_uuid email]],
|
||||
fields: [[:uuid, :submitter_uuid, :name, :type,
|
||||
:required, :readonly, :default_value,
|
||||
:title, :description,
|
||||
|
||||
@@ -12,6 +12,6 @@ class ApiSettingsController < ApplicationController
|
||||
|
||||
current_user.access_token.save!
|
||||
|
||||
redirect_back(fallback_location: settings_api_index_path, notice: 'API token as been updated.')
|
||||
redirect_back(fallback_location: settings_api_index_path, notice: I18n.t('api_token_has_been_updated'))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -79,7 +79,8 @@ class ApplicationController < ActionController::Base
|
||||
redirect_to setup_index_path unless User.exists?
|
||||
end
|
||||
|
||||
def button_title(title: 'Submit', disabled_with: 'Submitting', title_class: '', icon: nil, icon_disabled: nil)
|
||||
def button_title(title: I18n.t('submit'), disabled_with: I18n.t('submitting'), title_class: '', icon: nil,
|
||||
icon_disabled: nil)
|
||||
render_to_string(partial: 'shared/button_title',
|
||||
locals: { title:, disabled_with:, title_class:, icon:, icon_disabled: })
|
||||
end
|
||||
|
||||
@@ -33,7 +33,7 @@ class DashboardController < ApplicationController
|
||||
account_id: current_user.account_id,
|
||||
key: AccountConfig::FORCE_MFA)
|
||||
|
||||
redirect_to mfa_setup_path, notice: 'Setup 2FA to continue'
|
||||
redirect_to mfa_setup_path, notice: I18n.t('setup_2fa_to_continue')
|
||||
end
|
||||
|
||||
def maybe_render_landing
|
||||
|
||||
@@ -11,7 +11,7 @@ class EmailSmtpSettingsController < ApplicationController
|
||||
if @encrypted_config.update(email_configs)
|
||||
SettingsMailer.smtp_successful_setup(@encrypted_config.value['from_email']).deliver_now!
|
||||
|
||||
redirect_to settings_email_index_path, notice: 'Changes have been saved'
|
||||
redirect_to settings_email_index_path, notice: I18n.t('changes_have_been_saved')
|
||||
else
|
||||
render :index, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
@@ -48,7 +48,7 @@ class EsignSettingsController < ApplicationController
|
||||
if (@encrypted_config.value && @encrypted_config.value['custom']&.any? { |e| e['name'] == @cert_record.name }) ||
|
||||
@cert_record.name == DEFAULT_CERT_NAME
|
||||
|
||||
@cert_record.errors.add(:name, 'already exists')
|
||||
@cert_record.errors.add(:name, I18n.t('already_exists'))
|
||||
|
||||
return render turbo_stream: turbo_stream.replace(:modal, template: 'esign_settings/new'),
|
||||
status: :unprocessable_entity
|
||||
@@ -56,7 +56,7 @@ class EsignSettingsController < ApplicationController
|
||||
|
||||
save_new_cert!(@encrypted_config, @cert_record)
|
||||
|
||||
redirect_to settings_esign_path, notice: 'Certificate has been successfully added!'
|
||||
redirect_to settings_esign_path, notice: I18n.t('certificate_has_been_successfully_added_')
|
||||
rescue OpenSSL::PKCS12::PKCS12Error => e
|
||||
Rollbar.error(e) if defined?(Rollbar)
|
||||
|
||||
@@ -73,7 +73,7 @@ class EsignSettingsController < ApplicationController
|
||||
|
||||
@encrypted_config.save!
|
||||
|
||||
redirect_to settings_esign_path, notice: 'Default certificate has been selected'
|
||||
redirect_to settings_esign_path, notice: I18n.t('default_certificate_has_been_selected')
|
||||
end
|
||||
|
||||
def destroy
|
||||
@@ -81,7 +81,7 @@ class EsignSettingsController < ApplicationController
|
||||
|
||||
@encrypted_config.save!
|
||||
|
||||
redirect_to settings_esign_path, notice: 'Certificate has been removed'
|
||||
redirect_to settings_esign_path, notice: I18m.t('certificate_has_been_removed')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -18,11 +18,11 @@ class MfaSetupController < ApplicationController
|
||||
current_user.otp_required_for_login = true
|
||||
current_user.save!
|
||||
|
||||
redirect_to settings_profile_index_path, notice: '2FA has been configured'
|
||||
redirect_to settings_profile_index_path, notice: I18n.t('2fa_has_been_configured')
|
||||
else
|
||||
@provision_url = current_user.otp_provisioning_uri(current_user.email, issuer: Docuseal.product_name)
|
||||
|
||||
@error_message = 'Code is invalid'
|
||||
@error_message = I18n.t('code_is_invalid')
|
||||
|
||||
render turbo_stream: turbo_stream.replace(:mfa_form, partial: 'mfa_setup/form'), status: :unprocessable_entity
|
||||
end
|
||||
@@ -32,9 +32,9 @@ class MfaSetupController < ApplicationController
|
||||
if current_user.validate_and_consume_otp!(params[:otp_attempt])
|
||||
current_user.update!(otp_required_for_login: false, otp_secret: nil)
|
||||
|
||||
redirect_to settings_profile_index_path, notice: '2FA has been removed'
|
||||
redirect_to settings_profile_index_path, notice: I18n.t('2fa_has_been_removed')
|
||||
else
|
||||
@error_message = 'Code is invalid'
|
||||
@error_message = I18n.t('code_is_invalid')
|
||||
|
||||
render turbo_stream: turbo_stream.replace(:modal, template: 'mfa_setup/edit'), status: :unprocessable_entity
|
||||
end
|
||||
@@ -43,7 +43,7 @@ class MfaSetupController < ApplicationController
|
||||
private
|
||||
|
||||
def set_provision_url
|
||||
return redirect_to root_path, alert: '2FA has been set up already' if current_user.otp_required_for_login
|
||||
return redirect_to root_path, alert: I18n.t('2fa_has_been_set_up_already') if current_user.otp_required_for_login
|
||||
|
||||
current_user.otp_secret ||= User.generate_otp_secret
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ class NotificationsSettingsController < ApplicationController
|
||||
|
||||
def create
|
||||
if @account_config.value.present? ? @account_config.save : @account_config.delete
|
||||
redirect_back fallback_location: settings_notifications_path, notice: 'Changes have been saved'
|
||||
redirect_back fallback_location: settings_notifications_path, notice: I18n.t('changes_have_been_saved')
|
||||
else
|
||||
redirect_back fallback_location: settings_notifications_path, alert: 'Unable to save'
|
||||
redirect_back fallback_location: settings_notifications_path, alert: I18n.t('unable_to_save')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class PersonalizationSettingsController < ApplicationController
|
||||
@account_config.save!
|
||||
end
|
||||
|
||||
redirect_back(fallback_location: settings_personalization_path, notice: 'Settings have been saved.')
|
||||
redirect_back(fallback_location: settings_personalization_path, notice: I18n.t('settings_have_been_saved'))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -9,7 +9,7 @@ class ProfileController < ApplicationController
|
||||
|
||||
def update_contact
|
||||
if current_user.update(contact_params)
|
||||
redirect_to settings_profile_index_path, notice: 'Contact information has been updated'
|
||||
redirect_to settings_profile_index_path, notice: I18n.t('contact_information_has_been_update')
|
||||
else
|
||||
render :index, status: :unprocessable_entity
|
||||
end
|
||||
@@ -18,7 +18,7 @@ class ProfileController < ApplicationController
|
||||
def update_password
|
||||
if current_user.update(password_params)
|
||||
bypass_sign_in(current_user)
|
||||
redirect_to settings_profile_index_path, notice: 'Password has been changed'
|
||||
redirect_to settings_profile_index_path, notice: I18n.t('password_has_been_changed')
|
||||
else
|
||||
render :index, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
@@ -7,6 +7,8 @@ class SendSubmissionEmailController < ApplicationController
|
||||
skip_before_action :verify_authenticity_token
|
||||
skip_authorization_check
|
||||
|
||||
SEND_DURATION = 30.minutes
|
||||
|
||||
def success; end
|
||||
|
||||
def create
|
||||
@@ -23,7 +25,10 @@ class SendSubmissionEmailController < ApplicationController
|
||||
|
||||
RateLimit.call("send-email-#{@submitter.id}", limit: 2, ttl: 5.minutes)
|
||||
|
||||
SubmitterMailer.documents_copy_email(@submitter, sig: true).deliver_later!
|
||||
unless EmailEvent.exists?(tag: :submitter_documents_copy, email: @submitter.email, emailable: @submitter,
|
||||
event_type: :send, created_at: SEND_DURATION.ago..Time.current)
|
||||
SubmitterMailer.documents_copy_email(@submitter, sig: true).deliver_later!
|
||||
end
|
||||
|
||||
respond_to do |f|
|
||||
f.html { redirect_to success_send_submission_email_index_path }
|
||||
|
||||
@@ -12,7 +12,7 @@ class SessionsController < Devise::SessionsController
|
||||
Rollbar.warning('Sign in new user') if defined?(Rollbar)
|
||||
|
||||
return redirect_to new_registration_path(sign_up: true, user: sign_in_params.slice(:email)),
|
||||
notice: 'Create a new account'
|
||||
notice: I18n.t('create_a_new_account')
|
||||
end
|
||||
|
||||
if User.exists?(email:, otp_required_for_login: true) && sign_in_params[:otp_attempt].blank?
|
||||
|
||||
@@ -21,7 +21,7 @@ class SetupController < ApplicationController
|
||||
@encrypted_config = EncryptedConfig.new(encrypted_config_params)
|
||||
|
||||
unless URI.parse(encrypted_config_params[:value].to_s).class.in?([URI::HTTP, URI::HTTPS])
|
||||
@encrypted_config.errors.add(:value, 'should be a valid URL')
|
||||
@encrypted_config.errors.add(:value, I18n.t('should_be_a_valid_url'))
|
||||
|
||||
return render :index, status: :unprocessable_entity
|
||||
end
|
||||
@@ -66,10 +66,10 @@ class SetupController < ApplicationController
|
||||
end
|
||||
|
||||
def redirect_to_root_if_signed
|
||||
redirect_to root_path, notice: 'You are already signed in'
|
||||
redirect_to root_path, notice: I18n.t('you_are_already_signed_in')
|
||||
end
|
||||
|
||||
def ensure_first_user_not_created!
|
||||
redirect_to new_user_session_path, notice: 'Please sign in.' if User.exists?
|
||||
redirect_to new_user_session_path, notice: I18n.t('please_sign_in') if User.exists?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -24,7 +24,7 @@ class StartFormController < ApplicationController
|
||||
redirect_to start_form_completed_path(@template.slug, email: submitter_params[:email])
|
||||
else
|
||||
if filter_undefined_submitters(@template).size > 1 && @submitter.new_record?
|
||||
@error_message = 'Not found'
|
||||
@error_message = I18n.t('not_found')
|
||||
|
||||
return render :show
|
||||
end
|
||||
|
||||
@@ -11,7 +11,7 @@ class StorageSettingsController < ApplicationController
|
||||
if @encrypted_config.update(storage_configs)
|
||||
LoadActiveStorageConfigs.reload
|
||||
|
||||
redirect_to settings_storage_index_path, notice: 'Changes have been saved'
|
||||
redirect_to settings_storage_index_path, notice: I18n.t('changes_have_been_saved')
|
||||
else
|
||||
render :index, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
@@ -49,7 +49,7 @@ class SubmissionsController < ApplicationController
|
||||
|
||||
Submissions.send_signature_requests(submissions)
|
||||
|
||||
redirect_to template_path(@template), notice: 'New recipients have been added'
|
||||
redirect_to template_path(@template), notice: I18n.t('new_recipients_have_been_added')
|
||||
end
|
||||
|
||||
def destroy
|
||||
@@ -57,13 +57,13 @@ class SubmissionsController < ApplicationController
|
||||
if params[:permanently].present?
|
||||
@submission.destroy!
|
||||
|
||||
'Submission has been removed'
|
||||
I18n.t('submission_has_been_removed')
|
||||
else
|
||||
@submission.update!(archived_at: Time.current)
|
||||
|
||||
SendSubmissionArchivedWebhookRequestJob.perform_async('submission_id' => @submission.id)
|
||||
|
||||
'Submission has been archived'
|
||||
I18n.t('submission_has_been_archived')
|
||||
end
|
||||
|
||||
redirect_back(fallback_location: template_path(@submission.template), notice:)
|
||||
|
||||
@@ -19,7 +19,7 @@ class SubmissionsPreviewController < ApplicationController
|
||||
@submission ||= Submission.find_by!(slug: params[:slug])
|
||||
|
||||
if !@submission.submitters.all?(&:completed_at?) && current_user.blank?
|
||||
raise ActionController::RoutingError, 'Not Found'
|
||||
raise ActionController::RoutingError, I18n.t('not_found')
|
||||
end
|
||||
|
||||
if !submission_valid_ttl?(@submission) && !signature_valid
|
||||
|
||||
@@ -46,18 +46,21 @@ class SubmitFormController < ApplicationController
|
||||
submitter = Submitter.find_by!(slug: params[:slug])
|
||||
|
||||
if submitter.completed_at?
|
||||
return render json: { error: 'Form has been completed already.' }, status: :unprocessable_entity
|
||||
return render json: { error: I18n.t('form_has_been_completed_already') }, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
if submitter.template.archived_at? || submitter.submission.archived_at?
|
||||
return render json: { error: 'Form has been archived.' }, status: :unprocessable_entity
|
||||
return render json: { error: I18n.t('form_has_been_archived') }, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
if submitter.submission.expired?
|
||||
return render json: { error: 'Form has been expired.' }, status: :unprocessable_entity
|
||||
return render json: { error: I18n.t('form_has_been_expired') }, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
return render json: { error: 'Form has been declined.' }, status: :unprocessable_entity if submitter.declined_at?
|
||||
if submitter.declined_at?
|
||||
return render json: { error: I18n.t('form_has_been_declined') },
|
||||
status: :unprocessable_entity
|
||||
end
|
||||
|
||||
Submitters::SubmitValues.call(submitter, params, request)
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ class SubmittersSendEmailController < ApplicationController
|
||||
Rollbar.warning("Already sent: #{@submitter.id}") if defined?(Rollbar)
|
||||
|
||||
return redirect_back(fallback_location: submission_path(@submitter.submission),
|
||||
alert: 'Email has been sent already.')
|
||||
alert: I18n.t('email_has_been_sent_already'))
|
||||
end
|
||||
|
||||
SendSubmitterInvitationEmailJob.perform_async('submitter_id' => @submitter.id)
|
||||
@@ -18,6 +18,6 @@ class SubmittersSendEmailController < ApplicationController
|
||||
@submitter.sent_at ||= Time.current
|
||||
@submitter.save!
|
||||
|
||||
redirect_back(fallback_location: submission_path(@submitter.submission), notice: 'Email has been sent')
|
||||
redirect_back(fallback_location: submission_path(@submitter.submission), notice: I18n.t('email_has_been_sent'))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ class TemplateDocumentsController < ApplicationController
|
||||
|
||||
def create
|
||||
if params[:blobs].blank? && params[:files].blank?
|
||||
return render json: { error: 'File is missing' }, status: :unprocessable_entity
|
||||
return render json: { error: I18n.t('file_is_missing') }, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
old_fields_hash = @template.fields.hash
|
||||
@@ -28,6 +28,6 @@ class TemplateDocumentsController < ApplicationController
|
||||
)
|
||||
}
|
||||
rescue Templates::CreateAttachments::PdfEncrypted
|
||||
render json: { error: 'PDF encrypted' }, status: :unprocessable_entity
|
||||
render json: { error: 'PDF encrypted', status: 'pdf_encrypted' }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,9 +15,9 @@ class TemplateFoldersController < ApplicationController
|
||||
def update
|
||||
if @template_folder != current_account.default_template_folder &&
|
||||
@template_folder.update(template_folder_params)
|
||||
redirect_to folder_path(@template_folder), notice: 'Folder name has been updated'
|
||||
redirect_to folder_path(@template_folder), notice: I18n.t('folder_name_has_been_updated')
|
||||
else
|
||||
redirect_to folder_path(@template_folder), alert: 'Unable to rename folder'
|
||||
redirect_to folder_path(@template_folder), alert: I18n.t('unable_to_rename_folder')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ class TemplatesController < ApplicationController
|
||||
end
|
||||
|
||||
def new
|
||||
@template.name = "#{@base_template.name} (Clone)" if @base_template
|
||||
@template.name = "#{@base_template.name} (#{I18n.t('clone')})" if @base_template
|
||||
end
|
||||
|
||||
def edit
|
||||
@@ -87,11 +87,11 @@ class TemplatesController < ApplicationController
|
||||
if params[:permanently].present?
|
||||
@template.destroy!
|
||||
|
||||
'Template has been removed.'
|
||||
I18n.t('template_has_been_removed')
|
||||
else
|
||||
@template.update!(archived_at: Time.current)
|
||||
|
||||
'Template has been archived.'
|
||||
I18n.t('template_has_been_archived')
|
||||
end
|
||||
|
||||
redirect_back(fallback_location: root_path, notice:)
|
||||
@@ -123,7 +123,7 @@ class TemplatesController < ApplicationController
|
||||
if template.account == current_account
|
||||
redirect_to(edit_template_path(@template))
|
||||
else
|
||||
redirect_back(fallback_location: root_path, notice: 'Template has been cloned')
|
||||
redirect_back(fallback_location: root_path, notice: I18n.t('template_has_been_cloned'))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ class TemplatesFoldersController < ApplicationController
|
||||
@template.folder = TemplateFolders.find_or_create_by_name(current_user, params[:name])
|
||||
|
||||
if @template.save
|
||||
redirect_back(fallback_location: template_path(@template), notice: 'Document template has been moved')
|
||||
redirect_back(fallback_location: template_path(@template), notice: I18n.t('document_template_has_been_moved'))
|
||||
else
|
||||
redirect_back(fallback_location: template_path(@template), notice: 'Unable to move template into folder')
|
||||
redirect_back(fallback_location: template_path(@template), notice: I18n.t('unable_to_move_template_into_folder'))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -6,6 +6,6 @@ class TemplatesRestoreController < ApplicationController
|
||||
def create
|
||||
@template.update!(archived_at: nil)
|
||||
|
||||
redirect_to template_path(@template), notice: 'Template has been unarchived'
|
||||
redirect_to template_path(@template), notice: I18n.t('template_has_been_unarchived')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -33,7 +33,7 @@ class TemplatesUploadsController < ApplicationController
|
||||
|
||||
raise if Rails.env.local?
|
||||
|
||||
redirect_to root_path, alert: 'Unable to upload file'
|
||||
redirect_to root_path, alert: I18n.t('unable_to_update_file')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -14,12 +14,12 @@ class TimestampServerController < ApplicationController
|
||||
test_timeserver_url(@encrypted_config.value) if @encrypted_config.value.present?
|
||||
|
||||
if @encrypted_config.value.present? ? @encrypted_config.save : @encrypted_config.delete
|
||||
redirect_back fallback_location: settings_notifications_path, notice: 'Changes have been saved'
|
||||
redirect_back fallback_location: settings_notifications_path, notice: I18n.t('changes_have_been_saved')
|
||||
else
|
||||
redirect_back fallback_location: settings_notifications_path, alert: 'Unable to save'
|
||||
redirect_back fallback_location: settings_notifications_path, alert: I18n.t('unable_to_save')
|
||||
end
|
||||
rescue SocketError, TimestampError, OpenSSL::Timestamp::TimestampError
|
||||
redirect_back fallback_location: settings_notifications_path, alert: 'Invalid Timeserver'
|
||||
redirect_back fallback_location: settings_notifications_path, alert: t('invalid_timeserver')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -9,7 +9,7 @@ class UserInitialsController < ApplicationController
|
||||
def update
|
||||
file = params[:file]
|
||||
|
||||
return redirect_to settings_profile_index_path, notice: 'Unable to save initials' if file.blank?
|
||||
return redirect_to settings_profile_index_path, notice: I18n.t('unable_to_save_initials') if file.blank?
|
||||
|
||||
blob = ActiveStorage::Blob.create_and_upload!(io: file.open,
|
||||
filename: file.original_filename,
|
||||
@@ -22,16 +22,16 @@ class UserInitialsController < ApplicationController
|
||||
)
|
||||
|
||||
if @user_config.update(value: attachment.uuid)
|
||||
redirect_to settings_profile_index_path, notice: 'Initials has been saved'
|
||||
redirect_to settings_profile_index_path, notice: I18n.t('initials_has_been_saved')
|
||||
else
|
||||
redirect_to settings_profile_index_path, notice: 'Unable to save initials'
|
||||
redirect_to settings_profile_index_path, notice: I18n.t('unable_to_save_initials')
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@user_config.destroy
|
||||
|
||||
redirect_to settings_profile_index_path, notice: 'Initials has been removed'
|
||||
redirect_to settings_profile_index_path, notice: I18n.t('initials_has_been_removed')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -9,7 +9,7 @@ class UserSignaturesController < ApplicationController
|
||||
def update
|
||||
file = params[:file]
|
||||
|
||||
return redirect_to settings_profile_index_path, notice: 'Unable to save signature' if file.blank?
|
||||
return redirect_to settings_profile_index_path, notice: I18n.t('Unable to save signature') if file.blank?
|
||||
|
||||
blob = ActiveStorage::Blob.create_and_upload!(io: file.open,
|
||||
filename: file.original_filename,
|
||||
@@ -22,16 +22,16 @@ class UserSignaturesController < ApplicationController
|
||||
)
|
||||
|
||||
if @user_config.update(value: attachment.uuid)
|
||||
redirect_to settings_profile_index_path, notice: 'Signature has been saved'
|
||||
redirect_to settings_profile_index_path, notice: I18n.t('signature_has_been_saved')
|
||||
else
|
||||
redirect_to settings_profile_index_path, notice: 'Unable to save signature'
|
||||
redirect_to settings_profile_index_path, notice: I18n.t('Unable to save signature')
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@user_config.destroy
|
||||
|
||||
redirect_to settings_profile_index_path, notice: 'Signature has been removed'
|
||||
redirect_to settings_profile_index_path, notice: I18n.t('signature_has_been_removed')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -35,14 +35,14 @@ class UsersController < ApplicationController
|
||||
if @user.save
|
||||
UserMailer.invitation_email(@user).deliver_later!
|
||||
|
||||
redirect_back fallback_location: settings_users_path, notice: 'User has been invited'
|
||||
redirect_back fallback_location: settings_users_path, notice: I18n.t('user_has_been_invited')
|
||||
else
|
||||
render turbo_stream: turbo_stream.replace(:modal, template: 'users/new'), status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
return redirect_to settings_users_path, notice: 'Unable to update user.' if Docuseal.demo?
|
||||
return redirect_to settings_users_path, notice: I18n.t('unable_to_update_user') if Docuseal.demo?
|
||||
|
||||
attrs = user_params.compact_blank.merge(user_params.slice(:archived_at))
|
||||
attrs.delete(:role) if !role_valid?(attrs[:role]) || current_user == @user
|
||||
@@ -56,7 +56,7 @@ class UsersController < ApplicationController
|
||||
end
|
||||
|
||||
if @user.update(attrs)
|
||||
redirect_back fallback_location: settings_users_path, notice: 'User has been updated'
|
||||
redirect_back fallback_location: settings_users_path, notice: I18n.t('user_has_been_updated')
|
||||
else
|
||||
render turbo_stream: turbo_stream.replace(:modal, template: 'users/edit'), status: :unprocessable_entity
|
||||
end
|
||||
@@ -64,12 +64,12 @@ class UsersController < ApplicationController
|
||||
|
||||
def destroy
|
||||
if Docuseal.demo? || @user.id == current_user.id
|
||||
return redirect_to settings_users_path, notice: 'Unable to remove user'
|
||||
return redirect_to settings_users_path, notice: I18n.t('unable_to_remove_user')
|
||||
end
|
||||
|
||||
@user.update!(archived_at: Time.current)
|
||||
|
||||
redirect_back fallback_location: settings_users_path, notice: 'User has been removed'
|
||||
redirect_back fallback_location: settings_users_path, notice: I18n.t('user_has_been_removed')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -14,6 +14,6 @@ class VerifyPdfSignatureController < ApplicationController
|
||||
render turbo_stream: turbo_stream.replace('result', partial: 'result',
|
||||
locals: { pdfs:, files: params[:files], trusted_certs: })
|
||||
rescue HexaPDF::MalformedPDFError
|
||||
render turbo_stream: turbo_stream.replace('result', html: helpers.tag.div('Invalid PDF', id: 'result'))
|
||||
render turbo_stream: turbo_stream.replace('result', html: helpers.tag.div(I18n.t('invalid_pdf'), id: 'result'))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,7 +13,7 @@ class WebhookSecretController < ApplicationController
|
||||
|
||||
@encrypted_config.value.present? ? @encrypted_config.save! : @encrypted_config.delete
|
||||
|
||||
redirect_back(fallback_location: settings_webhooks_path, notice: 'Webhook Secret has been saved.')
|
||||
redirect_back(fallback_location: settings_webhooks_path, notice: I18n.t('webhook_secret_has_been_saved'))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -11,7 +11,7 @@ class WebhookSettingsController < ApplicationController
|
||||
|
||||
@encrypted_config.value.present? ? @encrypted_config.save! : @encrypted_config.delete
|
||||
|
||||
redirect_back(fallback_location: settings_webhooks_path, notice: 'Webhook URL has been saved.')
|
||||
redirect_back(fallback_location: settings_webhooks_path, notice: I18n.t('webhook_url_has_been_saved'))
|
||||
end
|
||||
|
||||
def update
|
||||
@@ -20,7 +20,7 @@ class WebhookSettingsController < ApplicationController
|
||||
SendFormCompletedWebhookRequestJob.perform_async({ 'submitter_id' => submitter.id,
|
||||
'encrypted_config_id' => @encrypted_config.id })
|
||||
|
||||
redirect_back(fallback_location: settings_webhooks_path, notice: 'Webhook request has been sent.')
|
||||
redirect_back(fallback_location: settings_webhooks_path, notice: I18n.t('webhook_request_has_been_sent'))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
class="field-area flex absolute lg:text-base -outline-offset-1"
|
||||
dir="auto"
|
||||
:style="computedStyle"
|
||||
:class="{ 'text-[1.6vw] lg:text-base': !textOverflowChars, 'text-[1.0vw] lg:text-xs': textOverflowChars, 'cursor-default': !submittable, 'border border-red-100 bg-red-100 cursor-pointer': submittable, 'border border-red-100': !isActive && submittable, 'bg-opacity-80': !isActive && !isValueSet && submittable, 'field-area-active outline-red-500 outline-dashed outline-2 z-10': isActive && submittable, 'bg-opacity-40': (isActive || isValueSet) && submittable }"
|
||||
:class="{ 'font-serif': field.preferences?.font === 'Times', 'text-[1.6vw] lg:text-base': !textOverflowChars, 'text-[1.0vw] lg:text-xs': textOverflowChars, 'cursor-default': !submittable, 'border border-red-100 bg-red-100 cursor-pointer': submittable, 'border border-red-100': !isActive && submittable, 'bg-opacity-80': !isActive && !isValueSet && submittable, 'field-area-active outline-red-500 outline-dashed outline-2 z-10': isActive && submittable, 'bg-opacity-40': (isActive || isValueSet) && submittable }"
|
||||
>
|
||||
<div
|
||||
v-if="(!withFieldPlaceholder || !field.name || field.type === 'cells') && !isActive && !isValueSet && field.type !== 'checkbox' && submittable && !area.option_uuid"
|
||||
@@ -29,12 +29,12 @@
|
||||
{{ optionValue(option) }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ field.name || fieldNames[field.type] }}
|
||||
{{ field.title || field.name || fieldNames[field.type] }}
|
||||
<template v-if="field.type === 'checkbox' && !field.name">
|
||||
{{ fieldIndex + 1 }}
|
||||
</template>
|
||||
<template v-else-if="!field.required && field.type !== 'checkbox'">
|
||||
(optional)
|
||||
({{ t('optional') }})
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
@@ -132,10 +132,18 @@ export default {
|
||||
this.scrollInContainer(areaRef.$el)
|
||||
} else {
|
||||
const targetRect = areaRef.$refs.scrollToElem.getBoundingClientRect()
|
||||
const root = this.$root.$el?.parentNode?.classList?.contains('ds') ? this.$root.$el : document.body
|
||||
const rootRect = root.getBoundingClientRect()
|
||||
const scrollEl = this.scrollEl || window
|
||||
|
||||
let rootRect = {}
|
||||
|
||||
if (this.scrollEl === document.documentElement) {
|
||||
rootRect = this.scrollEl.getBoundingClientRect()
|
||||
} else {
|
||||
const root = this.$root.$el?.parentNode?.classList?.contains('ds') ? this.$root.$el : document.body
|
||||
|
||||
rootRect = root.getBoundingClientRect()
|
||||
}
|
||||
|
||||
scrollEl.scrollTo({ top: targetRect.top - rootRect.top, behavior: 'smooth' })
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
:height="30"
|
||||
/>
|
||||
<span>
|
||||
{{ completedMessage.title || t('form_has_been_completed') }}
|
||||
{{ completedMessage.title || (hasSignatureFields ? (hasMultipleDocuments ? t('documents_have_been_signed') : t('document_has_been_signed')) : t('form_has_been_completed')) }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
@@ -88,7 +88,7 @@
|
||||
v-if="attribution"
|
||||
class="text-center mt-4"
|
||||
>
|
||||
{{ t('signed_with') }}
|
||||
{{ t('powered_by') }}
|
||||
<a
|
||||
href="https://www.docuseal.co/start"
|
||||
target="_blank"
|
||||
@@ -129,6 +129,16 @@ export default {
|
||||
required: false,
|
||||
default: true
|
||||
},
|
||||
hasSignatureFields: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
hasMultipleDocuments: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
withDownloadButton: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
|
||||
@@ -38,8 +38,11 @@
|
||||
<template v-else-if="alwaysMinimize">
|
||||
{{ t('next') }}
|
||||
</template>
|
||||
<template v-else-if="isShowContinue">
|
||||
{{ t('continue') }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ t('submit_form') }}
|
||||
{{ t('start_now') }}
|
||||
</template>
|
||||
<IconArrowsDiagonal
|
||||
class="absolute right-0 mr-4"
|
||||
@@ -59,7 +62,7 @@
|
||||
id="minimize_form_button"
|
||||
class="absolute right-0 mr-2 mt-2 top-0 hidden md:block"
|
||||
:title="t('minimize')"
|
||||
@click.prevent="isFormVisible = false"
|
||||
@click.prevent="minimizeForm"
|
||||
>
|
||||
<IconArrowsDiagonalMinimize2
|
||||
:width="20"
|
||||
@@ -201,7 +204,7 @@
|
||||
<span
|
||||
@click="scrollIntoField(currentField)"
|
||||
>
|
||||
{{ t('complete_hightlighted_checkboxes_and_click') }} <span class="font-semibold">{{ stepFields.length === currentStep + 1 ? t('submit') : t('next') }}</span>.
|
||||
{{ t('complete_hightlighted_checkboxes_and_click') }} <span class="font-semibold">{{ submitButtonText }}</span>.
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
@@ -265,7 +268,7 @@
|
||||
>
|
||||
<template v-if="isAnonymousChecboxes || !showFieldNames">
|
||||
<span class="text-xl">
|
||||
{{ t('complete_hightlighted_checkboxes_and_click') }} <span class="font-semibold">{{ stepFields.length === currentStep + 1 ? t('submit') : t('next') }}</span>.
|
||||
{{ t('complete_hightlighted_checkboxes_and_click') }} <span class="font-semibold">{{ submitButtonText }}</span>.
|
||||
</span>
|
||||
<input
|
||||
v-for="field in currentStepFields"
|
||||
@@ -340,7 +343,7 @@
|
||||
:remember-signature="rememberSignature"
|
||||
:attachments-index="attachmentsIndex"
|
||||
:require-signing-reason="requireSigningReason"
|
||||
:button-text="buttonText"
|
||||
:button-text="submitButtonText"
|
||||
:dry-run="dryRun"
|
||||
:with-disclosure="withDisclosure"
|
||||
:with-qr-button="withQrButton"
|
||||
@@ -349,7 +352,7 @@
|
||||
@update:reason="values[currentField.preferences?.reason_field_uuid] = $event"
|
||||
@attached="attachments.push($event)"
|
||||
@start="scrollIntoField(currentField)"
|
||||
@minimize="isFormVisible = false"
|
||||
@minimize="minimizeForm"
|
||||
/>
|
||||
<InitialsStep
|
||||
v-else-if="currentField.type === 'initials'"
|
||||
@@ -365,7 +368,7 @@
|
||||
@attached="attachments.push($event)"
|
||||
@start="scrollIntoField(currentField)"
|
||||
@focus="scrollIntoField(currentField)"
|
||||
@minimize="isFormVisible = false"
|
||||
@minimize="minimizeForm"
|
||||
/>
|
||||
<AttachmentStep
|
||||
v-else-if="currentField.type === 'file'"
|
||||
@@ -421,7 +424,7 @@
|
||||
class="mr-1 animate-spin"
|
||||
/>
|
||||
<span>
|
||||
{{ buttonText }}
|
||||
{{ submitButtonText }}
|
||||
</span><span
|
||||
v-if="isSubmitting"
|
||||
class="w-6 flex justify-start mr-1"
|
||||
@@ -449,6 +452,8 @@
|
||||
v-else
|
||||
:is-demo="isDemo"
|
||||
:attribution="attribution"
|
||||
:has-signature-fields="stepFields.some((fields) => fields.some((f) => ['signature', 'initials'].includes(f.type)))"
|
||||
:has-multiple-documents="hasMultipleDocuments"
|
||||
:completed-button="completedRedirectUrl ? {} : completedButton"
|
||||
:completed-message="completedRedirectUrl ? {} : completedMessage"
|
||||
:with-send-copy-button="withSendCopyButton && !completedRedirectUrl"
|
||||
@@ -759,6 +764,7 @@ export default {
|
||||
isFormVisible: this.expand !== false,
|
||||
showFillAllRequiredFields: false,
|
||||
currentStep: 0,
|
||||
isShowContinue: false,
|
||||
enableScrollIntoField: true,
|
||||
phoneVerifiedValues: {},
|
||||
orientation: screen?.orientation?.type,
|
||||
@@ -771,9 +777,15 @@ export default {
|
||||
isMobile () {
|
||||
return /android|iphone|ipad/i.test(navigator.userAgent)
|
||||
},
|
||||
buttonText () {
|
||||
if (this.alwaysMinimize || this.stepFields.length === this.currentStep + 1) {
|
||||
submitButtonText () {
|
||||
if (this.alwaysMinimize) {
|
||||
return this.t('submit')
|
||||
} else if (this.stepFields.length === this.currentStep + 1) {
|
||||
if (this.currentField.type === 'signature') {
|
||||
return this.t('sign_and_complete')
|
||||
} else {
|
||||
return this.t('complete')
|
||||
}
|
||||
} else {
|
||||
return this.t('next')
|
||||
}
|
||||
@@ -781,6 +793,18 @@ export default {
|
||||
alwaysMinimize () {
|
||||
return this.minimize || (this.orientation?.includes('landscape') && this.isMobile && parseInt(window.innerHeight) < 550)
|
||||
},
|
||||
hasMultipleDocuments () {
|
||||
return Object.keys(
|
||||
this.stepFields.reduce((acc, fields) => {
|
||||
fields.forEach((f) => {
|
||||
f.areas?.forEach((a) => {
|
||||
acc[a.attachment_uuid] = 1
|
||||
})
|
||||
})
|
||||
return acc
|
||||
}, {})
|
||||
).filter(Boolean).length > 1
|
||||
},
|
||||
currentStepFields () {
|
||||
return this.stepFields[this.currentStep] || []
|
||||
},
|
||||
@@ -905,11 +929,11 @@ export default {
|
||||
}
|
||||
|
||||
if (document.body?.clientWidth >= 768 && this.expand !== true && ['signature', 'initials', 'file', 'image'].includes(this.currentField?.type)) {
|
||||
this.isFormVisible = false
|
||||
this.minimizeForm()
|
||||
}
|
||||
|
||||
if (this.alwaysMinimize) {
|
||||
this.isFormVisible = false
|
||||
this.minimizeForm()
|
||||
}
|
||||
|
||||
if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) {
|
||||
@@ -1167,7 +1191,7 @@ export default {
|
||||
|
||||
if (nextStep) {
|
||||
if (this.alwaysMinimize) {
|
||||
this.isFormVisible = false
|
||||
this.minimizeForm()
|
||||
}
|
||||
|
||||
this.goToStep(this.stepFields.indexOf(nextStep), this.autoscrollFields)
|
||||
@@ -1195,10 +1219,14 @@ export default {
|
||||
this.isSubmitting = false
|
||||
})
|
||||
},
|
||||
minimizeForm () {
|
||||
this.isFormVisible = false
|
||||
this.isShowContinue = true
|
||||
},
|
||||
async performComplete (resp) {
|
||||
this.isCompleted = true
|
||||
|
||||
if (resp) {
|
||||
if (resp?.text) {
|
||||
const respData = await resp.text()
|
||||
|
||||
if (respData) {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
const en = {
|
||||
complete: 'Complete',
|
||||
sign_and_complete: 'Sign and Complete',
|
||||
text: 'Text',
|
||||
by_clicking_you_agree_to_the: 'By clicking "{button}", you agree to the',
|
||||
electronic_signature_disclosure: 'Electronic Signature Disclosure',
|
||||
@@ -38,7 +40,8 @@ const en = {
|
||||
minimize: 'Minimize',
|
||||
payment: 'Payment',
|
||||
phone: 'Phone',
|
||||
submit_form: 'Submit Form',
|
||||
start_now: 'Start Now',
|
||||
continue: 'Continue',
|
||||
sign_now: 'Sign Now',
|
||||
type_here_: 'Type here...',
|
||||
optional: 'optional',
|
||||
@@ -59,8 +62,10 @@ const en = {
|
||||
type_signature_here: 'Type signature here',
|
||||
type_initial_here: 'Type initials here',
|
||||
form_has_been_completed: 'Form has been completed!',
|
||||
document_has_been_signed: 'Document has been signed!',
|
||||
documents_have_been_signed: 'Documents have been signed!',
|
||||
create_a_free_account: 'Create a Free Account',
|
||||
signed_with: 'Signed with',
|
||||
powered_by: 'Powered by',
|
||||
please_check_the_box_to_continue: 'Please check the box to continue',
|
||||
open_source_documents_software: 'open source documents software',
|
||||
verified_phone_number: 'Verify Phone Number',
|
||||
@@ -87,6 +92,8 @@ const en = {
|
||||
}
|
||||
|
||||
const es = {
|
||||
complete: 'Completar',
|
||||
sign_and_complete: 'Firmar y Completar',
|
||||
invite: 'Invitar',
|
||||
email: 'Correo electrónico',
|
||||
approved: 'Aprobado',
|
||||
@@ -126,7 +133,8 @@ const es = {
|
||||
payment: 'Pago',
|
||||
phone: 'Teléfono',
|
||||
take_photo: 'Tomar foto',
|
||||
submit_form: 'Enviar Formulario',
|
||||
start_now: 'Comenzar ahora',
|
||||
continue: 'Continuar',
|
||||
sign_now: 'Firmar ahora',
|
||||
type_here_: 'Escribe aquí...',
|
||||
optional: 'opcional',
|
||||
@@ -146,8 +154,10 @@ const es = {
|
||||
type_signature_here: 'Escribe la firma aquí',
|
||||
type_initial_here: 'Escribe las iniciales aquí',
|
||||
form_has_been_completed: '¡El formulario ha sido completado!',
|
||||
document_has_been_signed: '¡El documento ha sido firmado!',
|
||||
documents_have_been_signed: '¡Los documentos han sido firmados!',
|
||||
create_a_free_account: 'Crear una Cuenta Gratuita',
|
||||
signed_with: 'Firmado con',
|
||||
powered_by: 'Desarrollado por',
|
||||
please_check_the_box_to_continue: 'Por favor marque la casilla para continuar',
|
||||
open_source_documents_software: 'software de documentos de código abierto',
|
||||
verified_phone_number: 'Verificar número de teléfono',
|
||||
@@ -174,6 +184,8 @@ const es = {
|
||||
}
|
||||
|
||||
const it = {
|
||||
complete: 'Completa',
|
||||
sign_and_complete: 'Firma e Completa',
|
||||
invite: 'Invita',
|
||||
email: 'Email',
|
||||
approved: 'Approvato',
|
||||
@@ -212,7 +224,8 @@ const it = {
|
||||
payment: 'Pagamento',
|
||||
number_phone_is_invalid: '{number} telefono non è valido',
|
||||
phone: 'Telefono',
|
||||
submit_form: 'Invia Modulo',
|
||||
start_now: 'Inizia ora',
|
||||
continue: 'Continua',
|
||||
sign_now: 'Firma ora',
|
||||
type_here_: 'Digita qui...',
|
||||
optional: 'opzionale',
|
||||
@@ -233,8 +246,10 @@ const it = {
|
||||
type_signature_here: 'Scrivi la firma qui',
|
||||
type_initial_here: 'Scrivi le iniziali qui',
|
||||
form_has_been_completed: 'Il modulo è stato completato!',
|
||||
document_has_been_signed: 'Il documento è stato firmato!',
|
||||
documents_have_been_signed: 'I documenti sono stati firmati!',
|
||||
create_a_free_account: 'Crea un Account Gratuito',
|
||||
signed_with: 'Firmato con',
|
||||
powered_by: 'Desarrollado por',
|
||||
please_check_the_box_to_continue: 'Si prega di spuntare la casella per continuare',
|
||||
open_source_documents_software: 'software di documenti open source',
|
||||
verified_phone_number: 'Verifica numero di telefono',
|
||||
@@ -261,6 +276,8 @@ const it = {
|
||||
}
|
||||
|
||||
const de = {
|
||||
complete: 'Abschließen',
|
||||
sign_and_complete: 'Signieren und Abschließen',
|
||||
invite: 'Einladen',
|
||||
email: 'E-Mail',
|
||||
approved: 'Genehmigt',
|
||||
@@ -299,7 +316,8 @@ const de = {
|
||||
payment: 'Zahlung',
|
||||
number_phone_is_invalid: '{number} Telefonnummer ist ungültig',
|
||||
phone: 'Telefon',
|
||||
submit_form: 'Formular absenden',
|
||||
start_now: 'Jetzt starten',
|
||||
continue: 'Fortsetzen',
|
||||
sign_now: 'Jetzt unterschreiben',
|
||||
type_here_: 'Hier eingeben...',
|
||||
optional: 'optional',
|
||||
@@ -320,8 +338,10 @@ const de = {
|
||||
type_signature_here: 'Unterschrift hier eingeben',
|
||||
type_initial_here: 'Initialen hier eingeben',
|
||||
form_has_been_completed: 'Formular wurde ausgefüllt!',
|
||||
document_has_been_signed: 'Dokument wurde unterschrieben!',
|
||||
documents_have_been_signed: 'Dokumente wurden unterschrieben!',
|
||||
create_a_free_account: 'Kostenloses Konto erstellen',
|
||||
signed_with: 'Unterschrieben mit',
|
||||
powered_by: 'Bereitgestellt von',
|
||||
please_check_the_box_to_continue: 'Bitte setzen Sie das Häkchen, um fortzufahren',
|
||||
open_source_documents_software: 'Open-Source-Dokumentensoftware',
|
||||
verified_phone_number: 'Telefonnummer überprüfen',
|
||||
@@ -348,6 +368,8 @@ const de = {
|
||||
}
|
||||
|
||||
const fr = {
|
||||
complete: 'Terminer',
|
||||
sign_and_complete: 'Signer et Terminer',
|
||||
invite: 'Inviter',
|
||||
email: 'Courriel',
|
||||
approved: 'Approuvé',
|
||||
@@ -386,7 +408,8 @@ const fr = {
|
||||
payment: 'Paiement',
|
||||
number_phone_is_invalid: '{number} téléphone est invalide',
|
||||
phone: 'Téléphone',
|
||||
submit_form: 'Envoyer le Formulaire',
|
||||
start_now: 'Commencer maintenant',
|
||||
continue: 'Continuer',
|
||||
sign_now: 'Signer maintenant',
|
||||
type_here_: 'Tapez ici...',
|
||||
optional: 'facultatif',
|
||||
@@ -407,8 +430,10 @@ const fr = {
|
||||
type_signature_here: 'Tapez la signature ici',
|
||||
type_initial_here: 'Tapez les initiales ici',
|
||||
form_has_been_completed: 'Le formulaire a été complété !',
|
||||
document_has_been_signed: 'Le document a été signé!',
|
||||
documents_have_been_signed: 'Les documents ont été signés!',
|
||||
create_a_free_account: 'Créer un Compte Gratuit',
|
||||
signed_with: 'Signé avec',
|
||||
powered_by: 'Propulsé par',
|
||||
please_check_the_box_to_continue: 'Veuillez cocher la case pour continuer',
|
||||
open_source_documents_software: 'logiciel de documents open source',
|
||||
verified_phone_number: 'Vérifier le numéro de téléphone',
|
||||
@@ -435,6 +460,8 @@ const fr = {
|
||||
}
|
||||
|
||||
const pl = {
|
||||
complete: 'Zakończ',
|
||||
sign_and_complete: 'Podpisz i zakończ',
|
||||
invite: 'Zaproś',
|
||||
email: 'E-mail',
|
||||
approved: 'Zaakceptowany',
|
||||
@@ -473,7 +500,8 @@ const pl = {
|
||||
payment: 'Płatność',
|
||||
number_phone_is_invalid: '{number} telefon jest nieprawidłowy',
|
||||
phone: 'Telefon',
|
||||
submit_form: 'Wyślij Formularz',
|
||||
start_now: 'Zacznij teraz',
|
||||
continue: 'Kontynuuj',
|
||||
sign_now: 'Podpisz teraz',
|
||||
type_here_: 'Wpisz tutaj...',
|
||||
optional: 'opcjonalny',
|
||||
@@ -494,8 +522,10 @@ const pl = {
|
||||
type_signature_here: 'Wpisz podpis tutaj',
|
||||
type_initial_here: 'Wpisz inicjały tutaj',
|
||||
form_has_been_completed: 'Formularz został wypełniony!',
|
||||
document_has_been_signed: 'Dokument został podpisany!',
|
||||
documents_have_been_signed: 'Dokumenty zostały podpisane!',
|
||||
create_a_free_account: 'Utwórz darmowe konto',
|
||||
signed_with: 'Podpisane za pomocą',
|
||||
powered_by: 'Napędzany przez',
|
||||
please_check_the_box_to_continue: 'Proszę zaznaczyć pole, aby kontynuować',
|
||||
open_source_documents_software: 'oprogramowanie do dokumentów open source',
|
||||
verified_phone_number: 'Zweryfikuj numer telefonu',
|
||||
@@ -522,6 +552,8 @@ const pl = {
|
||||
}
|
||||
|
||||
const uk = {
|
||||
complete: 'Завершити',
|
||||
sign_and_complete: 'Підписати і завершити',
|
||||
invite: 'Запросити',
|
||||
email: 'Електронна пошта',
|
||||
approved: 'Затверджено',
|
||||
@@ -560,7 +592,8 @@ const uk = {
|
||||
payment: 'Платіж',
|
||||
number_phone_is_invalid: '{number} телефон недійсний',
|
||||
phone: 'Телефон',
|
||||
submit_form: 'Надіслати Форму',
|
||||
start_now: 'Почати зараз',
|
||||
continue: 'Продовжити',
|
||||
sign_now: 'Підписати зараз',
|
||||
type_here_: 'Введіть тут',
|
||||
optional: 'необов’язково',
|
||||
@@ -581,8 +614,10 @@ const uk = {
|
||||
type_signature_here: 'Введіть підпис тут',
|
||||
type_initial_here: 'Введіть ініціали тут',
|
||||
form_has_been_completed: 'Форму заповнено!',
|
||||
document_has_been_signed: 'Документ був підписаний!',
|
||||
documents_have_been_signed: 'Документи були підписані!',
|
||||
create_a_free_account: 'Створити безкоштовний обліковий запис',
|
||||
signed_with: 'Підписано за допомогою',
|
||||
powered_by: 'Працює на базі',
|
||||
please_check_the_box_to_continue: 'Будь ласка, позначте прапорець, щоб продовжити',
|
||||
open_source_documents_software: 'відкритий програмний засіб для документів',
|
||||
verified_phone_number: 'Підтвердіть номер телефону',
|
||||
@@ -609,6 +644,8 @@ const uk = {
|
||||
}
|
||||
|
||||
const cs = {
|
||||
complete: 'Dokončit',
|
||||
sign_and_complete: 'Podepsat a dokončit',
|
||||
invite: 'Pozvat',
|
||||
email: 'E-mail',
|
||||
approved: 'Schváleno',
|
||||
@@ -647,7 +684,8 @@ const cs = {
|
||||
payment: 'Platba',
|
||||
phone: 'Telefon',
|
||||
number_phone_is_invalid: '{number} telefon je neplatný',
|
||||
submit_form: 'Odeslat formulář',
|
||||
start_now: 'Začít nyní',
|
||||
continue: 'Pokračovat',
|
||||
sign_now: 'Podepsat nyní',
|
||||
type_here_: 'Zadejte zde',
|
||||
optional: 'volitelné',
|
||||
@@ -668,8 +706,10 @@ const cs = {
|
||||
type_signature_here: 'Sem zadejte podpis',
|
||||
type_initial_here: 'Sem zadejte iniciály',
|
||||
form_has_been_completed: 'Formulář byl dokončen!',
|
||||
document_has_been_signed: 'Dokument byl podepsán!',
|
||||
documents_have_been_signed: 'Dokumenty byly podepsány!',
|
||||
create_a_free_account: 'Vytvořit bezplatný účet',
|
||||
signed_with: 'Podepsáno pomocí',
|
||||
powered_by: 'Poháněno',
|
||||
please_check_the_box_to_continue: 'Prosím, zaškrtněte políčko pro pokračování',
|
||||
open_source_documents_software: 'open source software pro dokumenty',
|
||||
verified_phone_number: 'Ověřte telefonní číslo',
|
||||
@@ -696,6 +736,8 @@ const cs = {
|
||||
}
|
||||
|
||||
const pt = {
|
||||
complete: 'Completar',
|
||||
sign_and_complete: 'Assinar e Completar',
|
||||
invite: 'Convidar',
|
||||
email: 'E-mail',
|
||||
approved: 'Aprovado',
|
||||
@@ -734,7 +776,8 @@ const pt = {
|
||||
payment: 'Pagamento',
|
||||
number_phone_is_invalid: '{number} telefone é inválido',
|
||||
phone: 'Telefone',
|
||||
submit_form: 'Enviar Formulário',
|
||||
start_now: 'Começar agora',
|
||||
continue: 'Continuar',
|
||||
sign_now: 'Assinar agora',
|
||||
type_here_: 'Digite aqui',
|
||||
optional: 'opcional',
|
||||
@@ -755,8 +798,10 @@ const pt = {
|
||||
type_signature_here: 'Digite a assinatura aqui',
|
||||
type_initial_here: 'Digite as iniciais aqui',
|
||||
form_has_been_completed: 'O formulário foi concluído!',
|
||||
document_has_been_signed: 'O documento foi assinado!',
|
||||
documents_have_been_signed: 'Os documentos foram assinados!',
|
||||
create_a_free_account: 'Criar uma Conta Gratuita',
|
||||
signed_with: 'Assinado com',
|
||||
powered_by: 'Desenvolvido por',
|
||||
please_check_the_box_to_continue: 'Por favor, marque a caixa para continuar',
|
||||
open_source_documents_software: 'software de documentos de código aberto',
|
||||
verified_phone_number: 'Verificar Número de Telefone',
|
||||
@@ -783,6 +828,8 @@ const pt = {
|
||||
}
|
||||
|
||||
const he = {
|
||||
complete: 'השלם',
|
||||
sign_and_complete: 'חתום והשלם',
|
||||
invite: 'הזמן',
|
||||
email: 'דוא"ל',
|
||||
approved: 'מאושר',
|
||||
@@ -821,7 +868,8 @@ const he = {
|
||||
payment: 'תשלום',
|
||||
phone: 'טלפון',
|
||||
number_phone_is_invalid: '{number} טלפון אינו חוקי',
|
||||
submit_form: 'שלח טופס',
|
||||
start_now: 'התחל עכשיו',
|
||||
continue: 'המשך',
|
||||
sign_now: 'חתום כעת',
|
||||
type_here_: 'הקלד כאן',
|
||||
optional: 'אופציונלי',
|
||||
@@ -843,8 +891,10 @@ const he = {
|
||||
type_signature_here: 'הקלד חתימה כאן',
|
||||
type_initial_here: 'הקלד ציוני ראשי תיבות כאן',
|
||||
form_has_been_completed: 'הטופס הושלם',
|
||||
document_has_been_signed: 'המסמך נחתם!',
|
||||
documents_have_been_signed: 'המסמכים נחתמו!',
|
||||
create_a_free_account: 'צור חשבון חינם',
|
||||
signed_with: 'חתום באמצעות',
|
||||
powered_by: 'מופעל על ידי',
|
||||
please_check_the_box_to_continue: 'אנא סמן את התיבה כדי להמשיך',
|
||||
open_source_documents_software: 'תוכנה פתוחה למסמכים',
|
||||
verified_phone_number: 'אימות מספר טלפון',
|
||||
@@ -871,6 +921,8 @@ const he = {
|
||||
}
|
||||
|
||||
const nl = {
|
||||
complete: 'Voltooien',
|
||||
sign_and_complete: 'Ondertekenen en voltooien',
|
||||
invite: 'Uitnodigen',
|
||||
email: 'E-mail',
|
||||
approved: 'Goedgekeurd',
|
||||
@@ -910,7 +962,8 @@ const nl = {
|
||||
payment: 'Betaling',
|
||||
phone: 'Telefoon',
|
||||
number_phone_is_invalid: '{number} telefoon is ongeldig',
|
||||
submit_form: 'Formulier verzenden',
|
||||
start_now: 'Nu beginnen',
|
||||
continue: 'Doorgaan',
|
||||
sign_now: 'Nu ondertekenen',
|
||||
type_here_: 'Typ hier...',
|
||||
optional: 'Optioneel',
|
||||
@@ -931,8 +984,10 @@ const nl = {
|
||||
type_signature_here: 'Typ hier uw handtekening',
|
||||
type_initial_here: 'Typ hier uw initialen',
|
||||
form_has_been_completed: 'Formulier is voltooid!',
|
||||
document_has_been_signed: 'Document is ondertekend!',
|
||||
documents_have_been_signed: 'De documenten zijn ondertekend!',
|
||||
create_a_free_account: 'Maak een gratis account aan',
|
||||
signed_with: 'Ondertekend met',
|
||||
powered_by: 'Aangedreven door',
|
||||
please_check_the_box_to_continue: 'Vink het vakje aan om door te gaan',
|
||||
open_source_documents_software: 'Open source documenten software',
|
||||
verified_phone_number: 'Geverifieerd telefoonnummer',
|
||||
@@ -959,6 +1014,8 @@ const nl = {
|
||||
}
|
||||
|
||||
const ar = {
|
||||
complete: 'اكتمال',
|
||||
sign_and_complete: 'التوقيع والاكتمال',
|
||||
invite: 'دعوة',
|
||||
email: 'البريد الإلكتروني',
|
||||
approved: 'موافق عليه',
|
||||
@@ -997,7 +1054,8 @@ const ar = {
|
||||
payment: 'الدفع',
|
||||
phone: 'هاتف',
|
||||
number_phone_is_invalid: '{number} هاتف غير صالح',
|
||||
submit_form: 'إرسال النموذج',
|
||||
start_now: 'ابدأ الآن',
|
||||
continue: 'متابعة',
|
||||
sign_now: 'وقع الآن',
|
||||
type_here_: 'اكتب هنا',
|
||||
optional: 'اختياري',
|
||||
@@ -1018,8 +1076,10 @@ const ar = {
|
||||
type_signature_here: 'اكتب التوقيع هنا',
|
||||
type_initial_here: 'اكتب الاختصارات هنا',
|
||||
form_has_been_completed: 'تم إكمال النموذج!',
|
||||
document_has_been_signed: 'تم توقيع الوثيقة!',
|
||||
documents_have_been_signed: 'تم توقيع الوثائق!',
|
||||
create_a_free_account: 'إنشاء حساب مجاني',
|
||||
signed_with: 'تم التوقيع بواسطة',
|
||||
powered_by: 'مدعوم من',
|
||||
please_check_the_box_to_continue: 'الرجاء التحقق من الخانة للمتابعة',
|
||||
open_source_documents_software: 'برنامج وثائق مفتوح المصدر',
|
||||
verified_phone_number: 'تحقق من رقم الهاتف',
|
||||
@@ -1046,6 +1106,8 @@ const ar = {
|
||||
}
|
||||
|
||||
const ko = {
|
||||
complete: '완료',
|
||||
sign_and_complete: '서명하고 완료하기',
|
||||
invite: '초대하기',
|
||||
email: '이메일',
|
||||
approved: '승인됨',
|
||||
@@ -1083,7 +1145,8 @@ const ko = {
|
||||
payment: '결제',
|
||||
phone: '전화',
|
||||
number_phone_is_invalid: '{number} 전화번호가 유효하지 않습니다',
|
||||
submit_form: '양식 제출',
|
||||
start_now: '지금 시작하기',
|
||||
continue: '계속하다',
|
||||
sign_now: '지금 서명',
|
||||
type_here_: '여기에 입력...',
|
||||
optional: '선택 사항',
|
||||
@@ -1104,8 +1167,10 @@ const ko = {
|
||||
type_signature_here: '여기에 서명 입력',
|
||||
type_initial_here: '여기에 이니셜 입력',
|
||||
form_has_been_completed: '양식이 완료되었습니다!',
|
||||
document_has_been_signed: '문서가 서명되었습니다!',
|
||||
documents_have_been_signed: '문서가 서명되었습니다!',
|
||||
create_a_free_account: '무료 계정 생성',
|
||||
signed_with: '다음으로 서명:',
|
||||
powered_by: '구동',
|
||||
please_check_the_box_to_continue: '계속하려면 확인란을 선택하십시오',
|
||||
open_source_documents_software: '오픈 소스 문서 소프트웨어',
|
||||
verified_phone_number: '전화번호 확인됨',
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
class="flex items-center justify-center space-x-2"
|
||||
>
|
||||
<IconEye class="w-6 h-6 flex-shrink-0" />
|
||||
<span class="whitespace-nowrap">Save and Preview</span>
|
||||
<span class="whitespace-nowrap">{{ t('save_and_preview') }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
@@ -142,7 +142,7 @@
|
||||
@click="closeDropdown"
|
||||
>
|
||||
<IconAdjustments class="w-6 h-6 flex-shrink-0" />
|
||||
<span class="whitespace-nowrap">Preferences</span>
|
||||
<span class="whitespace-nowrap">{{ t('preferences') }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
href="https://www.docuseal.co/pricing"
|
||||
target="_blank"
|
||||
class="link"
|
||||
>Available in Pro</a>
|
||||
>{{ t('available_in_pro') }}</a>
|
||||
</div>
|
||||
<form @submit.prevent="validateSaveAndClose">
|
||||
<div class="my-4 space-y-5">
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
href="https://www.docuseal.co/pricing"
|
||||
target="_blank"
|
||||
class="link"
|
||||
>Available in Pro</a>
|
||||
>{{ t('available_in_pro') }}</a>
|
||||
</div>
|
||||
<div class="flex-inline mb-2 gap-2 space-y-1">
|
||||
<button
|
||||
@@ -201,7 +201,7 @@ export default {
|
||||
const normalizedFormula = this.normalizeFormula(this.formula)
|
||||
|
||||
if (normalizedFormula.includes('FIELD NOT FOUND')) {
|
||||
alert('Some fields are missing in the formula.')
|
||||
alert(this.t('some_fields_are_missing_in_the_formula'))
|
||||
} else {
|
||||
this.field.preferences.formula = normalizedFormula
|
||||
|
||||
|
||||
@@ -117,7 +117,15 @@ const en = {
|
||||
custom: 'Custom',
|
||||
numbers_only: 'Numbers only',
|
||||
letters_only: 'Letters only',
|
||||
regexp_validation: 'Regexp validation'
|
||||
regexp_validation: 'Regexp validation',
|
||||
enter_pdf_password: 'Enter PDF password',
|
||||
wrong_password: 'Wrong password',
|
||||
currency: 'Currency',
|
||||
save_and_preview: 'Save and Preview',
|
||||
preferences: 'Preferences',
|
||||
available_in_pro: 'Available in Pro',
|
||||
some_fields_are_missing_in_the_formula: 'Some fields are missing in the formula.',
|
||||
learn_more: 'Learn more'
|
||||
}
|
||||
|
||||
export { en }
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
<div class="flex items-center pl-1">
|
||||
<span
|
||||
class="tooltip tooltip-top"
|
||||
data-tip="Remove"
|
||||
data-tip="<%= t('remove') %>"
|
||||
>
|
||||
<button
|
||||
:disabled="mappings.filter((m) => m.submitter_uuid === submitter.uuid).length < 2"
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
class="absolute -top-1 left-2.5 px-1 h-4"
|
||||
style="font-size: 8px"
|
||||
>
|
||||
Currency
|
||||
{{ t('currency') }}
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
@@ -156,7 +156,7 @@
|
||||
href="https://www.docuseal.co/blog/accept-payments-and-request-signatures-with-ease"
|
||||
target="_blank"
|
||||
data-turbo="false"
|
||||
>Learn more</a>
|
||||
>{{ t('learn_more') }}</a>
|
||||
</div>
|
||||
<li class="mb-1">
|
||||
<label
|
||||
|
||||
@@ -90,10 +90,10 @@ export default {
|
||||
})
|
||||
} else if (resp.status === 422) {
|
||||
resp.json().then((data) => {
|
||||
if (data.error === 'PDF encrypted') {
|
||||
if (data.status === 'pdf_encrypted') {
|
||||
const formData = new FormData(this.$refs.form)
|
||||
|
||||
formData.append('password', prompt('Enter PDF password'))
|
||||
formData.append('password', prompt(this.t('enter_pdf_password')))
|
||||
|
||||
this.baseFetch(`/templates/${this.templateId}/documents`, {
|
||||
method: 'POST',
|
||||
@@ -103,7 +103,7 @@ export default {
|
||||
this.$emit('success', await resp.json())
|
||||
this.$refs.input.value = ''
|
||||
} else {
|
||||
alert('Wrong password')
|
||||
alert(this.t('wrong_password'))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@ class SubmitterMailer < ApplicationMailer
|
||||
MAX_ATTACHMENTS_SIZE = 10.megabytes
|
||||
SIGN_TTL = 1.hour + 20.minutes
|
||||
|
||||
DEFAULT_INVITATION_SUBJECT = 'You are invited to submit a form'
|
||||
|
||||
NO_REPLY_REGEXP = /no-?reply@/i
|
||||
|
||||
def invitation_email(submitter)
|
||||
@@ -21,17 +19,19 @@ class SubmitterMailer < ApplicationMailer
|
||||
|
||||
@email_config = AccountConfigs.find_for_account(@current_account, AccountConfig::SUBMITTER_INVITATION_EMAIL_KEY)
|
||||
|
||||
subject =
|
||||
if @email_config || @subject
|
||||
ReplaceEmailVariables.call(@subject || @email_config.value['subject'], submitter:)
|
||||
else
|
||||
DEFAULT_INVITATION_SUBJECT
|
||||
end
|
||||
|
||||
assign_message_metadata('submitter_invitation', @submitter)
|
||||
|
||||
reply_to = build_submitter_reply_to(@submitter)
|
||||
|
||||
subject =
|
||||
if @email_config || @subject
|
||||
ReplaceEmailVariables.call(@subject || @email_config.value['subject'], submitter:)
|
||||
elsif @submitter.with_signature_fields?
|
||||
I18n.t(:you_are_invited_to_sign_a_document)
|
||||
else
|
||||
I18n.t(:you_are_invited_to_submit_a_form)
|
||||
end
|
||||
|
||||
mail(
|
||||
to: @submitter.friendly_name,
|
||||
from: from_address_for_submitter(submitter),
|
||||
@@ -64,15 +64,12 @@ class SubmitterMailer < ApplicationMailer
|
||||
@body = @submitter.template.preferences['completed_notification_email_body'].presence
|
||||
@body ||= @email_config.value['body'] if @email_config
|
||||
|
||||
subject =
|
||||
if @subject.present?
|
||||
ReplaceEmailVariables.call(@subject, submitter:)
|
||||
else
|
||||
build_completed_subject(submitter)
|
||||
end
|
||||
|
||||
assign_message_metadata('submitter_completed', @submitter)
|
||||
|
||||
subject =
|
||||
ReplaceEmailVariables.call(@subject.presence || I18n.t(:template_name_has_been_completed_by_submitters),
|
||||
submitter:)
|
||||
|
||||
mail(from: from_address_for_submitter(submitter),
|
||||
to: to || (user.role == 'integration' ? user.friendly_name.sub(/\+\w+@/, '@') : user.friendly_name),
|
||||
subject:)
|
||||
@@ -116,17 +113,16 @@ class SubmitterMailer < ApplicationMailer
|
||||
@body = @submitter.template.preferences['documents_copy_email_body'].presence
|
||||
@body ||= @email_config.value['body'] if @email_config
|
||||
|
||||
assign_message_metadata('submitter_documents_copy', @submitter)
|
||||
reply_to = build_submitter_reply_to(submitter)
|
||||
|
||||
subject =
|
||||
if @subject.present?
|
||||
ReplaceEmailVariables.call(@subject, submitter:)
|
||||
else
|
||||
'Your document copy'
|
||||
I18n.t(:your_document_copy)
|
||||
end
|
||||
|
||||
assign_message_metadata('submitter_documents_copy', @submitter)
|
||||
|
||||
reply_to = build_submitter_reply_to(submitter)
|
||||
|
||||
mail(from: from_address_for_submitter(submitter),
|
||||
to: to || @submitter.friendly_name,
|
||||
reply_to:,
|
||||
@@ -145,12 +141,6 @@ class SubmitterMailer < ApplicationMailer
|
||||
reply_to
|
||||
end
|
||||
|
||||
def build_completed_subject(submitter)
|
||||
submitters = submitter.submission.submitters.order(:completed_at)
|
||||
.map { |e| e.name || e.email || e.phone }.join(', ')
|
||||
%(#{submitter.submission.template.name} has been completed by #{submitters})
|
||||
end
|
||||
|
||||
def add_completed_email_attachments!(submitter, with_audit_log: true, with_documents: true)
|
||||
documents = with_documents ? Submitters.select_attachments_for_download(submitter) : []
|
||||
|
||||
|
||||
@@ -43,29 +43,23 @@ class AccountConfig < ApplicationRecord
|
||||
COMBINE_PDF_RESULT_KEY = 'combine_pdf_result_key'
|
||||
|
||||
DEFAULT_VALUES = {
|
||||
SUBMITTER_INVITATION_EMAIL_KEY => {
|
||||
'subject' => 'You are invited to submit a form',
|
||||
'body' => "Hi there,\n\n" \
|
||||
"You have been invited to submit the \"{{template.name}}\" form.\n\n" \
|
||||
"{{submitter.link}}\n\n" \
|
||||
"Please contact us by replying to this email if you didn't request this.\n\n" \
|
||||
"Thanks,\n" \
|
||||
'{{account.name}}'
|
||||
SUBMITTER_INVITATION_EMAIL_KEY => lambda {
|
||||
{
|
||||
'subject' => I18n.t(:you_are_invited_to_sign_a_document),
|
||||
'body' => I18n.t(:submitter_invitation_email_sign_body)
|
||||
}
|
||||
},
|
||||
SUBMITTER_COMPLETED_EMAIL_KEY => {
|
||||
'subject' => '{{template.name}} has been completed by {{submission.submitters}}',
|
||||
'body' => "Hi,\n\n" \
|
||||
"\"{{template.name}}\" form has been completed by {{submission.submitters}}\n\n" \
|
||||
'{{submission.link}}'
|
||||
SUBMITTER_COMPLETED_EMAIL_KEY => lambda {
|
||||
{
|
||||
'subject' => I18n.t(:template_name_has_been_completed_by_submitters),
|
||||
'body' => I18n.t(:submitter_completed_email_body)
|
||||
}
|
||||
},
|
||||
SUBMITTER_DOCUMENTS_COPY_EMAIL_KEY => {
|
||||
'subject' => 'Your document copy',
|
||||
'body' => "Hi there,\n\n" \
|
||||
"Please check the copy of your \"{{template.name}}\" submission in the email attachments.\n" \
|
||||
"Alternatively, you can download your copy using:\n\n" \
|
||||
"{{documents.link}}\n\n" \
|
||||
"Thanks,\n" \
|
||||
'{{account.name}}'
|
||||
SUBMITTER_DOCUMENTS_COPY_EMAIL_KEY => lambda {
|
||||
{
|
||||
'subject' => I18n.t(:your_document_copy),
|
||||
'body' => I18n.t(:submitter_documents_copy_email_body)
|
||||
}
|
||||
}
|
||||
}.freeze
|
||||
|
||||
|
||||
@@ -96,4 +96,12 @@ class Submitter < ApplicationRecord
|
||||
def status_event_at
|
||||
declined_at || completed_at || opened_at || sent_at || created_at
|
||||
end
|
||||
|
||||
def with_signature_fields?
|
||||
@with_signature_fields ||= begin
|
||||
fields = submission.template_fields || template.fields
|
||||
signature_field_types = %w[signature initials]
|
||||
fields.any? { |f| f['submitter_uuid'] == uuid && signature_field_types.include?(f['type']) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
<div class="flex flex-wrap space-y-4 md:flex-nowrap md:space-y-0">
|
||||
<%= render 'shared/settings_nav' %>
|
||||
<div class="flex-grow max-w-xl mx-auto">
|
||||
<h1 class="text-4xl font-bold mb-4">Account</h1>
|
||||
<h1 class="text-4xl font-bold mb-4">
|
||||
<%= t('account') %>
|
||||
</h1>
|
||||
<%= form_for '', url: settings_account_path, method: :patch, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
||||
<%= fields_for current_account do |ff| %>
|
||||
<div class="form-control">
|
||||
<%= ff.label :name, 'Company Name', class: 'label' %>
|
||||
<%= ff.label :name, t('company_name'), class: 'label' %>
|
||||
<%= ff.text_field :name, required: true, class: 'base-input', dir: 'auto' %>
|
||||
</div>
|
||||
<div class="grid md:grid-cols-2 gap-4">
|
||||
<div class="form-control">
|
||||
<%= ff.label :timezone, class: 'label' %>
|
||||
<%= ff.label :timezone, t('time_zone'), class: 'label' %>
|
||||
<%= ff.select :timezone, nil, {}, class: 'base-select' do %>
|
||||
<%= time_zone_options_for_select(current_account.timezone) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= ff.label :locale, 'Time format', class: 'label' %>
|
||||
<%= ff.label :locale, t('time_format'), class: 'label' %>
|
||||
<%= ff.select :locale, options_for_select(controller.class::LOCALE_OPTIONS.invert, current_account.locale), {}, class: 'base-select' %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -25,27 +27,29 @@
|
||||
<% if !Docuseal.multitenant? && can?(:manage, encrypted_config) && !current_account.testing? && ENV['APP_URL'].blank? %>
|
||||
<%= fields_for encrypted_config do |ff| %>
|
||||
<div class="form-control">
|
||||
<%= ff.label :value, 'App URL', class: 'label' %>
|
||||
<%= ff.label :value, t('app_url'), class: 'label' %>
|
||||
<%= ff.text_field :value, autocomplete: 'off', class: 'base-input' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if can?(:update, current_account) %>
|
||||
<div class="form-control pt-2">
|
||||
<%= f.button button_title(title: 'Update', disabled_with: 'Updating'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('update'), disabled_with: t('updating')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if can?(:manage, AccountConfig) %>
|
||||
<div class="px-1 mt-8">
|
||||
<h2 class="text-2xl font-bold mb-2">Preferences</h2>
|
||||
<h2 class="text-2xl font-bold mb-2">
|
||||
<%= t('preferences') %>
|
||||
</h2>
|
||||
<% account_config = AccountConfig.find_or_initialize_by(account: current_account, key: AccountConfig::FORCE_MFA) %>
|
||||
<% if can?(:manage, account_config) %>
|
||||
<%= form_for account_config, url: account_configs_path, method: :post do |f| %>
|
||||
<%= f.hidden_field :key %>
|
||||
<div class="flex items-center justify-between py-2.5">
|
||||
<span>
|
||||
Force 2FA with Authenticator App
|
||||
<%= t('force_2fa_with_authenticator_app') %>
|
||||
</span>
|
||||
<%= f.check_box :value, class: 'toggle', checked: account_config.value, onchange: 'this.form.requestSubmit()' %>
|
||||
</div>
|
||||
@@ -57,7 +61,7 @@
|
||||
<%= f.hidden_field :key %>
|
||||
<div class="flex items-center justify-between py-2.5">
|
||||
<span>
|
||||
Add signature ID to the documents
|
||||
<%= t('add_signature_id_to_the_documents') %>
|
||||
</span>
|
||||
<%= f.check_box :value, class: 'toggle', checked: account_config.value, onchange: 'this.form.requestSubmit()' %>
|
||||
</div>
|
||||
@@ -69,7 +73,7 @@
|
||||
<%= f.hidden_field :key %>
|
||||
<div class="flex items-center justify-between py-2.5">
|
||||
<span>
|
||||
Require signing reason
|
||||
<%= t('require_signing_reason') %>
|
||||
</span>
|
||||
<%= f.check_box :value, class: 'toggle', checked: account_config.value, onchange: 'this.form.requestSubmit()' %>
|
||||
</div>
|
||||
@@ -81,7 +85,7 @@
|
||||
<%= f.hidden_field :key %>
|
||||
<div class="flex items-center justify-between py-2.5">
|
||||
<span>
|
||||
Allow typed text signatures
|
||||
<%= t('allow_typed_text_signatures') %>
|
||||
</span>
|
||||
<%= f.check_box :value, class: 'toggle', checked: account_config.value != false, onchange: 'this.form.requestSubmit()' %>
|
||||
</div>
|
||||
@@ -93,7 +97,7 @@
|
||||
<%= f.hidden_field :key %>
|
||||
<div class="flex items-center justify-between py-2.5">
|
||||
<span>
|
||||
Allow to resubmit completed forms
|
||||
<%= t('allow_to_resubmit_completed_forms') %>
|
||||
</span>
|
||||
<%= f.check_box :value, class: 'toggle', checked: account_config.value != false, onchange: 'this.form.requestSubmit()' %>
|
||||
</div>
|
||||
@@ -105,7 +109,7 @@
|
||||
<%= f.hidden_field :key %>
|
||||
<div class="flex items-center justify-between py-2.5">
|
||||
<span>
|
||||
Remember and pre-fill signatures
|
||||
<%= t('remember_and_pre_fill_signatures') %>
|
||||
</span>
|
||||
<%= f.check_box :value, class: 'toggle', checked: account_config.value != false, onchange: 'this.form.requestSubmit()' %>
|
||||
</div>
|
||||
@@ -117,7 +121,7 @@
|
||||
<%= f.hidden_field :key %>
|
||||
<div class="flex items-center justify-between py-2.5">
|
||||
<span>
|
||||
Require authentication for file download links
|
||||
<%= t('require_authentication_for_file_download_links') %>
|
||||
</span>
|
||||
<%= f.check_box :value, class: 'toggle', checked: account_config.value, onchange: 'this.form.requestSubmit()' %>
|
||||
</div>
|
||||
@@ -129,7 +133,7 @@
|
||||
<%= f.hidden_field :key %>
|
||||
<div class="flex items-center justify-between py-2.5">
|
||||
<span>
|
||||
Combine completed documents and Audit Log
|
||||
<%= t('combine_completed_documents_and_audit_log') %>
|
||||
</span>
|
||||
<%= f.check_box :value, class: 'toggle', checked: account_config.value, onchange: 'this.form.requestSubmit()' %>
|
||||
</div>
|
||||
@@ -140,8 +144,10 @@
|
||||
<%= render 'integrations' %>
|
||||
<% if can?(:manage, current_account) && Docuseal.multitenant? && true_user == current_user %>
|
||||
<div class="px-1 mt-8">
|
||||
<h2 class="text-2xl font-bold mb-2">Danger Zone</h2>
|
||||
<%= button_to button_title(title: 'Delete my account'), settings_account_path, class: 'btn btn-outline btn-error block', data: { turbo_confirm: 'Schedule account for deletion?' }, method: :delete, id: :account_delete_button %>
|
||||
<h2 class="text-2xl font-bold mb-2">
|
||||
<%= t('danger_zone') %>
|
||||
</h2>
|
||||
<%= button_to button_title(title: t('delete_my_account')), settings_account_path, class: 'btn btn-outline btn-error block', data: { turbo_confirm: t('schedule_account_for_deletion_') }, method: :delete, id: :account_delete_button %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
<div class="flex flex-col md:flex-row gap-4">
|
||||
<div class="flex w-full space-x-4">
|
||||
<input id="api_key" type="text" value="<%= current_user.access_token.token %>" class="input font-mono input-bordered w-full" autocomplete="off" readonly>
|
||||
<%= render 'shared/clipboard_copy', icon: 'copy', text: current_user.access_token.token, class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy', copied_title: 'Copied' %>
|
||||
<%= render 'shared/clipboard_copy', icon: 'copy', text: current_user.access_token.token, class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: t('copy'), copied_title: t('copied') %>
|
||||
</div>
|
||||
<%= button_to button_title(title: 'Rotate', disabled_with: 'Rotate', icon: svg_icon('reload', class: 'w-6 h-6')), settings_api_index_path, class: 'white-button w-full', data: { turbo_confirm: 'Remove existing API token and generated a new one. Are you sure?' } %>
|
||||
<%= button_to button_title(title: t('rotate'), disabled_with: t('rotate'), icon: svg_icon('reload', class: 'w-6 h-6')), settings_api_index_path, class: 'white-button w-full', data: { turbo_confirm: t('remove_existing_api_token_and_generated_a_new_one_are_you_sure_') } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -22,7 +22,7 @@
|
||||
<input type="checkbox">
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
<div>
|
||||
Request signature, multiple submitters with default values
|
||||
<%= t('request_signature_multiple_submitters_with_default_values') %>
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
<div class="badge badge-warning badge-lg">POST</div>
|
||||
@@ -48,7 +48,7 @@
|
||||
]
|
||||
}'<% end.to_str %>
|
||||
<span class="top-0 right-0 absolute">
|
||||
<%= render 'shared/clipboard_copy', icon: 'copy', text:, class: 'btn btn-ghost text-white', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy', copied_title: 'Copied' %>
|
||||
<%= render 'shared/clipboard_copy', icon: 'copy', text:, class: 'btn btn-ghost text-white', icon_class: 'w-6 h-6 text-white', copy_title: t('copy'), copied_title: t('copied') %>
|
||||
</span>
|
||||
<pre data-prefix="$"><code class="overflow-hidden w-full"><%= text %></code></pre>
|
||||
</div>
|
||||
@@ -58,7 +58,7 @@
|
||||
<input type="checkbox">
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
<div>
|
||||
Request signature, single submitter
|
||||
<%= t('request_signature_single_submitter') %>
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
<div class="badge badge-warning badge-lg">POST</div>
|
||||
@@ -74,7 +74,7 @@
|
||||
"emails": "<%= current_user.email.sub('@', '+test@') %>, <%= current_user.email.sub('@', '+test2@') %>"
|
||||
}'<% end.to_str %>
|
||||
<span class="top-0 right-0 absolute">
|
||||
<%= render 'shared/clipboard_copy', icon: 'copy', text:, class: 'btn btn-ghost text-white', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy', copied_title: 'Copied' %>
|
||||
<%= render 'shared/clipboard_copy', icon: 'copy', text:, class: 'btn btn-ghost text-white', icon_class: 'w-6 h-6 text-white', copy_title: t('copy'), copied_title: t('copied') %>
|
||||
</span>
|
||||
<pre data-prefix="$"><code class="overflow-hidden w-full"><%= text %></code></pre>
|
||||
</div>
|
||||
@@ -84,7 +84,7 @@
|
||||
<input type="checkbox">
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
<div>
|
||||
Template details
|
||||
<%= t('template_details') %>
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
<div class="badge badge-info badge-lg">GET</div>
|
||||
@@ -96,7 +96,7 @@
|
||||
<% text = capture do %>curl '<%= api_template_url(current_account.templates&.last || 1) %>' \
|
||||
--header 'X-Auth-Token: <%= current_user.access_token.token %>'<% end.to_str %>
|
||||
<span class="top-0 right-0 absolute">
|
||||
<%= render 'shared/clipboard_copy', icon: 'copy', text:, class: 'btn btn-ghost text-white', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy', copied_title: 'Copied' %>
|
||||
<%= render 'shared/clipboard_copy', icon: 'copy', text:, class: 'btn btn-ghost text-white', icon_class: 'w-6 h-6 text-white', copy_title: t('copy'), copied_title: t('copied') %>
|
||||
</span>
|
||||
<pre data-prefix="$"><code class="overflow-hidden w-full"><%= text %></code></pre>
|
||||
</div>
|
||||
@@ -104,7 +104,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<%= link_to 'Open Full API Reference', "#{Docuseal::PRODUCT_URL}/docs/api", class: 'btn btn-warning text-base mt-4 px-8', target: '_blank', rel: 'noopener' %>
|
||||
<%= link_to t('open_full_api_reference'), "#{Docuseal::PRODUCT_URL}/docs/api", class: 'btn btn-warning text-base mt-4 px-8', target: '_blank', rel: 'noopener' %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<form action="<%= root_path %>" method="get" class="bg-base-200 px-1.5 rounded-xl py-1 whitespace-nowrap">
|
||||
<toggle-cookies data-value="templates" data-key="dashboard_view" class="sm:tooltip tooltip-top" data-tip="Templates">
|
||||
<toggle-cookies data-value="templates" data-key="dashboard_view" class="sm:tooltip tooltip-top" data-tip="<%= t('templates') %>">
|
||||
<button class="<%= local_assigns[:selected] == 'submissions' ? 'btn !border !rounded-lg btn-square !p-0 !btn-sm !h-8 !w-9' : 'btn btn-neutral !rounded-lg btn-square !p-0 hover:text-neutral-300 !btn-sm !h-8 !w-9 disabled:btn-neutral' %>">
|
||||
<%= svg_icon('layout_grid', class: 'w-6 h-6 stroke-2') %>
|
||||
</button>
|
||||
</toggle-cookies>
|
||||
<toggle-cookies data-value="submissions" data-key="dashboard_view" class="sm:tooltip tooltip-top" data-tip="Submissions">
|
||||
<toggle-cookies data-value="submissions" data-key="dashboard_view" class="sm:tooltip tooltip-top" data-tip="<%= t('submissions') %>">
|
||||
<button class="<%= local_assigns[:selected] == 'submissions' ? 'btn btn-neutral !rounded-lg btn-square !p-0 hover:text-neutral-300 !btn-sm !h-8 !w-9' : 'btn !border !rounded-lg btn-square !p-0 !btn-sm !h-8 !w-9 disabled:btn-neutral' %>">
|
||||
<%= svg_icon('layout_list', class: 'w-6 h-6 stroke-2') %>
|
||||
</button>
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
<div class="max-w-lg mx-auto px-2">
|
||||
<h1 class="text-4xl font-bold text-center mt-8">Change your password</h1>
|
||||
<h1 class="text-4xl font-bold text-center mt-8">
|
||||
<%= t('change_your_password') %>
|
||||
</h1>
|
||||
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put, class: 'space-y-6' }) do |f| %>
|
||||
<div class="space-y-2">
|
||||
<%= render 'devise/shared/error_messages', resource: %>
|
||||
<%= f.hidden_field :reset_password_token %>
|
||||
<div class="form-control">
|
||||
<%= f.label :password, 'New password', class: 'label' %>
|
||||
<%= f.label :password, t('new_password'), class: 'label' %>
|
||||
<%= f.password_field :password, autofocus: true, autocomplete: 'new-password', class: 'base-input' %>
|
||||
<% if @minimum_password_length %>
|
||||
<label class="label">
|
||||
<span class="label-text">(<%= @minimum_password_length %> characters minimum)</span>
|
||||
<span class="label-text">(<%= t('minimum_password_length_characters_minimum', minimum_password_length: @minimum_password_length) %>)</span>
|
||||
</label>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.label :password_confirmation, 'Confirm new password', class: 'label' %>
|
||||
<%= f.label :password_confirmation, t('confirm_new_password'), class: 'label' %>
|
||||
<%= f.password_field :password_confirmation, autocomplete: 'new-password', class: 'base-input' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.button button_title(title: 'Change my password', disabled_with: 'Changing password'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('change_my_password'), disabled_with: t('changing_password')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
<div class="max-w-lg mx-auto px-2">
|
||||
<h1 class="text-4xl font-bold text-center mt-8">Forgot your password?</h1>
|
||||
<h1 class="text-4xl font-bold text-center mt-8">
|
||||
<%= t('forgot_your_password_') %>
|
||||
</h1>
|
||||
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post, class: 'space-y-6' }) do |f| %>
|
||||
<div class="space-y-2">
|
||||
<%= render 'devise/shared/error_messages', resource: %>
|
||||
<div class="form-control">
|
||||
<%= f.label :email, class: 'label' %>
|
||||
<%= f.label :email, t(:email), class: 'label' %>
|
||||
<%= f.email_field :email, autofocus: true, autocomplete: 'email', class: 'base-input' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.button button_title(title: 'Reset password', disabled_with: 'Resetting password'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('reset_password'), disabled_with: t('resetting_password')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<div class="max-w-lg mx-auto px-2">
|
||||
<h1 class="text-4xl font-bold text-center mt-8">Sign In</h1>
|
||||
<h1 class="text-4xl font-bold text-center mt-8">
|
||||
<%= t('sign_in') %>
|
||||
</h1>
|
||||
<%= form_for(resource, as: resource_name, html: { class: 'space-y-6' }, data: { turbo: params[:redir].blank? }, url: session_path(resource_name)) do |f| %>
|
||||
<%= f.hidden_field :email %>
|
||||
<%= f.hidden_field :password %>
|
||||
@@ -8,12 +10,12 @@
|
||||
<% end %>
|
||||
<div class="space-y-2">
|
||||
<div class="form-control">
|
||||
<%= f.label :otp_attempt, 'Two-Factor Code from Authenticator App', class: 'label' %>
|
||||
<%= f.label :otp_attempt, t('two_factor_code_from_authenticator_app'), class: 'label' %>
|
||||
<%= f.text_field :otp_attempt, autofocus: true, placeholder: 'XXX-XXX', required: true, class: 'base-input' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.button button_title(title: 'Sign In', disabled_with: 'Signing In'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('sign_in'), disabled_with: t('signing_in')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<%= link_to t('already_have_an_account'), new_session_path(resource_name, { lang: params[:lang] }.compact_blank), class: 'link link-hover mx-auto' %>
|
||||
<% end %>
|
||||
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
|
||||
<%= link_to t('create_free_account'), registration_path({ redir: params[:redir], lang: params[:lang] }.compact_blank), class: 'link link-hover' %>
|
||||
<%= link_to t('create_free_account'), registration_path({ redir: params[:redir], lang: params[:lang] }.compact_blank), class: 'link link-hover capitalize' %>
|
||||
<% end %>
|
||||
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
|
||||
<%= link_to t('forgot_your_password_'), new_password_path(resource_name, { lang: params[:lang] }.compact_blank), class: 'link link-hover' %>
|
||||
|
||||
@@ -7,31 +7,31 @@
|
||||
<%= f.fields_for :value do |ff| %>
|
||||
<div class="grid md:grid-cols-2 gap-4">
|
||||
<div class="form-control">
|
||||
<%= ff.label :host, class: 'label' %>
|
||||
<%= ff.label :host, 'Host', class: 'label' %>
|
||||
<%= ff.text_field :host, value: value['host'], required: true, class: 'base-input' %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= ff.label :port, class: 'label' %>
|
||||
<%= ff.label :port, 'Port', class: 'label' %>
|
||||
<%= ff.text_field :port, value: value['port'], required: true, class: 'base-input' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid md:grid-cols-2 gap-4">
|
||||
<div class="form-control">
|
||||
<%= ff.label :username, class: 'label' %>
|
||||
<%= ff.label :username, 'Username', class: 'label' %>
|
||||
<%= ff.text_field :username, value: value['username'], class: 'base-input' %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= ff.label :password, class: 'label' %>
|
||||
<%= ff.label :password, 'Password', class: 'label' %>
|
||||
<%= ff.password_field :password, value: value['password'], class: 'base-input' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid md:grid-cols-2 gap-4">
|
||||
<div class="form-control">
|
||||
<%= ff.label :domain, 'Domain (optional)', class: 'label' %>
|
||||
<%= ff.label :domain, "Domain (#{t('optional')})", class: 'label' %>
|
||||
<%= ff.text_field :domain, value: value['domain'], class: 'base-input' %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= ff.label :authentication, class: 'label' %>
|
||||
<%= ff.label :authentication, 'Authentication', class: 'label' %>
|
||||
<%= ff.select :authentication, options_for_select([%w[Plain plain], %w[Login login], %w[CRAM-MD5 cram_md5]], value.fetch('authentication', 'plain')), { prompt: true }, required: true, class: 'base-select' %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -47,12 +47,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= ff.label :from_email, 'Send from Email', class: 'label' %>
|
||||
<%= ff.label :from_email, t('send_from_email'), class: 'label' %>
|
||||
<%= ff.email_field :from_email, value: value['from_email'], required: true, class: 'base-input' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="form-control pt-2">
|
||||
<%= f.button button_title(title: 'Save', disabled_with: 'Saving'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
<%= render 'shared/turbo_modal', title: 'Upload Certificate' do %>
|
||||
<%= render 'shared/turbo_modal', title: t('upload_certificate') do %>
|
||||
<%= form_for @cert_record, url: settings_esign_path, html: { class: 'space-y-4', enctype: 'multipart/form-data' }, data: { turbo_frame: :_top } do |f| %>
|
||||
<div class="space-y-2">
|
||||
<div class="form-control">
|
||||
<%= f.label :name, class: 'label' %>
|
||||
<%= f.label :name, t('name'), class: 'label' %>
|
||||
<%= f.text_field :name, required: true, class: 'base-input' %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.label :file, class: 'label' %>
|
||||
<%= f.label :file, t('file'), class: 'label' %>
|
||||
<%= f.file_field :file, required: true %>
|
||||
<label class="label">
|
||||
<span class="label-text-alt">Use a valid .der, .p12 or .pfx file.</span>
|
||||
<span class="label-text-alt">
|
||||
<%= t('use_a_valid_der_p12_or_pfx_file') %>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.label :password, 'Password (optional)', class: 'label' %>
|
||||
<%= f.label :password, "#{t('password')} (#{t('optional')})", class: 'label' %>
|
||||
<%= f.password_field :password, class: 'base-input' %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,17 +2,19 @@
|
||||
<%= render 'shared/settings_nav' %>
|
||||
<div class="md:flex-grow">
|
||||
<div class="max-w-xl">
|
||||
<h1 class="text-4xl font-bold mb-4">PDF Signature</h1>
|
||||
<h1 class="text-4xl font-bold mb-4">
|
||||
<%= t('pdf_signature') %>
|
||||
</h1>
|
||||
<div id="result">
|
||||
<p class="mb-2">
|
||||
Upload signed PDF file to validate its signature:
|
||||
<%= t('upload_signed_pdf_file_to_validate_its_signature_') %>
|
||||
</p>
|
||||
</div>
|
||||
<%= form_for '', url: verify_pdf_signature_index_path, method: :post, html: { enctype: 'multipart/form-data' } do |f| %>
|
||||
<%= f.button type: 'submit', class: 'flex' do %>
|
||||
<div class="disabled mb-3">
|
||||
<%= svg_icon('loader', class: 'w-5 h-5 animate-spin inline') %>
|
||||
Analyzing...
|
||||
<%= "#{t('analyzing')}..." %>
|
||||
</div>
|
||||
<% end %>
|
||||
<file-dropzone data-name="verify_attachments" data-submit-on-upload="true" class="w-full">
|
||||
@@ -26,10 +28,10 @@
|
||||
<%= svg_icon('loader', class: 'w-10 h-10 animate-spin') %>
|
||||
</span>
|
||||
<div class="font-medium mb-1">
|
||||
Verify Signed PDF
|
||||
<%= t('verify_signed_pdf') %>
|
||||
</div>
|
||||
<div class="text-xs">
|
||||
<span class="font-medium">Click to upload</span> or drag and drop files
|
||||
<%= t('click_to_upload_or_drag_and_drop_files_html') %>
|
||||
</div>
|
||||
</div>
|
||||
<input id="file" name="files[]" class="hidden" data-action="change:file-dropzone#onSelectFiles" data-target="file-dropzone.input" type="file" accept="application/pdf" multiple>
|
||||
@@ -39,11 +41,13 @@
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="flex justify-between items-end mb-4 mt-8">
|
||||
<h2 class="text-3xl font-bold">Signing Certificates</h2>
|
||||
<h2 class="text-3xl font-bold">
|
||||
<%= t('signing_certificates') %>
|
||||
</h2>
|
||||
<% if can?(:create, @encrypted_config) %>
|
||||
<%= link_to new_settings_esign_path, class: 'btn btn-primary btn-md', data: { turbo_frame: 'modal' } do %>
|
||||
<%= svg_icon('plus', class: 'w-6 h-6') %>
|
||||
<span>Upload Cert</span>
|
||||
<span><%= t('upload_cert') %></span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -53,13 +57,13 @@
|
||||
<thead class="bg-base-200">
|
||||
<tr class="text-neutral uppercase">
|
||||
<th>
|
||||
Name
|
||||
<%= t('name') %>
|
||||
</th>
|
||||
<th>
|
||||
Valid To
|
||||
<%= t('valid_to') %>
|
||||
</th>
|
||||
<th>
|
||||
Status
|
||||
<%= t('status') %>
|
||||
</th>
|
||||
<th class="text-right" width="1px">
|
||||
</th>
|
||||
@@ -77,18 +81,18 @@
|
||||
<td>
|
||||
<% if item['status'] == 'default' %>
|
||||
<span class="badge badge-lg badge-info badge-outline">
|
||||
<%= item['status'] %>
|
||||
<%= t('default') %>
|
||||
</span>
|
||||
<% elsif can?(:update, @encrypted_config) %>
|
||||
<%= button_to settings_esign_path, method: :put, params: { name: item['name'] }, class: 'btn btn-outline btn-neutral btn-xs whitespace-nowrap', title: 'Delete', data: { turbo_confirm: 'Are you sure?' } do %>
|
||||
Make Default
|
||||
<%= button_to settings_esign_path, method: :put, params: { name: item['name'] }, class: 'btn btn-outline btn-neutral btn-xs whitespace-nowrap', title: t('make_default'), data: { turbo_confirm: t('are_you_sure_') } do %>
|
||||
<%= t('make_default') %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</td>
|
||||
<td>
|
||||
<% if item['name'] != EsignSettingsController::DEFAULT_CERT_NAME && item['status'] != 'default' && can?(:destroy, @encrypted_config) %>
|
||||
<%= button_to settings_esign_path, params: { name: item['name'] }, method: :delete, class: 'btn btn-outline btn-error btn-xs', title: 'Delete', data: { turbo_confirm: 'Are you sure?' } do %>
|
||||
Remove
|
||||
<%= button_to settings_esign_path, params: { name: item['name'] }, method: :delete, class: 'btn btn-outline btn-error btn-xs', title: t('remove'), data: { turbo_confirm: t('are_you_sure_') } do %>
|
||||
<%= t('remove') %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</td>
|
||||
@@ -101,24 +105,26 @@
|
||||
<% if !Docuseal.multitenant? && can?(:manage, encrypted_config) %>
|
||||
<div class="flex-grow max-w-xl">
|
||||
<div class="flex justify-between items-end mb-4 mt-8">
|
||||
<h2 class="text-3xl font-bold">Timestamp Server</h2>
|
||||
<h2 class="text-3xl font-bold">
|
||||
<%= t('timestamp_server') %>
|
||||
</h2>
|
||||
</div>
|
||||
<%= form_for encrypted_config, url: timestamp_server_index_path, method: :post, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
||||
<div class="form-control">
|
||||
<%= f.label :value, class: 'label' do %>
|
||||
<span class="flex items-center space-x-1">
|
||||
<span>
|
||||
Timeserver URL
|
||||
<%= t('timeserver_url') %>
|
||||
</span>
|
||||
<span class="tooltip" data-tip="URL of the trusted RFC 3161 timeserver to be used to generate timestamp signatures.">
|
||||
<span class="tooltip" data-tip="<%= t('url_of_the_trusted_rfc_3161_timeserver_to_be_used_to_generate_timestamp_signatures') %>">
|
||||
<%= svg_icon('info_circle', class: 'w-4 h-4') %>
|
||||
</span>
|
||||
</span>
|
||||
<% end %>
|
||||
<%= f.url_field :value, autocomplete: 'off', class: 'base-input', placeholder: 'URL (optional)' %>
|
||||
<%= f.url_field :value, autocomplete: 'off', class: 'base-input', placeholder: "URL (#{t('optional')})" %>
|
||||
</div>
|
||||
<div class="form-control pt-2">
|
||||
<%= f.button button_title(title: 'Save', disabled_with: 'Updating'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('save'), disabled_with: t('updating')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -127,14 +133,16 @@
|
||||
<% if can?(:manage, account_config) %>
|
||||
<div class="px-1 mt-8 max-w-xl">
|
||||
<div class="flex justify-between items-end mb-4 mt-8">
|
||||
<h2 class="text-3xl font-bold">Preferences</h2>
|
||||
<h2 class="text-3xl font-bold">
|
||||
<%= t('preferences') %>
|
||||
</h2>
|
||||
</div>
|
||||
<% if can?(:manage, account_config) %>
|
||||
<%= form_for account_config, url: account_configs_path, method: :post do |f| %>
|
||||
<%= f.hidden_field :key %>
|
||||
<div class="flex items-center justify-between py-2.5">
|
||||
<span>
|
||||
Apply multiple PDF digital signatures in the document per each signer
|
||||
<%= t('apply_multiple_pdf_digital_signatures_in_the_document_per_each_signer') %>
|
||||
</span>
|
||||
<%= f.check_box :value, { class: 'toggle', checked: account_config.value == 'multiple', onchange: 'this.form.requestSubmit()' }, 'multiple', 'single' %>
|
||||
</div>
|
||||
@@ -146,7 +154,7 @@
|
||||
<%= f.hidden_field :key %>
|
||||
<div class="flex items-center justify-between py-2.5">
|
||||
<span>
|
||||
Remove PDF form fillable fields from the signed PDF (flatten form)
|
||||
<%= t('remove_pdf_form_fillable_fields_from_the_signed_pdf_flatten_form') %>
|
||||
</span>
|
||||
<%= f.check_box :value, { class: 'toggle', checked: account_config.value != false, onchange: 'this.form.requestSubmit()' } %>
|
||||
</div>
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
<div class="max-w-xl mx-auto px-2">
|
||||
<h1 class="flex text-4xl font-bold items-center justify-center my-8 space-x-2">
|
||||
<%= svg_icon('waving_hand', class: 'h-10 w-10') %>
|
||||
<span>Welcome to <%= Docuseal.product_name %></span>
|
||||
<span><%= t('welcome_to_product_name', product_name: Docuseal.product_name) %></span>
|
||||
</h1>
|
||||
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put, class: 'space-y-6' }) do |f| %>
|
||||
<div class="space-y-2">
|
||||
<%= render 'devise/shared/error_messages', resource: %>
|
||||
<%= f.hidden_field :reset_password_token %>
|
||||
<div class="form-control">
|
||||
<%= f.label :password, 'Set password', class: 'label' %>
|
||||
<%= f.label :password, t('set_password'), class: 'label' %>
|
||||
<%= f.password_field :password, autofocus: true, autocomplete: 'new-password', class: 'base-input' %>
|
||||
<% if @minimum_password_length %>
|
||||
<label class="label">
|
||||
<span class="label-text">(<%= @minimum_password_length %> characters minimum)</span>
|
||||
<span class="label-text">(<%= t('minimum_password_length_characters_minimum', minimum_password_length: @minimum_password_length) %>)</span>
|
||||
</label>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.label :password_confirmation, 'Confirm new password', class: 'label' %>
|
||||
<%= f.label :password_confirmation, t('confirm_password'), class: 'label' %>
|
||||
<%= f.password_field :password_confirmation, autocomplete: 'new-password', class: 'base-input' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.button button_title(title: 'Save password and Sign in', disabled_with: 'Saving'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('save_password_and_sign_in'), disabled_with: t('saving')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<%= form_for '', url: mfa_setup_path, data: { turbo_frame: :_top }, html: { id: 'mfa_form' } do |f| %>
|
||||
<p class="text-center">
|
||||
Use an authenticator mobile app like Google Authenticator or 1Password to scan the QR code below.
|
||||
<%= t('use_an_authenticator_mobile_app_like_google_authenticator_or_1password_to_scan_the_qr_code_below') %>
|
||||
</p>
|
||||
<div>
|
||||
<%== RQRCode::QRCode.new(@provision_url).as_svg(viewbox: true, svg_attributes: { class: 'md:w-80 md:h-80 my-4 mx-auto' }) %>
|
||||
@@ -12,6 +12,6 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-control mt-4">
|
||||
<%= f.button button_title(title: 'Save'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('save')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<%= render 'shared/turbo_modal', title: 'Remove 2FA' do %>
|
||||
<%= render 'shared/turbo_modal', title: t('remove_2fa') do %>
|
||||
<%= form_for '', url: mfa_setup_path, method: :delete, data: { turbo_frame: :_top } do |f| %>
|
||||
<div class="form-control my-6 space-y-2">
|
||||
<%= f.text_field :otp_attempt, required: true, placeholder: 'XXX-XXX', class: 'base-input text-center' %>
|
||||
@@ -7,7 +7,7 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-control mt-4">
|
||||
<%= f.button button_title(title: 'Remove 2FA'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('remove_2fa')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<%= render 'shared/turbo_modal', title: 'Setup 2FA' do %>
|
||||
<%= render 'shared/turbo_modal', title: t('setup_2fa') do %>
|
||||
<%= render 'mfa_setup/form' %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<div class="max-w-lg mx-auto px-2">
|
||||
<h1 class="text-4xl font-bold text-center mt-8">Setup 2FA</h1>
|
||||
<h1 class="text-4xl font-bold text-center mt-8">
|
||||
<%= t('setup_2fa') %>
|
||||
</h1>
|
||||
<%= render 'mfa_setup/form' %>
|
||||
</div>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<div class="max-w-xl mx-auto px-2">
|
||||
<h1 class="text-4xl font-bold text-center my-8">👨💻 Developer Newsletters</h1>
|
||||
<h1 class="text-4xl font-bold text-center my-8">👨💻 <%= t('developer_newsletters') %></h1>
|
||||
<%= form_for current_user, url: newsletter_path do |f| %>
|
||||
<div class="form-control">
|
||||
<%= f.email_field :email, placeholder: 'Email', required: true, class: 'base-input' %>
|
||||
<%= f.email_field :email, placeholder: t('email'), required: true, class: 'base-input' %>
|
||||
</div>
|
||||
<div class="form-control mt-4">
|
||||
<%= f.button button_title, class: 'base-button' %>
|
||||
</div>
|
||||
<div class="text-center mt-2">
|
||||
<a href="/" class="link">Skip</a>
|
||||
<a href="/" class="link"><%= t('skip') %></a>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<%= f.label :value, class: 'label' do %>
|
||||
<span class="flex items-center space-x-1">
|
||||
<span>
|
||||
Completed documents notification BCC address
|
||||
<%= t('completed_documents_notification_bcc_address') %>
|
||||
</span>
|
||||
<span class="tooltip" data-tip="Send email copy with completed documents to a specified BCC address.">
|
||||
<%= svg_icon('info_circle', class: 'w-4 h-4') %>
|
||||
@@ -14,6 +14,6 @@
|
||||
<%= tag.input type: 'email', multiple: true, name: 'account_config[value]', autocomplete: 'off', class: 'base-input', value: f.object.value %>
|
||||
</div>
|
||||
<div class="form-control pt-2">
|
||||
<%= f.button button_title(title: 'Save', disabled_with: 'Updating'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('save'), disabled_with: t('updating')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -2,29 +2,29 @@
|
||||
<%= f.hidden_field :key %>
|
||||
<div class="form-control">
|
||||
<% record = Struct.new(:first_duration, :second_duration, :third_duration).new(*(f.object.value || {}).values_at('first_duration', 'second_duration', 'third_duration')) %>
|
||||
<% durations = Docuseal.multitenant? ? AccountConfigs::REMINDER_DURATIONS.except('one_hour', 'two_hours').invert : AccountConfigs::REMINDER_DURATIONS.invert %>
|
||||
<% 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="w-full">
|
||||
<%= f.fields_for :value, record do |ff| %>
|
||||
<%= ff.label :first_duration, 'First reminder in', class: 'label' %>
|
||||
<%= ff.label :first_duration, t('first_reminder_in'), class: 'label' %>
|
||||
<%= ff.select :first_duration, durations, { include_blank: 'None' }, class: 'base-select' %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<%= f.fields_for :value, record do |ff| %>
|
||||
<%= ff.label :second_duration, 'Second reminder in', class: 'label' %>
|
||||
<%= ff.label :second_duration, t('second_reminder_in'), class: 'label' %>
|
||||
<%= ff.select :second_duration, durations, { include_blank: 'None' }, class: 'base-select' %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<%= f.fields_for :value, record do |ff| %>
|
||||
<%= ff.label :third_duration, 'Third reminder in', class: 'label' %>
|
||||
<%= ff.label :third_duration, t('third_reminder_in'), class: 'label' %>
|
||||
<%= ff.select :third_duration, durations, { include_blank: 'None' }, class: 'base-select' %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-control pt-4">
|
||||
<%= f.button button_title(title: 'Save', disabled_with: 'Updating'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('save'), disabled_with: t('updating')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
<div class="alert my-4">
|
||||
<%= svg_icon('info_circle', class: 'w-6 h-6') %>
|
||||
<div>
|
||||
<p class="font-bold">Unlock with DocuSeal Pro</p>
|
||||
<p class="font-bold">
|
||||
<%= t('unlock_with_docuseal_pro') %>
|
||||
</p>
|
||||
<p>
|
||||
Send automatic email reminders to your recipients.
|
||||
<%= t('send_automatic_email_reminders_to_your_recipients') %>
|
||||
<br>
|
||||
<a class="link font-medium" target="_blank" href="<%= Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") : "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premise" }.to_query}" %>" data-turbo="false">Learn More</a>
|
||||
<a class="link font-medium" target="_blank" href="<%= Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") : "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premise" }.to_query}" %>" data-turbo="false">
|
||||
<%= t('learn_more') %>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<div class="flex flex-wrap space-y-4 md:flex-nowrap md:space-y-0">
|
||||
<%= render 'shared/settings_nav' %>
|
||||
<div class="flex-grow max-w-xl mx-auto">
|
||||
<h1 class="text-4xl font-bold mb-4">Email Notifications</h1>
|
||||
<h1 class="text-4xl font-bold mb-4">
|
||||
<%= t('email_notifications') %>
|
||||
</h1>
|
||||
<div class="mt-2 mb-1">
|
||||
<% user_config = UserConfig.find_or_initialize_by(user: current_user, key: UserConfig::RECEIVE_COMPLETED_EMAIL) %>
|
||||
<% if can?(:manage, user_config) %>
|
||||
@@ -9,7 +11,7 @@
|
||||
<%= f.hidden_field :key %>
|
||||
<div class="flex items-center justify-between">
|
||||
<span>
|
||||
Receive notification emails on completed submission
|
||||
<%= t('receive_notification_emails_on_completed_submission') %>
|
||||
</span>
|
||||
<%= f.check_box :value, class: 'toggle', checked: user_config.value != false, onchange: 'this.form.requestSubmit()' %>
|
||||
</div>
|
||||
@@ -18,7 +20,9 @@
|
||||
</div>
|
||||
<%= render 'bcc_form', config: @bcc_config %>
|
||||
<div class="flex justify-between items-end mb-4 mt-8">
|
||||
<h2 class="text-3xl font-bold">Sign Request Email Reminders</h2>
|
||||
<h2 class="text-3xl font-bold">
|
||||
<%= t('sign_request_email_reminders') %>
|
||||
</h2>
|
||||
</div>
|
||||
<%= render 'reminder_banner' %>
|
||||
<%= render 'reminder_form', config: @reminder_config %>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<div class="collapse collapse-plus bg-base-200 overflow-visible">
|
||||
<input type="checkbox">
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
<div class="collapse-title text-xl font-medium capitalize">
|
||||
<div>
|
||||
Documents Copy Email
|
||||
<%= t('documents_copy_email') %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
@@ -10,13 +10,13 @@
|
||||
<%= f.hidden_field :key %>
|
||||
<%= f.fields_for :value, Struct.new(:subject, :body, :attach_audit_log).new(*f.object.value.values_at('subject', 'body', 'attach_audit_log')) do |ff| %>
|
||||
<div class="form-control">
|
||||
<%= ff.label :subject, class: 'label' %>
|
||||
<%= ff.label :subject, t('subject'), class: 'label' %>
|
||||
<%= ff.text_field :subject, required: true, class: 'base-input', dir: 'auto' %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<div class="flex items-center">
|
||||
<%= ff.label :body, class: 'label' %>
|
||||
<span class="tooltip" data-tip="Use following placeholders text: <%= AccountConfig::DEFAULT_VALUES.dig(AccountConfig::SUBMITTER_DOCUMENTS_COPY_EMAIL_KEY, 'body').scan(/{{.*?}}/).join(', ') %>">
|
||||
<%= ff.label :body, t('body'), class: 'label' %>
|
||||
<span class="tooltip" data-tip="<%= t('use_following_placeholders_text_') %> <%= AccountConfig::DEFAULT_VALUES[AccountConfig::SUBMITTER_DOCUMENTS_COPY_EMAIL_KEY].call['body'].scan(/{.*?}/).join(', ') %>">
|
||||
<%= svg_icon('info_circle', class: 'w-4 h-4') %>
|
||||
</span>
|
||||
</div>
|
||||
@@ -26,13 +26,13 @@
|
||||
</div>
|
||||
<div class="flex items-center justify-between py-2.5 mx-1">
|
||||
<span>
|
||||
Attach audit log PDF
|
||||
<%= t('attach_audit_log_pdf') %>
|
||||
</span>
|
||||
<%= ff.check_box :attach_audit_log, { checked: ff.object.attach_audit_log != false, class: 'toggle' }, 'true', 'false' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="form-control pt-2">
|
||||
<%= f.button button_title(title: 'Save', disabled_with: 'Saving'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<input type="checkbox">
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
<div>
|
||||
Completed Form Redirect Button
|
||||
<%= t('completed_form_redirect_button') %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
@@ -10,16 +10,16 @@
|
||||
<%= f.hidden_field :key %>
|
||||
<%= f.fields_for :value, Struct.new(:title, :url).new(*(f.object.value || {}).values_at('title', 'url')) do |ff| %>
|
||||
<div class="form-control">
|
||||
<%= ff.label :title, 'Button title', class: 'label' %>
|
||||
<%= ff.label :title, t('button_title'), class: 'label' %>
|
||||
<%= ff.text_field :title, class: 'base-input', dir: 'auto' %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= ff.label :url, 'Button URL', class: 'label' %>
|
||||
<%= ff.label :url, t('button_url'), class: 'label' %>
|
||||
<%= ff.url_field :url, class: 'base-input' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="form-control pt-2">
|
||||
<%= f.button button_title(title: 'Save', disabled_with: 'Saving'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<input type="checkbox">
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
<div>
|
||||
Completed Form Message
|
||||
<%= t('completed_form_message') %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
@@ -10,18 +10,18 @@
|
||||
<%= f.hidden_field :key %>
|
||||
<%= f.fields_for :value, Struct.new(:title, :body).new(*(f.object.value || {}).values_at('title', 'body')) do |ff| %>
|
||||
<div class="form-control">
|
||||
<%= ff.label :title, 'Title', class: 'label' %>
|
||||
<%= ff.label :title, t('title'), class: 'label' %>
|
||||
<%= ff.text_field :title, class: 'base-input', dir: 'auto' %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= ff.label :body, 'Body', class: 'label' %>
|
||||
<%= ff.label :body, t('body'), class: 'label' %>
|
||||
<autoresize-textarea>
|
||||
<%= ff.text_area :body, class: 'base-input w-full py-2', dir: 'auto' %>
|
||||
</autoresize-textarea>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="form-control pt-2">
|
||||
<%= f.button button_title(title: 'Save', disabled_with: 'Saving'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<%= f.hidden_field :key %>
|
||||
<div class="flex items-center justify-between py-2.5">
|
||||
<span>
|
||||
Show confetti on successful completion
|
||||
<%= t('show_confetti_on_successful_completion') %>
|
||||
</span>
|
||||
<%= f.check_box :value, { class: 'toggle', checked: account_config.value != false, onchange: 'this.form.requestSubmit()' }, '1', '0' %>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
<div class="alert my-4">
|
||||
<%= svg_icon('info_circle', class: 'w-6 h-6') %>
|
||||
<div>
|
||||
<p class="font-bold">Unlock with DocuSeal Pro</p>
|
||||
<p class="font-bold">
|
||||
<%= t('unlock_with_docuseal_pro') %>
|
||||
</p>
|
||||
<p>
|
||||
Display your company name and logo when signing documents.
|
||||
<%= t('display_your_company_name_and_logo_when_signing_documents') %>
|
||||
<br>
|
||||
<a class="link font-medium" target="_blank" href="<%= Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") : "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premise" }.to_query}" %>" data-turbo="false">Learn More</a>
|
||||
<a class="link font-medium" target="_blank" href="<%= Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") : "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premise" }.to_query}" %>" data-turbo="false">
|
||||
<%= t('learn_more') %>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<div class="collapse collapse-plus bg-base-200 overflow-visible">
|
||||
<input type="checkbox">
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
<div class="collapse-title text-xl font-medium capitalize">
|
||||
<div>
|
||||
Signature Request Email
|
||||
<%= t('signature_request_email') %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
@@ -10,13 +10,13 @@
|
||||
<%= f.hidden_field :key %>
|
||||
<%= f.fields_for :value, Struct.new(:subject, :body).new(*f.object.value.values_at('subject', 'body')) do |ff| %>
|
||||
<div class="form-control">
|
||||
<%= ff.label :subject, class: 'label' %>
|
||||
<%= ff.label :subject, t('subject'), class: 'label' %>
|
||||
<%= ff.text_field :subject, required: true, class: 'base-input', dir: 'auto' %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<div class="flex items-center">
|
||||
<%= ff.label :body, class: 'label' %>
|
||||
<span class="tooltip" data-tip="Use following placeholders text: <%= AccountConfig::DEFAULT_VALUES.dig(AccountConfig::SUBMITTER_INVITATION_EMAIL_KEY, 'body').scan(/{{.*?}}/).join(', ') %>">
|
||||
<%= ff.label :body, t('body'), class: 'label' %>
|
||||
<span class="tooltip" data-tip="<%= t('use_following_placeholders_text_') %> <%= AccountConfig::DEFAULT_VALUES[AccountConfig::SUBMITTER_INVITATION_EMAIL_KEY].call['body'].scan(/{.*?}/).join(', ') %>">
|
||||
<%= svg_icon('info_circle', class: 'w-4 h-4') %>
|
||||
</span>
|
||||
</div>
|
||||
@@ -26,7 +26,7 @@
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="form-control pt-2">
|
||||
<%= f.button button_title(title: 'Save', disabled_with: 'Saving'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<div class="collapse collapse-plus bg-base-200 overflow-visible">
|
||||
<input type="checkbox">
|
||||
<div class="collapse-title text-xl font-medium">
|
||||
<div class="collapse-title text-xl font-medium capitalize">
|
||||
<div>
|
||||
Completed Notification Email
|
||||
<%= t('copleted_notification_email') %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
@@ -11,8 +11,8 @@
|
||||
<%= f.fields_for :value, Struct.new(:subject, :body, :attach_audit_log, :attach_documents).new(*f.object.value.values_at('subject', 'body', 'attach_audit_log', 'attach_documents')) do |ff| %>
|
||||
<div class="form-control">
|
||||
<div class="flex items-center">
|
||||
<%= ff.label :subject, class: 'label' %>
|
||||
<span class="tooltip" data-tip="Use following placeholders text: <%= AccountConfig::DEFAULT_VALUES.dig(AccountConfig::SUBMITTER_COMPLETED_EMAIL_KEY, 'subject').scan(/{{.*?}}/).join(', ') %>">
|
||||
<%= ff.label :subject, t('subject'), class: 'label' %>
|
||||
<span class="tooltip" data-tip="<%= t('use_following_placeholders_text_') %> <%= AccountConfig::DEFAULT_VALUES[AccountConfig::SUBMITTER_COMPLETED_EMAIL_KEY].call['subject'].scan(/{.*?}/).join(', ') %>">
|
||||
<%= svg_icon('info_circle', class: 'w-4 h-4') %>
|
||||
</span>
|
||||
</div>
|
||||
@@ -20,8 +20,8 @@
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<div class="flex items-center">
|
||||
<%= ff.label :body, class: 'label' %>
|
||||
<span class="tooltip" data-tip="Use following placeholders text: <%= AccountConfig::DEFAULT_VALUES.dig(AccountConfig::SUBMITTER_COMPLETED_EMAIL_KEY, 'body').scan(/{{.*?}}/).join(', ') %>">
|
||||
<%= ff.label :body, t('body'), class: 'label' %>
|
||||
<span class="tooltip" data-tip="<%= t('use_following_placeholders_text_') %> <%= AccountConfig::DEFAULT_VALUES[AccountConfig::SUBMITTER_COMPLETED_EMAIL_KEY].call['body'].scan(/{.*?}/).join(', ') %>">
|
||||
<%= svg_icon('info_circle', class: 'w-4 h-4') %>
|
||||
</span>
|
||||
</div>
|
||||
@@ -31,19 +31,19 @@
|
||||
</div>
|
||||
<div class="flex items-center justify-between pt-2.5 mx-1">
|
||||
<span>
|
||||
Attach documents
|
||||
<%= t('attach_documents') %>
|
||||
</span>
|
||||
<%= ff.check_box :attach_documents, { checked: ff.object.attach_documents != false, class: 'toggle' }, 'true', 'false' %>
|
||||
</div>
|
||||
<div class="flex items-center justify-between pb-2.5 mx-1">
|
||||
<span>
|
||||
Attach audit log PDF
|
||||
<%= t('attach_audit_log_pdf') %>
|
||||
</span>
|
||||
<%= ff.check_box :attach_audit_log, { checked: ff.object.attach_audit_log != false, class: 'toggle' }, 'true', 'false' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="form-control pt-2">
|
||||
<%= f.button button_title(title: 'Save', disabled_with: 'Saving'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
<div class="flex flex-wrap space-y-4 md:flex-nowrap md:space-y-0">
|
||||
<%= render 'shared/settings_nav' %>
|
||||
<div class="flex-grow max-w-xl mx-auto">
|
||||
<p class="text-4xl font-bold mb-4">Email Templates</p>
|
||||
<p class="text-4xl font-bold mb-4">
|
||||
<%= t('email_templates') %>
|
||||
</p>
|
||||
<div class="space-y-4">
|
||||
<%= render 'signature_request_email_form' %>
|
||||
<%= render 'documents_copy_email_form' %>
|
||||
<%= render 'submitter_completed_email_form' %>
|
||||
</div>
|
||||
<p class="text-4xl font-bold mb-4 mt-8">Company Logo</p>
|
||||
<p class="text-4xl font-bold mb-4 mt-8">
|
||||
<%= t('company_logo') %>
|
||||
</p>
|
||||
<%= render 'logo_form' %>
|
||||
<p class="text-4xl font-bold mb-4 mt-8">Submission Form</p>
|
||||
<p class="text-4xl font-bold mb-4 mt-8">
|
||||
<%= t('submission_form') %>
|
||||
</p>
|
||||
<div class="space-y-4">
|
||||
<%= render 'form_completed_message_form' %>
|
||||
<%= render 'form_completed_button_form' %>
|
||||
|
||||
@@ -1,78 +1,92 @@
|
||||
<div class="flex flex-wrap space-y-4 md:flex-nowrap md:space-y-0">
|
||||
<%= render 'shared/settings_nav' %>
|
||||
<div class="flex-grow max-w-xl mx-auto">
|
||||
<h1 class="text-4xl font-bold mb-4">Profile</h1>
|
||||
<h1 class="text-4xl font-bold mb-4">
|
||||
<%= t('profile') %>
|
||||
</h1>
|
||||
<%= form_for current_user, url: update_contact_settings_profile_index_path, method: :patch, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
||||
<div class="grid md:grid-cols-2 gap-4">
|
||||
<div class="form-control">
|
||||
<%= f.label :first_name, class: 'label' %>
|
||||
<%= f.label :first_name, t('first_name'), class: 'label' %>
|
||||
<%= f.text_field :first_name, required: true, class: 'base-input', dir: 'auto' %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.label :last_name, class: 'label' %>
|
||||
<%= f.label :last_name, t('last_name'), class: 'label' %>
|
||||
<%= f.text_field :last_name, required: true, class: 'base-input', dir: 'auto' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.label :email, 'Email', class: 'label' %>
|
||||
<%= f.label :email, t('email'), class: 'label' %>
|
||||
<%= f.email_field :email, autocomplete: 'off', class: 'base-input' %>
|
||||
</div>
|
||||
<div class="form-control pt-2">
|
||||
<%= f.button button_title(title: 'Update', disabled_with: 'Updating'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('update'), disabled_with: t('updating')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= render 'email_configs' %>
|
||||
<p class="text-2xl font-bold mt-8 mb-4">Signature</p>
|
||||
<p class="text-2xl font-bold mt-8 mb-4">
|
||||
<%= t('signature') %>
|
||||
</p>
|
||||
<% signature = UserConfigs.load_signature(current_user) %>
|
||||
<% if signature %>
|
||||
<div class="flex justify-center mb-4 relative">
|
||||
<%= button_to button_title(title: 'Remove', disabled_with: 'Removing'), user_signature_path, method: :delete, class: 'right-0 top-0 absolute link' %>
|
||||
<%= button_to button_title(title: t('remove'), disabled_with: t('removing')), user_signature_path, method: :delete, class: 'right-0 top-0 absolute link' %>
|
||||
<img src="<%= signature.url %>" style="max-height: 200px; width: auto" width="<%= signature.metadata['width'] %>" height="<%= signature.metadata['height'] %>">
|
||||
</div>
|
||||
<% end %>
|
||||
<a href="<%= edit_user_signature_path %>" data-turbo-frame="modal" class="base-button w-full">Update Signature</a>
|
||||
<p class="text-2xl font-bold mt-8 mb-4">Initials</p>
|
||||
<a href="<%= edit_user_signature_path %>" data-turbo-frame="modal" class="base-button w-full">
|
||||
<%= t('update_signature') %>
|
||||
</a>
|
||||
<p class="text-2xl font-bold mt-8 mb-4">
|
||||
<%= t('initials') %>
|
||||
</p>
|
||||
<% initials = UserConfigs.load_initials(current_user) %>
|
||||
<% if initials %>
|
||||
<div class="flex justify-center mb-4 relative">
|
||||
<%= button_to button_title(title: 'Remove', disabled_with: 'Removing'), user_initials_path, method: :delete, class: 'right-0 top-0 absolute link' %>
|
||||
<%= button_to button_title(title: t('remove'), disabled_with: t('removing')), user_initials_path, method: :delete, class: 'right-0 top-0 absolute link' %>
|
||||
<img src="<%= initials.url %>" style="max-height: 200px; width: auto" width="<%= initials.metadata['width'] %>" height="<%= initials.metadata['height'] %>">
|
||||
</div>
|
||||
<% end %>
|
||||
<a href="<%= edit_user_initials_path %>" data-turbo-frame="modal" class="base-button w-full">Update Initials</a>
|
||||
<a href="<%= edit_user_initials_path %>" data-turbo-frame="modal" class="base-button w-full">
|
||||
<%= t('update_initials') %>
|
||||
</a>
|
||||
<% if true_user == current_user && !current_account.testing? %>
|
||||
<p class="text-2xl font-bold mt-8 mb-4">Change Password</p>
|
||||
<p class="text-2xl font-bold mt-8 mb-4">
|
||||
<%= t('change_password') %>
|
||||
</p>
|
||||
<%= form_for current_user, url: update_password_settings_profile_index_path, method: :patch, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
||||
<div class="form-control">
|
||||
<%= f.label :password, 'New password', class: 'label' %>
|
||||
<%= f.label :password, t('new_password'), class: 'label' %>
|
||||
<%= f.password_field :password, autocomplete: 'off', class: 'base-input' %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.label :password_confirmation, 'Confirm new password', class: 'label' %>
|
||||
<%= f.label :password_confirmation, t('confirm_password'), class: 'label' %>
|
||||
<%= f.password_field :password_confirmation, autocomplete: 'off', class: 'base-input' %>
|
||||
</div>
|
||||
<div class="form-control pt-2">
|
||||
<%= f.button button_title(title: 'Update', disabled_with: 'Updating'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('update'), disabled_with: t('updating')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<p class="text-2xl font-bold mt-8 mb-4">Two-Factor Authentication</p>
|
||||
<p class="text-2xl font-bold mt-8 mb-4">
|
||||
<%= t('two_factor_authentication') %>
|
||||
</p>
|
||||
<div class="space-y-4">
|
||||
<% if current_user.otp_required_for_login %>
|
||||
<p class="flex items-center space-x-1">
|
||||
<%= svg_icon('circle_check', class: 'stroke-success inline flex-none w-5 h-5') %>
|
||||
<span>
|
||||
2FA has been configured.
|
||||
<%= t('2fa_has_been_configured') %>
|
||||
</span>
|
||||
</p>
|
||||
<a href="<%= edit_mfa_setup_path %>" data-turbo-frame="modal" class="white-button w-full !px-8">🔓 Remove 2FA</a>
|
||||
<a href="<%= edit_mfa_setup_path %>" data-turbo-frame="modal" class="white-button w-full !px-8">🔓 <%= t('remove_2fa') %></a>
|
||||
<% else %>
|
||||
<p class="flex items-center space-x-1">
|
||||
<%= svg_icon('info_circle', class: 'stroke-warning inline flex-none w-5 h-5') %>
|
||||
<span>
|
||||
2FA is not configured.
|
||||
<%= t('2fa_is_not_configured') %>
|
||||
</span>
|
||||
</p>
|
||||
<a href="<%= new_mfa_setup_path %>" data-turbo-frame="modal" class="base-button w-full !px-8">🔒 Set up 2FA</a>
|
||||
<a href="<%= new_mfa_setup_path %>" data-turbo-frame="modal" class="base-button w-full !px-8">🔒 <%= t('set_up_2fa') %></a>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<%= render 'start_form/docuseal_logo' %>
|
||||
</div>
|
||||
<div class="text-center text-4xl font-bold">
|
||||
Email has been sent
|
||||
<%= t('email_has_been_sent') %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="max-w-xl mx-auto px-2">
|
||||
<h1 class="flex text-4xl font-bold items-center justify-center my-8 space-x-2">
|
||||
<span>Initial Setup</span>
|
||||
<span><%= t('initial_setup') %></span>
|
||||
<%= svg_icon('waving_hand', class: 'h-10 w-10') %>
|
||||
</h1>
|
||||
<%= form_for '', html: { class: 'space-y-6' }, url: setup_index_path do |f| %>
|
||||
@@ -8,18 +8,18 @@
|
||||
<%= fields_for @user do |ff| %>
|
||||
<div class="grid gap-2 md:grid-cols-2 md:gap-4">
|
||||
<div class="form-control">
|
||||
<%= ff.label :first_name, class: 'label' %>
|
||||
<%= ff.label :first_name, t('first_name'), class: 'label' %>
|
||||
<%= ff.text_field :first_name, required: true, class: 'base-input' %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= ff.label :last_name, class: 'label' %>
|
||||
<%= ff.label :last_name, t('last_name'), class: 'label' %>
|
||||
<%= ff.text_field :last_name, required: true, class: 'base-input' %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= fields_for @user do |ff| %>
|
||||
<div class="form-control">
|
||||
<%= ff.label :email, class: 'label' %>
|
||||
<%= ff.label :email, t('email'), class: 'label' %>
|
||||
<%= ff.email_field :email, required: true, class: 'base-input' %>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -27,13 +27,13 @@
|
||||
<set-timezone data-input-id="account_timezone"></set-timezone>
|
||||
<%= ff.hidden_field :timezone %>
|
||||
<div class="form-control">
|
||||
<%= ff.label :name, 'Company name', class: 'label' %>
|
||||
<%= ff.label :name, t('company_name'), class: 'label' %>
|
||||
<%= ff.text_field :name, required: true, class: 'base-input' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= fields_for @user do |ff| %>
|
||||
<div class="form-control">
|
||||
<%= ff.label :password, class: 'label' %>
|
||||
<%= ff.label :password, t('password'), class: 'label' %>
|
||||
<password-input class="block relative">
|
||||
<%= ff.password_field :password, required: true, placeholder: '************', class: 'base-input w-full pr-10', data: { target: 'password-input.passwordInput' } %>
|
||||
<button data-target="password-input.togglePasswordVisibility" type="button" class="absolute inset-y-0 h-12 right-0 pr-3 flex items-center">
|
||||
@@ -52,7 +52,7 @@
|
||||
<% if @encrypted_config.value.blank? %>
|
||||
<set-origin-url data-input-id="encrypted_config_value"></set-origin-url>
|
||||
<% end %>
|
||||
<%= ff.label :value, 'App URL', class: 'label' %>
|
||||
<%= ff.label :value, t('app_url'), class: 'label' %>
|
||||
<%= ff.text_field :value, required: true, class: 'base-input' %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<div class="mx-auto mt-1.5">
|
||||
<div class="py-3 rounded-2xl flex items-center justify-between mx-4 md:mx-0">
|
||||
<div class="w-full text-center">
|
||||
<span class="font-bold">Demo Environment</span>
|
||||
<span class="font-bold"><%= t('demo_environment') %></span>
|
||||
<br>
|
||||
<a href="<%= new_template_path %>" data-turbo-frame="modal" class="inline underline font-medium">Create a new template</a> document form or
|
||||
<a href="<%= start_form_url(slug: ::Template.first&.slug) %>" target="_blank" class="inline underline font-medium">submit the existing one</a> 😊
|
||||
<%= t('create_a_new_template_document_form_or_submit_the_existing_one_html', new_template_link: new_template_path, start_form_link: start_form_url(slug: ::Template.first&.slug)) %> 😊
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
<%= yield %>
|
||||
</div>
|
||||
</div>
|
||||
<label class="modal-backdrop" for="<%= uuid %>">Close</label>
|
||||
<label class="modal-backdrop" for="<%= uuid %>"><%= t('close') %></label>
|
||||
</div>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<% else %>
|
||||
<div class="flex items-center justify-center space-x-4 mr-1">
|
||||
<%= render 'shared/navbar_buttons' %>
|
||||
<%= link_to 'Settings', settings_profile_index_path, class: 'hidden md:inline-flex font-medium text-lg' %>
|
||||
<%= link_to t('settings'), settings_profile_index_path, class: 'hidden md:inline-flex font-medium text-lg' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="dropdown dropdown-end">
|
||||
@@ -30,14 +30,14 @@
|
||||
<li>
|
||||
<%= link_to settings_profile_index_path, class: 'flex items-center' do %>
|
||||
<%= svg_icon('adjustments', class: 'w-5 h-5 flex-shrink-0 stroke-2') %>
|
||||
<span class="mr-1">Profile</span>
|
||||
<span class="mr-1"><%= t('profile') %></span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% if !Docuseal.demo? && can?(:manage, EncryptedConfig) %>
|
||||
<li>
|
||||
<%= link_to Docuseal.multitenant? ? console_redirect_index_path : Docuseal::CONSOLE_URL, data: { prefetch: false }, class: 'flex items-center' do %>
|
||||
<%= svg_icon('terminal', class: 'w-5 h-5 stroke-2') %>
|
||||
Console
|
||||
<%= t('console') %>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
@@ -45,14 +45,14 @@
|
||||
<li>
|
||||
<%= link_to settings_esign_path, class: 'flex items-center' do %>
|
||||
<%= svg_icon('zoom_check', class: 'w-5 h-5 stroke-2') %>
|
||||
<span class="mr-1">Verify PDF</span>
|
||||
<span class="mr-1"><%= t('verify_pdf') %></span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<li>
|
||||
<%= button_to destroy_user_session_path, method: :delete, data: { turbo: false }, class: 'flex items-center' do %>
|
||||
<%= svg_icon('logout', class: 'w-5 h-5 stroke-2 mr-2 inline') %>
|
||||
<span class="mr-1">Sign out</span>
|
||||
<span class="mr-1"><%= t('sign_out') %></span>
|
||||
<% end %>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -71,7 +71,7 @@
|
||||
<% if Docuseal.multitenant? && !request.path.in?([registration_path, new_registration_path]) %>
|
||||
<%= link_to registration_path({ lang: params[:lang] }.compact_blank), class: 'btn btn-neutral btn-sm btn-outline' do %>
|
||||
<span class="flex items-center justify-center space-x-1">
|
||||
<span class="hidden sm:block"><%= t('create_free_account') %></span>
|
||||
<span class="hidden sm:block capitalize"><%= t('create_free_account') %></span>
|
||||
<span class="md:hidden"><%= t('sign_up') %></span>
|
||||
</span>
|
||||
<% end %>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<%= link_to Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") : "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premise" }.to_query}", class: 'hidden md:inline-flex btn btn-warning btn-sm', data: { prefetch: false } do %>
|
||||
Upgrade
|
||||
<%= t('upgrade') %>
|
||||
<% end %>
|
||||
<% if signed_in? && current_user != true_user %>
|
||||
<span class="hidden md:inline-flex h-3 border-r border-base-content"></span>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<span class="join-item btn btn-disabled !bg-base-200 min-h-full h-10">«</span>
|
||||
<% end %>
|
||||
<span class="join-item btn uppercase min-h-full h-10">
|
||||
Page <%= @pagy.page %>
|
||||
<%= t('page_number', number: @pagy.page) %>
|
||||
</span>
|
||||
<% if @pagy.next %>
|
||||
<%== link.call(@pagy.next, '»', classes: 'join-item btn min-h-full h-10') %>
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
<% if local_assigns[:with_counter] %>
|
||||
<% count = Submitter.where.not(completed_at: nil).distinct.count(:submission_id) %>
|
||||
<% if count > 1 %>
|
||||
<b><%= count %></b> documents signed with
|
||||
<%= t('count_documents_signed_with_html', count:) %>
|
||||
<% else %>
|
||||
Powered by
|
||||
<%= t('powered_by') %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
Powered by
|
||||
<%= t('powered_by') %>
|
||||
<% end %>
|
||||
<a href="<%= Docuseal::PRODUCT_URL %><%= local_assigns[:link_path] %>" class="underline"><%= Docuseal.product_name %></a> - open source documents software
|
||||
</div>
|
||||
|
||||
@@ -2,23 +2,25 @@
|
||||
<menu-active>
|
||||
<ul class="menu px-0">
|
||||
<li class="menu-title py-0 !bg-transparent mb-3 -mt-5"><a href="<%= '/' %>" class="!bg-transparent !text-neutral font-medium">← Back</a></li>
|
||||
<li class="menu-title py-0 !bg-transparent"><span class="!bg-transparent">Settings</span></li>
|
||||
<li class="menu-title py-0 !bg-transparent">
|
||||
<span class="!bg-transparent"><%= t('settings') %></span>
|
||||
</li>
|
||||
<li></li>
|
||||
<li>
|
||||
<%= link_to 'Profile', settings_profile_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
<%= link_to t('profile'), settings_profile_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<li>
|
||||
<%= link_to 'Account', settings_account_path, class: 'text-base hover:bg-base-300' %>
|
||||
<%= link_to t('account'), settings_account_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% unless Docuseal.multitenant? %>
|
||||
<% if can?(:read, EncryptedConfig.new(key: EncryptedConfig::EMAIL_SMTP_KEY, account: current_account)) && ENV['SMTP_ADDRESS'].blank? && true_user == current_user %>
|
||||
<li>
|
||||
<%= link_to 'Email', settings_email_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
<%= link_to t('email'), settings_email_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can?(:read, EncryptedConfig.new(key: EncryptedConfig::FILES_STORAGE_KEY, account: current_account)) && true_user == current_user %>
|
||||
<li>
|
||||
<%= link_to 'Storage', settings_storage_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
<%= link_to t('storage'), settings_storage_index_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can?(:read, EncryptedConfig.new(key: 'submitter_invitation_sms', account: current_account)) && true_user == current_user %>
|
||||
@@ -29,22 +31,22 @@
|
||||
<% end %>
|
||||
<% if can?(:read, AccountConfig) %>
|
||||
<li>
|
||||
<%= link_to 'Notifications', settings_notifications_path, class: 'text-base hover:bg-base-300' %>
|
||||
<%= link_to t('notifications'), settings_notifications_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can?(:read, EncryptedConfig.new(key: EncryptedConfig::ESIGN_CERTS_KEY, account: current_account)) %>
|
||||
<li>
|
||||
<%= link_to 'E-Signature', settings_esign_path, class: 'text-base hover:bg-base-300' %>
|
||||
<%= link_to t('e_signature'), settings_esign_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can?(:read, AccountConfig) %>
|
||||
<li>
|
||||
<%= link_to 'Personalization', settings_personalization_path, class: 'text-base hover:bg-base-300' %>
|
||||
<%= link_to t('personalization'), settings_personalization_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if can?(:read, User) %>
|
||||
<li>
|
||||
<%= link_to 'Users', settings_users_path, class: 'text-base hover:bg-base-300' %>
|
||||
<%= link_to t('users'), settings_users_path, class: 'text-base hover:bg-base-300' %>
|
||||
</li>
|
||||
<% end %>
|
||||
<%= render 'shared/settings_nav_extra' %>
|
||||
@@ -63,21 +65,21 @@
|
||||
<% if !Docuseal.demo? && can?(:manage, EncryptedConfig) && (current_user != true_user || !current_account.linked_account_account) %>
|
||||
<li>
|
||||
<%= link_to Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") : "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premise" }.to_query}", class: 'text-base hover:bg-base-300', data: { prefetch: false } do %>
|
||||
Plans
|
||||
<span class="badge badge-warning">New</span>
|
||||
<%= t('plans') %>
|
||||
<span class="badge badge-warning"><%= t('new') %></span>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% if !Docuseal.demo? && can?(:manage, EncryptedConfig) && (current_user != true_user || !current_account.testing?) %>
|
||||
<li>
|
||||
<%= link_to Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/api") : "#{Docuseal::CONSOLE_URL}/on_premise", class: 'text-base hover:bg-base-300', data: { prefetch: false } do %>
|
||||
<% if Docuseal.multitenant? %> API <% else %> Console <% end %>
|
||||
<% if Docuseal.multitenant? %> API <% else %> <%= t('console') %> <% end %>
|
||||
<% end %>
|
||||
</li>
|
||||
<% if Docuseal.multitenant? %>
|
||||
<li>
|
||||
<%= link_to console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/embedding/form"), class: 'text-base hover:bg-base-300', data: { prefetch: false } do %>
|
||||
Embedding
|
||||
<%= t('embedding') %>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
@@ -92,7 +94,7 @@
|
||||
<%= form_for '', url: testing_account_path, method: current_account.testing? ? :delete : :get, html: { class: 'flex w-full' } do |f| %>
|
||||
<label class="flex items-center text-base hover:bg-base-300 w-full justify-between" for="testing_toggle">
|
||||
<span class="mr-2 w-full">
|
||||
Test Environment
|
||||
<%= t('test_environment') %>
|
||||
</span>
|
||||
<%= f.check_box :testing_toggle, class: 'toggle toggle-sm', checked: current_account.testing?, onchange: 'this.form.requestSubmit()' %>
|
||||
</label>
|
||||
@@ -105,7 +107,7 @@
|
||||
<% if Docuseal.multitenant? || cannot?(:manage, :tenants) %>
|
||||
<div class="mx-4 border-t border-base-300 hidden md:block">
|
||||
<div class="text-sm mt-3">
|
||||
Need help? Ask a question:
|
||||
<%= t('need_help_ask_a_question_') %>
|
||||
</div>
|
||||
<div class="flex mt-3 space-x-3">
|
||||
<div class="tooltip" data-tip="GitHub">
|
||||
@@ -113,13 +115,13 @@
|
||||
<%= svg_icon('brand_github', class: 'w-8 h-8') %>
|
||||
</a>
|
||||
</div>
|
||||
<div class="tooltip" data-tip="Discord Community">
|
||||
<div class="tooltip" data-tip="<%= t('discord_community') %>">
|
||||
<a href="<%= Docuseal::DISCORD_URL %>" target="_blank" class="btn btn-circle btn-primary btn-md">
|
||||
<%= svg_icon('brand_discord', class: 'w-8 h-8') %>
|
||||
</a>
|
||||
</div>
|
||||
<%= capture do %>
|
||||
<div class="tooltip" data-tip="AI Assistant">
|
||||
<div class="tooltip" data-tip="<%= t('ai_assistant') %>">
|
||||
<a href="<%= Docuseal::CHATGPT_URL %>" target="_blank" class="btn btn-circle btn-primary btn-md">
|
||||
<%= svg_icon('brand_openai', class: 'w-8 h-8') %>
|
||||
</a>
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
<% 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">
|
||||
<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') %>Testing Environment
|
||||
<%= svg_icon('code_circle', class: 'w-5 h-5 mr-1') %>
|
||||
<span><%= t('testing_environment') %></span>
|
||||
</a>
|
||||
<span>
|
||||
|
|
||||
</span>
|
||||
<%= button_to testing_account_path, method: :delete, class: 'inline flex' do %>
|
||||
<% title = capture do %>
|
||||
<span class="link">Exit</span>
|
||||
<span class="link"><%= t('exit') %></span>
|
||||
<span>×</span>
|
||||
<% end %>
|
||||
<%= button_title(title:, disabled_with: 'Leave') %>
|
||||
<%= button_title(title:, disabled_with: t('leave')) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<%= 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">
|
||||
<span class="mr-2 text-lg">
|
||||
Test Environment
|
||||
<%= t('test_environment') %>
|
||||
</span>
|
||||
<%= f.check_box :testing_toggle, class: 'toggle', checked: current_account.testing?, onchange: 'this.form.requestSubmit()' %>
|
||||
</label>
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
<div class="alert">
|
||||
<%= svg_icon('info_circle', class: 'w-6 h-6') %>
|
||||
<div>
|
||||
<p class="font-bold">Send signature requests via SMS</p>
|
||||
<p class="font-bold">
|
||||
<%= t('send_signature_requests_via_sms') %>
|
||||
</p>
|
||||
<p class="text-gray-700">
|
||||
Unlock with DocuSeal Pro
|
||||
<%= t('unlock_with_docuseal_pro') %>
|
||||
<br>
|
||||
<a class="link font-medium" target="_blank" href="<%= Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") : "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premise" }.to_query}" %>" data-turbo="false">Learn More</a>
|
||||
<a class="link font-medium" target="_blank" href="<%= Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") : "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premise" }.to_query}" %>" data-turbo="false">
|
||||
<%= t('learn_more') %>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
<div class="alert">
|
||||
<%= svg_icon('info_circle', class: 'w-6 h-6') %>
|
||||
<div>
|
||||
<p class="font-bold">Single Sign On with SAML 2.0</p>
|
||||
<p class="font-bold">
|
||||
<%= t('single_sign_on_with_saml_2_0') %>
|
||||
</p>
|
||||
<p class="text-gray-700">
|
||||
Unlock with DocuSeal Pro
|
||||
<%= t('unlock_with_docuseal_pro') %>
|
||||
<br>
|
||||
<a class="link font-medium" target="_blank" href="<%= Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") : "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premise" }.to_query}" %>" data-turbo="false">Learn More</a>
|
||||
<a class="link font-medium" target="_blank" href="<%= Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") : "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premise" }.to_query}" %>" data-turbo="false">
|
||||
<%= t('learn_more') %>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,13 +11,15 @@
|
||||
</div>
|
||||
<div>
|
||||
<p dir="auto" class="text-lg font-bold mb-1"><%= @submitter.submission.template.name %></p>
|
||||
<p dir="auto" class="text-sm"><%= t('signed_on_time', time: l(@submitter.completed_at.to_date, format: :long)) %></p>
|
||||
<p dir="auto" class="text-sm">
|
||||
<%= t(@submitter.with_signature_fields? ? 'signed_on_time' : 'completed_on_time', time: l(@submitter.completed_at.to_date, format: :long)) %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div dir="auto" class="text-center text-2xl font-semibold">
|
||||
<%= t('form_has_been_submitted_already') %>
|
||||
<%= @submitter.with_signature_fields? ? t('document_has_been_signed_already') : t('form_has_been_submitted_already') %>
|
||||
</div>
|
||||
<% if Docuseal.multitenant? || Accounts.can_send_emails?(@submitter.account) %>
|
||||
<toggle-submit class="block">
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= fff.label :endpoint, 'Endpoint (optional)', class: 'label' %>
|
||||
<%= fff.label :endpoint, "Endpoint (#{t('optional')})", class: 'label' %>
|
||||
<%= fff.text_field :endpoint, value: configs['endpoint'], type: :url, class: 'base-input' %>
|
||||
<label class="label">
|
||||
<span class="label-text-alt">For AWS S3 compatible APIs like Minio.</span>
|
||||
<span class="label-text-alt"><%= t('for_aws_s3_compatible_apis_like_minio') %></span>
|
||||
</label>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
<div class="alert my-4">
|
||||
<%= svg_icon('info_circle', class: 'stroke-current flex-shrink-0 w-6 h-6') %>
|
||||
<div>
|
||||
<p class="font-bold">Store all files on disk</p>
|
||||
<p class="font-bold">
|
||||
<%= t('store_all_files_on_disk') %>
|
||||
</p>
|
||||
<p class="text-gray-700">
|
||||
No configs are needed but make sure your disk is persistent
|
||||
<%= t('no_configs_are_needed_but_make_sure_your_disk_is_persistent') %>
|
||||
<br>
|
||||
<i>(not suitable for Heroku and other PaaS)</i>
|
||||
<i>(<%= t('not_suitable_for_heroku_and_other_paas') %>)</i>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<div class="flex flex-wrap space-y-4 md:flex-nowrap md:space-y-0">
|
||||
<%= render 'shared/settings_nav' %>
|
||||
<div class="flex-grow max-w-xl mx-auto">
|
||||
<h1 class="text-4xl font-bold mb-4">Storage</h1>
|
||||
<h1 class="text-4xl font-bold mb-4">
|
||||
<%= t('storage') %>
|
||||
</h1>
|
||||
<% value = @encrypted_config.value || { 'service' => 'disk' } %>
|
||||
<% configs = value['configs'] || {} %>
|
||||
<%= form_for @encrypted_config, url: settings_storage_index_path, method: :post, html: { autocomplete: 'off', class: 'w-full' } do |f| %>
|
||||
@@ -29,7 +31,7 @@
|
||||
<%= render 'azure_form', f:, configs:, value: %>
|
||||
</disable-hidden>
|
||||
<div class="form-control">
|
||||
<%= f.button button_title(title: 'Save', disabled_with: 'Saving'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
<div class="alert">
|
||||
<%= svg_icon('info_circle', class: 'w-6 h-6') %>
|
||||
<div>
|
||||
<p class="font-bold">Bulk send from Excel XLSX or CSV</p>
|
||||
<p class="font-bold">
|
||||
<%= t('bulk_send_from_excel_xlsx_or_csv') %>
|
||||
</p>
|
||||
<p class="text-gray-700">
|
||||
Unlock with DocuSeal Pro
|
||||
<%= t('unlock_with_docuseal_pro') %>
|
||||
<br>
|
||||
<a class="link font-medium" target="_blank" href="<%= Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") : "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premise" }.to_query}" %>" data-turbo="false">Learn More</a>
|
||||
<a class="link font-medium" target="_blank" href="<%= Docuseal.multitenant? ? console_redirect_index_path(redir: "#{Docuseal::CONSOLE_URL}/plans") : "#{Docuseal::CLOUD_URL}/sign_up?#{{ redir: "#{Docuseal::CONSOLE_URL}/on_premise" }.to_query}" %>" data-turbo="false">
|
||||
<%= t('learn_more') %>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<% if params[:selfsign].blank? %>
|
||||
<a href="#" class="btn btn-primary btn-sm w-full flex items-center justify-center" data-action="click:dynamic-list#addItem">
|
||||
<%= svg_icon('user_plus', class: 'w-4 h-4 stroke-2') %>
|
||||
<span>Add New</span>
|
||||
<span><%= t('add_new') %></span>
|
||||
</a>
|
||||
<% end %>
|
||||
</dynamic-list>
|
||||
@@ -54,6 +54,6 @@
|
||||
<%= render 'send_sms', f: %>
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= f.button button_title(title: 'Add Recipients'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('add_recipients')), class: 'base-button' %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<emails-textarea data-bulk-enabled="<%= Docuseal.demo? || !Docuseal.multitenant? || can?(:manage, :bulk_send) %>" data-limit="<%= Docuseal.multitenant? ? (can?(:manage, :bulk_send) ? 40 : 1) : nil %>">
|
||||
<submitters-autocomplete data-field="email" class="block relative">
|
||||
<autoresize-textarea>
|
||||
<%= f.text_area :emails, required: true, class: 'base-textarea w-full !text-lg', placeholder: 'Type emails here...', rows: 2 %>
|
||||
<%= f.text_area :emails, required: true, class: 'base-textarea w-full !text-lg', placeholder: "#{t('type_emails_here')}...", rows: 2 %>
|
||||
</autoresize-textarea>
|
||||
</submitters-autocomplete>
|
||||
</emails-textarea>
|
||||
@@ -29,7 +29,7 @@
|
||||
<input type="hidden" name="submission[1][submitters][][uuid]" value="<%= item['uuid'] %>">
|
||||
<submitters-autocomplete data-field="email">
|
||||
<linked-input data-target-id="<%= "email_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||
<%= tag.input type: 'email', multiple: true, name: 'submission[1][submitters][][email]', autocomplete: 'off', class: 'base-input-slim w-full', placeholder: '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-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']}" %>
|
||||
</linked-input>
|
||||
</submitters-autocomplete>
|
||||
</submitter-item>
|
||||
@@ -41,7 +41,7 @@
|
||||
<% if params[:selfsign].blank? %>
|
||||
<a href="#" class="btn btn-primary btn-sm w-full flex items-center justify-center" data-action="click:dynamic-list#addItem">
|
||||
<%= svg_icon('user_plus', class: 'w-4 h-4 stroke-2') %>
|
||||
<span>Add New</span>
|
||||
<span><%= t('add_new') %></span>
|
||||
</a>
|
||||
<% end %>
|
||||
</dynamic-list>
|
||||
@@ -52,7 +52,7 @@
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= content_for(:submit_button) || capture do %>
|
||||
<%= f.button button_title(title: 'Add Recipients'), class: 'base-button' %>
|
||||
<%= f.button button_title(title: t('add_recipients')), class: 'base-button' %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -2,12 +2,16 @@
|
||||
<div class="">
|
||||
<input id="api_key" type="text" value="<%= start_form_url(slug: template.slug) %>" class="input font-mono input-bordered w-full bg-white" autocomplete="off" readonly>
|
||||
<div class="mt-4">
|
||||
<%= render 'shared/clipboard_copy', icon: 'copy', text: start_form_url(slug: template.slug), class: 'base-button w-full block', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy', copied_title: 'Copied' %>
|
||||
<%= render 'shared/clipboard_copy', icon: 'copy', text: start_form_url(slug: template.slug), class: 'base-button w-full block', icon_class: 'w-6 h-6 text-white', copy_title: t('copy'), copied_title: t('copied') %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="divider uppercase normal-case mt-5 mb-6 text-neutral-700">Or embed on your website</div>
|
||||
<div class="divider uppercase normal-case mt-5 mb-6 text-neutral-700">
|
||||
<%= t('or_embed_on_your_website') %>
|
||||
</div>
|
||||
<%= render 'templates/embedding', template: %>
|
||||
<div class="mt-4">
|
||||
<a href="#" class="link text-center block" data-action="click:turbo-modal#close">Close</a>
|
||||
<a href="#" class="link text-center block" data-action="click:turbo-modal#close">
|
||||
<%= t('close') %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user