Merge from docusealco/wip
This commit is contained in:
@@ -7,7 +7,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-24.04-arm
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
|
|||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
FROM ruby:3.4.1-alpine as fonts
|
FROM ruby:3.4.1-alpine AS fonts
|
||||||
|
|
||||||
WORKDIR /fonts
|
WORKDIR /fonts
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@ RUN apk --no-cache add fontforge wget && wget https://github.com/satbyy/go-noto-
|
|||||||
|
|
||||||
RUN fontforge -lang=py -c 'font1 = fontforge.open("FreeSans.ttf"); font2 = fontforge.open("NotoSansSymbols2-Regular.ttf"); font1.mergeFonts(font2); font1.generate("FreeSans.ttf")'
|
RUN fontforge -lang=py -c 'font1 = fontforge.open("FreeSans.ttf"); font2 = fontforge.open("NotoSansSymbols2-Regular.ttf"); font1.mergeFonts(font2); font1.generate("FreeSans.ttf")'
|
||||||
|
|
||||||
FROM ruby:3.4.1-alpine as webpack
|
FROM ruby:3.4.1-alpine AS webpack
|
||||||
|
|
||||||
ENV RAILS_ENV=production
|
ENV RAILS_ENV=production
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
@@ -32,7 +32,7 @@ COPY ./app/views ./app/views
|
|||||||
|
|
||||||
RUN echo "gem 'shakapacker'" > Gemfile && ./bin/shakapacker
|
RUN echo "gem 'shakapacker'" > Gemfile && ./bin/shakapacker
|
||||||
|
|
||||||
FROM ruby:3.4.1-alpine as app
|
FROM ruby:3.4.1-alpine AS app
|
||||||
|
|
||||||
ENV RAILS_ENV=production
|
ENV RAILS_ENV=production
|
||||||
ENV BUNDLE_WITHOUT="development:test"
|
ENV BUNDLE_WITHOUT="development:test"
|
||||||
|
|||||||
+6
-6
@@ -337,18 +337,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.2)
|
nokogiri (1.18.3)
|
||||||
mini_portile2 (~> 2.8.2)
|
mini_portile2 (~> 2.8.2)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.18.2-aarch64-linux-gnu)
|
nokogiri (1.18.3-aarch64-linux-gnu)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.18.2-aarch64-linux-musl)
|
nokogiri (1.18.3-aarch64-linux-musl)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.18.2-arm64-darwin)
|
nokogiri (1.18.3-arm64-darwin)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.18.2-x86_64-linux-gnu)
|
nokogiri (1.18.3-x86_64-linux-gnu)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.18.2-x86_64-linux-musl)
|
nokogiri (1.18.3-x86_64-linux-musl)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
oj (3.16.8)
|
oj (3.16.8)
|
||||||
bigdecimal (>= 3.0)
|
bigdecimal (>= 3.0)
|
||||||
|
|||||||
@@ -146,9 +146,15 @@ module Api
|
|||||||
|
|
||||||
if attrs[:completed]
|
if attrs[:completed]
|
||||||
submitter.values = Submitters::SubmitValues.merge_default_values(submitter)
|
submitter.values = Submitters::SubmitValues.merge_default_values(submitter)
|
||||||
submitter.values = Submitters::SubmitValues.merge_formula_values(submitter)
|
|
||||||
submitter.values = Submitters::SubmitValues.maybe_remove_condition_values(submitter)
|
submitter.values = Submitters::SubmitValues.maybe_remove_condition_values(submitter)
|
||||||
|
|
||||||
|
formula_values = Submitters::SubmitValues.build_formula_values(submitter)
|
||||||
|
|
||||||
|
if formula_values.present?
|
||||||
|
submitter.values = submitter.values.merge(formula_values)
|
||||||
|
submitter.values = Submitters::SubmitValues.maybe_remove_condition_values(submitter)
|
||||||
|
end
|
||||||
|
|
||||||
submitter.values = submitter.values.transform_values do |v|
|
submitter.values = submitter.values.transform_values do |v|
|
||||||
v == '{{date}}' ? Time.current.in_time_zone(submitter.account.timezone).to_date.to_s : v
|
v == '{{date}}' ? Time.current.in_time_zone(submitter.account.timezone).to_date.to_s : v
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1037,7 +1037,7 @@ export default {
|
|||||||
}, [])
|
}, [])
|
||||||
},
|
},
|
||||||
formulaFields () {
|
formulaFields () {
|
||||||
return this.fields.filter((f) => f.preferences?.formula && f.type !== 'payment')
|
return this.fields.filter((f) => f.preferences?.formula && f.type !== 'payment' && this.checkFieldConditions(f) && this.checkFieldDocumentsConditions(f))
|
||||||
},
|
},
|
||||||
attachmentsIndex () {
|
attachmentsIndex () {
|
||||||
return this.attachments.reduce((acc, a) => {
|
return this.attachments.reduce((acc, a) => {
|
||||||
|
|||||||
@@ -285,12 +285,12 @@
|
|||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= ff.text_field :name, class: 'w-full outline-none border-transparent focus:border-transparent focus:ring-0 bg-base-100 px-1 peer mb-2', autocomplete: 'off', placeholder: "#{index + 1}#{(index + 1).ordinal} Party", required: true %>
|
<%= ff.text_field :name, class: 'w-full outline-none border-transparent focus:border-transparent focus:ring-0 bg-base-100 px-1 peer mb-2', autocomplete: 'off', placeholder: "#{index + 1}#{(index + 1).ordinal} Party", required: true %>
|
||||||
<% if @template.submitters.size == 2 %>
|
<% if @template.submitters.size == 2 %>
|
||||||
<%= ff.email_field :email, class: 'base-input', autocomplete: 'off', placeholder: t('default_email'), disabled: ff.object.is_requester || ff.object.invite_by_uuid.present? || ff.object.optional_invite_by_uuid.present?, id: field_uuid = SecureRandom.uuid %>
|
<%= tag.input name: ff.field_name(:email), value: ff.object.email, type: :email, class: 'base-input', multiple: true, autocomplete: 'off', placeholder: t('default_email'), disabled: ff.object.is_requester || ff.object.invite_by_uuid.present? || ff.object.optional_invite_by_uuid.present?, id: field_uuid = SecureRandom.uuid %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<toggle-attribute data-target-id="<%= email_field_uuid = SecureRandom.uuid %>" data-class-name="hidden" data-value="email">
|
<toggle-attribute data-target-id="<%= email_field_uuid = SecureRandom.uuid %>" data-class-name="hidden" data-value="email">
|
||||||
<%= ff.select :option, [[t('not_specified'), 'not_set'], [t('submission_requester'), 'is_requester'], [t('specified_email'), 'email'], *(@template.submitters - [submitter]).flat_map { |e| [[t('invite_by_name', name: e['name']), "invite_by_#{e['uuid']}"], [t('invite_by_name', name: e['name']) + " (#{t(:optional).capitalize})", "optional_invite_by_#{e['uuid']}"]] }, *(@template.submitters - [submitter]).map { |e| [t('same_as_name', name: e['name']), "linked_to_#{e['uuid']}"] }], {}, class: 'base-select mb-3' %>
|
<%= ff.select :option, [[t('not_specified'), 'not_set'], [t('submission_requester'), 'is_requester'], [t('specified_email'), 'email'], *(@template.submitters - [submitter]).flat_map { |e| [[t('invite_by_name', name: e['name']), "invite_by_#{e['uuid']}"], [t('invite_by_name', name: e['name']) + " (#{t(:optional).capitalize})", "optional_invite_by_#{e['uuid']}"]] }, *(@template.submitters - [submitter]).map { |e| [t('same_as_name', name: e['name']), "linked_to_#{e['uuid']}"] }], {}, class: 'base-select mb-3' %>
|
||||||
</toggle-attribute>
|
</toggle-attribute>
|
||||||
<%= ff.email_field :email, class: "base-input #{'hidden' if item.option != 'email'}", autocomplete: 'off', placeholder: t('default_email'), id: email_field_uuid %>
|
<%= tag.input name: ff.field_name(:email), type: :email, value: ff.object.email, multiple: true, class: "base-input #{'hidden' if item.option != 'email'}", autocomplete: 'off', placeholder: t('default_email'), id: email_field_uuid %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% if @template.submitters.size == 2 %>
|
<% if @template.submitters.size == 2 %>
|
||||||
|
|||||||
+11
-10
@@ -8,19 +8,20 @@ module DownloadUtils
|
|||||||
module_function
|
module_function
|
||||||
|
|
||||||
def call(url)
|
def call(url)
|
||||||
uri = Addressable::URI.parse(url)
|
uri = begin
|
||||||
|
URI(url)
|
||||||
if Docuseal.multitenant?
|
rescue URI::Error
|
||||||
raise UnableToDownload, "Error loading: #{uri.display_uri}. Only HTTPS is allowed." if uri.scheme != 'https'
|
Addressable::URI.parse(url).normalize
|
||||||
|
|
||||||
if uri.host.in?(LOCALHOSTS)
|
|
||||||
raise UnableToDownload, "Error loading: #{uri.display_uri}. Can't download from localhost."
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
resp = conn.get(uri.display_uri.to_s)
|
if Docuseal.multitenant?
|
||||||
|
raise UnableToDownload, "Error loading: #{uri}. Only HTTPS is allowed." if uri.scheme != 'https'
|
||||||
|
raise UnableToDownload, "Error loading: #{uri}. Can't download from localhost." if uri.host.in?(LOCALHOSTS)
|
||||||
|
end
|
||||||
|
|
||||||
raise UnableToDownload, "Error loading: #{uri.display_uri}" if resp.status >= 400
|
resp = conn.get(uri)
|
||||||
|
|
||||||
|
raise UnableToDownload, "Error loading: #{uri}" if resp.status >= 400
|
||||||
|
|
||||||
resp
|
resp
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,7 +15,10 @@ module ReplaceEmailVariables
|
|||||||
SUBMITTER_SLUG = /\{+submitter\.slug\}+/i
|
SUBMITTER_SLUG = /\{+submitter\.slug\}+/i
|
||||||
SUBMISSION_LINK = /\{+submission\.link\}+/i
|
SUBMISSION_LINK = /\{+submission\.link\}+/i
|
||||||
SUBMISSION_ID = /\{+submission\.id\}+/i
|
SUBMISSION_ID = /\{+submission\.id\}+/i
|
||||||
SUBMISSION_SUBMITTERS = /\{+submission\.submitters\}+/i
|
SUBMITTERS = /\{+(?:submission\.)?submitters\}+/i
|
||||||
|
SUBMITTERS_N_EMAIL = /\{+submitters\[(?<index>\d+)\]\.email\}+/i
|
||||||
|
SUBMITTERS_N_NAME = /\{+submitters\[(?<index>\d+)\]\.name\}+/i
|
||||||
|
SUBMITTERS_N_FIRST_NAME = /\{+submitters\[(?<index>\d+)\]\.first_name\}+/i
|
||||||
DOCUMENTS_LINKS = /\{+documents\.links\}+/i
|
DOCUMENTS_LINKS = /\{+documents\.links\}+/i
|
||||||
DOCUMENTS_LINK = /\{+documents\.link\}+/i
|
DOCUMENTS_LINK = /\{+documents\.link\}+/i
|
||||||
|
|
||||||
@@ -37,13 +40,25 @@ module ReplaceEmailVariables
|
|||||||
text = replace(text, SUBMISSION_LINK, html_escape:) do
|
text = replace(text, SUBMISSION_LINK, html_escape:) do
|
||||||
submitter.submission ? build_submission_link(submitter.submission) : ''
|
submitter.submission ? build_submission_link(submitter.submission) : ''
|
||||||
end
|
end
|
||||||
text = replace(text, SUBMISSION_SUBMITTERS, html_escape:) { build_submission_submitters(submitter.submission) }
|
text = replace(text, SUBMITTERS, html_escape:) { build_submission_submitters(submitter.submission) }
|
||||||
text = replace(text, DOCUMENTS_LINKS, html_escape:) { build_documents_links_text(submitter, sig) }
|
text = replace(text, DOCUMENTS_LINKS, html_escape:) { build_documents_links_text(submitter, sig) }
|
||||||
text = replace(text, DOCUMENTS_LINK, html_escape:) { build_documents_links_text(submitter, sig) }
|
text = replace(text, DOCUMENTS_LINK, html_escape:) { build_documents_links_text(submitter, sig) }
|
||||||
text = replace(text, ACCOUNT_NAME, html_escape:) { submitter.submission.account.name }
|
text = replace(text, ACCOUNT_NAME, html_escape:) { submitter.submission.account.name }
|
||||||
text = replace(text, SENDER_NAME, html_escape:) { submitter.submission.created_by_user&.full_name }
|
text = replace(text, SENDER_NAME, html_escape:) { submitter.submission.created_by_user&.full_name }
|
||||||
text = replace(text, SENDER_FIRST_NAME, html_escape:) { submitter.submission.created_by_user&.first_name }
|
text = replace(text, SENDER_FIRST_NAME, html_escape:) { submitter.submission.created_by_user&.first_name }
|
||||||
|
|
||||||
|
text = replace(text, SUBMITTERS_N_NAME, html_escape:) do |match|
|
||||||
|
build_submitters_n_field(submitter.submission, match[:index].to_i - 1, :name)
|
||||||
|
end
|
||||||
|
|
||||||
|
text = replace(text, SUBMITTERS_N_EMAIL, html_escape:) do |match|
|
||||||
|
build_submitters_n_field(submitter.submission, match[:index].to_i - 1, :email)
|
||||||
|
end
|
||||||
|
|
||||||
|
text = replace(text, SUBMITTERS_N_FIRST_NAME, html_escape:) do |match|
|
||||||
|
build_submitters_n_field(submitter.submission, match[:index].to_i - 1, :first_name)
|
||||||
|
end
|
||||||
|
|
||||||
replace(text, SENDER_EMAIL, html_escape:) { submitter.submission.created_by_user&.email.to_s.sub(/\+\w+@/, '@') }
|
replace(text, SENDER_EMAIL, html_escape:) { submitter.submission.created_by_user&.email.to_s.sub(/\+\w+@/, '@') }
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics
|
# rubocop:enable Metrics
|
||||||
@@ -54,12 +69,18 @@ module ReplaceEmailVariables
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def build_submitters_n_field(submission, index, field_name)
|
||||||
|
uuid = (submission.template_submitters || submission.template.submitters).dig(index, 'uuid')
|
||||||
|
|
||||||
|
submission.submitters.find { |s| s.uuid == uuid }.try(field_name)
|
||||||
|
end
|
||||||
|
|
||||||
def replace(text, var, html_escape: false)
|
def replace(text, var, html_escape: false)
|
||||||
text.gsub(var) do
|
text.gsub(var) do
|
||||||
if html_escape
|
if html_escape
|
||||||
ERB::Util.html_escape(yield)
|
ERB::Util.html_escape(yield(Regexp.last_match))
|
||||||
else
|
else
|
||||||
yield
|
yield(Regexp.last_match)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -225,9 +225,15 @@ module Submissions
|
|||||||
|
|
||||||
def assign_completed_attributes(submitter)
|
def assign_completed_attributes(submitter)
|
||||||
submitter.values = Submitters::SubmitValues.merge_default_values(submitter)
|
submitter.values = Submitters::SubmitValues.merge_default_values(submitter)
|
||||||
submitter.values = Submitters::SubmitValues.merge_formula_values(submitter)
|
|
||||||
submitter.values = Submitters::SubmitValues.maybe_remove_condition_values(submitter)
|
submitter.values = Submitters::SubmitValues.maybe_remove_condition_values(submitter)
|
||||||
|
|
||||||
|
formula_values = Submitters::SubmitValues.build_formula_values(submitter)
|
||||||
|
|
||||||
|
if formula_values.present?
|
||||||
|
submitter.values = submitter.values.merge(formula_values)
|
||||||
|
submitter.values = Submitters::SubmitValues.maybe_remove_condition_values(submitter)
|
||||||
|
end
|
||||||
|
|
||||||
submitter.values = submitter.values.transform_values do |v|
|
submitter.values = submitter.values.transform_values do |v|
|
||||||
v == '{{date}}' ? Time.current.in_time_zone(submitter.submission.account.timezone).to_date.to_s : v
|
v == '{{date}}' ? Time.current.in_time_zone(submitter.submission.account.timezone).to_date.to_s : v
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -53,9 +53,17 @@ module Submitters
|
|||||||
submitter.completed_at = Time.current
|
submitter.completed_at = Time.current
|
||||||
submitter.ip = request.remote_ip
|
submitter.ip = request.remote_ip
|
||||||
submitter.ua = request.user_agent
|
submitter.ua = request.user_agent
|
||||||
|
|
||||||
submitter.values = merge_default_values(submitter)
|
submitter.values = merge_default_values(submitter)
|
||||||
submitter.values = maybe_remove_condition_values(submitter)
|
submitter.values = maybe_remove_condition_values(submitter)
|
||||||
submitter.values = merge_formula_values(submitter)
|
|
||||||
|
formula_values = build_formula_values(submitter)
|
||||||
|
|
||||||
|
if formula_values.present?
|
||||||
|
submitter.values = submitter.values.merge(formula_values)
|
||||||
|
submitter.values = maybe_remove_condition_values(submitter)
|
||||||
|
end
|
||||||
|
|
||||||
submitter.values = submitter.values.transform_values do |v|
|
submitter.values = submitter.values.transform_values do |v|
|
||||||
v == '{{date}}' ? Time.current.in_time_zone(submitter.account.timezone).to_date.to_s : v
|
v == '{{date}}' ? Time.current.in_time_zone(submitter.account.timezone).to_date.to_s : v
|
||||||
end
|
end
|
||||||
@@ -149,7 +157,7 @@ module Submitters
|
|||||||
default_values.compact_blank.merge(submitter.values)
|
default_values.compact_blank.merge(submitter.values)
|
||||||
end
|
end
|
||||||
|
|
||||||
def merge_formula_values(submitter)
|
def build_formula_values(submitter)
|
||||||
computed_values = submitter.submission.template_fields.each_with_object({}) do |field, acc|
|
computed_values = submitter.submission.template_fields.each_with_object({}) do |field, acc|
|
||||||
next if field['submitter_uuid'] != submitter.uuid
|
next if field['submitter_uuid'] != submitter.uuid
|
||||||
next if field['type'] == 'payment'
|
next if field['type'] == 'payment'
|
||||||
@@ -161,7 +169,7 @@ module Submitters
|
|||||||
acc[field['uuid']] = calculate_formula_value(formula, submitter.values.merge(acc.compact_blank))
|
acc[field['uuid']] = calculate_formula_value(formula, submitter.values.merge(acc.compact_blank))
|
||||||
end
|
end
|
||||||
|
|
||||||
submitter.values.merge(computed_values.compact_blank)
|
computed_values.compact_blank
|
||||||
end
|
end
|
||||||
|
|
||||||
def calculate_formula_value(_formula, _values)
|
def calculate_formula_value(_formula, _values)
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ module Templates
|
|||||||
|
|
||||||
template.external_id = external_id
|
template.external_id = external_id
|
||||||
template.author = author
|
template.author = author
|
||||||
template.preferences = original_template.preferences.deep_dup
|
|
||||||
template.name = name.presence || "#{original_template.name} (#{I18n.t('clone')})"
|
template.name = name.presence || "#{original_template.name} (#{I18n.t('clone')})"
|
||||||
|
|
||||||
if folder_name.present?
|
if folder_name.present?
|
||||||
@@ -18,10 +17,11 @@ module Templates
|
|||||||
template.folder_id = original_template.folder_id
|
template.folder_id = original_template.folder_id
|
||||||
end
|
end
|
||||||
|
|
||||||
template.submitters, template.fields, template.schema =
|
template.submitters, template.fields, template.schema, template.preferences =
|
||||||
update_submitters_and_fields_and_schema(original_template.submitters.deep_dup,
|
update_submitters_and_fields_and_schema(original_template.submitters.deep_dup,
|
||||||
original_template.fields.deep_dup,
|
original_template.fields.deep_dup,
|
||||||
original_template.schema.deep_dup)
|
original_template.schema.deep_dup,
|
||||||
|
original_template.preferences.deep_dup)
|
||||||
|
|
||||||
if name.present? && template.schema.size == 1 &&
|
if name.present? && template.schema.size == 1 &&
|
||||||
original_template.schema.first['name'] == original_template.name &&
|
original_template.schema.first['name'] == original_template.name &&
|
||||||
@@ -33,7 +33,7 @@ module Templates
|
|||||||
end
|
end
|
||||||
|
|
||||||
# rubocop:disable Metrics, Style/CombinableLoops
|
# rubocop:disable Metrics, Style/CombinableLoops
|
||||||
def update_submitters_and_fields_and_schema(cloned_submitters, cloned_fields, cloned_schema)
|
def update_submitters_and_fields_and_schema(cloned_submitters, cloned_fields, cloned_schema, cloned_preferences)
|
||||||
submitter_uuids_replacements = {}
|
submitter_uuids_replacements = {}
|
||||||
field_uuids_replacements = {}
|
field_uuids_replacements = {}
|
||||||
|
|
||||||
@@ -58,6 +58,10 @@ module Templates
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
cloned_preferences['submitters'].to_a.each do |submitter|
|
||||||
|
submitter['uuid'] = submitter_uuids_replacements[submitter['uuid']]
|
||||||
|
end
|
||||||
|
|
||||||
cloned_fields.each do |field|
|
cloned_fields.each do |field|
|
||||||
new_field_uuid = SecureRandom.uuid
|
new_field_uuid = SecureRandom.uuid
|
||||||
|
|
||||||
@@ -88,7 +92,7 @@ module Templates
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
[cloned_submitters, cloned_fields, cloned_schema]
|
[cloned_submitters, cloned_fields, cloned_schema, cloned_preferences]
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics, Style/CombinableLoops
|
# rubocop:enable Metrics, Style/CombinableLoops
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user