mirror of
https://github.com/docusealco/docuseal
synced 2026-11-04 14:42:32 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26749a4dbc | ||
|
|
14915d37b4 | ||
|
|
16d6d58efb | ||
|
|
b2b97a313a | ||
|
|
2974e6a64f | ||
|
|
dae34d0aa5 | ||
|
|
e9d0671184 | ||
|
|
897e33bf6a | ||
|
|
f37e93a409 | ||
|
|
561ac63c93 | ||
|
|
149e4be07a | ||
|
|
eb98dc9e06 | ||
|
|
ce7d965358 | ||
|
|
bb73024859 | ||
|
|
631a442e2a | ||
|
|
20a082ae8e | ||
|
|
154d706be1 | ||
|
|
aaae257c75 | ||
|
|
ec944a2283 | ||
|
|
69d63ecffe | ||
|
|
06a1e2992d | ||
|
|
ec9293bac0 | ||
|
|
8bf727c43c | ||
|
|
708b8afdf5 | ||
|
|
6f7b9b1ebf | ||
|
|
4f48c4fd9f | ||
|
|
9dac90e6cc |
No files matched your search
@@ -1,9 +1,17 @@
|
|||||||
name: Build Docker Images
|
name: Build Docker Images
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
workflow_dispatch:
|
||||||
tags:
|
inputs:
|
||||||
- "*.*.*"
|
version:
|
||||||
|
description: Version
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
image:
|
||||||
|
description: QEMU image
|
||||||
|
type: string
|
||||||
|
required: false
|
||||||
|
default: tonistiigi/binfmt:latest
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -16,23 +24,23 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
-
|
- name: Docker meta
|
||||||
name: Docker meta
|
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v4
|
uses: docker/metadata-action@v4
|
||||||
with:
|
with:
|
||||||
images: |
|
images: docuseal/docuseal
|
||||||
docuseal/docuseal
|
tags: type=semver,pattern={{version}}
|
||||||
tags: |
|
|
||||||
type=semver,pattern={{version}}
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v3
|
||||||
|
with:
|
||||||
|
image: ${{ inputs.image }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Create .version file
|
- name: Create .version file
|
||||||
run: echo ${{ github.ref_name }} > .version
|
run: echo ${{ inputs.version }} > .version
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
|
|||||||
+8
-8
@@ -319,7 +319,7 @@ GEM
|
|||||||
method_source (1.1.0)
|
method_source (1.1.0)
|
||||||
mini_magick (4.13.2)
|
mini_magick (4.13.2)
|
||||||
mini_mime (1.1.5)
|
mini_mime (1.1.5)
|
||||||
mini_portile2 (2.8.8)
|
mini_portile2 (2.8.9)
|
||||||
minitest (5.25.4)
|
minitest (5.25.4)
|
||||||
msgpack (1.7.5)
|
msgpack (1.7.5)
|
||||||
multi_json (1.15.0)
|
multi_json (1.15.0)
|
||||||
@@ -338,18 +338,18 @@ GEM
|
|||||||
net-smtp (0.5.0)
|
net-smtp (0.5.0)
|
||||||
net-protocol
|
net-protocol
|
||||||
nio4r (2.7.4)
|
nio4r (2.7.4)
|
||||||
nokogiri (1.18.8)
|
nokogiri (1.18.9)
|
||||||
mini_portile2 (~> 2.8.2)
|
mini_portile2 (~> 2.8.2)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.18.8-aarch64-linux-gnu)
|
nokogiri (1.18.9-aarch64-linux-gnu)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.18.8-aarch64-linux-musl)
|
nokogiri (1.18.9-aarch64-linux-musl)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.18.8-arm64-darwin)
|
nokogiri (1.18.9-arm64-darwin)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.18.8-x86_64-linux-gnu)
|
nokogiri (1.18.9-x86_64-linux-gnu)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.18.8-x86_64-linux-musl)
|
nokogiri (1.18.9-x86_64-linux-musl)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
oj (3.16.8)
|
oj (3.16.8)
|
||||||
bigdecimal (>= 3.0)
|
bigdecimal (>= 3.0)
|
||||||
@@ -541,7 +541,7 @@ GEM
|
|||||||
stringio (3.1.2)
|
stringio (3.1.2)
|
||||||
strip_attributes (1.14.1)
|
strip_attributes (1.14.1)
|
||||||
activemodel (>= 3.0, < 9.0)
|
activemodel (>= 3.0, < 9.0)
|
||||||
thor (1.3.2)
|
thor (1.4.0)
|
||||||
timeout (0.4.3)
|
timeout (0.4.3)
|
||||||
trailblazer-option (0.1.2)
|
trailblazer-option (0.1.2)
|
||||||
turbo-rails (2.0.11)
|
turbo-rails (2.0.11)
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ module Api
|
|||||||
params[:before] = Time.zone.at(params[:before].to_i) if params[:before].present?
|
params[:before] = Time.zone.at(params[:before].to_i) if params[:before].present?
|
||||||
|
|
||||||
submitters = paginate(
|
submitters = paginate(
|
||||||
submitters.preload(template: :folder, submission: [:submitters, { audit_trail_attachment: :blob,
|
submitters.preload(template: { folder: :parent_folder },
|
||||||
combined_document_attachment: :blob }],
|
submission: [:submitters, { audit_trail_attachment: :blob,
|
||||||
|
combined_document_attachment: :blob }],
|
||||||
documents_attachments: :blob, attachments_attachments: :blob),
|
documents_attachments: :blob, attachments_attachments: :blob),
|
||||||
field: :completed_at
|
field: :completed_at
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ module Api
|
|||||||
submissions = filter_submissions(submissions, params)
|
submissions = filter_submissions(submissions, params)
|
||||||
|
|
||||||
submissions = paginate(submissions.preload(:created_by_user, :submitters,
|
submissions = paginate(submissions.preload(:created_by_user, :submitters,
|
||||||
template: :folder,
|
template: { folder: :parent_folder },
|
||||||
combined_document_attachment: :blob,
|
combined_document_attachment: :blob,
|
||||||
audit_trail_attachment: :blob))
|
audit_trail_attachment: :blob))
|
||||||
|
|
||||||
@@ -104,9 +104,10 @@ module Api
|
|||||||
submissions = submissions.where(slug: params[:slug]) if params[:slug].present?
|
submissions = submissions.where(slug: params[:slug]) if params[:slug].present?
|
||||||
|
|
||||||
if params[:template_folder].present?
|
if params[:template_folder].present?
|
||||||
folder_ids = TemplateFolder.accessible_by(current_ability).where(name: params[:template_folder]).pluck(:id)
|
folders =
|
||||||
|
TemplateFolders.filter_by_full_name(TemplateFolder.accessible_by(current_ability), params[:template_folder])
|
||||||
|
|
||||||
submissions = submissions.joins(:template).where(template: { folder_id: folder_ids })
|
submissions = submissions.joins(:template).where(template: { folder_id: folders.pluck(:id) })
|
||||||
end
|
end
|
||||||
|
|
||||||
if params.key?(:archived)
|
if params.key?(:archived)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ module Api
|
|||||||
def index
|
def index
|
||||||
templates = filter_templates(@templates, params)
|
templates = filter_templates(@templates, params)
|
||||||
|
|
||||||
templates = paginate(templates.preload(:author, :folder))
|
templates = paginate(templates.preload(:author, folder: :parent_folder))
|
||||||
|
|
||||||
schema_documents =
|
schema_documents =
|
||||||
ActiveStorage::Attachment.where(record_id: templates.map(&:id),
|
ActiveStorage::Attachment.where(record_id: templates.map(&:id),
|
||||||
@@ -92,9 +92,9 @@ module Api
|
|||||||
templates = templates.where(slug: params[:slug]) if params[:slug].present?
|
templates = templates.where(slug: params[:slug]) if params[:slug].present?
|
||||||
|
|
||||||
if params[:folder].present?
|
if params[:folder].present?
|
||||||
folder_ids = TemplateFolder.accessible_by(current_ability).where(name: params[:folder]).pluck(:id)
|
folders = TemplateFolders.filter_by_full_name(TemplateFolder.accessible_by(current_ability), params[:folder])
|
||||||
|
|
||||||
templates = templates.where(folder_id: folder_ids)
|
templates = templates.where(folder_id: folders.pluck(:id))
|
||||||
end
|
end
|
||||||
|
|
||||||
templates
|
templates
|
||||||
@@ -109,7 +109,7 @@ module Api
|
|||||||
submitters: [%i[name uuid is_requester invite_by_uuid optional_invite_by_uuid linked_to_uuid email]],
|
submitters: [%i[name uuid is_requester invite_by_uuid optional_invite_by_uuid linked_to_uuid email]],
|
||||||
fields: [[:uuid, :submitter_uuid, :name, :type,
|
fields: [[:uuid, :submitter_uuid, :name, :type,
|
||||||
:required, :readonly, :default_value,
|
:required, :readonly, :default_value,
|
||||||
:title, :description,
|
:title, :description, :prefillable,
|
||||||
{ preferences: {},
|
{ preferences: {},
|
||||||
conditions: [%i[field_uuid value action operation]],
|
conditions: [%i[field_uuid value action operation]],
|
||||||
options: [%i[value uuid]],
|
options: [%i[value uuid]],
|
||||||
|
|||||||
@@ -32,10 +32,7 @@ class SubmissionsController < ApplicationController
|
|||||||
def create
|
def create
|
||||||
save_template_message(@template, params) if params[:save_message] == '1'
|
save_template_message(@template, params) if params[:save_message] == '1'
|
||||||
|
|
||||||
if params[:is_custom_message] != '1'
|
[params.delete(:subject), params.delete(:body)] if params[:is_custom_message] != '1'
|
||||||
params.delete(:subject)
|
|
||||||
params.delete(:body)
|
|
||||||
end
|
|
||||||
|
|
||||||
submissions =
|
submissions =
|
||||||
if params[:emails].present?
|
if params[:emails].present?
|
||||||
@@ -46,11 +43,16 @@ class SubmissionsController < ApplicationController
|
|||||||
emails: params[:emails],
|
emails: params[:emails],
|
||||||
params: params.merge('send_completed_email' => true))
|
params: params.merge('send_completed_email' => true))
|
||||||
else
|
else
|
||||||
|
submissions_attrs = submissions_params[:submission].to_h.values
|
||||||
|
|
||||||
|
submissions_attrs, =
|
||||||
|
Submissions::NormalizeParamUtils.normalize_submissions_params!(submissions_attrs, @template)
|
||||||
|
|
||||||
Submissions.create_from_submitters(template: @template,
|
Submissions.create_from_submitters(template: @template,
|
||||||
user: current_user,
|
user: current_user,
|
||||||
source: :invite,
|
source: :invite,
|
||||||
submitters_order: params[:preserve_order] == '1' ? 'preserved' : 'random',
|
submitters_order: params[:preserve_order] == '1' ? 'preserved' : 'random',
|
||||||
submissions_attrs: submissions_params[:submission].to_h.values,
|
submissions_attrs:,
|
||||||
params: params.merge('send_completed_email' => true))
|
params: params.merge('send_completed_email' => true))
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -62,9 +64,8 @@ class SubmissionsController < ApplicationController
|
|||||||
|
|
||||||
redirect_to template_path(@template), notice: I18n.t('new_recipients_have_been_added')
|
redirect_to template_path(@template), notice: I18n.t('new_recipients_have_been_added')
|
||||||
rescue Submissions::CreateFromSubmitters::BaseError => e
|
rescue Submissions::CreateFromSubmitters::BaseError => e
|
||||||
render turbo_stream: turbo_stream.replace(:submitters_error,
|
render turbo_stream: turbo_stream.replace(:submitters_error, partial: 'submissions/error',
|
||||||
partial: 'submissions/error',
|
locals: { error: e.message }),
|
||||||
locals: { error: e.message }),
|
|
||||||
status: :unprocessable_entity
|
status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -95,7 +96,7 @@ class SubmissionsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def submissions_params
|
def submissions_params
|
||||||
params.permit(submission: { submitters: [%i[uuid email phone name]] })
|
params.permit(submission: { submitters: [:uuid, :email, :phone, :name, { values: {} }] })
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_template
|
def load_template
|
||||||
|
|||||||
@@ -3,14 +3,31 @@
|
|||||||
class TemplateFoldersAutocompleteController < ApplicationController
|
class TemplateFoldersAutocompleteController < ApplicationController
|
||||||
load_and_authorize_resource :template_folder, parent: false
|
load_and_authorize_resource :template_folder, parent: false
|
||||||
|
|
||||||
LIMIT = 100
|
LIMIT = 30
|
||||||
|
|
||||||
def index
|
def index
|
||||||
templates_query = Template.accessible_by(current_ability).where(archived_at: nil)
|
parent_name, name =
|
||||||
|
if params[:parent_name].present?
|
||||||
|
[params[:parent_name], params[:q]]
|
||||||
|
else
|
||||||
|
params[:q].to_s.split(' /', 2).map(&:squish)
|
||||||
|
end
|
||||||
|
|
||||||
template_folders = @template_folders.where(id: templates_query.select(:folder_id))
|
if name
|
||||||
template_folders = TemplateFolders.search(template_folders, params[:q]).limit(LIMIT)
|
parent_folder = @template_folders.find_by(name: parent_name, parent_folder_id: nil)
|
||||||
|
else
|
||||||
|
name = parent_name
|
||||||
|
end
|
||||||
|
|
||||||
render json: template_folders.as_json(only: %i[name archived_at])
|
template_folders = TemplateFolders.filter_active_folders(@template_folders.where(parent_folder:),
|
||||||
|
Template.accessible_by(current_ability))
|
||||||
|
|
||||||
|
name = name.to_s.downcase
|
||||||
|
|
||||||
|
template_folders = TemplateFolders.search(template_folders, name).order(id: :desc).limit(LIMIT)
|
||||||
|
|
||||||
|
render json: template_folders.preload(:parent_folder)
|
||||||
|
.sort_by { |e| e.name.downcase.index(name) || Float::MAX }
|
||||||
|
.as_json(only: %i[name archived_at], methods: %i[full_name])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -5,13 +5,39 @@ class TemplateFoldersController < ApplicationController
|
|||||||
|
|
||||||
helper_method :selected_order
|
helper_method :selected_order
|
||||||
|
|
||||||
def show
|
TEMPLATES_PER_PAGE = 12
|
||||||
@templates = @template_folder.templates.active.accessible_by(current_ability)
|
FOLDERS_PER_PAGE = 18
|
||||||
.preload(:author, :template_accesses)
|
|
||||||
@templates = Templates.search(current_user, @templates, params[:q])
|
|
||||||
@templates = Templates::Order.call(@templates, current_user, selected_order)
|
|
||||||
|
|
||||||
@pagy, @templates = pagy_auto(@templates, limit: 12)
|
def show
|
||||||
|
@templates = Template.active.accessible_by(current_ability)
|
||||||
|
.where(folder: [@template_folder, *(params[:q].present? ? @template_folder.subfolders : [])])
|
||||||
|
.preload(:author, :template_accesses)
|
||||||
|
|
||||||
|
@template_folders =
|
||||||
|
@template_folder.subfolders.where(id: Template.accessible_by(current_ability).active.select(:folder_id))
|
||||||
|
|
||||||
|
@template_folders = TemplateFolders.search(@template_folders, params[:q])
|
||||||
|
@template_folders = TemplateFolders.sort(@template_folders, current_user, selected_order)
|
||||||
|
|
||||||
|
if @templates.exists?
|
||||||
|
@templates = Templates.search(current_user, @templates, params[:q])
|
||||||
|
@templates = Templates::Order.call(@templates, current_user, selected_order)
|
||||||
|
|
||||||
|
limit =
|
||||||
|
if @template_folders.size < 4
|
||||||
|
TEMPLATES_PER_PAGE
|
||||||
|
else
|
||||||
|
(@template_folders.size < 7 ? 9 : 6)
|
||||||
|
end
|
||||||
|
|
||||||
|
@pagy, @templates = pagy_auto(@templates, limit:)
|
||||||
|
|
||||||
|
load_related_submissions if params[:q].present? && @templates.blank?
|
||||||
|
else
|
||||||
|
@pagy, @template_folders = pagy(@template_folders, limit: FOLDERS_PER_PAGE)
|
||||||
|
|
||||||
|
@templates = @templates.none
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit; end
|
def edit; end
|
||||||
@@ -40,4 +66,21 @@ class TemplateFoldersController < ApplicationController
|
|||||||
def template_folder_params
|
def template_folder_params
|
||||||
params.require(:template_folder).permit(:name)
|
params.require(:template_folder).permit(:name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def load_related_submissions
|
||||||
|
@related_submissions =
|
||||||
|
Submission.accessible_by(current_ability)
|
||||||
|
.where(archived_at: nil)
|
||||||
|
.where(template_id: current_account.templates.active
|
||||||
|
.where(folder: [@template_folder, *@template_folder.subfolders])
|
||||||
|
.select(:id))
|
||||||
|
.preload(:template_accesses, :created_by_user,
|
||||||
|
template: :author,
|
||||||
|
submitters: :start_form_submission_events)
|
||||||
|
|
||||||
|
@related_submissions = Submissions.search(current_user, @related_submissions, params[:q])
|
||||||
|
.order(id: :desc)
|
||||||
|
|
||||||
|
@related_submissions_pagy, @related_submissions = pagy_auto(@related_submissions, limit: 5)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
@@ -4,9 +4,27 @@ class TemplatesArchivedController < ApplicationController
|
|||||||
load_and_authorize_resource :template, parent: false
|
load_and_authorize_resource :template, parent: false
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@templates = @templates.where.not(archived_at: nil).preload(:author, :folder, :template_accesses).order(id: :desc)
|
@templates = @templates.where.not(archived_at: nil)
|
||||||
|
.preload(:author, :template_accesses, folder: :parent_folder)
|
||||||
|
.order(id: :desc)
|
||||||
|
|
||||||
@templates = Templates.search(current_user, @templates, params[:q])
|
@templates = Templates.search(current_user, @templates, params[:q])
|
||||||
|
|
||||||
@pagy, @templates = pagy_auto(@templates, limit: 12)
|
@pagy, @templates = pagy_auto(@templates, limit: 12)
|
||||||
|
|
||||||
|
return unless params[:q].present? && @templates.blank?
|
||||||
|
|
||||||
|
@related_submissions =
|
||||||
|
Submission.accessible_by(current_ability)
|
||||||
|
.joins(:template)
|
||||||
|
.where.not(templates: { archived_at: nil })
|
||||||
|
.preload(:template_accesses, :created_by_user,
|
||||||
|
template: :author,
|
||||||
|
submitters: :start_form_submission_events)
|
||||||
|
|
||||||
|
@related_submissions = Submissions.search(current_user, @related_submissions, params[:q])
|
||||||
|
.order(id: :desc)
|
||||||
|
|
||||||
|
@related_submissions_pagy, @related_submissions = pagy_auto(@related_submissions, limit: 5)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -120,7 +120,7 @@ class TemplatesController < ApplicationController
|
|||||||
submitters: [%i[name uuid is_requester linked_to_uuid invite_by_uuid optional_invite_by_uuid email]],
|
submitters: [%i[name uuid is_requester linked_to_uuid invite_by_uuid optional_invite_by_uuid email]],
|
||||||
fields: [[:uuid, :submitter_uuid, :name, :type,
|
fields: [[:uuid, :submitter_uuid, :name, :type,
|
||||||
:required, :readonly, :default_value,
|
:required, :readonly, :default_value,
|
||||||
:title, :description,
|
:title, :description, :prefillable,
|
||||||
{ preferences: {},
|
{ preferences: {},
|
||||||
conditions: [%i[field_uuid value action operation]],
|
conditions: [%i[field_uuid value action operation]],
|
||||||
options: [%i[value uuid]],
|
options: [%i[value uuid]],
|
||||||
|
|||||||
@@ -11,10 +11,11 @@ class TemplatesDashboardController < ApplicationController
|
|||||||
helper_method :selected_order
|
helper_method :selected_order
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@template_folders = @template_folders.where(id: @templates.active.select(:folder_id))
|
@template_folders =
|
||||||
|
TemplateFolders.filter_active_folders(@template_folders.where(parent_folder_id: nil), @templates)
|
||||||
|
|
||||||
@template_folders = TemplateFolders.search(@template_folders, params[:q])
|
@template_folders = TemplateFolders.search(@template_folders, params[:q])
|
||||||
@template_folders = sort_template_folders(@template_folders, current_user, selected_order)
|
@template_folders = TemplateFolders.sort(@template_folders, current_user, selected_order)
|
||||||
|
|
||||||
@pagy, @template_folders = pagy(
|
@pagy, @template_folders = pagy(
|
||||||
@template_folders,
|
@template_folders,
|
||||||
@@ -68,40 +69,6 @@ class TemplatesDashboardController < ApplicationController
|
|||||||
Templates.search(current_user, rel, params[:q])
|
Templates.search(current_user, rel, params[:q])
|
||||||
end
|
end
|
||||||
|
|
||||||
def sort_template_folders(template_folders, current_user, order)
|
|
||||||
case order
|
|
||||||
when 'used_at'
|
|
||||||
subquery =
|
|
||||||
Template.left_joins(:submissions)
|
|
||||||
.group(:folder_id)
|
|
||||||
.where(account_id: current_user.account_id)
|
|
||||||
.select(
|
|
||||||
:folder_id,
|
|
||||||
Template.arel_table[:updated_at].maximum.as('updated_at_max'),
|
|
||||||
Submission.arel_table[:created_at].maximum.as('submission_created_at_max')
|
|
||||||
)
|
|
||||||
|
|
||||||
template_folders = template_folders.joins(
|
|
||||||
Template.arel_table
|
|
||||||
.join(subquery.arel.as('templates'), Arel::Nodes::OuterJoin)
|
|
||||||
.on(TemplateFolder.arel_table[:id].eq(Template.arel_table[:folder_id]))
|
|
||||||
.join_sources
|
|
||||||
)
|
|
||||||
|
|
||||||
template_folders.order(
|
|
||||||
Arel::Nodes::Case.new
|
|
||||||
.when(Template.arel_table[:submission_created_at_max].gt(Template.arel_table[:updated_at_max]))
|
|
||||||
.then(Template.arel_table[:submission_created_at_max])
|
|
||||||
.else(Template.arel_table[:updated_at_max])
|
|
||||||
.desc
|
|
||||||
)
|
|
||||||
when 'name'
|
|
||||||
template_folders.order(name: :asc)
|
|
||||||
else
|
|
||||||
template_folders.order(id: :desc)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def selected_order
|
def selected_order
|
||||||
@selected_order ||=
|
@selected_order ||=
|
||||||
if cookies.permanent[:dashboard_templates_order].blank? ||
|
if cookies.permanent[:dashboard_templates_order].blank? ||
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ class TemplatesFoldersController < ApplicationController
|
|||||||
def edit; end
|
def edit; end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@template.folder = TemplateFolders.find_or_create_by_name(current_user, params[:name])
|
name = [params[:parent_name], params[:name]].compact_blank.join(' / ')
|
||||||
|
|
||||||
|
@template.folder = TemplateFolders.find_or_create_by_name(current_user, name)
|
||||||
|
|
||||||
if @template.save
|
if @template.save
|
||||||
redirect_back(fallback_location: template_path(@template), notice: I18n.t('document_template_has_been_moved'))
|
redirect_back(fallback_location: template_path(@template), notice: I18n.t('document_template_has_been_moved'))
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class TemplatesPreferencesController < ApplicationController
|
|||||||
completed_redirect_url validate_unique_submitters
|
completed_redirect_url validate_unique_submitters
|
||||||
require_all_submitters submitters_order require_phone_2fa
|
require_all_submitters submitters_order require_phone_2fa
|
||||||
default_expire_at_duration shared_link_2fa
|
default_expire_at_duration shared_link_2fa
|
||||||
default_expire_at
|
default_expire_at request_email_enabled
|
||||||
completed_notification_email_subject completed_notification_email_body
|
completed_notification_email_subject completed_notification_email_body
|
||||||
completed_notification_email_enabled completed_notification_email_attach_audit] +
|
completed_notification_email_enabled completed_notification_email_attach_audit] +
|
||||||
[completed_message: %i[title body],
|
[completed_message: %i[title body],
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class TemplatesPrefillableFieldsController < ApplicationController
|
||||||
|
PREFILLABLE_FIELD_TYPES = %w[text number cells date checkbox select radio phone].freeze
|
||||||
|
|
||||||
|
load_and_authorize_resource :template
|
||||||
|
|
||||||
|
def create
|
||||||
|
authorize!(:update, @template)
|
||||||
|
|
||||||
|
field = @template.fields.find { |f| f['uuid'] == params[:field_uuid] }
|
||||||
|
|
||||||
|
if params[:prefillable] == 'false'
|
||||||
|
field.delete('prefillable')
|
||||||
|
field.delete('readonly')
|
||||||
|
elsif params[:prefillable] == 'true'
|
||||||
|
field['prefillable'] = true
|
||||||
|
field['readonly'] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
@template.save!
|
||||||
|
|
||||||
|
render turbo_stream: turbo_stream.replace(:prefillable_fields_list, partial: 'list',
|
||||||
|
locals: { template: @template })
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -37,6 +37,7 @@ import AppTour from './elements/app_tour'
|
|||||||
import DashboardDropzone from './elements/dashboard_dropzone'
|
import DashboardDropzone from './elements/dashboard_dropzone'
|
||||||
import RequiredCheckboxGroup from './elements/required_checkbox_group'
|
import RequiredCheckboxGroup from './elements/required_checkbox_group'
|
||||||
import PageContainer from './elements/page_container'
|
import PageContainer from './elements/page_container'
|
||||||
|
import EmailEditor from './elements/email_editor'
|
||||||
|
|
||||||
import * as TurboInstantClick from './lib/turbo_instant_click'
|
import * as TurboInstantClick from './lib/turbo_instant_click'
|
||||||
|
|
||||||
@@ -109,6 +110,7 @@ safeRegisterElement('dashboard-dropzone', DashboardDropzone)
|
|||||||
safeRegisterElement('check-on-click', CheckOnClick)
|
safeRegisterElement('check-on-click', CheckOnClick)
|
||||||
safeRegisterElement('required-checkbox-group', RequiredCheckboxGroup)
|
safeRegisterElement('required-checkbox-group', RequiredCheckboxGroup)
|
||||||
safeRegisterElement('page-container', PageContainer)
|
safeRegisterElement('page-container', PageContainer)
|
||||||
|
safeRegisterElement('email-editor', EmailEditor)
|
||||||
|
|
||||||
safeRegisterElement('template-builder', class extends HTMLElement {
|
safeRegisterElement('template-builder', class extends HTMLElement {
|
||||||
connectedCallback () {
|
connectedCallback () {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export default targetable(class extends HTMLElement {
|
|||||||
static [target.static] = [
|
static [target.static] = [
|
||||||
'form',
|
'form',
|
||||||
'fileDropzone',
|
'fileDropzone',
|
||||||
|
'folderDropzone',
|
||||||
'fileDropzoneLoading'
|
'fileDropzoneLoading'
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -25,12 +26,13 @@ export default targetable(class extends HTMLElement {
|
|||||||
window.addEventListener('dragleave', this.onWindowDragleave)
|
window.addEventListener('dragleave', this.onWindowDragleave)
|
||||||
|
|
||||||
this.fileDropzone?.addEventListener('drop', this.onDropFile)
|
this.fileDropzone?.addEventListener('drop', this.onDropFile)
|
||||||
|
this.folderDropzone?.addEventListener('drop', this.onDropNewFolder)
|
||||||
|
|
||||||
this.folderCards.forEach((el) => el.addEventListener('drop', (e) => this.onDropFolder(e, el)))
|
this.folderCards.forEach((el) => el.addEventListener('drop', (e) => this.onDropFolder(e, el)))
|
||||||
this.templateCards.forEach((el) => el.addEventListener('drop', this.onDropTemplate))
|
this.templateCards.forEach((el) => el.addEventListener('drop', this.onDropTemplate))
|
||||||
this.templateCards.forEach((el) => el.addEventListener('dragstart', this.onTemplateDragStart))
|
this.templateCards.forEach((el) => el.addEventListener('dragstart', this.onTemplateDragStart))
|
||||||
|
|
||||||
return [this.fileDropzone, ...this.folderCards, ...this.templateCards].forEach((el) => {
|
return [this.fileDropzone, this.folderDropzone, ...this.folderCards, ...this.templateCards].forEach((el) => {
|
||||||
el?.addEventListener('dragover', this.onDragover)
|
el?.addEventListener('dragover', this.onDragover)
|
||||||
el?.addEventListener('dragleave', this.onDragleave)
|
el?.addEventListener('dragleave', this.onDragleave)
|
||||||
})
|
})
|
||||||
@@ -46,6 +48,10 @@ export default targetable(class extends HTMLElement {
|
|||||||
onTemplateDragStart = (e) => {
|
onTemplateDragStart = (e) => {
|
||||||
const id = e.target.href.split('/').pop()
|
const id = e.target.href.split('/').pop()
|
||||||
|
|
||||||
|
this.folderCards.forEach((el) => el.classList.remove('bg-base-200', 'before:hidden'))
|
||||||
|
this.folderDropzone?.classList?.remove('hidden')
|
||||||
|
window.flash?.remove()
|
||||||
|
|
||||||
e.dataTransfer.effectAllowed = 'move'
|
e.dataTransfer.effectAllowed = 'move'
|
||||||
|
|
||||||
if (id) {
|
if (id) {
|
||||||
@@ -104,7 +110,7 @@ export default targetable(class extends HTMLElement {
|
|||||||
} else {
|
} else {
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
|
|
||||||
formData.append('name', el.innerText.trim())
|
formData.append('name', el.dataset.fullName)
|
||||||
|
|
||||||
fetch(`/templates/${templateId}/folder`, {
|
fetch(`/templates/${templateId}/folder`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
@@ -176,6 +182,24 @@ export default targetable(class extends HTMLElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDropNewFolder (e) {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
const templateId = e.dataTransfer.getData('template_id')
|
||||||
|
|
||||||
|
const a = document.createElement('a')
|
||||||
|
|
||||||
|
a.href = `/templates/${templateId}/folder/edit?autocomplete=false`
|
||||||
|
a.dataset.turboFrame = 'modal'
|
||||||
|
a.classList.add('hidden')
|
||||||
|
|
||||||
|
document.body.append(a)
|
||||||
|
|
||||||
|
a.click()
|
||||||
|
|
||||||
|
a.remove()
|
||||||
|
}
|
||||||
|
|
||||||
onDragleave () {
|
onDragleave () {
|
||||||
this.style.backgroundColor = null
|
this.style.backgroundColor = null
|
||||||
|
|
||||||
@@ -199,6 +223,7 @@ export default targetable(class extends HTMLElement {
|
|||||||
|
|
||||||
this.isDrag = true
|
this.isDrag = true
|
||||||
|
|
||||||
|
window.flash?.remove()
|
||||||
this.fileDropzone?.classList?.remove('hidden')
|
this.fileDropzone?.classList?.remove('hidden')
|
||||||
|
|
||||||
this.hiddenOnDrag.forEach((el) => { el.style.display = 'none' })
|
this.hiddenOnDrag.forEach((el) => { el.style.display = 'none' })
|
||||||
@@ -212,6 +237,7 @@ export default targetable(class extends HTMLElement {
|
|||||||
this.isDrag = false
|
this.isDrag = false
|
||||||
|
|
||||||
this.fileDropzone?.classList?.add('hidden')
|
this.fileDropzone?.classList?.add('hidden')
|
||||||
|
this.folderDropzone?.classList?.add('hidden')
|
||||||
|
|
||||||
this.hiddenOnDrag.forEach((el) => { el.style.display = null })
|
this.hiddenOnDrag.forEach((el) => { el.style.display = null })
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
import { target, targetable } from '@github/catalyst/lib/targetable'
|
||||||
|
|
||||||
|
let loaderPromise = null
|
||||||
|
|
||||||
|
function loadCodeMirror () {
|
||||||
|
if (!loaderPromise) {
|
||||||
|
loaderPromise = Promise.all([
|
||||||
|
import(/* webpackChunkName: "email-editor" */ '@codemirror/view'),
|
||||||
|
import(/* webpackChunkName: "email-editor" */ '@codemirror/commands'),
|
||||||
|
import(/* webpackChunkName: "email-editor" */ '@codemirror/language'),
|
||||||
|
import(/* webpackChunkName: "email-editor" */ '@codemirror/lang-html'),
|
||||||
|
import(/* webpackChunkName: "email-editor" */ '@specious/htmlflow')
|
||||||
|
]).then(([view, commands, language, html, htmlflow]) => {
|
||||||
|
return {
|
||||||
|
minimalSetup: [
|
||||||
|
commands.history(),
|
||||||
|
language.syntaxHighlighting(language.defaultHighlightStyle, { fallback: true }),
|
||||||
|
view.keymap.of([...commands.defaultKeymap, ...commands.historyKeymap])
|
||||||
|
],
|
||||||
|
EditorView: view.EditorView,
|
||||||
|
html: html.html,
|
||||||
|
htmlflow: htmlflow.default || htmlflow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return loaderPromise
|
||||||
|
}
|
||||||
|
|
||||||
|
export default targetable(class extends HTMLElement {
|
||||||
|
static [target.static] = [
|
||||||
|
'codeViewTab',
|
||||||
|
'previewViewTab',
|
||||||
|
'editorContainer',
|
||||||
|
'previewIframe'
|
||||||
|
]
|
||||||
|
|
||||||
|
connectedCallback () {
|
||||||
|
this.mount()
|
||||||
|
|
||||||
|
if (this.input.value) {
|
||||||
|
this.showPreviewView()
|
||||||
|
} else {
|
||||||
|
this.showCodeView()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.previewViewTab.addEventListener('click', this.showPreviewView)
|
||||||
|
this.codeViewTab.addEventListener('click', this.showCodeView)
|
||||||
|
}
|
||||||
|
|
||||||
|
showCodeView = () => {
|
||||||
|
this.editorView.dispatch({
|
||||||
|
changes: { from: 0, to: this.editorView.state.doc.length, insert: this.input.value }
|
||||||
|
})
|
||||||
|
|
||||||
|
this.previewViewTab.classList.remove('tab-active', 'tab-bordered')
|
||||||
|
this.previewViewTab.classList.add('pb-[3px]')
|
||||||
|
this.codeViewTab.classList.remove('pb-[3px]')
|
||||||
|
this.codeViewTab.classList.add('tab-active', 'tab-bordered')
|
||||||
|
this.editorContainer.classList.remove('hidden')
|
||||||
|
this.previewIframe.classList.add('hidden')
|
||||||
|
}
|
||||||
|
|
||||||
|
showPreviewView = () => {
|
||||||
|
this.previewIframe.srcdoc = this.input.value
|
||||||
|
|
||||||
|
this.codeViewTab.classList.remove('tab-active', 'tab-bordered')
|
||||||
|
this.codeViewTab.classList.add('pb-[3px]')
|
||||||
|
this.previewViewTab.classList.remove('pb-[3px]')
|
||||||
|
this.previewViewTab.classList.add('tab-active', 'tab-bordered')
|
||||||
|
this.editorContainer.classList.add('hidden')
|
||||||
|
this.previewIframe.classList.remove('hidden')
|
||||||
|
}
|
||||||
|
|
||||||
|
async mount () {
|
||||||
|
this.input = this.querySelector('input[type="hidden"]')
|
||||||
|
this.input.style.display = 'none'
|
||||||
|
|
||||||
|
const { EditorView, minimalSetup, html, htmlflow } = await loadCodeMirror()
|
||||||
|
|
||||||
|
this.editorView = new EditorView({
|
||||||
|
doc: this.input.value,
|
||||||
|
parent: this.editorContainer,
|
||||||
|
extensions: [
|
||||||
|
html(),
|
||||||
|
minimalSetup,
|
||||||
|
EditorView.lineWrapping,
|
||||||
|
EditorView.updateListener.of(update => {
|
||||||
|
if (update.docChanged) this.input.value = update.state.doc.toString()
|
||||||
|
}),
|
||||||
|
EditorView.theme({
|
||||||
|
'&': {
|
||||||
|
backgroundColor: 'white',
|
||||||
|
color: 'black',
|
||||||
|
fontSize: '14px',
|
||||||
|
fontFamily: 'monospace'
|
||||||
|
},
|
||||||
|
'&.cm-focused': {
|
||||||
|
outline: 'none'
|
||||||
|
},
|
||||||
|
'&.cm-editor': {
|
||||||
|
borderRadius: '0.375rem',
|
||||||
|
border: 'none'
|
||||||
|
},
|
||||||
|
'.cm-gutters': {
|
||||||
|
display: 'none'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
this.previewIframe.srcdoc = this.editorView.state.doc.toString()
|
||||||
|
|
||||||
|
this.previewIframe.onload = () => {
|
||||||
|
const previewIframeDoc = this.previewIframe.contentDocument
|
||||||
|
|
||||||
|
if (previewIframeDoc.body) {
|
||||||
|
previewIframeDoc.body.contentEditable = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentDocument = this.previewIframe.contentDocument || this.previewIframe.contentWindow.document
|
||||||
|
|
||||||
|
contentDocument.body.addEventListener('input', async () => {
|
||||||
|
const html = contentDocument.documentElement.outerHTML.replace(' contenteditable="true"', '')
|
||||||
|
const prettifiedHtml = await htmlflow(html)
|
||||||
|
|
||||||
|
this.input.value = prettifiedHtml
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -2,6 +2,8 @@ import autocomplete from 'autocompleter'
|
|||||||
|
|
||||||
export default class extends HTMLElement {
|
export default class extends HTMLElement {
|
||||||
connectedCallback () {
|
connectedCallback () {
|
||||||
|
if (this.dataset.enabled === 'false') return
|
||||||
|
|
||||||
autocomplete({
|
autocomplete({
|
||||||
input: this.input,
|
input: this.input,
|
||||||
preventSubmit: this.dataset.submitOnSelect === 'true' ? 0 : 1,
|
preventSubmit: this.dataset.submitOnSelect === 'true' ? 0 : 1,
|
||||||
@@ -14,12 +16,16 @@ export default class extends HTMLElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onSelect = (item) => {
|
onSelect = (item) => {
|
||||||
this.input.value = item.name
|
this.input.value = this.dataset.parentName ? item.name : item.full_name
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch = (text, resolve) => {
|
fetch = (text, resolve) => {
|
||||||
const queryParams = new URLSearchParams({ q: text })
|
const queryParams = new URLSearchParams({ q: text })
|
||||||
|
|
||||||
|
if (this.dataset.parentName) {
|
||||||
|
queryParams.append('parent_name', this.dataset.parentName)
|
||||||
|
}
|
||||||
|
|
||||||
fetch('/template_folders_autocomplete?' + queryParams).then(async (resp) => {
|
fetch('/template_folders_autocomplete?' + queryParams).then(async (resp) => {
|
||||||
const items = await resp.json()
|
const items = await resp.json()
|
||||||
|
|
||||||
@@ -34,7 +40,7 @@ export default class extends HTMLElement {
|
|||||||
|
|
||||||
div.setAttribute('dir', 'auto')
|
div.setAttribute('dir', 'auto')
|
||||||
|
|
||||||
div.textContent = item.name
|
div.textContent = this.dataset.parentName ? item.name : item.full_name
|
||||||
|
|
||||||
return div
|
return div
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
export default class extends HTMLElement {
|
export default class extends HTMLElement {
|
||||||
connectedCallback () {
|
connectedCallback () {
|
||||||
this.image.addEventListener('load', (e) => {
|
const image = this.querySelector('img')
|
||||||
this.image.setAttribute('width', e.target.naturalWidth)
|
|
||||||
this.image.setAttribute('height', e.target.naturalHeight)
|
image.addEventListener('load', (e) => {
|
||||||
|
image.setAttribute('width', e.target.naturalWidth)
|
||||||
|
image.setAttribute('height', e.target.naturalHeight)
|
||||||
|
|
||||||
this.style.aspectRatio = `${e.target.naturalWidth} / ${e.target.naturalHeight}`
|
this.style.aspectRatio = `${e.target.naturalWidth} / ${e.target.naturalHeight}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
get image () {
|
|
||||||
return this.querySelector('img')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -7,5 +7,9 @@ export default actionable(class extends HTMLElement {
|
|||||||
elementIds.forEach((elementId) => {
|
elementIds.forEach((elementId) => {
|
||||||
document.getElementById(elementId).classList.toggle('hidden', (event.target.dataset.toggleId || event.target.value) !== elementId)
|
document.getElementById(elementId).classList.toggle('hidden', (event.target.dataset.toggleId || event.target.value) !== elementId)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (this.dataset.focusId) {
|
||||||
|
document.getElementById(this.dataset.focusId)?.focus()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -56,11 +56,11 @@
|
|||||||
<div
|
<div
|
||||||
v-else-if="field.type === 'signature' && signature"
|
v-else-if="field.type === 'signature' && signature"
|
||||||
class="flex justify-between h-full gap-1 overflow-hidden w-full"
|
class="flex justify-between h-full gap-1 overflow-hidden w-full"
|
||||||
:class="isNarrow && (withSignatureId || field.preferences?.reason_field_uuid) ? 'flex-row' : 'flex-col'"
|
:class="isNarrow && (isShowSignatureId || field.preferences?.reason_field_uuid) ? 'flex-row' : 'flex-col'"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="flex overflow-hidden"
|
class="flex overflow-hidden"
|
||||||
:class="isNarrow && (withSignatureId || field.preferences?.reason_field_uuid) ? 'w-1/2' : 'flex-grow'"
|
:class="isNarrow && (isShowSignatureId || field.preferences?.reason_field_uuid) ? 'w-1/2' : 'flex-grow'"
|
||||||
style="min-height: 50%"
|
style="min-height: 50%"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="withSignatureId || field.preferences?.reason_field_uuid"
|
v-if="isShowSignatureId || field.preferences?.reason_field_uuid"
|
||||||
class="text-[1vw] lg:text-[0.55rem] lg:leading-[0.65rem]"
|
class="text-[1vw] lg:text-[0.55rem] lg:leading-[0.65rem]"
|
||||||
:class="isNarrow ? 'w-1/2' : 'w-full'"
|
:class="isNarrow ? 'w-1/2' : 'w-full'"
|
||||||
>
|
>
|
||||||
@@ -333,6 +333,13 @@ export default {
|
|||||||
verification: this.t('verify_id')
|
verification: this.t('verify_id')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
isShowSignatureId () {
|
||||||
|
if ([true, false].includes(this.field.preferences?.with_signature_id)) {
|
||||||
|
return this.field.preferences.with_signature_id
|
||||||
|
} else {
|
||||||
|
return this.withSignatureId
|
||||||
|
}
|
||||||
|
},
|
||||||
alignClasses () {
|
alignClasses () {
|
||||||
if (!this.field.preferences) {
|
if (!this.field.preferences) {
|
||||||
return { 'items-center': true }
|
return { 'items-center': true }
|
||||||
@@ -460,9 +467,6 @@ export default {
|
|||||||
fontScale () {
|
fontScale () {
|
||||||
return 1000 / 612.0
|
return 1000 / 612.0
|
||||||
},
|
},
|
||||||
ladscapeScale () {
|
|
||||||
return 8.5 / 11.0
|
|
||||||
},
|
|
||||||
computedStyle () {
|
computedStyle () {
|
||||||
const { x, y, w, h } = this.area
|
const { x, y, w, h } = this.area
|
||||||
|
|
||||||
|
|||||||
@@ -112,11 +112,23 @@ export default {
|
|||||||
onSelectFiles (e) {
|
onSelectFiles (e) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
this.uploadFiles(this.$refs.input.files).then(() => {
|
const files = Array.from(this.$refs.input.files).filter((f) => {
|
||||||
if (this.$refs.input) {
|
if (this.accept === 'image/*') {
|
||||||
this.$refs.input.value = ''
|
return f.type.startsWith('image')
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (this.accept === 'image/*' && !files.length) {
|
||||||
|
alert(this.t('please_upload_an_image_file'))
|
||||||
|
} else {
|
||||||
|
this.uploadFiles(files).then(() => {
|
||||||
|
if (this.$refs.input) {
|
||||||
|
this.$refs.input.value = ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async uploadFiles (files) {
|
async uploadFiles (files) {
|
||||||
this.isLoading = true
|
this.isLoading = true
|
||||||
|
|||||||
@@ -149,7 +149,8 @@ export default {
|
|||||||
return fetch(this.baseUrl + `/api/identity_verification/${this.field.uuid}`, {
|
return fetch(this.baseUrl + `/api/identity_verification/${this.field.uuid}`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
submitter_slug: this.submitterSlug
|
submitter_slug: this.submitterSlug,
|
||||||
|
redirect_url: document.location.href
|
||||||
}),
|
}),
|
||||||
headers: { 'Content-Type': 'application/json' }
|
headers: { 'Content-Type': 'application/json' }
|
||||||
}).then(async (resp) => {
|
}).then(async (resp) => {
|
||||||
|
|||||||
@@ -140,6 +140,8 @@
|
|||||||
:background-color="'white'"
|
:background-color="'white'"
|
||||||
:with-required="false"
|
:with-required="false"
|
||||||
:with-areas="false"
|
:with-areas="false"
|
||||||
|
:with-signature-id="withSignatureId"
|
||||||
|
:with-prefillable="withPrefillable"
|
||||||
@click-formula="isShowFormulaModal = true"
|
@click-formula="isShowFormulaModal = true"
|
||||||
@click-font="isShowFontModal = true"
|
@click-font="isShowFontModal = true"
|
||||||
@click-description="isShowDescriptionModal = true"
|
@click-description="isShowDescriptionModal = true"
|
||||||
@@ -347,6 +349,16 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
|
withSignatureId: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
withPrefillable: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
defaultSubmitters: {
|
defaultSubmitters: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -414,9 +426,6 @@ export default {
|
|||||||
fontScale () {
|
fontScale () {
|
||||||
return 1040 / 612.0
|
return 1040 / 612.0
|
||||||
},
|
},
|
||||||
ladscapeScale () {
|
|
||||||
return 8.5 / 11.0
|
|
||||||
},
|
|
||||||
isDefaultValuePresent () {
|
isDefaultValuePresent () {
|
||||||
if (this.field?.type === 'radio' && this.field?.areas?.length > 1) {
|
if (this.field?.type === 'radio' && this.field?.areas?.length > 1) {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -330,6 +330,8 @@
|
|||||||
:input-mode="inputMode"
|
:input-mode="inputMode"
|
||||||
:default-fields="[...defaultRequiredFields, ...defaultFields]"
|
:default-fields="[...defaultRequiredFields, ...defaultFields]"
|
||||||
:allow-draw="!onlyDefinedFields || drawField"
|
:allow-draw="!onlyDefinedFields || drawField"
|
||||||
|
:with-signature-id="withSignatureId"
|
||||||
|
:with-prefillable="withPrefillable"
|
||||||
:data-document-uuid="document.uuid"
|
:data-document-uuid="document.uuid"
|
||||||
:default-submitters="defaultSubmitters"
|
:default-submitters="defaultSubmitters"
|
||||||
:drag-field-placeholder="fieldsDragFieldRef.value || dragField"
|
:drag-field-placeholder="fieldsDragFieldRef.value || dragField"
|
||||||
@@ -436,6 +438,8 @@
|
|||||||
:default-required-fields="defaultRequiredFields"
|
:default-required-fields="defaultRequiredFields"
|
||||||
:field-types="fieldTypes"
|
:field-types="fieldTypes"
|
||||||
:with-sticky-submitters="withStickySubmitters"
|
:with-sticky-submitters="withStickySubmitters"
|
||||||
|
:with-signature-id="withSignatureId"
|
||||||
|
:with-prefillable="withPrefillable"
|
||||||
:only-defined-fields="onlyDefinedFields"
|
:only-defined-fields="onlyDefinedFields"
|
||||||
:editable="editable"
|
:editable="editable"
|
||||||
:show-tour-start-form="showTourStartForm"
|
:show-tour-start-form="showTourStartForm"
|
||||||
@@ -563,6 +567,11 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
|
withSignatureId: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
backgroundColor: {
|
backgroundColor: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -794,6 +803,13 @@ export default {
|
|||||||
language () {
|
language () {
|
||||||
return this.locale.split('-')[0].toLowerCase()
|
return this.locale.split('-')[0].toLowerCase()
|
||||||
},
|
},
|
||||||
|
withPrefillable () {
|
||||||
|
if (this.template.fields) {
|
||||||
|
return this.template.fields.some((f) => f.prefillable)
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
isInlineSize () {
|
isInlineSize () {
|
||||||
return CSS.supports('container-type: size')
|
return CSS.supports('container-type: size')
|
||||||
},
|
},
|
||||||
@@ -1068,6 +1084,11 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type === 'signature' && [true, false].includes(this.withSignatureId)) {
|
||||||
|
field.preferences ||= {}
|
||||||
|
field.preferences.with_signature_id = this.withSignatureId
|
||||||
|
}
|
||||||
|
|
||||||
this.template.fields.push(field)
|
this.template.fields.push(field)
|
||||||
|
|
||||||
this.save()
|
this.save()
|
||||||
@@ -1474,6 +1495,11 @@ export default {
|
|||||||
field.preferences ||= {}
|
field.preferences ||= {}
|
||||||
field.preferences.format ||= this.defaultDateFormat
|
field.preferences.format ||= this.defaultDateFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (field.type === 'signature' && [true, false].includes(this.withSignatureId)) {
|
||||||
|
field.preferences ||= {}
|
||||||
|
field.preferences.with_signature_id = this.withSignatureId
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fieldArea = {
|
const fieldArea = {
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
:data-page="index"
|
:data-page="index"
|
||||||
:areas="areasIndex[index]"
|
:areas="areasIndex[index]"
|
||||||
:allow-draw="allowDraw"
|
:allow-draw="allowDraw"
|
||||||
|
:with-signature-id="withSignatureId"
|
||||||
|
:with-prefillable="withPrefillable"
|
||||||
:is-drag="isDrag"
|
:is-drag="isDrag"
|
||||||
:with-field-placeholder="withFieldPlaceholder"
|
:with-field-placeholder="withFieldPlaceholder"
|
||||||
:default-fields="defaultFields"
|
:default-fields="defaultFields"
|
||||||
@@ -66,6 +68,16 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
|
withSignatureId: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
withPrefillable: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
drawFieldType: {
|
drawFieldType: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
|
|||||||
@@ -125,6 +125,8 @@
|
|||||||
:field="field"
|
:field="field"
|
||||||
:default-field="defaultField"
|
:default-field="defaultField"
|
||||||
:editable="editable"
|
:editable="editable"
|
||||||
|
:with-signature-id="withSignatureId"
|
||||||
|
:with-prefillable="withPrefillable"
|
||||||
:background-color="dropdownBgColor"
|
:background-color="dropdownBgColor"
|
||||||
@click-formula="isShowFormulaModal = true"
|
@click-formula="isShowFormulaModal = true"
|
||||||
@click-font="isShowFontModal = true"
|
@click-font="isShowFontModal = true"
|
||||||
@@ -302,6 +304,16 @@ export default {
|
|||||||
type: Object,
|
type: Object,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
withSignatureId: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
withPrefillable: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
withOptions: {
|
withOptions: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
|
|||||||
@@ -320,6 +320,21 @@
|
|||||||
{{ t('format') }}
|
{{ t('format') }}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<li
|
||||||
|
v-if="[true, false].includes(withSignatureId) && field.type === 'signature'"
|
||||||
|
@click.stop
|
||||||
|
>
|
||||||
|
<label class="cursor-pointer py-1.5">
|
||||||
|
<input
|
||||||
|
:checked="field.preferences?.with_signature_id"
|
||||||
|
type="checkbox"
|
||||||
|
:disabled="!editable || (defaultField && [true, false].includes(defaultField.required))"
|
||||||
|
class="toggle toggle-xs"
|
||||||
|
@change="[field.preferences ||= {}, field.preferences.with_signature_id = $event.target.checked, save()]"
|
||||||
|
>
|
||||||
|
<span class="label-text">{{ t('signature_id') }}</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
<li
|
<li
|
||||||
v-if="withRequired && field.type !== 'phone' && field.type !== 'stamp' && field.type !== 'verification'"
|
v-if="withRequired && field.type !== 'phone' && field.type !== 'stamp' && field.type !== 'verification'"
|
||||||
@click.stop
|
@click.stop
|
||||||
@@ -391,6 +406,21 @@
|
|||||||
<span class="label-text">{{ t('read_only') }}</span>
|
<span class="label-text">{{ t('read_only') }}</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
|
<li
|
||||||
|
v-if="withPrefillable && ['text', 'number', 'cells', 'date', 'checkbox', 'select', 'radio', 'phone'].includes(field['type'])"
|
||||||
|
@click.stop
|
||||||
|
>
|
||||||
|
<label class="cursor-pointer py-1.5">
|
||||||
|
<input
|
||||||
|
v-model="field.prefillable"
|
||||||
|
type="checkbox"
|
||||||
|
:disabled="!editable || (defaultField && [true, false].includes(defaultField.prefillable))"
|
||||||
|
class="toggle toggle-xs"
|
||||||
|
@update:model-value="save"
|
||||||
|
>
|
||||||
|
<span class="label-text">{{ t('prefillable') }}</span>
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
<hr
|
<hr
|
||||||
v-if="field.type != 'stamp'"
|
v-if="field.type != 'stamp'"
|
||||||
class="pb-0.5 mt-0.5"
|
class="pb-0.5 mt-0.5"
|
||||||
@@ -525,6 +555,11 @@ export default {
|
|||||||
type: Object,
|
type: Object,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
withSignatureId: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
backgroundColor: {
|
backgroundColor: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -535,6 +570,11 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: null
|
default: null
|
||||||
},
|
},
|
||||||
|
withPrefillable: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
withRequired: {
|
withRequired: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
:field="field"
|
:field="field"
|
||||||
:type-index="fields.filter((f) => f.type === field.type).indexOf(field)"
|
:type-index="fields.filter((f) => f.type === field.type).indexOf(field)"
|
||||||
:editable="editable"
|
:editable="editable"
|
||||||
|
:with-signature-id="withSignatureId"
|
||||||
|
:with-prefillable="withPrefillable"
|
||||||
:default-field="defaultFieldsIndex[field.name]"
|
:default-field="defaultFieldsIndex[field.name]"
|
||||||
:draggable="editable"
|
:draggable="editable"
|
||||||
@dragstart="[fieldsDragFieldRef.value = field, removeDragOverlay($event), setDragPlaceholder($event)]"
|
@dragstart="[fieldsDragFieldRef.value = field, removeDragOverlay($event), setDragPlaceholder($event)]"
|
||||||
@@ -253,6 +255,16 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: null
|
default: null
|
||||||
},
|
},
|
||||||
|
withSignatureId: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
withPrefillable: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
template: {
|
template: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
@@ -163,7 +163,7 @@
|
|||||||
class="flex border border-base-content/20 rounded-xl bg-white px-4 h-16 modal-field-font-preview"
|
class="flex border border-base-content/20 rounded-xl bg-white px-4 h-16 modal-field-font-preview"
|
||||||
:style="{
|
:style="{
|
||||||
color: preferences.color || 'black',
|
color: preferences.color || 'black',
|
||||||
fontSize: (preferences.font_size || 12) + 'pt',
|
fontSize: (preferences.font_size || 11) + 'pt',
|
||||||
}"
|
}"
|
||||||
:class="textClasses"
|
:class="textClasses"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
<div
|
<div
|
||||||
v-if="isDragging || isLoading"
|
v-if="isDragging || isLoading"
|
||||||
class="modal modal-open"
|
class="modal modal-open"
|
||||||
|
@dragover.prevent
|
||||||
|
@drop.prevent="$emit('error')"
|
||||||
>
|
>
|
||||||
<div class="flex flex-col gap-2 p-4 items-center bg-base-100 h-full max-h-[85vh] max-w-6xl rounded-2xl w-full">
|
<div class="flex flex-col gap-2 p-4 items-center bg-base-100 h-full max-h-[85vh] max-w-6xl rounded-2xl w-full">
|
||||||
<Dropzone
|
<Dropzone
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
const en = {
|
const en = {
|
||||||
|
prefillable: 'Prefillable',
|
||||||
|
signature_id: 'Signature ID',
|
||||||
error_message: 'Error message',
|
error_message: 'Error message',
|
||||||
length: 'Length',
|
length: 'Length',
|
||||||
min: 'Min',
|
min: 'Min',
|
||||||
@@ -172,6 +174,8 @@ const en = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const es = {
|
const es = {
|
||||||
|
prefillable: 'Rellenable',
|
||||||
|
signature_id: 'ID de Firma',
|
||||||
error_message: 'Mensaje de error',
|
error_message: 'Mensaje de error',
|
||||||
length: 'Longitud',
|
length: 'Longitud',
|
||||||
min: 'Mín',
|
min: 'Mín',
|
||||||
@@ -345,6 +349,8 @@ const es = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const it = {
|
const it = {
|
||||||
|
prefillable: 'Precompilabile',
|
||||||
|
signature_id: 'ID firma',
|
||||||
error_message: 'Messaggio di errore',
|
error_message: 'Messaggio di errore',
|
||||||
length: 'Lunghezza',
|
length: 'Lunghezza',
|
||||||
min: 'Min',
|
min: 'Min',
|
||||||
@@ -518,6 +524,8 @@ const it = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const pt = {
|
const pt = {
|
||||||
|
prefillable: 'Pré-preenchível',
|
||||||
|
signature_id: 'ID da Assinatura',
|
||||||
error_message: 'Mensagem de erro',
|
error_message: 'Mensagem de erro',
|
||||||
length: 'Comprimento',
|
length: 'Comprimento',
|
||||||
min: 'Mín',
|
min: 'Mín',
|
||||||
@@ -691,6 +699,8 @@ const pt = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fr = {
|
const fr = {
|
||||||
|
prefillable: 'Pré-remplissable',
|
||||||
|
signature_id: 'ID de signature',
|
||||||
error_message: 'Message d\'erreur',
|
error_message: 'Message d\'erreur',
|
||||||
length: 'Longueur',
|
length: 'Longueur',
|
||||||
min: 'Min',
|
min: 'Min',
|
||||||
@@ -864,6 +874,8 @@ const fr = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const de = {
|
const de = {
|
||||||
|
prefillable: 'Vorausfüllbar',
|
||||||
|
signature_id: 'Signatur-ID',
|
||||||
error_message: 'Fehlermeldung',
|
error_message: 'Fehlermeldung',
|
||||||
length: 'Länge',
|
length: 'Länge',
|
||||||
min: 'Min',
|
min: 'Min',
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
:field="item.field"
|
:field="item.field"
|
||||||
:editable="editable"
|
:editable="editable"
|
||||||
:with-field-placeholder="withFieldPlaceholder"
|
:with-field-placeholder="withFieldPlaceholder"
|
||||||
|
:with-signature-id="withSignatureId"
|
||||||
|
:with-prefillable="withPrefillable"
|
||||||
:default-field="defaultFieldsIndex[item.field.name]"
|
:default-field="defaultFieldsIndex[item.field.name]"
|
||||||
:default-submitters="defaultSubmitters"
|
:default-submitters="defaultSubmitters"
|
||||||
:max-page="totalPages - 1"
|
:max-page="totalPages - 1"
|
||||||
@@ -78,6 +80,16 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: null
|
default: null
|
||||||
},
|
},
|
||||||
|
withSignatureId: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
withPrefillable: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
areas: {
|
areas: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: false,
|
required: false,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ class SendSubmitterInvitationEmailJob
|
|||||||
def perform(params = {})
|
def perform(params = {})
|
||||||
submitter = Submitter.find(params['submitter_id'])
|
submitter = Submitter.find(params['submitter_id'])
|
||||||
|
|
||||||
|
return if submitter.completed_at?
|
||||||
return if submitter.submission.source == 'invite' && !Accounts.can_send_emails?(submitter.account, on_events: true)
|
return if submitter.submission.source == 'invite' && !Accounts.can_send_emails?(submitter.account, on_events: true)
|
||||||
|
|
||||||
unless Accounts.can_send_invitation_emails?(submitter.account)
|
unless Accounts.can_send_invitation_emails?(submitter.account)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class SubmitterMailer < ApplicationMailer
|
|||||||
@submitter.template&.preferences&.dig('request_email_subject').presence
|
@submitter.template&.preferences&.dig('request_email_subject').presence
|
||||||
|
|
||||||
@email_config = AccountConfigs.find_for_account(@current_account, AccountConfig::SUBMITTER_INVITATION_EMAIL_KEY)
|
@email_config = AccountConfigs.find_for_account(@current_account, AccountConfig::SUBMITTER_INVITATION_EMAIL_KEY)
|
||||||
|
@body ||= fetch_config_email_body(@email_config, @submitter)
|
||||||
|
|
||||||
assign_message_metadata('submitter_invitation', @submitter)
|
assign_message_metadata('submitter_invitation', @submitter)
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ class SubmitterMailer < ApplicationMailer
|
|||||||
@subject ||= @email_config.value['subject'] if @email_config
|
@subject ||= @email_config.value['subject'] if @email_config
|
||||||
|
|
||||||
@body = template_preferences['completed_notification_email_body'].presence
|
@body = template_preferences['completed_notification_email_body'].presence
|
||||||
@body ||= @email_config.value['body'] if @email_config
|
@body ||= fetch_config_email_body(@email_config, @submitter)
|
||||||
|
|
||||||
assign_message_metadata('submitter_completed', @submitter)
|
assign_message_metadata('submitter_completed', @submitter)
|
||||||
|
|
||||||
@@ -127,7 +128,7 @@ class SubmitterMailer < ApplicationMailer
|
|||||||
@subject ||= @email_config.value['subject'] if @email_config
|
@subject ||= @email_config.value['subject'] if @email_config
|
||||||
|
|
||||||
@body = template_preferences['documents_copy_email_body'].presence
|
@body = template_preferences['documents_copy_email_body'].presence
|
||||||
@body ||= @email_config.value['body'] if @email_config
|
@body ||= fetch_config_email_body(@email_config, @submitter)
|
||||||
|
|
||||||
assign_message_metadata('submitter_documents_copy', @submitter)
|
assign_message_metadata('submitter_documents_copy', @submitter)
|
||||||
reply_to = build_submitter_reply_to(submitter, email_config: @email_config, documents_copy_email: true)
|
reply_to = build_submitter_reply_to(submitter, email_config: @email_config, documents_copy_email: true)
|
||||||
@@ -246,4 +247,8 @@ class SubmitterMailer < ApplicationMailer
|
|||||||
user.friendly_name
|
user.friendly_name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def fetch_config_email_body(email_config, _submitter = nil)
|
||||||
|
email_config ? email_config.value['body'].presence : nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
@@ -41,6 +41,7 @@ class AccountConfig < ApplicationRecord
|
|||||||
FORCE_SSO_AUTH_KEY = 'force_sso_auth'
|
FORCE_SSO_AUTH_KEY = 'force_sso_auth'
|
||||||
FLATTEN_RESULT_PDF_KEY = 'flatten_result_pdf'
|
FLATTEN_RESULT_PDF_KEY = 'flatten_result_pdf'
|
||||||
WITH_SIGNATURE_ID = 'with_signature_id'
|
WITH_SIGNATURE_ID = 'with_signature_id'
|
||||||
|
WITH_SIGNATURE_ID_REASON_KEY = 'with_signature_id_reason'
|
||||||
WITH_AUDIT_VALUES_KEY = 'with_audit_values'
|
WITH_AUDIT_VALUES_KEY = 'with_audit_values'
|
||||||
WITH_SUBMITTER_TIMEZONE_KEY = 'with_submitter_timezone'
|
WITH_SUBMITTER_TIMEZONE_KEY = 'with_submitter_timezone'
|
||||||
REQUIRE_SIGNING_REASON_KEY = 'require_signing_reason'
|
REQUIRE_SIGNING_REASON_KEY = 'require_signing_reason'
|
||||||
|
|||||||
@@ -72,12 +72,14 @@ class Template < ApplicationRecord
|
|||||||
scope :active, -> { where(archived_at: nil) }
|
scope :active, -> { where(archived_at: nil) }
|
||||||
scope :archived, -> { where.not(archived_at: nil) }
|
scope :archived, -> { where.not(archived_at: nil) }
|
||||||
|
|
||||||
delegate :name, to: :folder, prefix: true
|
|
||||||
|
|
||||||
def application_key
|
def application_key
|
||||||
external_id
|
external_id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def folder_name
|
||||||
|
folder.full_name
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def maybe_set_default_folder
|
def maybe_set_default_folder
|
||||||
|
|||||||
@@ -4,36 +4,50 @@
|
|||||||
#
|
#
|
||||||
# Table name: template_folders
|
# Table name: template_folders
|
||||||
#
|
#
|
||||||
# id :bigint not null, primary key
|
# id :bigint not null, primary key
|
||||||
# archived_at :datetime
|
# archived_at :datetime
|
||||||
# name :string not null
|
# name :string not null
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
# account_id :bigint not null
|
# account_id :bigint not null
|
||||||
# author_id :bigint not null
|
# author_id :bigint not null
|
||||||
|
# parent_folder_id :bigint
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
# index_template_folders_on_account_id (account_id)
|
# index_template_folders_on_account_id (account_id)
|
||||||
# index_template_folders_on_author_id (author_id)
|
# index_template_folders_on_author_id (author_id)
|
||||||
|
# index_template_folders_on_parent_folder_id (parent_folder_id)
|
||||||
#
|
#
|
||||||
# Foreign Keys
|
# Foreign Keys
|
||||||
#
|
#
|
||||||
# fk_rails_... (account_id => accounts.id)
|
# fk_rails_... (account_id => accounts.id)
|
||||||
# fk_rails_... (author_id => users.id)
|
# fk_rails_... (author_id => users.id)
|
||||||
|
# fk_rails_... (parent_folder_id => template_folders.id)
|
||||||
#
|
#
|
||||||
class TemplateFolder < ApplicationRecord
|
class TemplateFolder < ApplicationRecord
|
||||||
DEFAULT_NAME = 'Default'
|
DEFAULT_NAME = 'Default'
|
||||||
|
|
||||||
belongs_to :author, class_name: 'User'
|
belongs_to :author, class_name: 'User'
|
||||||
belongs_to :account
|
belongs_to :account
|
||||||
|
belongs_to :parent_folder, class_name: 'TemplateFolder', optional: true
|
||||||
|
|
||||||
has_many :templates, dependent: :destroy, foreign_key: :folder_id, inverse_of: :folder
|
has_many :templates, dependent: :destroy, foreign_key: :folder_id, inverse_of: :folder
|
||||||
|
has_many :subfolders, class_name: 'TemplateFolder', foreign_key: :parent_folder_id, inverse_of: :parent_folder,
|
||||||
|
dependent: :destroy
|
||||||
has_many :active_templates, -> { where(archived_at: nil) },
|
has_many :active_templates, -> { where(archived_at: nil) },
|
||||||
class_name: 'Template', dependent: :destroy, foreign_key: :folder_id, inverse_of: :folder
|
class_name: 'Template', dependent: :destroy, foreign_key: :folder_id, inverse_of: :folder
|
||||||
|
|
||||||
scope :active, -> { where(archived_at: nil) }
|
scope :active, -> { where(archived_at: nil) }
|
||||||
|
|
||||||
|
def full_name
|
||||||
|
if parent_folder_id?
|
||||||
|
[parent_folder.name, name].join(' / ')
|
||||||
|
else
|
||||||
|
name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def default?
|
def default?
|
||||||
name == DEFAULT_NAME
|
name == DEFAULT_NAME
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
<span class="top-0 right-0 absolute">
|
<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: t('copy'), copied_title: t('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>
|
</span>
|
||||||
<pre data-prefix="$"><code class="overflow-hidden w-full"><%= text %></code></pre>
|
<pre data-prefix="$"><code class="overflow-hidden w-full"><%== HighlightCode.call(text, 'Shell', theme: 'base16.dark') %></code></pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
<span class="top-0 right-0 absolute">
|
<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: t('copy'), copied_title: t('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>
|
</span>
|
||||||
<pre data-prefix="$"><code class="overflow-hidden w-full"><%= text %></code></pre>
|
<pre data-prefix="$"><code class="overflow-hidden w-full"><%== HighlightCode.call(text, 'Shell', theme: 'base16.dark') %></code></pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
<span class="top-0 right-0 absolute">
|
<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: t('copy'), copied_title: t('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>
|
</span>
|
||||||
<pre data-prefix="$"><code class="overflow-hidden w-full"><%= text %></code></pre>
|
<pre data-prefix="$"><code class="overflow-hidden w-full"><%== HighlightCode.call(text, 'Shell', theme: 'base16.dark') %></code></pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -141,7 +141,7 @@
|
|||||||
<%= t('preferences') %>
|
<%= t('preferences') %>
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<% if can?(:manage, account_config) && (can?(:manage, :personalization_advanced) || !Docuseal.multitenant?) %>
|
<% if can?(:manage, account_config) && (can?(:manage, :personalization_advanced) || account_config.persisted?) %>
|
||||||
<%= form_for account_config, url: account_configs_path, method: :post do |f| %>
|
<%= form_for account_config, url: account_configs_path, method: :post do |f| %>
|
||||||
<%= f.hidden_field :key %>
|
<%= f.hidden_field :key %>
|
||||||
<div class="flex items-center justify-between py-2.5">
|
<div class="flex items-center justify-between py-2.5">
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M5 12l14 0" /><path d="M5 12l6 6" /><path d="M5 12l6 -6" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 351 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M12 21a9 9 0 1 0 0 -18a9 9 0 0 0 0 18" /><path d="M8 12l4 4" /><path d="M8 12h8" /><path d="M12 8l-4 4" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 398 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M12 21a9 9 0 1 0 0 -18a9 9 0 0 0 0 18" /><path d="M9 12l4 4" /><path d="M13 8l-4 4" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 378 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M12 19h-7a2 2 0 0 1 -2 -2v-11a2 2 0 0 1 2 -2h4l3 3h7a2 2 0 0 1 2 2v3.5" /><path d="M16 19h6" /><path d="M19 16v6" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 408 B |
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M17 5l-10 14" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 308 B |
@@ -18,7 +18,6 @@
|
|||||||
<link href="<%= canonical_url %>" rel="canonical">
|
<link href="<%= canonical_url %>" rel="canonical">
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= stylesheet_pack_tag 'application', media: 'all' %>
|
<%= stylesheet_pack_tag 'application', media: 'all' %>
|
||||||
<%= render 'shared/posthog' if ENV['POSTHOG_TOKEN'] %>
|
|
||||||
<%= render 'shared/plausible' if !signed_in? && ENV['PLAUSIBLE_DOMAIN'] %>
|
<%= render 'shared/plausible' if !signed_in? && ENV['PLAUSIBLE_DOMAIN'] %>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
<%= javascript_pack_tag 'form', defer: true %>
|
<%= javascript_pack_tag 'form', defer: true %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= stylesheet_pack_tag 'form', media: 'all' %>
|
<%= stylesheet_pack_tag 'form', media: 'all' %>
|
||||||
<%= render 'shared/posthog' if ENV['POSTHOG_TOKEN'] %>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<%= yield %>
|
<%= yield %>
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
<%= javascript_pack_tag 'application', defer: true %>
|
<%= javascript_pack_tag 'application', defer: true %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= stylesheet_pack_tag 'application', media: 'all' %>
|
<%= stylesheet_pack_tag 'application', media: 'all' %>
|
||||||
<%= render 'shared/posthog' if ENV['POSTHOG_TOKEN'] %>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<% if flash.present? %><%= render 'shared/flash' %><% end %>
|
<% if flash.present? %><%= render 'shared/flash' %><% end %>
|
||||||
|
|||||||
@@ -13,17 +13,7 @@
|
|||||||
<%= ff.label :subject, t('subject'), class: 'label' %>
|
<%= ff.label :subject, t('subject'), class: 'label' %>
|
||||||
<%= ff.text_field :subject, required: true, class: 'base-input', dir: 'auto' %>
|
<%= ff.text_field :subject, required: true, class: 'base-input', dir: 'auto' %>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control">
|
<%= render 'personalization_settings/email_body_field', ff:, config: f.object %>
|
||||||
<div class="flex items-center">
|
|
||||||
<%= ff.label :body, t('body'), class: 'label' %>
|
|
||||||
<span class="tooltip" data-tip="<%= t('use_following_placeholders_text_') %> <%= AccountConfig::DEFAULT_VALUES[AccountConfig::SUBMITTER_DOCUMENTS_COPY_EMAIL_KEY].call['body'].scan(/{.*?}/).join(', ') %>">
|
|
||||||
<%= svg_icon('info_circle', class: 'w-4 h-4') %>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<autoresize-textarea>
|
|
||||||
<%= ff.text_area :body, required: true, class: 'base-input w-full py-2', dir: 'auto' %>
|
|
||||||
</autoresize-textarea>
|
|
||||||
</div>
|
|
||||||
<% if can?(:manage, :reply_to) || can?(:manage, :personalization_advanced) %>
|
<% if can?(:manage, :reply_to) || can?(:manage, :personalization_advanced) %>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= ff.label :reply_to, t('reply_to'), class: 'label' %>
|
<%= ff.label :reply_to, t('reply_to'), class: 'label' %>
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<div class="form-control">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<%= ff.label :body, t('body'), class: 'label' %>
|
||||||
|
<span class="tooltip" data-tip="<%= t('use_following_placeholders_text_') %> <%= AccountConfig::DEFAULT_VALUES[local_assigns[:config].key].call['body'].scan(/{.*?}/).join(', ') %>">
|
||||||
|
<%= svg_icon('info_circle', class: 'w-4 h-4') %>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<autoresize-textarea>
|
||||||
|
<%= ff.text_area :body, required: true, class: 'base-input w-full !rounded-2xl py-2', dir: 'auto' %>
|
||||||
|
</autoresize-textarea>
|
||||||
|
</div>
|
||||||
@@ -13,17 +13,7 @@
|
|||||||
<%= ff.label :subject, t('subject'), class: 'label' %>
|
<%= ff.label :subject, t('subject'), class: 'label' %>
|
||||||
<%= ff.text_field :subject, required: true, class: 'base-input', dir: 'auto' %>
|
<%= ff.text_field :subject, required: true, class: 'base-input', dir: 'auto' %>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control">
|
<%= render 'personalization_settings/email_body_field', ff:, config: f.object %>
|
||||||
<div class="flex items-center">
|
|
||||||
<%= ff.label :body, t('body'), class: 'label' %>
|
|
||||||
<span class="tooltip" data-tip="<%= t('use_following_placeholders_text_') %> <%= AccountConfig::DEFAULT_VALUES[AccountConfig::SUBMITTER_INVITATION_EMAIL_KEY].call['body'].scan(/{.*?}/).join(', ') %>">
|
|
||||||
<%= svg_icon('info_circle', class: 'w-4 h-4') %>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<autoresize-textarea>
|
|
||||||
<%= ff.text_area :body, required: true, class: 'base-input w-full py-2', dir: 'auto' %>
|
|
||||||
</autoresize-textarea>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
<div class="form-control pt-2">
|
<div class="form-control pt-2">
|
||||||
<%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button' %>
|
<%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button' %>
|
||||||
|
|||||||
@@ -18,17 +18,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<%= ff.text_field :subject, required: true, class: 'base-input', dir: 'auto' %>
|
<%= ff.text_field :subject, required: true, class: 'base-input', dir: 'auto' %>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control">
|
<%= render 'personalization_settings/email_body_field', ff:, config: f.object %>
|
||||||
<div class="flex items-center">
|
|
||||||
<%= ff.label :body, t('body'), class: 'label' %>
|
|
||||||
<span class="tooltip" data-tip="<%= t('use_following_placeholders_text_') %> <%= AccountConfig::DEFAULT_VALUES[AccountConfig::SUBMITTER_COMPLETED_EMAIL_KEY].call['body'].scan(/{.*?}/).join(', ') %>">
|
|
||||||
<%= svg_icon('info_circle', class: 'w-4 h-4') %>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<autoresize-textarea>
|
|
||||||
<%= ff.text_area :body, required: true, class: 'base-input w-full py-2', dir: 'auto' %>
|
|
||||||
</autoresize-textarea>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center justify-between pt-2.5 mx-1">
|
<div class="flex items-center justify-between pt-2.5 mx-1">
|
||||||
<span>
|
<span>
|
||||||
<%= t('attach_documents') %>
|
<%= t('attach_documents') %>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<a target="_blank" href="<%= Docuseal::GITHUB_URL %>" rel="noopener noreferrer nofollow" class="relative flex items-center rounded-full px-2 py-0.5 text-xs leading-4 mt-1 text-base-content border border-base-300 tooltip tooltip-bottom" data-tip="Give a star on GitHub">
|
<a target="_blank" href="<%= Docuseal::GITHUB_URL %>" rel="noopener noreferrer nofollow" class="relative flex items-center rounded-full px-2 py-0.5 text-xs leading-4 mt-1 text-base-content border border-base-300 tooltip tooltip-bottom" data-tip="Give a star on GitHub">
|
||||||
<span class="flex items-center justify-between space-x-0.5 font-extrabold">
|
<span class="flex items-center justify-between space-x-0.5 font-medium">
|
||||||
<%= svg_icon('start', class: 'h-3 w-3') %>
|
<%= svg_icon('start', class: 'h-3 w-3') %>
|
||||||
<span>9k</span>
|
<span>9k</span>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
<script>
|
|
||||||
!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.async=!0,p.src=s.api_host+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags getFeatureFlag getFeatureFlagPayload reloadFeatureFlags group updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures getActiveMatchingSurveys getSurveys".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
|
|
||||||
posthog.init('<%= ENV.fetch('POSTHOG_TOKEN', nil) %>',{api_host:'https://app.posthog.com',autocapture: false,enable_recording_console_log: true,capture_pageview: false,session_recording:{maskAllInputs: false,maskInputOptions: {password: true}}})
|
|
||||||
</script>
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<div class="block w-full md:w-52 flex-none">
|
<div class="block w-full md:w-52 flex-none">
|
||||||
<menu-active>
|
<menu-active>
|
||||||
<ul id="account_settings_menu" class="menu px-0">
|
<ul id="account_settings_menu" 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">← <%= t('back') %></a></li>
|
<li class="menu-title py-0 !bg-transparent mb-3 -mt-5"><a href="<%= '/' %>" class="!bg-transparent !text-neutral font-medium flex items-center space-x-0.5"><%= svg_icon('arrow_left', class: 'w-4 h-4 stroke-2') %><span><%= t('back') %></span></a></li>
|
||||||
<li class="menu-title py-0 !bg-transparent">
|
<li class="menu-title py-0 !bg-transparent">
|
||||||
<span class="!bg-transparent"><%= t('settings') %></span>
|
<span class="!bg-transparent"><%= t('settings') %></span>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<% has_phone_field = false %>
|
||||||
<%= form_for '', url: template_submissions_path(template), html: { class: 'space-y-4', autocomplete: 'off' }, data: { turbo_frame: :_top } do |f| %>
|
<%= form_for '', url: template_submissions_path(template), html: { class: 'space-y-4', autocomplete: 'off' }, data: { turbo_frame: :_top } do |f| %>
|
||||||
<% submitters = template.submitters.reject { |e| e['invite_by_uuid'].present? || e['optional_invite_by_uuid'].present? } %>
|
<% submitters = template.submitters.reject { |e| e['invite_by_uuid'].present? || e['optional_invite_by_uuid'].present? } %>
|
||||||
<dynamic-list class="space-y-4">
|
<dynamic-list class="space-y-4">
|
||||||
@@ -11,6 +12,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="grid <%= 'md:grid-cols-2' if submitters.size > 1 %> gap-4">
|
<div class="grid <%= 'md:grid-cols-2' if submitters.size > 1 %> gap-4">
|
||||||
<% submitters.each_with_index do |item, index| %>
|
<% submitters.each_with_index do |item, index| %>
|
||||||
|
<% prefillable_fields = local_assigns[:prefillable_fields].to_a.select { |f| f['submitter_uuid'] == item['uuid'] } %>
|
||||||
<submitter-item class="form-control">
|
<submitter-item class="form-control">
|
||||||
<% if submitters.size > 1 %>
|
<% if submitters.size > 1 %>
|
||||||
<label class="label pt-0 pb-1">
|
<label class="label pt-0 pb-1">
|
||||||
@@ -18,30 +20,62 @@
|
|||||||
</label>
|
</label>
|
||||||
<% end %>
|
<% end %>
|
||||||
<input type="hidden" name="submission[1][submitters][][uuid]" value="<%= item['uuid'] %>">
|
<input type="hidden" name="submission[1][submitters][][uuid]" value="<%= item['uuid'] %>">
|
||||||
<submitters-autocomplete data-field="name">
|
<% if prefillable_fields.blank? %>
|
||||||
<linked-input data-target-id="<%= "detailed_name_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
<submitters-autocomplete data-field="name">
|
||||||
<%= tag.input type: 'text', name: 'submission[1][submitters][][name]', autocomplete: 'off', class: 'base-input !h-10 w-full', placeholder: t('name'), required: index.zero? || template.preferences['require_all_submitters'], value: item['email'].present? ? current_account.submitters.accessible_by(current_ability).where.not(name: nil).order(id: :desc).find_by(email: item['email'])&.name : ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : ''), dir: 'auto', id: "detailed_name_#{item['uuid']}" %>
|
<linked-input data-target-id="<%= "detailed_name_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||||
</linked-input>
|
<%= tag.input type: 'text', name: 'submission[1][submitters][][name]', autocomplete: 'off', class: 'base-input !h-10 w-full', placeholder: t('name'), required: index.zero? || template.preferences['require_all_submitters'], value: item['email'].present? ? current_account.submitters.accessible_by(current_ability).where.not(name: nil).order(id: :desc).find_by(email: item['email'])&.name : ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.full_name : ''), dir: 'auto', id: "detailed_name_#{item['uuid']}" %>
|
||||||
</submitters-autocomplete>
|
</linked-input>
|
||||||
<div class="grid <%= 'md:grid-cols-2 gap-1' if submitters.size == 1 %>">
|
</submitters-autocomplete>
|
||||||
|
<div class="grid <%= 'md:grid-cols-2 gap-1' if submitters.size == 1 %>">
|
||||||
|
<submitters-autocomplete data-field="email">
|
||||||
|
<linked-input data-target-id="<%= "detailed_email_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||||
|
<input type="email" multiple name="submission[1][submitters][][email]" autocomplete="off" class="base-input !h-10 mt-1.5 w-full" placeholder="<%= "#{t('email')} (#{t('optional')})" %>" value="<%= item['email'].presence || ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.email : '') %>" id="detailed_email_<%= item['uuid'] %>">
|
||||||
|
</linked-input>
|
||||||
|
</submitters-autocomplete>
|
||||||
|
<% has_phone_field = true %>
|
||||||
|
<submitters-autocomplete data-field="phone">
|
||||||
|
<linked-input data-target-id="<%= "detailed_phone_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||||
|
<%= tag.input type: 'tel', pattern: '^\+[0-9\s\-]+$', oninvalid: "this.value ? this.setCustomValidity('#{t('use_international_format_1xxx_')}') : ''", oninput: "this.setCustomValidity('')", name: 'submission[1][submitters][][phone]', autocomplete: 'off', class: 'base-input !h-10 mt-1.5 w-full', placeholder: local_assigns[:require_phone_2fa] == true ? t(:phone) : "#{t('phone')} (#{t('optional')})", id: "detailed_phone_#{item['uuid']}", required: local_assigns[:require_phone_2fa] == true %>
|
||||||
|
</linked-input>
|
||||||
|
</submitters-autocomplete>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<% if prefillable_fields.present? %>
|
||||||
<submitters-autocomplete data-field="email">
|
<submitters-autocomplete data-field="email">
|
||||||
<linked-input data-target-id="<%= "detailed_email_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
<linked-input data-target-id="<%= "detailed_email_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||||
<input type="email" multiple name="submission[1][submitters][][email]" autocomplete="off" class="base-input !h-10 mt-1.5 w-full" placeholder="<%= "#{t('email')} (#{t('optional')})" %>" value="<%= item['email'].presence || ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.email : '') %>" id="detailed_email_<%= item['uuid'] %>">
|
<input type="email" multiple name="submission[1][submitters][][email]" autocomplete="off" class="base-input !h-10 w-full" placeholder="<%= t('email') %>" value="<%= item['email'].presence || ((params[:selfsign] && index.zero?) || item['is_requester'] ? current_user.email : '') %>" id="detailed_email_<%= item['uuid'] %>" required>
|
||||||
</linked-input>
|
</linked-input>
|
||||||
</submitters-autocomplete>
|
</submitters-autocomplete>
|
||||||
<submitters-autocomplete data-field="phone">
|
<% if local_assigns[:require_phone_2fa] == true || prefillable_fields.any? { |f| f['type'] == 'phone' } %>
|
||||||
<linked-input data-target-id="<%= "detailed_phone_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
<% has_phone_field = true %>
|
||||||
<%= tag.input type: 'tel', pattern: '^\+[0-9\s\-]+$', oninvalid: "this.value ? this.setCustomValidity('#{t('use_international_format_1xxx_')}') : ''", oninput: "this.setCustomValidity('')", name: 'submission[1][submitters][][phone]', autocomplete: 'off', class: 'base-input !h-10 mt-1.5 w-full', placeholder: local_assigns[:require_phone_2fa] == true ? t(:phone) : "#{t('phone')} (#{t('optional')})", id: "detailed_phone_#{item['uuid']}", required: local_assigns[:require_phone_2fa] == true %>
|
<submitters-autocomplete data-field="phone">
|
||||||
</linked-input>
|
<linked-input data-target-id="<%= "detailed_phone_#{item['linked_to_uuid']}" if item['linked_to_uuid'].present? %>">
|
||||||
</submitters-autocomplete>
|
<%= tag.input type: 'tel', pattern: '^\+[0-9\s\-]+$', oninvalid: "this.value ? this.setCustomValidity('#{t('use_international_format_1xxx_')}') : ''", oninput: "this.setCustomValidity('')", name: 'submission[1][submitters][][phone]', autocomplete: 'off', class: 'base-input !h-10 mt-1.5 w-full', placeholder: t(:phone), id: "detailed_phone_#{item['uuid']}", required: true %>
|
||||||
</div>
|
</linked-input>
|
||||||
|
</submitters-autocomplete>
|
||||||
|
<% end %>
|
||||||
|
<% prefillable_fields.each do |field| %>
|
||||||
|
<% if field['type'] == 'checkbox' %>
|
||||||
|
<label for="detailed_field_<%= field['uuid'] %>" class="flex items-center justify-between mt-1.5 pl-3 pr-2.5 h-10 border border-base-content/20 rounded-full cursor-pointer transition-colors bg-white">
|
||||||
|
<span class="text-base select-none px-1"> <%= field['title'].presence || field['name'] %></span>
|
||||||
|
<%= tag.input type: 'checkbox', name: "submission[1][submitters][][values][#{field['uuid']}]", id: "detailed_field_#{field['uuid']}", class: 'toggle toggle-sm', style: 'width: 38px; --handleoffset: 17px', checked: field['default_value'].present? && (field['default_value'] == true || field['default_value'].to_s == '1' || field['default_value'].to_s.downcase == 'true'), required: field['required'], value: 'true' %>
|
||||||
|
</label>
|
||||||
|
<% elsif field['type'] == 'select' || field['type'] == 'radio' %>
|
||||||
|
<%= select_tag "submission[1][submitters][][values][#{field['uuid']}]", options_for_select(field['options'].pluck('value'), field['default_value']), prompt: t(:select), id: "detailed_field_#{field['uuid']}", class: 'select select-sm base-input !h-10 mt-1.5 ', required: field['required'] %>
|
||||||
|
<% elsif field['type'] == 'date' %>
|
||||||
|
<%= tag.input type: field['type'], name: "submission[1][submitters][][values][#{field['uuid']}]", autocomplete: 'off', class: 'base-input !h-10 mt-1.5 w-full border rounded p-3', placeholder: (field['required'] ? field['title'].presence || field['name'] : "#{field['title'].presence || field['name']} (#{t('optional')})"), value: field['default_value'], id: "detailed_field_#{field['uuid']}", required: field['required'] %>
|
||||||
|
<% elsif field['type'] != 'phone' %>
|
||||||
|
<%= tag.input type: field['type'], name: "submission[1][submitters][][values][#{field['uuid']}]", autocomplete: 'off', class: 'base-input !h-10 mt-1.5 w-full border rounded p-3', placeholder: (field['required'] ? field['title'].presence || field['name'] : "#{field['title'].presence || field['name']} (#{t('optional')})"), value: field['default_value'], id: "detailed_field_#{field['uuid']}", required: field['required'] %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
</submitter-item>
|
</submitter-item>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% if params[:selfsign].blank? %>
|
<% if params[:selfsign].blank? && local_assigns[:prefillable_fields].blank? %>
|
||||||
<a href="#" class="btn btn-primary btn-sm w-full flex items-center justify-center" data-action="click:dynamic-list#addItem">
|
<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') %>
|
<%= svg_icon('user_plus', class: 'w-4 h-4 stroke-2') %>
|
||||||
<span><%= t('add_new') %></span>
|
<span><%= t('add_new') %></span>
|
||||||
@@ -51,7 +85,9 @@
|
|||||||
<div>
|
<div>
|
||||||
<%= render('submitters_order', f:, template:) if Accounts.can_send_emails?(current_account) %>
|
<%= render('submitters_order', f:, template:) if Accounts.can_send_emails?(current_account) %>
|
||||||
<%= render 'send_email', f:, template: %>
|
<%= render 'send_email', f:, template: %>
|
||||||
<%= render 'send_sms', f: %>
|
<% if has_phone_field %>
|
||||||
|
<%= render 'send_sms', f: %>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= f.button button_title(title: t('add_recipients')), class: 'base-button' %>
|
<%= f.button button_title(title: t('add_recipients')), class: 'base-button' %>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<% can_send_emails = Accounts.can_send_emails?(current_account) %>
|
<% can_send_emails = Accounts.can_send_emails?(current_account) %>
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<%= f.label :send_email, for: uuid = SecureRandom.uuid, class: 'flex items-center cursor-pointer' do %>
|
<%= f.label :send_email, for: uuid = SecureRandom.uuid, class: 'flex items-center cursor-pointer' do %>
|
||||||
<%= f.check_box :send_email, id: uuid, class: 'base-checkbox', disabled: !can_send_emails || local_assigns[:disable_email], checked: can_send_emails && !local_assigns.key?(:resend_email) && !local_assigns[:disable_email] %>
|
<%= f.check_box :send_email, id: uuid, class: 'base-checkbox', disabled: !can_send_emails || local_assigns[:disable_email], checked: can_send_emails && !local_assigns.key?(:resend_email) && !local_assigns[:disable_email] && template&.preferences&.dig('request_email_enabled') != false %>
|
||||||
<span class="label"><%= local_assigns[:resend_email] ? t('re_send_email') : t('send_email') %></span>
|
<span class="label"><%= local_assigns[:resend_email] ? t('re_send_email') : t('send_email') %></span>
|
||||||
<% end %>
|
<% end %>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -16,15 +16,18 @@
|
|||||||
<div class="truncate uppercase">
|
<div class="truncate uppercase">
|
||||||
ID: <%= attachment.uuid %>
|
ID: <%= attachment.uuid %>
|
||||||
</div>
|
</div>
|
||||||
|
<% if local_assigns[:with_signature_id_reason] != false %>
|
||||||
|
<div>
|
||||||
|
<% reason_value = submitter.values[field.dig('preferences', 'reason_field_uuid')].presence %>
|
||||||
|
<% if reason_value %><%= t('reason') %>: <% end %><%= reason_value || t('digitally_signed_by') %> <%= submitter.name %>
|
||||||
|
<% if submitter.email %>
|
||||||
|
<<%= submitter.email %>>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
<div>
|
<div>
|
||||||
<% reason_value = submitter.values[field.dig('preferences', 'reason_field_uuid')].presence %>
|
<% timezone = local_assigns[:with_submitter_timezone] ? (submitter.timezone || local_assigns[:timezone]) : local_assigns[:timezone] %>
|
||||||
<% if reason_value %><%= t('reason') %>: <% end %><%= reason_value || t('digitally_signed_by') %> <%= submitter.name %>
|
<%= l(attachment.created_at.in_time_zone(timezone), format: :long, locale: local_assigns[:locale]) %> <%= TimeUtils.timezone_abbr(timezone, attachment.created_at) %>
|
||||||
<% if submitter.email %>
|
|
||||||
<<%= submitter.email %>>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<%= l(attachment.created_at.in_time_zone(local_assigns[:timezone]), format: :long, locale: local_assigns[:locale]) %> <%= TimeUtils.timezone_abbr(local_assigns[:timezone], attachment.created_at) %>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
<% require_phone_2fa = @template.preferences['require_phone_2fa'] == true %>
|
<% require_phone_2fa = @template.preferences['require_phone_2fa'] == true %>
|
||||||
|
<% prefillable_fields = @template.fields.select { |f| f['prefillable'] } %>
|
||||||
|
<% only_detailed = require_phone_2fa || prefillable_fields.present? %>
|
||||||
<%= render 'shared/turbo_modal_large', title: params[:selfsign] ? t('add_recipients') : t('add_new_recipients') do %>
|
<%= render 'shared/turbo_modal_large', title: params[:selfsign] ? t('add_recipients') : t('add_new_recipients') do %>
|
||||||
<% options = [require_phone_2fa ? nil : [t('via_email'), 'email'], require_phone_2fa ? nil : [t('via_phone'), 'phone'], [t('detailed'), 'detailed'], [t('upload_list'), 'list']].compact %>
|
<% options = [only_detailed ? nil : [t('via_email'), 'email'], only_detailed ? nil : [t('via_phone'), 'phone'], [t('detailed'), 'detailed'], [t('upload_list'), 'list']].compact %>
|
||||||
<toggle-visible data-element-ids="<%= options.map(&:last).to_json %>" class="relative text-center px-2 mt-4 block">
|
<toggle-visible data-element-ids="<%= options.map(&:last).to_json %>" class="relative text-center px-2 mt-4 block">
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
<% options.each_with_index do |(label, value), index| %>
|
<% options.each_with_index do |(label, value), index| %>
|
||||||
<div>
|
<div>
|
||||||
<%= radio_button_tag 'option', value, value == (require_phone_2fa ? 'detailed' : 'email'), class: 'peer hidden', data: { action: 'change:toggle-visible#trigger' } %>
|
<%= radio_button_tag 'option', value, value == (only_detailed ? 'detailed' : 'email'), class: 'peer hidden', data: { action: 'change:toggle-visible#trigger' } %>
|
||||||
<label for="option_<%= value %>" class="block bg-base-200 md:min-w-[112px] text-sm font-semibold whitespace-nowrap py-1.5 px-4 peer-checked:bg-base-300 <%= 'hidden sm:inline-block' if value == 'list' %> <%= 'rounded-l-3xl' if index.zero? %> <%= 'rounded-r-3xl sm:rounded-r-none' if value == 'detailed' %> <%= 'rounded-r-3xl' if index == options.size - 1 %>">
|
<label for="option_<%= value %>" class="block bg-base-200 md:min-w-[112px] text-sm font-semibold whitespace-nowrap py-1.5 px-4 peer-checked:bg-base-300 <%= 'hidden sm:inline-block' if value == 'list' %> <%= 'rounded-l-3xl' if index.zero? %> <%= 'rounded-r-3xl sm:rounded-r-none' if value == 'detailed' %> <%= 'rounded-r-3xl' if index == options.size - 1 %>">
|
||||||
<%= label %>
|
<%= label %>
|
||||||
</label>
|
</label>
|
||||||
@@ -14,7 +16,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</toggle-visible>
|
</toggle-visible>
|
||||||
<div class="px-5 mb-5 mt-4">
|
<div class="px-5 mb-5 mt-4">
|
||||||
<% unless require_phone_2fa %>
|
<% unless only_detailed %>
|
||||||
<div id="email">
|
<div id="email">
|
||||||
<%= render 'email_form', template: @template %>
|
<%= render 'email_form', template: @template %>
|
||||||
</div>
|
</div>
|
||||||
@@ -22,8 +24,8 @@
|
|||||||
<%= render 'phone_form', template: @template %>
|
<%= render 'phone_form', template: @template %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<div id="detailed" class="<%= 'hidden' unless require_phone_2fa %>">
|
<div id="detailed" class="<%= 'hidden' unless only_detailed %>">
|
||||||
<%= render 'detailed_form', template: @template, require_phone_2fa: %>
|
<%= render 'detailed_form', template: @template, require_phone_2fa:, prefillable_fields: %>
|
||||||
</div>
|
</div>
|
||||||
<div id="list" class="hidden">
|
<div id="list" class="hidden">
|
||||||
<%= render 'list_form', template: @template %>
|
<%= render 'list_form', template: @template %>
|
||||||
|
|||||||
@@ -2,7 +2,11 @@
|
|||||||
<%= render 'submissions/preview_tags' %>
|
<%= render 'submissions/preview_tags' %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% font_scale = 1040.0 / PdfUtils::US_LETTER_W %>
|
<% font_scale = 1040.0 / PdfUtils::US_LETTER_W %>
|
||||||
<% with_signature_id, is_combined_enabled = AccountConfig.where(account_id: @submission.account_id, key: [AccountConfig::COMBINE_PDF_RESULT_KEY, AccountConfig::WITH_SIGNATURE_ID], value: true).then { |configs| [configs.any? { |e| e.key == AccountConfig::WITH_SIGNATURE_ID }, configs.any? { |e| e.key == AccountConfig::COMBINE_PDF_RESULT_KEY }] } %>
|
<% configs = AccountConfig.where(account_id: @submission.account_id, key: [AccountConfig::COMBINE_PDF_RESULT_KEY, AccountConfig::WITH_SIGNATURE_ID, AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY, AccountConfig::WITH_SIGNATURE_ID_REASON_KEY]) %>
|
||||||
|
<% with_signature_id = configs.find { |e| e.key == AccountConfig::WITH_SIGNATURE_ID }&.value == true %>
|
||||||
|
<% is_combined_enabled = configs.find { |e| e.key == AccountConfig::COMBINE_PDF_RESULT_KEY }&.value == true %>
|
||||||
|
<% with_submitter_timezone = configs.find { |e| e.key == AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY }&.value == true %>
|
||||||
|
<% with_signature_id_reason = configs.find { |e| e.key == AccountConfig::WITH_SIGNATURE_ID_REASON_KEY }&.value != false %>
|
||||||
<div style="max-width: 1600px" class="mx-auto pl-4">
|
<div style="max-width: 1600px" class="mx-auto pl-4">
|
||||||
<div class="flex justify-between py-1.5 items-center pr-4 sticky top-0 md:relative z-10 bg-base-100">
|
<div class="flex justify-between py-1.5 items-center pr-4 sticky top-0 md:relative z-10 bg-base-100">
|
||||||
<a href="<%= signed_in? && @submission.account_id == current_account&.id && @submission.template ? template_path(@submission.template) : '/' %>" class="flex items-center space-x-3 py-1">
|
<a href="<%= signed_in? && @submission.account_id == current_account&.id && @submission.template ? template_path(@submission.template) : '/' %>" class="flex items-center space-x-3 py-1">
|
||||||
@@ -108,17 +112,18 @@
|
|||||||
<% value = values[field['uuid']] %>
|
<% value = values[field['uuid']] %>
|
||||||
<% value ||= field['default_value'] if field['type'] == 'heading' %>
|
<% value ||= field['default_value'] if field['type'] == 'heading' %>
|
||||||
<% next if value.blank? %>
|
<% next if value.blank? %>
|
||||||
|
<% submitter = submitters_index[field['submitter_uuid']] %>
|
||||||
<% if (mask = field.dig('preferences', 'mask').presence) && signed_in? && can?(:read, @submission) %>
|
<% if (mask = field.dig('preferences', 'mask').presence) && signed_in? && can?(:read, @submission) %>
|
||||||
<span class="group">
|
<span class="group">
|
||||||
<span class="hidden group-hover:inline">
|
<span class="hidden group-hover:inline">
|
||||||
<%= render 'submissions/value', font_scale:, area:, field:, attachments_index:, value:, locale: @submission.account.locale, timezone: @submission.account.timezone, submitter: submitters_index[field['submitter_uuid']], with_signature_id: %>
|
<%= render 'submissions/value', font_scale:, area:, field:, attachments_index:, value:, locale: @submission.account.locale, timezone: @submission.account.timezone, submitter:, with_signature_id: %>
|
||||||
</span>
|
</span>
|
||||||
<span class="group-hover:hidden">
|
<span class="group-hover:hidden">
|
||||||
<%= render 'submissions/value', font_scale:, area:, field:, attachments_index:, value: Array.wrap(value).map { |e| TextUtils.mask_value(e, mask) }.join(', '), locale: @submission.account.locale, timezone: @submission.account.timezone, submitter: submitters_index[field['submitter_uuid']], with_signature_id: %>
|
<%= render 'submissions/value', font_scale:, area:, field:, attachments_index:, value: Array.wrap(value).map { |e| TextUtils.mask_value(e, mask) }.join(', '), locale: @submission.account.locale, timezone: @submission.account.timezone, submitter:, with_signature_id: %>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= render 'submissions/value', font_scale:, area:, field:, attachments_index:, value: mask.present? ? Array.wrap(value).map { |e| TextUtils.mask_value(e, mask) }.join(', ') : value, locale: @submission.account.locale, timezone: @submission.account.timezone, submitter: submitters_index[field['submitter_uuid']], with_signature_id: %>
|
<%= render 'submissions/value', font_scale:, area:, field:, attachments_index:, value: mask.present? ? Array.wrap(value).map { |e| TextUtils.mask_value(e, mask) }.join(', ') : value, locale: @submission.account.locale, timezone: @submission.account.timezone, submitter:, with_signature_id:, with_submitter_timezone:, with_signature_id_reason: %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<% filter_params = params.permit(Submissions::Filter::ALLOWED_PARAMS).compact_blank %>
|
<% filter_params = params.permit(Submissions::Filter::ALLOWED_PARAMS).compact_blank %>
|
||||||
<div>
|
<div>
|
||||||
<%= link_to root_path do %>
|
<%= link_to root_path, class: 'flex items-center' do %>
|
||||||
←
|
<%= svg_icon('chevron_left', class: 'w-5 h-5') %>
|
||||||
<span><%= t('back_to_active') %></span>
|
<span style="margin-left: 3px"><%= t('back_to_active') %></span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col md:flex-row md:items-center mb-4 gap-3">
|
<div class="flex flex-col md:flex-row md:items-center mb-4 gap-3">
|
||||||
<div class="flex w-full justify-between">
|
<div class="flex w-full justify-between items-center">
|
||||||
<div>
|
<div>
|
||||||
<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>
|
<h1 class="text-2xl md:text-3xl 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>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<% if params[:q].present? || @pagy.pages > 1 || filter_params.present? %>
|
<% if params[:q].present? || @pagy.pages > 1 || filter_params.present? %>
|
||||||
|
|||||||
@@ -10,6 +10,17 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<% if params[:folder].present? %>
|
||||||
|
<div class="tooltip tooltip-bottom 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-34 border-neutral-700" data-tip="<%= t('folder') %>">
|
||||||
|
<%= link_to submissions_filter_path('folder', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 w-full pr-1 md:max-w-[140px]' do %>
|
||||||
|
<%= svg_icon('folder', class: 'w-5 h-5 shrink-0') %>
|
||||||
|
<span class="font-normal truncate"><%= params[:folder] %></span>
|
||||||
|
<% end %>
|
||||||
|
<%= link_to url_for(params.to_unsafe_h.except(:folder)), class: 'rounded-lg ml-1 hover:bg-base-content hover:text-white' do %>
|
||||||
|
<%= svg_icon('x', class: 'w-5 h-5') %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
<% if params[:author].present? %>
|
<% if params[:author].present? %>
|
||||||
<div class="tooltip tooltip-bottom 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-34 border-neutral-700" data-tip="<%= t('author') %>">
|
<div class="tooltip tooltip-bottom 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-34 border-neutral-700" data-tip="<%= t('author') %>">
|
||||||
<%= link_to submissions_filter_path('author', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 w-full pr-1 md:max-w-[140px]' do %>
|
<%= link_to submissions_filter_path('author', query_params.merge(path: url_for, with_remove: true)), data: { turbo_frame: 'modal' }, class: 'flex items-center space-x-1 w-full pr-1 md:max-w-[140px]' do %>
|
||||||
|
|||||||
@@ -84,7 +84,7 @@
|
|||||||
<% next if field['conditions'].present? && values[field['uuid']].blank? && field['submitter_uuid'] != @submitter.uuid %>
|
<% next if field['conditions'].present? && values[field['uuid']].blank? && field['submitter_uuid'] != @submitter.uuid %>
|
||||||
<% next if field['conditions'].present? && field['submitter_uuid'] == @submitter.uuid %>
|
<% next if field['conditions'].present? && field['submitter_uuid'] == @submitter.uuid %>
|
||||||
<% next if field.dig('preferences', 'formula').present? && field['submitter_uuid'] == @submitter.uuid %>
|
<% next if field.dig('preferences', 'formula').present? && field['submitter_uuid'] == @submitter.uuid %>
|
||||||
<%= render 'submissions/value', font_scale:, area:, field:, attachments_index: @attachments_index, value: field.dig('preferences', 'mask').present? ? TextUtils.mask_value(value, field.dig('preferences', 'mask')) : value, locale: @submitter.account.locale, timezone: @submitter.account.timezone, submitter: submitters_index[field['submitter_uuid']], with_signature_id: @form_configs[:with_signature_id] %>
|
<%= render 'submissions/value', font_scale:, area:, field:, attachments_index: @attachments_index, value: field.dig('preferences', 'mask').present? ? TextUtils.mask_value(value, field.dig('preferences', 'mask')) : value, locale: @submitter.account.locale, timezone: @submitter.account.timezone, submitter: submitters_index[field['submitter_uuid']], with_signature_id: @form_configs[:with_signature_id], with_submitter_timezone: @form_configs[:with_submitter_timezone], with_signature_id_reason: @form_configs[:with_signature_id_reason] %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</page-container>
|
</page-container>
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
<%= javascript_pack_tag 'draw', defer: true %>
|
<%= javascript_pack_tag 'draw', defer: true %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= stylesheet_pack_tag 'form', media: 'all' %>
|
<%= stylesheet_pack_tag 'form', media: 'all' %>
|
||||||
<%= render 'shared/posthog' if ENV['POSTHOG_TOKEN'] %>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<% field = (@submitter.submission.template_fields || @submitter.template.fields).find { |f| f['type'] == 'signature' && f['uuid'].starts_with?(params[:f]) } %>
|
<% field = (@submitter.submission.template_fields || @submitter.template.fields).find { |f| f['type'] == 'signature' && f['uuid'].starts_with?(params[:f]) } %>
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
<% if @email_config || @body.present? %>
|
<% if @body.present? %>
|
||||||
<% body = (@body.presence || @email_config.value['body']).to_s %>
|
<%= render 'custom_content', content: @body, submitter: @submitter %>
|
||||||
<%= render 'custom_content', content: body, submitter: @submitter %>
|
<% if !@body.match?(ReplaceEmailVariables::SUBMITTER_LINK) && !@body.match?(ReplaceEmailVariables::SUBMITTER_ID) && !@body.match?(ReplaceEmailVariables::SUBMISSION_LINK) && !@body.match?(ReplaceEmailVariables::TEMPLATE_ID) && !@submitter.submission.source.in?(%w[api embed]) %>
|
||||||
<% if !body.match?(ReplaceEmailVariables::SUBMITTER_LINK) && !body.match?(ReplaceEmailVariables::SUBMITTER_ID) && !body.match?(ReplaceEmailVariables::SUBMISSION_LINK) && !body.match?(ReplaceEmailVariables::TEMPLATE_ID) && !@submitter.submission.source.in?(%w[api embed]) %>
|
|
||||||
<p><%= link_to nil, submit_form_url(slug: @submitter.slug, t: SubmissionEvents.build_tracking_param(@submitter, 'click_email')) %></p>
|
<p><%= link_to nil, submit_form_url(slug: @submitter.slug, t: SubmissionEvents.build_tracking_param(@submitter, 'click_email')) %></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<p><%= t('hi_there') %>,</p>
|
<p><%= t('hi_there') %>,</p>
|
||||||
<p><%= I18n.t(@submitter.with_signature_fields? ? :you_have_been_invited_to_sign_the_name : :you_have_been_invited_to_submit_the_name_form, name: @submitter.submission.name || @submitter.submission.template.name) %></p>
|
<p><%= I18n.t(@submitter.with_signature_fields? ? :you_have_been_invited_to_sign_the_name : :you_have_been_invited_to_submit_the_name_form, name: @submitter.submission.name || @submitter.submission.template.name) %></p>
|
||||||
<p><%= link_to I18n.t(@submitter.with_signature_fields? ? :review_and_sign : :review_and_submit), submit_form_url(slug: @submitter.slug, t: SubmissionEvents.build_tracking_param(@submitter, 'click_email'), host: ENV.fetch('EMAIL_HOST', Docuseal.default_url_options[:host])) %></p>
|
<p><%= link_to I18n.t(@submitter.with_signature_fields? ? :review_and_sign : :review_and_submit), submit_form_url(slug: @submitter.slug, t: SubmissionEvents.build_tracking_param(@submitter, 'click_email'), host: ENV.fetch('EMAIL_HOST', Docuseal.default_url_options[:host])) %></p>
|
||||||
<p><%= t('please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this') %></p>
|
<p><%= t('please_contact_us_by_replying_to_this_email_if_you_have_any_questions') %></p>
|
||||||
<p>
|
<p>
|
||||||
<%= t('thanks') %>,<br><%= @current_account.name %>
|
<%= t('thanks') %>,<br><%= @current_account.name %>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<% is_long = folder.name.size > 32 %>
|
<% is_long = folder.name.size > 32 %>
|
||||||
<a href="<%= folder_path(folder) %>" class="flex h-full flex-col justify-between rounded-2xl py-5 px-6 w-full bg-base-200 before:border-2 before:border-base-300 before:border-dashed before:absolute before:left-0 before:right-0 before:top-0 before:bottom-0 before:hidden before:rounded-2xl relative" data-targets="dashboard-dropzone.folderCards">
|
<a href="<%= folder_path(folder) %>" class="flex h-full flex-col justify-between rounded-2xl py-5 px-6 w-full bg-base-200 before:border-2 before:border-base-300 before:border-dashed before:absolute before:left-0 before:right-0 before:top-0 before:bottom-0 before:hidden before:rounded-2xl relative" data-targets="dashboard-dropzone.folderCards" data-full-name="<%= folder.full_name %>">
|
||||||
<% if !is_long %>
|
<% if !is_long %>
|
||||||
<%= svg_icon('folder', class: 'w-6 h-6') %>
|
<%= svg_icon('folder', class: 'w-6 h-6') %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1,24 +1,27 @@
|
|||||||
<div>
|
<div>
|
||||||
<%= link_to root_path do %>
|
<%= link_to @template_folder.parent_folder ? folder_path(@template_folder.parent_folder) : root_path, class: 'flex items-center' do %>
|
||||||
←
|
<%= svg_icon('chevron_left', class: 'w-5 h-5') %>
|
||||||
<span><%= t('home') %></span>
|
<span style="margin-left: 3px"><%= @template_folder.parent_folder&.name || t('home') %></span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<dashboard-dropzone>
|
<dashboard-dropzone>
|
||||||
<div class="relative flex justify-between items-center w-full mb-4">
|
<div class="relative flex justify-between items-center w-full mb-4">
|
||||||
<%= form_for '', url: '', id: form_id = SecureRandom.uuid, method: :post, class: 'hidden', data: { target: 'dashboard-dropzone.form' }, html: { enctype: 'multipart/form-data' } do %>
|
<%= form_for '', url: '', id: form_id = SecureRandom.uuid, method: :post, class: 'hidden', data: { target: 'dashboard-dropzone.form' }, html: { enctype: 'multipart/form-data' } do %>
|
||||||
<input name="form_id" value="<%= form_id %>">
|
<input name="form_id" value="<%= form_id %>">
|
||||||
<input name="folder_name" value="<%= @template_folder.name %>">
|
<input name="folder_name" value="<%= @template_folder.full_name %>">
|
||||||
<button type="submit"></button>
|
<button type="submit"></button>
|
||||||
<input id="dashboard_dropzone_input" name="files[]" type="file" multiple>
|
<input id="dashboard_dropzone_input" name="files[]" type="file" multiple>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= render 'templates/dashboard_dropzone', style: 'height: 137px' %>
|
<%= render 'templates/dashboard_dropzone', style: 'height: 137px' %>
|
||||||
|
<% unless @template_folder.parent_folder %>
|
||||||
|
<%= render 'templates/dashboard_folder_dropzone', style: 'height: 137px' %>
|
||||||
|
<% end %>
|
||||||
<h1 class="text-2xl truncate md:text-3xl font-bold flex items-center flex-grow min-w-0 space-x-2 md:flex <%= 'hidden' if params[:q].present? %>">
|
<h1 class="text-2xl truncate md:text-3xl font-bold flex items-center flex-grow min-w-0 space-x-2 md:flex <%= 'hidden' if params[:q].present? %>">
|
||||||
<%= svg_icon('folder', class: 'w-9 h-9 flex-shrink-0') %>
|
<%= svg_icon('folder', class: 'w-9 h-9 flex-shrink-0') %>
|
||||||
<span class="peer truncate">
|
<span class="peer truncate">
|
||||||
<%= @template_folder.name %>
|
<%= @template_folder.name %>
|
||||||
</span>
|
</span>
|
||||||
<% if can?(:update, @template_folder) && @template_folder.name != TemplateFolder::DEFAULT_NAME %>
|
<% if can?(:update, @template_folder) && @template_folder.full_name != TemplateFolder::DEFAULT_NAME %>
|
||||||
<span class="opacity-0 hover:opacity-100 peer-hover:opacity-100">
|
<span class="opacity-0 hover:opacity-100 peer-hover:opacity-100">
|
||||||
<a href="<%= edit_folder_path(@template_folder) %>" data-turbo-frame="modal">
|
<a href="<%= edit_folder_path(@template_folder) %>" data-turbo-frame="modal">
|
||||||
<%= svg_icon('pencil', class: 'w-7 h-7') %>
|
<%= svg_icon('pencil', class: 'w-7 h-7') %>
|
||||||
@@ -27,18 +30,23 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</h1>
|
</h1>
|
||||||
<div class="flex space-x-2">
|
<div class="flex space-x-2">
|
||||||
<% if params[:q].present? || @pagy.pages > 1 %>
|
<% if params[:q].present? || @pagy.pages > 1 || @template_folders.present? %>
|
||||||
<%= render 'shared/search_input' %>
|
<%= render 'shared/search_input' %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if can?(:create, ::Template) %>
|
<% if can?(:create, ::Template) %>
|
||||||
<%= render 'templates/upload_button', folder_name: @template_folder.name %>
|
<%= render 'templates/upload_button', folder_name: @template_folder.full_name %>
|
||||||
<%= link_to new_template_path(folder_name: @template_folder.name), class: 'white-button !border gap-2', data: { turbo_frame: :modal } do %>
|
<%= link_to new_template_path(folder_name: @template_folder.full_name), class: 'white-button !border gap-2', data: { turbo_frame: :modal } do %>
|
||||||
<%= svg_icon('plus', class: 'w-6 h-6 stroke-2') %>
|
<%= svg_icon('plus', class: 'w-6 h-6 stroke-2') %>
|
||||||
<span class="hidden md:block"><%= t('create') %></span>
|
<span class="hidden md:block"><%= t('create') %></span>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<% if @template_folders.present? %>
|
||||||
|
<div class="grid gap-4 md:grid-cols-3 <%= 'mb-6' if @templates.present? %>">
|
||||||
|
<%= render partial: 'template_folders/folder', collection: @template_folders, as: :folder %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
<% if @pagy.count.nil? || @pagy.count > 0 %>
|
<% if @pagy.count.nil? || @pagy.count > 0 %>
|
||||||
<div class="grid gap-4 md:grid-cols-3">
|
<div class="grid gap-4 md:grid-cols-3">
|
||||||
<%= render partial: 'templates/template', collection: @templates %>
|
<%= render partial: 'templates/template', collection: @templates %>
|
||||||
@@ -48,12 +56,21 @@
|
|||||||
<%= render 'shared/templates_order_select', with_recently_used: @pagy.count.present? && @pagy.count < 10_000 && !can?(:manage, :countless), selected_order: %>
|
<%= render 'shared/templates_order_select', with_recently_used: @pagy.count.present? && @pagy.count < 10_000 && !can?(:manage, :countless), selected_order: %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= render 'shared/pagination', pagy: @pagy, items_name: 'templates', right_additional_html: templates_order_select_html %>
|
<%= render 'shared/pagination', pagy: @pagy, items_name: @templates.present? ? 'templates' : 'template_folders', right_additional_html: templates_order_select_html %>
|
||||||
<% elsif params[:q].present? %>
|
<% elsif params[:q].present? %>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<div class="mt-16 text-3xl font-semibold">
|
<div class="mt-16 text-3xl font-semibold">
|
||||||
<%= t('templates_not_found') %>
|
<%= t('templates_not_found') %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<% if @related_submissions.present? %>
|
||||||
|
<h1 class="text-2xl md:text-3xl sm:text-4xl font-bold mt-8 md:mt-4">
|
||||||
|
<%= t('submissions') %>
|
||||||
|
</h1>
|
||||||
|
<div class="space-y-4 mt-4">
|
||||||
|
<%= render partial: 'templates/submission', collection: @related_submissions, locals: { with_template: true } %>
|
||||||
|
</div>
|
||||||
|
<%= render 'shared/pagination', pagy: @related_submissions_pagy, items_name: 'submissions', next_page_path: submissions_path(q: params[:q], folder: @template_folder.full_name) %>
|
||||||
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</dashboard-dropzone>
|
</dashboard-dropzone>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<div class="absolute bottom-0 w-full cursor-pointer rounded-xl bg-base-100 border-2 border-base-300 border-dashed hidden z-50" data-target="dashboard-dropzone.folderDropzone" style="<%= local_assigns[:style] %>">
|
||||||
|
<div class="absolute top-0 right-0 left-0 bottom-0 flex justify-center p-2 items-center pointer-events-none">
|
||||||
|
<div class="flex flex-col items-center text-center" data-target="dashboard-dropzone.toggleLoading">
|
||||||
|
<span class="flex flex-col items-center">
|
||||||
|
<span>
|
||||||
|
<%= svg_icon('folder_plus', class: 'w-9 h-9') %>
|
||||||
|
</span>
|
||||||
|
<div class="font-medium mb-1">
|
||||||
|
<%= t('create_a_new_folder') %>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
<span class="flex flex-col items-center hidden" data-target="dashboard-dropzone.fileDropzoneLoading">
|
||||||
|
<%= svg_icon('loader', class: 'w-9 h-9 animate-spin') %>
|
||||||
|
<div class="font-medium mb-1">
|
||||||
|
<%= t('loading') %>...
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<div class="h-36 relative group">
|
<div class="h-36 relative group">
|
||||||
<a href="<%= template_path(template) %>" class="flex h-full flex-col justify-between rounded-2xl pt-6 px-7 w-full bg-base-200 before:border-2 before:border-base-300 before:border-dashed before:absolute before:left-0 before:right-0 before:top-0 before:bottom-0 before:hidden before:rounded-2xl" data-targets="dashboard-dropzone.templateCards">
|
<a href="<%= template_path(template) %>" class="flex h-full flex-col justify-between rounded-2xl pt-6 px-7 w-full bg-base-200 before:border-2 before:border-base-300 before:border-dashed before:absolute before:left-0 before:right-0 before:top-0 before:bottom-0 before:hidden before:rounded-2xl" data-targets="dashboard-dropzone.templateCards">
|
||||||
<div class="text-xl font-semibold" style="overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;">
|
<div class="text-xl font-semibold" style="line-height: 1.6rem; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;">
|
||||||
<% if template.template_accesses.present? %>
|
<% if template.template_accesses.present? %>
|
||||||
<%= svg_icon('lock', class: 'w-6 h-6 inline -translate-y-[4px]') %>
|
<%= svg_icon('lock', class: 'w-6 h-6 inline -translate-y-[4px]') %>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
<% if template.archived_at? %>
|
<% if template.archived_at? %>
|
||||||
<span class="flex items-center space-x-1 w-1/2">
|
<span class="flex items-center space-x-1 w-1/2">
|
||||||
<%= svg_icon('folder', class: 'w-4 h-4 flex-shrink-0') %>
|
<%= svg_icon('folder', class: 'w-4 h-4 flex-shrink-0') %>
|
||||||
<span class="truncate"><%= template.folder.name %></span>
|
<span class="truncate"><%= template.folder.full_name %></span>
|
||||||
</span>
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -16,12 +16,12 @@
|
|||||||
<a href="<%= folder_path(@template.folder) %>" class="flex items-center space-x-1 mt-1 peer">
|
<a href="<%= folder_path(@template.folder) %>" class="flex items-center space-x-1 mt-1 peer">
|
||||||
<%= svg_icon('folder', class: 'w-5 h-5 flex-shrink-0') %>
|
<%= svg_icon('folder', class: 'w-5 h-5 flex-shrink-0') %>
|
||||||
<span class="text-sm">
|
<span class="text-sm">
|
||||||
<%= @template.folder.name %>
|
<%= @template.folder.full_name %>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
<% if can?(:update, template) %>
|
<% if can?(:update, template) %>
|
||||||
<span class="pl-1 tooltip tooltip-right md:opacity-0 hover:opacity-100 peer-hover:opacity-100" data-tip="<%= t('move') %>">
|
<span class="pl-1 tooltip tooltip-right md:opacity-0 hover:opacity-100 peer-hover:opacity-100" data-tip="<%= t('move') %>">
|
||||||
<a href="<%= edit_template_folder_path(template.id) %>" data-turbo-frame="modal">
|
<a href="<%= edit_template_folder_path(template.id, subfolder: @template.folder.parent_folder.present?) %>" data-turbo-frame="modal">
|
||||||
<%= svg_icon('pencil_share', class: 'w-5 h-5') %>
|
<%= svg_icon('pencil_share', class: 'w-5 h-5') %>
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<%= svg_icon('folder', class: 'w-6 h-6') %>
|
<%= svg_icon('folder', class: 'w-6 h-6') %>
|
||||||
</a>
|
</a>
|
||||||
<folder-autocomplete class="flex justify-between w-full">
|
<folder-autocomplete class="flex justify-between w-full">
|
||||||
<input id="folder_name" placeholder="<%= t('folder_name') %>" type="text" class="w-full outline-none border-transparent focus:border-transparent focus:ring-0 bg-base-100 px-1 peer" name="folder_name" value="<%= params[:folder_name].presence || @base_template&.folder&.name || TemplateFolder::DEFAULT_NAME %>" onblur="window.folder_name.value = window.folder_name.value || 'Default'" autocomplete="off">
|
<input id="folder_name" placeholder="<%= t('folder_name') %>" type="text" class="w-full outline-none border-transparent focus:border-transparent focus:ring-0 bg-base-100 px-1 peer" name="folder_name" value="<%= params[:folder_name].presence || @base_template&.folder&.full_name || TemplateFolder::DEFAULT_NAME %>" onblur="window.folder_name.value = window.folder_name.value || 'Default'" autocomplete="off">
|
||||||
<a href="#" onclick="[event.preventDefault(), window.folder_name.value = '', window.folder_name.focus()]" class="shrink-0 link peer-focus:hidden mr-1.5">
|
<a href="#" onclick="[event.preventDefault(), window.folder_name.value = '', window.folder_name.focus()]" class="shrink-0 link peer-focus:hidden mr-1.5">
|
||||||
<%= t('change_folder') %>
|
<%= t('change_folder') %>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<div>
|
<div>
|
||||||
<%= link_to root_path do %>
|
<%= link_to root_path, class: 'flex items-center' do %>
|
||||||
←
|
<%= svg_icon('chevron_left', class: 'w-5 h-5') %>
|
||||||
<span><%= t('back_to_active') %></span>
|
<span style="margin-left: 3px"><%= t('back_to_active') %></span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between mb-4 items-center">
|
<div class="flex justify-between mb-4 items-center">
|
||||||
<div>
|
<div>
|
||||||
<h1 class="text-4xl font-bold md:block <%= 'hidden' if params[:q].present? %>"><%= t('document_templates_html') %> <span class="badge badge-outline badge-lg align-middle"><%= t('archived') %></span></h1>
|
<h1 class="text-2xl md:text-3xl font-bold md:block <%= 'hidden' if params[:q].present? %>"><%= t('document_templates_html') %> <span class="badge badge-outline badge-lg align-middle"><%= t('archived') %></span></h1>
|
||||||
</div>
|
</div>
|
||||||
<% if params[:q].present? || @pagy.pages > 1 %>
|
<% if params[:q].present? || @pagy.pages > 1 %>
|
||||||
<%= render 'shared/search_input', placeholder: "#{t('search')}..." %>
|
<%= render 'shared/search_input', placeholder: "#{t('search')}..." %>
|
||||||
@@ -22,5 +22,14 @@
|
|||||||
<%= t('templates_not_found') %>
|
<%= t('templates_not_found') %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<% if @related_submissions.present? %>
|
||||||
|
<h1 class="text-2xl md:text-3xl sm:text-4xl font-bold mt-8 md:mt-4">
|
||||||
|
<%= t('submissions') %>
|
||||||
|
</h1>
|
||||||
|
<div class="space-y-4 mt-4">
|
||||||
|
<%= render partial: 'templates/submission', collection: @related_submissions, locals: { with_template: true } %>
|
||||||
|
</div>
|
||||||
|
<%= render 'shared/pagination', pagy: @related_submissions_pagy, items_name: 'submissions', next_page_path: submissions_archived_index_path(q: params[:q]) %>
|
||||||
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= render 'shared/pagination', pagy: @pagy, items_name: 'templates' %>
|
<%= render 'shared/pagination', pagy: @pagy, items_name: 'templates' %>
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
<% filter_params = params.permit(Submissions::Filter::ALLOWED_PARAMS).compact_blank %>
|
<% filter_params = params.permit(Submissions::Filter::ALLOWED_PARAMS).compact_blank %>
|
||||||
<% with_filters = @pagy.pages > 1 || params[:q].present? || filter_params.present? %>
|
<% with_filters = @pagy.pages > 1 || params[:q].present? || filter_params.present? %>
|
||||||
<%= render 'templates/title', template: @template %>
|
<%= render 'templates/title', template: @template %>
|
||||||
<div>
|
|
||||||
<%= link_to template_path(@template) do %>
|
|
||||||
←
|
|
||||||
<span><%= t('back_to_active') %></span>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col md:flex-row md:items-center mb-6 gap-3">
|
<div class="flex flex-col md:flex-row md:items-center mb-6 gap-3">
|
||||||
<div class="flex w-full justify-between md:items-end items-center">
|
<div class="flex w-full justify-between md:items-end items-end">
|
||||||
<div>
|
<div>
|
||||||
|
<div>
|
||||||
|
<%= link_to template_path(@template), class: 'flex items-center' do %>
|
||||||
|
<%= svg_icon('chevron_left', class: 'w-5 h-5') %>
|
||||||
|
<span style="margin-left: 3px"><%= t('back_to_active') %></span>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
<h1 class="text-3xl font-bold md:block"><%= t('submissions') %> <span class="badge badge-outline badge-lg align-middle"><%= t('archived') %></span></h1>
|
<h1 class="text-3xl font-bold md:block"><%= t('submissions') %> <span class="badge badge-outline badge-lg align-middle"><%= t('archived') %></span></h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex space-x-2 justify-end">
|
<div class="flex space-x-2 justify-end">
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
<% unless show_dropzone %>
|
<% unless show_dropzone %>
|
||||||
<%= render 'templates/dashboard_dropzone', style: 'height: 114px' %>
|
<%= render 'templates/dashboard_dropzone', style: 'height: 114px' %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<%= render 'templates/dashboard_folder_dropzone', style: 'height: 114px' %>
|
||||||
<div class="flex items-center flex-grow min-w-0">
|
<div class="flex items-center flex-grow min-w-0">
|
||||||
<% if has_archived || @pagy.count.nil? || @pagy.count > 0 || @template_folders.present? %>
|
<% if has_archived || @pagy.count.nil? || @pagy.count > 0 || @template_folders.present? %>
|
||||||
<div class="mr-2">
|
<div class="mr-2">
|
||||||
|
|||||||
@@ -1,7 +1,35 @@
|
|||||||
|
<% with_subfolder = @template.folder.name != TemplateFolder::DEFAULT_NAME && params[:subfolder] != 'false' %>
|
||||||
<%= render 'shared/turbo_modal', title: t('move_into_folder') do %>
|
<%= render 'shared/turbo_modal', title: t('move_into_folder') do %>
|
||||||
<%= form_for '', url: template_folder_path(@template), method: :put, data: { turbo_frame: :_top }, html: { autocomplete: :off } do |f| %>
|
<% if with_subfolder %>
|
||||||
<div class="form-control my-6">
|
<%= form_for '', url: template_folder_path(@template), method: :put, data: { turbo_frame: :_top }, html: { id: 'subfolder_form', autocomplete: :off } do |f| %>
|
||||||
<folder-autocomplete class="block" data-submit-on-select="true">
|
<%= f.hidden_field :parent_name, value: @template.folder.parent_folder&.name || @template.folder.name %>
|
||||||
|
<toggle-visible data-element-ids="<%= %w[folder_form subfolder_form].to_json %>" class="block relative" data-focus-id="name">
|
||||||
|
<div class="flex items-center justify-between mb-2.5">
|
||||||
|
<label for="is_root_folder" class="flex items-center tooltip tooltip-right pr-2 group" data-tip="<%= t('change_parent_folder') %>">
|
||||||
|
<%= check_box_tag :is_root_folder, 'folder_form', data: { action: 'change:toggle-visible#trigger' }, class: 'hidden' %>
|
||||||
|
<span class="flex items-center mt-1">
|
||||||
|
<%= svg_icon('folder', class: 'w-5 h-5 flex-shrink-0 group-hover:hidden mr-1') %>
|
||||||
|
<%= svg_icon('folder_share', class: 'w-5 h-5 flex-shrink-0 hidden group-hover:inline mr-1') %>
|
||||||
|
<span class="text-md">
|
||||||
|
<%= @template.folder.parent_folder&.name || @template.folder.name %>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</toggle-visible>
|
||||||
|
<div class="form-control mb-6">
|
||||||
|
<folder-autocomplete class="block" data-submit-on-select="true" data-parent-name="<%= @template.folder.parent_folder&.name || @template.folder.name %>" data-enabled="<%= params[:autocomplete] != 'false' %>">
|
||||||
|
<%= f.text_field :name, required: true, placeholder: "#{t('new_subfolder_name')}...", class: 'base-input w-full', autofocus: true, id: 'subfolder_name' %>
|
||||||
|
</folder-autocomplete>
|
||||||
|
</div>
|
||||||
|
<div class="form-control">
|
||||||
|
<%= f.button button_title(title: t('move'), disabled_with: t('moving')), class: 'base-button' %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<%= form_for '', url: template_folder_path(@template), method: :put, data: { turbo_frame: :_top }, html: { id: 'folder_form', autocomplete: :off, class: "mt-6 #{'hidden' if with_subfolder}" } do |f| %>
|
||||||
|
<div class="form-control mb-6">
|
||||||
|
<folder-autocomplete class="block" data-submit-on-select="true" data-enabled="<%= params[:autocomplete] != 'false' %>">
|
||||||
<%= f.text_field :name, required: true, placeholder: "#{t('new_folder_name')}...", class: 'base-input w-full', autofocus: true %>
|
<%= f.text_field :name, required: true, placeholder: "#{t('new_folder_name')}...", class: 'base-input w-full', autofocus: true %>
|
||||||
</folder-autocomplete>
|
</folder-autocomplete>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -59,6 +59,7 @@
|
|||||||
<%= t('form_preferences') %>
|
<%= t('form_preferences') %>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse-content">
|
<div class="collapse-content">
|
||||||
|
<%= render 'templates_prefillable_fields/form', template: @template %>
|
||||||
<%= form_for @template, url: template_preferences_path(@template), method: :post, html: { autocomplete: 'off', class: 'mt-1' }, data: { close_on_submit: false } do |f| %>
|
<%= form_for @template, url: template_preferences_path(@template), method: :post, html: { autocomplete: 'off', class: 'mt-1' }, data: { close_on_submit: false } do |f| %>
|
||||||
<toggle-on-submit data-element-id="form_saved_alert"></toggle-on-submit>
|
<toggle-on-submit data-element-id="form_saved_alert"></toggle-on-submit>
|
||||||
<% configs = AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::SUBMITTER_COMPLETED_EMAIL_KEY).value %>
|
<% configs = AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::SUBMITTER_COMPLETED_EMAIL_KEY).value %>
|
||||||
@@ -68,7 +69,7 @@
|
|||||||
<%= ff.url_field :completed_redirect_url, required: false, class: 'base-input', dir: 'auto' %>
|
<%= ff.url_field :completed_redirect_url, required: false, class: 'base-input', dir: 'auto' %>
|
||||||
</div>
|
</div>
|
||||||
<%= ff.fields_for :completed_message, ff.object.completed_message do |fff| %>
|
<%= ff.fields_for :completed_message, ff.object.completed_message do |fff| %>
|
||||||
<div class="form-control mb-2 border-t mt-4">
|
<div class="form-control mb-2 mt-4">
|
||||||
<%= fff.label :body, t('completion_message'), class: 'label' %>
|
<%= fff.label :body, t('completion_message'), class: 'label' %>
|
||||||
<autoresize-textarea>
|
<autoresize-textarea>
|
||||||
<%= fff.text_area :body, required: false, class: 'base-input w-full py-2', dir: 'auto' %>
|
<%= fff.text_area :body, required: false, class: 'base-input w-full py-2', dir: 'auto' %>
|
||||||
@@ -162,6 +163,14 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<%= f.fields_for :preferences, Struct.new(:request_email_enabled).new(@template.preferences['request_email_enabled']) do |ff| %>
|
||||||
|
<div class="flex items-center justify-between py-2.5 px-1 mb-2">
|
||||||
|
<span>
|
||||||
|
<%= 'Send signature request email' %>
|
||||||
|
</span>
|
||||||
|
<%= ff.check_box :request_email_enabled, { checked: ff.object.request_email_enabled != false, class: 'toggle', onchange: 'this.form.requestSubmit()' }, 'true', 'false' %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
<div class="form-control pt-2">
|
<div class="form-control pt-2">
|
||||||
<%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button' %>
|
<%= f.button button_title(title: t('save'), disabled_with: t('saving')), class: 'base-button' %>
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<% select_fields = template.fields.filter_map { |f| [f['name'], f['uuid']] if f['name'].present? && f['type'].in?(TemplatesPrefillableFieldsController::PREFILLABLE_FIELD_TYPES) } %>
|
||||||
|
<% if select_fields.present? %>
|
||||||
|
<div class="border-b pb-4 mb-4">
|
||||||
|
<%= form_for '', url: template_prefillable_fields_path(template), method: :post, data: { close_on_submit: false } do |f| %>
|
||||||
|
<div class="form-control">
|
||||||
|
<%= f.hidden_field :prefillable, value: 'true' %>
|
||||||
|
<%= f.label :field_uuid, t(:invite_form_fields), class: 'label' %>
|
||||||
|
<div class="join w-full">
|
||||||
|
<%= select_tag :field_uuid, options_for_select(select_fields), prompt: t(:select_field), class: 'base-select w-full join-item', dir: 'auto', required: true %>
|
||||||
|
<%= f.button button_title(title: t('add'), disabled_with: t('add')), class: 'base-button join-item !px-6' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<%= render partial: 'templates_prefillable_fields/list', locals: { template: } %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<div id="prefillable_fields_list" class="flex gap-1 px-0.5 mt-2 flex-wrap">
|
||||||
|
<% template.fields.each do |f| %>
|
||||||
|
<% next unless f['prefillable'] %>
|
||||||
|
<%= button_to button_title(title: f['name'].presence || f['type'].capitalize, disabled_with: f['name'].presence || f['type'].capitalize, icon: svg_icon('x', class: 'w-4 h-4'), icon_disabled: svg_icon('loader', class: 'w-4 h-4 animate-spin')), template_prefillable_fields_path(template), params: { field_uuid: f['uuid'], prefillable: 'false' }, class: 'badge badge-lg badge-primary space-x-1 pr-3 pl-2', form: { data: { close_on_submit: false } } %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<% multiple_submitters = @template.submitters.to_a.length > 1 %>
|
||||||
|
<% enough_defined_submitters = Templates.filter_undefined_submitters(@template.submitters).size < 2 %>
|
||||||
<%= render 'shared/turbo_modal_large', title: t('share_link') do %>
|
<%= render 'shared/turbo_modal_large', title: t('share_link') do %>
|
||||||
<div class="mt-2 mb-4 px-5">
|
<div class="mt-2 mb-4 px-5">
|
||||||
<%= form_for @template, url: template_share_link_path(@template), method: :post, html: { id: 'shared_link_form', autocomplete: 'off', class: 'mt-3' }, data: { close_on_submit: false } do |f| %>
|
<%= form_for @template, url: template_share_link_path(@template), method: :post, html: { id: 'shared_link_form', autocomplete: 'off', class: 'mt-3' }, data: { close_on_submit: false } do |f| %>
|
||||||
@@ -12,28 +14,14 @@
|
|||||||
</check-on-click>
|
</check-on-click>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= form_for @template, url: template_preferences_path(@template), method: :post, html: { autocomplete: 'off', class: 'mt-4 mb-5' }, data: { close_on_submit: false } do |f| %>
|
<% if multiple_submitters && !enough_defined_submitters %>
|
||||||
<% link_form_fields = @template.preferences.fetch('link_form_fields', ['email']) %>
|
|
||||||
<label class="pl-1"><%= t('link_form_fields') %></label>
|
|
||||||
<required-checkbox-group class="flex flex-col md:flex-row items-center gap-2 w-full mt-2">
|
|
||||||
<% %w[name email phone].each do |field| %>
|
|
||||||
<%= label_tag "link_form_fields_#{field}", t(field), class: 'relative flex w-full md:w-1/3 items-center h-12 border-base-300 py-3.5 border rounded-xl' do %>
|
|
||||||
<%= check_box_tag 'template[preferences][link_form_fields][]', field, link_form_fields.include?(field), class: 'absolute !animate-none checkbox left-3', id: "link_form_fields_#{field}" %>
|
|
||||||
<span class="font-medium w-full text-center"><%= t(field) %></span>
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
</required-checkbox-group>
|
|
||||||
<% end %>
|
|
||||||
<% if Templates.filter_undefined_submitters(@template.submitters).size > 1 %>
|
|
||||||
<div class="alert items-start bg-base-100 border-base-300 mt-4">
|
<div class="alert items-start bg-base-100 border-base-300 mt-4">
|
||||||
<%= svg_icon('info_circle', class: 'stroke-current shrink-0 h-6 w-6 mt-1') %>
|
<%= svg_icon('info_circle', class: 'stroke-current shrink-0 h-6 w-6 mt-1') %>
|
||||||
<div><%= t('this_template_has_multiple_parties_which_prevents_the_use_of_a_sharing_link') %></div>
|
<div><%= t('this_template_has_multiple_parties_which_prevents_the_use_of_a_sharing_link') %></div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<div class="collapse collapse-arrow join-item border border-base-300 mt-4">
|
||||||
<% if @template.submitters.to_a.length > 1 %>
|
<input type="checkbox" name="accordion" class="min-h-0">
|
||||||
<div class="collapse collapse-arrow join-item border border-base-300 mt-4 mb-5">
|
<div class="collapse-title py-4 min-h-0">
|
||||||
<input type="checkbox" name="accordion">
|
|
||||||
<div class="collapse-title text-xl font-medium">
|
|
||||||
<%= t('default_parties') %>
|
<%= t('default_parties') %>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse-content !pb-0">
|
<div class="collapse-content !pb-0">
|
||||||
@@ -41,15 +29,46 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if Docuseal.multitenant? || Accounts.can_send_emails?(current_account) %>
|
<div class="collapse collapse-arrow join-item mt-4">
|
||||||
<%= form_for @template, url: template_preferences_path(@template), method: :post, html: { autocomplete: 'off', class: 'mt-3' }, data: { close_on_submit: false } do |f| %>
|
<input id="accordion_checkbox" type="checkbox" name="accordion" class="min-h-0">
|
||||||
<%= f.fields_for :preferences, Struct.new(:shared_link_2fa).new(@template.preferences['shared_link_2fa'] == true) do |ff| %>
|
<div class="collapse-title min-h-0 after:!right-3 p-1">
|
||||||
<label for="template_preferences_shared_link_2fa" class="flex items-center my-4 justify-between gap-1 alert bg-base-100 border-base-300">
|
<%= t('advanced_settings') %>
|
||||||
<span><%= t('request_email_otp_verification_with_shared_link') %></span>
|
</div>
|
||||||
<%= ff.check_box :shared_link_2fa, { checked: ff.object.shared_link_2fa == true, disabled: !can?(:update, @template), class: 'toggle', onchange: 'this.form.requestSubmit()' }, 'true', 'false' %>
|
<div class="collapse-content !p-0">
|
||||||
</label>
|
<%= form_for @template, url: template_preferences_path(@template), method: :post, html: { autocomplete: 'off', class: 'mt-4 pt-4 border-t border-base-300' }, data: { close_on_submit: false } do |f| %>
|
||||||
|
<% link_form_fields = @template.preferences.fetch('link_form_fields', ['email']) %>
|
||||||
|
<label class="pl-1"><%= t('link_form_fields') %></label>
|
||||||
|
<required-checkbox-group class="flex flex-col md:flex-row items-center gap-2 w-full mt-2">
|
||||||
|
<% %w[name email phone].each do |field| %>
|
||||||
|
<%= label_tag "link_form_fields_#{field}", t(field), class: 'relative flex w-full md:w-1/3 items-center h-14 border-base-300 py-3.5 border rounded-xl' do %>
|
||||||
|
<%= check_box_tag 'template[preferences][link_form_fields][]', field, link_form_fields.include?(field), class: 'absolute !animate-none checkbox left-3', id: "link_form_fields_#{field}" %>
|
||||||
|
<span class="font-medium w-full text-center"><%= t(field) %></span>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</required-checkbox-group>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% if multiple_submitters && enough_defined_submitters %>
|
||||||
<% end %>
|
<div class="collapse collapse-arrow join-item border border-base-300 mt-4">
|
||||||
|
<input type="checkbox" name="accordion" class="min-h-0">
|
||||||
|
<div class="collapse-title py-4 min-h-0">
|
||||||
|
<%= t('default_parties') %>
|
||||||
|
</div>
|
||||||
|
<div class="collapse-content !pb-0">
|
||||||
|
<%= render 'templates_preferences/recipients', template: @template, close_on_submit: false, with_toggles: false, with_submission_requester: false %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<% if Docuseal.multitenant? || Accounts.can_send_emails?(current_account) %>
|
||||||
|
<%= form_for @template, url: template_preferences_path(@template), method: :post, html: { autocomplete: 'off', class: 'mt-4' }, data: { close_on_submit: false } do |f| %>
|
||||||
|
<%= f.fields_for :preferences, Struct.new(:shared_link_2fa).new(@template.preferences['shared_link_2fa'] == true) do |ff| %>
|
||||||
|
<label for="template_preferences_shared_link_2fa" class="flex items-center mt-4 h-14 justify-between gap-1 alert bg-base-100 border-base-300">
|
||||||
|
<span><%= t('request_email_otp_verification_with_shared_link') %></span>
|
||||||
|
<%= ff.check_box :shared_link_2fa, { checked: ff.object.shared_link_2fa == true, disabled: !can?(:update, @template), class: 'toggle', onchange: 'this.form.requestSubmit()' }, 'true', 'false' %>
|
||||||
|
</label>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<p><%= @user.first_name.present? ? t('hello_name', name: @user.first_name) : t('hi_there') %>,</p>
|
<p><%= @user.first_name.present? ? t('hello_name', name: @user.first_name) : t('hi_there') %>,</p>
|
||||||
<p><%= t('you_have_been_invited_to_account_name_product_name_please_sign_up_using_the_link_below_', account_name: @user.account.name, product_name: Docuseal.product_name) %></p>
|
<p><%= t('you_have_been_invited_to_account_name_product_name_please_sign_up_using_the_link_below_', account_name: @user.account.name, product_name: Docuseal.product_name) %></p>
|
||||||
<p><%= link_to t('sign_up'), invitation_url(reset_password_token: @token) %></p>
|
<p><%= link_to t('sign_up'), invitation_url(reset_password_token: @token) %></p>
|
||||||
<p><%= t('please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this') %></p>
|
<p><%= t('please_contact_us_by_replying_to_this_email_if_you_have_any_questions') %></p>
|
||||||
<p>
|
<p>
|
||||||
<%= t('thanks') %>,<br><%= @current_account.name %>
|
<%= t('thanks') %>,<br><%= @current_account.name %>
|
||||||
</p>
|
</p>
|
||||||
@@ -8,6 +8,7 @@ module Rouge
|
|||||||
|
|
||||||
module Lexers
|
module Lexers
|
||||||
autoload :JSON, 'rouge/lexers/json'
|
autoload :JSON, 'rouge/lexers/json'
|
||||||
|
autoload :Shell, 'rouge/lexers/shell'
|
||||||
end
|
end
|
||||||
|
|
||||||
autoload :Formatter, 'rouge/formatter'
|
autoload :Formatter, 'rouge/formatter'
|
||||||
|
|||||||
+131
-55
@@ -23,6 +23,8 @@ en: &en
|
|||||||
pro: Pro
|
pro: Pro
|
||||||
thanks: Thanks
|
thanks: Thanks
|
||||||
private: Private
|
private: Private
|
||||||
|
select: Select
|
||||||
|
invite_form_fields: Invite form fields
|
||||||
default_parties: Default parties
|
default_parties: Default parties
|
||||||
authenticate_embedded_form_preview_with_token: Authenticate embedded form preview with token
|
authenticate_embedded_form_preview_with_token: Authenticate embedded form preview with token
|
||||||
stripe_integration: Stripe Integration
|
stripe_integration: Stripe Integration
|
||||||
@@ -42,7 +44,6 @@ en: &en
|
|||||||
send_verification_code: Send verification code
|
send_verification_code: Send verification code
|
||||||
code_has_been_resent: Code has been re-sent
|
code_has_been_resent: Code has been re-sent
|
||||||
invalid_code: Invalid code
|
invalid_code: Invalid code
|
||||||
unarchive: Unarchive
|
|
||||||
signed: Signed
|
signed: Signed
|
||||||
first_party: 'First Party'
|
first_party: 'First Party'
|
||||||
remove_filter: Remove filter
|
remove_filter: Remove filter
|
||||||
@@ -56,7 +57,6 @@ en: &en
|
|||||||
accessiable_by: Accessible by
|
accessiable_by: Accessible by
|
||||||
team_access: Team access
|
team_access: Team access
|
||||||
document_download_filename_format: Document download filename format
|
document_download_filename_format: Document download filename format
|
||||||
document_name: Document Name
|
|
||||||
docuseal_trusted_signature: DocuSeal Trusted Signature
|
docuseal_trusted_signature: DocuSeal Trusted Signature
|
||||||
hello_name: Hello %{name}
|
hello_name: Hello %{name}
|
||||||
you_are_invited_to_product_name: You are invited to %{product_name}
|
you_are_invited_to_product_name: You are invited to %{product_name}
|
||||||
@@ -73,7 +73,7 @@ en: &en
|
|||||||
awaiting_completion_by_the_other_party: "Awaiting completion by the other party"
|
awaiting_completion_by_the_other_party: "Awaiting completion by the other party"
|
||||||
review_and_sign: Review and Sign
|
review_and_sign: Review and Sign
|
||||||
review_and_submit: Review and Submit
|
review_and_submit: Review and Submit
|
||||||
please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this: "Please contact us by replying to this email if you have any questions."
|
please_contact_us_by_replying_to_this_email_if_you_have_any_questions: "Please contact us by replying to this email if you have any questions."
|
||||||
submitter_invitation_sms_body_sign: '{account.name} has invited you to sign a document: {submitter.link}'
|
submitter_invitation_sms_body_sign: '{account.name} has invited you to sign a document: {submitter.link}'
|
||||||
verification_code_sms_body: 'Verification code: {code}'
|
verification_code_sms_body: 'Verification code: {code}'
|
||||||
you_are_invited_to_submit_a_form: 'You are invited to submit a form'
|
you_are_invited_to_submit_a_form: 'You are invited to submit a form'
|
||||||
@@ -398,7 +398,6 @@ en: &en
|
|||||||
send_signature_request_emails_without_limits_with_docuseal_pro: Send signature request emails without limits with DocuSeal Pro
|
send_signature_request_emails_without_limits_with_docuseal_pro: Send signature request emails without limits with DocuSeal Pro
|
||||||
count_emails_used: '%{count} emails used'
|
count_emails_used: '%{count} emails used'
|
||||||
has_been_connected: has been connected
|
has_been_connected: has been connected
|
||||||
but_not_activated: but not activated
|
|
||||||
sms_not_configured: SMS not Configure
|
sms_not_configured: SMS not Configure
|
||||||
configure_sms_settings_in_order_to_send_text_messages_: 'Configure SMS settings in order to send text messages:'
|
configure_sms_settings_in_order_to_send_text_messages_: 'Configure SMS settings in order to send text messages:'
|
||||||
go_to_sms_settings: Go to SMS settings
|
go_to_sms_settings: Go to SMS settings
|
||||||
@@ -460,6 +459,10 @@ en: &en
|
|||||||
users_count_total_users_count_pro_users_limit_was_reached_to_invite_additional_users_please_purchase_more_pro_user_seats_via_the_manage_plan_button: '%{users_count}/%{total_users_count} Pro users limit was reached. To invite additional users, please purchase more Pro user seats via the "Manage plan" button.'
|
users_count_total_users_count_pro_users_limit_was_reached_to_invite_additional_users_please_purchase_more_pro_user_seats_via_the_manage_plan_button: '%{users_count}/%{total_users_count} Pro users limit was reached. To invite additional users, please purchase more Pro user seats via the "Manage plan" button.'
|
||||||
move_into_folder: Move Into Folder
|
move_into_folder: Move Into Folder
|
||||||
new_folder_name: New Folder Name
|
new_folder_name: New Folder Name
|
||||||
|
new_subfolder_name: New Subfolder Name
|
||||||
|
change_parent_folder: Change Parent Folder
|
||||||
|
folder: Folder
|
||||||
|
create_a_new_folder: Create a New Folder
|
||||||
exit_preview: Exit Preview
|
exit_preview: Exit Preview
|
||||||
general: General
|
general: General
|
||||||
recipients: Recipients
|
recipients: Recipients
|
||||||
@@ -492,7 +495,6 @@ en: &en
|
|||||||
edit_user: Edit User
|
edit_user: Edit User
|
||||||
new_user: New User
|
new_user: New User
|
||||||
unarchive: Unarchive
|
unarchive: Unarchive
|
||||||
role: Role
|
|
||||||
last_session: Last session
|
last_session: Last session
|
||||||
unlock_more_user_roles_with_docuseal_pro: Unlock more user roles with DocuSeal Pro.
|
unlock_more_user_roles_with_docuseal_pro: Unlock more user roles with DocuSeal Pro.
|
||||||
view_active: View Active
|
view_active: View Active
|
||||||
@@ -559,8 +561,6 @@ en: &en
|
|||||||
new_webhook: New Webhook
|
new_webhook: New Webhook
|
||||||
delete_webhook: Delete webhook
|
delete_webhook: Delete webhook
|
||||||
count_submissions_have_been_created: '%{count} submissions have been created.'
|
count_submissions_have_been_created: '%{count} submissions have been created.'
|
||||||
gmail_has_been_connected: Gmail has been connected
|
|
||||||
microsoft_account_has_been_connected: Microsoft Account has been connected
|
|
||||||
sms_length_cant_be_longer_than_120_bytes: SMS length can't be longer than 120 bytes
|
sms_length_cant_be_longer_than_120_bytes: SMS length can't be longer than 120 bytes
|
||||||
connected_successfully: Connected successfully.
|
connected_successfully: Connected successfully.
|
||||||
user_nameid_not_found: 'User %{nameid} not found.'
|
user_nameid_not_found: 'User %{nameid} not found.'
|
||||||
@@ -779,6 +779,19 @@ en: &en
|
|||||||
email_verification: Email verification
|
email_verification: Email verification
|
||||||
your_verification_code_to_access_the_name: 'Your verification code to access the "%{name}":'
|
your_verification_code_to_access_the_name: 'Your verification code to access the "%{name}":'
|
||||||
please_reply_to_this_email_if_you_didnt_request_this: Please reply to this email if you didn't request this.
|
please_reply_to_this_email_if_you_didnt_request_this: Please reply to this email if you didn't request this.
|
||||||
|
advanced_settings: Advanced settings
|
||||||
|
text: Text
|
||||||
|
code: Code
|
||||||
|
custom_html_emails: Custom HTML emails
|
||||||
|
connect_your_email_to_send_html_emails: Connect your email to send HTML emails
|
||||||
|
connect_your_email_or_outlook_account_or_add_smtp_settings_to_send_custom_html_emails: Connect your Gmail or Outlook account or add SMTP settings to send custom HTML emails.
|
||||||
|
connect_gmail_or_outlook: Connect Gmail or Outlook
|
||||||
|
connect_your_email_to_bulk_send: Connect your email to bulk send
|
||||||
|
connect_your_email_or_outlook_account_or_add_smtp_settings_to_bulk_send: Connect your Gmail or Outlook account or add SMTP settings to bulk send.
|
||||||
|
are_you_sure_you_want_to_add_recipients_without_sending_to_send_emails_it_requires_to_connect_gmail_or_outlook: Are you sure you want to add recipients without sending? To send emails it requires to connect Gmail or Outlook.
|
||||||
|
template_name_has_been_completed_by_submitters_html: '"<strong>{template.name}</strong>" has been completed by <strong>{submission.submitters}</strong>'
|
||||||
|
please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Please check the copy of your "<strong>{template.name}</strong>" in the email attachments.'
|
||||||
|
you_have_been_invited_to_sign_the_template_name_html: 'You have been invited to sign the "<strong>{template.name}</strong>".'
|
||||||
submission_sources:
|
submission_sources:
|
||||||
api: API
|
api: API
|
||||||
bulk: Bulk Send
|
bulk: Bulk Send
|
||||||
@@ -885,6 +898,8 @@ en: &en
|
|||||||
range_without_total: "%{from}-%{to} events"
|
range_without_total: "%{from}-%{to} events"
|
||||||
|
|
||||||
es: &es
|
es: &es
|
||||||
|
select: Seleccionar
|
||||||
|
invite_form_fields: Invitar campos del formulario
|
||||||
pro: Pro
|
pro: Pro
|
||||||
default_parties: Partes predeterminadas
|
default_parties: Partes predeterminadas
|
||||||
authenticate_embedded_form_preview_with_token: Autenticar vista previa del formulario incrustado con token
|
authenticate_embedded_form_preview_with_token: Autenticar vista previa del formulario incrustado con token
|
||||||
@@ -918,8 +933,6 @@ es: &es
|
|||||||
team_access: Acceso del equipo
|
team_access: Acceso del equipo
|
||||||
remove_filter: Eliminar filtro
|
remove_filter: Eliminar filtro
|
||||||
document_download_filename_format: Formato del nombre del archivo de descarga del documento
|
document_download_filename_format: Formato del nombre del archivo de descarga del documento
|
||||||
document_name: Nombre del documento
|
|
||||||
unarchive: Desarchivar
|
|
||||||
awaiting_completion_by_the_other_party: "Esperando la finalización por la otra parte"
|
awaiting_completion_by_the_other_party: "Esperando la finalización por la otra parte"
|
||||||
enforce_recipients_order: 'Hacer cumplir el orden de los destinatarios'
|
enforce_recipients_order: 'Hacer cumplir el orden de los destinatarios'
|
||||||
first_party: 'Primera Parte'
|
first_party: 'Primera Parte'
|
||||||
@@ -940,7 +953,7 @@ es: &es
|
|||||||
please_check_the_copy_of_your_name_in_the_email_attachments: 'Por favor, revisa la copia de tu "%{name}" en los archivos adjuntos del correo electrónico.'
|
please_check_the_copy_of_your_name_in_the_email_attachments: 'Por favor, revisa la copia de tu "%{name}" en los archivos adjuntos del correo electrónico.'
|
||||||
review_and_sign: Revisar y Firmar
|
review_and_sign: Revisar y Firmar
|
||||||
review_and_submit: Revisar y Enviar
|
review_and_submit: Revisar y Enviar
|
||||||
please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this: "Por favor, contáctanos respondiendo a este correo si tienes alguna pregunta."
|
please_contact_us_by_replying_to_this_email_if_you_have_any_questions: "Por favor, contáctanos respondiendo a este correo si tienes alguna pregunta."
|
||||||
submitter_invitation_sms_body_sign: '{account.name} te ha invitado a firmar un documento: {submitter.link}'
|
submitter_invitation_sms_body_sign: '{account.name} te ha invitado a firmar un documento: {submitter.link}'
|
||||||
verification_code_sms_body: 'Código de verificación: {code}'
|
verification_code_sms_body: 'Código de verificación: {code}'
|
||||||
you_are_invited_to_submit_a_form: 'Estás invitado/a a enviar un formulario'
|
you_are_invited_to_submit_a_form: 'Estás invitado/a a enviar un formulario'
|
||||||
@@ -969,7 +982,7 @@ es: &es
|
|||||||
submitter_documents_copy_email_body: |
|
submitter_documents_copy_email_body: |
|
||||||
Hola,
|
Hola,
|
||||||
|
|
||||||
Por favor, revisa la copia de tu "{template.name}" en los archivos adjuntos.
|
Por favor, revisa la copia de tu "{template.name}" en los archivos adjuntos del correo electrónico.
|
||||||
Alternativamente, puedes revisar y descargar tu copia usando el enlace a continuación:
|
Alternativamente, puedes revisar y descargar tu copia usando el enlace a continuación:
|
||||||
|
|
||||||
[{template.name}]({documents.link})
|
[{template.name}]({documents.link})
|
||||||
@@ -1264,7 +1277,6 @@ es: &es
|
|||||||
send_signature_request_emails_without_limits_with_docuseal_pro: Envía solicitudes de firma sin límites con DocuSeal Pro
|
send_signature_request_emails_without_limits_with_docuseal_pro: Envía solicitudes de firma sin límites con DocuSeal Pro
|
||||||
count_emails_used: '%{count} correos electrónicos utilizados'
|
count_emails_used: '%{count} correos electrónicos utilizados'
|
||||||
has_been_connected: ha sido conectado
|
has_been_connected: ha sido conectado
|
||||||
but_not_activated: pero no activado
|
|
||||||
sms_not_configured: SMS no configurado
|
sms_not_configured: SMS no configurado
|
||||||
configure_sms_settings_in_order_to_send_text_messages_: 'Configura los ajustes de SMS para enviar mensajes de texto:'
|
configure_sms_settings_in_order_to_send_text_messages_: 'Configura los ajustes de SMS para enviar mensajes de texto:'
|
||||||
go_to_sms_settings: Ir a la configuración de SMS
|
go_to_sms_settings: Ir a la configuración de SMS
|
||||||
@@ -1326,6 +1338,10 @@ es: &es
|
|||||||
users_count_total_users_count_pro_users_limit_was_reached_to_invite_additional_users_please_purchase_more_pro_user_seats_via_the_manage_plan_button: 'Se alcanzó el límite de %{users_count}/%{total_users_count} usuarios Pro. Para invitar a más usuarios, compra más plazas Pro usando el botón "Gestionar plan".'
|
users_count_total_users_count_pro_users_limit_was_reached_to_invite_additional_users_please_purchase_more_pro_user_seats_via_the_manage_plan_button: 'Se alcanzó el límite de %{users_count}/%{total_users_count} usuarios Pro. Para invitar a más usuarios, compra más plazas Pro usando el botón "Gestionar plan".'
|
||||||
move_into_folder: Mover a la carpeta
|
move_into_folder: Mover a la carpeta
|
||||||
new_folder_name: Nuevo nombre de la carpeta
|
new_folder_name: Nuevo nombre de la carpeta
|
||||||
|
new_subfolder_name: Nuevo nombre de subcarpeta
|
||||||
|
change_parent_folder: Cambiar carpeta principal
|
||||||
|
folder: Carpeta
|
||||||
|
create_a_new_folder: Crear una nueva carpeta
|
||||||
exit_preview: Salir de la vista previa
|
exit_preview: Salir de la vista previa
|
||||||
general: General
|
general: General
|
||||||
recipients: Destinatarios
|
recipients: Destinatarios
|
||||||
@@ -1358,7 +1374,6 @@ es: &es
|
|||||||
edit_user: Editar usuario
|
edit_user: Editar usuario
|
||||||
new_user: Nuevo usuario
|
new_user: Nuevo usuario
|
||||||
unarchive: Desarchivar
|
unarchive: Desarchivar
|
||||||
role: Rol
|
|
||||||
last_session: Última sesión
|
last_session: Última sesión
|
||||||
unlock_more_user_roles_with_docuseal_pro: Desbloquea más roles de usuario con DocuSeal Pro.
|
unlock_more_user_roles_with_docuseal_pro: Desbloquea más roles de usuario con DocuSeal Pro.
|
||||||
view_active: Ver activos
|
view_active: Ver activos
|
||||||
@@ -1425,8 +1440,6 @@ es: &es
|
|||||||
new_webhook: Nuevo Webhook
|
new_webhook: Nuevo Webhook
|
||||||
delete_webhook: Eliminar webhook
|
delete_webhook: Eliminar webhook
|
||||||
count_submissions_have_been_created: '%{count} envíos han sido creados.'
|
count_submissions_have_been_created: '%{count} envíos han sido creados.'
|
||||||
gmail_has_been_connected: Gmail ha sido conectado.
|
|
||||||
microsoft_account_has_been_connected: La cuenta de Microsoft ha sido conectada.
|
|
||||||
sms_length_cant_be_longer_than_120_bytes: La longitud del SMS no puede ser mayor a 120 bytes.
|
sms_length_cant_be_longer_than_120_bytes: La longitud del SMS no puede ser mayor a 120 bytes.
|
||||||
connected_successfully: Conectado con éxito.
|
connected_successfully: Conectado con éxito.
|
||||||
user_nameid_not_found: 'Usuario %{nameid} no encontrado.'
|
user_nameid_not_found: 'Usuario %{nameid} no encontrado.'
|
||||||
@@ -1519,7 +1532,6 @@ es: &es
|
|||||||
select_field: Campo de Selección
|
select_field: Campo de Selección
|
||||||
multiple_field: Campo Múltiple
|
multiple_field: Campo Múltiple
|
||||||
radio_field: Campo de Grupo Radio
|
radio_field: Campo de Grupo Radio
|
||||||
radio_field: Campo de Radio
|
|
||||||
cells_field: Campo de Celdas
|
cells_field: Campo de Celdas
|
||||||
stamp_field: Campo de Sello
|
stamp_field: Campo de Sello
|
||||||
payment_field: Campo de Pago
|
payment_field: Campo de Pago
|
||||||
@@ -1645,6 +1657,19 @@ es: &es
|
|||||||
email_verification: Verificación por correo electrónico
|
email_verification: Verificación por correo electrónico
|
||||||
your_verification_code_to_access_the_name: 'Su código de verificación para acceder a "%{name}":'
|
your_verification_code_to_access_the_name: 'Su código de verificación para acceder a "%{name}":'
|
||||||
please_reply_to_this_email_if_you_didnt_request_this: Por favor, responda este correo si no solicitó esto.
|
please_reply_to_this_email_if_you_didnt_request_this: Por favor, responda este correo si no solicitó esto.
|
||||||
|
advanced_settings: Configuración avanzada
|
||||||
|
text: Texto
|
||||||
|
code: Código
|
||||||
|
custom_html_emails: Correos electrónicos HTML personalizados
|
||||||
|
connect_your_email_to_send_html_emails: Conecta tu correo electrónico para enviar correos HTML
|
||||||
|
connect_your_email_or_outlook_account_or_add_smtp_settings_to_send_custom_html_emails: Conecta tu cuenta de Gmail u Outlook o añade ajustes SMTP para enviar correos HTML personalizados.
|
||||||
|
connect_gmail_or_outlook: Conectar Gmail u Outlook
|
||||||
|
connect_your_email_to_bulk_send: Conecta tu correo electrónico para el envío masivo
|
||||||
|
connect_your_email_or_outlook_account_or_add_smtp_settings_to_bulk_send: Conecta tu cuenta de Gmail u Outlook o añade ajustes SMTP para el envío masivo.
|
||||||
|
are_you_sure_you_want_to_add_recipients_without_sending_to_send_emails_it_requires_to_connect_gmail_or_outlook: ¿Estás seguro de que quieres añadir destinatarios sin enviar? Para enviar correos electrónicos necesitas conectar Gmail u Outlook.
|
||||||
|
template_name_has_been_completed_by_submitters_html: '"<strong>{template.name}</strong>" ha sido completado por <strong>{submission.submitters}</strong>'
|
||||||
|
please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Por favor, revisa la copia de tu "<strong>{template.name}</strong>" en los archivos adjuntos del correo electrónico.'
|
||||||
|
you_have_been_invited_to_sign_the_template_name_html: 'Has sido invitado a firmar el "<strong>{template.name}</strong>".'
|
||||||
submission_sources:
|
submission_sources:
|
||||||
api: API
|
api: API
|
||||||
bulk: Envío masivo
|
bulk: Envío masivo
|
||||||
@@ -1751,6 +1776,8 @@ es: &es
|
|||||||
range_without_total: "%{from}-%{to} eventos"
|
range_without_total: "%{from}-%{to} eventos"
|
||||||
|
|
||||||
it: &it
|
it: &it
|
||||||
|
select: Seleziona
|
||||||
|
invite_form_fields: Invita campi modulo
|
||||||
pro: Pro
|
pro: Pro
|
||||||
default_parties: Parti predefiniti
|
default_parties: Parti predefiniti
|
||||||
authenticate_embedded_form_preview_with_token: "Autentica l'anteprima del modulo incorporato con il token"
|
authenticate_embedded_form_preview_with_token: "Autentica l'anteprima del modulo incorporato con il token"
|
||||||
@@ -1783,8 +1810,6 @@ it: &it
|
|||||||
team_access: Accesso al team
|
team_access: Accesso al team
|
||||||
remove_filter: Rimuovi filtro
|
remove_filter: Rimuovi filtro
|
||||||
document_download_filename_format: Formato del nome file scaricato
|
document_download_filename_format: Formato del nome file scaricato
|
||||||
document_name: Nome del Documento
|
|
||||||
unarchive: Ripristina
|
|
||||||
awaiting_completion_by_the_other_party: "In attesa di completamento da parte dell'altra parte"
|
awaiting_completion_by_the_other_party: "In attesa di completamento da parte dell'altra parte"
|
||||||
enforce_recipients_order: "Applicare l'ordine dei destinatari"
|
enforce_recipients_order: "Applicare l'ordine dei destinatari"
|
||||||
first_party: 'Prima parte'
|
first_party: 'Prima parte'
|
||||||
@@ -1805,7 +1830,7 @@ it: &it
|
|||||||
please_check_the_copy_of_your_name_in_the_email_attachments: "Per favore, controlla la copia del tuo \"%{name}\" negli allegati dell'email."
|
please_check_the_copy_of_your_name_in_the_email_attachments: "Per favore, controlla la copia del tuo \"%{name}\" negli allegati dell'email."
|
||||||
review_and_sign: Rivedi e Firma
|
review_and_sign: Rivedi e Firma
|
||||||
review_and_submit: Rivedi e Invia
|
review_and_submit: Rivedi e Invia
|
||||||
please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this: "Per favore, contattaci rispondendo a questa email se hai domande."
|
please_contact_us_by_replying_to_this_email_if_you_have_any_questions: "Per favore, contattaci rispondendo a questa email se hai domande."
|
||||||
submitter_invitation_sms_body_sign: '{account.name} ti ha invitato a firmare un documento: {submitter.link}'
|
submitter_invitation_sms_body_sign: '{account.name} ti ha invitato a firmare un documento: {submitter.link}'
|
||||||
verification_code_sms_body: 'Codice di verifica: {code}'
|
verification_code_sms_body: 'Codice di verifica: {code}'
|
||||||
you_are_invited_to_submit_a_form: 'Sei stato invitato a inviare un modulo'
|
you_are_invited_to_submit_a_form: 'Sei stato invitato a inviare un modulo'
|
||||||
@@ -2129,7 +2154,6 @@ it: &it
|
|||||||
send_signature_request_emails_without_limits_with_docuseal_pro: Invia email di richiesta di firma senza limiti con DocuSeal Pro
|
send_signature_request_emails_without_limits_with_docuseal_pro: Invia email di richiesta di firma senza limiti con DocuSeal Pro
|
||||||
count_emails_used: '%{count} email utilizzate'
|
count_emails_used: '%{count} email utilizzate'
|
||||||
has_been_connected: è stato connesso
|
has_been_connected: è stato connesso
|
||||||
but_not_activated: ma non attivato
|
|
||||||
sms_not_configured: SMS non configurato
|
sms_not_configured: SMS non configurato
|
||||||
configure_sms_settings_in_order_to_send_text_messages_: 'Configura le impostazioni SMS per inviare messaggi di testo:'
|
configure_sms_settings_in_order_to_send_text_messages_: 'Configura le impostazioni SMS per inviare messaggi di testo:'
|
||||||
go_to_sms_settings: Vai alle impostazioni SMS
|
go_to_sms_settings: Vai alle impostazioni SMS
|
||||||
@@ -2191,6 +2215,10 @@ it: &it
|
|||||||
users_count_total_users_count_pro_users_limit_was_reached_to_invite_additional_users_please_purchase_more_pro_user_seats_via_the_manage_plan_button: 'È stato raggiunto il limite di %{users_count}/%{total_users_count} utenti Pro. Per invitare altri utenti, acquista più posti Pro tramite il pulsante "Gestisci piano".'
|
users_count_total_users_count_pro_users_limit_was_reached_to_invite_additional_users_please_purchase_more_pro_user_seats_via_the_manage_plan_button: 'È stato raggiunto il limite di %{users_count}/%{total_users_count} utenti Pro. Per invitare altri utenti, acquista più posti Pro tramite il pulsante "Gestisci piano".'
|
||||||
move_into_folder: Sposta nella cartella
|
move_into_folder: Sposta nella cartella
|
||||||
new_folder_name: Nuovo nome della cartella
|
new_folder_name: Nuovo nome della cartella
|
||||||
|
new_subfolder_name: Nuovo nome della sottocartella
|
||||||
|
change_parent_folder: Cambia cartella principale
|
||||||
|
folder: Cartella
|
||||||
|
create_a_new_folder: Crea una nuova cartella
|
||||||
exit_preview: "Esci dall'anteprima"
|
exit_preview: "Esci dall'anteprima"
|
||||||
general: Generale
|
general: Generale
|
||||||
recipients: Destinatari
|
recipients: Destinatari
|
||||||
@@ -2222,7 +2250,6 @@ it: &it
|
|||||||
edit_user: Modifica utente
|
edit_user: Modifica utente
|
||||||
new_user: Nuovo utente
|
new_user: Nuovo utente
|
||||||
unarchive: Disarchivia
|
unarchive: Disarchivia
|
||||||
role: Ruolo
|
|
||||||
last_session: Ultima sessione
|
last_session: Ultima sessione
|
||||||
unlock_more_user_roles_with_docuseal_pro: Sblocca più ruoli utente con DocuSeal Pro.
|
unlock_more_user_roles_with_docuseal_pro: Sblocca più ruoli utente con DocuSeal Pro.
|
||||||
view_active: Visualizza attivi
|
view_active: Visualizza attivi
|
||||||
@@ -2289,8 +2316,6 @@ it: &it
|
|||||||
new_webhook: Nuovo Webhook
|
new_webhook: Nuovo Webhook
|
||||||
delete_webhook: Elimina webhook
|
delete_webhook: Elimina webhook
|
||||||
count_submissions_have_been_created: '%{count} invii sono stati creati.'
|
count_submissions_have_been_created: '%{count} invii sono stati creati.'
|
||||||
gmail_has_been_connected: Gmail è stato connesso.
|
|
||||||
microsoft_account_has_been_connected: "L'account Microsoft è stato connesso."
|
|
||||||
sms_length_cant_be_longer_than_120_bytes: "La lunghezza dell'SMS non può superare i 120 byte."
|
sms_length_cant_be_longer_than_120_bytes: "La lunghezza dell'SMS non può superare i 120 byte."
|
||||||
connected_successfully: Collegamento avvenuto con successo.
|
connected_successfully: Collegamento avvenuto con successo.
|
||||||
user_nameid_not_found: 'Utente %{nameid} non trovato.'
|
user_nameid_not_found: 'Utente %{nameid} non trovato.'
|
||||||
@@ -2510,6 +2535,19 @@ it: &it
|
|||||||
email_verification: Verifica email
|
email_verification: Verifica email
|
||||||
your_verification_code_to_access_the_name: 'Il tuo codice per accedere a "%{name}":'
|
your_verification_code_to_access_the_name: 'Il tuo codice per accedere a "%{name}":'
|
||||||
please_reply_to_this_email_if_you_didnt_request_this: Rispondi a questa email se non hai richiesto questo.
|
please_reply_to_this_email_if_you_didnt_request_this: Rispondi a questa email se non hai richiesto questo.
|
||||||
|
advanced_settings: Impostazioni avanzate
|
||||||
|
text: Testo
|
||||||
|
code: Codice
|
||||||
|
custom_html_emails: Email HTML personalizzate
|
||||||
|
connect_your_email_to_send_html_emails: Collega la tua email per inviare email HTML
|
||||||
|
connect_your_email_or_outlook_account_or_add_smtp_settings_to_send_custom_html_emails: Collega il tuo account Gmail o Outlook oppure aggiungi impostazioni SMTP per inviare email HTML personalizzate.
|
||||||
|
connect_gmail_or_outlook: Collega Gmail o Outlook
|
||||||
|
connect_your_email_to_bulk_send: Collega la tua email per invio multiplo
|
||||||
|
connect_your_email_or_outlook_account_or_add_smtp_settings_to_bulk_send: Collega il tuo account Gmail o Outlook oppure aggiungi impostazioni SMTP per invio multiplo.
|
||||||
|
are_you_sure_you_want_to_add_recipients_without_sending_to_send_emails_it_requires_to_connect_gmail_or_outlook: Sei sicuro di voler aggiungere destinatari senza inviare? Per inviare email devi collegare Gmail o Outlook.
|
||||||
|
template_name_has_been_completed_by_submitters_html: '"<strong>{template.name}</strong>" è stato completato da <strong>{submission.submitters}</strong>'
|
||||||
|
please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Per favore, controlla la copia del tuo "<strong>{template.name}</strong>" negli allegati dell''email.'
|
||||||
|
you_have_been_invited_to_sign_the_template_name_html: 'Sei stato invitato a firmare il "<strong>{template.name}</strong>".'
|
||||||
submission_sources:
|
submission_sources:
|
||||||
api: API
|
api: API
|
||||||
bulk: Invio massivo
|
bulk: Invio massivo
|
||||||
@@ -2616,6 +2654,8 @@ it: &it
|
|||||||
range_without_total: "%{from}-%{to} eventi"
|
range_without_total: "%{from}-%{to} eventi"
|
||||||
|
|
||||||
fr: &fr
|
fr: &fr
|
||||||
|
select: Sélectionner
|
||||||
|
invite_form_fields: Inviter des champs de formulaire
|
||||||
pro: Pro
|
pro: Pro
|
||||||
default_parties: Parties par défaut
|
default_parties: Parties par défaut
|
||||||
authenticate_embedded_form_preview_with_token: Authentifier l’aperçu du formulaire intégré avec un jeton
|
authenticate_embedded_form_preview_with_token: Authentifier l’aperçu du formulaire intégré avec un jeton
|
||||||
@@ -2649,8 +2689,6 @@ fr: &fr
|
|||||||
team_access: Accès à l'équipe
|
team_access: Accès à l'équipe
|
||||||
remove_filter: Supprimer le filtre
|
remove_filter: Supprimer le filtre
|
||||||
document_download_filename_format: Format du nom de fichier du téléchargement de document
|
document_download_filename_format: Format du nom de fichier du téléchargement de document
|
||||||
document_name: Nom du document
|
|
||||||
unarchive: Désarchiver
|
|
||||||
awaiting_completion_by_the_other_party: "En attente de la complétion par l'autre partie"
|
awaiting_completion_by_the_other_party: "En attente de la complétion par l'autre partie"
|
||||||
enforce_recipients_order: "Respecter l'ordre des destinataires"
|
enforce_recipients_order: "Respecter l'ordre des destinataires"
|
||||||
first_party: 'Première partie'
|
first_party: 'Première partie'
|
||||||
@@ -2671,7 +2709,7 @@ fr: &fr
|
|||||||
please_check_the_copy_of_your_name_in_the_email_attachments: "Veuillez vérifier la copie de votre \"%{name}\" dans les pièces jointes de l'email."
|
please_check_the_copy_of_your_name_in_the_email_attachments: "Veuillez vérifier la copie de votre \"%{name}\" dans les pièces jointes de l'email."
|
||||||
review_and_sign: Consulter et signer
|
review_and_sign: Consulter et signer
|
||||||
review_and_submit: Consulter et soumettre
|
review_and_submit: Consulter et soumettre
|
||||||
please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this: 'Veuillez nous contacter en répondant à cet e-mail si vous avez des questions.'
|
please_contact_us_by_replying_to_this_email_if_you_have_any_questions: 'Veuillez nous contacter en répondant à cet e-mail si vous avez des questions.'
|
||||||
submitter_invitation_sms_body_sign: '{account.name} vous a invité à signer un document: {submitter.link}'
|
submitter_invitation_sms_body_sign: '{account.name} vous a invité à signer un document: {submitter.link}'
|
||||||
verification_code_sms_body: 'Code de vérification: {code}'
|
verification_code_sms_body: 'Code de vérification: {code}'
|
||||||
you_are_invited_to_submit_a_form: Vous êtes invité à soumettre un formulaire
|
you_are_invited_to_submit_a_form: Vous êtes invité à soumettre un formulaire
|
||||||
@@ -2687,7 +2725,7 @@ fr: &fr
|
|||||||
|
|
||||||
[Consulter et signer]({submitter.link})
|
[Consulter et signer]({submitter.link})
|
||||||
|
|
||||||
Veuillez nous contacter si vous avez des questions.
|
Veuillez nous contacter en répondant à cet e-mail si vous avez des questions.
|
||||||
|
|
||||||
Merci,
|
Merci,
|
||||||
{account.name}
|
{account.name}
|
||||||
@@ -2700,7 +2738,7 @@ fr: &fr
|
|||||||
submitter_documents_copy_email_body: |
|
submitter_documents_copy_email_body: |
|
||||||
Bonjour,
|
Bonjour,
|
||||||
|
|
||||||
Veuillez vérifier la copie de votre "{template.name}" dans les pièces jointes.
|
Veuillez vérifier la copie de votre "{template.name}" dans les pièces jointes de l'email.
|
||||||
Vous pouvez également consulter et télécharger votre copie en utilisant le lien ci-dessous:
|
Vous pouvez également consulter et télécharger votre copie en utilisant le lien ci-dessous:
|
||||||
|
|
||||||
[{template.name}]({documents.link})
|
[{template.name}]({documents.link})
|
||||||
@@ -2996,7 +3034,6 @@ fr: &fr
|
|||||||
send_signature_request_emails_without_limits_with_docuseal_pro: Envoyez des e-mails de demande de signature sans limites avec DocuSeal Pro
|
send_signature_request_emails_without_limits_with_docuseal_pro: Envoyez des e-mails de demande de signature sans limites avec DocuSeal Pro
|
||||||
count_emails_used: '%{count} e-mails utilisés'
|
count_emails_used: '%{count} e-mails utilisés'
|
||||||
has_been_connected: a été connecté
|
has_been_connected: a été connecté
|
||||||
but_not_activated: mais pas activé
|
|
||||||
sms_not_configured: SMS non configuré
|
sms_not_configured: SMS non configuré
|
||||||
configure_sms_settings_in_order_to_send_text_messages_: 'Configurez les paramètres SMS pour envoyer des messages texte'
|
configure_sms_settings_in_order_to_send_text_messages_: 'Configurez les paramètres SMS pour envoyer des messages texte'
|
||||||
go_to_sms_settings: Aller aux paramètres SMS
|
go_to_sms_settings: Aller aux paramètres SMS
|
||||||
@@ -3058,6 +3095,10 @@ fr: &fr
|
|||||||
users_count_total_users_count_pro_users_limit_was_reached_to_invite_additional_users_please_purchase_more_pro_user_seats_via_the_manage_plan_button: 'La limite de %{users_count}/%{total_users_count} utilisateurs Pro a été atteinte. Pour inviter d''autres utilisateurs, veuillez acheter plus de places Pro via le bouton "Gérer le plan".'
|
users_count_total_users_count_pro_users_limit_was_reached_to_invite_additional_users_please_purchase_more_pro_user_seats_via_the_manage_plan_button: 'La limite de %{users_count}/%{total_users_count} utilisateurs Pro a été atteinte. Pour inviter d''autres utilisateurs, veuillez acheter plus de places Pro via le bouton "Gérer le plan".'
|
||||||
move_into_folder: Déplacer dans le dossier
|
move_into_folder: Déplacer dans le dossier
|
||||||
new_folder_name: Nouveau nom du dossier
|
new_folder_name: Nouveau nom du dossier
|
||||||
|
new_subfolder_name: Nouveau nom du sous-dossier
|
||||||
|
change_parent_folder: Changer le dossier parent
|
||||||
|
folder: Dossier
|
||||||
|
create_a_new_folder: Créer un nouveau dossier
|
||||||
exit_preview: "Quitter l'aperçu"
|
exit_preview: "Quitter l'aperçu"
|
||||||
general: Général
|
general: Général
|
||||||
recipients: Destinataires
|
recipients: Destinataires
|
||||||
@@ -3090,7 +3131,6 @@ fr: &fr
|
|||||||
edit_user: "Modifier l'utilisateur"
|
edit_user: "Modifier l'utilisateur"
|
||||||
new_user: Nouvel utilisateur
|
new_user: Nouvel utilisateur
|
||||||
unarchive: Désarchiver
|
unarchive: Désarchiver
|
||||||
role: Rôle
|
|
||||||
last_session: Dernière session
|
last_session: Dernière session
|
||||||
unlock_more_user_roles_with_docuseal_pro: Déverrouillez plus de rôles d'utilisateurs avec DocuSeal Pro.
|
unlock_more_user_roles_with_docuseal_pro: Déverrouillez plus de rôles d'utilisateurs avec DocuSeal Pro.
|
||||||
view_active: Voir les actifs
|
view_active: Voir les actifs
|
||||||
@@ -3157,8 +3197,6 @@ fr: &fr
|
|||||||
new_webhook: Nouveau Webhook
|
new_webhook: Nouveau Webhook
|
||||||
delete_webhook: Supprimer le webhook
|
delete_webhook: Supprimer le webhook
|
||||||
count_submissions_have_been_created: '%{count} soumissions ont été créées.'
|
count_submissions_have_been_created: '%{count} soumissions ont été créées.'
|
||||||
gmail_has_been_connected: Gmail a été connecté.
|
|
||||||
microsoft_account_has_been_connected: Le compte Microsoft a été connecté.
|
|
||||||
sms_length_cant_be_longer_than_120_bytes: La longueur du SMS ne peut pas dépasser 120 octets.
|
sms_length_cant_be_longer_than_120_bytes: La longueur du SMS ne peut pas dépasser 120 octets.
|
||||||
connected_successfully: Connecté avec succès.
|
connected_successfully: Connecté avec succès.
|
||||||
user_nameid_not_found: 'Utilisateur %{nameid} introuvable.'
|
user_nameid_not_found: 'Utilisateur %{nameid} introuvable.'
|
||||||
@@ -3378,6 +3416,19 @@ fr: &fr
|
|||||||
email_verification: Vérification de l'email
|
email_verification: Vérification de l'email
|
||||||
your_verification_code_to_access_the_name: 'Votre code pour accéder à "%{name}" :'
|
your_verification_code_to_access_the_name: 'Votre code pour accéder à "%{name}" :'
|
||||||
please_reply_to_this_email_if_you_didnt_request_this: Veuillez répondre à cet email si vous n'avez pas fait cette demande.
|
please_reply_to_this_email_if_you_didnt_request_this: Veuillez répondre à cet email si vous n'avez pas fait cette demande.
|
||||||
|
advanced_settings: Paramètres avancés
|
||||||
|
text: Texte
|
||||||
|
code: Code
|
||||||
|
custom_html_emails: E-mails HTML personnalisés
|
||||||
|
connect_your_email_to_send_html_emails: Connectez votre e-mail pour envoyer des e-mails HTML
|
||||||
|
connect_your_email_or_outlook_account_or_add_smtp_settings_to_send_custom_html_emails: Connectez votre compte Gmail ou Outlook ou ajoutez des paramètres SMTP pour envoyer des e-mails HTML personnalisés.
|
||||||
|
connect_gmail_or_outlook: Connecter Gmail ou Outlook
|
||||||
|
connect_your_email_to_bulk_send: Connectez votre e-mail pour l'envoi groupé
|
||||||
|
connect_your_email_or_outlook_account_or_add_smtp_settings_to_bulk_send: Connectez votre compte Gmail ou Outlook ou ajoutez des paramètres SMTP pour l'envoi groupé.
|
||||||
|
are_you_sure_you_want_to_add_recipients_without_sending_to_send_emails_it_requires_to_connect_gmail_or_outlook: Êtes-vous sûr de vouloir ajouter des destinataires sans envoi ? Pour envoyer des e-mails, vous devez connecter Gmail ou Outlook.
|
||||||
|
template_name_has_been_completed_by_submitters_html: '"<strong>{template.name}</strong>" a été complété par <strong>{submission.submitters}</strong>'
|
||||||
|
please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Veuillez vérifier la copie de votre "<strong>{template.name}</strong>" dans les pièces jointes de l’e-mail.'
|
||||||
|
you_have_been_invited_to_sign_the_template_name_html: 'Vous avez été invité à signer le "<strong>{template.name}</strong>".'
|
||||||
submission_sources:
|
submission_sources:
|
||||||
api: API
|
api: API
|
||||||
bulk: Envoi en masse
|
bulk: Envoi en masse
|
||||||
@@ -3484,6 +3535,8 @@ fr: &fr
|
|||||||
range_without_total: "%{from} à %{to} événements"
|
range_without_total: "%{from} à %{to} événements"
|
||||||
|
|
||||||
pt: &pt
|
pt: &pt
|
||||||
|
select: Selecionar
|
||||||
|
invite_form_fields: Convidar campos do formulário
|
||||||
pro: Pro
|
pro: Pro
|
||||||
default_parties: Partes padrão
|
default_parties: Partes padrão
|
||||||
authenticate_embedded_form_preview_with_token: Autenticar visualização incorporada do formulário com token
|
authenticate_embedded_form_preview_with_token: Autenticar visualização incorporada do formulário com token
|
||||||
@@ -3517,8 +3570,6 @@ pt: &pt
|
|||||||
team_access: Acesso à equipe
|
team_access: Acesso à equipe
|
||||||
remove_filter: Remover filtro
|
remove_filter: Remover filtro
|
||||||
document_download_filename_format: Formato do nome do arquivo de download do documento
|
document_download_filename_format: Formato do nome do arquivo de download do documento
|
||||||
document_name: Nome do documento
|
|
||||||
unarchive: Desarquivar
|
|
||||||
awaiting_completion_by_the_other_party: "Aguardando a conclusão pela outra parte"
|
awaiting_completion_by_the_other_party: "Aguardando a conclusão pela outra parte"
|
||||||
enforce_recipients_order: 'Forçar a ordem dos recipientes'
|
enforce_recipients_order: 'Forçar a ordem dos recipientes'
|
||||||
first_party: 'Primeira Parte'
|
first_party: 'Primeira Parte'
|
||||||
@@ -3539,7 +3590,7 @@ pt: &pt
|
|||||||
please_check_the_copy_of_your_name_in_the_email_attachments: 'Por favor, verifique a cópia de "%{name}" nos anexos do e-mail.'
|
please_check_the_copy_of_your_name_in_the_email_attachments: 'Por favor, verifique a cópia de "%{name}" nos anexos do e-mail.'
|
||||||
review_and_sign: Revisar e assinar
|
review_and_sign: Revisar e assinar
|
||||||
review_and_submit: Revisar e submeter
|
review_and_submit: Revisar e submeter
|
||||||
please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this: 'Por favor, entre em contato conosco respondendo a este e-mail se você tiver alguma dúvida.'
|
please_contact_us_by_replying_to_this_email_if_you_have_any_questions: 'Por favor, entre em contato conosco respondendo a este e-mail se você tiver alguma dúvida.'
|
||||||
submitter_invitation_sms_body_sign: '{account.name} convidou você para assinar um documento: {submitter.link}'
|
submitter_invitation_sms_body_sign: '{account.name} convidou você para assinar um documento: {submitter.link}'
|
||||||
verification_code_sms_body: 'Código de verificação: {code}'
|
verification_code_sms_body: 'Código de verificação: {code}'
|
||||||
you_are_invited_to_submit_a_form: Você foi convidado a submeter um formulário
|
you_are_invited_to_submit_a_form: Você foi convidado a submeter um formulário
|
||||||
@@ -3551,11 +3602,11 @@ pt: &pt
|
|||||||
submitter_invitation_email_sign_body: |
|
submitter_invitation_email_sign_body: |
|
||||||
Olá,
|
Olá,
|
||||||
|
|
||||||
Você foi convidado a assinar o documento "{template.name}".
|
Você foi convidado a assinar "{template.name}".
|
||||||
|
|
||||||
[Revisar e assinar]({submitter.link})
|
[Revisar e assinar]({submitter.link})
|
||||||
|
|
||||||
Por favor, entre em contato conosco se tiver alguma dúvida.
|
Por favor, entre em contato conosco respondendo a este e-mail se você tiver alguma dúvida.
|
||||||
|
|
||||||
Obrigado,
|
Obrigado,
|
||||||
{account.name}
|
{account.name}
|
||||||
@@ -3568,8 +3619,8 @@ pt: &pt
|
|||||||
submitter_documents_copy_email_body: |
|
submitter_documents_copy_email_body: |
|
||||||
Olá,
|
Olá,
|
||||||
|
|
||||||
Por favor, verifique a cópia de seu "{template.name}" nos anexos do e-mail.
|
Por favor, verifique a cópia de "{template.name}" nos anexos do e-mail.
|
||||||
Alternativamente, você pode revisar e baixar sua cópia usando o link abaixo:
|
Você pode revisar e baixar sua cópia usando o link abaixo:
|
||||||
|
|
||||||
[{template.name}]({documents.link})
|
[{template.name}]({documents.link})
|
||||||
|
|
||||||
@@ -3863,7 +3914,6 @@ pt: &pt
|
|||||||
send_signature_request_emails_without_limits_with_docuseal_pro: Enviar e-mails de solicitação de assinatura sem limites com o DocuSeal Pro
|
send_signature_request_emails_without_limits_with_docuseal_pro: Enviar e-mails de solicitação de assinatura sem limites com o DocuSeal Pro
|
||||||
count_emails_used: '%{count} e-mails usados'
|
count_emails_used: '%{count} e-mails usados'
|
||||||
has_been_connected: foi conectado
|
has_been_connected: foi conectado
|
||||||
but_not_activated: mas não ativado
|
|
||||||
sms_not_configured: SMS não configurado
|
sms_not_configured: SMS não configurado
|
||||||
configure_sms_settings_in_order_to_send_text_messages_: 'Configure as configurações de SMS para enviar mensagens de texto:'
|
configure_sms_settings_in_order_to_send_text_messages_: 'Configure as configurações de SMS para enviar mensagens de texto:'
|
||||||
go_to_sms_settings: Ir para configurações de SMS
|
go_to_sms_settings: Ir para configurações de SMS
|
||||||
@@ -3925,6 +3975,10 @@ pt: &pt
|
|||||||
users_count_total_users_count_pro_users_limit_was_reached_to_invite_additional_users_please_purchase_more_pro_user_seats_via_the_manage_plan_button: 'O limite de %{users_count}/%{total_users_count} usuários Pro foi atingido. Para convidar mais usuários, adquira mais licenças Pro através do botão "Gerenciar plano".'
|
users_count_total_users_count_pro_users_limit_was_reached_to_invite_additional_users_please_purchase_more_pro_user_seats_via_the_manage_plan_button: 'O limite de %{users_count}/%{total_users_count} usuários Pro foi atingido. Para convidar mais usuários, adquira mais licenças Pro através do botão "Gerenciar plano".'
|
||||||
move_into_folder: Mover para pasta
|
move_into_folder: Mover para pasta
|
||||||
new_folder_name: Novo nome da pasta
|
new_folder_name: Novo nome da pasta
|
||||||
|
new_subfolder_name: Novo nome da subpasta
|
||||||
|
change_parent_folder: Alterar pasta pai
|
||||||
|
folder: Pasta
|
||||||
|
create_a_new_folder: Criar uma nova pasta
|
||||||
exit_preview: Sair da pré-visualização
|
exit_preview: Sair da pré-visualização
|
||||||
general: Geral
|
general: Geral
|
||||||
recipients: Destinatários
|
recipients: Destinatários
|
||||||
@@ -3957,7 +4011,6 @@ pt: &pt
|
|||||||
edit_user: Editar usuário
|
edit_user: Editar usuário
|
||||||
new_user: Novo usuário
|
new_user: Novo usuário
|
||||||
unarchive: Desarquivar
|
unarchive: Desarquivar
|
||||||
role: Função
|
|
||||||
last_session: Última sessão
|
last_session: Última sessão
|
||||||
unlock_more_user_roles_with_docuseal_pro: Desbloqueie mais funções de usuário com DocuSeal Pro.
|
unlock_more_user_roles_with_docuseal_pro: Desbloqueie mais funções de usuário com DocuSeal Pro.
|
||||||
view_active: Ver ativos
|
view_active: Ver ativos
|
||||||
@@ -4024,8 +4077,6 @@ pt: &pt
|
|||||||
new_webhook: Novo Webhook
|
new_webhook: Novo Webhook
|
||||||
delete_webhook: Excluir webhook
|
delete_webhook: Excluir webhook
|
||||||
count_submissions_have_been_created: '%{count} submissões foram criadas.'
|
count_submissions_have_been_created: '%{count} submissões foram criadas.'
|
||||||
gmail_has_been_connected: O Gmail foi conectado
|
|
||||||
microsoft_account_has_been_connected: A conta da Microsoft foi conectada
|
|
||||||
sms_length_cant_be_longer_than_120_bytes: O comprimento do SMS não pode ultrapassar 120 bytes
|
sms_length_cant_be_longer_than_120_bytes: O comprimento do SMS não pode ultrapassar 120 bytes
|
||||||
connected_successfully: Conectado com sucesso.
|
connected_successfully: Conectado com sucesso.
|
||||||
user_nameid_not_found: 'Usuário %{nameid} não encontrado.'
|
user_nameid_not_found: 'Usuário %{nameid} não encontrado.'
|
||||||
@@ -4244,6 +4295,19 @@ pt: &pt
|
|||||||
email_verification: Verificação de e-mail
|
email_verification: Verificação de e-mail
|
||||||
your_verification_code_to_access_the_name: 'Seu código de verificação para acessar "%{name}":'
|
your_verification_code_to_access_the_name: 'Seu código de verificação para acessar "%{name}":'
|
||||||
please_reply_to_this_email_if_you_didnt_request_this: Responda a este e-mail se você não solicitou isso.
|
please_reply_to_this_email_if_you_didnt_request_this: Responda a este e-mail se você não solicitou isso.
|
||||||
|
advanced_settings: Configurações avançadas
|
||||||
|
text: Texto
|
||||||
|
code: Código
|
||||||
|
custom_html_emails: E-mails HTML personalizados
|
||||||
|
connect_your_email_to_send_html_emails: Conecte seu e-mail para enviar e-mails HTML
|
||||||
|
connect_your_email_or_outlook_account_or_add_smtp_settings_to_send_custom_html_emails: Conecte sua conta Gmail ou Outlook ou adicione configurações SMTP para enviar e-mails HTML personalizados.
|
||||||
|
connect_gmail_or_outlook: Conectar Gmail ou Outlook
|
||||||
|
connect_your_email_to_bulk_send: Conecte seu e-mail para envio em massa
|
||||||
|
connect_your_email_or_outlook_account_or_add_smtp_settings_to_bulk_send: Conecte sua conta Gmail ou Outlook ou adicione configurações SMTP para envio em massa.
|
||||||
|
are_you_sure_you_want_to_add_recipients_without_sending_to_send_emails_it_requires_to_connect_gmail_or_outlook: Tem certeza de que deseja adicionar destinatários sem enviar? Para enviar e-mails é necessário conectar Gmail ou Outlook.
|
||||||
|
template_name_has_been_completed_by_submitters_html: '"<strong>{template.name}</strong>" foi concluído por <strong>{submission.submitters}</strong>'
|
||||||
|
please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Por favor, verifique a cópia do seu "<strong>{template.name}</strong>" nos anexos do e-mail.'
|
||||||
|
you_have_been_invited_to_sign_the_template_name_html: 'Você foi convidado a assinar o "<strong>{template.name}</strong>".'
|
||||||
submission_sources:
|
submission_sources:
|
||||||
api: API
|
api: API
|
||||||
bulk: Envio em massa
|
bulk: Envio em massa
|
||||||
@@ -4324,7 +4388,6 @@ pt: &pt
|
|||||||
settings_account_description: 'Com configurações completas de conta, você pode personalizar a experiência de assinatura eletrônica e convidar mais usuários.'
|
settings_account_description: 'Com configurações completas de conta, você pode personalizar a experiência de assinatura eletrônica e convidar mais usuários.'
|
||||||
support: 'Suporte'
|
support: 'Suporte'
|
||||||
support_description: 'Você pode usar nosso assistente de IA ou nos escrever para support@docuseal.com se tiver dúvidas.'
|
support_description: 'Você pode usar nosso assistente de IA ou nos escrever para support@docuseal.com se tiver dúvidas.'
|
||||||
settings: 'Configurações'
|
|
||||||
settings_template_description: 'Use este botão para acessar a página de configurações da sua conta.'
|
settings_template_description: 'Use este botão para acessar a página de configurações da sua conta.'
|
||||||
doorkeeper:
|
doorkeeper:
|
||||||
scopes:
|
scopes:
|
||||||
@@ -4351,6 +4414,8 @@ pt: &pt
|
|||||||
range_without_total: "%{from}-%{to} eventos"
|
range_without_total: "%{from}-%{to} eventos"
|
||||||
|
|
||||||
de: &de
|
de: &de
|
||||||
|
select: Auswählen
|
||||||
|
invite_form_fields: Formularfelder einladen
|
||||||
pro: Pro
|
pro: Pro
|
||||||
default_parties: Standardparteien
|
default_parties: Standardparteien
|
||||||
authenticate_embedded_form_preview_with_token: Authentifizieren Sie die eingebettete Formularvorschau mit Token
|
authenticate_embedded_form_preview_with_token: Authentifizieren Sie die eingebettete Formularvorschau mit Token
|
||||||
@@ -4384,8 +4449,6 @@ de: &de
|
|||||||
team_access: Teamzugang
|
team_access: Teamzugang
|
||||||
remove_filter: Filter entfernen
|
remove_filter: Filter entfernen
|
||||||
document_download_filename_format: Format des Dateinamens beim Herunterladen von Dokumenten
|
document_download_filename_format: Format des Dateinamens beim Herunterladen von Dokumenten
|
||||||
document_name: Dokumentname
|
|
||||||
unarchive: Wiederherstellen
|
|
||||||
awaiting_completion_by_the_other_party: "Warten auf die Fertigstellung durch die andere Partei"
|
awaiting_completion_by_the_other_party: "Warten auf die Fertigstellung durch die andere Partei"
|
||||||
enforce_recipients_order: 'Empfängerreihenfolge durchsetzen'
|
enforce_recipients_order: 'Empfängerreihenfolge durchsetzen'
|
||||||
first_party: 'Erste Partei'
|
first_party: 'Erste Partei'
|
||||||
@@ -4406,7 +4469,7 @@ de: &de
|
|||||||
please_check_the_copy_of_your_name_in_the_email_attachments: 'Bitte überprüfe die Kopie von "%{name}" im E-Mail-Anhang.'
|
please_check_the_copy_of_your_name_in_the_email_attachments: 'Bitte überprüfe die Kopie von "%{name}" im E-Mail-Anhang.'
|
||||||
review_and_sign: Überprüfen und unterschreiben
|
review_and_sign: Überprüfen und unterschreiben
|
||||||
review_and_submit: Überprüfen und einreichen
|
review_and_submit: Überprüfen und einreichen
|
||||||
please_contact_us_by_replying_to_this_email_if_you_didn_t_request_this: 'Bitte kontaktiere uns, indem du auf diese E-Mail antwortest, falls du Fragen hast.'
|
please_contact_us_by_replying_to_this_email_if_you_have_any_questions: 'Bitte kontaktieren Sie uns, indem Sie auf diese E-Mail antworten, falls Sie Fragen haben.'
|
||||||
submitter_invitation_sms_body_sign: '{account.name} hat dich eingeladen, ein Dokument zu unterschreiben: {submitter.link}'
|
submitter_invitation_sms_body_sign: '{account.name} hat dich eingeladen, ein Dokument zu unterschreiben: {submitter.link}'
|
||||||
verification_code_sms_body: 'Verifizierungscode: {code}'
|
verification_code_sms_body: 'Verifizierungscode: {code}'
|
||||||
you_are_invited_to_submit_a_form: Du wurdest eingeladen, ein Formular einzureichen
|
you_are_invited_to_submit_a_form: Du wurdest eingeladen, ein Formular einzureichen
|
||||||
@@ -4418,11 +4481,11 @@ de: &de
|
|||||||
submitter_invitation_email_sign_body: |
|
submitter_invitation_email_sign_body: |
|
||||||
Hallo,
|
Hallo,
|
||||||
|
|
||||||
Du wurdest eingeladen, das Dokument "{template.name}" zu unterschreiben.
|
Du wurdest eingeladen, "{template.name}" zu unterschreiben.
|
||||||
|
|
||||||
[Überprüfen und unterschreiben]({submitter.link})
|
[Überprüfen und unterschreiben]({submitter.link})
|
||||||
|
|
||||||
Bitte kontaktiere uns, falls du Fragen hast.
|
Bitte kontaktieren Sie uns, indem Sie auf diese E-Mail antworten, falls Sie Fragen haben.
|
||||||
|
|
||||||
Danke,
|
Danke,
|
||||||
{account.name}
|
{account.name}
|
||||||
@@ -4435,8 +4498,8 @@ de: &de
|
|||||||
submitter_documents_copy_email_body: |
|
submitter_documents_copy_email_body: |
|
||||||
Hallo,
|
Hallo,
|
||||||
|
|
||||||
Bitte überprüfe die Kopie deines "{template.name}" im E-Mail-Anhang.
|
Bitte überprüfe die Kopie von "{template.name}" im E-Mail-Anhang.
|
||||||
Alternativ kannst du deine Kopie mit dem untenstehenden Link überprüfen und herunterladen:
|
Du kannst alternativ deine Kopie mit dem untenstehenden Link überprüfen und herunterladen:
|
||||||
|
|
||||||
[{template.name}]({documents.link})
|
[{template.name}]({documents.link})
|
||||||
|
|
||||||
@@ -4730,7 +4793,6 @@ de: &de
|
|||||||
send_signature_request_emails_without_limits_with_docuseal_pro: Unterschriftsanfragen ohne Limits mit DocuSeal Pro senden
|
send_signature_request_emails_without_limits_with_docuseal_pro: Unterschriftsanfragen ohne Limits mit DocuSeal Pro senden
|
||||||
count_emails_used: '%{count} E-Mails verwendet'
|
count_emails_used: '%{count} E-Mails verwendet'
|
||||||
has_been_connected: wurde verbunden
|
has_been_connected: wurde verbunden
|
||||||
but_not_activated: aber nicht aktiviert
|
|
||||||
sms_not_configured: SMS nicht konfiguriert
|
sms_not_configured: SMS nicht konfiguriert
|
||||||
configure_sms_settings_in_order_to_send_text_messages_: 'Konfiguriere die SMS-Einstellungen, um Textnachrichten zu senden:'
|
configure_sms_settings_in_order_to_send_text_messages_: 'Konfiguriere die SMS-Einstellungen, um Textnachrichten zu senden:'
|
||||||
go_to_sms_settings: Zu den SMS-Einstellungen gehen
|
go_to_sms_settings: Zu den SMS-Einstellungen gehen
|
||||||
@@ -4792,6 +4854,10 @@ de: &de
|
|||||||
users_count_total_users_count_pro_users_limit_was_reached_to_invite_additional_users_please_purchase_more_pro_user_seats_via_the_manage_plan_button: 'Das Limit von %{users_count}/%{total_users_count} Pro-Benutzern wurde erreicht. Um weitere Benutzer einzuladen, kaufen Sie bitte zusätzliche Pro-Benutzerplätze über die Schaltfläche "Plan verwalten".'
|
users_count_total_users_count_pro_users_limit_was_reached_to_invite_additional_users_please_purchase_more_pro_user_seats_via_the_manage_plan_button: 'Das Limit von %{users_count}/%{total_users_count} Pro-Benutzern wurde erreicht. Um weitere Benutzer einzuladen, kaufen Sie bitte zusätzliche Pro-Benutzerplätze über die Schaltfläche "Plan verwalten".'
|
||||||
move_into_folder: In Ordner verschieben
|
move_into_folder: In Ordner verschieben
|
||||||
new_folder_name: Neuer Ordnername
|
new_folder_name: Neuer Ordnername
|
||||||
|
new_subfolder_name: Neuer Unterordnername
|
||||||
|
change_parent_folder: Übergeordneten Ordner ändern
|
||||||
|
folder: Ordner
|
||||||
|
create_a_new_folder: Neuen Ordner erstellen
|
||||||
exit_preview: Vorschau beenden
|
exit_preview: Vorschau beenden
|
||||||
general: Allgemein
|
general: Allgemein
|
||||||
recipients: Empfänger
|
recipients: Empfänger
|
||||||
@@ -4824,7 +4890,6 @@ de: &de
|
|||||||
edit_user: Benutzer bearbeiten
|
edit_user: Benutzer bearbeiten
|
||||||
new_user: Neuer Benutzer
|
new_user: Neuer Benutzer
|
||||||
unarchive: Entarchivieren
|
unarchive: Entarchivieren
|
||||||
role: Rolle
|
|
||||||
last_session: Letzte Sitzung
|
last_session: Letzte Sitzung
|
||||||
unlock_more_user_roles_with_docuseal_pro: Weitere Benutzerrollen mit DocuSeal Pro freischalten.
|
unlock_more_user_roles_with_docuseal_pro: Weitere Benutzerrollen mit DocuSeal Pro freischalten.
|
||||||
view_active: Aktive anzeigen
|
view_active: Aktive anzeigen
|
||||||
@@ -4891,8 +4956,6 @@ de: &de
|
|||||||
new_webhook: Neuer Webhook
|
new_webhook: Neuer Webhook
|
||||||
delete_webhook: Webhook löschen
|
delete_webhook: Webhook löschen
|
||||||
count_submissions_have_been_created: '%{count} Einreichungen wurden erstellt.'
|
count_submissions_have_been_created: '%{count} Einreichungen wurden erstellt.'
|
||||||
gmail_has_been_connected: Gmail wurde verbunden.
|
|
||||||
microsoft_account_has_been_connected: Microsoft-Konto wurde verbunden.
|
|
||||||
sms_length_cant_be_longer_than_120_bytes: Die SMS-Länge darf 120 Bytes nicht überschreiten.
|
sms_length_cant_be_longer_than_120_bytes: Die SMS-Länge darf 120 Bytes nicht überschreiten.
|
||||||
connected_successfully: Erfolgreich verbunden.
|
connected_successfully: Erfolgreich verbunden.
|
||||||
user_nameid_not_found: 'Benutzer %{nameid} nicht gefunden.'
|
user_nameid_not_found: 'Benutzer %{nameid} nicht gefunden.'
|
||||||
@@ -5111,6 +5174,19 @@ de: &de
|
|||||||
email_verification: E-Mail-Verifizierung
|
email_verification: E-Mail-Verifizierung
|
||||||
your_verification_code_to_access_the_name: 'Ihr Verifizierungscode für den Zugriff auf "%{name}":'
|
your_verification_code_to_access_the_name: 'Ihr Verifizierungscode für den Zugriff auf "%{name}":'
|
||||||
please_reply_to_this_email_if_you_didnt_request_this: Antworten Sie auf diese E-Mail, wenn Sie dies nicht angefordert haben.
|
please_reply_to_this_email_if_you_didnt_request_this: Antworten Sie auf diese E-Mail, wenn Sie dies nicht angefordert haben.
|
||||||
|
advanced_settings: Erweiterte Einstellungen
|
||||||
|
text: Text
|
||||||
|
code: Code
|
||||||
|
custom_html_emails: Benutzerdefinierte HTML-E-Mails
|
||||||
|
connect_your_email_to_send_html_emails: Verbinden Sie Ihr E-Mail-Konto, um HTML-E-Mails zu senden
|
||||||
|
connect_your_email_or_outlook_account_or_add_smtp_settings_to_send_custom_html_emails: Verbinden Sie Ihr Gmail- oder Outlook-Konto oder fügen Sie SMTP-Einstellungen hinzu, um benutzerdefinierte HTML-E-Mails zu senden.
|
||||||
|
connect_gmail_or_outlook: Gmail oder Outlook verbinden
|
||||||
|
connect_your_email_to_bulk_send: Verbinden Sie Ihr E-Mail-Konto für Massenversand
|
||||||
|
connect_your_email_or_outlook_account_or_add_smtp_settings_to_bulk_send: Verbinden Sie Ihr Gmail- oder Outlook-Konto oder fügen Sie SMTP-Einstellungen für den Massenversand hinzu.
|
||||||
|
are_you_sure_you_want_to_add_recipients_without_sending_to_send_emails_it_requires_to_connect_gmail_or_outlook: Möchten Sie wirklich Empfänger hinzufügen, ohne zu senden? Zum Senden von E-Mails ist eine Verbindung zu Gmail oder Outlook erforderlich.
|
||||||
|
template_name_has_been_completed_by_submitters_html: '"<strong>{template.name}</strong>" wurde von <strong>{submission.submitters}</strong> abgeschlossen'
|
||||||
|
please_check_the_copy_of_your_template_name_in_the_email_attachments_html: 'Bitte prüfen Sie die Kopie Ihres "<strong>{template.name}</strong>" in den E-Mail-Anhängen.'
|
||||||
|
you_have_been_invited_to_sign_the_template_name_html: 'Du wurdest eingeladen, "<strong>{template.name}</strong>" zu unterschreiben.'
|
||||||
submission_sources:
|
submission_sources:
|
||||||
api: API
|
api: API
|
||||||
bulk: Massenversand
|
bulk: Massenversand
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ Rails.application.routes.draw do
|
|||||||
resource :preferences, only: %i[show create], controller: 'templates_preferences'
|
resource :preferences, only: %i[show create], controller: 'templates_preferences'
|
||||||
resource :share_link, only: %i[show create], controller: 'templates_share_link'
|
resource :share_link, only: %i[show create], controller: 'templates_share_link'
|
||||||
resources :recipients, only: %i[create], controller: 'templates_recipients'
|
resources :recipients, only: %i[create], controller: 'templates_recipients'
|
||||||
|
resources :prefillable_fields, only: %i[create], controller: 'templates_prefillable_fields'
|
||||||
resources :submissions_export, only: %i[index new]
|
resources :submissions_export, only: %i[index new]
|
||||||
end
|
end
|
||||||
resources :preview_document_page, only: %i[show], path: '/preview/:signed_uuid'
|
resources :preview_document_page, only: %i[show], path: '/preview/:signed_uuid'
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddParentFolderIdToTemplateFolders < ActiveRecord::Migration[8.0]
|
||||||
|
def change
|
||||||
|
add_reference :template_folders, :parent_folder, foreign_key: { to_table: :template_folders }, index: true
|
||||||
|
end
|
||||||
|
end
|
||||||
+4
-1
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[8.0].define(version: 2025_06_27_130628) do
|
ActiveRecord::Schema[8.0].define(version: 2025_07_18_121133) do
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "btree_gin"
|
enable_extension "btree_gin"
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
@@ -356,8 +356,10 @@ ActiveRecord::Schema[8.0].define(version: 2025_06_27_130628) do
|
|||||||
t.datetime "archived_at"
|
t.datetime "archived_at"
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
|
t.bigint "parent_folder_id"
|
||||||
t.index ["account_id"], name: "index_template_folders_on_account_id"
|
t.index ["account_id"], name: "index_template_folders_on_account_id"
|
||||||
t.index ["author_id"], name: "index_template_folders_on_author_id"
|
t.index ["author_id"], name: "index_template_folders_on_author_id"
|
||||||
|
t.index ["parent_folder_id"], name: "index_template_folders_on_parent_folder_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "template_sharings", force: :cascade do |t|
|
create_table "template_sharings", force: :cascade do |t|
|
||||||
@@ -498,6 +500,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_06_27_130628) do
|
|||||||
add_foreign_key "submitters", "submissions"
|
add_foreign_key "submitters", "submissions"
|
||||||
add_foreign_key "template_accesses", "templates"
|
add_foreign_key "template_accesses", "templates"
|
||||||
add_foreign_key "template_folders", "accounts"
|
add_foreign_key "template_folders", "accounts"
|
||||||
|
add_foreign_key "template_folders", "template_folders", column: "parent_folder_id"
|
||||||
add_foreign_key "template_folders", "users", column: "author_id"
|
add_foreign_key "template_folders", "users", column: "author_id"
|
||||||
add_foreign_key "template_sharings", "templates"
|
add_foreign_key "template_sharings", "templates"
|
||||||
add_foreign_key "templates", "accounts"
|
add_foreign_key "templates", "accounts"
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ module Submissions
|
|||||||
ALLOWED_PARAMS = %w[
|
ALLOWED_PARAMS = %w[
|
||||||
author
|
author
|
||||||
status
|
status
|
||||||
|
folder
|
||||||
completed_at_from
|
completed_at_from
|
||||||
completed_at_to
|
completed_at_to
|
||||||
created_at_from
|
created_at_from
|
||||||
@@ -24,6 +25,7 @@ module Submissions
|
|||||||
filters = normalize_filter_params(params, current_user)
|
filters = normalize_filter_params(params, current_user)
|
||||||
|
|
||||||
submissions = filter_by_author(submissions, filters, current_user)
|
submissions = filter_by_author(submissions, filters, current_user)
|
||||||
|
submissions = filter_by_folder(submissions, filters, current_user)
|
||||||
submissions = filter_by_status(submissions, filters)
|
submissions = filter_by_status(submissions, filters)
|
||||||
submissions = filter_by_created_at(submissions, filters)
|
submissions = filter_by_created_at(submissions, filters)
|
||||||
|
|
||||||
@@ -34,6 +36,7 @@ module Submissions
|
|||||||
return submissions if filters[:author].blank?
|
return submissions if filters[:author].blank?
|
||||||
|
|
||||||
user = current_user.account.users.find_by(email: filters[:author])
|
user = current_user.account.users.find_by(email: filters[:author])
|
||||||
|
|
||||||
submissions.where(created_by_user_id: user&.id || -1)
|
submissions.where(created_by_user_id: user&.id || -1)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -87,6 +90,17 @@ module Submissions
|
|||||||
submissions
|
submissions
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def filter_by_folder(submissions, filters, current_user)
|
||||||
|
return submissions if filters[:folder].blank?
|
||||||
|
|
||||||
|
folders =
|
||||||
|
TemplateFolders.filter_by_full_name(current_user.account.template_folders, filters[:folder])
|
||||||
|
|
||||||
|
folders += folders.preload(:subfolders).flat_map(&:subfolders)
|
||||||
|
|
||||||
|
submissions.joins(:template).where(templates: { folder_id: folders.map(&:id) })
|
||||||
|
end
|
||||||
|
|
||||||
def filter_by_completed_at(submissions, filters)
|
def filter_by_completed_at(submissions, filters)
|
||||||
return submissions unless filters[:completed_at_from].present? || filters[:completed_at_to].present?
|
return submissions unless filters[:completed_at_from].present? || filters[:completed_at_to].present?
|
||||||
|
|
||||||
|
|||||||
@@ -261,8 +261,6 @@ module Submissions
|
|||||||
e['type'] == 'verification' && e['submitter_uuid'] == submitter.uuid && submitter.values[e['uuid']].present?
|
e['type'] == 'verification' && e['submitter_uuid'] == submitter.uuid && submitter.values[e['uuid']].present?
|
||||||
end
|
end
|
||||||
|
|
||||||
submitter_field_counters = Hash.new { 0 }
|
|
||||||
|
|
||||||
info_rows = [
|
info_rows = [
|
||||||
[
|
[
|
||||||
composer.document.layout.formatted_text_box(
|
composer.document.layout.formatted_text_box(
|
||||||
@@ -298,25 +296,53 @@ module Submissions
|
|||||||
|
|
||||||
composer.table(info_rows, cell_style: { padding: [0, 0, 0, 0], border: { width: 0 } })
|
composer.table(info_rows, cell_style: { padding: [0, 0, 0, 0], border: { width: 0 } })
|
||||||
|
|
||||||
|
submitter_field_counters = Hash.new { 0 }
|
||||||
|
grouped_value_field_names = {}
|
||||||
|
skip_grouped_field_uuids = {}
|
||||||
|
|
||||||
|
submission.template_fields.each do |field|
|
||||||
|
next unless field['type'].in?(%w[signature initials])
|
||||||
|
|
||||||
|
submitter_field_counters[field['type']] += 1
|
||||||
|
|
||||||
|
next if field['submitter_uuid'] != submitter.uuid
|
||||||
|
|
||||||
|
value = submitter.values[field['uuid']]
|
||||||
|
|
||||||
|
field_name = field['title'].presence || field['name'].presence ||
|
||||||
|
"#{I18n.t("#{field['type']}_field")} #{submitter_field_counters[field['type']]}"
|
||||||
|
|
||||||
|
if grouped_value_field_names[value]
|
||||||
|
skip_grouped_field_uuids[field['uuid']] = true
|
||||||
|
|
||||||
|
grouped_value_field_names[value] += ", #{field_name}"
|
||||||
|
else
|
||||||
|
grouped_value_field_names[value] = field_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
submitter_field_counters = Hash.new { 0 }
|
||||||
|
|
||||||
submission.template_fields.filter_map do |field|
|
submission.template_fields.filter_map do |field|
|
||||||
|
submitter_field_counters[field['type']] += 1
|
||||||
|
|
||||||
next if field['submitter_uuid'] != submitter.uuid
|
next if field['submitter_uuid'] != submitter.uuid
|
||||||
next if field['type'] == 'heading'
|
next if field['type'] == 'heading'
|
||||||
next if !with_audit_values && !field['type'].in?(%w[signature initials])
|
next if !with_audit_values && !field['type'].in?(%w[signature initials])
|
||||||
|
next if skip_grouped_field_uuids[field['uuid']]
|
||||||
submitter_field_counters[field['type']] += 1
|
|
||||||
|
|
||||||
value = submitter.values[field['uuid']]
|
value = submitter.values[field['uuid']]
|
||||||
|
|
||||||
next if Array.wrap(value).compact_blank.blank?
|
next if Array.wrap(value).compact_blank.blank?
|
||||||
|
|
||||||
field_name = field['title'].presence || field['name'].to_s
|
field_name = grouped_value_field_names[value].presence || field['title'].presence || field['name'].to_s
|
||||||
|
|
||||||
[
|
[
|
||||||
composer.formatted_text_box(
|
composer.formatted_text_box(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
text: TextUtils.maybe_rtl_reverse(field_name).upcase.presence ||
|
text: TextUtils.maybe_rtl_reverse(field_name).upcase.presence ||
|
||||||
"#{I18n.t("#{field['type']}_field")} #{submitter_field_counters[field['type']]}\n".upcase,
|
"#{I18n.t("#{field['type']}_field")} #{submitter_field_counters[field['type']]}".upcase,
|
||||||
font_size: 6
|
font_size: 6
|
||||||
}
|
}
|
||||||
].compact_blank,
|
].compact_blank,
|
||||||
|
|||||||
@@ -14,11 +14,14 @@ module Submissions
|
|||||||
|
|
||||||
configs = submission.account.account_configs.where(key: [AccountConfig::FLATTEN_RESULT_PDF_KEY,
|
configs = submission.account.account_configs.where(key: [AccountConfig::FLATTEN_RESULT_PDF_KEY,
|
||||||
AccountConfig::WITH_SIGNATURE_ID,
|
AccountConfig::WITH_SIGNATURE_ID,
|
||||||
AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY])
|
AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY,
|
||||||
|
AccountConfig::WITH_SIGNATURE_ID_REASON_KEY])
|
||||||
|
|
||||||
with_signature_id = configs.find { |c| c.key == AccountConfig::WITH_SIGNATURE_ID }&.value == true
|
with_signature_id = configs.find { |c| c.key == AccountConfig::WITH_SIGNATURE_ID }&.value == true
|
||||||
is_flatten = configs.find { |c| c.key == AccountConfig::FLATTEN_RESULT_PDF_KEY }&.value != false
|
is_flatten = configs.find { |c| c.key == AccountConfig::FLATTEN_RESULT_PDF_KEY }&.value != false
|
||||||
with_submitter_timezone = configs.find { |c| c.key == AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY }&.value == true
|
with_submitter_timezone = configs.find { |c| c.key == AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY }&.value == true
|
||||||
|
with_signature_id_reason =
|
||||||
|
configs.find { |c| c.key == AccountConfig::WITH_SIGNATURE_ID_REASON_KEY }&.value != false
|
||||||
|
|
||||||
pdfs_index = GenerateResultAttachments.build_pdfs_index(submission, flatten: is_flatten)
|
pdfs_index = GenerateResultAttachments.build_pdfs_index(submission, flatten: is_flatten)
|
||||||
|
|
||||||
@@ -31,7 +34,8 @@ module Submissions
|
|||||||
submitters.preload(attachments_attachments: :blob).each_with_index do |s, index|
|
submitters.preload(attachments_attachments: :blob).each_with_index do |s, index|
|
||||||
GenerateResultAttachments.fill_submitter_fields(s, submission.account, pdfs_index,
|
GenerateResultAttachments.fill_submitter_fields(s, submission.account, pdfs_index,
|
||||||
with_signature_id:, is_flatten:, with_headings: index.zero?,
|
with_signature_id:, is_flatten:, with_headings: index.zero?,
|
||||||
with_submitter_timezone:)
|
with_submitter_timezone:,
|
||||||
|
with_signature_id_reason:)
|
||||||
end
|
end
|
||||||
|
|
||||||
template = submission.template
|
template = submission.template
|
||||||
|
|||||||
@@ -139,11 +139,14 @@ module Submissions
|
|||||||
def generate_pdfs(submitter)
|
def generate_pdfs(submitter)
|
||||||
configs = submitter.account.account_configs.where(key: [AccountConfig::FLATTEN_RESULT_PDF_KEY,
|
configs = submitter.account.account_configs.where(key: [AccountConfig::FLATTEN_RESULT_PDF_KEY,
|
||||||
AccountConfig::WITH_SIGNATURE_ID,
|
AccountConfig::WITH_SIGNATURE_ID,
|
||||||
AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY])
|
AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY,
|
||||||
|
AccountConfig::WITH_SIGNATURE_ID_REASON_KEY])
|
||||||
|
|
||||||
with_signature_id = configs.find { |c| c.key == AccountConfig::WITH_SIGNATURE_ID }&.value == true
|
with_signature_id = configs.find { |c| c.key == AccountConfig::WITH_SIGNATURE_ID }&.value == true
|
||||||
is_flatten = configs.find { |c| c.key == AccountConfig::FLATTEN_RESULT_PDF_KEY }&.value != false
|
is_flatten = configs.find { |c| c.key == AccountConfig::FLATTEN_RESULT_PDF_KEY }&.value != false
|
||||||
with_submitter_timezone = configs.find { |c| c.key == AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY }&.value == true
|
with_submitter_timezone = configs.find { |c| c.key == AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY }&.value == true
|
||||||
|
with_signature_id_reason =
|
||||||
|
configs.find { |c| c.key == AccountConfig::WITH_SIGNATURE_ID_REASON_KEY }&.value != false
|
||||||
|
|
||||||
pdfs_index = build_pdfs_index(submitter.submission, submitter:, flatten: is_flatten)
|
pdfs_index = build_pdfs_index(submitter.submission, submitter:, flatten: is_flatten)
|
||||||
|
|
||||||
@@ -188,11 +191,12 @@ module Submissions
|
|||||||
end
|
end
|
||||||
|
|
||||||
fill_submitter_fields(submitter, submitter.account, pdfs_index, with_signature_id:, is_flatten:,
|
fill_submitter_fields(submitter, submitter.account, pdfs_index, with_signature_id:, is_flatten:,
|
||||||
with_submitter_timezone:)
|
with_submitter_timezone:,
|
||||||
|
with_signature_id_reason:)
|
||||||
end
|
end
|
||||||
|
|
||||||
def fill_submitter_fields(submitter, account, pdfs_index, with_signature_id:, is_flatten:, with_headings: nil,
|
def fill_submitter_fields(submitter, account, pdfs_index, with_signature_id:, is_flatten:, with_headings: nil,
|
||||||
with_submitter_timezone: false)
|
with_submitter_timezone: false, with_signature_id_reason: true)
|
||||||
cell_layouter = HexaPDF::Layout::TextLayouter.new(text_valign: :center, text_align: :center)
|
cell_layouter = HexaPDF::Layout::TextLayouter.new(text_valign: :center, text_align: :center)
|
||||||
|
|
||||||
attachments_data_cache = {}
|
attachments_data_cache = {}
|
||||||
@@ -274,6 +278,10 @@ module Submissions
|
|||||||
field_type = 'file' if field_type == 'image' &&
|
field_type = 'file' if field_type == 'image' &&
|
||||||
!submitter.attachments.find { |a| a.uuid == value }.image?
|
!submitter.attachments.find { |a| a.uuid == value }.image?
|
||||||
|
|
||||||
|
if field_type == 'signature' && field.dig('preferences', 'with_signature_id').in?([true, false])
|
||||||
|
with_signature_id = field['preferences']['with_signature_id']
|
||||||
|
end
|
||||||
|
|
||||||
case field_type
|
case field_type
|
||||||
when ->(type) { type == 'signature' && (with_signature_id || field.dig('preferences', 'reason_field_uuid')) }
|
when ->(type) { type == 'signature' && (with_signature_id || field.dig('preferences', 'reason_field_uuid')) }
|
||||||
attachment = submitter.attachments.find { |a| a.uuid == value }
|
attachment = submitter.attachments.find { |a| a.uuid == value }
|
||||||
@@ -295,10 +303,15 @@ module Submissions
|
|||||||
timezone = submitter.account.timezone
|
timezone = submitter.account.timezone
|
||||||
timezone = submitter.timezone || submitter.account.timezone if with_submitter_timezone
|
timezone = submitter.timezone || submitter.account.timezone if with_submitter_timezone
|
||||||
|
|
||||||
"#{reason_value ? "#{I18n.t('reason')}: " : ''}#{reason_value || I18n.t('digitally_signed_by')} " \
|
if with_signature_id_reason
|
||||||
"#{submitter.name}#{submitter.email.present? ? " <#{submitter.email}>" : ''}\n" \
|
"#{reason_value ? "#{I18n.t('reason')}: " : ''}#{reason_value || I18n.t('digitally_signed_by')} " \
|
||||||
|
"#{submitter.name}#{submitter.email.present? ? " <#{submitter.email}>" : ''}\n" \
|
||||||
|
"#{I18n.l(attachment.created_at.in_time_zone(timezone), format: :long)} " \
|
||||||
|
"#{TimeUtils.timezone_abbr(timezone, attachment.created_at)}"
|
||||||
|
else
|
||||||
"#{I18n.l(attachment.created_at.in_time_zone(timezone), format: :long)} " \
|
"#{I18n.l(attachment.created_at.in_time_zone(timezone), format: :long)} " \
|
||||||
"#{TimeUtils.timezone_abbr(timezone, attachment.created_at)}"
|
"#{TimeUtils.timezone_abbr(timezone, attachment.created_at)}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
reason_text = HexaPDF::Layout::TextFragment.create(reason_string,
|
reason_text = HexaPDF::Layout::TextFragment.create(reason_string,
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ module Submitters
|
|||||||
AccountConfig::REUSE_SIGNATURE_KEY,
|
AccountConfig::REUSE_SIGNATURE_KEY,
|
||||||
AccountConfig::ALLOW_TO_PARTIAL_DOWNLOAD_KEY,
|
AccountConfig::ALLOW_TO_PARTIAL_DOWNLOAD_KEY,
|
||||||
AccountConfig::ALLOW_TYPED_SIGNATURE,
|
AccountConfig::ALLOW_TYPED_SIGNATURE,
|
||||||
|
AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY,
|
||||||
|
AccountConfig::WITH_SIGNATURE_ID_REASON_KEY,
|
||||||
*(Docuseal.multitenant? ? [] : [AccountConfig::POLICY_LINKS_KEY])].freeze
|
*(Docuseal.multitenant? ? [] : [AccountConfig::POLICY_LINKS_KEY])].freeze
|
||||||
|
|
||||||
module_function
|
module_function
|
||||||
@@ -31,20 +33,15 @@ module Submitters
|
|||||||
with_signature_id = find_safe_value(configs, AccountConfig::WITH_SIGNATURE_ID) == true
|
with_signature_id = find_safe_value(configs, AccountConfig::WITH_SIGNATURE_ID) == true
|
||||||
require_signing_reason = find_safe_value(configs, AccountConfig::REQUIRE_SIGNING_REASON_KEY) == true
|
require_signing_reason = find_safe_value(configs, AccountConfig::REQUIRE_SIGNING_REASON_KEY) == true
|
||||||
enforce_signing_order = find_safe_value(configs, AccountConfig::ENFORCE_SIGNING_ORDER_KEY) == true
|
enforce_signing_order = find_safe_value(configs, AccountConfig::ENFORCE_SIGNING_ORDER_KEY) == true
|
||||||
|
with_submitter_timezone = find_safe_value(configs, AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY) == true
|
||||||
|
with_signature_id_reason = find_safe_value(configs, AccountConfig::WITH_SIGNATURE_ID_REASON_KEY) != false
|
||||||
policy_links = find_safe_value(configs, AccountConfig::POLICY_LINKS_KEY)
|
policy_links = find_safe_value(configs, AccountConfig::POLICY_LINKS_KEY)
|
||||||
|
|
||||||
attrs = { completed_button:,
|
attrs = { completed_button:, with_typed_signature:, with_confetti:,
|
||||||
with_typed_signature:,
|
reuse_signature:, with_decline:, with_partial_download:,
|
||||||
with_confetti:,
|
policy_links:, enforce_signing_order:, completed_message:,
|
||||||
reuse_signature:,
|
require_signing_reason:, prefill_signature:, with_submitter_timezone:,
|
||||||
with_decline:,
|
with_signature_id_reason:, with_signature_id: }
|
||||||
with_partial_download:,
|
|
||||||
policy_links:,
|
|
||||||
enforce_signing_order:,
|
|
||||||
completed_message:,
|
|
||||||
require_signing_reason:,
|
|
||||||
prefill_signature:,
|
|
||||||
with_signature_id: }
|
|
||||||
|
|
||||||
keys.each do |key|
|
keys.each do |key|
|
||||||
attrs[key.to_sym] = configs.find { |e| e.key == key.to_s }&.value
|
attrs[key.to_sym] = configs.find { |e| e.key == key.to_s }&.value
|
||||||
|
|||||||
+75
-1
@@ -3,15 +3,89 @@
|
|||||||
module TemplateFolders
|
module TemplateFolders
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
|
def filter_by_full_name(template_folders, name)
|
||||||
|
return template_folders.none if name.blank?
|
||||||
|
|
||||||
|
parent_name, name = name.to_s.split(' / ', 2).map(&:squish)
|
||||||
|
|
||||||
|
if name.present?
|
||||||
|
parent_folder = template_folders.where(parent_folder_id: nil).find_by(name: parent_name)
|
||||||
|
else
|
||||||
|
name = parent_name
|
||||||
|
end
|
||||||
|
|
||||||
|
template_folders.where(name:, parent_folder:)
|
||||||
|
end
|
||||||
|
|
||||||
def search(folders, keyword)
|
def search(folders, keyword)
|
||||||
return folders if keyword.blank?
|
return folders if keyword.blank?
|
||||||
|
|
||||||
folders.where(TemplateFolder.arel_table[:name].lower.matches("%#{keyword.downcase}%"))
|
folders.where(TemplateFolder.arel_table[:name].lower.matches("%#{keyword.downcase}%"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def filter_active_folders(template_folders, templates)
|
||||||
|
folder_exists =
|
||||||
|
templates.active.where(TemplateFolder.arel_table[:id].eq(Template.arel_table[:folder_id]))
|
||||||
|
.select(1).limit(1).arel.exists
|
||||||
|
|
||||||
|
subfolders_arel = TemplateFolder.arel_table.alias('subfolders')
|
||||||
|
|
||||||
|
subfolder_exists =
|
||||||
|
TemplateFolder.from(subfolders_arel)
|
||||||
|
.where(subfolders_arel[:parent_folder_id].eq(TemplateFolder.arel_table[:id]))
|
||||||
|
.where(
|
||||||
|
templates.active.where(Template.arel_table[:folder_id].eq(subfolders_arel[:id])).arel.exists
|
||||||
|
).select(1).limit(1).arel.exists
|
||||||
|
|
||||||
|
template_folders.where(folder_exists).or(template_folders.where(subfolder_exists))
|
||||||
|
end
|
||||||
|
|
||||||
|
def sort(template_folders, current_user, order)
|
||||||
|
case order
|
||||||
|
when 'used_at'
|
||||||
|
subquery =
|
||||||
|
Template.left_joins(:submissions)
|
||||||
|
.group(:folder_id)
|
||||||
|
.where(account_id: current_user.account_id)
|
||||||
|
.select(
|
||||||
|
:folder_id,
|
||||||
|
Template.arel_table[:updated_at].maximum.as('updated_at_max'),
|
||||||
|
Submission.arel_table[:created_at].maximum.as('submission_created_at_max')
|
||||||
|
)
|
||||||
|
|
||||||
|
template_folders = template_folders.joins(
|
||||||
|
Template.arel_table
|
||||||
|
.join(subquery.arel.as('templates'), Arel::Nodes::OuterJoin)
|
||||||
|
.on(TemplateFolder.arel_table[:id].eq(Template.arel_table[:folder_id]))
|
||||||
|
.join_sources
|
||||||
|
)
|
||||||
|
|
||||||
|
template_folders.order(
|
||||||
|
Arel::Nodes::Case.new
|
||||||
|
.when(Template.arel_table[:submission_created_at_max].gt(Template.arel_table[:updated_at_max]))
|
||||||
|
.then(Template.arel_table[:submission_created_at_max])
|
||||||
|
.else(Template.arel_table[:updated_at_max])
|
||||||
|
.desc
|
||||||
|
)
|
||||||
|
when 'name'
|
||||||
|
template_folders.order(name: :asc)
|
||||||
|
else
|
||||||
|
template_folders.order(id: :desc)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def find_or_create_by_name(author, name)
|
def find_or_create_by_name(author, name)
|
||||||
return author.account.default_template_folder if name.blank? || name == TemplateFolder::DEFAULT_NAME
|
return author.account.default_template_folder if name.blank? || name == TemplateFolder::DEFAULT_NAME
|
||||||
|
|
||||||
author.account.template_folders.create_with(author:, account: author.account).find_or_create_by(name:)
|
parent_name, name = name.to_s.split(' / ', 2).map(&:squish)
|
||||||
|
|
||||||
|
if name.present?
|
||||||
|
parent_folder = author.account.template_folders.create_with(author:)
|
||||||
|
.find_or_create_by(name: parent_name, parent_folder_id: nil)
|
||||||
|
else
|
||||||
|
name = parent_name
|
||||||
|
end
|
||||||
|
|
||||||
|
author.account.template_folders.create_with(author:).find_or_create_by(name:, parent_folder:)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -6,10 +6,12 @@
|
|||||||
"@babel/plugin-transform-runtime": "7.21.4",
|
"@babel/plugin-transform-runtime": "7.21.4",
|
||||||
"@babel/preset-env": "7.21.5",
|
"@babel/preset-env": "7.21.5",
|
||||||
"@babel/runtime": "7.21.5",
|
"@babel/runtime": "7.21.5",
|
||||||
|
"@codemirror/lang-html": "^6.4.9",
|
||||||
"@eid-easy/eideasy-widget": "^2.163.4",
|
"@eid-easy/eideasy-widget": "^2.163.4",
|
||||||
"@github/catalyst": "^2.0.0-beta",
|
"@github/catalyst": "^2.0.0-beta",
|
||||||
"@hotwired/turbo": "https://github.com/docusealco/turbo#main",
|
"@hotwired/turbo": "https://github.com/docusealco/turbo#main",
|
||||||
"@hotwired/turbo-rails": "^7.3.0",
|
"@hotwired/turbo-rails": "^7.3.0",
|
||||||
|
"@specious/htmlflow": "^1.1.0",
|
||||||
"@tabler/icons-vue": "^2.47.0",
|
"@tabler/icons-vue": "^2.47.0",
|
||||||
"autocompleter": "^9.1.0",
|
"autocompleter": "^9.1.0",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
@@ -17,6 +19,7 @@
|
|||||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||||
"babel-plugin-macros": "^3.1.0",
|
"babel-plugin-macros": "^3.1.0",
|
||||||
"canvas-confetti": "^1.6.0",
|
"canvas-confetti": "^1.6.0",
|
||||||
|
"codemirror": "^6.0.2",
|
||||||
"compression-webpack-plugin": "10.0.0",
|
"compression-webpack-plugin": "10.0.0",
|
||||||
"css-loader": "^6.7.3",
|
"css-loader": "^6.7.3",
|
||||||
"css-minimizer-webpack-plugin": "^5.0.0",
|
"css-minimizer-webpack-plugin": "^5.0.0",
|
||||||
|
|||||||
@@ -1030,6 +1030,112 @@
|
|||||||
"@babel/helper-string-parser" "^7.25.9"
|
"@babel/helper-string-parser" "^7.25.9"
|
||||||
"@babel/helper-validator-identifier" "^7.25.9"
|
"@babel/helper-validator-identifier" "^7.25.9"
|
||||||
|
|
||||||
|
"@codemirror/autocomplete@^6.0.0":
|
||||||
|
version "6.18.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.18.6.tgz#de26e864a1ec8192a1b241eb86addbb612964ddb"
|
||||||
|
integrity sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/language" "^6.0.0"
|
||||||
|
"@codemirror/state" "^6.0.0"
|
||||||
|
"@codemirror/view" "^6.17.0"
|
||||||
|
"@lezer/common" "^1.0.0"
|
||||||
|
|
||||||
|
"@codemirror/commands@^6.0.0":
|
||||||
|
version "6.8.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.8.1.tgz#639f5559d2f33f2582a2429c58cb0c1b925c7a30"
|
||||||
|
integrity sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/language" "^6.0.0"
|
||||||
|
"@codemirror/state" "^6.4.0"
|
||||||
|
"@codemirror/view" "^6.27.0"
|
||||||
|
"@lezer/common" "^1.1.0"
|
||||||
|
|
||||||
|
"@codemirror/lang-css@^6.0.0":
|
||||||
|
version "6.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@codemirror/lang-css/-/lang-css-6.3.1.tgz#763ca41aee81bb2431be55e3cfcc7cc8e91421a3"
|
||||||
|
integrity sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/autocomplete" "^6.0.0"
|
||||||
|
"@codemirror/language" "^6.0.0"
|
||||||
|
"@codemirror/state" "^6.0.0"
|
||||||
|
"@lezer/common" "^1.0.2"
|
||||||
|
"@lezer/css" "^1.1.7"
|
||||||
|
|
||||||
|
"@codemirror/lang-html@^6.4.9":
|
||||||
|
version "6.4.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/@codemirror/lang-html/-/lang-html-6.4.9.tgz#d586f2cc9c341391ae07d1d7c545990dfa069727"
|
||||||
|
integrity sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/autocomplete" "^6.0.0"
|
||||||
|
"@codemirror/lang-css" "^6.0.0"
|
||||||
|
"@codemirror/lang-javascript" "^6.0.0"
|
||||||
|
"@codemirror/language" "^6.4.0"
|
||||||
|
"@codemirror/state" "^6.0.0"
|
||||||
|
"@codemirror/view" "^6.17.0"
|
||||||
|
"@lezer/common" "^1.0.0"
|
||||||
|
"@lezer/css" "^1.1.0"
|
||||||
|
"@lezer/html" "^1.3.0"
|
||||||
|
|
||||||
|
"@codemirror/lang-javascript@^6.0.0":
|
||||||
|
version "6.2.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@codemirror/lang-javascript/-/lang-javascript-6.2.4.tgz#eef2227d1892aae762f3a0f212f72bec868a02c5"
|
||||||
|
integrity sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/autocomplete" "^6.0.0"
|
||||||
|
"@codemirror/language" "^6.6.0"
|
||||||
|
"@codemirror/lint" "^6.0.0"
|
||||||
|
"@codemirror/state" "^6.0.0"
|
||||||
|
"@codemirror/view" "^6.17.0"
|
||||||
|
"@lezer/common" "^1.0.0"
|
||||||
|
"@lezer/javascript" "^1.0.0"
|
||||||
|
|
||||||
|
"@codemirror/language@^6.0.0", "@codemirror/language@^6.4.0", "@codemirror/language@^6.6.0":
|
||||||
|
version "6.11.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.11.2.tgz#90d2d094cfbd14263bc5354ebd2445ee4e81bdc3"
|
||||||
|
integrity sha512-p44TsNArL4IVXDTbapUmEkAlvWs2CFQbcfc0ymDsis1kH2wh0gcY96AS29c/vp2d0y2Tquk1EDSaawpzilUiAw==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/state" "^6.0.0"
|
||||||
|
"@codemirror/view" "^6.23.0"
|
||||||
|
"@lezer/common" "^1.1.0"
|
||||||
|
"@lezer/highlight" "^1.0.0"
|
||||||
|
"@lezer/lr" "^1.0.0"
|
||||||
|
style-mod "^4.0.0"
|
||||||
|
|
||||||
|
"@codemirror/lint@^6.0.0":
|
||||||
|
version "6.8.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@codemirror/lint/-/lint-6.8.5.tgz#9edaa808e764e28e07665b015951934c8ec3a418"
|
||||||
|
integrity sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/state" "^6.0.0"
|
||||||
|
"@codemirror/view" "^6.35.0"
|
||||||
|
crelt "^1.0.5"
|
||||||
|
|
||||||
|
"@codemirror/search@^6.0.0":
|
||||||
|
version "6.5.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/@codemirror/search/-/search-6.5.11.tgz#a324ffee36e032b7f67aa31c4fb9f3e6f9f3ed63"
|
||||||
|
integrity sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/state" "^6.0.0"
|
||||||
|
"@codemirror/view" "^6.0.0"
|
||||||
|
crelt "^1.0.5"
|
||||||
|
|
||||||
|
"@codemirror/state@^6.0.0", "@codemirror/state@^6.4.0", "@codemirror/state@^6.5.0":
|
||||||
|
version "6.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.5.2.tgz#8eca3a64212a83367dc85475b7d78d5c9b7076c6"
|
||||||
|
integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==
|
||||||
|
dependencies:
|
||||||
|
"@marijn/find-cluster-break" "^1.0.0"
|
||||||
|
|
||||||
|
"@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0", "@codemirror/view@^6.27.0", "@codemirror/view@^6.35.0":
|
||||||
|
version "6.38.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.38.0.tgz#4486062b791a4247793e0953e05ae71a9e172217"
|
||||||
|
integrity sha512-yvSchUwHOdupXkd7xJ0ob36jdsSR/I+/C+VbY0ffBiL5NiSTEBDfB1ZGWbbIlDd5xgdUkody+lukAdOxYrOBeg==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/state" "^6.5.0"
|
||||||
|
crelt "^1.0.6"
|
||||||
|
style-mod "^4.1.0"
|
||||||
|
w3c-keyname "^2.2.4"
|
||||||
|
|
||||||
"@discoveryjs/json-ext@0.5.7", "@discoveryjs/json-ext@^0.5.0":
|
"@discoveryjs/json-ext@0.5.7", "@discoveryjs/json-ext@^0.5.0":
|
||||||
version "0.5.7"
|
version "0.5.7"
|
||||||
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
|
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
|
||||||
@@ -1237,6 +1343,57 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b"
|
resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b"
|
||||||
integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==
|
integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==
|
||||||
|
|
||||||
|
"@lezer/common@^1.0.0", "@lezer/common@^1.0.2", "@lezer/common@^1.1.0", "@lezer/common@^1.2.0":
|
||||||
|
version "1.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.2.3.tgz#138fcddab157d83da557554851017c6c1e5667fd"
|
||||||
|
integrity sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==
|
||||||
|
|
||||||
|
"@lezer/css@^1.1.0", "@lezer/css@^1.1.7":
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@lezer/css/-/css-1.3.0.tgz#296f298814782c2fad42a936f3510042cdcd2034"
|
||||||
|
integrity sha512-pBL7hup88KbI7hXnZV3PQsn43DHy6TWyzuyk2AO9UyoXcDltvIdqWKE1dLL/45JVZ+YZkHe1WVHqO6wugZZWcw==
|
||||||
|
dependencies:
|
||||||
|
"@lezer/common" "^1.2.0"
|
||||||
|
"@lezer/highlight" "^1.0.0"
|
||||||
|
"@lezer/lr" "^1.3.0"
|
||||||
|
|
||||||
|
"@lezer/highlight@^1.0.0", "@lezer/highlight@^1.1.3":
|
||||||
|
version "1.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@lezer/highlight/-/highlight-1.2.1.tgz#596fa8f9aeb58a608be0a563e960c373cbf23f8b"
|
||||||
|
integrity sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==
|
||||||
|
dependencies:
|
||||||
|
"@lezer/common" "^1.0.0"
|
||||||
|
|
||||||
|
"@lezer/html@^1.3.0":
|
||||||
|
version "1.3.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/@lezer/html/-/html-1.3.10.tgz#1be9a029a6fe835c823b20a98a449a630416b2af"
|
||||||
|
integrity sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==
|
||||||
|
dependencies:
|
||||||
|
"@lezer/common" "^1.2.0"
|
||||||
|
"@lezer/highlight" "^1.0.0"
|
||||||
|
"@lezer/lr" "^1.0.0"
|
||||||
|
|
||||||
|
"@lezer/javascript@^1.0.0":
|
||||||
|
version "1.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@lezer/javascript/-/javascript-1.5.1.tgz#2a424a6ec29f1d4ef3c34cbccc5447e373618ad8"
|
||||||
|
integrity sha512-ATOImjeVJuvgm3JQ/bpo2Tmv55HSScE2MTPnKRMRIPx2cLhHGyX2VnqpHhtIV1tVzIjZDbcWQm+NCTF40ggZVw==
|
||||||
|
dependencies:
|
||||||
|
"@lezer/common" "^1.2.0"
|
||||||
|
"@lezer/highlight" "^1.1.3"
|
||||||
|
"@lezer/lr" "^1.3.0"
|
||||||
|
|
||||||
|
"@lezer/lr@^1.0.0", "@lezer/lr@^1.3.0":
|
||||||
|
version "1.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@lezer/lr/-/lr-1.4.2.tgz#931ea3dea8e9de84e90781001dae30dea9ff1727"
|
||||||
|
integrity sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==
|
||||||
|
dependencies:
|
||||||
|
"@lezer/common" "^1.0.0"
|
||||||
|
|
||||||
|
"@marijn/find-cluster-break@^1.0.0":
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz#775374306116d51c0c500b8c4face0f9a04752d8"
|
||||||
|
integrity sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==
|
||||||
|
|
||||||
"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1":
|
"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1":
|
||||||
version "5.1.1-v1"
|
version "5.1.1-v1"
|
||||||
resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129"
|
resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129"
|
||||||
@@ -1280,6 +1437,13 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.24.tgz#8c7688559979f7079aacaf31aa881c3aa410b718"
|
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.24.tgz#8c7688559979f7079aacaf31aa881c3aa410b718"
|
||||||
integrity sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==
|
integrity sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==
|
||||||
|
|
||||||
|
"@specious/htmlflow@^1.1.0":
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@specious/htmlflow/-/htmlflow-1.1.0.tgz#cc8319c2cc6b5e2e309fa213d5a1f54cc093d9eb"
|
||||||
|
integrity sha512-g41FgN5kfuGkOrWhhmVvFes2BzQ3msU5oR/8KPdXbkBt8UIHtwL+by9maItDIhu+BR7pxshABtaB/FqpESa9Mg==
|
||||||
|
dependencies:
|
||||||
|
htmlparser2 "^8.0.1"
|
||||||
|
|
||||||
"@tabler/icons-vue@^2.47.0":
|
"@tabler/icons-vue@^2.47.0":
|
||||||
version "2.47.0"
|
version "2.47.0"
|
||||||
resolved "https://registry.yarnpkg.com/@tabler/icons-vue/-/icons-vue-2.47.0.tgz#604608a6df673d035c0e8e33f0565eeffa3adf36"
|
resolved "https://registry.yarnpkg.com/@tabler/icons-vue/-/icons-vue-2.47.0.tgz#604608a6df673d035c0e8e33f0565eeffa3adf36"
|
||||||
@@ -2172,6 +2336,19 @@ clone-deep@^4.0.1:
|
|||||||
kind-of "^6.0.2"
|
kind-of "^6.0.2"
|
||||||
shallow-clone "^3.0.0"
|
shallow-clone "^3.0.0"
|
||||||
|
|
||||||
|
codemirror@^6.0.2:
|
||||||
|
version "6.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-6.0.2.tgz#4d3fea1ad60b6753f97ca835f2f48c6936a8946e"
|
||||||
|
integrity sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/autocomplete" "^6.0.0"
|
||||||
|
"@codemirror/commands" "^6.0.0"
|
||||||
|
"@codemirror/language" "^6.0.0"
|
||||||
|
"@codemirror/lint" "^6.0.0"
|
||||||
|
"@codemirror/search" "^6.0.0"
|
||||||
|
"@codemirror/state" "^6.0.0"
|
||||||
|
"@codemirror/view" "^6.0.0"
|
||||||
|
|
||||||
color-convert@^1.9.0:
|
color-convert@^1.9.0:
|
||||||
version "1.9.3"
|
version "1.9.3"
|
||||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||||
@@ -2351,6 +2528,11 @@ cosmiconfig@^8.1.3:
|
|||||||
parse-json "^5.0.0"
|
parse-json "^5.0.0"
|
||||||
path-type "^4.0.0"
|
path-type "^4.0.0"
|
||||||
|
|
||||||
|
crelt@^1.0.5, crelt@^1.0.6:
|
||||||
|
version "1.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/crelt/-/crelt-1.0.6.tgz#7cc898ea74e190fb6ef9dae57f8f81cf7302df72"
|
||||||
|
integrity sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==
|
||||||
|
|
||||||
cross-spawn@^7.0.2, cross-spawn@^7.0.3:
|
cross-spawn@^7.0.2, cross-spawn@^7.0.3:
|
||||||
version "7.0.3"
|
version "7.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
|
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
|
||||||
@@ -2711,7 +2893,7 @@ enhanced-resolve@^5.17.1:
|
|||||||
graceful-fs "^4.2.4"
|
graceful-fs "^4.2.4"
|
||||||
tapable "^2.2.0"
|
tapable "^2.2.0"
|
||||||
|
|
||||||
entities@^4.2.0:
|
entities@^4.2.0, entities@^4.4.0:
|
||||||
version "4.5.0"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
|
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
|
||||||
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
|
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
|
||||||
@@ -3511,6 +3693,16 @@ html-entities@^2.3.2:
|
|||||||
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46"
|
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46"
|
||||||
integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==
|
integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==
|
||||||
|
|
||||||
|
htmlparser2@^8.0.1:
|
||||||
|
version "8.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21"
|
||||||
|
integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==
|
||||||
|
dependencies:
|
||||||
|
domelementtype "^2.3.0"
|
||||||
|
domhandler "^5.0.3"
|
||||||
|
domutils "^3.0.1"
|
||||||
|
entities "^4.4.0"
|
||||||
|
|
||||||
http-deceiver@^1.2.7:
|
http-deceiver@^1.2.7:
|
||||||
version "1.2.7"
|
version "1.2.7"
|
||||||
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
|
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
|
||||||
@@ -5438,6 +5630,11 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
|
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
|
||||||
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
||||||
|
|
||||||
|
style-mod@^4.0.0, style-mod@^4.1.0:
|
||||||
|
version "4.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.1.2.tgz#ca238a1ad4786520f7515a8539d5a63691d7bf67"
|
||||||
|
integrity sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==
|
||||||
|
|
||||||
stylehacks@^6.0.0:
|
stylehacks@^6.0.0:
|
||||||
version "6.0.0"
|
version "6.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-6.0.0.tgz#9fdd7c217660dae0f62e14d51c89f6c01b3cb738"
|
resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-6.0.0.tgz#9fdd7c217660dae0f62e14d51c89f6c01b3cb738"
|
||||||
@@ -5845,6 +6042,11 @@ vue@^3.3.2:
|
|||||||
"@vue/server-renderer" "3.3.4"
|
"@vue/server-renderer" "3.3.4"
|
||||||
"@vue/shared" "3.3.4"
|
"@vue/shared" "3.3.4"
|
||||||
|
|
||||||
|
w3c-keyname@^2.2.4:
|
||||||
|
version "2.2.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz#7b17c8c6883d4e8b86ac8aba79d39e880f8869c5"
|
||||||
|
integrity sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==
|
||||||
|
|
||||||
watchpack@^2.4.0, watchpack@^2.4.1:
|
watchpack@^2.4.0, watchpack@^2.4.1:
|
||||||
version "2.4.2"
|
version "2.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da"
|
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da"
|
||||||
|
|||||||
Reference in new issue
Block a user