mirror of
https://github.com/docusealco/docuseal
synced 2026-11-04 14:42:32 -05:00
Compare commits
16
Commits
11856a17ac
...
6e2430e5a2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e2430e5a2 | ||
|
|
85fbae1813 | ||
|
|
9941122d90 | ||
|
|
71be6db358 | ||
|
|
994c1b3155 | ||
|
|
92b297a620 | ||
|
|
bd03498b0f | ||
|
|
660b24710e | ||
|
|
1416cf72e8 | ||
|
|
ae7b0ce608 | ||
|
|
a3828ec390 | ||
|
|
b8c1691bd7 | ||
|
|
4b00c896e4 | ||
|
|
781da32a07 | ||
|
|
307036eae6 | ||
|
|
9944a9b1a5 |
No files matched your search
@@ -36,7 +36,7 @@ gem 'rotp'
|
|||||||
gem 'rouge', require: false
|
gem 'rouge', require: false
|
||||||
gem 'rqrcode', require: false
|
gem 'rqrcode', require: false
|
||||||
gem 'ruby-vips'
|
gem 'ruby-vips'
|
||||||
gem 'rubyXL', require: false
|
gem 'rubyzip', require: false
|
||||||
gem 'shakapacker'
|
gem 'shakapacker'
|
||||||
gem 'sidekiq'
|
gem 'sidekiq'
|
||||||
gem 'sqlite3', require: false
|
gem 'sqlite3', require: false
|
||||||
@@ -45,6 +45,7 @@ gem 'trilogy', require: false
|
|||||||
gem 'turbo-rails'
|
gem 'turbo-rails'
|
||||||
gem 'twitter_cldr', require: false
|
gem 'twitter_cldr', require: false
|
||||||
gem 'tzinfo-data'
|
gem 'tzinfo-data'
|
||||||
|
gem 'xlsxtream', require: false
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
gem 'better_html'
|
gem 'better_html'
|
||||||
|
|||||||
+5
-4
@@ -497,9 +497,6 @@ GEM
|
|||||||
ruby-vips (2.3.0)
|
ruby-vips (2.3.0)
|
||||||
ffi (~> 1.12)
|
ffi (~> 1.12)
|
||||||
logger
|
logger
|
||||||
rubyXL (3.4.35)
|
|
||||||
nokogiri (>= 1.10.8)
|
|
||||||
rubyzip (>= 3.2.2)
|
|
||||||
rubyzip (3.2.2)
|
rubyzip (3.2.2)
|
||||||
securerandom (0.4.1)
|
securerandom (0.4.1)
|
||||||
semantic_range (3.1.1)
|
semantic_range (3.1.1)
|
||||||
@@ -575,10 +572,13 @@ GEM
|
|||||||
base64
|
base64
|
||||||
websocket-extensions (>= 0.1.0)
|
websocket-extensions (>= 0.1.0)
|
||||||
websocket-extensions (0.1.5)
|
websocket-extensions (0.1.5)
|
||||||
|
xlsxtream (3.1.0)
|
||||||
|
zip_kit (>= 6.2, < 7)
|
||||||
xpath (3.2.0)
|
xpath (3.2.0)
|
||||||
nokogiri (~> 1.8)
|
nokogiri (~> 1.8)
|
||||||
yaml (0.4.0)
|
yaml (0.4.0)
|
||||||
zeitwerk (2.8.2)
|
zeitwerk (2.8.2)
|
||||||
|
zip_kit (6.3.4)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
aarch64-linux
|
aarch64-linux
|
||||||
@@ -638,7 +638,7 @@ DEPENDENCIES
|
|||||||
rubocop-rails
|
rubocop-rails
|
||||||
rubocop-rspec
|
rubocop-rspec
|
||||||
ruby-vips
|
ruby-vips
|
||||||
rubyXL
|
rubyzip
|
||||||
shakapacker
|
shakapacker
|
||||||
sidekiq
|
sidekiq
|
||||||
simplecov
|
simplecov
|
||||||
@@ -650,6 +650,7 @@ DEPENDENCIES
|
|||||||
tzinfo-data
|
tzinfo-data
|
||||||
web-console
|
web-console
|
||||||
webmock
|
webmock
|
||||||
|
xlsxtream
|
||||||
|
|
||||||
RUBY VERSION
|
RUBY VERSION
|
||||||
ruby 4.0.5
|
ruby 4.0.5
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ class SubmitFormDeclineController < ApplicationController
|
|||||||
|
|
||||||
user = @submitter.submission.created_by_user || @submitter.template.author
|
user = @submitter.submission.created_by_user || @submitter.template.author
|
||||||
|
|
||||||
if user.user_configs.find_by(key: UserConfig::RECEIVE_DECLINED_EMAIL)&.value != false
|
if Users.send_emails?(user) &&
|
||||||
|
user.user_configs.find_by(key: UserConfig::RECEIVE_DECLINED_EMAIL)&.value != false
|
||||||
SubmitterMailer.declined_email(@submitter, user).deliver_later!
|
SubmitterMailer.declined_email(@submitter, user).deliver_later!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ class SubmitFormDelegateController < ApplicationController
|
|||||||
SubmissionEvents.create_with_tracking_data(@submitter, 'delegate_form', request,
|
SubmissionEvents.create_with_tracking_data(@submitter, 'delegate_form', request,
|
||||||
{ old_email: @submitter.email, email: })
|
{ old_email: @submitter.email, email: })
|
||||||
|
|
||||||
@submitter.update!(email:, phone: nil, name: nil, slug: SecureRandom.base58(14))
|
@submitter.update!(email:, phone: nil, name: nil, slug: SecureRandom.base58(14),
|
||||||
|
values: Submitters.fetch_values_for_delegate(@submitter))
|
||||||
end
|
end
|
||||||
|
|
||||||
SendSubmitterInvitationEmailJob.perform_async('submitter_id' => @submitter.id)
|
SendSubmitterInvitationEmailJob.perform_async('submitter_id' => @submitter.id)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class SubmitFormInviteController < ApplicationController
|
|||||||
|
|
||||||
@submitter.submission.submitters.create!(uuid: attrs[:uuid], email:, account_id: @submitter.account_id)
|
@submitter.submission.submitters.create!(uuid: attrs[:uuid], email:, account_id: @submitter.account_id)
|
||||||
|
|
||||||
SubmissionEvents.create_with_tracking_data(@submitter, 'invite_party', request, { uuid: @submitter.uuid })
|
SubmissionEvents.create_with_tracking_data(@submitter, 'invite_party', request, { uuid: attrs[:uuid] })
|
||||||
end
|
end
|
||||||
|
|
||||||
@submitter.submission.update!(submitters_order: :preserved)
|
@submitter.submission.update!(submitters_order: :preserved)
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class TemplatesUploadsController < ApplicationController
|
|||||||
tempfile.write(DownloadUtils.call(params[:url], validate: true).body)
|
tempfile.write(DownloadUtils.call(params[:url], validate: true).body)
|
||||||
tempfile.rewind
|
tempfile.rewind
|
||||||
|
|
||||||
filename = URI.decode_www_form_component(params[:filename]) if params[:filename].present?
|
filename = URI.decode_www_form_component(params[:filename]).tr('/', '-') if params[:filename].present?
|
||||||
filename ||= File.basename(URI.decode_www_form_component(params[:url]))
|
filename ||= File.basename(URI.decode_www_form_component(params[:url]))
|
||||||
|
|
||||||
file = ActionDispatch::Http::UploadedFile.new(
|
file = ActionDispatch::Http::UploadedFile.new(
|
||||||
|
|||||||
@@ -3,11 +3,19 @@
|
|||||||
class WebhookSecretController < ApplicationController
|
class WebhookSecretController < ApplicationController
|
||||||
load_and_authorize_resource :webhook_url, parent: false
|
load_and_authorize_resource :webhook_url, parent: false
|
||||||
|
|
||||||
|
HEADER_NAME_REGEXP = /\A[\w-]+\z/
|
||||||
|
|
||||||
def show; end
|
def show; end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
key = webhook_secret_params[:key]
|
||||||
|
|
||||||
|
if key.present? && !HEADER_NAME_REGEXP.match?(key)
|
||||||
|
return redirect_back(fallback_location: settings_webhook_path(@webhook_url), alert: I18n.t('unable_to_save'))
|
||||||
|
end
|
||||||
|
|
||||||
@webhook_url.update!(secret: {
|
@webhook_url.update!(secret: {
|
||||||
webhook_secret_params[:key] => webhook_secret_params[:value]
|
key => webhook_secret_params[:value]
|
||||||
}.compact_blank)
|
}.compact_blank)
|
||||||
|
|
||||||
redirect_back(fallback_location: settings_webhook_path(@webhook_url),
|
redirect_back(fallback_location: settings_webhook_path(@webhook_url),
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
resendCode () {
|
resendCode () {
|
||||||
if (this.codeSentAt && Date.now() - this.codeSentAt < 15000) {
|
if (this.codeSentAt && Date.now() - this.codeSentAt < 30000) {
|
||||||
this.startResendCodeCountdown()
|
this.startResendCodeCountdown()
|
||||||
} else {
|
} else {
|
||||||
this.isResendLoading = true
|
this.isResendLoading = true
|
||||||
@@ -274,7 +274,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
startResendCodeCountdown () {
|
startResendCodeCountdown () {
|
||||||
this.resendCodeCountdown = 15 - parseInt((Date.now() - this.codeSentAt) / 1000)
|
this.resendCodeCountdown = 30 - parseInt((Date.now() - this.codeSentAt) / 1000)
|
||||||
|
|
||||||
this.interval = setInterval(() => {
|
this.interval = setInterval(() => {
|
||||||
this.resendCodeCountdown--
|
this.resendCodeCountdown--
|
||||||
|
|||||||
@@ -2371,7 +2371,6 @@ export default {
|
|||||||
const areaCopy = JSON.parse(JSON.stringify(area))
|
const areaCopy = JSON.parse(JSON.stringify(area))
|
||||||
|
|
||||||
delete fieldCopy.areas
|
delete fieldCopy.areas
|
||||||
delete fieldCopy.submitter_uuid
|
|
||||||
|
|
||||||
areaCopy.relativeX = area.x - minX
|
areaCopy.relativeX = area.x - minX
|
||||||
areaCopy.relativeY = area.y - minY
|
areaCopy.relativeY = area.y - minY
|
||||||
@@ -2381,6 +2380,7 @@ export default {
|
|||||||
|
|
||||||
const clipboardData = {
|
const clipboardData = {
|
||||||
items,
|
items,
|
||||||
|
submitters: this.template.submitters.map((submitter) => ({ uuid: submitter.uuid, name: submitter.name })),
|
||||||
templateId: this.template.id,
|
templateId: this.template.id,
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
isGroup: true
|
isGroup: true
|
||||||
@@ -2491,6 +2491,20 @@ export default {
|
|||||||
|
|
||||||
const fieldUuidIndex = {}
|
const fieldUuidIndex = {}
|
||||||
const fieldOptionsMap = {}
|
const fieldOptionsMap = {}
|
||||||
|
const submitterUuidsMap = {}
|
||||||
|
|
||||||
|
const copiedSubmitterUuids = [...new Set(data.items.map((item) => item.field.submitter_uuid).filter(Boolean))]
|
||||||
|
|
||||||
|
if (copiedSubmitterUuids.length > 1) {
|
||||||
|
copiedSubmitterUuids.forEach((uuid) => {
|
||||||
|
const name = data.submitters?.find((submitter) => submitter.uuid === uuid)?.name
|
||||||
|
|
||||||
|
const submitter = this.template.submitters.find((s) => s.uuid === uuid) ||
|
||||||
|
(name && this.template.submitters.find((s) => s.name.toLowerCase() === name.toLowerCase()))
|
||||||
|
|
||||||
|
submitterUuidsMap[uuid] = (submitter || this.selectedSubmitter).uuid
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
data.items.forEach((item) => {
|
data.items.forEach((item) => {
|
||||||
const field = JSON.parse(JSON.stringify(item.field))
|
const field = JSON.parse(JSON.stringify(item.field))
|
||||||
@@ -2515,7 +2529,7 @@ export default {
|
|||||||
const newField = fieldUuidIndex[field.uuid] || {
|
const newField = fieldUuidIndex[field.uuid] || {
|
||||||
...field,
|
...field,
|
||||||
uuid: v4(),
|
uuid: v4(),
|
||||||
submitter_uuid: this.selectedSubmitter.uuid,
|
submitter_uuid: submitterUuidsMap[field.submitter_uuid] || this.selectedSubmitter.uuid,
|
||||||
areas: []
|
areas: []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ class ProcessSubmitterCompletionJob
|
|||||||
user_submitter = submission.submitters.find { |s| s.email == user.email }
|
user_submitter = submission.submitters.find { |s| s.email == user.email }
|
||||||
|
|
||||||
is_sent_to_user =
|
is_sent_to_user =
|
||||||
if user.role != 'integration' &&
|
if user.role != 'integration' && Users.send_emails?(user) &&
|
||||||
(!user_submitter || user_submitter.preferences['send_email'] == false || !is_copy_email_enabled) &&
|
(!user_submitter || user_submitter.preferences['send_email'] == false || !is_copy_email_enabled) &&
|
||||||
user.user_configs.find_by(key: UserConfig::RECEIVE_COMPLETED_EMAIL)&.value != false
|
user.user_configs.find_by(key: UserConfig::RECEIVE_COMPLETED_EMAIL)&.value != false
|
||||||
SubmitterMailer.completed_email(submitter, user).deliver_later!
|
SubmitterMailer.completed_email(submitter, user).deliver_later!
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ class Submitter < ApplicationRecord
|
|||||||
|
|
||||||
def friendly_name
|
def friendly_name
|
||||||
if name.present? && email.present? && email.exclude?(',')
|
if name.present? && email.present? && email.exclude?(',')
|
||||||
%("#{name.delete('"')}" <#{email}>)
|
%("#{name.delete('"').squish}" <#{email}>)
|
||||||
else
|
else
|
||||||
email
|
email
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse-content">
|
<div class="collapse-content">
|
||||||
<%= form_for AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::SUBMITTER_DOCUMENTS_COPY_EMAIL_KEY), url: settings_personalization_path, method: :post, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
<%= form_for AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::SUBMITTER_DOCUMENTS_COPY_EMAIL_KEY), url: settings_personalization_path, method: :post, html: { autocomplete: 'off', class: 'flex flex-col gap-4' } do |f| %>
|
||||||
<%= f.hidden_field :key %>
|
<%= f.hidden_field :key %>
|
||||||
<%= f.fields_for :value, Struct.new(:subject, :body, :reply_to, :attach_audit_log, :attach_documents, :bcc_recipients, :enabled).new(*f.object.value.values_at('subject', 'body', 'reply_to', 'attach_audit_log', 'attach_documents', 'bcc_recipients', 'enabled')) do |ff| %>
|
<%= f.fields_for :value, Struct.new(:subject, :body, :reply_to, :attach_audit_log, :attach_documents, :bcc_recipients, :enabled).new(*f.object.value.values_at('subject', 'body', 'reply_to', 'attach_audit_log', 'attach_documents', 'bcc_recipients', 'enabled')) do |ff| %>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse-content">
|
<div class="collapse-content">
|
||||||
<%= form_for AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::FORM_COMPLETED_BUTTON_KEY), url: settings_personalization_path, method: :post, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
<%= form_for AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::FORM_COMPLETED_BUTTON_KEY), url: settings_personalization_path, method: :post, html: { autocomplete: 'off', class: 'flex flex-col gap-4' } do |f| %>
|
||||||
<%= f.hidden_field :key %>
|
<%= f.hidden_field :key %>
|
||||||
<%= f.fields_for :value, Struct.new(:title, :url).new(*(f.object.value || {}).values_at('title', 'url')) do |ff| %>
|
<%= f.fields_for :value, Struct.new(:title, :url).new(*(f.object.value || {}).values_at('title', 'url')) do |ff| %>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse-content">
|
<div class="collapse-content">
|
||||||
<%= form_for AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::FORM_COMPLETED_MESSAGE_KEY), url: settings_personalization_path, method: :post, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
<%= form_for AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::FORM_COMPLETED_MESSAGE_KEY), url: settings_personalization_path, method: :post, html: { autocomplete: 'off', class: 'flex flex-col gap-4' } do |f| %>
|
||||||
<%= f.hidden_field :key %>
|
<%= f.hidden_field :key %>
|
||||||
<%= f.fields_for :value, Struct.new(:title, :body).new(*(f.object.value || {}).values_at('title', 'body')) do |ff| %>
|
<%= f.fields_for :value, Struct.new(:title, :body).new(*(f.object.value || {}).values_at('title', 'body')) do |ff| %>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse-content">
|
<div class="collapse-content">
|
||||||
<%= form_for AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::POLICY_LINKS_KEY), url: settings_personalization_path, method: :post, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
<%= form_for AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::POLICY_LINKS_KEY), url: settings_personalization_path, method: :post, html: { autocomplete: 'off', class: 'flex flex-col gap-4' } do |f| %>
|
||||||
<%= f.hidden_field :key %>
|
<%= f.hidden_field :key %>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<autoresize-textarea>
|
<autoresize-textarea>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse-content">
|
<div class="collapse-content">
|
||||||
<%= form_for AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::SUBMITTER_INVITATION_EMAIL_KEY), url: settings_personalization_path, method: :post, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
<%= form_for AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::SUBMITTER_INVITATION_EMAIL_KEY), url: settings_personalization_path, method: :post, html: { autocomplete: 'off', class: 'flex flex-col gap-4' } do |f| %>
|
||||||
<%= f.hidden_field :key %>
|
<%= f.hidden_field :key %>
|
||||||
<%= f.fields_for :value, Struct.new(:subject, :body, :reply_to).new(*f.object.value.values_at('subject', 'body', 'reply_to')) do |ff| %>
|
<%= f.fields_for :value, Struct.new(:subject, :body, :reply_to).new(*f.object.value.values_at('subject', 'body', 'reply_to')) do |ff| %>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse-content">
|
<div class="collapse-content">
|
||||||
<%= form_for AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::SUBMITTER_COMPLETED_EMAIL_KEY), url: settings_personalization_path, method: :post, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
<%= form_for AccountConfigs.find_or_initialize_for_key(current_account, AccountConfig::SUBMITTER_COMPLETED_EMAIL_KEY), url: settings_personalization_path, method: :post, html: { autocomplete: 'off', class: 'flex flex-col gap-4' } do |f| %>
|
||||||
<%= f.hidden_field :key %>
|
<%= f.hidden_field :key %>
|
||||||
<%= f.fields_for :value, Struct.new(:subject, :body, :attach_audit_log, :attach_documents).new(*f.object.value.values_at('subject', 'body', 'attach_audit_log', 'attach_documents')) do |ff| %>
|
<%= f.fields_for :value, Struct.new(:subject, :body, :attach_audit_log, :attach_documents).new(*f.object.value.values_at('subject', 'body', 'attach_audit_log', 'attach_documents')) do |ff| %>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% view_archived_html = capture do %>
|
<% view_archived_html = capture do %>
|
||||||
<% if can?(:manage, :countless) || current_account.submissions.where.not(archived_at: nil).exists? %>
|
<% if can?(:manage, :countless) || current_account.submissions.archived.exists? || current_account.templates.where(Submission.where(Submission.arel_table[:template_id].eq(::Template.arel_table[:id])).arel.exists).archived.exists? %>
|
||||||
<div>
|
<div>
|
||||||
<a href="<%= submissions_archived_index_path %>" class="link text-sm"><%= t('view_archived') %></a>
|
<a href="<%= submissions_archived_index_path %>" class="link text-sm"><%= t('view_archived') %></a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<% has_archived = can?(:manage, :countless) || current_account.templates.where.not(archived_at: nil).exists? %>
|
<% has_archived = can?(:manage, :countless) || current_account.templates.archived.exists? %>
|
||||||
<% show_dropzone = params[:q].blank? && @pagy.pages == 1 && ((@template_folders.size < 10 && @templates.size.zero?) || (@template_folders.size < 7 && @templates.size < 4) || (@template_folders.size < 4 && @templates.size < 7)) %>
|
<% show_dropzone = params[:q].blank? && @pagy.pages == 1 && ((@template_folders.size < 10 && @templates.size.zero?) || (@template_folders.size < 7 && @templates.size < 4) || (@template_folders.size < 4 && @templates.size < 7)) %>
|
||||||
<% if Docuseal.demo? %><%= render 'shared/demo_alert' %><% end %>
|
<% if Docuseal.demo? %><%= render 'shared/demo_alert' %><% end %>
|
||||||
<dashboard-dropzone>
|
<dashboard-dropzone>
|
||||||
|
|||||||
@@ -83,7 +83,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<% if @webhook_events.present? || params[:status].present? %>
|
<% if @webhook_events.present? || params[:status].present? %>
|
||||||
<div class="mt-6">
|
<div class="mt-6">
|
||||||
<h2 id="log" class="text-2xl md:text-3xl font-bold"><%= t('events_log') %></h2>
|
<h2 id="log" class="text-2xl md:text-3xl font-bold"><%= t('event_log') %></h2>
|
||||||
<div class="tabs border-b mt-4">
|
<div class="tabs border-b mt-4">
|
||||||
<%= link_to t('all'), url_for(params: request.query_parameters.except('status', 'page')), style: 'margin-bottom: -1px', class: "tab h-10 text-base #{params[:status].blank? ? 'tab-active tab-bordered' : 'pb-[3px]'}" %>
|
<%= link_to t('all'), url_for(params: request.query_parameters.except('status', 'page')), style: 'margin-bottom: -1px', class: "tab h-10 text-base #{params[:status].blank? ? 'tab-active tab-bordered' : 'pb-[3px]'}" %>
|
||||||
<%= link_to t('succeeded'), url_for(params: request.query_parameters.except('page').merge('status' => 'success')), style: 'margin-bottom: -1px', class: "tab h-10 text-base #{params[:status] == 'success' ? 'tab-active tab-bordered' : 'pb-[3px]'}" %>
|
<%= link_to t('succeeded'), url_for(params: request.query_parameters.except('page').merge('status' => 'success')), style: 'margin-bottom: -1px', class: "tab h-10 text-base #{params[:status] == 'success' ? 'tab-active tab-bordered' : 'pb-[3px]'}" %>
|
||||||
|
|||||||
+1
-1
@@ -105,6 +105,6 @@ if ENV['REDIS_URL'].to_s.empty?
|
|||||||
|
|
||||||
redis_password = Digest::SHA1.hexdigest("redis#{ENV.fetch('SECRET_KEY_BASE', '')}")
|
redis_password = Digest::SHA1.hexdigest("redis#{ENV.fetch('SECRET_KEY_BASE', '')}")
|
||||||
|
|
||||||
ENV['REDIS_URL'] = "redis://default:#{redis_password}@0.0.0.0:6379/0"
|
ENV['REDIS_URL'] = "redis://default:#{redis_password}@127.0.0.1:16379/0"
|
||||||
ENV['LOCAL_REDIS_URL'] = ENV.fetch('REDIS_URL', nil)
|
ENV['LOCAL_REDIS_URL'] = ENV.fetch('REDIS_URL', nil)
|
||||||
end
|
end
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
autoload :CSV, 'csv'
|
autoload :CSV, 'csv'
|
||||||
autoload :CSVSafe, 'csv-safe'
|
autoload :CSVSafe, 'csv-safe'
|
||||||
autoload :RubyXL, 'rubyXL'
|
autoload :Xlsxtream, 'xlsxtream'
|
||||||
autoload :Zip, 'zip'
|
autoload :Zip, 'zip'
|
||||||
autoload :Numo, 'numo/narray'
|
autoload :Numo, 'numo/narray'
|
||||||
autoload :OnnxRuntime, 'onnxruntime'
|
autoload :OnnxRuntime, 'onnxruntime'
|
||||||
|
|||||||
@@ -8034,7 +8034,7 @@ nl: &nl
|
|||||||
awaiting: Wachten
|
awaiting: Wachten
|
||||||
document_id: Document-ID
|
document_id: Document-ID
|
||||||
envelope_id: Envelop-ID
|
envelope_id: Envelop-ID
|
||||||
event_log: Gebeurtenissenlogboek
|
event_log: Gebeurtenislogboek
|
||||||
verify: Verifiëren
|
verify: Verifiëren
|
||||||
testing_log_not_for_production_use: Testlogboek - Niet voor productiegebruik
|
testing_log_not_for_production_use: Testlogboek - Niet voor productiegebruik
|
||||||
original_sha256: Oorspronkelijke SHA256
|
original_sha256: Oorspronkelijke SHA256
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ Puma::Plugin.create do
|
|||||||
Dir.chdir(ENV.fetch('WORKDIR', nil)) unless ENV['WORKDIR'].to_s.empty?
|
Dir.chdir(ENV.fetch('WORKDIR', nil)) unless ENV['WORKDIR'].to_s.empty?
|
||||||
|
|
||||||
exec('redis-server', '--requirepass', Digest::SHA1.hexdigest("redis#{ENV.fetch('SECRET_KEY_BASE', '')}"),
|
exec('redis-server', '--requirepass', Digest::SHA1.hexdigest("redis#{ENV.fetch('SECRET_KEY_BASE', '')}"),
|
||||||
|
'--bind', '127.0.0.1', '--port', '16379',
|
||||||
'--loglevel', 'warning')
|
'--loglevel', 'warning')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ module Submissions
|
|||||||
ActiveStorage::Attachment.create!(
|
ActiveStorage::Attachment.create!(
|
||||||
blob: ActiveStorage::Blob.create_and_upload!(
|
blob: ActiveStorage::Blob.create_and_upload!(
|
||||||
io: io.tap(&:rewind), filename: "#{I18n.t('audit_log')} - " \
|
io: io.tap(&:rewind), filename: "#{I18n.t('audit_log')} - " \
|
||||||
"#{submission.name || submission.template&.name}.pdf"
|
"#{submission.name || submission.template&.name}.pdf".tr('/', '-')
|
||||||
),
|
),
|
||||||
name: 'audit_trail',
|
name: 'audit_trail',
|
||||||
record: submission
|
record: submission
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ module Submissions
|
|||||||
|
|
||||||
ActiveStorage::Attachment.create!(
|
ActiveStorage::Attachment.create!(
|
||||||
blob: ActiveStorage::Blob.create_and_upload!(
|
blob: ActiveStorage::Blob.create_and_upload!(
|
||||||
io: io.tap(&:rewind), filename: "#{submission.name || submission.template&.name}.pdf"
|
io: io.tap(&:rewind), filename: "#{submission.name || submission.template&.name}.pdf".tr('/', '-')
|
||||||
),
|
),
|
||||||
name: with_audit ? 'combined_document' : 'merged_document',
|
name: with_audit ? 'combined_document' : 'merged_document',
|
||||||
record: submission
|
record: submission
|
||||||
|
|||||||
@@ -19,22 +19,19 @@ module Submissions
|
|||||||
end
|
end
|
||||||
|
|
||||||
def rows_to_xlsx(rows)
|
def rows_to_xlsx(rows)
|
||||||
workbook = RubyXL::Workbook.new
|
|
||||||
worksheet = workbook[0]
|
|
||||||
worksheet.sheet_name = Time.current.to_date.to_s
|
|
||||||
|
|
||||||
headers = build_headers(rows)
|
headers = build_headers(rows)
|
||||||
headers.each_with_index do |column_name, column_index|
|
|
||||||
worksheet.add_cell(0, column_index, column_name)
|
|
||||||
end
|
|
||||||
|
|
||||||
rows.each.with_index(1) do |row, row_index|
|
io = StringIO.new
|
||||||
extract_columns(row, headers).each_with_index do |value, column_index|
|
|
||||||
worksheet.add_cell(row_index, column_index, value)
|
Xlsxtream::Workbook.open(io) do |workbook|
|
||||||
|
workbook.write_worksheet(Time.current.to_date.to_s) do |sheet|
|
||||||
|
sheet << headers.to_a
|
||||||
|
|
||||||
|
rows.each { |row| sheet << extract_columns(row, headers) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
workbook.stream.string
|
io.string
|
||||||
end
|
end
|
||||||
|
|
||||||
def rows_to_csv(rows)
|
def rows_to_csv(rows)
|
||||||
@@ -150,8 +147,6 @@ module Submissions
|
|||||||
|
|
||||||
ActiveStorage::Blob.proxy_url(attachment.blob, expires_at:) if attachment
|
ActiveStorage::Blob.proxy_url(attachment.blob, expires_at:) if attachment
|
||||||
end
|
end
|
||||||
elsif submitter_value == true || submitter_value == false
|
|
||||||
submitter_value.to_s
|
|
||||||
else
|
else
|
||||||
submitter_value
|
submitter_value
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ module Submissions
|
|||||||
submission:,
|
submission:,
|
||||||
values_hash:,
|
values_hash:,
|
||||||
name: 'preview_merged_document',
|
name: 'preview_merged_document',
|
||||||
filename: "#{submission.name || template&.name}.pdf"
|
filename: "#{submission.name || template&.name}.pdf".tr('/', '-')
|
||||||
)
|
)
|
||||||
|
|
||||||
ApplicationRecord.no_touching { attachment.save! }
|
ApplicationRecord.no_touching { attachment.save! }
|
||||||
@@ -115,7 +115,7 @@ module Submissions
|
|||||||
submitter:,
|
submitter:,
|
||||||
uuid: GenerateResultAttachments.images_pdf_uuid(original_documents.select(&:image?)),
|
uuid: GenerateResultAttachments.images_pdf_uuid(original_documents.select(&:image?)),
|
||||||
values_hash:,
|
values_hash:,
|
||||||
filename: "#{submission.name || template&.name}.pdf"
|
filename: "#{submission.name || template&.name}.pdf".tr('/', '-')
|
||||||
)
|
)
|
||||||
|
|
||||||
ApplicationRecord.no_touching do
|
ApplicationRecord.no_touching do
|
||||||
|
|||||||
@@ -814,7 +814,7 @@ module Submissions
|
|||||||
end
|
end
|
||||||
|
|
||||||
ActiveStorage::Attachment.new(
|
ActiveStorage::Attachment.new(
|
||||||
blob: ActiveStorage::Blob.create_and_upload!(io: io.tap(&:rewind), filename: "#{name}.pdf"),
|
blob: ActiveStorage::Blob.create_and_upload!(io: io.tap(&:rewind), filename: "#{name}.pdf".tr('/', '-')),
|
||||||
metadata: { original_uuid: uuid,
|
metadata: { original_uuid: uuid,
|
||||||
analyzed: true,
|
analyzed: true,
|
||||||
sha256: Base64.urlsafe_encode64(Digest::SHA256.digest(io.string)) },
|
sha256: Base64.urlsafe_encode64(Digest::SHA256.digest(io.string)) },
|
||||||
|
|||||||
+16
-1
@@ -165,6 +165,21 @@ module Submitters
|
|||||||
preferences
|
preferences
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def fetch_values_for_delegate(submitter)
|
||||||
|
fields = submitter.submission.template_fields || submitter.template.fields
|
||||||
|
default_values = submitter.preferences['default_values'] || {}
|
||||||
|
|
||||||
|
field_uuids = fields.filter_map do |field|
|
||||||
|
next if field['submitter_uuid'] != submitter.uuid
|
||||||
|
next unless field['type'].in?(%w[signature phone verification kba initials])
|
||||||
|
next if default_values[field['uuid']].present?
|
||||||
|
|
||||||
|
field['uuid']
|
||||||
|
end
|
||||||
|
|
||||||
|
submitter.values.except(*field_uuids)
|
||||||
|
end
|
||||||
|
|
||||||
def send_signature_requests(submitters, delay_seconds: nil)
|
def send_signature_requests(submitters, delay_seconds: nil)
|
||||||
submitters.each_with_index do |submitter, index|
|
submitters.each_with_index do |submitter, index|
|
||||||
next if submitter.email.blank?
|
next if submitter.email.blank?
|
||||||
@@ -238,7 +253,7 @@ module Submitters
|
|||||||
I18n.l(completed_at.in_time_zone(submitter.account.timezone), format: :short)
|
I18n.l(completed_at.in_time_zone(submitter.account.timezone), format: :short)
|
||||||
end
|
end
|
||||||
|
|
||||||
"#{filename}.#{blob.filename.extension}"
|
"#{filename}.#{blob.filename.extension}".tr('/', '-')
|
||||||
end
|
end
|
||||||
|
|
||||||
def send_shared_link_email_verification_code(submitter, request:)
|
def send_shared_link_email_verification_code(submitter, request:)
|
||||||
|
|||||||
@@ -490,7 +490,7 @@ module Submitters
|
|||||||
|
|
||||||
submission.submitters.create!(uuid: s['uuid'], email:, phone:, account_id: submitter.account_id)
|
submission.submitters.create!(uuid: s['uuid'], email:, phone:, account_id: submitter.account_id)
|
||||||
|
|
||||||
SubmissionEvents.create_with_tracking_data(submitter, 'invite_party', request, { uuid: submitter.uuid })
|
SubmissionEvents.create_with_tracking_data(submitter, 'invite_party', request, { uuid: s['uuid'] })
|
||||||
|
|
||||||
is_invited = true
|
is_invited = true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ module Templates
|
|||||||
|
|
||||||
blob = ActiveStorage::Blob.create_and_upload!(
|
blob = ActiveStorage::Blob.create_and_upload!(
|
||||||
io: StringIO.new(document_data),
|
io: StringIO.new(document_data),
|
||||||
filename: file.original_filename,
|
filename: file.original_filename.tr('/', '-'),
|
||||||
metadata: {
|
metadata: {
|
||||||
**metadata,
|
**metadata,
|
||||||
identified: file.content_type == PDF_CONTENT_TYPE,
|
identified: file.content_type == PDF_CONTENT_TYPE,
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
module Users
|
module Users
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
|
def send_emails?(user)
|
||||||
|
!user.archived_at?
|
||||||
|
end
|
||||||
|
|
||||||
def generate_csv(users)
|
def generate_csv(users)
|
||||||
headers = %w[email first_name last_name role current_sign_in_at last_sign_in_at updated_at created_at]
|
headers = %w[email first_name last_name role current_sign_in_at last_sign_in_at updated_at created_at]
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user