pull/381/head
Oleksandr Turchyn 1 year ago committed by Oleksandr Turchyn
parent 3c60fb4ee6
commit e9d728fa4a

@ -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

@ -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

@ -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_deleted')
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

@ -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'))
}
})
}

@ -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>

@ -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.dig(AccountConfig::SUBMITTER_DOCUMENTS_COPY_EMAIL_KEY, '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.dig(AccountConfig::SUBMITTER_INVITATION_EMAIL_KEY, '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.dig(AccountConfig::SUBMITTER_COMPLETED_EMAIL_KEY, '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.dig(AccountConfig::SUBMITTER_COMPLETED_EMAIL_KEY, '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">&larr; 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>&times;</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>

@ -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>

@ -21,13 +21,13 @@
<input type="hidden" name="submission[1][submitters][][uuid]" value="<%= item['uuid'] %>">
<submitters-autocomplete data-field="phone">
<linked-input data-target-id="<%= "phone_phone_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
<%= tag.input type: 'tel', pattern: '^\+[0-9\s\-]+$', oninvalid: "this.value ? this.setCustomValidity('Use internatioanl format: +1xxx...') : ''", oninput: "this.setCustomValidity('')", name: 'submission[1][submitters][][phone]', autocomplete: 'off', class: 'base-input-slim w-full', placeholder: 'Phone', required: index.zero?, id: "phone_phone_#{item['uuid']}" %>
<%= tag.input type: 'tel', pattern: '^\+[0-9\s\-]+$', oninvalid: "this.value ? this.setCustomValidity('Use internatioanl format: +1xxx...') : ''", oninput: "this.setCustomValidity('')", name: 'submission[1][submitters][][phone]', autocomplete: 'off', class: 'base-input-slim w-full', placeholder: t('phone'), required: index.zero?, id: "phone_phone_#{item['uuid']}" %>
</linked-input>
</submitters-autocomplete>
<% if submitters.size > 1 %>
<submitters-autocomplete data-field="name">
<linked-input data-target-id="<%= "phone_name_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
<input type="text" name="submission[1][submitters][][name]" autocomplete="off" class="base-input-slim mt-1.5 w-full" placeholder="Name (optional)" value="<%= (params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : '' %>" dir="auto" id="phone_name_<%= item['uuid'] %>">
<input type="text" name="submission[1][submitters][][name]" autocomplete="off" class="base-input-slim mt-1.5 w-full" placeholder="<%= "#{t('name')} (#{t('optional')})" %>" value="<%= (params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : '' %>" dir="auto" id="phone_name_<%= item['uuid'] %>">
</linked-input>
</submitters-autocomplete>
<% end %>
@ -36,7 +36,7 @@
<div class="form-control flex">
<submitters-autocomplete data-field="name">
<linked-input data-target-id="<%= "phone_name_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
<input type="text" name="submission[1][submitters][][name]" autocomplete="off" class="base-input-slim w-full" placeholder="Name (optional)" value="<%= (params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : '' %>" dir="auto" id="phone_name_<%= item['uuid'] %>">
<input type="text" name="submission[1][submitters][][name]" autocomplete="off" class="base-input-slim w-full" placeholder="<%= "#{t('name')} (#{t('optional')})" %>" value="<%= (params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : '' %>" dir="auto" id="phone_name_<%= item['uuid'] %>">
</linked-input>
</submitters-autocomplete>
</div>
@ -50,7 +50,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>
@ -59,6 +59,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 %>

@ -3,13 +3,13 @@
<div class="flex justify-between items-center">
<%= f.label :send_email, for: uuid = SecureRandom.uuid, class: 'flex items-center cursor-pointer' do %>
<%= f.check_box :send_email, id: uuid, class: 'base-checkbox', disabled: !can_send_emails, checked: can_send_emails %>
<span class="label">Send emails</span>
<span class="label"><%= t('send_emails') %></span>
<% end %>
<div>
<% if can_send_emails %>
<label>
<%= f.check_box :is_custom_message, onchange: "[this.form.querySelector('#message_field').classList.toggle('hidden', !event.currentTarget.checked)]", checked: false, class: 'hidden peer' %>
<span class="link peer-checked:hidden">Edit message</span>
<span class="link peer-checked:hidden"><%= t('edit_message') %></span>
</label>
<% end %>
<%= render 'email_stats' %>
@ -19,11 +19,13 @@
<div class="alert my-4">
<%= svg_icon('info_circle', class: 'w-6 h-6') %>
<div>
<p class="font-bold">SMTP not Configured</p>
<p class="font-bold"><%= t('smtp_not_configured') %></p>
<p class="text-gray-700">
Configure SMTP settings in order to send emails:
<%= t('configure_smtp_settings_in_order_to_send_emails_') %>
<br>
<a class="link font-medium" data-turbo-frame="_top" href="<%= settings_email_index_path %>">Go to SMTP settings</a>
<a class="link font-medium" data-turbo-frame="_top" href="<%= settings_email_index_path %>">
<%= t('go_to_smtp_setting') %>
</a>
</p>
</div>
</div>
@ -34,13 +36,13 @@
<div class="card-body">
<div class="form-control space-y-2">
<div class="form-control">
<%= f.label :subject, class: 'label' %>
<%= f.label :subject, t('subject'), class: 'label' %>
<%= f.text_field :subject, value: @template.preferences['request_email_subject'].presence || config.value['subject'], required: true, class: '!text-sm base-input w-full', dir: 'auto' %>
</div>
<div class="form-control">
<div class="flex items-center">
<%= f.label :message, 'Body', class: 'label' %>
<span class="tooltip tooltip-right" data-tip="Use following placeholders text: <%= AccountConfig::DEFAULT_VALUES.dig(AccountConfig::SUBMITTER_INVITATION_EMAIL_KEY, 'body').scan(/{{.*?}}/).join(', ') %>">
<%= f.label :message, t('body'), class: 'label' %>
<span class="tooltip tooltip-right" data-tip="<%= t('use_following_placeholders_text_') %> <%= AccountConfig::DEFAULT_VALUES.dig(AccountConfig::SUBMITTER_INVITATION_EMAIL_KEY, 'body').scan(/{{.*?}}/).join(', ') %>">
<%= svg_icon('info_circle', class: 'w-4 h-4') %>
</span>
</div>
@ -49,7 +51,7 @@
</autoresize-textarea>
<label for="<%= uuid = SecureRandom.uuid %>" class="flex items-center cursor-pointer">
<%= check_box_tag :save_message, id: uuid, class: 'base-checkbox', checked: false %>
<span class="label">Save as default template message</span>
<span class="label"><%= t('save_as_default_template_message') %></span>
</label>
</div>
<%= render 'message_fields' %>

@ -1,5 +1,5 @@
<div class="mt-2 mb-1">
<div class="tooltip w-full" data-tip="Unlock with Enterpise">
<%= link_to submitter.sent_at? ? 'Re-send SMS' : 'Send SMS', 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: 'btn btn-sm btn-primary text-gray-400 w-full' %>
<div class="tooltip w-full" data-tip="<%= t('unlock_with_docuseal_pro') %>">
<%= link_to submitter.sent_at? ? t('re_send_sms') : t('send_sms'), 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: 'btn btn-sm btn-primary text-gray-400 w-full' %>
</div>
</div>

@ -2,8 +2,8 @@
<div class="form-control">
<%= f.label :preserve_order, for: uuid = SecureRandom.uuid, class: 'flex items-center cursor-pointer' do %>
<%= f.check_box :preserve_order, id: uuid, class: 'base-checkbox', checked: template.submissions.last&.submitters_order.in?(['preserved', nil]) %>
<span class="label">Preserve order</span>
<span class="tooltip" data-tip="When checked, notifications will be sent to the second party once the form is completed by the previous party. Uncheck this option to send notifications to all parties simultaneously right away.">
<span class="label"><%= t('preserve_order') %></span>
<span class="tooltip" data-tip="<%= t('when_checked_notifications_will_be_sent_to_the_second_party_once_the_form_is_completed_by_the_previous_party') %>">
<%= svg_icon('info_circle', class: 'w-4 h-4') %>
</span>
<% end %>

@ -1,4 +1,4 @@
<%= render 'shared/turbo_modal_large', title: params[:selfsign] ? 'Add Recipients' : 'Add New Recipients' do %>
<%= render 'shared/turbo_modal_large', title: params[:selfsign] ? t('add_recipients') : 'Add New Recipients' do %>
<% options = [['via Email', 'email'], ['via Phone', 'phone'], %w[Detailed detailed], ['Upload List', 'list']].compact %>
<toggle-visible data-element-ids="<%= options.map(&:last).to_json %>" class="relative text-center px-2 mt-4 block">
<div class="join">

@ -12,9 +12,7 @@
<% if @submission.audit_trail.present? %>
<a href="<%= ActiveStorage::Blob.proxy_url(@submission.audit_trail.blob, expires_at: 4.hours.from_now) %>" class="white-button" target="_blank">
<%= svg_icon('external_link', class: 'w-6 h-6') %>
<span class="hidden md:inline">
Audit Log
</span>
<span class="hidden md:inline"><%= t('audit_log') %></span>
</a>
<% end %>
<% if last_submitter = @submission.submitters.to_a.select(&:completed_at?).max_by(&:completed_at) %>
@ -23,11 +21,11 @@
<download-button data-src="<%= submitter_download_index_path(last_submitter.slug, { sig: params[:sig], combined: is_combined_enabled }.compact) %>" class="base-button <%= '!rounded-r-none !pr-2' if is_all_completed && !is_combined_enabled %>">
<span class="flex items-center justify-center space-x-2" data-target="download-button.defaultButton">
<%= svg_icon('download', class: 'w-6 h-6') %>
<span class="hidden md:inline">Download</span>
<span class="hidden md:inline"><%= t('download') %></span>
</span>
<span class="flex items-center justify-center space-x-2 hidden" data-target="download-button.loadingButton">
<%= svg_icon('loader', class: 'w-6 h-6 animate-spin') %>
<span class="hidden md:inline">Downloading</span>
<span class="hidden md:inline"><%= t('downloading') %></span>
</span>
</download-button>
<% if is_all_completed && !is_combined_enabled %>
@ -42,11 +40,11 @@
<download-button data-src="<%= submitter_download_index_path(last_submitter.slug, { sig: params[:sig], combined: true }.compact) %>" class="flex items-center">
<span class="flex items-center justify-center space-x-2" data-target="download-button.defaultButton">
<%= svg_icon('download', class: 'w-6 h-6 flex-shrink-0') %>
<span class="whitespace-nowrap">Download combined PDF</span>
<span class="whitespace-nowrap"><%= t('download_combined_pdf') %></span>
</span>
<span class="flex items-center justify-center space-x-2 hidden" data-target="download-button.loadingButton">
<%= svg_icon('loader', class: 'w-6 h-6 animate-spin') %>
<span>Downloading</span>
<span><%= t('downloading') %></span>
</span>
</download-button>
</li>
@ -144,25 +142,25 @@
<%= svg_icon('writing', class: 'w-5 h-5') %>
<span>
<% if submitter&.declined_at? %>
Declined on <%= l(submitter.declined_at.in_time_zone(@submission.account.timezone), format: :short, locale: @submission.account.locale) %>
<%= t('declined_on_time', time: l(submitter.declined_at.in_time_zone(@submission.account.timezone), format: :short, locale: @submission.account.locale)) %>
<% elsif submitter %>
<%= submitter.completed_at? ? l(submitter.completed_at.in_time_zone(@submission.account.timezone), format: :long, locale: @submission.account.locale) : 'Not completed yet' %>
<%= submitter.completed_at? ? l(submitter.completed_at.in_time_zone(@submission.account.timezone), format: :long, locale: @submission.account.locale) : t('not_copleted_yet') %>
<% else %>
Not invited yet
<%= t('not_invited_yet') %>
<% end %>
</span>
</div>
<% if submitter&.declined_at? %>
<div class="flex items-center space-x-1 mt-1">
<span>
Reason:
<%= t('Reason') %>:
<%= simple_format(h(submitter.submission_events.find_by(event_type: :decline_form).data['reason'])) %>
</span>
</div>
<% end %>
<% if signed_in? && submitter && submitter.email && !submitter.completed_at && !@submission.archived_at? && can?(:update, submitter) && Accounts.can_send_emails?(current_account) && !@submission.expired? && !submitter.declined_at? %>
<div class="mt-2 mb-1">
<%= button_to button_title(title: submitter.sent_at? ? 'Re-send Email' : 'Send Email', disabled_with: 'Sending'), submitter_send_email_index_path(submitter_slug: submitter.slug), class: 'btn btn-sm btn-primary w-full' %>
<%= button_to button_title(title: submitter.sent_at? ? 'Re-send Email' : 'Send Email', disabled_with: t('sending')), submitter_send_email_index_path(submitter_slug: submitter.slug), class: 'btn btn-sm btn-primary w-full' %>
</div>
<% end %>
<% if signed_in? && submitter && submitter.phone && !submitter.completed_at && !@submission.archived_at? && can?(:update, submitter) && !@submission.expired? && !submitter.declined_at? %>
@ -171,7 +169,7 @@
<% if signed_in? && submitter && !submitter.completed_at? && !@submission.archived_at? && can?(:create, submitter) && !@submission.expired? && !submitter.declined_at? %>
<div class="mt-2 mb-1">
<a class="btn btn-sm btn-primary w-full" target="_blank" href="<%= submit_form_path(slug: submitter.slug) %>">
Sign In-person
<%= t('sign_in_person') %>
</a>
</div>
<% end %>
@ -222,11 +220,11 @@
<input type="checkbox" class="peer hidden" onclick="[document_view.classList.toggle('hidden'), parties_view.classList.toggle('hidden')]">
<span class="peer-checked:hidden flex items-center space-x-2">
<%= svg_icon('users', class: 'w-8 h-8') %>
<span>Signers</span>
<span><%= t('signers') %></span>
</span>
<span class="hidden peer-checked:flex items-center">
<%= svg_icon('chevron_left', class: 'w-8 h-8') %>
<span>Back</span>
<span><%= t('back') %></span>
</span>
</label>
</div>

@ -1,15 +1,15 @@
<div>
<%= link_to root_path do %>
&larr;
<span>Back to Active</span>
<span><%= t('back_to_active') %></span>
<% end %>
</div>
<div class="flex justify-between mb-4 items-center">
<div>
<h1 class="text-4xl font-bold md:block <%= 'hidden' if params[:q].present? %>">Submissions <span class="badge badge-outline badge-lg align-middle">Archived</span></h1>
<h1 class="text-4xl font-bold md:block <%= 'hidden' if params[:q].present? %>"><%= t('submissions') %> <span class="badge badge-outline badge-lg align-middle"><%= t('archived') %></span></h1>
</div>
<% if params[:q].present? || @pagy.pages > 1 %>
<%= render 'shared/search_input', placeholder: 'Search...' %>
<%= render 'shared/search_input', placeholder: "#{t('search')}..." %>
<% end %>
</div>
<% if @pagy.count > 0 %>
@ -19,7 +19,7 @@
<% elsif params[:q].present? %>
<div class="text-center">
<div class="mt-16 text-3xl font-semibold">
Submissions not Found
<%= t('submissions_not_found') %>
</div>
</div>
<% end %>

@ -5,7 +5,9 @@
<div class="mr-2">
<%= render 'dashboard/toggle_view', selected: 'submissions' %>
</div>
<h1 class="text-2xl md:text-3xl sm:text-4xl font-bold md:block <%= 'hidden' if params[:q].present? %>">Submissions</h1>
<h1 class="text-2xl md:text-3xl sm:text-4xl font-bold md:block <%= 'hidden' if params[:q].present? %>">
<%= t('submissions') %>
</h1>
</div>
<div class="flex space-x-2">
<% if params[:q].present? || @pagy.pages > 1 %>
@ -17,7 +19,7 @@
</span>
<%= link_to new_template_path, class: 'white-button !border gap-2', data: { turbo_frame: :modal } do %>
<%= svg_icon('plus', class: 'w-6 h-6 stroke-2') %>
<span class="hidden md:block">Create</span>
<span class="hidden md:block"><%= t('create') %></span>
<% end %>
<% end %>
</div>
@ -25,7 +27,7 @@
<% view_archived_html = capture do %>
<% if current_account.submissions.where.not(archived_at: nil).exists? %>
<div>
<a href="<%= submissions_archived_index_path %>" class="link text-sm">View Archived</a>
<a href="<%= submissions_archived_index_path %>" class="link text-sm"><%= t('view_archived') %></a>
</div>
<% end %>
<% end %>
@ -34,19 +36,19 @@
<a href="<%= url_for(params.to_unsafe_h.except(:status)) %>" class="<%= params[:status].blank? ? 'border-neutral-700' : 'border-neutral-300' %> flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-48 hover:border-neutral-600">
<div class="flex items-center space-x-1">
<%= svg_icon('list', class: 'w-5 h-5') %>
<span class="font-normal">All</span>
<span class="font-normal"><%= t('all') %></span>
</div>
</a>
<a href="<%= url_for(params.to_unsafe_h.merge(status: :pending)) %>" class="<%= params[:status] == 'pending' ? 'border-neutral-700' : 'border-neutral-300' %> flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-48 hover:border-neutral-600">
<div class="flex items-center space-x-1">
<%= svg_icon('clock', class: 'w-5 h-5') %>
<span class="font-normal">Pending</span>
<span class="font-normal"><%= t('pending') %></span>
</div>
</a>
<a href="<%= url_for(params.to_unsafe_h.merge(status: :completed)) %>" class="<%= params[:status] == 'completed' ? 'border-neutral-700' : 'border-neutral-300' %> flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-48 hover:border-neutral-600">
<div class="flex items-center space-x-1">
<%= svg_icon('circle_check', class: 'w-5 h-5') %>
<span class="font-normal">Completed</span>
<span class="font-normal"><%= t('completed') %></span>
</div>
</a>
</div>
@ -70,7 +72,7 @@
<% elsif params[:q].present? %>
<div class="text-center">
<div class="mt-16 text-3xl font-semibold">
Submissions not Found
<%= t('submissions_not_found') %>
</div>
</div>
<% end %>

@ -10,7 +10,7 @@
</div>
<div class="flex flex-col">
<span class="mb-1 text-lg font-semibold">XLSX</span>
<p class="text-sm"> Primarily opened with Microsoft Excel. Other options include Google Sheets, LibreOffice Calc, and OpenOffice Calc.</p>
<p class="text-sm"><%= t('primarily_opened_with_microsoft_excel_other_options_include_google_sheets_libreoffice_calc_and_openoffice_calc') %></p>
</div>
</div>
<% end %>
@ -24,7 +24,7 @@
</div>
<div class="flex flex-col">
<span class="mb-1 text-lg font-semibold">CSV</span>
<p class="text-sm">Can be opened with Microsoft Excel, Google Sheets, or any text editor like Notepad.</p>
<p class="text-sm"><%= t('can_be_opened_with_microsoft_excel_google_sheets_or_any_text_editor_like_notepad') %></p>
</div>
</div>
<% end %>

@ -41,7 +41,7 @@
<% end %>
<% if Docuseal.multitenant? %>
<div>
<%= link_to 'Create free account', registration_path, class: 'white-button w-full' %>
<%= link_to t('create_free_account'), registration_path, class: 'white-button w-full' %>
</div>
<% end %>
</div>

@ -19,31 +19,31 @@
<%= form_for '', url: submit_form_path(params[:slug]), html: { style: 'max-width: 900px; width: 100%; margin-bottom: 120px' }, method: :put do |f| %>
<input value="" type="hidden" name="values[<%= (@submitter.submission.template_fields || @submitter.template.fields).find { |f| f['type'] == 'signature' && f['uuid'].starts_with?(params[:f]) }['uuid'] %>]">
<div class="font-semibold text-4xl text-center w-full mb-2">
Draw Signature
<%= t('draw_signature') %>
</div>
<div class="w-full bg-white rounded-2xl border relative" style="height: 300px">
<canvas class="w-full"></canvas>
<button aria-label="Clear" class="btn btn-ghost btn-sm font-medium top-0 right-0 absolute mt-1 mr-1">
<button aria-label="<%= t('clear') %>" class="btn btn-ghost btn-sm font-medium top-0 right-0 absolute mt-1 mr-1">
<%= svg_icon('reload', class: 'w-5 h-5') %>
<span class="inline">Clear</span>
<span class="inline"><%= t('clear') %></span>
</button>
</div>
<div class="mt-4">
<button disabled class="base-button w-full">
Submit
<%= t('submit') %>
</button>
<%= f.button button_title(title: 'Submit'), class: 'base-button w-full', style: 'display: none' %>
<%= f.button button_title(title: t('submit')), class: 'base-button w-full', style: 'display: none' %>
</div>
<% end %>
<div id="success" class="text-center p-2 hidden" style="margin-bottom: 100px">
<div class="flex items-center space-x-1 items-center justify-center text-2xl font-semibold mb-2">
<%= svg_icon('circle_check', class: 'text-green-600') %>
<span>
Signature Uploaded
<%= t('signature_uploaded') %>
</span>
</div>
<div>
Return back to your desktop device to complete the form or <a class="link" href="<%= submit_form_path(params[:slug]) %>">continue on mobile</a>
<%= t('return_back_to_your_desktop_device_to_complete_the_form_or_continue_on_mobile_html', link: submit_form_path(params[:slug])) %>
</div>
</div>
</draw-signature>

@ -1,10 +1,10 @@
<%= render 'shared/turbo_modal', title: 'Rename Folder' do %>
<%= render 'shared/turbo_modal', title: t('rename_folder') do %>
<%= form_for @template_folder, url: folder_path(@template_folder), data: { turbo_frame: :_top }, html: { autocomplete: :off } do |f| %>
<div class="form-control my-6">
<%= f.text_field :name, required: true, placeholder: 'Folder Name...', class: 'base-input w-full', autofocus: true, dir: 'auto' %>
<%= f.text_field :name, required: true, placeholder: "#{t('folder_name')}...", class: 'base-input w-full', autofocus: true, dir: 'auto' %>
</div>
<div class="form-control">
<%= f.button button_title(title: 'Rename', disabled_with: 'Saving'), class: 'base-button' %>
<%= f.button button_title(title: t('rename'), disabled_with: t('saving')), class: 'base-button' %>
</div>
<% end %>
<% end %>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save