set default value
This commit is contained in:
@@ -111,6 +111,7 @@ module Api
|
|||||||
:required, :readonly, :default_value,
|
:required, :readonly, :default_value,
|
||||||
:title, :description, :prefillable,
|
:title, :description, :prefillable,
|
||||||
{ preferences: {},
|
{ preferences: {},
|
||||||
|
default_value: [],
|
||||||
conditions: [%i[field_uuid value action operation]],
|
conditions: [%i[field_uuid value action operation]],
|
||||||
options: [%i[value uuid]],
|
options: [%i[value uuid]],
|
||||||
validation: %i[message pattern min max step],
|
validation: %i[message pattern min max step],
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ class TemplatesController < ApplicationController
|
|||||||
:required, :readonly, :default_value,
|
:required, :readonly, :default_value,
|
||||||
:title, :description, :prefillable,
|
:title, :description, :prefillable,
|
||||||
{ preferences: {},
|
{ preferences: {},
|
||||||
|
default_value: [],
|
||||||
conditions: [%i[field_uuid value action operation]],
|
conditions: [%i[field_uuid value action operation]],
|
||||||
options: [%i[value uuid]],
|
options: [%i[value uuid]],
|
||||||
validation: %i[message pattern min max step],
|
validation: %i[message pattern min max step],
|
||||||
|
|||||||
@@ -422,10 +422,14 @@ export default {
|
|||||||
},
|
},
|
||||||
formattedDate () {
|
formattedDate () {
|
||||||
if (this.field.type === 'date' && this.modelValue) {
|
if (this.field.type === 'date' && this.modelValue) {
|
||||||
return this.formatDate(
|
try {
|
||||||
this.modelValue === '{{date}}' ? new Date() : new Date(this.modelValue),
|
return this.formatDate(
|
||||||
this.field.preferences?.format || (this.locale.endsWith('-US') ? 'MM/DD/YYYY' : 'DD/MM/YYYY')
|
this.modelValue === '{{date}}' ? new Date() : new Date(this.modelValue),
|
||||||
)
|
this.field.preferences?.format || (this.locale.endsWith('-US') ? 'MM/DD/YYYY' : 'DD/MM/YYYY')
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
return this.modelValue
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,11 +72,11 @@
|
|||||||
@blur="onNameBlur"
|
@blur="onNameBlur"
|
||||||
>{{ optionIndexText }} {{ (defaultField ? (defaultField.title || field.title || field.name) : field.name) || defaultName }}</span>
|
>{{ optionIndexText }} {{ (defaultField ? (defaultField.title || field.title || field.name) : field.name) || defaultName }}</span>
|
||||||
<div
|
<div
|
||||||
v-if="isSettingsFocus || (isValueInput && field.type !== 'heading') || (isNameFocus && !['checkbox', 'phone'].includes(field.type))"
|
v-if="isSettingsFocus || isSelectInput || (isValueInput && field.type !== 'heading') || (isNameFocus && !['checkbox', 'phone'].includes(field.type))"
|
||||||
class="flex items-center ml-1.5"
|
class="flex items-center ml-1.5"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
v-if="!isValueInput"
|
v-if="!isValueInput && !isSelectInput"
|
||||||
:id="`required-checkbox-${field.uuid}`"
|
:id="`required-checkbox-${field.uuid}`"
|
||||||
v-model="field.required"
|
v-model="field.required"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@@ -84,14 +84,14 @@
|
|||||||
@mousedown.prevent
|
@mousedown.prevent
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
v-if="!isValueInput"
|
v-if="!isValueInput && !isSelectInput"
|
||||||
:for="`required-checkbox-${field.uuid}`"
|
:for="`required-checkbox-${field.uuid}`"
|
||||||
class="label text-xs"
|
class="label text-xs"
|
||||||
@click.prevent="field.required = !field.required"
|
@click.prevent="field.required = !field.required"
|
||||||
@mousedown.prevent
|
@mousedown.prevent
|
||||||
>{{ t('required') }}</label>
|
>{{ t('required') }}</label>
|
||||||
<input
|
<input
|
||||||
v-if="isValueInput"
|
v-if="isValueInput || isSelectInput"
|
||||||
:id="`readonly-checkbox-${field.uuid}`"
|
:id="`readonly-checkbox-${field.uuid}`"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="checkbox checkbox-xs no-animation rounded"
|
class="checkbox checkbox-xs no-animation rounded"
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
@mousedown.prevent
|
@mousedown.prevent
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
v-if="isValueInput"
|
v-if="isValueInput || isSelectInput"
|
||||||
:for="`readonly-checkbox-${field.uuid}`"
|
:for="`readonly-checkbox-${field.uuid}`"
|
||||||
class="label text-xs"
|
class="label text-xs"
|
||||||
@click.prevent="field.readonly = !(field.readonly ?? true)"
|
@click.prevent="field.readonly = !(field.readonly ?? true)"
|
||||||
@@ -164,30 +164,39 @@
|
|||||||
ref="touchValueTarget"
|
ref="touchValueTarget"
|
||||||
class="flex h-full w-full field-area"
|
class="flex h-full w-full field-area"
|
||||||
dir="auto"
|
dir="auto"
|
||||||
:class="[isValueInput ? 'bg-opacity-50' : 'bg-opacity-80', field.type === 'heading' ? 'bg-gray-50' : bgColors[submitterIndex % bgColors.length], isDefaultValuePresent || isValueInput || (withFieldPlaceholder && field.areas) ? fontClasses : 'justify-center items-center']"
|
:class="[isValueInput ? 'cursor-text' : '', isValueInput || isCheckboxInput || isSelectInput ? 'bg-opacity-50' : 'bg-opacity-80', field.type === 'heading' ? 'bg-gray-50' : bgColors[submitterIndex % bgColors.length], isDefaultValuePresent || isValueInput || (withFieldPlaceholder && field.areas) ? fontClasses : 'justify-center items-center']"
|
||||||
@click="focusValueInput"
|
@click="focusValueInput"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
v-if="field"
|
v-if="field"
|
||||||
class="flex justify-center items-center space-x-1"
|
class="flex justify-center items-center space-x-1"
|
||||||
:class="{ 'w-full': ['cells', 'checkbox'].includes(field.type), 'h-full': !isValueInput && !isDefaultValuePresent }"
|
:class="{ 'w-full': isWFullType, 'h-full': !isValueInput && !isDefaultValuePresent }"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="isDefaultValuePresent || isValueInput || (withFieldPlaceholder && field.areas && field.type !== 'checkbox')"
|
v-if="isDefaultValuePresent || isValueInput || isSelectInput || (withFieldPlaceholder && field.areas && field.type !== 'checkbox')"
|
||||||
:class="{ 'w-full h-full': ['cells', 'checkbox'].includes(field.type) }"
|
:class="{ 'w-full h-full': isWFullType }"
|
||||||
:style="fontStyle"
|
:style="fontStyle"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
ref="textContainer"
|
ref="textContainer"
|
||||||
class="flex items-center px-0.5"
|
class="flex items-center px-0.5"
|
||||||
:style="{ color: field.preferences?.color }"
|
:style="{ color: field.preferences?.color }"
|
||||||
:class="{ 'w-full h-full': ['cells', 'checkbox'].includes(field.type) }"
|
:class="{ 'w-full h-full': isWFullType }"
|
||||||
>
|
>
|
||||||
<IconCheck
|
<IconCheck
|
||||||
v-if="field.type == 'checkbox'"
|
v-if="field.type == 'checkbox'"
|
||||||
class="aspect-square mx-auto"
|
class="aspect-square mx-auto"
|
||||||
: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 }"
|
||||||
/>
|
/>
|
||||||
|
<template
|
||||||
|
v-else-if="(field.type === 'radio' || field.type === 'multiple') && field?.areas?.length > 1"
|
||||||
|
>
|
||||||
|
<IconCheck
|
||||||
|
v-if="field.type === 'multiple' ? field.default_value.includes(optionsUuidIndex[area.option_uuid].value) : optionsUuidIndex[area.option_uuid].value === field.default_value"
|
||||||
|
class="aspect-square mx-auto"
|
||||||
|
:class="{ '!w-auto !h-full': area.w > area.h, '!w-full !h-auto': area.w <= area.h }"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
<span
|
<span
|
||||||
v-else-if="field.type === 'number' && !isValueInput && (field.default_value || field.default_value == 0)"
|
v-else-if="field.type === 'number' && !isValueInput && (field.default_value || field.default_value == 0)"
|
||||||
class="whitespace-pre-wrap"
|
class="whitespace-pre-wrap"
|
||||||
@@ -210,14 +219,39 @@
|
|||||||
{{ char }}
|
{{ char }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<select
|
||||||
|
v-else-if="isSelectInput"
|
||||||
|
ref="defaultValueSelect"
|
||||||
|
class="bg-transparent outline-none focus:outline-none w-full"
|
||||||
|
@change="[field.default_value = $event.target.value, field.readonly = !!field.default_value?.length, save()]"
|
||||||
|
@focus="selectedAreaRef.value = area"
|
||||||
|
@keydown.enter="onDefaultValueEnter"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
:disabled="!field.default_value?.length"
|
||||||
|
:selected="!field.default_value?.length"
|
||||||
|
:value="''"
|
||||||
|
>
|
||||||
|
{{ t(field.default_value?.length ? 'none' : 'select') }}
|
||||||
|
</option>
|
||||||
|
<option
|
||||||
|
v-for="(option, index) in field.options"
|
||||||
|
:key="index"
|
||||||
|
:selected="field.default_value === option.value"
|
||||||
|
:value="option.value"
|
||||||
|
>
|
||||||
|
{{ option.value }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
<span
|
<span
|
||||||
v-else
|
v-else
|
||||||
ref="defaultValue"
|
ref="defaultValue"
|
||||||
:contenteditable="isValueInput"
|
:contenteditable="isValueInput"
|
||||||
class="whitespace-pre-wrap outline-none empty:before:content-[attr(placeholder)] before:text-gray-400"
|
class="whitespace-pre-wrap outline-none empty:before:content-[attr(placeholder)] before:text-base-content/30"
|
||||||
:class="{ 'cursor-text': isValueInput }"
|
:class="{ 'cursor-text': isValueInput }"
|
||||||
:placeholder="withFieldPlaceholder && !isValueInput ? defaultField?.title || field.title || field.name || defaultName : t('type_value')"
|
:placeholder="withFieldPlaceholder && !isValueInput ? defaultField?.title || field.title || field.name || defaultName : (field.type === 'date' ? field.preferences.format || t('type_value') : t('type_value'))"
|
||||||
@blur="onDefaultValueBlur"
|
@blur="onDefaultValueBlur"
|
||||||
|
@focus="selectedAreaRef.value = area"
|
||||||
@paste.prevent="onPaste"
|
@paste.prevent="onPaste"
|
||||||
@keydown.enter="onDefaultValueEnter"
|
@keydown.enter="onDefaultValueEnter"
|
||||||
>{{ field.default_value }}</span>
|
>{{ field.default_value }}</span>
|
||||||
@@ -225,7 +259,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<component
|
<component
|
||||||
:is="fieldIcons[field.type]"
|
:is="fieldIcons[field.type]"
|
||||||
v-else
|
v-else-if="!isCheckboxInput"
|
||||||
width="100%"
|
width="100%"
|
||||||
height="100%"
|
height="100%"
|
||||||
class="max-h-10 opacity-50"
|
class="max-h-10 opacity-50"
|
||||||
@@ -233,12 +267,12 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="!isValueInput"
|
v-if="!isValueInput && !isSelectInput"
|
||||||
ref="touchTarget"
|
ref="touchTarget"
|
||||||
class="absolute top-0 bottom-0 right-0 left-0"
|
class="absolute top-0 bottom-0 right-0 left-0"
|
||||||
:class="isDragged ? 'cursor-grab' : 'cursor-pointer'"
|
:class="isDragged ? 'cursor-grab' : 'cursor-pointer'"
|
||||||
@dblclick="maybeToggleDefaultValue"
|
@dblclick="maybeToggleDefaultValue"
|
||||||
@click="maybeToggleCheckboxValue"
|
@click="inputMode && maybeToggleCheckboxValue()"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
v-if="field?.type && editable"
|
v-if="field?.type && editable"
|
||||||
@@ -398,6 +432,9 @@ export default {
|
|||||||
fieldNames: FieldType.computed.fieldNames,
|
fieldNames: FieldType.computed.fieldNames,
|
||||||
fieldLabels: FieldType.computed.fieldLabels,
|
fieldLabels: FieldType.computed.fieldLabels,
|
||||||
fieldIcons: FieldType.computed.fieldIcons,
|
fieldIcons: FieldType.computed.fieldIcons,
|
||||||
|
isWFullType () {
|
||||||
|
return ['cells', 'checkbox', 'radio', 'multiple', 'select'].includes(this.field.type)
|
||||||
|
},
|
||||||
fontStyle () {
|
fontStyle () {
|
||||||
let fontSize = ''
|
let fontSize = ''
|
||||||
|
|
||||||
@@ -417,6 +454,13 @@ export default {
|
|||||||
|
|
||||||
return { fontSize, lineHeight: `calc(${fontSize} * ${this.lineHeight})` }
|
return { fontSize, lineHeight: `calc(${fontSize} * ${this.lineHeight})` }
|
||||||
},
|
},
|
||||||
|
optionsUuidIndex () {
|
||||||
|
return this.field.options.reduce((acc, option) => {
|
||||||
|
acc[option.uuid] = option
|
||||||
|
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
},
|
||||||
fontSizePx () {
|
fontSizePx () {
|
||||||
return parseInt(this.field?.preferences?.font_size || 11) * this.fontScale
|
return parseInt(this.field?.preferences?.font_size || 11) * this.fontScale
|
||||||
},
|
},
|
||||||
@@ -427,14 +471,17 @@ export default {
|
|||||||
return 1040 / 612.0
|
return 1040 / 612.0
|
||||||
},
|
},
|
||||||
isDefaultValuePresent () {
|
isDefaultValuePresent () {
|
||||||
if (this.field?.type === 'radio' && this.field?.areas?.length > 1) {
|
return this.field?.default_value || this.field?.default_value === 0
|
||||||
return false
|
},
|
||||||
} else {
|
isSelectInput () {
|
||||||
return this.field?.default_value || this.field?.default_value === 0
|
return this.inputMode && (this.field.type === 'select' || (this.field.type === 'radio' && this.field.areas?.length < 2))
|
||||||
}
|
},
|
||||||
|
isCheckboxInput () {
|
||||||
|
return this.inputMode && (this.field.type === 'checkbox' || (['radio', 'multiple'].includes(this.field.type) && this.area.option_uuid))
|
||||||
},
|
},
|
||||||
isValueInput () {
|
isValueInput () {
|
||||||
return (this.field.type === 'heading' && this.isHeadingSelected) || this.isContenteditable || (this.inputMode && ['text', 'number', 'date'].includes(this.field.type))
|
return (this.field.type === 'heading' && this.isHeadingSelected) || this.isContenteditable ||
|
||||||
|
(this.inputMode && (['text', 'number'].includes(this.field.type) || (this.field.type === 'date' && this.field.default_value !== '{{date}}')))
|
||||||
},
|
},
|
||||||
modalContainerEl () {
|
modalContainerEl () {
|
||||||
return this.$el.getRootNode().querySelector('#docuseal_modal_container')
|
return this.$el.getRootNode().querySelector('#docuseal_modal_container')
|
||||||
@@ -558,22 +605,45 @@ export default {
|
|||||||
this.isContenteditable = true
|
this.isContenteditable = true
|
||||||
|
|
||||||
this.focusValueInput()
|
this.focusValueInput()
|
||||||
} else if (this.field.type === 'checkbox') {
|
|
||||||
this.field.readonly = !this.field.readonly
|
|
||||||
this.field.default_value === true ? delete this.field.default_value : this.field.default_value = true
|
|
||||||
|
|
||||||
this.save()
|
|
||||||
} else if (this.field.type === 'date') {
|
} else if (this.field.type === 'date') {
|
||||||
this.field.readonly = !this.field.readonly
|
this.field.readonly = !this.field.readonly
|
||||||
this.field.default_value === '{{date}}' ? delete this.field.default_value : this.field.default_value = '{{date}}'
|
this.field.default_value === '{{date}}' ? delete this.field.default_value : this.field.default_value = '{{date}}'
|
||||||
|
|
||||||
this.save()
|
this.save()
|
||||||
|
} else {
|
||||||
|
this.maybeToggleCheckboxValue()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
maybeToggleCheckboxValue () {
|
maybeToggleCheckboxValue () {
|
||||||
if (this.inputMode && this.field.type === 'checkbox') {
|
if (this.field.type === 'checkbox') {
|
||||||
this.field.readonly = !this.field.readonly
|
|
||||||
this.field.default_value === true ? delete this.field.default_value : this.field.default_value = true
|
this.field.default_value === true ? delete this.field.default_value : this.field.default_value = true
|
||||||
|
this.field.readonly = this.field.default_value === true
|
||||||
|
|
||||||
|
this.save()
|
||||||
|
} else if (this.field.type === 'radio' && this.area.option_uuid) {
|
||||||
|
const option = this.optionsUuidIndex[this.area.option_uuid]
|
||||||
|
|
||||||
|
const value = option.value || `${this.t('option')} ${this.field.options.indexOf(option) + 1}`
|
||||||
|
|
||||||
|
this.field.default_value === value ? delete this.field.default_value : this.field.default_value = value
|
||||||
|
|
||||||
|
this.field.readonly = !!this.field.default_value?.length
|
||||||
|
|
||||||
|
this.save()
|
||||||
|
} else if (this.field.type === 'multiple' && this.area.option_uuid) {
|
||||||
|
const option = this.optionsUuidIndex[this.area.option_uuid]
|
||||||
|
|
||||||
|
const value = option.value || `${this.t('option')} ${this.field.options.indexOf(option) + 1}`
|
||||||
|
|
||||||
|
if (this.field.default_value?.includes(value)) {
|
||||||
|
this.field.default_value.splice(this.field.default_value.indexOf(value), 1)
|
||||||
|
|
||||||
|
if (!this.field.default_value?.length) delete this.field.default_value
|
||||||
|
} else {
|
||||||
|
Array.isArray(this.field.default_value) ? this.field.default_value.push(value) : this.field.default_value = [value]
|
||||||
|
}
|
||||||
|
|
||||||
|
this.field.readonly = !!this.field.default_value?.length
|
||||||
|
|
||||||
this.save()
|
this.save()
|
||||||
}
|
}
|
||||||
@@ -749,7 +819,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
drag (e) {
|
drag (e) {
|
||||||
if (e.target.id === 'mask') {
|
if (e.target.id === 'mask' && this.editable) {
|
||||||
this.isDragged = true
|
this.isDragged = true
|
||||||
|
|
||||||
this.area.x = (e.offsetX - this.dragFrom.x) / e.target.clientWidth
|
this.area.x = (e.offsetX - this.dragFrom.x) / e.target.clientWidth
|
||||||
@@ -765,7 +835,9 @@ export default {
|
|||||||
|
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
this.isDragged = true
|
if (this.editable) {
|
||||||
|
this.isDragged = true
|
||||||
|
}
|
||||||
|
|
||||||
const rect = e.target.getBoundingClientRect()
|
const rect = e.target.getBoundingClientRect()
|
||||||
|
|
||||||
@@ -818,7 +890,9 @@ export default {
|
|||||||
|
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|
||||||
this.isDragged = true
|
if (this.editable) {
|
||||||
|
this.isDragged = true
|
||||||
|
}
|
||||||
|
|
||||||
const rect = e.target.getBoundingClientRect()
|
const rect = e.target.getBoundingClientRect()
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="relative select-none mb-4 before:border before:rounded before:top-0 before:bottom-0 before:left-0 before:right-0 before:absolute"
|
class="relative select-none mb-4 before:border before:rounded before:top-0 before:bottom-0 before:left-0 before:right-0 before:absolute"
|
||||||
:class="{ 'cursor-crosshair': allowDraw, 'touch-none': !!drawField }"
|
:class="{ 'cursor-crosshair': allowDraw && editable, 'touch-none': !!drawField }"
|
||||||
style="container-type: size"
|
style="container-type: size"
|
||||||
:style="{ aspectRatio: `${width} / ${height}`}"
|
:style="{ aspectRatio: `${width} / ${height}`}"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ module Submitters
|
|||||||
end
|
end
|
||||||
|
|
||||||
def replace_default_variables(value, attrs, submission, with_time: false)
|
def replace_default_variables(value, attrs, submission, with_time: false)
|
||||||
return value if value.in?([true, false]) || value.is_a?(Numeric)
|
return value if value.in?([true, false]) || value.is_a?(Numeric) || value.is_a?(Array)
|
||||||
return if value.blank?
|
return if value.blank?
|
||||||
|
|
||||||
value.to_s.gsub(VARIABLE_REGEXP) do |e|
|
value.to_s.gsub(VARIABLE_REGEXP) do |e|
|
||||||
|
|||||||
Reference in New Issue
Block a user