Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 33ca930055 | |||
| 3b396f8421 | |||
| aa77e3a8d3 | |||
| 75316d8d87 | |||
| a999109a5c | |||
| bdd33c7d6b | |||
| 61c5ee22a0 | |||
| 12c5b909e0 | |||
| 871ef6dda6 | |||
| 40052a2d7c | |||
| 347be0137d | |||
| fe6baba8bf | |||
| ed8c313bd4 | |||
| ca0acb34d6 | |||
| 34ea639c25 | |||
| 680ab9dbed | |||
| 9377766e52 | |||
| 7a2c37454e | |||
| 8f6f418f54 | |||
| 9b7745c565 | |||
| a389e8cc38 | |||
| 2056301f70 | |||
| 93babe3660 | |||
| 4aef2d8eb0 | |||
| c5ec2ed230 | |||
| a156d5f6cc | |||
| f84674cddd | |||
| b7b62c197a | |||
| f5350eac36 | |||
| ee6228db15 | |||
| 3e434c0878 | |||
| 7c5372a8e2 |
@@ -205,7 +205,7 @@ GEM
|
||||
railties (>= 6.1.0)
|
||||
faker (3.6.0)
|
||||
i18n (>= 1.8.11, < 2)
|
||||
faraday (2.14.0)
|
||||
faraday (2.14.1)
|
||||
faraday-net_http (>= 2.0, < 3.5)
|
||||
json
|
||||
logger
|
||||
@@ -285,7 +285,7 @@ GEM
|
||||
rdoc (>= 4.0.0)
|
||||
reline (>= 0.4.2)
|
||||
jmespath (1.6.2)
|
||||
json (2.18.0)
|
||||
json (2.18.1)
|
||||
jwt (3.1.2)
|
||||
base64
|
||||
language_server-protocol (3.17.0.5)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<h1 align="center" style="border-bottom: none">
|
||||
<div>
|
||||
<a href="https://www.docuseal.com">
|
||||
<img alt="DocuSeal" src="https://github.com/docusealco/docuseal/assets/5418788/c12cd051-81cd-4402-bc3a-92f2cfdc1b06" width="80" />
|
||||
<img alt="DocuSeal" src="https://github.com/user-attachments/assets/38b45682-ffa4-4919-abde-d2d422325c44" width="80" />
|
||||
<br>
|
||||
</a>
|
||||
DocuSeal
|
||||
|
||||
@@ -27,20 +27,18 @@ class SubmissionsDownloadController < ApplicationController
|
||||
|
||||
Submissions::EnsureResultGenerated.call(last_submitter)
|
||||
|
||||
if last_submitter.completed_at < TTL.ago && !signature_valid && !current_user_submitter?(last_submitter)
|
||||
Rollbar.info("TTL: #{last_submitter.id}") if defined?(Rollbar)
|
||||
if !signature_valid && !current_user_submitter?(last_submitter)
|
||||
return head :not_found unless Submitters::AuthorizedForForm.call(@submitter, current_user, request)
|
||||
|
||||
return head :not_found
|
||||
if last_submitter.completed_at < TTL.ago
|
||||
Rollbar.info("TTL: #{last_submitter.id}") if defined?(Rollbar)
|
||||
|
||||
return head :not_found
|
||||
end
|
||||
end
|
||||
|
||||
if params[:combined] == 'true'
|
||||
url = build_combined_url(@submitter)
|
||||
|
||||
if url
|
||||
render json: [url]
|
||||
else
|
||||
head :not_found
|
||||
end
|
||||
respond_with_combined(last_submitter)
|
||||
else
|
||||
render json: build_urls(last_submitter)
|
||||
end
|
||||
@@ -48,8 +46,18 @@ class SubmissionsDownloadController < ApplicationController
|
||||
|
||||
private
|
||||
|
||||
def respond_with_combined(submitter)
|
||||
url = build_combined_url(submitter)
|
||||
|
||||
if url
|
||||
render json: [url]
|
||||
else
|
||||
head :not_found
|
||||
end
|
||||
end
|
||||
|
||||
def current_user_submitter?(submitter)
|
||||
current_user && current_user.account.submitters.exists?(id: submitter.id)
|
||||
current_user && current_ability.can?(:read, submitter)
|
||||
end
|
||||
|
||||
def build_urls(submitter)
|
||||
|
||||
@@ -9,15 +9,15 @@ class SubmitFormController < ApplicationController
|
||||
|
||||
before_action :load_submitter, only: %i[show update completed]
|
||||
before_action :maybe_render_locked_page, only: :show
|
||||
before_action :maybe_require_link_2fa, only: %i[show update]
|
||||
before_action :maybe_require_link_2fa, only: %i[show]
|
||||
|
||||
CONFIG_KEYS = [].freeze
|
||||
|
||||
def show
|
||||
submission = @submitter.submission
|
||||
|
||||
return render :email_2fa unless Submitters::AuthorizedForForm.pass_email_2fa?(@submitter, request)
|
||||
return redirect_to submit_form_completed_path(@submitter.slug) if @submitter.completed_at?
|
||||
return render :email_2fa if require_email_2fa?(@submitter)
|
||||
|
||||
@form_configs = Submitters::FormConfigs.call(@submitter, CONFIG_KEYS)
|
||||
|
||||
@@ -48,7 +48,7 @@ class SubmitFormController < ApplicationController
|
||||
end
|
||||
|
||||
def update
|
||||
if require_email_2fa?(@submitter)
|
||||
unless Submitters::AuthorizedForForm.call(@submitter, current_user, request)
|
||||
return render json: { error: I18n.t('verification_required_refresh_the_page_and_pass_2fa') },
|
||||
status: :unprocessable_content
|
||||
end
|
||||
@@ -84,7 +84,9 @@ class SubmitFormController < ApplicationController
|
||||
def completed
|
||||
raise ActionController::RoutingError, I18n.t('not_found') if @submitter.account.archived_at?
|
||||
|
||||
redirect_to submit_form_path(params[:submit_form_slug]) if require_email_2fa?(@submitter)
|
||||
return if Submitters::AuthorizedForForm.call(@submitter, current_user, request)
|
||||
|
||||
redirect_to submit_form_path(params[:submit_form_slug])
|
||||
end
|
||||
|
||||
def success; end
|
||||
@@ -92,10 +94,7 @@ class SubmitFormController < ApplicationController
|
||||
private
|
||||
|
||||
def maybe_require_link_2fa
|
||||
return if @submitter.submission.source != 'link'
|
||||
return unless @submitter.submission.template&.preferences&.dig('shared_link_2fa') == true
|
||||
return if cookies.encrypted[:email_2fa_slug] == @submitter.slug
|
||||
return if @submitter.email == current_user&.email && current_user&.account_id == @submitter.account_id
|
||||
return if Submitters::AuthorizedForForm.pass_link_2fa?(@submitter, current_user, request)
|
||||
|
||||
redirect_to start_form_path(@submitter.submission.template.slug)
|
||||
end
|
||||
@@ -117,12 +116,4 @@ class SubmitFormController < ApplicationController
|
||||
ActiveStorage::Attachment.where(record: submission.submitters, name: :attachments)
|
||||
.preload(:blob).index_by(&:uuid)
|
||||
end
|
||||
|
||||
def require_email_2fa?(submitter)
|
||||
return false if submitter.submission.template&.preferences&.dig('require_email_2fa') != true &&
|
||||
submitter.preferences['require_email_2fa'] != true
|
||||
return false if cookies.encrypted[:email_2fa_slug] == submitter.slug
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,7 +11,9 @@ class SubmitFormDeclineController < ApplicationController
|
||||
submitter.completed_at? ||
|
||||
submitter.submission.archived_at? ||
|
||||
submitter.submission.expired? ||
|
||||
submitter.submission.template&.archived_at?
|
||||
submitter.submission.template&.archived_at? ||
|
||||
!Submitters::AuthorizedForForm.call(submitter, current_user,
|
||||
request)
|
||||
|
||||
ApplicationRecord.transaction do
|
||||
submitter.update!(declined_at: Time.current)
|
||||
|
||||
@@ -17,7 +17,8 @@ class SubmitFormDownloadController < ApplicationController
|
||||
@submitter.submission.template&.archived_at? ||
|
||||
AccountConfig.exists?(account_id: @submitter.account_id,
|
||||
key: AccountConfig::ALLOW_TO_PARTIAL_DOWNLOAD_KEY,
|
||||
value: false)
|
||||
value: false) ||
|
||||
!Submitters::AuthorizedForForm.call(@submitter, current_user, request)
|
||||
|
||||
last_completed_submitter = @submitter.submission.submitters
|
||||
.where.not(id: @submitter.id)
|
||||
|
||||
@@ -12,7 +12,8 @@ class SubmitFormDrawSignatureController < ApplicationController
|
||||
|
||||
return redirect_to submit_form_completed_path(@submitter.slug) if @submitter.completed_at?
|
||||
|
||||
if @submitter.submission.template&.archived_at? || @submitter.submission.archived_at?
|
||||
if @submitter.submission.template&.archived_at? || @submitter.submission.archived_at? ||
|
||||
!Submitters::AuthorizedForForm.call(@submitter, current_user, request)
|
||||
return redirect_to submit_form_path(@submitter.slug)
|
||||
end
|
||||
|
||||
|
||||
@@ -45,7 +45,8 @@ class SubmitFormInviteController < ApplicationController
|
||||
!submitter.completed_at? &&
|
||||
!submitter.submission.archived_at? &&
|
||||
!submitter.submission.expired? &&
|
||||
!submitter.submission.template&.archived_at?
|
||||
!submitter.submission.template&.archived_at? &&
|
||||
Submitters::AuthorizedForForm.call(submitter, current_user, request)
|
||||
end
|
||||
|
||||
def filter_invite_submitters(submitter, key = 'invite_by_uuid')
|
||||
|
||||
@@ -7,10 +7,12 @@ class SubmitFormValuesController < ApplicationController
|
||||
def index
|
||||
submitter = Submitter.find_by!(slug: params[:submit_form_slug])
|
||||
|
||||
return render json: {} if submitter.completed_at? || submitter.declined_at?
|
||||
return render json: {} if submitter.submission.template&.archived_at? ||
|
||||
return render json: {} if submitter.completed_at? ||
|
||||
submitter.declined_at? ||
|
||||
submitter.submission.template&.archived_at? ||
|
||||
submitter.submission.archived_at? ||
|
||||
submitter.submission.expired?
|
||||
submitter.submission.expired? ||
|
||||
!Submitters::AuthorizedForForm.call(submitter, current_user, request)
|
||||
|
||||
value = submitter.values[params['field_uuid']]
|
||||
attachment = submitter.attachments.where(created_at: params[:after]..).find_by(uuid: value) if value.present?
|
||||
|
||||
@@ -56,7 +56,7 @@ class TemplatesUploadsController < ApplicationController
|
||||
def create_file_params_from_url
|
||||
tempfile = Tempfile.new
|
||||
tempfile.binmode
|
||||
tempfile.write(DownloadUtils.call(params[:url]).body)
|
||||
tempfile.write(DownloadUtils.call(params[:url], validate: true).body)
|
||||
tempfile.rewind
|
||||
|
||||
filename = URI.decode_www_form_component(params[:filename]) if params[:filename].present?
|
||||
|
||||
@@ -12,6 +12,6 @@ export default class extends HTMLElement {
|
||||
}
|
||||
|
||||
get button () {
|
||||
return this.querySelector('button')
|
||||
return this.querySelector('button, label')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +161,11 @@ export default {
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
fetchOptions: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({})
|
||||
},
|
||||
completedButton: {
|
||||
type: Object,
|
||||
required: false,
|
||||
@@ -214,7 +219,10 @@ export default {
|
||||
download () {
|
||||
this.isDownloading = true
|
||||
|
||||
fetch(this.baseUrl + `/submitters/${this.submitterSlug}/download`).then(async (response) => {
|
||||
fetch(this.baseUrl + `/submitters/${this.submitterSlug}/download`, {
|
||||
method: 'GET',
|
||||
...this.fetchOptions
|
||||
}).then(async (response) => {
|
||||
if (response.ok) {
|
||||
const urls = await response.json()
|
||||
const isMobileSafariIos = 'ontouchstart' in window && navigator.maxTouchPoints > 0 && /AppleWebKit/i.test(navigator.userAgent)
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<MarkdownContent :string="field.description" />
|
||||
</div>
|
||||
<AppearsOn :field="field" />
|
||||
<div class="text-center">
|
||||
<div class="text-center flex">
|
||||
<input
|
||||
:id="field.uuid"
|
||||
ref="input"
|
||||
|
||||
@@ -421,6 +421,7 @@
|
||||
v-model="values[currentField.uuid]"
|
||||
:field="currentField"
|
||||
:dry-run="dryRun"
|
||||
:submitter="submitter"
|
||||
:previous-value="previousInitialsValue"
|
||||
:attachments-index="attachmentsIndex"
|
||||
:show-field-names="showFieldNames"
|
||||
@@ -529,6 +530,7 @@
|
||||
v-else-if="isInvite"
|
||||
:submitters="inviteSubmitters"
|
||||
:optional-submitters="optionalInviteSubmitters"
|
||||
:fetch-options="fetchOptions"
|
||||
:submitter-slug="submitterSlug"
|
||||
:authenticity-token="authenticityToken"
|
||||
:url="baseUrl + submitPath + '/invite'"
|
||||
@@ -542,6 +544,7 @@
|
||||
:has-signature-fields="stepFields.some((fields) => fields.some((f) => ['signature', 'initials'].includes(f.type)))"
|
||||
:has-multiple-documents="hasMultipleDocuments"
|
||||
:completed-button="completedRedirectUrl ? {} : completedButton"
|
||||
:fetch-options="fetchOptions"
|
||||
:completed-message="completedRedirectUrl ? {} : completedMessage"
|
||||
:with-send-copy-button="withSendCopyButton && !completedRedirectUrl"
|
||||
:with-download-button="withDownloadButton && !completedRedirectUrl && !dryRun"
|
||||
@@ -554,14 +557,18 @@
|
||||
class="flex justify-center mt-3 sm:mt-4 mb-0 sm:mb-1 select-none"
|
||||
>
|
||||
<div class="flex items-center flex-wrap steps-progress">
|
||||
<a
|
||||
<template
|
||||
v-for="(step, index) in stepFields"
|
||||
:key="step[0].uuid"
|
||||
href="#"
|
||||
class="inline border border-base-300 h-3 w-3 rounded-full mx-1 mt-1"
|
||||
:class="{ 'bg-base-300 steps-progress-current': index === currentStep, 'bg-base-content': (index < currentStep && stepFields[index].every((f) => !f.required || ![null, undefined, ''].includes(values[f.uuid]))) || isCompleted, 'bg-white': index > currentStep }"
|
||||
@click.prevent="isCompleted ? '' : [saveStep(), goToStep(index, true)]"
|
||||
/>
|
||||
>
|
||||
<a
|
||||
v-if="!onlyRequiredFields || step.some((f) => f.required)"
|
||||
href="#"
|
||||
class="inline border border-base-300 h-3 w-3 rounded-full mx-1 mt-1"
|
||||
:class="{ 'bg-base-300 steps-progress-current': index === currentStep, 'bg-base-content': (index < currentStep && stepFields[index].every((f) => !f.required || ![null, undefined, ''].includes(values[f.uuid]))) || isCompleted, 'bg-white': index > currentStep }"
|
||||
@click.prevent="isCompleted ? '' : [saveStep(), goToStep(index, true)]"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -673,6 +680,11 @@ export default {
|
||||
required: false,
|
||||
default: () => []
|
||||
},
|
||||
fetchOptions: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({})
|
||||
},
|
||||
optionalInviteSubmitters: {
|
||||
type: Array,
|
||||
required: false,
|
||||
@@ -693,6 +705,11 @@ export default {
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
onlyRequiredFields: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
requireSigningReason: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
@@ -955,7 +972,13 @@ export default {
|
||||
submitButtonText () {
|
||||
if (this.alwaysMinimize) {
|
||||
return this.t('submit')
|
||||
} else if (this.stepFields.length === this.currentStep + 1) {
|
||||
} else if (!this.onlyRequiredFields && this.stepFields.length === this.currentStep + 1) {
|
||||
if (this.currentField.type === 'signature') {
|
||||
return this.t('sign_and_complete')
|
||||
} else {
|
||||
return this.t('complete')
|
||||
}
|
||||
} else if (this.onlyRequiredFields && !this.findNextStep(this.currentStep)) {
|
||||
if (this.currentField.type === 'signature') {
|
||||
return this.t('sign_and_complete')
|
||||
} else {
|
||||
@@ -1174,11 +1197,11 @@ export default {
|
||||
|
||||
const indexesList = [this.stepFields.length - 1]
|
||||
|
||||
if (requiredEmptyStepIndex !== -1) {
|
||||
if (requiredEmptyStepIndex !== -1 && (!this.onlyRequiredFields || this.stepFields[requiredEmptyStepIndex].some((f) => f.required))) {
|
||||
indexesList.push(requiredEmptyStepIndex)
|
||||
}
|
||||
|
||||
if (lastFilledStepIndex !== -1) {
|
||||
if (lastFilledStepIndex !== -1 && (!this.onlyRequiredFields || this.stepFields[lastFilledStepIndex].some((f) => f.required))) {
|
||||
indexesList.push(lastFilledStepIndex)
|
||||
}
|
||||
|
||||
@@ -1239,11 +1262,11 @@ export default {
|
||||
}
|
||||
},
|
||||
checkFieldConditions (field, cache = {}) {
|
||||
if (cache[field.uuid] !== undefined) {
|
||||
return cache[field.uuid]
|
||||
}
|
||||
const cacheKey = field.uuid || field.attachment_uuid
|
||||
|
||||
cache[field.uuid] = true
|
||||
if (cache[cacheKey] !== undefined) {
|
||||
return cache[cacheKey]
|
||||
}
|
||||
|
||||
if (field.conditions?.length) {
|
||||
const result = field.conditions.reduce((acc, cond) => {
|
||||
@@ -1256,10 +1279,12 @@ export default {
|
||||
return acc
|
||||
}, [])
|
||||
|
||||
cache[field.uuid] = !result.includes(false)
|
||||
cache[cacheKey] = !result.includes(false)
|
||||
} else {
|
||||
cache[cacheKey] = true
|
||||
}
|
||||
|
||||
return cache[field.uuid]
|
||||
return cache[cacheKey]
|
||||
},
|
||||
checkFieldCondition (condition, cache = {}) {
|
||||
const field = this.fieldsUuidIndex[condition.field_uuid]
|
||||
@@ -1329,6 +1354,13 @@ export default {
|
||||
return `${this.t('option')} ${index + 1}`
|
||||
}
|
||||
},
|
||||
findNextStep (currentStepIndex) {
|
||||
if (this.onlyRequiredFields) {
|
||||
return this.stepFields.find((step, index) => index > currentStepIndex && step.some((f) => f.required))
|
||||
} else {
|
||||
return this.stepFields[currentStepIndex + 1]
|
||||
}
|
||||
},
|
||||
maybeTrackEmailClick () {
|
||||
const { queryParams } = this
|
||||
|
||||
@@ -1442,7 +1474,8 @@ export default {
|
||||
} else {
|
||||
return fetch(this.baseUrl + this.submitPath, {
|
||||
method: 'POST',
|
||||
body: formData || new FormData(this.$refs.form)
|
||||
body: formData || new FormData(this.$refs.form),
|
||||
...this.fetchOptions
|
||||
}).then((response) => {
|
||||
if (response.status === 200) {
|
||||
currentFieldUuids.forEach((fieldUuid) => {
|
||||
@@ -1475,7 +1508,7 @@ export default {
|
||||
this.isSubmittingComplete = true
|
||||
}
|
||||
|
||||
const submitStep = this.currentStep
|
||||
const submitStepIndex = this.currentStep
|
||||
|
||||
const stepPromise = ['signature', 'phone', 'initials', 'payment', 'verification', 'kba'].includes(this.currentField.type)
|
||||
? this.$refs.currentStep.submit
|
||||
@@ -1483,7 +1516,7 @@ export default {
|
||||
|
||||
stepPromise().then(async () => {
|
||||
const emptyRequiredField = this.stepFields.find((fields, index) => {
|
||||
if (forceComplete ? index === submitStep : index >= submitStep) {
|
||||
if (forceComplete ? index === submitStepIndex : index >= submitStepIndex) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -1493,7 +1526,7 @@ export default {
|
||||
})
|
||||
|
||||
const formData = new FormData(this.$refs.form)
|
||||
const isLastStep = (submitStep === this.stepFields.length - 1) || forceComplete
|
||||
const isLastStep = (this.onlyRequiredFields ? !this.findNextStep(submitStepIndex) : (submitStepIndex === this.stepFields.length - 1)) || forceComplete
|
||||
|
||||
if (isLastStep && !emptyRequiredField && !this.inviteSubmitters.length && !this.optionalInviteSubmitters.length) {
|
||||
formData.append('completed', 'true')
|
||||
@@ -1537,7 +1570,7 @@ export default {
|
||||
return Promise.reject(new Error(data.error))
|
||||
}
|
||||
|
||||
const nextStep = (isLastStep && emptyRequiredField) || (forceComplete ? null : this.stepFields[submitStep + 1])
|
||||
const nextStep = (isLastStep && emptyRequiredField) || (forceComplete ? null : this.findNextStep(submitStepIndex))
|
||||
|
||||
if (nextStep) {
|
||||
if (this.alwaysMinimize) {
|
||||
|
||||
@@ -175,6 +175,10 @@ export default {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
submitter: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
dryRun: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
@@ -257,6 +261,14 @@ export default {
|
||||
|
||||
this.$refs.canvas.getContext('2d').scale(scale, scale)
|
||||
|
||||
if (!this.isDrawInitials) {
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.textInput) {
|
||||
this.initTextInitial()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.intersectionObserver?.disconnect()
|
||||
}
|
||||
})
|
||||
@@ -332,12 +344,27 @@ export default {
|
||||
|
||||
if (!this.isDrawInitials) {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.textInput.focus()
|
||||
if (this.$refs.textInput) {
|
||||
if (!this.submitter.name) {
|
||||
this.$refs.textInput.focus()
|
||||
}
|
||||
|
||||
this.$emit('start')
|
||||
this.initTextInitial()
|
||||
|
||||
this.$emit('start')
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
initTextInitial () {
|
||||
if (this.submitter.name) {
|
||||
this.$refs.textInput.value = this.submitter.name.trim().split(/\s+/).filter(Boolean).slice(0, 2).map((part) => part[0]?.toUpperCase() || '').join('')
|
||||
}
|
||||
|
||||
if (this.$refs.textInput.value) {
|
||||
this.updateWrittenInitials({ target: this.$refs.textInput })
|
||||
}
|
||||
},
|
||||
async submit () {
|
||||
if (this.modelValue || this.computedPreviousValue) {
|
||||
if (this.computedPreviousValue) {
|
||||
|
||||
@@ -78,6 +78,11 @@ export default {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
fetchOptions: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({})
|
||||
},
|
||||
optionalSubmitters: {
|
||||
type: Array,
|
||||
required: false,
|
||||
@@ -108,7 +113,8 @@ export default {
|
||||
|
||||
return fetch(this.url, {
|
||||
method: 'POST',
|
||||
body: new FormData(this.$refs.form)
|
||||
body: new FormData(this.$refs.form),
|
||||
...this.fetchOptions
|
||||
}).then((response) => {
|
||||
if (response.status === 200) {
|
||||
this.$emit('success')
|
||||
|
||||
@@ -316,7 +316,7 @@ import FileDropzone from './dropzone'
|
||||
import MarkdownContent from './markdown_content'
|
||||
import { v4 } from 'uuid'
|
||||
|
||||
let isFontLoaded = false
|
||||
let fontLoadPromise = null
|
||||
|
||||
const scale = 3
|
||||
|
||||
@@ -482,6 +482,14 @@ export default {
|
||||
if (entry.isIntersecting) {
|
||||
this.setCanvasSize()
|
||||
|
||||
if (this.isTextSignature) {
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.textInput) {
|
||||
this.initTypedSignature()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.intersectionObserver?.disconnect()
|
||||
}
|
||||
})
|
||||
@@ -504,6 +512,10 @@ export default {
|
||||
})
|
||||
|
||||
this.resizeObserver.observe(this.$refs.canvas.parentNode)
|
||||
|
||||
if (this.isTextSignature) {
|
||||
this.loadFont()
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeUnmount () {
|
||||
@@ -541,7 +553,7 @@ export default {
|
||||
|
||||
this.pad.fromData(scaledData)
|
||||
} else if (this.isTextSignature && this.$refs.textInput) {
|
||||
this.updateWrittenSignature({ target: { value: this.$refs.textInput.value } })
|
||||
this.updateWrittenSignature({ target: this.$refs.textInput })
|
||||
}
|
||||
},
|
||||
remove () {
|
||||
@@ -551,17 +563,17 @@ export default {
|
||||
this.isSignatureStarted = false
|
||||
},
|
||||
loadFont () {
|
||||
if (!isFontLoaded) {
|
||||
if (!fontLoadPromise) {
|
||||
const font = new FontFace('Dancing Script', `url(${this.baseUrl}/fonts/DancingScript-Regular.otf) format("opentype")`)
|
||||
|
||||
font.load().then((loadedFont) => {
|
||||
fontLoadPromise = font.load().then((loadedFont) => {
|
||||
document.fonts.add(loadedFont)
|
||||
|
||||
isFontLoaded = true
|
||||
}).catch((error) => {
|
||||
console.error('Font loading failed:', error)
|
||||
})
|
||||
}
|
||||
|
||||
return fontLoadPromise
|
||||
},
|
||||
showQr () {
|
||||
this.isShowQr = true
|
||||
@@ -661,14 +673,29 @@ export default {
|
||||
|
||||
if (this.isTextSignature) {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.textInput.focus()
|
||||
if (this.$refs.textInput) {
|
||||
if (!this.submitter.name) {
|
||||
this.$refs.textInput.focus()
|
||||
}
|
||||
|
||||
this.loadFont()
|
||||
this.initTypedSignature()
|
||||
|
||||
this.$emit('start')
|
||||
this.$emit('start')
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
async initTypedSignature () {
|
||||
if (this.submitter.name) {
|
||||
this.$refs.textInput.value = this.submitter.name
|
||||
}
|
||||
|
||||
await this.loadFont()
|
||||
|
||||
if (this.$refs.textInput.value) {
|
||||
this.updateWrittenSignature({ target: this.$refs.textInput })
|
||||
}
|
||||
},
|
||||
drawImage (event) {
|
||||
this.remove()
|
||||
this.clear()
|
||||
|
||||
@@ -2,87 +2,20 @@
|
||||
<svg
|
||||
height="40"
|
||||
width="40"
|
||||
version="1.1"
|
||||
style="color: #e0753f"
|
||||
viewBox="0 0 180 180"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 511.998 511.998"
|
||||
xml:space="preserve"
|
||||
>
|
||||
<path
|
||||
style="fill:#AA968C;"
|
||||
d="M503.999,247.999c0,128.13-111.033,240-248,240S8,376.129,8,247.999s111.033-224,248-224
|
||||
S503.999,119.869,503.999,247.999z"
|
||||
/>
|
||||
<path
|
||||
style="fill:#AA968C;"
|
||||
d="M255.999,23.999C119.033,23.999,8,119.868,8,247.999c0,24.631,4.138,48.647,11.74,71.397
|
||||
c25.518,34.29,66.232,56.602,112.26,56.602c53.893,0,100.6-30.495,124-75.13c23.4,44.636,70.107,75.13,124,75.13
|
||||
c46.028,0,86.743-22.312,112.26-56.602c7.602-22.75,11.74-46.767,11.74-71.397C503.999,119.868,392.966,23.999,255.999,23.999z"
|
||||
fill="currentColor"
|
||||
d="M 178.224 72.09 c -0.296 -1.463 -0.627 -2.919 -0.996 -4.364 -0.293 -1.151 -0.616 -2.293 -0.956 -3.433 -0.301 -1.008 -0.612 -2.014 -0.95 -3.012 -0.531 -1.578 -1.113 -3.142 -1.735 -4.694 -0.216 -0.54 -0.433 -1.082 -0.661 -1.618 -0.195 -0.462 -0.399 -0.917 -0.601 -1.375 -0.262 -0.591 -0.53 -1.177 -0.804 -1.762 -0.074 -0.159 -0.151 -0.315 -0.226 -0.474 -0.209 -0.441 -0.422 -0.881 -0.638 -1.318 -0.076 -0.154 -0.153 -0.306 -0.229 -0.459 -0.236 -0.471 -0.477 -0.939 -0.721 -1.406 -0.053 -0.101 -0.105 -0.201 -0.158 -0.302 -1.143 -2.16 -2.367 -4.269 -3.68 -6.322 -0.116 -0.181 -0.237 -0.359 -0.355 -0.539 -0.094 -0.144 -0.189 -0.288 -0.284 -0.432 -0.284 -0.431 -0.57 -0.861 -0.862 -1.287 -0.112 -0.164 -0.225 -0.326 -0.338 -0.489 -0.193 -0.279 -0.382 -0.56 -0.579 -0.836 -0.089 -0.125 -0.182 -0.249 -0.273 -0.374 -0.13 -0.182 -0.264 -0.362 -0.395 -0.542 -0.277 -0.38 -0.556 -0.76 -0.838 -1.135 -0.15 -0.199 -0.303 -0.395 -0.454 -0.593 -0.21 -0.274 -0.417 -0.552 -0.63 -0.823 -0.055 -0.069 -0.111 -0.136 -0.166 -0.205 -0.482 -0.61 -0.971 -1.216 -1.47 -1.814 -0.129 -0.155 -0.262 -0.306 -0.392 -0.461 -0.402 -0.476 -0.808 -0.95 -1.22 -1.417 -0.186 -0.212 -0.375 -0.422 -0.563 -0.631 -0.384 -0.428 -0.773 -0.854 -1.167 -1.276 -0.176 -0.189 -0.351 -0.379 -0.529 -0.567 -0.564 -0.595 -1.134 -1.186 -1.716 -1.768 -1.091 -1.091 -2.207 -2.15 -3.346 -3.178 -1.016 -0.919 -2.05 -1.815 -3.103 -2.684 -0.772 -0.636 -1.557 -1.255 -2.348 -1.864 -3.465 -2.67 -7.112 -5.075 -10.927 -7.209 -2.869 -1.604 -5.83 -3.06 -8.883 -4.351 -2.443 -1.033 -4.922 -1.948 -7.428 -2.756 -8.879 -2.863 -18.13 -4.318 -27.605 -4.318 -3.19 0 -6.354 0.169 -9.488 0.496 -4.036 0.421 -8.019 1.114 -11.94 2.073 -1.732 0.423 -3.452 0.892 -5.157 1.42 -2.856 0.883 -5.673 1.912 -8.447 3.085 -2.645 1.118 -5.222 2.357 -7.729 3.711 -2.574 1.39 -5.073 2.901 -7.494 4.533 -1.195 0.805 -2.37 1.64 -3.527 2.503 -1.156 0.864 -2.292 1.756 -3.408 2.676 -0.553 0.456 -1.1 0.919 -1.643 1.389 -1.649 1.427 -3.252 2.92 -4.806 4.473 -2.582 2.582 -4.991 5.299 -7.222 8.138 -0.892 1.135 -1.756 2.292 -2.59 3.467 -0.417 0.588 -0.827 1.18 -1.23 1.778 -0.403 0.597 -0.798 1.199 -1.186 1.806 -0.388 0.607 -0.769 1.218 -1.143 1.835 -2.241 3.697 -4.216 7.562 -5.916 11.582 -1.095 2.589 -2.059 5.217 -2.901 7.877 -0.153 0.482 -0.3 0.965 -0.444 1.449 -0.339 1.14 -0.663 2.282 -0.956 3.433 -0.369 1.446 -0.7 2.901 -0.996 4.364 -1.034 5.121 -1.618 10.343 -1.749 15.637 -0.018 0.757 -0.028 1.514 -0.028 2.274 0 1.123 0.02 2.244 0.062 3.361 0.285 7.82 1.568 15.475 3.825 22.879 0.044 0.147 0.088 0.295 0.133 0.441 0.877 2.823 1.894 5.608 3.054 8.35 0.85 2.009 1.769 3.98 2.755 5.912 0.539 1.057 1.105 2.099 1.685 3.132 4.013 7.142 8.98 13.698 14.846 19.564 7.713 7.713 16.611 13.878 26.477 18.352 0.705 0.32 1.415 0.632 2.131 0.935 2.081 0.88 4.185 1.679 6.313 2.396 9.217 3.106 18.85 4.677 28.719 4.677 8.031 0 15.902 -1.047 23.522 -3.107 0.633 -0.172 1.266 -0.35 1.895 -0.535 0.757 -0.222 1.509 -0.456 2.26 -0.698 0.717 -0.232 1.431 -0.474 2.145 -0.723 1.752 -0.616 3.49 -1.281 5.211 -2.009 0.755 -0.319 1.503 -0.651 2.247 -0.989 1.237 -0.563 2.459 -1.15 3.664 -1.766 0.644 -0.328 1.283 -0.665 1.917 -1.009 1.654 -0.896 3.274 -1.848 4.865 -2.844 5.736 -3.591 11.06 -7.827 15.912 -12.679 0.775 -0.775 1.534 -1.562 2.278 -2.36 5.204 -5.59 9.636 -11.754 13.246 -18.417 0.343 -0.634 0.68 -1.274 1.009 -1.917 0.482 -0.944 0.943 -1.9 1.392 -2.863 0.471 -1.007 0.928 -2.021 1.364 -3.049 1.22 -2.886 2.281 -5.82 3.187 -8.793 0.559 -1.833 1.056 -3.68 1.494 -5.542 0.108 -0.458 0.211 -0.916 0.312 -1.376 0.194 -0.883 0.373 -1.77 0.539 -2.659 1.02 -5.455 1.542 -11.02 1.542 -16.663 0 -6.074 -0.595 -12.058 -1.776 -17.911 z m -161.733 19.614 c -1.118 -56.662 44.604 -74.877 60.998 -67.647 2.187 0.965 4.732 2.431 7.042 2.96 5.295 1.213 13.432 -3.113 13.521 6.273 0.078 8.156 -3.389 13.108 -10.797 16.177 -7.539 3.124 -14.777 9.181 -19.95 15.493 -21.487 26.216 -31.231 68.556 -7.565 94.296 -13.679 -5.545 -42.418 -25.467 -43.248 -67.552 z m 91.109 72.619 c -0.053 0.008 -4.171 0.775 -4.171 0.775 0 0 -15.862 -22.957 -23.509 -21.719 11.291 16.04 12.649 22.625 12.649 22.625 -0.053 0.001 -0.107 0.001 -0.161 0.003 -51.831 2.131 -42.785 -64.026 -28.246 -86.502 -1.555 13.073 8.878 39.992 39.034 44.1 9.495 1.293 32.302 -3.275 41.015 -11.38 0.098 1.825 0.163 3.85 0.159 6.013 -0.046 23.538 -13.47 42.743 -36.77 46.085 z m 30.575 -15.708 c 9.647 -9.263 12.869 -27.779 9.103 -44.137 -4.608 -20.011 -28.861 -32.383 -40.744 -35.564 5.766 -8.089 27.908 -14.274 39.567 5.363 -5.172 -10.519 -13.556 -23.023 -1.732 -33.128 12.411 13.329 19.411 29.94 20.161 48.7 0.75 18.753 -6.64 41.768 -26.355 58.765 z"
|
||||
/>
|
||||
<circle
|
||||
style="fill:#C8AF9B;"
|
||||
cx="256"
|
||||
cy="351.999"
|
||||
r="136"
|
||||
fill="currentColor"
|
||||
cx="71.927"
|
||||
cy="32.004"
|
||||
r="2.829"
|
||||
/>
|
||||
<g>
|
||||
<circle
|
||||
style="fill:#464655;"
|
||||
cx="132"
|
||||
cy="203.999"
|
||||
r="28"
|
||||
/>
|
||||
<circle
|
||||
style="fill:#464655;"
|
||||
cx="380"
|
||||
cy="203.999"
|
||||
r="28"
|
||||
/>
|
||||
<path
|
||||
style="fill:#464655;"
|
||||
d="M269.949,284.516c-7.672,10.741-20.227,10.741-27.899,0l-12.101-16.941
|
||||
c-7.672-10.741-3.15-19.53,10.05-19.53h32c13.2,0,17.723,8.788,10.05,19.53L269.949,284.516z"
|
||||
/>
|
||||
</g>
|
||||
<path
|
||||
style="fill:#AA968C;"
|
||||
d="M 350.964 399.998 C 316.628 399.998 299.021 351.998 255.882 351.998 C 212.742 351.998 195.135 399.998 160.801 399.998 C 145.395 399.998 131.723 394.147 120.621 374.798 C 131.595 439.03 187.893 487.998 255.881 487.998 C 323.868 487.998 380.168 439.03 391.14 374.798 C 380.04 394.148 366.368 399.998 350.964 399.998 Z"
|
||||
/>
|
||||
<g>
|
||||
<path
|
||||
style="fill:#8C7873;"
|
||||
d="M32,423.998c-3.172,0-6.18-1.906-7.43-5.031c-1.641-4.105,0.359-8.758,4.461-10.402l160.008-64
|
||||
c4.062-1.617,8.758,0.352,10.398,4.457s-0.359,8.758-4.461,10.402l-160.008,64C34,423.811,32.992,423.998,32,423.998z"
|
||||
/>
|
||||
<path
|
||||
style="fill:#8C7873;"
|
||||
d="M15.992,375.995c-3.547,0-6.781-2.375-7.727-5.965c-1.125-4.273,1.422-8.648,5.695-9.773l152-40
|
||||
c4.289-1.121,8.648,1.426,9.773,5.703c1.125,4.273-1.422,8.648-5.695,9.773l-152,40C17.351,375.913,16.672,375.995,15.992,375.995z
|
||||
"
|
||||
/>
|
||||
<path
|
||||
style="fill:#8C7873;"
|
||||
d="M7.992,335.995c-3.812,0-7.187-2.73-7.867-6.609c-0.773-4.352,2.133-8.5,6.484-9.27l136-24
|
||||
c4.328-0.77,8.508,2.141,9.266,6.488c0.773,4.352-2.133,8.5-6.484,9.27l-136,24C8.922,335.956,8.453,335.995,7.992,335.995z"
|
||||
/>
|
||||
<path
|
||||
style="fill:#8C7873;"
|
||||
d="M480,423.998c3.172,0,6.18-1.906,7.43-5.031c1.641-4.105-0.359-8.758-4.461-10.402l-160.008-64
|
||||
c-4.063-1.617-8.758,0.352-10.398,4.457s0.359,8.758,4.461,10.402l160.008,64C478,423.811,479.007,423.998,480,423.998z"
|
||||
/>
|
||||
<path
|
||||
style="fill:#8C7873;"
|
||||
d="M496.007,375.995c3.547,0,6.781-2.375,7.727-5.965c1.125-4.273-1.422-8.648-5.695-9.773l-152-40
|
||||
c-4.289-1.121-8.648,1.426-9.773,5.703c-1.125,4.273,1.422,8.648,5.695,9.773l152,40
|
||||
C494.648,375.913,495.328,375.995,496.007,375.995z"
|
||||
/>
|
||||
<path
|
||||
style="fill:#8C7873;"
|
||||
d="M504.007,335.995c3.813,0,7.188-2.73,7.867-6.609c0.773-4.352-2.133-8.5-6.484-9.27l-136-24
|
||||
c-4.328-0.77-8.508,2.141-9.266,6.488c-0.773,4.352,2.133,8.5,6.484,9.27l136,24C503.078,335.956,503.546,335.995,504.007,335.995z
|
||||
"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
isSelectMode () {
|
||||
return this.isSelectModeRef.value && !this.drawFieldType && this.editable && !this.drawField
|
||||
return this.isSelectModeRef.value && !this.drawFieldType && this.editable && !this.drawField && !this.drawCustomField
|
||||
},
|
||||
pageSelectedAreas () {
|
||||
if (!this.selectedAreasRef.value) return []
|
||||
|
||||
@@ -26,7 +26,7 @@ class SendTestWebhookRequestJob
|
||||
Addressable::URI.parse(webhook_url.url).normalize
|
||||
end
|
||||
|
||||
raise HttpsError, 'Only HTTPS is allowed.' if uri.scheme != 'https'
|
||||
raise HttpsError, 'Only HTTPS is allowed.' if uri.scheme != 'https' || [443, nil].exclude?(uri.port)
|
||||
raise LocalhostError, "Can't send to localhost." if uri.host.in?(SendWebhookRequest::LOCALHOSTS)
|
||||
end
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= ff.label :password, 'Password', class: 'label' %>
|
||||
<%= ff.password_field :password, value: value['password'], class: 'base-input' %>
|
||||
<%= ff.password_field :password, class: 'base-input', required: value['password'].present?, placeholder: value['password'].present? ? '*************' : '' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid md:grid-cols-2 gap-4">
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<% if params[:modal].present? %>
|
||||
<% url_params = Rails.application.routes.recognize_path(params[:modal], method: :get) %>
|
||||
<% if url_params[:action] == 'new' %>
|
||||
<open-modal src="<%= params[:modal] %>"></open-modal>
|
||||
<open-modal src="<%= url_for(url_params) %>"></open-modal>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<turbo-frame id="modal"></turbo-frame>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"id": "/",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/logo.svg",
|
||||
"src": "/favicon.svg",
|
||||
"type": "image/svg+xml",
|
||||
"sizes": "any"
|
||||
},
|
||||
|
||||
@@ -1,32 +1,4 @@
|
||||
<svg height="<%= local_assigns.fetch(:height, '37') %>" width="<%= local_assigns.fetch(:width, '37') %>" class="<%= local_assigns[:class] %>" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 511.998 511.998" xml:space="preserve">
|
||||
<path style="fill:#AA968C;" d="M503.999,247.999c0,128.13-111.033,240-248,240S8,376.129,8,247.999s111.033-224,248-224
|
||||
S503.999,119.869,503.999,247.999z" />
|
||||
<path style="fill:#AA968C;" d="M255.999,23.999C119.033,23.999,8,119.868,8,247.999c0,24.631,4.138,48.647,11.74,71.397
|
||||
c25.518,34.29,66.232,56.602,112.26,56.602c53.893,0,100.6-30.495,124-75.13c23.4,44.636,70.107,75.13,124,75.13
|
||||
c46.028,0,86.743-22.312,112.26-56.602c7.602-22.75,11.74-46.767,11.74-71.397C503.999,119.868,392.966,23.999,255.999,23.999z" />
|
||||
<circle style="fill:#C8AF9B;" cx="256" cy="351.999" r="136" />
|
||||
<g>
|
||||
<circle style="fill:#464655;" cx="132" cy="203.999" r="28" />
|
||||
<circle style="fill:#464655;" cx="380" cy="203.999" r="28" />
|
||||
<path style="fill:#464655;" d="M269.949,284.516c-7.672,10.741-20.227,10.741-27.899,0l-12.101-16.941
|
||||
c-7.672-10.741-3.15-19.53,10.05-19.53h32c13.2,0,17.723,8.788,10.05,19.53L269.949,284.516z" />
|
||||
</g>
|
||||
<path style="fill:#AA968C;" d="M 350.964 399.998 C 316.628 399.998 299.021 351.998 255.882 351.998 C 212.742 351.998 195.135 399.998 160.801 399.998 C 145.395 399.998 131.723 394.147 120.621 374.798 C 131.595 439.03 187.893 487.998 255.881 487.998 C 323.868 487.998 380.168 439.03 391.14 374.798 C 380.04 394.148 366.368 399.998 350.964 399.998 Z" />
|
||||
<g>
|
||||
<path style="fill:#8C7873;" d="M32,423.998c-3.172,0-6.18-1.906-7.43-5.031c-1.641-4.105,0.359-8.758,4.461-10.402l160.008-64
|
||||
c4.062-1.617,8.758,0.352,10.398,4.457s-0.359,8.758-4.461,10.402l-160.008,64C34,423.811,32.992,423.998,32,423.998z" />
|
||||
<path style="fill:#8C7873;" d="M15.992,375.995c-3.547,0-6.781-2.375-7.727-5.965c-1.125-4.273,1.422-8.648,5.695-9.773l152-40
|
||||
c4.289-1.121,8.648,1.426,9.773,5.703c1.125,4.273-1.422,8.648-5.695,9.773l-152,40C17.351,375.913,16.672,375.995,15.992,375.995z
|
||||
" />
|
||||
<path style="fill:#8C7873;" d="M7.992,335.995c-3.812,0-7.187-2.73-7.867-6.609c-0.773-4.352,2.133-8.5,6.484-9.27l136-24
|
||||
c4.328-0.77,8.508,2.141,9.266,6.488c0.773,4.352-2.133,8.5-6.484,9.27l-136,24C8.922,335.956,8.453,335.995,7.992,335.995z" />
|
||||
<path style="fill:#8C7873;" d="M480,423.998c3.172,0,6.18-1.906,7.43-5.031c1.641-4.105-0.359-8.758-4.461-10.402l-160.008-64
|
||||
c-4.063-1.617-8.758,0.352-10.398,4.457s0.359,8.758,4.461,10.402l160.008,64C478,423.811,479.007,423.998,480,423.998z" />
|
||||
<path style="fill:#8C7873;" d="M496.007,375.995c3.547,0,6.781-2.375,7.727-5.965c1.125-4.273-1.422-8.648-5.695-9.773l-152-40
|
||||
c-4.289-1.121-8.648,1.426-9.773,5.703c-1.125,4.273,1.422,8.648,5.695,9.773l152,40
|
||||
C494.648,375.913,495.328,375.995,496.007,375.995z" />
|
||||
<path style="fill:#8C7873;" d="M504.007,335.995c3.813,0,7.188-2.73,7.867-6.609c0.773-4.352-2.133-8.5-6.484-9.27l-136-24
|
||||
c-4.328-0.77-8.508,2.141-9.266,6.488c-0.773,4.352,2.133,8.5,6.484,9.27l136,24C503.078,335.956,503.546,335.995,504.007,335.995z
|
||||
" />
|
||||
</g>
|
||||
<svg class="<%= local_assigns[:class] %>" height="<%= local_assigns.fetch(:height, '37') %>" width="<%= local_assigns.fetch(:width, '37') %>" style="color: #e0753f" viewBox="0 0 180 180" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor" d="M 178.224 72.09 c -0.296 -1.463 -0.627 -2.919 -0.996 -4.364 -0.293 -1.151 -0.616 -2.293 -0.956 -3.433 -0.301 -1.008 -0.612 -2.014 -0.95 -3.012 -0.531 -1.578 -1.113 -3.142 -1.735 -4.694 -0.216 -0.54 -0.433 -1.082 -0.661 -1.618 -0.195 -0.462 -0.399 -0.917 -0.601 -1.375 -0.262 -0.591 -0.53 -1.177 -0.804 -1.762 -0.074 -0.159 -0.151 -0.315 -0.226 -0.474 -0.209 -0.441 -0.422 -0.881 -0.638 -1.318 -0.076 -0.154 -0.153 -0.306 -0.229 -0.459 -0.236 -0.471 -0.477 -0.939 -0.721 -1.406 -0.053 -0.101 -0.105 -0.201 -0.158 -0.302 -1.143 -2.16 -2.367 -4.269 -3.68 -6.322 -0.116 -0.181 -0.237 -0.359 -0.355 -0.539 -0.094 -0.144 -0.189 -0.288 -0.284 -0.432 -0.284 -0.431 -0.57 -0.861 -0.862 -1.287 -0.112 -0.164 -0.225 -0.326 -0.338 -0.489 -0.193 -0.279 -0.382 -0.56 -0.579 -0.836 -0.089 -0.125 -0.182 -0.249 -0.273 -0.374 -0.13 -0.182 -0.264 -0.362 -0.395 -0.542 -0.277 -0.38 -0.556 -0.76 -0.838 -1.135 -0.15 -0.199 -0.303 -0.395 -0.454 -0.593 -0.21 -0.274 -0.417 -0.552 -0.63 -0.823 -0.055 -0.069 -0.111 -0.136 -0.166 -0.205 -0.482 -0.61 -0.971 -1.216 -1.47 -1.814 -0.129 -0.155 -0.262 -0.306 -0.392 -0.461 -0.402 -0.476 -0.808 -0.95 -1.22 -1.417 -0.186 -0.212 -0.375 -0.422 -0.563 -0.631 -0.384 -0.428 -0.773 -0.854 -1.167 -1.276 -0.176 -0.189 -0.351 -0.379 -0.529 -0.567 -0.564 -0.595 -1.134 -1.186 -1.716 -1.768 -1.091 -1.091 -2.207 -2.15 -3.346 -3.178 -1.016 -0.919 -2.05 -1.815 -3.103 -2.684 -0.772 -0.636 -1.557 -1.255 -2.348 -1.864 -3.465 -2.67 -7.112 -5.075 -10.927 -7.209 -2.869 -1.604 -5.83 -3.06 -8.883 -4.351 -2.443 -1.033 -4.922 -1.948 -7.428 -2.756 -8.879 -2.863 -18.13 -4.318 -27.605 -4.318 -3.19 0 -6.354 0.169 -9.488 0.496 -4.036 0.421 -8.019 1.114 -11.94 2.073 -1.732 0.423 -3.452 0.892 -5.157 1.42 -2.856 0.883 -5.673 1.912 -8.447 3.085 -2.645 1.118 -5.222 2.357 -7.729 3.711 -2.574 1.39 -5.073 2.901 -7.494 4.533 -1.195 0.805 -2.37 1.64 -3.527 2.503 -1.156 0.864 -2.292 1.756 -3.408 2.676 -0.553 0.456 -1.1 0.919 -1.643 1.389 -1.649 1.427 -3.252 2.92 -4.806 4.473 -2.582 2.582 -4.991 5.299 -7.222 8.138 -0.892 1.135 -1.756 2.292 -2.59 3.467 -0.417 0.588 -0.827 1.18 -1.23 1.778 -0.403 0.597 -0.798 1.199 -1.186 1.806 -0.388 0.607 -0.769 1.218 -1.143 1.835 -2.241 3.697 -4.216 7.562 -5.916 11.582 -1.095 2.589 -2.059 5.217 -2.901 7.877 -0.153 0.482 -0.3 0.965 -0.444 1.449 -0.339 1.14 -0.663 2.282 -0.956 3.433 -0.369 1.446 -0.7 2.901 -0.996 4.364 -1.034 5.121 -1.618 10.343 -1.749 15.637 -0.018 0.757 -0.028 1.514 -0.028 2.274 0 1.123 0.02 2.244 0.062 3.361 0.285 7.82 1.568 15.475 3.825 22.879 0.044 0.147 0.088 0.295 0.133 0.441 0.877 2.823 1.894 5.608 3.054 8.35 0.85 2.009 1.769 3.98 2.755 5.912 0.539 1.057 1.105 2.099 1.685 3.132 4.013 7.142 8.98 13.698 14.846 19.564 7.713 7.713 16.611 13.878 26.477 18.352 0.705 0.32 1.415 0.632 2.131 0.935 2.081 0.88 4.185 1.679 6.313 2.396 9.217 3.106 18.85 4.677 28.719 4.677 8.031 0 15.902 -1.047 23.522 -3.107 0.633 -0.172 1.266 -0.35 1.895 -0.535 0.757 -0.222 1.509 -0.456 2.26 -0.698 0.717 -0.232 1.431 -0.474 2.145 -0.723 1.752 -0.616 3.49 -1.281 5.211 -2.009 0.755 -0.319 1.503 -0.651 2.247 -0.989 1.237 -0.563 2.459 -1.15 3.664 -1.766 0.644 -0.328 1.283 -0.665 1.917 -1.009 1.654 -0.896 3.274 -1.848 4.865 -2.844 5.736 -3.591 11.06 -7.827 15.912 -12.679 0.775 -0.775 1.534 -1.562 2.278 -2.36 5.204 -5.59 9.636 -11.754 13.246 -18.417 0.343 -0.634 0.68 -1.274 1.009 -1.917 0.482 -0.944 0.943 -1.9 1.392 -2.863 0.471 -1.007 0.928 -2.021 1.364 -3.049 1.22 -2.886 2.281 -5.82 3.187 -8.793 0.559 -1.833 1.056 -3.68 1.494 -5.542 0.108 -0.458 0.211 -0.916 0.312 -1.376 0.194 -0.883 0.373 -1.77 0.539 -2.659 1.02 -5.455 1.542 -11.02 1.542 -16.663 0 -6.074 -0.595 -12.058 -1.776 -17.911 z m -161.733 19.614 c -1.118 -56.662 44.604 -74.877 60.998 -67.647 2.187 0.965 4.732 2.431 7.042 2.96 5.295 1.213 13.432 -3.113 13.521 6.273 0.078 8.156 -3.389 13.108 -10.797 16.177 -7.539 3.124 -14.777 9.181 -19.95 15.493 -21.487 26.216 -31.231 68.556 -7.565 94.296 -13.679 -5.545 -42.418 -25.467 -43.248 -67.552 z m 91.109 72.619 c -0.053 0.008 -4.171 0.775 -4.171 0.775 0 0 -15.862 -22.957 -23.509 -21.719 11.291 16.04 12.649 22.625 12.649 22.625 -0.053 0.001 -0.107 0.001 -0.161 0.003 -51.831 2.131 -42.785 -64.026 -28.246 -86.502 -1.555 13.073 8.878 39.992 39.034 44.1 9.495 1.293 32.302 -3.275 41.015 -11.38 0.098 1.825 0.163 3.85 0.159 6.013 -0.046 23.538 -13.47 42.743 -36.77 46.085 z m 30.575 -15.708 c 9.647 -9.263 12.869 -27.779 9.103 -44.137 -4.608 -20.011 -28.861 -32.383 -40.744 -35.564 5.766 -8.089 27.908 -14.274 39.567 5.363 -5.172 -10.519 -13.556 -23.023 -1.732 -33.128 12.411 13.329 19.411 29.94 20.161 48.7 0.75 18.753 -6.64 41.768 -26.355 58.765 z" />
|
||||
<circle fill="currentColor" cx="71.927" cy="32.004" r="2.829" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 4.8 KiB |
@@ -27,4 +27,5 @@
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
||||
<meta name="theme-color" content="#faf7f5">
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<% end %>
|
||||
<% if params[:q].present? %>
|
||||
<div class="relative">
|
||||
<a href="<%= url_for(params.to_unsafe_h.except(:q)) %>" title="<%= t('clear') %>" class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-auto text-neutral text-2xl font-extralight">
|
||||
<a href="<%= url_for(params: request.query_parameters.except('q')) %>" title="<%= t('clear') %>" class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-auto text-neutral text-2xl font-extralight">
|
||||
×
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= fff.label :secret_access_key, class: 'label' %>
|
||||
<%= fff.password_field :secret_access_key, value: configs['secret_access_key'], required: true, class: 'base-input' %>
|
||||
<%= fff.password_field :secret_access_key, required: true, class: 'base-input', placeholder: configs['secret_access_key'].present? ? '*************' : '' %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid md:grid-cols-2 gap-4">
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= fff.label :storage_access_key, 'Storage Access Key', class: 'label' %>
|
||||
<%= fff.password_field :storage_access_key, value: configs['storage_access_key'], required: true, class: 'base-input' %>
|
||||
<%= fff.password_field :storage_access_key, required: true, class: 'base-input', placeholder: configs['storage_access_key'].present? ? '*************' : '' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</div>
|
||||
<div class="form-control">
|
||||
<%= fff.label :credentials, 'Credentials (JSON key content)', class: 'label' %>
|
||||
<%= fff.text_area :credentials, value: configs['credentials'], required: true, class: 'base-textarea w-full font-mono', rows: 4 %>
|
||||
<%= fff.text_area :credentials, required: true, class: 'base-textarea w-full font-mono', rows: 4, placeholder: configs['credentials'].present? ? "{\n**REDACTED**\n}" : '' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<% require_phone_2fa = @template.preferences['require_phone_2fa'] == true %>
|
||||
<% require_email_2fa = @template.preferences['require_email_2fa'] == true %>
|
||||
<% prefillable_fields = @template.fields.select { |f| f['prefillable'] } %>
|
||||
<% default_tab = cookies.permanent[:add_recipients_tab].presence || 'email' %>
|
||||
<% recipient_form_fields = Accounts.load_recipient_form_fields(current_account) if prefillable_fields.blank? %>
|
||||
<% only_detailed = require_phone_2fa || require_email_2fa || prefillable_fields.present? || recipient_form_fields.present? %>
|
||||
<%= render 'shared/turbo_modal_large', title: params[:selfsign] ? t('add_recipients') : t('add_new_recipients') do %>
|
||||
@@ -8,25 +9,25 @@
|
||||
<toggle-visible data-element-ids="<%= options.map(&:last).to_json %>" class="relative text-center px-2 mt-4 block">
|
||||
<div class="flex justify-center">
|
||||
<% options.each_with_index do |(label, value), index| %>
|
||||
<div>
|
||||
<%= radio_button_tag 'option', value, value == (only_detailed ? 'detailed' : 'email'), class: 'peer hidden', data: { action: 'change:toggle-visible#trigger' } %>
|
||||
<%= content_tag(value == 'list' ? 'span' : 'toggle-cookies', data: { value:, key: 'add_recipients_tab' }) do %>
|
||||
<%= radio_button_tag 'option', value, value == (only_detailed ? 'detailed' : default_tab), 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 %>
|
||||
</label>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</toggle-visible>
|
||||
<div class="px-5 mb-5 mt-4">
|
||||
<% unless only_detailed %>
|
||||
<div id="email">
|
||||
<div id="email" class="<%= 'hidden' if default_tab != 'email' %>">
|
||||
<%= render 'email_form', template: @template %>
|
||||
</div>
|
||||
<div id="phone" class="hidden">
|
||||
<div id="phone" class="<%= 'hidden' if default_tab != 'phone' %>">
|
||||
<%= render 'phone_form', template: @template %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div id="detailed" class="<%= 'hidden' unless only_detailed %>">
|
||||
<div id="detailed" class="<%= 'hidden' if !only_detailed && default_tab != 'detailed' %>">
|
||||
<%= render 'detailed_form', template: @template, require_phone_2fa:, require_email_2fa:, prefillable_fields:, recipient_form_fields: %>
|
||||
</div>
|
||||
<div id="list" class="hidden">
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% elsif @submission.submitters.to_a.size == 1 && !@submission.expired? && !@submission.submitters.to_a.first.declined_at? && !@submission.archived_at? %>
|
||||
<% elsif @submission.submitters.to_a.size == 1 && !@submission.expired? && !@submission.submitters.to_a.first.declined_at? && !@submission.archived_at? && !@submission.template&.archived_at? %>
|
||||
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: @submission.submitters.to_a.first.slug, host: form_link_host), class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: t('copy_share_link'), copied_title: t('copied_to_clipboard') %>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -159,7 +159,7 @@
|
||||
<%= (@submission.template_submitters || @submission.template.submitters).find { |e| e['uuid'] == submitter&.uuid }&.dig('name') || "#{(index + 1).ordinalize} Submitter" %>
|
||||
</span>
|
||||
</div>
|
||||
<% if signed_in? && can?(:update, @submission) && submitter && !submitter.completed_at? && !submitter.declined_at? && !@submission.archived_at? && !@submission.expired? && !submitter.start_form_submission_events.any? %>
|
||||
<% if signed_in? && can?(:update, @submission) && submitter && !submitter.completed_at? && !submitter.declined_at? && !@submission.archived_at? && !@submission.template&.archived_at? && !@submission.expired? && !submitter.start_form_submission_events.any? %>
|
||||
<span class="tooltip tooltip-left" data-tip="<%= t('edit') %>">
|
||||
<%= link_to edit_submitter_path(submitter), class: 'shrink-0 inline md:hidden md:group-hover:inline', data: { turbo_frame: 'modal' } do %>
|
||||
<%= svg_icon('pencil', class: 'w-5 h-5') %>
|
||||
@@ -225,15 +225,15 @@
|
||||
</span>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if signed_in? && submitter && submitter.email && !submitter.completed_at && !@submission.archived_at? && can?(:update, @submission) && Accounts.can_send_emails?(current_account) && !@submission.expired? && !submitter.declined_at? %>
|
||||
<% if signed_in? && submitter && submitter.email && !submitter.completed_at && !@submission.archived_at? && !@submission.template&.archived_at? && can?(:update, @submission) && Accounts.can_send_emails?(current_account) && !@submission.expired? && !submitter.declined_at? %>
|
||||
<div class="mt-2 mb-1">
|
||||
<%= button_to button_title(title: submitter.sent_at? ? t('re_send_email') : t('send_email'), disabled_with: t('sending')), submitter_send_email_index_path(submitter_slug: submitter.slug), class: 'btn btn-sm btn-primary w-full' %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if signed_in? && submitter && submitter.phone && !submitter.completed_at && !@submission.archived_at? && can?(:update, @submission) && !@submission.expired? && !submitter.declined_at? %>
|
||||
<% if signed_in? && submitter && submitter.phone && !submitter.completed_at && !@submission.archived_at? && !@submission.template&.archived_at? && can?(:update, @submission) && !@submission.expired? && !submitter.declined_at? %>
|
||||
<%= render 'submissions/send_sms_button', submitter: %>
|
||||
<% end %>
|
||||
<% if signed_in? && submitter && !submitter.completed_at? && !@submission.archived_at? && can?(:create, @submission) && !@submission.expired? && !submitter.declined_at? %>
|
||||
<% if signed_in? && submitter && !submitter.completed_at? && !@submission.archived_at? && !@submission.template&.archived_at? && can?(:create, @submission) && !@submission.expired? && !submitter.declined_at? %>
|
||||
<div class="mt-2 mb-1">
|
||||
<a class="btn btn-sm btn-primary w-full" target="_blank" href="<%= submit_form_path(slug: submitter.slug) %>">
|
||||
<%= t('sign_in_person') %>
|
||||
|
||||
@@ -35,19 +35,19 @@
|
||||
<% if is_show_tabs %>
|
||||
<div class="flex items-center flex-col md:flex-row md:flex-wrap gap-2 mb-4">
|
||||
<div class="flex items-center md:items-end flex-col md:flex-row gap-2 w-full md:w-fit">
|
||||
<a href="<%= url_for(params.to_unsafe_h.except(:status)) %>" class="<%= params[:status].blank? ? 'border-neutral-700' : 'border-neutral-300' %> flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-48 hover:border-neutral-600">
|
||||
<a href="<%= url_for(params: request.query_parameters.except('status')) %>" class="<%= params[:status].blank? ? 'border-neutral-700' : 'border-neutral-300' %> flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-48 hover:border-neutral-600">
|
||||
<div class="flex items-center space-x-1">
|
||||
<%= svg_icon('list', class: 'w-5 h-5') %>
|
||||
<span class="font-normal"><%= t('all') %></span>
|
||||
</div>
|
||||
</a>
|
||||
<a href="<%= url_for(params.to_unsafe_h.merge(status: :pending)) %>" class="<%= params[:status] == 'pending' ? 'border-neutral-700' : 'border-neutral-300' %> flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-48 hover:border-neutral-600">
|
||||
<a href="<%= url_for(params: request.query_parameters.merge('status' => 'pending')) %>" class="<%= params[:status] == 'pending' ? 'border-neutral-700' : 'border-neutral-300' %> flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-48 hover:border-neutral-600">
|
||||
<div class="flex items-center space-x-1">
|
||||
<%= svg_icon('clock', class: 'w-5 h-5') %>
|
||||
<span class="font-normal"><%= t('pending') %></span>
|
||||
</div>
|
||||
</a>
|
||||
<a href="<%= url_for(params.to_unsafe_h.merge(status: :completed)) %>" class="<%= params[:status] == 'completed' ? 'border-neutral-700' : 'border-neutral-300' %> flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-48 hover:border-neutral-600">
|
||||
<a href="<%= url_for(params: request.query_parameters.merge('status' => 'completed')) %>" class="<%= params[:status] == 'completed' ? 'border-neutral-700' : 'border-neutral-300' %> flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-48 hover:border-neutral-600">
|
||||
<div class="flex items-center space-x-1">
|
||||
<%= svg_icon('circle_check', class: 'w-5 h-5') %>
|
||||
<span class="font-normal"><%= t('completed') %></span>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<%= svg_icon(icon, class: 'w-5 h-5 shrink-0') %>
|
||||
<span class="font-normal truncate"><%= t(params[:status]) %></span>
|
||||
<% end %>
|
||||
<%= link_to url_for(params.to_unsafe_h.except(:status)), class: 'rounded-lg ml-1 hover:bg-base-content hover:text-white' do %>
|
||||
<%= link_to url_for(params: request.query_parameters.except('status')), class: 'rounded-lg ml-1 hover:bg-base-content hover:text-white' do %>
|
||||
<%= svg_icon('x', class: 'w-5 h-5') %>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -16,7 +16,7 @@
|
||||
<%= 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 %>
|
||||
<%= link_to url_for(params: request.query_parameters.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>
|
||||
@@ -27,7 +27,7 @@
|
||||
<%= svg_icon('user', class: 'w-5 h-5 shrink-0') %>
|
||||
<span class="font-normal truncate"><%= current_account.users.accessible_by(current_ability).where(account: current_account).find_by(email: params[:author])&.full_name || 'NA' %></span>
|
||||
<% end %>
|
||||
<%= link_to url_for(params.to_unsafe_h.except(:author)), class: 'rounded-lg ml-1 hover:bg-base-content hover:text-white' do %>
|
||||
<%= link_to url_for(params: request.query_parameters.except('author')), class: 'rounded-lg ml-1 hover:bg-base-content hover:text-white' do %>
|
||||
<%= svg_icon('x', class: 'w-5 h-5') %>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -46,7 +46,7 @@
|
||||
<% end %>
|
||||
</span>
|
||||
<% end %>
|
||||
<%= link_to url_for(params.to_unsafe_h.except(:completed_at_from, :completed_at_to)), class: 'rounded-lg ml-1 hover:bg-base-content hover:text-white' do %>
|
||||
<%= link_to url_for(params: request.query_parameters.except('completed_at_from', 'completed_at_to')), class: 'rounded-lg ml-1 hover:bg-base-content hover:text-white' do %>
|
||||
<%= svg_icon('x', class: 'w-5 h-5') %>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -65,7 +65,7 @@
|
||||
<% end %>
|
||||
</span>
|
||||
<% end %>
|
||||
<%= link_to url_for(params.to_unsafe_h.except(:created_at_to, :created_at_from)), class: 'rounded-lg ml-1 hover:bg-base-content hover:text-white' do %>
|
||||
<%= link_to url_for(params: request.query_parameters.except('created_at_to', 'created_at_from')), class: 'rounded-lg ml-1 hover:bg-base-content hover:text-white' do %>
|
||||
<%= svg_icon('x', class: 'w-5 h-5') %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<% if params[:with_remove] %>
|
||||
<div class="text-center w-full mt-4">
|
||||
<%= link_to t('remove_filter'), "#{params[:path]}?#{params.to_unsafe_h.slice(:q).merge(local_assigns[:default_params]).to_query}", class: 'link', data: { turbo_frame: :_top } %>
|
||||
<%= link_to t('remove_filter'), "#{params[:path]}?#{request.query_parameters.slice('q').merge(local_assigns[:default_params]).to_query}", class: 'link', data: { turbo_frame: :_top } %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<% if is_show_tabs %>
|
||||
<div class="flex items-center flex-col md:flex-row md:flex-wrap gap-2 mb-4">
|
||||
<div class="flex items-center md:items-end flex-col md:flex-row gap-2 w-full md:w-fit">
|
||||
<a href="<%= url_for(params.to_unsafe_h.except(:status)) %>" class="<%= params[:status].blank? ? 'border-neutral-700' : 'border-neutral-300' %> flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-48 hover:border-neutral-700">
|
||||
<a href="<%= url_for(params: request.query_parameters.except('status')) %>" class="<%= params[:status].blank? ? 'border-neutral-700' : 'border-neutral-300' %> flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-48 hover:border-neutral-700">
|
||||
<div class="flex items-center space-x-1">
|
||||
<%= svg_icon('list', class: 'w-5 h-5') %>
|
||||
<span class="font-normal"><%= t('all') %></span>
|
||||
@@ -41,7 +41,7 @@
|
||||
</div>
|
||||
<% end %>
|
||||
</a>
|
||||
<a href="<%= url_for(params.to_unsafe_h.merge(status: :pending)) %>" class="<%= params[:status] == 'pending' ? 'border-neutral-700' : 'border-neutral-300' %> flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-48 hover:border-neutral-700">
|
||||
<a href="<%= url_for(params: request.query_parameters.merge('status' => 'pending')) %>" class="<%= params[:status] == 'pending' ? 'border-neutral-700' : 'border-neutral-300' %> flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-48 hover:border-neutral-700">
|
||||
<div class="flex items-center space-x-1">
|
||||
<%= svg_icon('clock', class: 'w-5 h-5') %>
|
||||
<span class="font-normal"><%= t('pending') %></span>
|
||||
@@ -52,7 +52,7 @@
|
||||
</div>
|
||||
<% end %>
|
||||
</a>
|
||||
<a href="<%= url_for(params.to_unsafe_h.merge(status: :completed)) %>" class="<%= params[:status] == 'completed' ? 'border-neutral-700' : 'border-neutral-300' %> flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-48 hover:border-neutral-700">
|
||||
<a href="<%= url_for(params: request.query_parameters.merge('status' => 'completed')) %>" class="<%= params[:status] == 'completed' ? 'border-neutral-700' : 'border-neutral-300' %> flex h-10 px-2 py-1 text-lg items-center justify-between border text-center text-neutral font-semibold rounded-xl w-full md:w-48 hover:border-neutral-700">
|
||||
<div class="flex items-center space-x-1">
|
||||
<%= svg_icon('circle_check', class: 'w-5 h-5') %>
|
||||
<span class="font-normal"><%= t('completed') %></span>
|
||||
|
||||
@@ -85,9 +85,9 @@
|
||||
<div class="mt-6">
|
||||
<h2 id="log" class="text-3xl font-bold"><%= t('events_log') %></h2>
|
||||
<div class="tabs border-b mt-4">
|
||||
<%= link_to t('all'), url_for(params.to_unsafe_h.except(:status)), 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.to_unsafe_h.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('failed'), url_for(params.to_unsafe_h.merge(status: 'error')), style: 'margin-bottom: -1px', class: "tab h-10 text-base #{params[:status] == 'error' ? 'tab-active tab-bordered' : 'pb-[3px]'}" %>
|
||||
<%= link_to t('all'), url_for(params: request.query_parameters.except('status')), 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.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('failed'), url_for(params: request.query_parameters.merge('status' => 'error')), style: 'margin-bottom: -1px', class: "tab h-10 text-base #{params[:status] == 'error' ? 'tab-active tab-bordered' : 'pb-[3px]'}" %>
|
||||
</div>
|
||||
<% if @webhook_events.present? %>
|
||||
<div class="divide-y divide-base-300 rounded-lg">
|
||||
|
||||
@@ -64,6 +64,16 @@ module HexaPDF
|
||||
end
|
||||
end
|
||||
|
||||
# fix NoMethodError: undefined method `stream' for an instance of Symbol
|
||||
class TextField
|
||||
def field_value
|
||||
return unless value[:V]
|
||||
return self[:V].to_s if self[:V].is_a?(Symbol)
|
||||
|
||||
self[:V].is_a?(String) ? self[:V] : self[:V].stream
|
||||
end
|
||||
end
|
||||
|
||||
class AppearanceGenerator
|
||||
def create_push_button_appearances
|
||||
nil
|
||||
|
||||
@@ -336,7 +336,7 @@ en: &en
|
||||
two_factor_authentication: Two-Factor Authentication
|
||||
2fa_is_not_configured: 2FA is not configured
|
||||
set_up_2fa: Set up 2FA
|
||||
contact_information_has_been_update: Contact information has been update.
|
||||
contact_information_has_been_update: Contact information has been updated.
|
||||
password_has_been_changed: Password has been changed.
|
||||
email_integration: Email Integration
|
||||
send_via_connected_email: Send via connected email
|
||||
|
||||
@@ -56,7 +56,7 @@ Rails.application.routes.draw do
|
||||
resources :account_custom_fields, only: %i[create]
|
||||
resources :user_configs, only: %i[create]
|
||||
resources :encrypted_user_configs, only: %i[destroy]
|
||||
resources :timestamp_server, only: %i[create]
|
||||
resources :timestamp_server, only: %i[create] unless Docuseal.multitenant?
|
||||
resources :dashboard, only: %i[index]
|
||||
resources :setup, only: %i[index create]
|
||||
resource :newsletter, only: %i[show update]
|
||||
|
||||
@@ -35,16 +35,16 @@ module DownloadUtils
|
||||
|
||||
module_function
|
||||
|
||||
def call(url)
|
||||
def call(url, validate: Docuseal.multitenant?)
|
||||
uri = begin
|
||||
URI(url)
|
||||
rescue URI::Error
|
||||
Addressable::URI.parse(url).normalize
|
||||
end
|
||||
|
||||
validate_uri!(uri) if Docuseal.multitenant?
|
||||
validate_uri!(uri) if validate
|
||||
|
||||
resp = conn.get(uri)
|
||||
resp = conn(validate:).get(uri)
|
||||
|
||||
raise UnableToDownload, "Error loading: #{uri}" if resp.status >= 400
|
||||
|
||||
@@ -52,14 +52,15 @@ module DownloadUtils
|
||||
end
|
||||
|
||||
def validate_uri!(uri)
|
||||
raise UnableToDownload, "Error loading: #{uri}. Only HTTPS is allowed." if uri.scheme != 'https'
|
||||
raise UnableToDownload, "Error loading: #{uri}. Only HTTPS is allowed." if uri.scheme != 'https' ||
|
||||
[443, nil].exclude?(uri.port)
|
||||
raise UnableToDownload, "Error loading: #{uri}. Can't download from localhost." if uri.host.in?(LOCALHOSTS)
|
||||
end
|
||||
|
||||
def conn
|
||||
def conn(validate: Docuseal.multitenant?)
|
||||
Faraday.new do |faraday|
|
||||
faraday.response :follow_redirects, callback: lambda { |_, new_env|
|
||||
validate_uri!(new_env[:url]) if Docuseal.multitenant?
|
||||
validate_uri!(new_env[:url]) if validate
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -20,10 +20,6 @@ module PdfIcons
|
||||
StringIO.new(logo_data)
|
||||
end
|
||||
|
||||
def logo_new_io
|
||||
StringIO.new(logo_new_data)
|
||||
end
|
||||
|
||||
def stamp_logo_io
|
||||
StringIO.new(stamp_logo_data)
|
||||
end
|
||||
@@ -40,10 +36,6 @@ module PdfIcons
|
||||
@logo_data ||= PATH.join('logo.png').read
|
||||
end
|
||||
|
||||
def logo_new_data
|
||||
@logo_new_data ||= PATH.join('logo_new.png').read
|
||||
end
|
||||
|
||||
def stamp_logo_data
|
||||
@stamp_logo_data ||= PATH.join('stamp-logo.png').read
|
||||
end
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 14 KiB |
@@ -22,7 +22,7 @@ module SendWebhookRequest
|
||||
end
|
||||
|
||||
if Docuseal.multitenant?
|
||||
raise HttpsError, 'Only HTTPS is allowed.' if uri.scheme != 'https' &&
|
||||
raise HttpsError, 'Only HTTPS is allowed.' if (uri.scheme != 'https' || [443, nil].exclude?(uri.port)) &&
|
||||
!AccountConfig.exists?(key: :allow_http,
|
||||
account_id: webhook_url.account_id)
|
||||
raise LocalhostError, "Can't send to localhost." if uri.host.in?(LOCALHOSTS)
|
||||
@@ -43,7 +43,7 @@ module SendWebhookRequest
|
||||
data: data
|
||||
}.to_json
|
||||
|
||||
req.options.read_timeout = 8
|
||||
req.options.read_timeout = 15
|
||||
req.options.open_timeout = 8
|
||||
end
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@ module Submissions
|
||||
def plain_search(submissions, keyword, search_values: false, search_template: false)
|
||||
return submissions if keyword.blank?
|
||||
|
||||
term = "%#{keyword.downcase}%"
|
||||
sanitized = ActiveRecord::Base.sanitize_sql_like(keyword.downcase)
|
||||
term = "%#{sanitized}%"
|
||||
|
||||
arel_table = Submitter.arel_table
|
||||
|
||||
@@ -31,7 +32,7 @@ module Submissions
|
||||
if search_template
|
||||
submissions = submissions.left_joins(:template)
|
||||
|
||||
arel = arel.or(Template.arel_table[:name].lower.matches("%#{keyword.downcase}%"))
|
||||
arel = arel.or(Template.arel_table[:name].lower.matches("%#{sanitized}%"))
|
||||
end
|
||||
|
||||
submissions.joins(:submitters).where(arel).group(:id)
|
||||
|
||||
@@ -162,7 +162,7 @@ module Submissions
|
||||
|
||||
pdf.trailer.info[:DocumentID] = document_id
|
||||
pdf.pages.each do |page|
|
||||
font_size = (([page.box.width, page.box.height].min / A4_SIZE[0].to_f) * 9).to_i
|
||||
font_size = [(([page.box.width, page.box.height].min / A4_SIZE[0].to_f) * 9).to_i, 4].max
|
||||
cnv = page.canvas(type: :overlay)
|
||||
|
||||
text =
|
||||
|
||||
@@ -14,6 +14,7 @@ module Submitters
|
||||
UnableToSendCode = Class.new(StandardError)
|
||||
InvalidOtp = Class.new(StandardError)
|
||||
MaliciousFileExtension = Class.new(StandardError)
|
||||
ArgumentError = Class.new(StandardError)
|
||||
|
||||
DANGEROUS_EXTENSIONS = Set.new(%w[
|
||||
exe com bat cmd scr pif vbs vbe js jse wsf wsh msi msp
|
||||
@@ -133,7 +134,7 @@ module Submitters
|
||||
filename: file.original_filename,
|
||||
content_type: file.content_type)
|
||||
else
|
||||
ActiveStorage::Blob.find_signed(params[:blob_signed_id])
|
||||
raise ArgumentError, 'file param is missing'
|
||||
end
|
||||
|
||||
ActiveStorage::Attachment.create!(
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Submitters
|
||||
module AuthorizedForForm
|
||||
Unauthorized = Class.new(StandardError)
|
||||
|
||||
module_function
|
||||
|
||||
def call(submitter, current_user, request)
|
||||
pass_email_2fa?(submitter, request) && pass_link_2fa?(submitter, current_user, request)
|
||||
end
|
||||
|
||||
def pass_email_2fa?(submitter, request)
|
||||
return false unless submitter
|
||||
|
||||
return true if submitter.submission.template&.preferences&.dig('require_email_2fa') != true &&
|
||||
submitter.preferences['require_email_2fa'] != true
|
||||
return true if request.cookie_jar.encrypted[:email_2fa_slug] == submitter.slug
|
||||
|
||||
token = request.params[:two_factor_token].presence || request.headers['x-two-factor-token'].presence
|
||||
|
||||
return true if token.present? &&
|
||||
Submitter.signed_id_verifier.verified(token, purpose: :email_two_factor) == submitter.slug
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
def pass_link_2fa?(submitter, current_user, request)
|
||||
return false unless submitter
|
||||
|
||||
return true if submitter.submission.source != 'link'
|
||||
return true unless submitter.submission.template&.preferences&.dig('shared_link_2fa') == true
|
||||
return true if request.cookie_jar.encrypted[:email_2fa_slug] == submitter.slug
|
||||
return true if submitter.email == current_user&.email && current_user&.account_id == submitter.account_id
|
||||
|
||||
if (token = request.params[:two_factor_token].presence || request.headers['x-two-factor-token'].presence)
|
||||
link_2fa_key = [submitter.email.downcase.squish, submitter.submission.template.slug].join(':')
|
||||
|
||||
return true if Submitter.signed_id_verifier.verified(token, purpose: :email_two_factor) == link_2fa_key
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -236,7 +236,7 @@ module Submitters
|
||||
|
||||
return blob if blob
|
||||
|
||||
data = DownloadUtils.call(url).body
|
||||
data = DownloadUtils.call(url, validate: true).body
|
||||
|
||||
checksum = Digest::MD5.base64digest(data)
|
||||
|
||||
|
||||
@@ -20,7 +20,9 @@ module TemplateFolders
|
||||
def search(folders, keyword)
|
||||
return folders if keyword.blank?
|
||||
|
||||
folders.where(TemplateFolder.arel_table[:name].lower.matches("%#{keyword.downcase}%"))
|
||||
sanitized = ActiveRecord::Base.sanitize_sql_like(keyword.downcase)
|
||||
|
||||
folders.where(TemplateFolder.arel_table[:name].lower.matches("%#{sanitized}%"))
|
||||
end
|
||||
|
||||
def filter_active_folders(template_folders, templates)
|
||||
|
||||
@@ -52,7 +52,9 @@ module Templates
|
||||
def plain_search(templates, keyword)
|
||||
return templates if keyword.blank?
|
||||
|
||||
templates.where(Template.arel_table[:name].lower.matches("%#{keyword.downcase}%"))
|
||||
sanitized = ActiveRecord::Base.sanitize_sql_like(keyword.downcase)
|
||||
|
||||
templates.where(Template.arel_table[:name].lower.matches("%#{sanitized}%"))
|
||||
end
|
||||
|
||||
def fulltext_search(current_user, templates, keyword)
|
||||
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 807 B |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,5 @@
|
||||
<svg height="180" width="180" viewBox="0 0 180 180" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle fill="white" cx="90" cy="90" r="88"/>
|
||||
<path fill="#e0753f" d="M 178.224 72.09 c -0.296 -1.463 -0.627 -2.919 -0.996 -4.364 -0.293 -1.151 -0.616 -2.293 -0.956 -3.433 -0.301 -1.008 -0.612 -2.014 -0.95 -3.012 -0.531 -1.578 -1.113 -3.142 -1.735 -4.694 -0.216 -0.54 -0.433 -1.082 -0.661 -1.618 -0.195 -0.462 -0.399 -0.917 -0.601 -1.375 -0.262 -0.591 -0.53 -1.177 -0.804 -1.762 -0.074 -0.159 -0.151 -0.315 -0.226 -0.474 -0.209 -0.441 -0.422 -0.881 -0.638 -1.318 -0.076 -0.154 -0.153 -0.306 -0.229 -0.459 -0.236 -0.471 -0.477 -0.939 -0.721 -1.406 -0.053 -0.101 -0.105 -0.201 -0.158 -0.302 -1.143 -2.16 -2.367 -4.269 -3.68 -6.322 -0.116 -0.181 -0.237 -0.359 -0.355 -0.539 -0.094 -0.144 -0.189 -0.288 -0.284 -0.432 -0.284 -0.431 -0.57 -0.861 -0.862 -1.287 -0.112 -0.164 -0.225 -0.326 -0.338 -0.489 -0.193 -0.279 -0.382 -0.56 -0.579 -0.836 -0.089 -0.125 -0.182 -0.249 -0.273 -0.374 -0.13 -0.182 -0.264 -0.362 -0.395 -0.542 -0.277 -0.38 -0.556 -0.76 -0.838 -1.135 -0.15 -0.199 -0.303 -0.395 -0.454 -0.593 -0.21 -0.274 -0.417 -0.552 -0.63 -0.823 -0.055 -0.069 -0.111 -0.136 -0.166 -0.205 -0.482 -0.61 -0.971 -1.216 -1.47 -1.814 -0.129 -0.155 -0.262 -0.306 -0.392 -0.461 -0.402 -0.476 -0.808 -0.95 -1.22 -1.417 -0.186 -0.212 -0.375 -0.422 -0.563 -0.631 -0.384 -0.428 -0.773 -0.854 -1.167 -1.276 -0.176 -0.189 -0.351 -0.379 -0.529 -0.567 -0.564 -0.595 -1.134 -1.186 -1.716 -1.768 -1.091 -1.091 -2.207 -2.15 -3.346 -3.178 -1.016 -0.919 -2.05 -1.815 -3.103 -2.684 -0.772 -0.636 -1.557 -1.255 -2.348 -1.864 -3.465 -2.67 -7.112 -5.075 -10.927 -7.209 -2.869 -1.604 -5.83 -3.06 -8.883 -4.351 -2.443 -1.033 -4.922 -1.948 -7.428 -2.756 -8.879 -2.863 -18.13 -4.318 -27.605 -4.318 -3.19 0 -6.354 0.169 -9.488 0.496 -4.036 0.421 -8.019 1.114 -11.94 2.073 -1.732 0.423 -3.452 0.892 -5.157 1.42 -2.856 0.883 -5.673 1.912 -8.447 3.085 -2.645 1.118 -5.222 2.357 -7.729 3.711 -2.574 1.39 -5.073 2.901 -7.494 4.533 -1.195 0.805 -2.37 1.64 -3.527 2.503 -1.156 0.864 -2.292 1.756 -3.408 2.676 -0.553 0.456 -1.1 0.919 -1.643 1.389 -1.649 1.427 -3.252 2.92 -4.806 4.473 -2.582 2.582 -4.991 5.299 -7.222 8.138 -0.892 1.135 -1.756 2.292 -2.59 3.467 -0.417 0.588 -0.827 1.18 -1.23 1.778 -0.403 0.597 -0.798 1.199 -1.186 1.806 -0.388 0.607 -0.769 1.218 -1.143 1.835 -2.241 3.697 -4.216 7.562 -5.916 11.582 -1.095 2.589 -2.059 5.217 -2.901 7.877 -0.153 0.482 -0.3 0.965 -0.444 1.449 -0.339 1.14 -0.663 2.282 -0.956 3.433 -0.369 1.446 -0.7 2.901 -0.996 4.364 -1.034 5.121 -1.618 10.343 -1.749 15.637 -0.018 0.757 -0.028 1.514 -0.028 2.274 0 1.123 0.02 2.244 0.062 3.361 0.285 7.82 1.568 15.475 3.825 22.879 0.044 0.147 0.088 0.295 0.133 0.441 0.877 2.823 1.894 5.608 3.054 8.35 0.85 2.009 1.769 3.98 2.755 5.912 0.539 1.057 1.105 2.099 1.685 3.132 4.013 7.142 8.98 13.698 14.846 19.564 7.713 7.713 16.611 13.878 26.477 18.352 0.705 0.32 1.415 0.632 2.131 0.935 2.081 0.88 4.185 1.679 6.313 2.396 9.217 3.106 18.85 4.677 28.719 4.677 8.031 0 15.902 -1.047 23.522 -3.107 0.633 -0.172 1.266 -0.35 1.895 -0.535 0.757 -0.222 1.509 -0.456 2.26 -0.698 0.717 -0.232 1.431 -0.474 2.145 -0.723 1.752 -0.616 3.49 -1.281 5.211 -2.009 0.755 -0.319 1.503 -0.651 2.247 -0.989 1.237 -0.563 2.459 -1.15 3.664 -1.766 0.644 -0.328 1.283 -0.665 1.917 -1.009 1.654 -0.896 3.274 -1.848 4.865 -2.844 5.736 -3.591 11.06 -7.827 15.912 -12.679 0.775 -0.775 1.534 -1.562 2.278 -2.36 5.204 -5.59 9.636 -11.754 13.246 -18.417 0.343 -0.634 0.68 -1.274 1.009 -1.917 0.482 -0.944 0.943 -1.9 1.392 -2.863 0.471 -1.007 0.928 -2.021 1.364 -3.049 1.22 -2.886 2.281 -5.82 3.187 -8.793 0.559 -1.833 1.056 -3.68 1.494 -5.542 0.108 -0.458 0.211 -0.916 0.312 -1.376 0.194 -0.883 0.373 -1.77 0.539 -2.659 1.02 -5.455 1.542 -11.02 1.542 -16.663 0 -6.074 -0.595 -12.058 -1.776 -17.911 z m -161.733 19.614 c -1.118 -56.662 44.604 -74.877 60.998 -67.647 2.187 0.965 4.732 2.431 7.042 2.96 5.295 1.213 13.432 -3.113 13.521 6.273 0.078 8.156 -3.389 13.108 -10.797 16.177 -7.539 3.124 -14.777 9.181 -19.95 15.493 -21.487 26.216 -31.231 68.556 -7.565 94.296 -13.679 -5.545 -42.418 -25.467 -43.248 -67.552 z m 91.109 72.619 c -0.053 0.008 -4.171 0.775 -4.171 0.775 0 0 -15.862 -22.957 -23.509 -21.719 11.291 16.04 12.649 22.625 12.649 22.625 -0.053 0.001 -0.107 0.001 -0.161 0.003 -51.831 2.131 -42.785 -64.026 -28.246 -86.502 -1.555 13.073 8.878 39.992 39.034 44.1 9.495 1.293 32.302 -3.275 41.015 -11.38 0.098 1.825 0.163 3.85 0.159 6.013 -0.046 23.538 -13.47 42.743 -36.77 46.085 z m 30.575 -15.708 c 9.647 -9.263 12.869 -27.779 9.103 -44.137 -4.608 -20.011 -28.861 -32.383 -40.744 -35.564 5.766 -8.089 27.908 -14.274 39.567 5.363 -5.172 -10.519 -13.556 -23.023 -1.732 -33.128 12.411 13.329 19.411 29.94 20.161 48.7 0.75 18.753 -6.64 41.768 -26.355 58.765 z"/>
|
||||
<circle fill="#e0753f" cx="71.927" cy="32.004" r="2.829"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
@@ -1,32 +1,4 @@
|
||||
<svg height="40" width="40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 511.998 511.998" xml:space="preserve">
|
||||
<path style="fill:#AA968C;" d="M503.999,247.999c0,128.13-111.033,240-248,240S8,376.129,8,247.999s111.033-224,248-224
|
||||
S503.999,119.869,503.999,247.999z" />
|
||||
<path style="fill:#AA968C;" d="M255.999,23.999C119.033,23.999,8,119.868,8,247.999c0,24.631,4.138,48.647,11.74,71.397
|
||||
c25.518,34.29,66.232,56.602,112.26,56.602c53.893,0,100.6-30.495,124-75.13c23.4,44.636,70.107,75.13,124,75.13
|
||||
c46.028,0,86.743-22.312,112.26-56.602c7.602-22.75,11.74-46.767,11.74-71.397C503.999,119.868,392.966,23.999,255.999,23.999z" />
|
||||
<circle style="fill:#C8AF9B;" cx="256" cy="351.999" r="136" />
|
||||
<g>
|
||||
<circle style="fill:#464655;" cx="132" cy="203.999" r="28" />
|
||||
<circle style="fill:#464655;" cx="380" cy="203.999" r="28" />
|
||||
<path style="fill:#464655;" d="M269.949,284.516c-7.672,10.741-20.227,10.741-27.899,0l-12.101-16.941
|
||||
c-7.672-10.741-3.15-19.53,10.05-19.53h32c13.2,0,17.723,8.788,10.05,19.53L269.949,284.516z" />
|
||||
</g>
|
||||
<path style="fill:#AA968C;" d="M 350.964 399.998 C 316.628 399.998 299.021 351.998 255.882 351.998 C 212.742 351.998 195.135 399.998 160.801 399.998 C 145.395 399.998 131.723 394.147 120.621 374.798 C 131.595 439.03 187.893 487.998 255.881 487.998 C 323.868 487.998 380.168 439.03 391.14 374.798 C 380.04 394.148 366.368 399.998 350.964 399.998 Z" />
|
||||
<g>
|
||||
<path style="fill:#8C7873;" d="M32,423.998c-3.172,0-6.18-1.906-7.43-5.031c-1.641-4.105,0.359-8.758,4.461-10.402l160.008-64
|
||||
c4.062-1.617,8.758,0.352,10.398,4.457s-0.359,8.758-4.461,10.402l-160.008,64C34,423.811,32.992,423.998,32,423.998z" />
|
||||
<path style="fill:#8C7873;" d="M15.992,375.995c-3.547,0-6.781-2.375-7.727-5.965c-1.125-4.273,1.422-8.648,5.695-9.773l152-40
|
||||
c4.289-1.121,8.648,1.426,9.773,5.703c1.125,4.273-1.422,8.648-5.695,9.773l-152,40C17.351,375.913,16.672,375.995,15.992,375.995z
|
||||
" />
|
||||
<path style="fill:#8C7873;" d="M7.992,335.995c-3.812,0-7.187-2.73-7.867-6.609c-0.773-4.352,2.133-8.5,6.484-9.27l136-24
|
||||
c4.328-0.77,8.508,2.141,9.266,6.488c0.773,4.352-2.133,8.5-6.484,9.27l-136,24C8.922,335.956,8.453,335.995,7.992,335.995z" />
|
||||
<path style="fill:#8C7873;" d="M480,423.998c3.172,0,6.18-1.906,7.43-5.031c1.641-4.105-0.359-8.758-4.461-10.402l-160.008-64
|
||||
c-4.063-1.617-8.758,0.352-10.398,4.457s0.359,8.758,4.461,10.402l160.008,64C478,423.811,479.007,423.998,480,423.998z" />
|
||||
<path style="fill:#8C7873;" d="M496.007,375.995c3.547,0,6.781-2.375,7.727-5.965c1.125-4.273-1.422-8.648-5.695-9.773l-152-40
|
||||
c-4.289-1.121-8.648,1.426-9.773,5.703c-1.125,4.273,1.422,8.648,5.695,9.773l152,40
|
||||
C494.648,375.913,495.328,375.995,496.007,375.995z" />
|
||||
<path style="fill:#8C7873;" d="M504.007,335.995c3.813,0,7.188-2.73,7.867-6.609c0.773-4.352-2.133-8.5-6.484-9.27l-136-24
|
||||
c-4.328-0.77-8.508,2.141-9.266,6.488c-0.773,4.352,2.133,8.5,6.484,9.27l136,24C503.078,335.956,503.546,335.995,504.007,335.995z
|
||||
" />
|
||||
</g>
|
||||
<svg height="180" width="180" style="color: #e0753f" viewBox="0 0 180 180" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="currentColor" d="M 178.224 72.09 c -0.296 -1.463 -0.627 -2.919 -0.996 -4.364 -0.293 -1.151 -0.616 -2.293 -0.956 -3.433 -0.301 -1.008 -0.612 -2.014 -0.95 -3.012 -0.531 -1.578 -1.113 -3.142 -1.735 -4.694 -0.216 -0.54 -0.433 -1.082 -0.661 -1.618 -0.195 -0.462 -0.399 -0.917 -0.601 -1.375 -0.262 -0.591 -0.53 -1.177 -0.804 -1.762 -0.074 -0.159 -0.151 -0.315 -0.226 -0.474 -0.209 -0.441 -0.422 -0.881 -0.638 -1.318 -0.076 -0.154 -0.153 -0.306 -0.229 -0.459 -0.236 -0.471 -0.477 -0.939 -0.721 -1.406 -0.053 -0.101 -0.105 -0.201 -0.158 -0.302 -1.143 -2.16 -2.367 -4.269 -3.68 -6.322 -0.116 -0.181 -0.237 -0.359 -0.355 -0.539 -0.094 -0.144 -0.189 -0.288 -0.284 -0.432 -0.284 -0.431 -0.57 -0.861 -0.862 -1.287 -0.112 -0.164 -0.225 -0.326 -0.338 -0.489 -0.193 -0.279 -0.382 -0.56 -0.579 -0.836 -0.089 -0.125 -0.182 -0.249 -0.273 -0.374 -0.13 -0.182 -0.264 -0.362 -0.395 -0.542 -0.277 -0.38 -0.556 -0.76 -0.838 -1.135 -0.15 -0.199 -0.303 -0.395 -0.454 -0.593 -0.21 -0.274 -0.417 -0.552 -0.63 -0.823 -0.055 -0.069 -0.111 -0.136 -0.166 -0.205 -0.482 -0.61 -0.971 -1.216 -1.47 -1.814 -0.129 -0.155 -0.262 -0.306 -0.392 -0.461 -0.402 -0.476 -0.808 -0.95 -1.22 -1.417 -0.186 -0.212 -0.375 -0.422 -0.563 -0.631 -0.384 -0.428 -0.773 -0.854 -1.167 -1.276 -0.176 -0.189 -0.351 -0.379 -0.529 -0.567 -0.564 -0.595 -1.134 -1.186 -1.716 -1.768 -1.091 -1.091 -2.207 -2.15 -3.346 -3.178 -1.016 -0.919 -2.05 -1.815 -3.103 -2.684 -0.772 -0.636 -1.557 -1.255 -2.348 -1.864 -3.465 -2.67 -7.112 -5.075 -10.927 -7.209 -2.869 -1.604 -5.83 -3.06 -8.883 -4.351 -2.443 -1.033 -4.922 -1.948 -7.428 -2.756 -8.879 -2.863 -18.13 -4.318 -27.605 -4.318 -3.19 0 -6.354 0.169 -9.488 0.496 -4.036 0.421 -8.019 1.114 -11.94 2.073 -1.732 0.423 -3.452 0.892 -5.157 1.42 -2.856 0.883 -5.673 1.912 -8.447 3.085 -2.645 1.118 -5.222 2.357 -7.729 3.711 -2.574 1.39 -5.073 2.901 -7.494 4.533 -1.195 0.805 -2.37 1.64 -3.527 2.503 -1.156 0.864 -2.292 1.756 -3.408 2.676 -0.553 0.456 -1.1 0.919 -1.643 1.389 -1.649 1.427 -3.252 2.92 -4.806 4.473 -2.582 2.582 -4.991 5.299 -7.222 8.138 -0.892 1.135 -1.756 2.292 -2.59 3.467 -0.417 0.588 -0.827 1.18 -1.23 1.778 -0.403 0.597 -0.798 1.199 -1.186 1.806 -0.388 0.607 -0.769 1.218 -1.143 1.835 -2.241 3.697 -4.216 7.562 -5.916 11.582 -1.095 2.589 -2.059 5.217 -2.901 7.877 -0.153 0.482 -0.3 0.965 -0.444 1.449 -0.339 1.14 -0.663 2.282 -0.956 3.433 -0.369 1.446 -0.7 2.901 -0.996 4.364 -1.034 5.121 -1.618 10.343 -1.749 15.637 -0.018 0.757 -0.028 1.514 -0.028 2.274 0 1.123 0.02 2.244 0.062 3.361 0.285 7.82 1.568 15.475 3.825 22.879 0.044 0.147 0.088 0.295 0.133 0.441 0.877 2.823 1.894 5.608 3.054 8.35 0.85 2.009 1.769 3.98 2.755 5.912 0.539 1.057 1.105 2.099 1.685 3.132 4.013 7.142 8.98 13.698 14.846 19.564 7.713 7.713 16.611 13.878 26.477 18.352 0.705 0.32 1.415 0.632 2.131 0.935 2.081 0.88 4.185 1.679 6.313 2.396 9.217 3.106 18.85 4.677 28.719 4.677 8.031 0 15.902 -1.047 23.522 -3.107 0.633 -0.172 1.266 -0.35 1.895 -0.535 0.757 -0.222 1.509 -0.456 2.26 -0.698 0.717 -0.232 1.431 -0.474 2.145 -0.723 1.752 -0.616 3.49 -1.281 5.211 -2.009 0.755 -0.319 1.503 -0.651 2.247 -0.989 1.237 -0.563 2.459 -1.15 3.664 -1.766 0.644 -0.328 1.283 -0.665 1.917 -1.009 1.654 -0.896 3.274 -1.848 4.865 -2.844 5.736 -3.591 11.06 -7.827 15.912 -12.679 0.775 -0.775 1.534 -1.562 2.278 -2.36 5.204 -5.59 9.636 -11.754 13.246 -18.417 0.343 -0.634 0.68 -1.274 1.009 -1.917 0.482 -0.944 0.943 -1.9 1.392 -2.863 0.471 -1.007 0.928 -2.021 1.364 -3.049 1.22 -2.886 2.281 -5.82 3.187 -8.793 0.559 -1.833 1.056 -3.68 1.494 -5.542 0.108 -0.458 0.211 -0.916 0.312 -1.376 0.194 -0.883 0.373 -1.77 0.539 -2.659 1.02 -5.455 1.542 -11.02 1.542 -16.663 0 -6.074 -0.595 -12.058 -1.776 -17.911 z m -161.733 19.614 c -1.118 -56.662 44.604 -74.877 60.998 -67.647 2.187 0.965 4.732 2.431 7.042 2.96 5.295 1.213 13.432 -3.113 13.521 6.273 0.078 8.156 -3.389 13.108 -10.797 16.177 -7.539 3.124 -14.777 9.181 -19.95 15.493 -21.487 26.216 -31.231 68.556 -7.565 94.296 -13.679 -5.545 -42.418 -25.467 -43.248 -67.552 z m 91.109 72.619 c -0.053 0.008 -4.171 0.775 -4.171 0.775 0 0 -15.862 -22.957 -23.509 -21.719 11.291 16.04 12.649 22.625 12.649 22.625 -0.053 0.001 -0.107 0.001 -0.161 0.003 -51.831 2.131 -42.785 -64.026 -28.246 -86.502 -1.555 13.073 8.878 39.992 39.034 44.1 9.495 1.293 32.302 -3.275 41.015 -11.38 0.098 1.825 0.163 3.85 0.159 6.013 -0.046 23.538 -13.47 42.743 -36.77 46.085 z m 30.575 -15.708 c 9.647 -9.263 12.869 -27.779 9.103 -44.137 -4.608 -20.011 -28.861 -32.383 -40.744 -35.564 5.766 -8.089 27.908 -14.274 39.567 5.363 -5.172 -10.519 -13.556 -23.023 -1.732 -33.128 12.411 13.329 19.411 29.94 20.161 48.7 0.75 18.753 -6.64 41.768 -26.355 58.765 z"/>
|
||||
<circle fill="currentColor" cx="71.927" cy="32.004" r="2.829"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 4.7 KiB |
@@ -16,6 +16,10 @@ RSpec.describe SendFormCompletedWebhookRequestJob do
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
around do |example|
|
||||
freeze_time { example.run }
|
||||
end
|
||||
|
||||
before do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 200)
|
||||
end
|
||||
|
||||
@@ -16,6 +16,10 @@ RSpec.describe SendFormDeclinedWebhookRequestJob do
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
around do |example|
|
||||
freeze_time { example.run }
|
||||
end
|
||||
|
||||
before do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 200)
|
||||
end
|
||||
|
||||
@@ -16,6 +16,10 @@ RSpec.describe SendFormStartedWebhookRequestJob do
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
around do |example|
|
||||
freeze_time { example.run }
|
||||
end
|
||||
|
||||
before do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 200)
|
||||
end
|
||||
|
||||
@@ -16,6 +16,10 @@ RSpec.describe SendFormViewedWebhookRequestJob do
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
around do |example|
|
||||
freeze_time { example.run }
|
||||
end
|
||||
|
||||
before do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 200)
|
||||
end
|
||||
|
||||
@@ -13,6 +13,10 @@ RSpec.describe SendSubmissionCompletedWebhookRequestJob do
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
around do |example|
|
||||
freeze_time { example.run }
|
||||
end
|
||||
|
||||
before do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 200)
|
||||
end
|
||||
|
||||
@@ -13,6 +13,10 @@ RSpec.describe SendSubmissionCreatedWebhookRequestJob do
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
around do |example|
|
||||
freeze_time { example.run }
|
||||
end
|
||||
|
||||
before do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 200)
|
||||
end
|
||||
|
||||
@@ -13,6 +13,10 @@ RSpec.describe SendSubmissionExpiredWebhookRequestJob do
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
around do |example|
|
||||
freeze_time { example.run }
|
||||
end
|
||||
|
||||
before do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 200)
|
||||
end
|
||||
|
||||
@@ -12,6 +12,10 @@ RSpec.describe SendTemplateCreatedWebhookRequestJob do
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
around do |example|
|
||||
freeze_time { example.run }
|
||||
end
|
||||
|
||||
before do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 200)
|
||||
end
|
||||
|
||||
@@ -12,6 +12,10 @@ RSpec.describe SendTemplateUpdatedWebhookRequestJob do
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
around do |example|
|
||||
freeze_time { example.run }
|
||||
end
|
||||
|
||||
before do
|
||||
stub_request(:post, webhook_url.url).to_return(status: 200)
|
||||
end
|
||||
|
||||
@@ -54,6 +54,7 @@ RSpec.configure do |config|
|
||||
config.include FactoryBot::Syntax::Methods
|
||||
config.include Devise::Test::IntegrationHelpers
|
||||
config.include SigningFormHelper
|
||||
config.include ActiveSupport::Testing::TimeHelpers
|
||||
|
||||
config.before(:each, type: :system) do
|
||||
if ENV['HEADLESS'] == 'false'
|
||||
|
||||
@@ -61,7 +61,6 @@ RSpec.describe 'Email Settings' do
|
||||
expect(page).to have_field('Host', with: encrypted_config.value['host'])
|
||||
expect(page).to have_field('Port', with: encrypted_config.value['port'])
|
||||
expect(page).to have_field('Username', with: encrypted_config.value['username'])
|
||||
expect(page).to have_field('Password', with: encrypted_config.value['password'])
|
||||
expect(page).to have_field('Domain', with: encrypted_config.value['domain'])
|
||||
expect(page).to have_select('Authentication', selected: 'Plain')
|
||||
expect(page).to have_field('Send from Email', with: encrypted_config.value['from_email'])
|
||||
|
||||