improve accessibility

pull/636/head
Pete Matsyburka 3 weeks ago committed by Pete Matsyburka
parent 0af6ccf35f
commit ee65a5693c

@ -5,6 +5,12 @@ export default targetable(class extends HTMLElement {
connectedCallback () { connectedCallback () {
this.addEventListener('click', () => this.downloadFiles()) this.addEventListener('click', () => this.downloadFiles())
this.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
this.downloadFiles()
}
})
} }
toggleState () { toggleState () {

@ -0,0 +1,18 @@
export default class extends HTMLElement {
connectedCallback () {
const dialog = document.getElementById(this.dataset.target)
this.querySelector('button').addEventListener('click', () => {
if (dialog) {
dialog.inert = false
dialog.showModal()
}
})
if (dialog) {
dialog.addEventListener('close', () => {
dialog.inert = true
})
}
}
}

@ -47,11 +47,13 @@ export default class extends HTMLElement {
this.classList.remove('hidden', '-translate-y-10', 'opacity-0') this.classList.remove('hidden', '-translate-y-10', 'opacity-0')
this.classList.add('translate-y-0', 'opacity-100') this.classList.add('translate-y-0', 'opacity-100')
this.querySelectorAll('[tabindex]').forEach((el) => { el.tabIndex = 0 })
} }
hideButtons () { hideButtons () {
this.classList.remove('translate-y-0', 'opacity-100') this.classList.remove('translate-y-0', 'opacity-100')
this.classList.add('-translate-y-10', 'opacity-0') this.classList.add('-translate-y-10', 'opacity-0')
this.querySelectorAll('[tabindex]').forEach((el) => { el.tabIndex = -1 })
setTimeout(() => { setTimeout(() => {
if (this.classList.contains('-translate-y-10')) { if (this.classList.contains('-translate-y-10')) {

@ -7,6 +7,7 @@ import FetchForm from './elements/fetch_form'
import ScrollButtons from './elements/scroll_buttons' import ScrollButtons from './elements/scroll_buttons'
import PageContainer from './elements/page_container' import PageContainer from './elements/page_container'
import SubmitForm from './elements/submit_form' import SubmitForm from './elements/submit_form'
import ModalButton from './elements/modal_button'
const safeRegisterElement = (name, element, options = {}) => !window.customElements.get(name) && window.customElements.define(name, element, options) const safeRegisterElement = (name, element, options = {}) => !window.customElements.get(name) && window.customElements.define(name, element, options)
@ -16,6 +17,7 @@ safeRegisterElement('fetch-form', FetchForm)
safeRegisterElement('scroll-buttons', ScrollButtons) safeRegisterElement('scroll-buttons', ScrollButtons)
safeRegisterElement('page-container', PageContainer) safeRegisterElement('page-container', PageContainer)
safeRegisterElement('submit-form', SubmitForm) safeRegisterElement('submit-form', SubmitForm)
safeRegisterElement('modal-button', ModalButton)
safeRegisterElement('submission-form', class extends HTMLElement { safeRegisterElement('submission-form', class extends HTMLElement {
connectedCallback () { connectedCallback () {
this.appElem = document.createElement('div') this.appElem = document.createElement('div')

@ -1,9 +1,14 @@
<template> <template>
<div <div
class="flex absolute lg:text-base -outline-offset-1 field-area" class="flex absolute lg:text-base -outline-offset-1 focus-visible:outline-blue-500 focus-visible:outline-2 focus-visible:outline field-area"
dir="auto" dir="auto"
:style="[computedStyle, fontStyle]" :style="[computedStyle, fontStyle]"
:class="{ 'cursor-default': !submittable, 'border border-red-100 bg-red-100 cursor-pointer': submittable, 'border border-red-100': !isActive && submittable, 'bg-opacity-80': !isActive && !isValueSet && submittable, 'outline-red-500 outline-dashed outline-2 z-10 field-area-active': isActive && submittable, 'bg-opacity-40': (isActive || isValueSet) && submittable }" :class="{ 'cursor-default': !submittable, 'border border-red-100 bg-red-100 cursor-pointer': submittable, 'border border-red-100': !isActive && submittable, 'bg-opacity-80': !isActive && !isValueSet && submittable, 'outline-red-500 outline-dashed outline-2 z-10 field-area-active': isActive && submittable, 'bg-opacity-40': (isActive || isValueSet) && submittable }"
:role="submittable && field.type !== 'checkbox' && field.type !== 'radio' && field.type !== 'multiple' ? 'button' : undefined"
:tabindex="submittable ? 0 : undefined"
:aria-label="submittable ? fieldAreaLabel : undefined"
@keydown.enter.prevent="submittable ? $el.click() : undefined"
@keydown.space.prevent="submittable ? $el.click() : undefined"
> >
<div <div
v-if="(!withFieldPlaceholder || !field.name || field.type === 'cells') && !isActive && !isValueSet && field.type !== 'checkbox' && submittable && !area.option_uuid" v-if="(!withFieldPlaceholder || !field.name || field.type === 'cells') && !isActive && !isValueSet && field.type !== 'checkbox' && submittable && !area.option_uuid"
@ -129,6 +134,7 @@
v-if="submittable" v-if="submittable"
type="checkbox" type="checkbox"
:value="false" :value="false"
:aria-label="field.name || fieldNames[field.type]"
class="aspect-square base-checkbox" class="aspect-square base-checkbox"
:class="{ '!w-auto !h-full': area.w > area.h, '!w-full !h-auto': area.w <= area.h }" :class="{ '!w-auto !h-full': area.w > area.h, '!w-full !h-auto': area.w <= area.h }"
:checked="!!modelValue" :checked="!!modelValue"
@ -149,6 +155,7 @@
v-if="submittable" v-if="submittable"
type="radio" type="radio"
:value="false" :value="false"
:aria-label="optionValue(option)"
class="aspect-square checked:checkbox checked:checkbox-xs" class="aspect-square checked:checkbox checked:checkbox-xs"
:class="{ 'base-radio': !modelValue || modelValue !== optionValue(option), '!w-auto !h-full': area.w > area.h, '!w-full !h-auto': area.w <= area.h }" :class="{ 'base-radio': !modelValue || modelValue !== optionValue(option), '!w-auto !h-full': area.w > area.h, '!w-full !h-auto': area.w <= area.h }"
:checked="!!modelValue && modelValue === optionValue(option)" :checked="!!modelValue && modelValue === optionValue(option)"
@ -169,6 +176,7 @@
v-if="submittable" v-if="submittable"
type="checkbox" type="checkbox"
:value="false" :value="false"
:aria-label="optionValue(option)"
class="aspect-square base-checkbox" class="aspect-square base-checkbox"
:class="{ '!w-auto !h-full': area.w > area.h, '!w-full !h-auto': area.w <= area.h }" :class="{ '!w-auto !h-full': area.w > area.h, '!w-full !h-auto': area.w <= area.h }"
:checked="!!modelValue && modelValue.includes(optionValue(option))" :checked="!!modelValue && modelValue.includes(optionValue(option))"
@ -400,6 +408,13 @@ export default {
kba: this.t('kba') kba: this.t('kba')
} }
}, },
fieldAreaLabel () {
const name = this.field.name || this.fieldNames[this.field.type] || this.field.type
if (this.area.option_uuid && this.option) {
return `${name} - ${this.optionValue(this.option)}`
}
return name
},
strikethroughWidth () { strikethroughWidth () {
if (this.isInlineSize) { if (this.isInlineSize) {
return '0.6cqmin' return '0.6cqmin'

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<div v-if="value.length"> <ul v-if="value.length" :aria-label="t('uploaded_files')" class="list-none p-0 m-0">
<div <li
v-for="(val, index) in value" v-for="(val, index) in value"
:key="index" :key="index"
class="flex mb-2" class="flex mb-2"
@ -21,22 +21,26 @@
:width="16" :width="16"
class="flex-none" class="flex-none"
:heigh="16" :heigh="16"
aria-hidden="true"
/> />
<span> <span>
{{ attachmentsIndex[val].filename }} {{ attachmentsIndex[val].filename }}
</span> </span>
</a> </a>
<button <button
type="button"
class="remove-attachment-button" class="remove-attachment-button"
:aria-label="`${t('clear')} ${attachmentsIndex[val].filename}`"
@click.prevent="removeAttachment(val)" @click.prevent="removeAttachment(val)"
> >
<IconTrashX <IconTrashX
:width="18" :width="18"
:heigh="19" :heigh="19"
aria-hidden="true"
/> />
</button> </button>
</div> </li>
</div> </ul>
<template v-else> <template v-else>
<input <input
value="" value=""

@ -3,6 +3,9 @@
id="form_completed" id="form_completed"
class="mx-auto max-w-md flex flex-col completed-form" class="mx-auto max-w-md flex flex-col completed-form"
dir="auto" dir="auto"
role="status"
aria-live="assertive"
tabindex="-1"
> >
<div class="font-medium text-2xl flex items-center space-x-1.5 mx-auto"> <div class="font-medium text-2xl flex items-center space-x-1.5 mx-auto">
<IconCircleCheck <IconCircleCheck
@ -42,6 +45,7 @@
<IconInnerShadowTop <IconInnerShadowTop
v-if="isSendingCopy" v-if="isSendingCopy"
class="animate-spin" class="animate-spin"
aria-hidden="true"
/> />
<IconMail v-else /> <IconMail v-else />
<span> <span>
@ -57,6 +61,7 @@
<IconInnerShadowTop <IconInnerShadowTop
v-if="isDownloading" v-if="isDownloading"
class="animate-spin" class="animate-spin"
aria-hidden="true"
/> />
<IconDownload v-else /> <IconDownload v-else />
<span> <span>
@ -199,7 +204,7 @@ export default {
}) })
} }
document.querySelectorAll('#decline_button').forEach((button) => { document.querySelectorAll('#decline_button, #decline_button_mobile, #delegate_button, #delegate_button_mobile').forEach((button) => {
button.setAttribute('disabled', 'true') button.setAttribute('disabled', 'true')
}) })
}, },

@ -30,12 +30,13 @@
class="btn btn-outline btn-sm !normal-case font-normal set-current-date-button" class="btn btn-outline btn-sm !normal-case font-normal set-current-date-button"
@click.prevent="[setCurrentDate(), $emit('focus')]" @click.prevent="[setCurrentDate(), $emit('focus')]"
> >
<IconCalendarCheck :width="16" /> <IconCalendarCheck :width="16" aria-hidden="true" />
{{ t('set_today') }} {{ t('set_today') }}
</button> </button>
</div> </div>
<div <div
v-if="field.description" v-if="field.description"
:id="field.uuid + '-desc'"
class="mb-3 px-1 field-description-text" class="mb-3 px-1 field-description-text"
dir="auto" dir="auto"
> >
@ -51,6 +52,7 @@
:max="validationMax" :max="validationMax"
class="base-input !text-2xl text-center w-full" class="base-input !text-2xl text-center w-full"
:required="field.required" :required="field.required"
:aria-describedby="field.description ? field.uuid + '-desc' : undefined"
type="date" type="date"
:name="`values[${field.uuid}]`" :name="`values[${field.uuid}]`"
@keydown.enter="onEnter" @keydown.enter="onEnter"

@ -39,8 +39,9 @@
ref="input" ref="input"
:multiple="multiple" :multiple="multiple"
:accept="accept" :accept="accept"
:aria-label="message"
type="file" type="file"
class="hidden" class="sr-only"
@change="onSelectFiles" @change="onSelectFiles"
> >
</label> </label>

@ -57,6 +57,7 @@
<IconInnerShadowTop <IconInnerShadowTop
v-if="isSubmittingComplete" v-if="isSubmittingComplete"
class="mr-1 animate-spin w-5 h-5" class="mr-1 animate-spin w-5 h-5"
aria-hidden="true"
/> />
<span> <span>
{{ t('complete') }} {{ t('complete') }}
@ -88,6 +89,7 @@
class="absolute right-0 mr-4" class="absolute right-0 mr-4"
:width="20" :width="20"
:height="20" :height="20"
aria-hidden="true"
/> />
</button> </button>
<div <div
@ -103,11 +105,13 @@
class="absolute right-0 top-0 minimize-form-button" class="absolute right-0 top-0 minimize-form-button"
:class="currentField?.description?.length > 100 ? 'mr-1 mt-1 md:mr-2 md:mt-2': 'mr-2 mt-2 hidden md:block'" :class="currentField?.description?.length > 100 ? 'mr-1 mt-1 md:mr-2 md:mt-2': 'mr-2 mt-2 hidden md:block'"
:title="t('minimize')" :title="t('minimize')"
:aria-label="t('minimize')"
@click.prevent="minimizeForm" @click.prevent="minimizeForm"
> >
<IconArrowsDiagonalMinimize2 <IconArrowsDiagonalMinimize2
:width="20" :width="20"
:height="20" :height="20"
aria-hidden="true"
/> />
</button> </button>
<div <div
@ -193,6 +197,7 @@
/> />
<div <div
v-if="currentField.description" v-if="currentField.description"
:id="currentField.uuid + '-desc'"
dir="auto" dir="auto"
class="mb-3 px-1 field-description-text" class="mb-3 px-1 field-description-text"
> >
@ -203,6 +208,7 @@
:id="currentField.uuid" :id="currentField.uuid"
dir="auto" dir="auto"
:required="currentField.required" :required="currentField.required"
:aria-describedby="currentField.description ? currentField.uuid + '-desc' : undefined"
class="select base-input !text-2xl w-full text-center font-normal" class="select base-input !text-2xl w-full text-center font-normal"
:class="{ 'text-gray-300': !values[currentField.uuid] }" :class="{ 'text-gray-300': !values[currentField.uuid] }"
:name="`values[${currentField.uuid}]`" :name="`values[${currentField.uuid}]`"
@ -250,6 +256,7 @@
</label> </label>
<div <div
v-if="currentField.description" v-if="currentField.description"
:id="currentField.uuid + '-desc'"
dir="auto" dir="auto"
class="mb-3 px-1 field-description-text" class="mb-3 px-1 field-description-text"
> >
@ -309,6 +316,7 @@
> >
<div <div
v-if="currentField.description" v-if="currentField.description"
:id="currentField.uuid + '-desc'"
dir="auto" dir="auto"
class="mb-3 px-1 field-description-text" class="mb-3 px-1 field-description-text"
> >
@ -511,6 +519,7 @@
<IconInnerShadowTop <IconInnerShadowTop
v-if="isSubmitting" v-if="isSubmitting"
class="mr-1 animate-spin" class="mr-1 animate-spin"
aria-hidden="true"
/> />
<span> <span>
{{ submitButtonText }} {{ submitButtonText }}
@ -522,6 +531,7 @@
</button> </button>
<div <div
v-if="showFillAllRequiredFields" v-if="showFillAllRequiredFields"
role="alert"
class="text-center mt-1" class="text-center mt-1"
> >
{{ t('please_fill_all_required_fields') }} {{ t('please_fill_all_required_fields') }}
@ -554,8 +564,9 @@
:can-send-email="canSendEmail && !!submitter.email" :can-send-email="canSendEmail && !!submitter.email"
:submitter-slug="submitterSlug" :submitter-slug="submitterSlug"
/> />
<div <nav
v-if="stepFields.length < 80" v-if="stepFields.length < 80"
:aria-label="t('form_progress')"
class="flex justify-center mt-3 sm:mt-4 mb-0 sm:mb-1 select-none" 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"> <div class="flex items-center flex-wrap steps-progress">
@ -563,16 +574,18 @@
v-for="(step, index) in stepFields" v-for="(step, index) in stepFields"
:key="step[0].uuid" :key="step[0].uuid"
> >
<a <button
v-if="!onlyRequiredFields || step.some((f) => f.required)" v-if="!onlyRequiredFields || step.some((f) => f.required)"
href="#" type="button"
class="inline border border-base-300 h-3 w-3 rounded-full mx-1 mt-1" :aria-label="`${t('step')} ${index + 1}`"
:aria-current="index === currentStep ? 'step' : undefined"
class="inline border border-base-300 h-3 w-3 rounded-full mx-1 mt-1 p-0"
: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 }" :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)]" @click="isCompleted ? '' : [saveStep(), goToStep(index, true)]"
/> />
</template> </template>
</div> </div>
</div> </nav>
<div <div
v-else v-else
class="mt-5" class="mt-5"
@ -1458,7 +1471,7 @@ export default {
} }
this.enableScrollIntoField = false this.enableScrollIntoField = false
this.$refs.form.querySelector('input[type="date"], input[type="number"], input[type="text"], select')?.focus() this.$refs.form.querySelector('input[type="date"], input[type="number"], input[type="text"], input[type="tel"], textarea, select')?.focus()
this.enableScrollIntoField = true this.enableScrollIntoField = true
if (clickUpload && !this.values[this.currentField.uuid] && ['file', 'image'].includes(this.currentField.type)) { if (clickUpload && !this.values[this.currentField.uuid] && ['file', 'image'].includes(this.currentField.type)) {
@ -1629,6 +1642,15 @@ export default {
if (this.completedRedirectUrl) { if (this.completedRedirectUrl) {
window.location.href = sanitizeUrl(this.completedRedirectUrl) window.location.href = sanitizeUrl(this.completedRedirectUrl)
} else {
this.$nextTick(() => {
const root = this.$root.$el.parentNode.getRootNode()
const completedEl = root.getElementById('form_completed')
if (completedEl) {
completedEl.focus()
}
})
} }
} }
} }

@ -1,4 +1,10 @@
const en = { const en = {
step: 'Step',
form_progress: 'Form progress',
close: 'Close',
uploaded_files: 'Uploaded files',
minimize: 'Minimize',
signature_drawing_area: 'Signature drawing area. Use mouse or touch to draw your signature.',
kba: 'KBA', kba: 'KBA',
please_upload_an_image_file: 'Please upload an image file', please_upload_an_image_file: 'Please upload an image file',
must_be_characters_length: 'Must be {number} characters long', must_be_characters_length: 'Must be {number} characters long',
@ -102,6 +108,11 @@ const en = {
} }
const es = { const es = {
step: 'Paso',
form_progress: 'Progreso del formulario',
close: 'Cerrar',
uploaded_files: 'Archivos subidos',
signature_drawing_area: 'Área de dibujo de firma. Use el ratón o toque para dibujar su firma.',
kba: 'KBA', kba: 'KBA',
please_upload_an_image_file: 'Por favor, sube un archivo de imagen', please_upload_an_image_file: 'Por favor, sube un archivo de imagen',
must_be_characters_length: 'Debe tener {number} caracteres de longitud', must_be_characters_length: 'Debe tener {number} caracteres de longitud',
@ -205,6 +216,11 @@ const es = {
} }
const it = { const it = {
step: 'Passo',
form_progress: 'Progresso del modulo',
close: 'Chiudi',
uploaded_files: 'File caricati',
signature_drawing_area: 'Area di disegno della firma. Usa il mouse o il tocco per disegnare la tua firma.',
kba: 'KBA', kba: 'KBA',
please_upload_an_image_file: 'Per favore carica un file immagine', please_upload_an_image_file: 'Per favore carica un file immagine',
must_be_characters_length: 'Deve essere lungo {number} caratteri', must_be_characters_length: 'Deve essere lungo {number} caratteri',
@ -308,6 +324,11 @@ const it = {
} }
const de = { const de = {
step: 'Schritt',
form_progress: 'Formularfortschritt',
close: 'Schließen',
uploaded_files: 'Hochgeladene Dateien',
signature_drawing_area: 'Unterschriftszeichenbereich. Verwenden Sie die Maus oder Berührung, um Ihre Unterschrift zu zeichnen.',
kba: 'KBA', kba: 'KBA',
please_upload_an_image_file: 'Bitte laden Sie eine Bilddatei hoch', please_upload_an_image_file: 'Bitte laden Sie eine Bilddatei hoch',
must_be_characters_length: 'Muss {number} Zeichen lang sein', must_be_characters_length: 'Muss {number} Zeichen lang sein',
@ -411,6 +432,11 @@ const de = {
} }
const fr = { const fr = {
step: 'Étape',
form_progress: 'Progression du formulaire',
close: 'Fermer',
uploaded_files: 'Fichiers téléchargés',
signature_drawing_area: 'Zone de dessin de signature. Utilisez la souris ou le toucher pour dessiner votre signature.',
kba: 'KBA', kba: 'KBA',
please_upload_an_image_file: 'Veuillez téléverser un fichier image', please_upload_an_image_file: 'Veuillez téléverser un fichier image',
must_be_characters_length: 'Doit comporter {number} caractères', must_be_characters_length: 'Doit comporter {number} caractères',
@ -514,6 +540,11 @@ const fr = {
} }
const pl = { const pl = {
step: 'Krok',
form_progress: 'Postęp formularza',
close: 'Zamknij',
uploaded_files: 'Przesłane pliki',
signature_drawing_area: 'Obszar rysowania podpisu. Użyj myszy lub dotyku, aby narysować swój podpis.',
kba: 'KBA', kba: 'KBA',
please_upload_an_image_file: 'Proszę przesłać plik obrazu', please_upload_an_image_file: 'Proszę przesłać plik obrazu',
must_be_characters_length: 'Musi mieć długość {number} znaków', must_be_characters_length: 'Musi mieć długość {number} znaków',
@ -617,6 +648,11 @@ const pl = {
} }
const uk = { const uk = {
step: 'Крок',
form_progress: 'Прогрес форми',
close: 'Закрити',
uploaded_files: 'Завантажені файли',
signature_drawing_area: 'Область малювання підпису. Використовуйте мишу або дотик, щоб намалювати свій підпис.',
kba: 'KBA', kba: 'KBA',
please_upload_an_image_file: 'Будь ласка, завантажте файл зображення', please_upload_an_image_file: 'Будь ласка, завантажте файл зображення',
must_be_characters_length: 'Має містити {number} символів', must_be_characters_length: 'Має містити {number} символів',
@ -720,6 +756,11 @@ const uk = {
} }
const cs = { const cs = {
step: 'Krok',
form_progress: 'Průběh formuláře',
close: 'Zavřít',
uploaded_files: 'Nahrané soubory',
signature_drawing_area: 'Oblast pro kreslení podpisu. Použijte myš nebo dotyk k nakreslení podpisu.',
kba: 'KBA', kba: 'KBA',
please_upload_an_image_file: 'Nahrajte prosím obrázkový soubor', please_upload_an_image_file: 'Nahrajte prosím obrázkový soubor',
must_be_characters_length: 'Musí mít délku {number} znaků', must_be_characters_length: 'Musí mít délku {number} znaků',
@ -823,6 +864,11 @@ const cs = {
} }
const pt = { const pt = {
step: 'Passo',
form_progress: 'Progresso do formulário',
close: 'Fechar',
uploaded_files: 'Arquivos enviados',
signature_drawing_area: 'Área de desenho da assinatura. Use o mouse ou toque para desenhar sua assinatura.',
kba: 'KBA', kba: 'KBA',
please_upload_an_image_file: 'Por favor, envie um arquivo de imagem', please_upload_an_image_file: 'Por favor, envie um arquivo de imagem',
must_be_characters_length: 'Deve ter {number} caracteres', must_be_characters_length: 'Deve ter {number} caracteres',
@ -926,6 +972,11 @@ const pt = {
} }
const he = { const he = {
step: 'שלב',
form_progress: 'התקדמות הטופס',
close: 'סגור',
uploaded_files: 'קבצים שהועלו',
signature_drawing_area: 'אזור ציור חתימה. השתמש בעכבר או במגע כדי לצייר את החתימה שלך.',
kba: 'KBA', kba: 'KBA',
please_upload_an_image_file: 'אנא העלה קובץ תמונה', please_upload_an_image_file: 'אנא העלה קובץ תמונה',
must_be_characters_length: 'חייב להיות באורך של {number} תווים', must_be_characters_length: 'חייב להיות באורך של {number} תווים',
@ -1029,6 +1080,11 @@ const he = {
} }
const nl = { const nl = {
step: 'Stap',
form_progress: 'Formuliervoortgang',
close: 'Sluiten',
uploaded_files: 'Geüploade bestanden',
signature_drawing_area: 'Handtekening tekengebied. Gebruik de muis of aanraking om uw handtekening te tekenen.',
kba: 'KBA', kba: 'KBA',
please_upload_an_image_file: 'Upload alstublieft een afbeeldingsbestand', please_upload_an_image_file: 'Upload alstublieft een afbeeldingsbestand',
must_be_characters_length: 'Moet {number} tekens lang zijn', must_be_characters_length: 'Moet {number} tekens lang zijn',
@ -1132,6 +1188,11 @@ const nl = {
} }
const ar = { const ar = {
step: 'خطوة',
form_progress: 'تقدم النموذج',
close: 'إغلاق',
uploaded_files: 'الملفات المرفوعة',
signature_drawing_area: 'منطقة رسم التوقيع. استخدم الماوس أو اللمس لرسم توقيعك.',
kba: 'KBA', kba: 'KBA',
please_upload_an_image_file: 'يرجى تحميل ملف صورة', please_upload_an_image_file: 'يرجى تحميل ملف صورة',
must_be_characters_length: 'يجب أن يكون الطول {number} حرفًا', must_be_characters_length: 'يجب أن يكون الطول {number} حرفًا',
@ -1235,6 +1296,11 @@ const ar = {
} }
const ko = { const ko = {
step: '단계',
form_progress: '양식 진행',
close: '닫기',
uploaded_files: '업로드된 파일',
signature_drawing_area: '서명 그리기 영역. 마우스 또는 터치를 사용하여 서명을 그리세요.',
kba: 'KBA', kba: 'KBA',
please_upload_an_image_file: '이미지 파일을 업로드해 주세요', please_upload_an_image_file: '이미지 파일을 업로드해 주세요',
must_be_characters_length: '{number}자여야 합니다', must_be_characters_length: '{number}자여야 합니다',
@ -1338,6 +1404,11 @@ const ko = {
} }
const ja = { const ja = {
step: 'ステップ',
form_progress: 'フォームの進捗',
close: '閉じる',
uploaded_files: 'アップロードされたファイル',
signature_drawing_area: '署名描画エリア。マウスまたはタッチを使用して署名を描いてください。',
kba: 'KBA', kba: 'KBA',
please_upload_an_image_file: '画像ファイルをアップロードしてください', please_upload_an_image_file: '画像ファイルをアップロードしてください',
must_be_characters_length: '{number}文字でなければなりません', must_be_characters_length: '{number}文字でなければなりません',

@ -18,13 +18,14 @@
class="btn btn-outline btn-sm reupload-button" class="btn btn-outline btn-sm reupload-button"
@click.prevent="remove" @click.prevent="remove"
> >
<IconReload :width="16" /> <IconReload :width="16" aria-hidden="true" />
{{ t('reupload') }} {{ t('reupload') }}
</button> </button>
</div> </div>
<div> <div>
<img <img
:src="attachmentsIndex[modelValue].url" :src="attachmentsIndex[modelValue].url"
:alt="field.name || t('image')"
class="h-52 border border-base-300 rounded mx-auto uploaded-image-preview" class="h-52 border border-base-300 rounded mx-auto uploaded-image-preview"
> >
</div> </div>

@ -22,41 +22,43 @@
class="md:tooltip" class="md:tooltip"
:data-tip="t('type_initial')" :data-tip="t('type_initial')"
> >
<a <button
id="type_text_button" id="type_text_button"
href="#" type="button"
:aria-label="t('type_initial')"
class="btn btn-outline font-medium btn-sm type-text-button" class="btn btn-outline font-medium btn-sm type-text-button"
@click.prevent="toggleTextInput" @click="toggleTextInput"
> >
<IconTextSize :width="16" /> <IconTextSize :width="16" aria-hidden="true" />
<span class="hidden sm:inline"> <span class="hidden sm:inline">
{{ t('type') }} {{ t('type') }}
</span> </span>
</a> </button>
</span> </span>
<span <span
v-else v-else
class="md:tooltip ml-2" class="md:tooltip ml-2"
:data-tip="t('draw_initials')" :data-tip="t('draw_initials')"
> >
<a <button
id="type_text_button" id="type_text_button"
href="#" type="button"
:aria-label="t('draw_initials')"
class="btn btn-outline font-medium btn-sm type-text-button" class="btn btn-outline font-medium btn-sm type-text-button"
@click.prevent="toggleTextInput" @click="toggleTextInput"
> >
<IconSignature :width="16" /> <IconSignature :width="16" aria-hidden="true" />
<span class="hidden sm:inline"> <span class="hidden sm:inline">
{{ t('draw') }} {{ t('draw') }}
</span> </span>
</a> </button>
</span> </span>
<span <span
class="md:tooltip" class="md:tooltip"
:data-tip="t('click_to_upload')" :data-tip="t('click_to_upload')"
> >
<label class="btn btn-outline btn-sm font-medium inline-flex flex-nowrap upload-image-button"> <label role="button" tabindex="0" :aria-label="t('click_to_upload')" class="btn btn-outline btn-sm font-medium inline-flex flex-nowrap upload-image-button" @keydown.enter.prevent="$el.querySelector('input')?.click()" @keydown.space.prevent="$el.querySelector('input')?.click()">
<IconUpload :width="16" /> <IconUpload :width="16" aria-hidden="true" />
<input <input
:key="uploadImageInputKey" :key="uploadImageInputKey"
type="file" type="file"
@ -69,35 +71,37 @@
</span> </span>
</label> </label>
</span> </span>
<a <button
v-if="modelValue || computedPreviousValue" v-if="modelValue || computedPreviousValue"
href="#" type="button"
class="btn font-medium btn-outline btn-sm clear-canvas-button" class="btn font-medium btn-outline btn-sm clear-canvas-button"
@click.prevent="remove" @click="remove"
> >
<IconReload :width="16" /> <IconReload :width="16" aria-hidden="true" />
{{ t('clear') }} {{ t('clear') }}
</a> </button>
<a <button
v-else v-else
href="#" type="button"
class="btn font-medium btn-outline btn-sm clear-canvas-button" class="btn font-medium btn-outline btn-sm clear-canvas-button"
@click.prevent="clear" @click="clear"
> >
<IconReload :width="16" /> <IconReload :width="16" aria-hidden="true" />
{{ t('clear') }} {{ t('clear') }}
</a> </button>
<a <button
type="button"
:title="t('minimize')" :title="t('minimize')"
href="#" :aria-label="t('minimize')"
class="py-1.5 inline md:hidden" class="py-1.5 inline md:hidden"
@click.prevent="$emit('minimize')" @click="$emit('minimize')"
> >
<IconArrowsDiagonalMinimize2 <IconArrowsDiagonalMinimize2
:width="20" :width="20"
:height="20" :height="20"
aria-hidden="true"
/> />
</a> </button>
</div> </div>
</div> </div>
<div <div

@ -19,6 +19,7 @@
</label> </label>
<div <div
v-if="field.description" v-if="field.description"
:id="field.uuid + '-desc'"
dir="auto" dir="auto"
class="mb-3 px-1 field-description-text" class="mb-3 px-1 field-description-text"
> >
@ -59,6 +60,7 @@
type="checkbox" type="checkbox"
:name="`values[${field.uuid}][]`" :name="`values[${field.uuid}][]`"
:value="optionValue(option, index)" :value="optionValue(option, index)"
:aria-describedby="field.description ? field.uuid + '-desc' : undefined"
class="base-checkbox !h-7 !w-7" class="base-checkbox !h-7 !w-7"
:checked="(modelValue || []).includes(optionValue(option, index))" :checked="(modelValue || []).includes(optionValue(option, index))"
@change="onChange" @change="onChange"

@ -23,6 +23,7 @@
/> />
<div <div
v-if="field.description" v-if="field.description"
:id="field.uuid + '-desc'"
dir="auto" dir="auto"
class="mb-3 px-1 field-description-text" class="mb-3 px-1 field-description-text"
> >
@ -44,6 +45,7 @@
:max="field.validation?.max" :max="field.validation?.max"
class="base-input !text-2xl w-full" class="base-input !text-2xl w-full"
:required="field.required" :required="field.required"
:aria-describedby="field.description ? field.uuid + '-desc' : undefined"
:placeholder="`${t('type_here_')}${field.required ? '' : ` (${t('optional')})`}`" :placeholder="`${t('type_here_')}${field.required ? '' : ` (${t('optional')})`}`"
:name="`values[${field.uuid}]`" :name="`values[${field.uuid}]`"
@focus="$emit('focus')" @focus="$emit('focus')"

@ -16,6 +16,7 @@
</label> </label>
<div <div
v-if="field.description" v-if="field.description"
:id="field.uuid + '-desc'"
dir="auto" dir="auto"
class="mb-3 px-1 field-description-text" class="mb-3 px-1 field-description-text"
> >
@ -42,28 +43,28 @@
@input="onInputCode" @input="onInputCode"
> >
<div class="flex justify-between mt-2 -mb-2 md:-mb-4"> <div class="flex justify-between mt-2 -mb-2 md:-mb-4">
<a <button
v-if="!defaultValue" v-if="!defaultValue"
href="#" type="button"
class="link change-phone-number-link" class="link change-phone-number-link"
@click.prevent="isCodeSent = false" @click="isCodeSent = false"
> >
{{ t('change_phone_number') }} {{ t('change_phone_number') }}
</a> </button>
<span <span
v-if="resendCodeCountdown > 0" v-if="resendCodeCountdown > 0"
class="link" class="link"
> >
{{ t('wait_countdown_seconds').replace('{countdown}', resendCodeCountdown) }} {{ t('wait_countdown_seconds').replace('{countdown}', resendCodeCountdown) }}
</span> </span>
<a <button
v-else v-else
href="#" type="button"
class="link resend-code-link" class="link resend-code-link"
@click.prevent="resendCode" @click="resendCode"
> >
{{ isResendLoading ? t('sending') : t('resend_code') }} {{ isResendLoading ? t('sending') : t('resend_code') }}
</a> </button>
</div> </div>
</div> </div>
<div <div
@ -107,6 +108,7 @@
type="tel" type="tel"
inputmode="tel" inputmode="tel"
:required="field.required" :required="field.required"
:aria-describedby="field.description ? field.uuid + '-desc' : undefined"
placeholder="234 567-8900" placeholder="234 567-8900"
@input="onPhoneInput" @input="onPhoneInput"
@focus="$emit('focus')" @focus="$emit('focus')"

@ -25,17 +25,21 @@
class="md:tooltip" class="md:tooltip"
:data-tip="t('draw_signature')" :data-tip="t('draw_signature')"
> >
<a <button
id="type_text_button" id="type_text_button"
href="#" type="button"
:aria-label="t('draw_signature')"
class="btn btn-outline btn-sm font-medium type-text-button" class="btn btn-outline btn-sm font-medium type-text-button"
@click.prevent="[toggleTextInput(), hideQr()]" @click="[toggleTextInput(), hideQr()]"
> >
<IconSignature :width="16" /> <IconSignature
:width="16"
aria-hidden="true"
/>
<span class="hidden sm:inline"> <span class="hidden sm:inline">
{{ t('draw') }} {{ t('draw') }}
</span> </span>
</a> </button>
</span> </span>
<span <span
v-else-if="withTypedSignature && format !== 'drawn_or_upload' && format !== 'typed_or_upload' && format !== 'typed' && format !== 'drawn' && format !== 'upload'" v-else-if="withTypedSignature && format !== 'drawn_or_upload' && format !== 'typed_or_upload' && format !== 'typed' && format !== 'drawn' && format !== 'upload'"
@ -43,17 +47,21 @@
:class="{ 'hidden sm:inline': modelValue || computedPreviousValue }" :class="{ 'hidden sm:inline': modelValue || computedPreviousValue }"
:data-tip="t('type_text')" :data-tip="t('type_text')"
> >
<a <button
id="type_text_button" id="type_text_button"
href="#" type="button"
:aria-label="t('type_text')"
class="btn btn-outline btn-sm font-medium inline-flex flex-nowrap type-text-button" class="btn btn-outline btn-sm font-medium inline-flex flex-nowrap type-text-button"
@click.prevent="[toggleTextInput(), hideQr()]" @click="[toggleTextInput(), hideQr()]"
> >
<IconTextSize :width="16" /> <IconTextSize
:width="16"
aria-hidden="true"
/>
<span class="hidden sm:inline"> <span class="hidden sm:inline">
{{ t('type') }} {{ t('type') }}
</span> </span>
</a> </button>
</span> </span>
<span <span
v-if="format !== 'typed' && format !== 'drawn' && format !== 'upload' && format !== 'drawn_or_typed'" v-if="format !== 'typed' && format !== 'drawn' && format !== 'upload' && format !== 'drawn_or_typed'"
@ -61,8 +69,18 @@
:class="{ 'hidden sm:inline': modelValue || computedPreviousValue }" :class="{ 'hidden sm:inline': modelValue || computedPreviousValue }"
:data-tip="t('take_photo')" :data-tip="t('take_photo')"
> >
<label class="btn btn-outline btn-sm font-medium inline-flex flex-nowrap upload-image-button"> <label
<IconCamera :width="16" /> role="button"
tabindex="0"
:aria-label="t('take_photo')"
class="btn btn-outline btn-sm font-medium inline-flex flex-nowrap upload-image-button"
@keydown.enter.prevent="$el.querySelector('input')?.click()"
@keydown.space.prevent="$el.querySelector('input')?.click()"
>
<IconCamera
:width="16"
aria-hidden="true"
/>
<input <input
:key="uploadImageInputKey" :key="uploadImageInputKey"
type="file" type="file"
@ -75,47 +93,55 @@
</span> </span>
</label> </label>
</span> </span>
<a <button
v-if="modelValue || computedPreviousValue" v-if="modelValue || computedPreviousValue"
href="#" type="button"
class="btn btn-outline btn-sm font-medium reupload-button" class="btn btn-outline btn-sm font-medium reupload-button"
@click.prevent="remove" @click="remove"
> >
<IconReload :width="16" /> <IconReload
:width="16"
aria-hidden="true"
/>
{{ t(format === 'upload' ? 'reupload' : 'redraw') }} {{ t(format === 'upload' ? 'reupload' : 'redraw') }}
</a> </button>
<span <span
v-if="withQrButton && !modelValue && !computedPreviousValue && format !== 'typed_or_upload' && format !== 'typed' && format !== 'upload'" v-if="withQrButton && !modelValue && !computedPreviousValue && format !== 'typed_or_upload' && format !== 'typed' && format !== 'upload'"
class="md:tooltip before:translate-x-[-90%]" class="md:tooltip before:translate-x-[-90%]"
:data-tip="t('sign_on_the_touchscreen')" :data-tip="t('sign_on_the_touchscreen')"
> >
<a <button
href="#" type="button"
:aria-label="t('sign_on_the_touchscreen')"
class="btn btn-sm btn-neutral font-medium hidden md:flex" class="btn btn-sm btn-neutral font-medium hidden md:flex"
:class="{ 'btn-outline': !isShowQr, 'text-white': isShowQr }" :class="{ 'btn-outline': !isShowQr, 'text-white': isShowQr }"
@click.prevent="isShowQr ? hideQr() : [isTextSignature = false, showQr()]" @click="isShowQr ? hideQr() : [isTextSignature = false, showQr()]"
> >
<IconQrcode <IconQrcode
:width="19" :width="19"
:height="19" :height="19"
aria-hidden="true"
/> />
</a> </button>
</span> </span>
<a <button
href="#" type="button"
:title="t('minimize')" :title="t('minimize')"
:aria-label="t('minimize')"
class="py-1.5 inline md:hidden" class="py-1.5 inline md:hidden"
@click.prevent="$emit('minimize')" @click="$emit('minimize')"
> >
<IconArrowsDiagonalMinimize2 <IconArrowsDiagonalMinimize2
:width="20" :width="20"
:height="20" :height="20"
aria-hidden="true"
/> />
</a> </button>
</div> </div>
</div> </div>
<div <div
v-if="field.description" v-if="field.description"
:id="field.uuid + '-desc'"
dir="auto" dir="auto"
class="mb-3 px-1 field-description-text" class="mb-3 px-1 field-description-text"
> >
@ -136,6 +162,7 @@
<img <img
v-if="modelValue || computedPreviousValue" v-if="modelValue || computedPreviousValue"
:src="attachmentsIndex[modelValue || computedPreviousValue].url" :src="attachmentsIndex[modelValue || computedPreviousValue].url"
:alt="field.name || t('signature')"
class="mx-auto bg-white border border-base-300 rounded max-h-44" class="mx-auto bg-white border border-base-300 rounded max-h-44"
> >
<FileDropzone <FileDropzone
@ -154,14 +181,17 @@
v-if="!modelValue && !computedPreviousValue && !isShowQr && !isTextSignature && isSignatureStarted" v-if="!modelValue && !computedPreviousValue && !isShowQr && !isTextSignature && isSignatureStarted"
class="absolute top-0.5 right-0.5" class="absolute top-0.5 right-0.5"
> >
<a <button
href="#" type="button"
class="btn btn-ghost font-medium btn-xs md:btn-sm" class="btn btn-ghost font-medium btn-xs md:btn-sm"
@click.prevent="[clear(), hideQr()]" @click="[clear(), hideQr()]"
> >
<IconReload :width="16" /> <IconReload
:width="16"
aria-hidden="true"
/>
{{ t('clear') }} {{ t('clear') }}
</a> </button>
</div> </div>
<div <div
v-if="isTextSignature" v-if="isTextSignature"
@ -170,6 +200,8 @@
<canvas <canvas
v-show="!modelValue && !computedPreviousValue" v-show="!modelValue && !computedPreviousValue"
ref="canvas" ref="canvas"
role="application"
:aria-label="t('signature_drawing_area')"
style="padding: 1px; 0" style="padding: 1px; 0"
class="bg-white border border-base-300 rounded-2xl w-full draw-canvas" class="bg-white border border-base-300 rounded-2xl w-full draw-canvas"
/> />
@ -182,13 +214,14 @@
class="top-0 bottom-0 right-0 left-0 absolute bg-base-content/10 rounded-2xl" class="top-0 bottom-0 right-0 left-0 absolute bg-base-content/10 rounded-2xl"
> >
<div class="absolute top-1.5 right-1.5"> <div class="absolute top-1.5 right-1.5">
<a <button
href="#" type="button"
class="btn btn-sm btn-circle btn-normal btn-outline" class="btn btn-sm btn-circle btn-normal btn-outline"
@click.prevent="hideQr" :aria-label="t('close')"
@click="hideQr"
> >
<IconX /> <IconX aria-hidden="true" />
</a> </button>
</div> </div>
<div class="flex items-center justify-center w-full h-full p-4"> <div class="flex items-center justify-center w-full h-full p-4">
<div <div

@ -23,6 +23,7 @@
/> />
<div <div
v-if="field.description" v-if="field.description"
:id="field.uuid + '-desc'"
dir="auto" dir="auto"
class="mb-3 px-1 field-description-text" class="mb-3 px-1 field-description-text"
> >
@ -40,6 +41,7 @@
:class="{ '!pr-11 -mr-10': !field.validation?.pattern }" :class="{ '!pr-11 -mr-10': !field.validation?.pattern }"
:required="field.required" :required="field.required"
:pattern="field.validation?.pattern" :pattern="field.validation?.pattern"
:aria-describedby="field.description ? field.uuid + '-desc' : undefined"
:placeholder="`${t('type_here_')}${field.required ? '' : ` (${t('optional')})`}`" :placeholder="`${t('type_here_')}${field.required ? '' : ` (${t('optional')})`}`"
type="text" type="text"
:name="`values[${field.uuid}]`" :name="`values[${field.uuid}]`"
@ -54,6 +56,7 @@
v-model="text" v-model="text"
dir="auto" dir="auto"
class="base-textarea !text-2xl w-full" class="base-textarea !text-2xl w-full"
:aria-describedby="field.description ? field.uuid + '-desc' : undefined"
:placeholder="`${t('type_here_')}${field.required ? '' : ` (${t('optional')})`}`" :placeholder="`${t('type_here_')}${field.required ? '' : ` (${t('optional')})`}`"
:required="field.required" :required="field.required"
:name="`values[${field.uuid}]`" :name="`values[${field.uuid}]`"
@ -65,13 +68,14 @@
class="tooltip" class="tooltip"
:data-tip="t('toggle_multiline_text')" :data-tip="t('toggle_multiline_text')"
> >
<a <button
href="#" type="button"
:aria-label="t('toggle_multiline_text')"
class="btn btn-ghost btn-circle btn-sm toggle-multiline-text-button" class="btn btn-ghost btn-circle btn-sm toggle-multiline-text-button"
@click.prevent="toggleTextArea" @click="toggleTextArea"
> >
<IconAlignBoxLeftTop /> <IconAlignBoxLeftTop aria-hidden="true" />
</a> </button>
</div> </div>
</div> </div>
</template> </template>

@ -30,6 +30,7 @@
<IconInnerShadowTop <IconInnerShadowTop
width="40" width="40"
class="animate-spin h-10" class="animate-spin h-10"
aria-hidden="true"
/> />
</div> </div>
<div v-else-if="redirectUrl"> <div v-else-if="redirectUrl">

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0"></path> <path d="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0"></path>
<path d="M9 12l2 2l4 -4"></path> <path d="M9 12l2 2l4 -4"></path>

Before

Width:  |  Height:  |  Size: 389 B

After

Width:  |  Height:  |  Size: 408 B

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" /> <path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2" /> <path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2" />
<path d="M7 11l5 5l5 -5" /> <path d="M7 11l5 5l5 -5" />

Before

Width:  |  Height:  |  Size: 397 B

After

Width:  |  Height:  |  Size: 416 B

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0"></path> <path d="M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0"></path>
<path d="M12 9h.01"></path> <path d="M12 9h.01"></path>

Before

Width:  |  Height:  |  Size: 412 B

After

Width:  |  Height:  |  Size: 431 B

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" /> <path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M12 3a9 9 0 1 0 9 9" /> <path d="M12 3a9 9 0 1 0 9 9" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 318 B

After

Width:  |  Height:  |  Size: 337 B

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" /> <path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M12 18h-7a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v7.5" /> <path d="M12 18h-7a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v7.5" />
<path d="M3 6l9 6l9 -6" /> <path d="M3 6l9 6l9 -6" />

Before

Width:  |  Height:  |  Size: 448 B

After

Width:  |  Height:  |  Size: 467 B

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="2" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M19.933 13.041a8 8 0 1 1 -9.925 -8.788c3.899 -1 7.935 1.007 9.425 4.747"></path> <path d="M19.933 13.041a8 8 0 1 1 -9.925 -8.788c3.899 -1 7.935 1.007 9.425 4.747"></path>
<path d="M20 4v5h-5"></path> <path d="M20 4v5h-5"></path>

Before

Width:  |  Height:  |  Size: 409 B

After

Width:  |  Height:  |  Size: 428 B

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="<%= local_assigns[:class] %>"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0" /><path d="M6 21v-2a4 4 0 0 1 4 -4h3" /><path d="M16 22l5 -5" /><path d="M21 21.5v-4.5h-4.5" /></svg> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="<%= local_assigns[:class] %>"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><path d="M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0" /><path d="M6 21v-2a4 4 0 0 1 4 -4h3" /><path d="M16 22l5 -5" /><path d="M21 21.5v-4.5h-4.5" /></svg>

Before

Width:  |  Height:  |  Size: 416 B

After

Width:  |  Height:  |  Size: 435 B

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M3 19c3.333 -2 5 -4 5 -6c0 -3 -1 -3 -2 -3s-2.032 1.085 -2 3c.034 2.048 1.658 2.877 2.5 4c1.5 2 2.5 2.5 3.5 1c.667 -1 1.167 -1.833 1.5 -2.5c1 2.333 2.333 3.5 4 3.5h2.5"></path> <path d="M3 19c3.333 -2 5 -4 5 -6c0 -3 -1 -3 -2 -3s-2.032 1.085 -2 3c.034 2.048 1.658 2.877 2.5 4c1.5 2 2.5 2.5 3.5 1c.667 -1 1.167 -1.833 1.5 -2.5c1 2.333 2.333 3.5 4 3.5h2.5"></path>
<path d="M20 17v-12c0 -1.121 -.879 -2 -2 -2s-2 .879 -2 2v12l2 2l2 -2z"></path> <path d="M20 17v-12c0 -1.121 -.879 -2 -2 -2s-2 .879 -2 2v12l2 2l2 -2z"></path>

Before

Width:  |  Height:  |  Size: 584 B

After

Width:  |  Height:  |  Size: 603 B

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" width="24" height="24" stroke-width="2"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" class="<%= local_assigns[:class] %>" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" width="24" height="24" stroke-width="2">
<path d="M18 6l-12 12"></path> <path d="M18 6l-12 12"></path>
<path d="M6 6l12 12"></path> <path d="M6 6l12 12"></path>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 290 B

After

Width:  |  Height:  |  Size: 309 B

@ -1,18 +1,22 @@
<% uuid = local_assigns[:uuid] || SecureRandom.uuid %> <% uuid = local_assigns[:uuid] || SecureRandom.uuid %>
<input type="checkbox" id="<%= uuid %>" class="modal-toggle"> <% title_id = "#{uuid}-title" %>
<div id="<%= local_assigns[:id] %>" class="modal items-start !animate-none overflow-y-auto"> <%= tag.dialog id: uuid, class: "modal items-start overflow-y-auto", inert: true, "aria-labelledby": (title_id if local_assigns[:title]) do %>
<div class="modal-box pt-4 pb-6 px-6 mt-20 max-h-none"> <div class="modal-box pt-4 pb-6 px-6 mt-20 max-h-none">
<% if local_assigns[:title] %> <% if local_assigns[:title] %>
<div class="flex justify-between items-center border-b pb-2 mb-2 font-medium"> <div class="flex justify-between items-center border-b pb-2 mb-2 font-medium">
<span> <span id="<%= title_id %>">
<%= local_assigns[:title] %> <%= local_assigns[:title] %>
</span> </span>
<label for="<%= uuid %>" class="text-xl">&times;</label> <form method="dialog">
<button class="text-xl cursor-pointer w-6 h-6" aria-label="<%= t('close') %>">&times;</button>
</form>
</div> </div>
<% end %> <% end %>
<div> <div>
<%= yield %> <%= yield %>
</div> </div>
</div> </div>
<label class="modal-backdrop" for="<%= uuid %>"></label> <form method="dialog" class="modal-backdrop">
</div> <button aria-label="<%= t('close') %>"></button>
</form>
<% end %>

@ -1,4 +1,4 @@
<div class="max-w-md mx-auto px-2 mt-12 mb-4"> <main class="max-w-md mx-auto px-2 mt-12 mb-4">
<div class="space-y-6 mx-auto"> <div class="space-y-6 mx-auto">
<div class="space-y-6"> <div class="space-y-6">
<div class="flex items-center justify-center"> <div class="flex items-center justify-center">
@ -32,5 +32,5 @@
</toggle-submit> </toggle-submit>
<% end %> <% end %>
</div> </div>
</div> </main>
<%= render 'shared/attribution', link_path: '/start', account: @submitter.account %> <%= render 'shared/attribution', link_path: '/start', account: @submitter.account %>

@ -2,7 +2,7 @@
<% I18n.with_locale(@template.account.locale) do %> <% I18n.with_locale(@template.account.locale) do %>
<% content_for(:html_description, t('account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution', account_name: @template.account.name)) %> <% content_for(:html_description, t('account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution', account_name: @template.account.name)) %>
<% end %> <% end %>
<div class="max-w-md mx-auto px-2 mt-12 mb-4"> <main class="max-w-md mx-auto px-2 mt-12 mb-4">
<div class="space-y-6 mx-auto"> <div class="space-y-6 mx-auto">
<div class="space-y-6"> <div class="space-y-6">
<div class="flex items-center justify-center"> <div class="flex items-center justify-center">
@ -51,4 +51,4 @@
<% end %> <% end %>
<%= button_to t(:re_send_email), start_form_email_2fa_send_index_path, params: { slug: @template.slug, resend: true, submitter: { name: params[:name] || @submitter&.name, email: params[:email] || @submitter&.email, phone: params[:phone] || @submitter&.phone } }.compact, method: :post, id: 'resend_code', class: 'hidden' %> <%= button_to t(:re_send_email), start_form_email_2fa_send_index_path, params: { slug: @template.slug, resend: true, submitter: { name: params[:name] || @submitter&.name, email: params[:email] || @submitter&.email, phone: params[:phone] || @submitter&.phone } }.compact, method: :post, id: 'resend_code', class: 'hidden' %>
</div> </div>
</div> </main>

@ -2,7 +2,7 @@
<% I18n.with_locale(@template.account.locale) do %> <% I18n.with_locale(@template.account.locale) do %>
<% content_for(:html_description, t('share_link_is_currently_disabled')) %> <% content_for(:html_description, t('share_link_is_currently_disabled')) %>
<% end %> <% end %>
<div class="max-w-md space-y-6 mx-auto px-2 mt-12 mb-4"> <main class="max-w-md space-y-6 mx-auto px-2 mt-12 mb-4">
<div class="text-center w-full space-y-6"> <div class="text-center w-full space-y-6">
<%= render 'banner' %> <%= render 'banner' %>
<p class="text-xl font-semibold text-center"> <p class="text-xl font-semibold text-center">
@ -27,5 +27,5 @@
<%= button_to button_title(title: t('enable_shared_link'), icon: svg_icon('lock_open', class: 'w-6 h-6')), template_share_link_path(@template), params: { template: { shared_link: true }, redir: start_form_path(slug: @template.slug) }, method: :post, class: 'white-button w-full' %> <%= button_to button_title(title: t('enable_shared_link'), icon: svg_icon('lock_open', class: 'w-6 h-6')), template_share_link_path(@template), params: { template: { shared_link: true }, redir: start_form_path(slug: @template.slug) }, method: :post, class: 'white-button w-full' %>
</toggle-submit> </toggle-submit>
<% end %> <% end %>
</div> </main>
<%= render 'shared/attribution', link_path: '/start', account: @template.account %> <%= render 'shared/attribution', link_path: '/start', account: @template.account %>

@ -2,7 +2,7 @@
<% I18n.with_locale(@template.account.locale) do %> <% I18n.with_locale(@template.account.locale) do %>
<% content_for(:html_description, t('account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution', account_name: @template.account.name)) %> <% content_for(:html_description, t('account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution', account_name: @template.account.name)) %>
<% end %> <% end %>
<div class="max-w-md mx-auto px-2 mt-12 mb-4"> <main class="max-w-md mx-auto px-2 mt-12 mb-4">
<div class="space-y-6 mx-auto"> <div class="space-y-6 mx-auto">
<div class="space-y-6"> <div class="space-y-6">
<div class="text-center w-full space-y-6"> <div class="text-center w-full space-y-6">
@ -63,6 +63,8 @@
<% end %> <% end %>
<% end %> <% end %>
</div> </div>
</div> <div class="mt-4">
<%= render 'shared/attribution', link_path: '/start', account: @template.account %> <%= render 'shared/attribution', link_path: '/start', account: @template.account %>
<%= render 'start_form/policy', account: @template.account %> <%= render 'start_form/policy', account: @template.account %>
</div>
</main>

@ -10,7 +10,7 @@
<% is_narrow = area['h'].positive? && ((area['w'] * local_assigns[:page_width]).to_f / (area['h'] * local_assigns[:page_height])) > 4.5 %> <% is_narrow = area['h'].positive? && ((area['w'] * local_assigns[:page_width]).to_f / (area['h'] * local_assigns[:page_height])) > 4.5 %>
<div class="flex justify-between w-full h-full gap-1 <%= is_narrow && (local_assigns[:with_signature_id] || field.dig('preferences', 'reason_field_uuid').present?) ? 'flex-row' : 'flex-col' %>"> <div class="flex justify-between w-full h-full gap-1 <%= is_narrow && (local_assigns[:with_signature_id] || field.dig('preferences', 'reason_field_uuid').present?) ? 'flex-row' : 'flex-col' %>">
<div class="flex overflow-hidden <%= is_narrow && (local_assigns[:with_signature_id] || field.dig('preferences', 'reason_field_uuid').present?) ? 'w-1/2' : 'flex-grow' %>" style="min-height: 50%"> <div class="flex overflow-hidden <%= is_narrow && (local_assigns[:with_signature_id] || field.dig('preferences', 'reason_field_uuid').present?) ? 'w-1/2' : 'flex-grow' %>" style="min-height: 50%">
<img class="object-contain mx-auto" src="<%= attachments_index[value].url %>"> <img class="object-contain mx-auto" src="<%= attachments_index[value].url %>" alt="<%= field['name'].presence || field['title'].presence || field['type'] %>">
</div> </div>
<% if (local_assigns[:with_signature_id] || field.dig('preferences', 'reason_field_uuid').present?) && attachment = attachments_index[value] %> <% if (local_assigns[:with_signature_id] || field.dig('preferences', 'reason_field_uuid').present?) && attachment = attachments_index[value] %>
<div class="text-[1vw] lg:text-[0.55rem] lg:leading-[0.65rem] <%= is_narrow ? 'w-1/2' : 'w-full' %>"> <div class="text-[1vw] lg:text-[0.55rem] lg:leading-[0.65rem] <%= is_narrow ? 'w-1/2' : 'w-full' %>">
@ -35,7 +35,7 @@
<% end %> <% end %>
</div> </div>
<% elsif field['type'].in?(['image', 'initials', 'stamp', 'kba']) && attachments_index[value].image? %> <% elsif field['type'].in?(['image', 'initials', 'stamp', 'kba']) && attachments_index[value].image? %>
<img class="object-contain mx-auto" src="<%= attachments_index[value].url %>" loading="lazy"> <img class="object-contain mx-auto" src="<%= attachments_index[value].url %>" loading="lazy" alt="<%= field['name'].presence || field['title'].presence || field['type'] %>">
<% elsif field['type'].in?(['file', 'payment', 'image']) %> <% elsif field['type'].in?(['file', 'payment', 'image']) %>
<autosize-field></autosize-field> <autosize-field></autosize-field>
<div class="px-0.5 flex flex-col justify-center"> <div class="px-0.5 flex flex-col justify-center">

@ -8,11 +8,11 @@
<% with_submitter_timezone = configs.find { |e| e.key == AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY }&.value == true %> <% with_submitter_timezone = configs.find { |e| e.key == AccountConfig::WITH_SUBMITTER_TIMEZONE_KEY }&.value == true %>
<% with_timestamp_seconds = configs.find { |e| e.key == AccountConfig::WITH_TIMESTAMP_SECONDS_KEY }&.value == true %> <% with_timestamp_seconds = configs.find { |e| e.key == AccountConfig::WITH_TIMESTAMP_SECONDS_KEY }&.value == true %>
<% with_signature_id_reason = configs.find { |e| e.key == AccountConfig::WITH_SIGNATURE_ID_REASON_KEY }&.value != false %> <% with_signature_id_reason = configs.find { |e| e.key == AccountConfig::WITH_SIGNATURE_ID_REASON_KEY }&.value != false %>
<div style="max-width: 1600px" class="mx-auto pl-4"> <main style="max-width: 1600px" class="mx-auto pl-4">
<div class="flex justify-between py-1.5 items-center pr-4 sticky top-0 md:relative z-10 bg-base-100"> <div class="flex justify-between py-1.5 items-center pr-4 sticky top-0 md:relative z-10 bg-base-100">
<a href="<%= signed_in? && @submission.account_id == current_account&.id && @submission.template ? template_path(@submission.template) : '/' %>" class="flex items-center space-x-3 py-1"> <a href="<%= signed_in? && @submission.account_id == current_account&.id && @submission.template ? template_path(@submission.template) : '/' %>" class="flex items-center space-x-3 py-1">
<span><%= render 'submissions/logo' %></span> <span><%= render 'submissions/logo' %></span>
<span class="text-xl md:text-3xl font-semibold focus:text-clip" style="overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;"><% (@submission.name || @submission.template.name).split(/(_)/).each do |item| %><%= item %><wbr><% end %></span> <h1 class="text-xl md:text-3xl font-semibold focus:text-clip" style="overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;"><% (@submission.name || @submission.template.name).split(/(_)/).each do |item| %><%= item %><wbr><% end %></h1>
</a> </a>
<div class="space-x-3 flex items-center"> <div class="space-x-3 flex items-center">
<% is_all_completed = @submission.submitters.to_a.all?(&:completed_at?) %> <% is_all_completed = @submission.submitters.to_a.all?(&:completed_at?) %>
@ -33,7 +33,7 @@
<% if @submission.submitters.to_a.any?(&:completed_at?) %> <% if @submission.submitters.to_a.any?(&:completed_at?) %>
<% if is_all_completed || !is_combined_enabled %> <% if is_all_completed || !is_combined_enabled %>
<div class="join relative"> <div class="join relative">
<download-button data-src="<%= local_assigns[:is_preview] ? (@sig_submitter ? submit_form_documents_path(@sig_submitter.slug, { sig: params[:sig], combined: is_combined_enabled }.compact_blank) : submissions_preview_download_index_path(@submission.slug, combined: is_combined_enabled.presence)) : submission_download_index_path(@submission, combined: is_combined_enabled.presence) %>" class="base-button <%= '!rounded-r-none !pr-2' if is_all_completed && !is_combined_enabled %>"> <download-button role="button" tabindex="0" aria-label="<%= t('download') %>" data-src="<%= local_assigns[:is_preview] ? (@sig_submitter ? submit_form_documents_path(@sig_submitter.slug, { sig: params[:sig], combined: is_combined_enabled }.compact_blank) : submissions_preview_download_index_path(@submission.slug, combined: is_combined_enabled.presence)) : submission_download_index_path(@submission, combined: is_combined_enabled.presence) %>" class="base-button <%= '!rounded-r-none !pr-2' if is_all_completed && !is_combined_enabled %>">
<span class="flex items-center justify-center space-x-2" data-target="download-button.defaultButton"> <span class="flex items-center justify-center space-x-2" data-target="download-button.defaultButton">
<%= svg_icon('download', class: 'w-6 h-6') %> <%= svg_icon('download', class: 'w-6 h-6') %>
<span class="hidden md:inline"><%= t('download') %></span> <span class="hidden md:inline"><%= t('download') %></span>
@ -45,14 +45,14 @@
</download-button> </download-button>
<% if is_all_completed && !is_combined_enabled %> <% if is_all_completed && !is_combined_enabled %>
<div class="dropdown dropdown-end"> <div class="dropdown dropdown-end">
<label tabindex="0" class="base-button !rounded-l-none !pl-1 !pr-2 !border-l-neutral-500"> <label tabindex="0" aria-label="<%= t('download') %>" class="base-button !rounded-l-none !pl-1 !pr-2 !border-l-neutral-500">
<span class="text-sm align-text-top"> <span class="text-sm align-text-top">
<%= svg_icon('chevron_down', class: 'w-6 h-6 flex-shrink-0 stroke-2') %> <%= svg_icon('chevron_down', class: 'w-6 h-6 flex-shrink-0 stroke-2') %>
</span> </span>
</label> </label>
<ul tabindex="0" class="z-10 dropdown-content p-2 mt-2 shadow menu text-base bg-base-100 rounded-box text-right"> <ul class="z-10 dropdown-content p-2 mt-2 shadow menu text-base bg-base-100 rounded-box text-right">
<li> <li>
<download-button data-src="<%= local_assigns[:is_preview] ? (@sig_submitter ? submit_form_documents_path(@sig_submitter.slug, { sig: params[:sig], combined: true }.compact) : submissions_preview_download_index_path(@submission.slug, combined: true)) : submission_download_index_path(@submission, combined: true) %>" class="flex items-center"> <download-button role="button" tabindex="0" data-src="<%= local_assigns[:is_preview] ? (@sig_submitter ? submit_form_documents_path(@sig_submitter.slug, { sig: params[:sig], combined: true }.compact) : submissions_preview_download_index_path(@submission.slug, combined: true)) : submission_download_index_path(@submission, combined: true) %>" class="flex items-center">
<span class="flex items-center justify-center space-x-2" data-target="download-button.defaultButton"> <span class="flex items-center justify-center space-x-2" data-target="download-button.defaultButton">
<%= svg_icon('download', class: 'w-6 h-6 flex-shrink-0') %> <%= svg_icon('download', class: 'w-6 h-6 flex-shrink-0') %>
<span class="whitespace-nowrap"><%= t('download_combined_pdf') %></span> <span class="whitespace-nowrap"><%= t('download_combined_pdf') %></span>
@ -74,14 +74,14 @@
</div> </div>
</div> </div>
<div class="flex md:max-h-[calc(100vh-60px)]"> <div class="flex md:max-h-[calc(100vh-60px)]">
<div class="overflow-y-auto overflow-x-hidden hidden lg:block w-52 flex-none pr-3 mt-0.5 pt-0.5"> <div class="overflow-y-auto overflow-x-hidden hidden lg:block w-52 flex-none pr-3 mt-0.5 pt-0.5" tabindex="0">
<% values = @submission.submitters.reduce({}) { |acc, sub| acc.merge(sub.values) } %> <% values = @submission.submitters.reduce({}) { |acc, sub| acc.merge(sub.values) } %>
<% schema = Submissions.filtered_conditions_schema(@submission, values:) %> <% schema = Submissions.filtered_conditions_schema(@submission, values:) %>
<% schema.each do |item| %> <% schema.each do |item| %>
<% document = @submission.schema_documents.find { |a| item['attachment_uuid'] == a.uuid } %> <% document = @submission.schema_documents.find { |a| item['attachment_uuid'] == a.uuid } %>
<% if document.preview_images.first %> <% if document.preview_images.first %>
<scroll-to data-selector-id="page-<%= document.uuid %>-0" class="block cursor-pointer"> <scroll-to data-selector-id="page-<%= document.uuid %>-0" class="block cursor-pointer">
<img src="<%= (document.preview_images.find { |e| e.filename.base.to_i.zero? } || document.preview_images.first).url %>" width="<%= document.preview_images.first.metadata['width'] %>" height="<%= document.preview_images.first.metadata['height'] %>" class="rounded border" loading="lazy"> <img src="<%= (document.preview_images.find { |e| e.filename.base.to_i.zero? } || document.preview_images.first).url %>" width="<%= document.preview_images.first.metadata['width'] %>" height="<%= document.preview_images.first.metadata['height'] %>" class="rounded border" loading="lazy" alt="<%= item['name'].presence || document.filename.base %>">
<div class="pb-2 pt-1.5 text-center" dir="auto"> <div class="pb-2 pt-1.5 text-center" dir="auto">
<%= item['name'].presence || document.filename.base %> <%= item['name'].presence || document.filename.base %>
</div> </div>
@ -89,7 +89,7 @@
<% end %> <% end %>
<% end %> <% end %>
</div> </div>
<div id="document_view" class="w-full overflow-y-auto overflow-x-hidden mt-0.5 pt-0.5"> <div id="document_view" class="w-full overflow-y-auto overflow-x-hidden mt-0.5 pt-0.5" tabindex="0">
<div class="pr-3.5 pl-0.5"> <div class="pr-3.5 pl-0.5">
<% fields_index = Templates.build_field_areas_index(@submission.template_fields || @submission.template.fields) %> <% fields_index = Templates.build_field_areas_index(@submission.template_fields || @submission.template.fields) %>
<% submitters_index = @submission.submitters.index_by(&:uuid) %> <% submitters_index = @submission.submitters.index_by(&:uuid) %>
@ -105,7 +105,7 @@
<% (document.metadata.dig('pdf', 'number_of_pages') || (document.preview_images.loaded? ? preview_images_index.size : document.preview_images.size)).times do |index| %> <% (document.metadata.dig('pdf', 'number_of_pages') || (document.preview_images.loaded? ? preview_images_index.size : document.preview_images.size)).times do |index| %>
<% page = preview_images_index[index] || page_blob_struct.new(metadata: lazyload_metadata, url: preview_document_page_path(document.signed_key, "#{index}.jpg")) %> <% page = preview_images_index[index] || page_blob_struct.new(metadata: lazyload_metadata, url: preview_document_page_path(document.signed_key, "#{index}.jpg")) %>
<page-container id="<%= "page-#{document.uuid}-#{index}" %>" class="block before:border before:absolute before:top-0 before:bottom-0 before:left-0 before:right-0 before:rounded relative mb-4" style="container-type: size; aspect-ratio: <%= width = page.metadata['width'] %> / <%= height = page.metadata['height'] %>"> <page-container id="<%= "page-#{document.uuid}-#{index}" %>" class="block before:border before:absolute before:top-0 before:bottom-0 before:left-0 before:right-0 before:rounded relative mb-4" style="container-type: size; aspect-ratio: <%= width = page.metadata['width'] %> / <%= height = page.metadata['height'] %>">
<img loading="lazy" src="<%= page.url %>" width="<%= width %>" class="rounded" height="<%= height %>"> <img loading="lazy" src="<%= page.url %>" width="<%= width %>" class="rounded" height="<%= height %>" alt="<%= "#{item['name']} - #{t('page')} #{index + 1}" %>">
<div class="top-0 bottom-0 left-0 right-0 absolute"> <div class="top-0 bottom-0 left-0 right-0 absolute">
<% document_annots_index[index]&.each do |annot| %> <% document_annots_index[index]&.each do |annot| %>
<%= render 'submissions/annotation', annot: %> <%= render 'submissions/annotation', annot: %>
@ -144,7 +144,7 @@
<% end %> <% end %>
</div> </div>
</div> </div>
<div id="parties_view" class="hidden md:block relative w-full md:w-80 flex-none pt-0.5 pr-4 pl-0.5 overflow-auto space"> <div id="parties_view" class="hidden md:block relative w-full md:w-80 flex-none pt-0.5 pr-4 pl-0.5 overflow-auto space" tabindex="0">
<% colors = %w[bg-red-500 bg-sky-500 bg-emerald-500 bg-yellow-300 bg-purple-600 bg-pink-500 bg-cyan-500 bg-orange-500 bg-lime-500 bg-indigo-500] %> <% colors = %w[bg-red-500 bg-sky-500 bg-emerald-500 bg-yellow-300 bg-purple-600 bg-pink-500 bg-cyan-500 bg-orange-500 bg-lime-500 bg-indigo-500] %>
<% submitter_fields_index = (@submission.template_fields || @submission.template.fields).group_by { |f| f['submitter_uuid'] } %> <% submitter_fields_index = (@submission.template_fields || @submission.template.fields).group_by { |f| f['submitter_uuid'] } %>
<% submitter_field_counters = Hash.new { 0 } %> <% submitter_field_counters = Hash.new { 0 } %>
@ -260,10 +260,10 @@
<div dir="auto"> <div dir="auto">
<% if field['type'].in?(%w[signature initials]) %> <% if field['type'].in?(%w[signature initials]) %>
<div class="w-full bg-base-300 py-1"> <div class="w-full bg-base-300 py-1">
<img class="object-contain mx-auto" style="max-height: <%= field['type'] == 'signature' ? 100 : 50 %>px" height="<%= attachments_index[value].metadata['height'] %>" width="<%= attachments_index[value].metadata['width'] %>" src="<%= attachments_index[value].url %>" loading="lazy"> <img class="object-contain mx-auto" style="max-height: <%= field['type'] == 'signature' ? 100 : 50 %>px" height="<%= attachments_index[value].metadata['height'] %>" width="<%= attachments_index[value].metadata['width'] %>" src="<%= attachments_index[value].url %>" loading="lazy" alt="<%= field['name'] || field['title'] || field['type'] %>">
</div> </div>
<% elsif field['type'].in?(['image', 'stamp', 'kba']) && attachments_index[value].image? %> <% elsif field['type'].in?(['image', 'stamp', 'kba']) && attachments_index[value].image? %>
<img class="object-contain mx-auto max-h-28" style="max-height: 200px" height="<%= attachments_index[value].metadata['height'] %>" width="<%= attachments_index[value].metadata['width'] %>" src="<%= attachments_index[value].url %>" loading="lazy"> <img class="object-contain mx-auto max-h-28" style="max-height: 200px" height="<%= attachments_index[value].metadata['height'] %>" width="<%= attachments_index[value].metadata['width'] %>" src="<%= attachments_index[value].url %>" loading="lazy" alt="<%= field['name'] || field['title'] || field['type'] %>">
<% elsif field['type'].in?(['file', 'payment', 'image']) %> <% elsif field['type'].in?(['file', 'payment', 'image']) %>
<div class="flex flex-col justify-center"> <div class="flex flex-col justify-center">
<% Array.wrap(value).each do |val| %> <% Array.wrap(value).each do |val| %>
@ -313,7 +313,7 @@
</span> </span>
</label> </label>
</toggle-visible> </toggle-visible>
</div> </main>
<% unless request.headers['HTTP_X_TURBO'] %> <% unless request.headers['HTTP_X_TURBO'] %>
<%= render 'scripts/autosize_field' %> <%= render 'scripts/autosize_field' %>
<% end %> <% end %>

@ -1,8 +1,6 @@
<%= form_for '', url: submit_form_decline_index_path(submitter.slug), method: :post do |f| %> <%= form_for '', url: submit_form_decline_index_path(submitter.slug), method: :post do |f| %>
<div class="mt-4 text-center"> <div class="form-control mt-4">
<%= t(:notify_the_sender_with_the_reason_you_declined) %> <label class="label justify-center" for="reason"><%= t(:notify_the_sender_with_the_reason_you_declined) %></label>
</div>
<div class="form-control mt-2">
<%= f.text_area :reason, required: true, class: 'base-input w-full py-2 h-40', dir: 'auto', placeholder: t('provide_a_reason'), style: 'height: 200px', rows: '10' %> <%= f.text_area :reason, required: true, class: 'base-input w-full py-2 h-40', dir: 'auto', placeholder: t('provide_a_reason'), style: 'height: 200px', rows: '10' %>
</div> </div>
<toggle-submit dir="auto" class="form-control mt-4"> <toggle-submit dir="auto" class="form-control mt-4">

@ -1,4 +1,4 @@
<div class="max-w-md mx-auto px-2 mt-12 mb-4"> <main class="max-w-md mx-auto px-2 mt-12 mb-4">
<div class="space-y-6 mx-auto"> <div class="space-y-6 mx-auto">
<div class="space-y-6"> <div class="space-y-6">
<div class="flex items-center justify-center"> <div class="flex items-center justify-center">
@ -30,7 +30,7 @@
<% end %> <% end %>
<% end %> <% end %>
<% if @submitter.completed_at > 30.minutes.ago || (current_user && current_user.account.submitters.exists?(id: @submitter.id)) %> <% if @submitter.completed_at > 30.minutes.ago || (current_user && current_user.account.submitters.exists?(id: @submitter.id)) %>
<download-button data-src="<%= submit_form_documents_path(@submitter.slug) %>" class="base-button w-full"> <download-button role="button" tabindex="0" aria-label="<%= t('download_documents') %>" data-src="<%= submit_form_documents_path(@submitter.slug) %>" class="base-button w-full">
<span class="flex items-center justify-center space-x-2" data-target="download-button.defaultButton"> <span class="flex items-center justify-center space-x-2" data-target="download-button.defaultButton">
<%= svg_icon('download', class: 'w-6 h-6') %> <%= svg_icon('download', class: 'w-6 h-6') %>
<span><%= t('download_documents') %></span> <span><%= t('download_documents') %></span>
@ -50,5 +50,5 @@
</toggle-submit> </toggle-submit>
<% end %> <% end %>
</div> </div>
</div> </main>
<%= render 'shared/attribution', link_path: '/start', account: @submitter.account %> <%= render 'shared/attribution', link_path: '/start', account: @submitter.account %>

@ -2,7 +2,7 @@
<% I18n.with_locale(@submitter.account.locale) do %> <% I18n.with_locale(@submitter.account.locale) do %>
<% content_for(:html_description, t('account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution', account_name: @submitter.account.name)) %> <% content_for(:html_description, t('account_name_has_invited_you_to_fill_and_sign_documents_online_effortlessly_with_a_secure_fast_and_user_friendly_digital_document_signing_solution', account_name: @submitter.account.name)) %>
<% end %> <% end %>
<div class="max-w-md mx-auto px-2 mt-12 mb-4"> <main class="max-w-md mx-auto px-2 mt-12 mb-4">
<div class="space-y-6 mx-auto"> <div class="space-y-6 mx-auto">
<div class="space-y-6"> <div class="space-y-6">
<div class="flex items-center justify-center"> <div class="flex items-center justify-center">
@ -46,7 +46,7 @@
<% end %> <% end %>
</span> </span>
<span> <span>
<label for="resend_code" id="resend_label" class="link"><%= t(:re_send_email) %></label> <button type="submit" form="resend_code_form" class="link"><%= t(:re_send_email) %></button>
</span> </span>
</div> </div>
</div> </div>
@ -54,7 +54,7 @@
<%= f.button button_title(title: t('submit')), class: 'base-button' %> <%= f.button button_title(title: t('submit')), class: 'base-button' %>
</toggle-submit> </toggle-submit>
<% end %> <% end %>
<%= button_to t(:re_send_email), submit_form_email_2fa_path, params: { submitter_slug: @submitter.slug, resend: true }, method: :put, id: 'resend_code', class: 'hidden' %> <%= button_to t(:re_send_email), submit_form_email_2fa_path, params: { submitter_slug: @submitter.slug, resend: true }, method: :put, form: { id: 'resend_code_form', class: 'hidden' } %>
<% else %> <% else %>
<% if params[:t] %> <% if params[:t] %>
<fetch-form data-onload="true"> <fetch-form data-onload="true">
@ -69,4 +69,4 @@
<div><%= t('please_contact_the_requester_to_specify_your_email_for_two_factor_authentication') %></div> <div><%= t('please_contact_the_requester_to_specify_your_email_for_two_factor_authentication') %></div>
<% end %> <% end %>
</div> </div>
</div> </main>

@ -8,28 +8,32 @@
<% page_blob_struct = Struct.new(:url, :metadata) %> <% page_blob_struct = Struct.new(:url, :metadata) %>
<% schema = Submissions.filtered_conditions_schema(@submitter.submission, values:, include_submitter_uuid: @submitter.uuid) %> <% schema = Submissions.filtered_conditions_schema(@submitter.submission, values:, include_submitter_uuid: @submitter.uuid) %>
<% font_scale = 1000.0 / PdfUtils::US_LETTER_W %> <% font_scale = 1000.0 / PdfUtils::US_LETTER_W %>
<% decline_modal_checkbox_uuid = nil %> <% decline_modal_id = nil %>
<% delegate_modal_checkbox_uuid = nil %> <% delegate_modal_id = nil %>
<div style="max-height: -webkit-fill-available;"> <div style="max-height: -webkit-fill-available;">
<div id="scrollbox"> <main id="scrollbox">
<div class="mx-auto block pb-72" style="max-width: 1000px"> <div class="mx-auto block pb-72" style="max-width: 1000px">
<%# flex block w-full sticky top-0 z-50 space-x-2 items-center bg-yellow-100 p-2 border-y border-yellow-200 transition-transform duration-300 %> <%# flex block w-full sticky top-0 z-50 space-x-2 items-center bg-yellow-100 p-2 border-y border-yellow-200 transition-transform duration-300 %>
<%= local_assigns[:banner_html] || capture do %> <%= local_assigns[:banner_html] || capture do %>
<%= render('submit_form/banner') %> <%= render('submit_form/banner') %>
<div id="signing_form_header" class="sticky min-[1230px]:static top-0 z-50 bg-base-100 py-2 px-2 flex items-center md:-mx-[8px]" style="margin-bottom: -16px"> <header id="signing_form_header" class="sticky min-[1230px]:static top-0 z-50 bg-base-100 py-2 px-2 flex items-center md:-mx-[8px]" style="margin-bottom: -16px">
<div class="text-xl md:text-2xl font-medium focus:text-clip" style="width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"> <h1 class="text-xl md:text-2xl font-medium focus:text-clip" style="width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
<%= @submitter.submission.name || @submitter.submission.template.name %> <%= @submitter.submission.name || @submitter.submission.template.name %>
</div> </h1>
<div class="flex items-center space-x-2" style="margin-left: 20px; flex-shrink: 0"> <div class="flex items-center space-x-2" style="margin-left: 20px; flex-shrink: 0">
<% if @form_configs[:with_delegate] %> <% if @form_configs[:with_delegate] %>
<label id="delegate_button" for="<%= delegate_modal_checkbox_uuid = SecureRandom.uuid %>" class="btn btn-sm !px-5"><%= t(:delegate) %></label> <modal-button data-target="<%= delegate_modal_id = SecureRandom.uuid %>">
<button id="delegate_button" type="button" class="btn btn-sm !px-5"><%= t(:delegate) %></button>
</modal-button>
<% if @form_configs[:with_decline] %> <% if @form_configs[:with_decline] %>
<label id="decline_button" for="<%= decline_modal_checkbox_uuid = SecureRandom.uuid %>" class="btn btn-sm px-2" title="<%= t(:decline) %>"> <modal-button data-target="<%= decline_modal_id = SecureRandom.uuid %>">
<button id="decline_button" type="button" class="btn btn-sm px-2" aria-label="<%= t(:decline) %>">
<%= svg_icon('x', class: 'w-5 h-5') %> <%= svg_icon('x', class: 'w-5 h-5') %>
</label> </button>
</modal-button>
<% end %> <% end %>
<% if @form_configs[:with_partial_download] %> <% if @form_configs[:with_partial_download] %>
<download-button data-src="<%= submit_form_download_index_path(@submitter.slug) %>" class="btn btn-neutral text-white btn-sm px-2" title="<%= t('download') %>"> <download-button role="button" tabindex="0" data-src="<%= submit_form_download_index_path(@submitter.slug) %>" class="btn btn-neutral text-white btn-sm px-2" title="<%= t('download') %>" aria-label="<%= t('download') %>">
<span data-target="download-button.defaultButton"> <span data-target="download-button.defaultButton">
<%= svg_icon('download', class: 'w-5 h-5') %> <%= svg_icon('download', class: 'w-5 h-5') %>
</span> </span>
@ -40,10 +44,12 @@
<% end %> <% end %>
<% else %> <% else %>
<% if @form_configs[:with_decline] %> <% if @form_configs[:with_decline] %>
<label id="decline_button" for="<%= decline_modal_checkbox_uuid = SecureRandom.uuid %>" class="btn btn-sm !px-5"><%= t(:decline) %></label> <modal-button data-target="<%= decline_modal_id = SecureRandom.uuid %>">
<button id="decline_button" type="button" class="btn btn-sm !px-5"><%= t(:decline) %></button>
</modal-button>
<% end %> <% end %>
<% if @form_configs[:with_partial_download] %> <% if @form_configs[:with_partial_download] %>
<download-button data-src="<%= submit_form_download_index_path(@submitter.slug) %>" class="btn btn-neutral text-white btn-sm !px-4"> <download-button role="button" tabindex="0" data-src="<%= submit_form_download_index_path(@submitter.slug) %>" class="btn btn-neutral text-white btn-sm !px-4" aria-label="<%= t('download') %>">
<span class="flex items-center justify-center" data-target="download-button.defaultButton"> <span class="flex items-center justify-center" data-target="download-button.defaultButton">
<%= svg_icon('download', class: 'w-6 h-6 inline md:hidden') %> <%= svg_icon('download', class: 'w-6 h-6 inline md:hidden') %>
<span class="hidden md:inline"><%= t('download') %></span> <span class="hidden md:inline"><%= t('download') %></span>
@ -56,23 +62,27 @@
<% end %> <% end %>
<% end %> <% end %>
</div> </div>
</div> </header>
<scroll-buttons class="fixed right-5 top-2 hidden md:flex gap-1 z-50 ease-in-out opacity-0 -translate-y-10"> <scroll-buttons class="fixed right-5 top-2 hidden md:flex gap-1 z-50 ease-in-out opacity-0 -translate-y-10">
<% if @form_configs[:with_delegate] %> <% if @form_configs[:with_delegate] %>
<label id="delegate_button" for="<%= delegate_modal_checkbox_uuid %>" class="btn btn-sm px-0"> <modal-button data-target="<%= delegate_modal_id %>">
<button id="delegate_button_mobile" type="button" class="btn btn-sm px-0" aria-label="<%= t(:delegate) %>" tabindex="-1">
<span class="min-[1366px]:inline hidden px-3"> <span class="min-[1366px]:inline hidden px-3">
<%= t(:delegate) %> <%= t(:delegate) %>
</span> </span>
<span class="inline min-[1366px]:hidden px-2"> <span class="inline min-[1366px]:hidden px-2">
<%= svg_icon('user_share', class: 'w-5 h-5') %> <%= svg_icon('user_share', class: 'w-5 h-5') %>
</span> </span>
</label> </button>
</modal-button>
<% if @form_configs[:with_decline] %> <% if @form_configs[:with_decline] %>
<label id="decline_button" for="<%= decline_modal_checkbox_uuid %>" class="btn btn-sm px-2"> <modal-button data-target="<%= decline_modal_id %>">
<button id="decline_button_mobile" type="button" class="btn btn-sm px-2" aria-label="<%= t(:decline) %>" tabindex="-1">
<%= svg_icon('x', class: 'w-5 h-5') %> <%= svg_icon('x', class: 'w-5 h-5') %>
</label> </button>
</modal-button>
<% end %> <% end %>
<download-button data-src="<%= submit_form_download_index_path(@submitter.slug) %>" class="btn btn-neutral text-white btn-sm px-2"> <download-button role="button" tabindex="-1" data-src="<%= submit_form_download_index_path(@submitter.slug) %>" class="btn btn-neutral text-white btn-sm px-2" aria-label="<%= t('download') %>">
<span data-target="download-button.defaultButton"> <span data-target="download-button.defaultButton">
<%= svg_icon('download', class: 'w-5 h-5') %> <%= svg_icon('download', class: 'w-5 h-5') %>
</span> </span>
@ -82,16 +92,18 @@
</download-button> </download-button>
<% else %> <% else %>
<% if @form_configs[:with_decline] %> <% if @form_configs[:with_decline] %>
<label id="decline_button" for="<%= decline_modal_checkbox_uuid %>" class="btn btn-sm px-0"> <modal-button data-target="<%= decline_modal_id %>">
<button id="decline_button_mobile" type="button" class="btn btn-sm px-0" aria-label="<%= t(:decline) %>" tabindex="-1">
<span class="min-[1366px]:inline hidden px-3"> <span class="min-[1366px]:inline hidden px-3">
<%= t(:decline) %> <%= t(:decline) %>
</span> </span>
<span class="inline min-[1366px]:hidden px-2"> <span class="inline min-[1366px]:hidden px-2">
<%= svg_icon('x', class: 'w-5 h-5') %> <%= svg_icon('x', class: 'w-5 h-5') %>
</span> </span>
</label> </button>
</modal-button>
<% end %> <% end %>
<download-button data-src="<%= submit_form_download_index_path(@submitter.slug) %>" class="btn btn-neutral text-white btn-sm px-2"> <download-button role="button" tabindex="-1" data-src="<%= submit_form_download_index_path(@submitter.slug) %>" class="btn btn-neutral text-white btn-sm px-2" aria-label="<%= t('download') %>">
<span data-target="download-button.defaultButton"> <span data-target="download-button.defaultButton">
<%= svg_icon('download', class: 'w-5 h-5') %> <%= svg_icon('download', class: 'w-5 h-5') %>
</span> </span>
@ -111,7 +123,7 @@
<% (document.metadata.dig('pdf', 'number_of_pages') || (document.preview_images.loaded? ? preview_images_index.size : document.preview_images.size)).times do |index| %> <% (document.metadata.dig('pdf', 'number_of_pages') || (document.preview_images.loaded? ? preview_images_index.size : document.preview_images.size)).times do |index| %>
<% page = preview_images_index[index] || page_blob_struct.new(metadata: lazyload_metadata, url: preview_document_page_path(document.signed_key, "#{index}.jpg")) %> <% page = preview_images_index[index] || page_blob_struct.new(metadata: lazyload_metadata, url: preview_document_page_path(document.signed_key, "#{index}.jpg")) %>
<page-container class="block relative my-4 shadow-md" style="container-type: size; aspect-ratio: <%= width = page.metadata['width'] %> / <%= height = page.metadata['height'] %>"> <page-container class="block relative my-4 shadow-md" style="container-type: size; aspect-ratio: <%= width = page.metadata['width'] %> / <%= height = page.metadata['height'] %>">
<img loading="lazy" src="<%= page.url %>" width="<%= width %>" height="<%= height %>"> <img loading="lazy" src="<%= page.url %>" width="<%= width %>" height="<%= height %>" alt="<%= "#{item['name']} - #{t('page')} #{index + 1}" %>">
<div id="page-<%= [document.uuid, index].join('-') %>" class="top-0 bottom-0 left-0 right-0 absolute"> <div id="page-<%= [document.uuid, index].join('-') %>" class="top-0 bottom-0 left-0 right-0 absolute">
<% if annots = document_annots_index[index] %> <% if annots = document_annots_index[index] %>
<%= render 'submit_form/annotations', annots: %> <%= render 'submit_form/annotations', annots: %>
@ -140,7 +152,7 @@
</div> </div>
<% end %> <% end %>
</div> </div>
</div> </main>
</div> </div>
<div class="fixed bottom-0 w-full h-0 z-50"> <div class="fixed bottom-0 w-full h-0 z-50">
<div class="mx-auto" style="max-width: 1000px"> <div class="mx-auto" style="max-width: 1000px">
@ -150,12 +162,12 @@
</div> </div>
</div> </div>
<% if @form_configs[:with_decline] %> <% if @form_configs[:with_decline] %>
<%= render 'shared/html_modal', title: t(:decline), uuid: decline_modal_checkbox_uuid do %> <%= render 'shared/html_modal', title: t(:decline), uuid: decline_modal_id do %>
<%= render 'submit_form/decline_form', submitter: @submitter %> <%= render 'submit_form/decline_form', submitter: @submitter %>
<% end %> <% end %>
<% end %> <% end %>
<% if @form_configs[:with_delegate] %> <% if @form_configs[:with_delegate] %>
<%= render 'shared/html_modal', title: t(:delegate), uuid: delegate_modal_checkbox_uuid do %> <%= render 'shared/html_modal', title: t(:delegate), uuid: delegate_modal_id do %>
<%= render 'submit_form/delegate_form', submitter: @submitter %> <%= render 'submit_form/delegate_form', submitter: @submitter %>
<% end %> <% end %>
<% end %> <% end %>

@ -162,6 +162,7 @@ en: &en
download_documents: Download documents download_documents: Download documents
downloading: Downloading downloading: Downloading
download: Download download: Download
page: Page
decline: Decline decline: Decline
declined: Declined declined: Declined
delegate: Delegate delegate: Delegate
@ -1204,6 +1205,7 @@ es: &es
download_documents: Descargar documentos download_documents: Descargar documentos
downloading: Descargando downloading: Descargando
download: Descargar download: Descargar
page: Página
decline: Rechazar decline: Rechazar
delegate: Delegar delegate: Delegar
enter_the_email_address_of_the_person_you_want_to_delegate_to: Ingrese la dirección de correo electrónico de la persona a quien desea delegar enter_the_email_address_of_the_person_you_want_to_delegate_to: Ingrese la dirección de correo electrónico de la persona a quien desea delegar
@ -2243,6 +2245,7 @@ it: &it
download_documents: Scarica documenti download_documents: Scarica documenti
downloading: Scaricamento downloading: Scaricamento
download: Scarica download: Scarica
page: Pagina
decline: Rifiuta decline: Rifiuta
delegate: Delega delegate: Delega
enter_the_email_address_of_the_person_you_want_to_delegate_to: Inserisci l'indirizzo email della persona a cui vuoi delegare enter_the_email_address_of_the_person_you_want_to_delegate_to: Inserisci l'indirizzo email della persona a cui vuoi delegare
@ -3283,6 +3286,7 @@ fr: &fr
download_documents: Télécharger les documents download_documents: Télécharger les documents
downloading: Téléchargement downloading: Téléchargement
download: Télécharger download: Télécharger
page: Page
decline: Refuser decline: Refuser
delegate: Déléguer delegate: Déléguer
enter_the_email_address_of_the_person_you_want_to_delegate_to: Saisissez l'adresse e-mail de la personne à qui vous souhaitez déléguer enter_the_email_address_of_the_person_you_want_to_delegate_to: Saisissez l'adresse e-mail de la personne à qui vous souhaitez déléguer
@ -4319,6 +4323,7 @@ pt: &pt
download_documents: Baixar documentos download_documents: Baixar documentos
downloading: Baixando downloading: Baixando
download: Baixar download: Baixar
page: Página
decline: Recusar decline: Recusar
delegate: Delegar delegate: Delegar
enter_the_email_address_of_the_person_you_want_to_delegate_to: Insira o endereço de e-mail da pessoa para quem deseja delegar enter_the_email_address_of_the_person_you_want_to_delegate_to: Insira o endereço de e-mail da pessoa para quem deseja delegar
@ -5358,6 +5363,7 @@ de: &de
download_documents: Dokumente herunterladen download_documents: Dokumente herunterladen
downloading: Wird heruntergeladen downloading: Wird heruntergeladen
download: Download download: Download
page: Seite
decline: Ablehnen decline: Ablehnen
delegate: Delegieren delegate: Delegieren
enter_the_email_address_of_the_person_you_want_to_delegate_to: Geben Sie die E-Mail-Adresse der Person ein, an die Sie delegieren möchten enter_the_email_address_of_the_person_you_want_to_delegate_to: Geben Sie die E-Mail-Adresse der Person ein, an die Sie delegieren möchten
@ -6261,6 +6267,7 @@ pl:
view: Widok view: Widok
hi_there: Cześć, hi_there: Cześć,
download: Pobierz download: Pobierz
page: Strona
decline: Odrzuć decline: Odrzuć
delegate: Deleguj delegate: Deleguj
enter_the_email_address_of_the_person_you_want_to_delegate_to: Wprowadź adres e-mail osoby, do której chcesz delegować enter_the_email_address_of_the_person_you_want_to_delegate_to: Wprowadź adres e-mail osoby, do której chcesz delegować
@ -6361,6 +6368,7 @@ uk:
view: Переглянути view: Переглянути
hi_there: Привіт, hi_there: Привіт,
download: Завантажити download: Завантажити
page: Сторінка
decline: Відхилити decline: Відхилити
delegate: Делегувати delegate: Делегувати
enter_the_email_address_of_the_person_you_want_to_delegate_to: Введіть адресу електронної пошти особи, якій ви хочете делегувати enter_the_email_address_of_the_person_you_want_to_delegate_to: Введіть адресу електронної пошти особи, якій ви хочете делегувати
@ -6461,6 +6469,7 @@ cs:
view: Zobrazit view: Zobrazit
hi_there: Ahoj, hi_there: Ahoj,
download: Stáhnout download: Stáhnout
page: Stránka
decline: Odmítnout decline: Odmítnout
delegate: Delegovat delegate: Delegovat
enter_the_email_address_of_the_person_you_want_to_delegate_to: Zadejte e-mailovou adresu osoby, na kterou chcete delegovat enter_the_email_address_of_the_person_you_want_to_delegate_to: Zadejte e-mailovou adresu osoby, na kterou chcete delegovat
@ -6561,6 +6570,7 @@ he:
view: תצוגה view: תצוגה
hi_there: שלום, hi_there: שלום,
download: הורד download: הורד
page: עמוד
decline: דחייה decline: דחייה
delegate: הואלה delegate: הואלה
enter_the_email_address_of_the_person_you_want_to_delegate_to: הזן את כתובת הדוא"ל של האדם שברצונך להאציל אליו enter_the_email_address_of_the_person_you_want_to_delegate_to: הזן את כתובת הדוא"ל של האדם שברצונך להאציל אליו
@ -6798,6 +6808,7 @@ nl: &nl
download_documents: Documenten downloaden download_documents: Documenten downloaden
downloading: Downloaden downloading: Downloaden
download: Downloaden download: Downloaden
page: Pagina
decline: Weigeren decline: Weigeren
delegate: Delegeren delegate: Delegeren
enter_the_email_address_of_the_person_you_want_to_delegate_to: Voer het e-mailadres in van de persoon aan wie u wilt delegeren enter_the_email_address_of_the_person_you_want_to_delegate_to: Voer het e-mailadres in van de persoon aan wie u wilt delegeren
@ -7697,6 +7708,7 @@ ar:
view: عرض view: عرض
hi_there: مرحبا, hi_there: مرحبا,
download: تحميل download: تحميل
page: صفحة
decline: رفض decline: رفض
delegate: تفويض delegate: تفويض
enter_the_email_address_of_the_person_you_want_to_delegate_to: أدخل عنوان البريد الإلكتروني للشخص الذي تريد التفويض إليه enter_the_email_address_of_the_person_you_want_to_delegate_to: أدخل عنوان البريد الإلكتروني للشخص الذي تريد التفويض إليه
@ -7797,6 +7809,7 @@ ko:
view: 보기 view: 보기
hi_there: 안녕하세요, hi_there: 안녕하세요,
download: 다운로드 download: 다운로드
page: 페이지
decline: 거절 decline: 거절
delegate: 위임 delegate: 위임
enter_the_email_address_of_the_person_you_want_to_delegate_to: 위임할 사람의 이메일 주소를 입력하세요 enter_the_email_address_of_the_person_you_want_to_delegate_to: 위임할 사람의 이메일 주소를 입력하세요
@ -7897,6 +7910,7 @@ ja:
view: 表示 view: 表示
hi_there: こんにちは hi_there: こんにちは
download: ダウンロード download: ダウンロード
page: ページ
decline: 辞退 decline: 辞退
delegate: 委任 delegate: 委任
enter_the_email_address_of_the_person_you_want_to_delegate_to: 委任したい人のメールアドレスを入力してください enter_the_email_address_of_the_person_you_want_to_delegate_to: 委任したい人のメールアドレスを入力してください

Loading…
Cancel
Save