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 +1255,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 +1272,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 +1347,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
@@ -1475,7 +1500,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 +1508,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 +1518,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 +1562,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) {
diff --git a/app/javascript/submission_form/initials_step.vue b/app/javascript/submission_form/initials_step.vue
index 2dede0e4..8e1cc1b5 100644
--- a/app/javascript/submission_form/initials_step.vue
+++ b/app/javascript/submission_form/initials_step.vue
@@ -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) {
diff --git a/app/javascript/submission_form/signature_step.vue b/app/javascript/submission_form/signature_step.vue
index 91937ec9..ef5ba45c 100644
--- a/app/javascript/submission_form/signature_step.vue
+++ b/app/javascript/submission_form/signature_step.vue
@@ -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()
diff --git a/app/javascript/template_builder/logo.vue b/app/javascript/template_builder/logo.vue
index 31621d60..8f878e14 100644
--- a/app/javascript/template_builder/logo.vue
+++ b/app/javascript/template_builder/logo.vue
@@ -2,87 +2,20 @@
diff --git a/app/views/shared/_logo.html.erb b/app/views/shared/_logo.html.erb
index d97d9913..ce505b8f 100644
--- a/app/views/shared/_logo.html.erb
+++ b/app/views/shared/_logo.html.erb
@@ -1,32 +1,4 @@
-