Skip to content

Commit

Permalink
Merge from docusealco/wip
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexBTurchyn authored Jan 27, 2025
2 parents 2da059d + 37de5e0 commit 395d43d
Show file tree
Hide file tree
Showing 27 changed files with 209 additions and 176 deletions.
2 changes: 1 addition & 1 deletion app/controllers/accounts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def destroy
# rubocop:disable Layout/LineLength
render turbo_stream: turbo_stream.replace(
:account_delete_button,
html: helpers.tag.p(I18n.t('your_account_removal_request_will_be_processed_within_2_weeks_please_contact_us_if_you_want_to_keep_your_account'))
html: helpers.tag.p(I18n.t('your_account_removal_request_will_be_processed_within_2_months_please_contact_us_if_you_want_to_keep_your_account'))
)
# rubocop:enable Layout/LineLength
end
Expand Down
1 change: 1 addition & 0 deletions app/controllers/start_form_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def find_or_initialize_submitter(template, submitter_params)
.or(template.submissions.where(expire_at: nil)).where(archived_at: nil))
.order(id: :desc)
.where(declined_at: nil)
.where(external_id: nil)
.then { |rel| params[:resubmit].present? ? rel.where(completed_at: nil) : rel }
.find_or_initialize_by(**submitter_params.compact_blank)
end
Expand Down
5 changes: 4 additions & 1 deletion app/controllers/submissions_preview_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ def show

@submission ||= Submission.find_by!(slug: params[:slug])

if @submission.account.archived_at? || (!@submission.submitters.all?(&:completed_at?) && current_user.blank?)
raise ActionController::RoutingError if @submission.account.archived_at?

if !@submission.submitters.all?(&:completed_at?) && !signature_valid &&
(!current_user || !current_ability.can?(:read, @submission))
raise ActionController::RoutingError, I18n.t('not_found')
end

Expand Down
58 changes: 58 additions & 0 deletions app/controllers/submitters_resubmit_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# frozen_string_literal: true

class SubmittersResubmitController < ApplicationController
load_and_authorize_resource :submitter, parent: false

def update
return redirect_to submit_form_path(slug: @submitter.slug) if @submitter.email != current_user.email

submission = @submitter.template.submissions.new(created_by_user: current_user,
submitters_order: :preserved,
**@submitter.submission.slice(:template_fields,
:account_id,
:template_schema,
:template_submitters,
:preferences))

@submitter.submission.submitters.each do |submitter|
new_submitter = submission.submitters.new(submitter.slice(:uuid, :email, :phone, :name,
:preferences, :metadata, :account_id))

next unless submitter.uuid == @submitter.uuid

assign_submitter_values(new_submitter, submitter)

@new_submitter ||= new_submitter
end

submission.save!

redirect_to submit_form_path(slug: @new_submitter.slug)
end

private

def assign_submitter_values(new_submitter, submitter)
attachments_index = submitter.attachments.index_by(&:uuid)

submitter.submission.template_fields.each do |field|
next if field['submitter_uuid'] != submitter.uuid
next if field['default_value'] == '{{date}}'
next if field['type'] == 'stamp'
next if field['type'] == 'signature'
next if field.dig('preferences', 'formula').present?

value = submitter.values[field['uuid']]

next if value.blank?

if field['type'].in?(%w[image file initials])
Array.wrap(value).each do |attachment_uuid|
new_submitter.attachments << attachments_index[attachment_uuid].dup
end
end

new_submitter.values[field['uuid']] = value
end
end
end
2 changes: 1 addition & 1 deletion app/javascript/submission_form/dropzone.vue
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export default {
}
})
} else {
if (file.type === 'image/bmp') {
if (file.type === 'image/bmp' || file.type === 'image/vnd.microsoft.icon') {
file = await this.convertBmpToPng(file)
}
Expand Down
36 changes: 21 additions & 15 deletions app/javascript/template_builder/area.vue
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ export default {
isMoved: false,
renderDropdown: false,
isNameFocus: false,
isHeadingSelected: false,
textOverflowChars: 0,
dragFrom: { x: 0, y: 0 }
}
Expand All @@ -377,7 +378,7 @@ export default {
}
},
isValueInput () {
return (this.field.type === 'heading' && this.isSelected) || this.isContenteditable || (this.inputMode && ['text', 'number', 'date'].includes(this.field.type))
return (this.field.type === 'heading' && this.isHeadingSelected) || this.isContenteditable || (this.inputMode && ['text', 'number', 'date'].includes(this.field.type))
},
modalContainerEl () {
return this.$el.getRootNode().querySelector('#docuseal_modal_container')
Expand Down Expand Up @@ -485,7 +486,7 @@ export default {
if (['text', 'number'].includes(this.field.type)) {
this.isContenteditable = true
this.$nextTick(() => this.focusValueInput())
this.focusValueInput()
} else if (this.field.type === 'checkbox') {
this.field.readonly = !this.field.readonly
this.field.default_value === true ? delete this.field.default_value : this.field.default_value = true
Expand All @@ -507,16 +508,18 @@ export default {
}
},
focusValueInput (e) {
if (this.$refs.defaultValue !== document.activeElement) {
this.$refs.defaultValue.focus()
if (this.$refs.defaultValue.innerText.length && this.$refs.defaultValue !== e?.target) {
window.getSelection().collapse(
this.$refs.defaultValue.firstChild,
this.$refs.defaultValue.innerText.length
)
this.$nextTick(() => {
if (this.$refs.defaultValue && this.$refs.defaultValue !== document.activeElement) {
this.$refs.defaultValue.focus()
if (this.$refs.defaultValue.innerText.length && this.$refs.defaultValue !== e?.target) {
window.getSelection().collapse(
this.$refs.defaultValue.firstChild,
this.$refs.defaultValue.innerText.length
)
}
}
}
})
},
formatNumber (number, format) {
if (format === 'comma') {
Expand Down Expand Up @@ -632,6 +635,7 @@ export default {
const text = this.$refs.defaultValue.innerText.trim()
this.isContenteditable = false
this.isHeadingSelected = false
if (text) {
if (this.field.type === 'number') {
Expand Down Expand Up @@ -749,10 +753,6 @@ export default {
this.selectedAreaRef.value = this.area
if (this.field.type === 'heading') {
this.$nextTick(() => this.focusValueInput())
}
this.dragFrom = { x: rect.left - e.clientX, y: rect.top - e.clientY }
this.$el.getRootNode().addEventListener('mousemove', this.mouseMove)
Expand Down Expand Up @@ -787,6 +787,12 @@ export default {
this.save()
}
if (this.field.type === 'heading') {
this.isHeadingSelected = !this.isMoved
this.focusValueInput()
}
this.isDragged = false
this.isMoved = false
Expand Down
2 changes: 2 additions & 0 deletions app/javascript/template_builder/builder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -1427,6 +1427,8 @@ export default {
const documentRef = this.documentRefs.find((e) => e.document.uuid === area.attachment_uuid)
const areaRef = documentRef.pageRefs[area.page].areaRefs.find((ref) => ref.area === this.selectedAreaRef.value)
areaRef.isHeadingSelected = true
areaRef.focusValueInput()
})
}
Expand Down
25 changes: 23 additions & 2 deletions app/javascript/template_builder/field_submitter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@
<li
v-for="(submitter, index) in submitters"
:key="submitter.uuid"
class="w-full"
>
<a
href="#"
Expand Down Expand Up @@ -191,7 +192,10 @@
</div>
</a>
</li>
<li v-if="submitters.length < names.length && editable && allowAddNew">
<li
v-if="submitters.length < names.length && editable && allowAddNew"
class="w-full"
>
<a
href="#"
class="flex px-2"
Expand All @@ -215,6 +219,14 @@ import { IconUserPlus, IconTrashX, IconPlus, IconChevronUp, IconChevronDown } fr
import Contenteditable from './contenteditable'
import { v4 } from 'uuid'
function getOrdinalSuffix (num) {
if (num % 10 === 1 && num % 100 !== 11) return 'st'
if (num % 10 === 2 && num % 100 !== 12) return 'nd'
if (num % 10 === 3 && num % 100 !== 13) return 'rd'
return 'th'
}
export default {
name: 'FieldSubmitter',
components: {
Expand Down Expand Up @@ -288,6 +300,14 @@ export default {
]
},
names () {
const generatedNames = []
for (let i = 21; i < 101; i++) {
const suffix = getOrdinalSuffix(i)
generatedNames.push(`${i}${suffix} ${this.t('party')}`)
}
return [
this.t('first_party'),
this.t('second_party'),
Expand All @@ -308,7 +328,8 @@ export default {
this.t('seventeenth_party'),
this.t('eighteenth_party'),
this.t('nineteenth_party'),
this.t('twentieth_party')
this.t('twentieth_party'),
...generatedNames
]
},
lastPartyIndex () {
Expand Down
4 changes: 2 additions & 2 deletions app/javascript/template_builder/fields.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
class="roles-dropdown w-full rounded-lg"
:style="withStickySubmitters ? { backgroundColor } : {}"
:submitters="submitters"
:menu-style="{ backgroundColor: ['', null, 'transparent'].includes(backgroundColor) ? 'white' : backgroundColor }"
:menu-style="{ overflow: 'auto', display: 'flex', flexDirection: 'row', maxHeight: 'calc(100vh - 120px)', backgroundColor: ['', null, 'transparent'].includes(backgroundColor) ? 'white' : backgroundColor }"
:editable="editable && !defaultSubmitters.length"
@new-submitter="save"
@remove="removeSubmitter"
Expand Down Expand Up @@ -327,7 +327,7 @@ export default {
},
filteredSubmitterDefaultFields () {
if (this.defaultFieldsSearch) {
return this.submitterDefaultFields.filter((f) => f.name.toLowerCase().includes(this.defaultFieldsSearch.toLowerCase()))
return this.submitterDefaultFields.filter((f) => (f.title || f.name).toLowerCase().includes(this.defaultFieldsSearch.toLowerCase()))
} else {
return this.submitterDefaultFields
}
Expand Down
6 changes: 6 additions & 0 deletions app/javascript/template_builder/i18n.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const en = {
party: 'Party',
method: 'Method',
reorder_fields: 'Reorder fields',
verify_id: 'Verify ID',
Expand Down Expand Up @@ -160,6 +161,7 @@ const en = {
}

const es = {
party: 'Parte',
method: 'Método',
reorder_fields: 'Reordenar campos',
verify_id: 'Verificar ID',
Expand Down Expand Up @@ -321,6 +323,7 @@ const es = {
}

const it = {
party: 'Parte',
method: 'Metodo',
reorder_fields: 'Riordina i campi',
verify_id: 'Verifica ID',
Expand Down Expand Up @@ -482,6 +485,7 @@ const it = {
}

const pt = {
party: 'Parte',
method: 'Método',
reorder_fields: 'Reorganizar campos',
verify_id: 'Verificar ID',
Expand Down Expand Up @@ -643,6 +647,7 @@ const pt = {
}

const fr = {
party: 'Partie',
method: 'Méthode',
reorder_fields: 'Réorganiser les champs',
verify_id: "Vérifier l'ID",
Expand Down Expand Up @@ -804,6 +809,7 @@ const fr = {
}

const de = {
party: 'Partei',
method: 'Verfahren',
reorder_fields: 'Felder neu anordnen',
verify_id: 'ID überprüfen',
Expand Down
17 changes: 2 additions & 15 deletions app/jobs/send_form_completed_webhook_request_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ class SendFormCompletedWebhookRequestJob

sidekiq_options queue: :webhooks

USER_AGENT = 'DocuSeal.com Webhook'

MAX_ATTEMPTS = 20

def perform(params = {})
Expand All @@ -21,19 +19,8 @@ def perform(params = {})

ActiveStorage::Current.url_options = Docuseal.default_url_options

resp = begin
Faraday.post(webhook_url.url,
{
event_type: 'form.completed',
timestamp: Time.current,
data: Submitters::SerializeForWebhook.call(submitter)
}.to_json,
'Content-Type' => 'application/json',
'User-Agent' => USER_AGENT,
**webhook_url.secret.to_h)
rescue Faraday::Error
nil
end
resp = SendWebhookRequest.call(webhook_url, event_type: 'form.completed',
data: Submitters::SerializeForWebhook.call(submitter))

if (resp.nil? || resp.status.to_i >= 400) && attempt <= MAX_ATTEMPTS &&
(!Docuseal.multitenant? || submitter.account.account_configs.exists?(key: :plan))
Expand Down
17 changes: 2 additions & 15 deletions app/jobs/send_form_declined_webhook_request_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ class SendFormDeclinedWebhookRequestJob

sidekiq_options queue: :webhooks

USER_AGENT = 'DocuSeal.com Webhook'

MAX_ATTEMPTS = 10

def perform(params = {})
Expand All @@ -19,19 +17,8 @@ def perform(params = {})

ActiveStorage::Current.url_options = Docuseal.default_url_options

resp = begin
Faraday.post(webhook_url.url,
{
event_type: 'form.declined',
timestamp: Time.current,
data: Submitters::SerializeForWebhook.call(submitter)
}.to_json,
**webhook_url.secret.to_h,
'Content-Type' => 'application/json',
'User-Agent' => USER_AGENT)
rescue Faraday::Error
nil
end
resp = SendWebhookRequest.call(webhook_url, event_type: 'form.declined',
data: Submitters::SerializeForWebhook.call(submitter))

if (resp.nil? || resp.status.to_i >= 400) && attempt <= MAX_ATTEMPTS &&
(!Docuseal.multitenant? || submitter.account.account_configs.exists?(key: :plan))
Expand Down
Loading

0 comments on commit 395d43d

Please sign in to comment.