double click to edit default value

pull/349/head
Pete Matsyburka 1 year ago
parent 2389c3fc40
commit 3b717ae3de

@ -3,7 +3,7 @@
class="absolute overflow-visible group" class="absolute overflow-visible group"
:style="positionStyle" :style="positionStyle"
@pointerdown.stop @pointerdown.stop
@mousedown.stop="startDrag" @mousedown="startMouseMove"
@touchstart="startTouchDrag" @touchstart="startTouchDrag"
> >
<div <div
@ -70,10 +70,11 @@
@blur="onNameBlur" @blur="onNameBlur"
>{{ optionIndexText }} {{ (defaultField ? (field.title || field.name) : field.name) || defaultName }}</span> >{{ optionIndexText }} {{ (defaultField ? (field.title || field.name) : field.name) || defaultName }}</span>
<div <div
v-if="isSettingsFocus || (isNameFocus && !['checkbox', 'phone'].includes(field.type))" v-if="isSettingsFocus || isContenteditable || (isNameFocus && !['checkbox', 'phone'].includes(field.type))"
class="flex items-center ml-1.5" class="flex items-center ml-1.5"
> >
<input <input
v-if="!isContenteditable"
:id="`required-checkbox-${field.uuid}`" :id="`required-checkbox-${field.uuid}`"
v-model="field.required" v-model="field.required"
type="checkbox" type="checkbox"
@ -81,13 +82,30 @@
@mousedown.prevent @mousedown.prevent
> >
<label <label
v-if="!isContenteditable"
: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
v-if="isContenteditable"
:id="`readonly-checkbox-${field.uuid}`"
type="checkbox"
class="checkbox checkbox-xs no-animation rounded"
:checked="!(field.readonly ?? true)"
@change="field.readonly = !(field.readonly ?? true)"
@mousedown.prevent
>
<label
v-if="isContenteditable"
:for="`readonly-checkbox-${field.uuid}`"
class="label text-xs"
@click.prevent="field.readonly = !(field.readonly ?? true)"
@mousedown.prevent
>{{ t('editable') }}</label>
<span <span
v-if="field.type !== 'payment'" v-if="field.type !== 'payment' && !isContenteditable"
class="dropdown dropdown-end" class="dropdown dropdown-end"
@mouseenter="renderDropdown = true" @mouseenter="renderDropdown = true"
@touchstart="renderDropdown = true" @touchstart="renderDropdown = true"
@ -140,7 +158,7 @@
<div <div
class="flex items-center h-full w-full" class="flex items-center h-full w-full"
dir="auto" dir="auto"
:class="[bgColors[submitterIndex], field?.default_value ? (alignClasses[field.preferences?.align] || '') : 'justify-center']" :class="[isContenteditable ? 'bg-opacity-50' : 'bg-opacity-80', bgColors[submitterIndex], isDefaultValuePresent || isContenteditable ? (alignClasses[field.preferences?.align] || '') : 'justify-center']"
> >
<span <span
v-if="field" v-if="field"
@ -148,7 +166,7 @@
:class="{'w-full h-full': field.type == 'checkbox'}" :class="{'w-full h-full': field.type == 'checkbox'}"
> >
<div <div
v-if="field?.default_value" v-if="isDefaultValuePresent || isContenteditable"
:class="{ 'w-full h-full': field.type == 'checkbox', 'text-[1.5vw] lg:text-base': !textOverflowChars, 'text-[1.0vw] lg:text-xs': textOverflowChars }" :class="{ 'w-full h-full': field.type == 'checkbox', 'text-[1.5vw] lg:text-base': !textOverflowChars, 'text-[1.0vw] lg:text-xs': textOverflowChars }"
> >
<div <div
@ -162,12 +180,18 @@
: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 }"
/> />
<span <span
v-else-if="field.type === 'number'" v-else-if="field.type === 'number' && !isContenteditable"
class="whitespace-pre-wrap" class="whitespace-pre-wrap"
>{{ formatNumber(field.default_value, field.preferences?.format) }}</span> >{{ formatNumber(field.default_value, field.preferences?.format) }}</span>
<span <span
v-else v-else
class="whitespace-pre-wrap" ref="defaultValue"
:contenteditable="isContenteditable"
class="whitespace-pre-wrap outline-none empty:before:content-[attr(placeholder)] before:text-gray-400"
:class="{ 'cursor-text': isContenteditable }"
:placeholder="t('type_value')"
@blur="onDefaultValueBlur"
@keydown.enter.prevent="onDefaultValueEnter"
>{{ field.default_value }}</span> >{{ field.default_value }}</span>
</div> </div>
</div> </div>
@ -181,8 +205,11 @@
</span> </span>
</div> </div>
<div <div
v-if="!isContenteditable"
ref="touchTarget" ref="touchTarget"
class="absolute top-0 bottom-0 right-0 left-0 cursor-pointer" class="absolute top-0 bottom-0 right-0 left-0"
:class="isDragged ? 'cursor-grab' : 'cursor-pointer'"
@dblclick="maybeFocusDefaultValue"
/> />
<span <span
v-if="field?.type && editable" v-if="field?.type && editable"
@ -286,6 +313,7 @@ export default {
return { return {
isShowFormulaModal: false, isShowFormulaModal: false,
isShowConditionsModal: false, isShowConditionsModal: false,
isContenteditable: false,
isSettingsFocus: false, isSettingsFocus: false,
isShowDescriptionModal: false, isShowDescriptionModal: false,
isResize: false, isResize: false,
@ -299,6 +327,9 @@ export default {
computed: { computed: {
fieldNames: FieldType.computed.fieldNames, fieldNames: FieldType.computed.fieldNames,
fieldIcons: FieldType.computed.fieldIcons, fieldIcons: FieldType.computed.fieldIcons,
isDefaultValuePresent () {
return this.field?.default_value || this.field?.default_value === 0
},
modalContainerEl () { modalContainerEl () {
return this.$el.getRootNode().querySelector('#docuseal_modal_container') return this.$el.getRootNode().querySelector('#docuseal_modal_container')
}, },
@ -364,26 +395,26 @@ export default {
}, },
bgColors () { bgColors () {
return [ return [
'bg-red-100/80', 'bg-red-100',
'bg-sky-100/80', 'bg-sky-100',
'bg-emerald-100/80', 'bg-emerald-100',
'bg-yellow-100/80', 'bg-yellow-100',
'bg-purple-100/80', 'bg-purple-100',
'bg-pink-100/80', 'bg-pink-100',
'bg-cyan-100/80', 'bg-cyan-100',
'bg-orange-100/80', 'bg-orange-100',
'bg-lime-100/80', 'bg-lime-100',
'bg-indigo-100/80', 'bg-indigo-100',
'bg-red-100/80', 'bg-red-100',
'bg-sky-100/80', 'bg-sky-100',
'bg-emerald-100/80', 'bg-emerald-100',
'bg-yellow-100/80', 'bg-yellow-100',
'bg-purple-100/80', 'bg-purple-100',
'bg-pink-100/80', 'bg-pink-100',
'bg-cyan-100/80', 'bg-cyan-100',
'bg-orange-100/80', 'bg-orange-100',
'bg-lime-100/80', 'bg-lime-100',
'bg-indigo-100/80' 'bg-indigo-100'
] ]
}, },
isSelected () { isSelected () {
@ -421,6 +452,22 @@ export default {
closeDropdown () { closeDropdown () {
document.activeElement.blur() document.activeElement.blur()
}, },
maybeFocusDefaultValue () {
if (['text', 'number'].includes(this.field.type)) {
this.isContenteditable = true
this.$nextTick(() => {
this.$refs.defaultValue.focus()
if (this.$refs.defaultValue.innerText.length) {
window.getSelection().collapse(
this.$refs.defaultValue.firstChild,
this.$refs.defaultValue.innerText.length
)
}
})
}
},
formatNumber (number, format) { formatNumber (number, format) {
if (format === 'comma') { if (format === 'comma') {
return new Intl.NumberFormat('en-US').format(number) return new Intl.NumberFormat('en-US').format(number)
@ -510,6 +557,38 @@ export default {
this.save() this.save()
}, },
onDefaultValueBlur (e) {
const text = this.$refs.defaultValue.innerText.trim()
this.isContenteditable = false
if (text) {
if (this.field.type === 'number') {
const number = parseFloat(text)
if (number || number === 0) {
this.field.default_value = parseFloat(text)
}
} else {
this.field.default_value = text
}
if (![true, false].includes(this.field.readonly)) {
this.field.readonly = true
}
this.$refs.defaultValue.innerText = text
} else {
delete this.field.readonly
delete this.field.default_value
this.$refs.defaultValue.innerText = ''
}
this.save()
},
onDefaultValueEnter (e) {
this.$refs.defaultValue.blur()
},
onNameEnter (e) { onNameEnter (e) {
this.$refs.name.blur() this.$refs.name.blur()
}, },
@ -569,8 +648,8 @@ export default {
const page = this.$parent.$refs.mask.previousSibling const page = this.$parent.$refs.mask.previousSibling
const rect = page.getBoundingClientRect() const rect = page.getBoundingClientRect()
this.area.x = (this.dragFrom.x + e.touches[0].clientX - rect.left) / rect.width this.area.x = Math.min(Math.max((this.dragFrom.x + e.touches[0].clientX - rect.left) / rect.width, 0), 1 - this.area.w)
this.area.y = (this.dragFrom.y + e.touches[0].clientY - rect.top) / rect.height this.area.y = Math.min(Math.max((this.dragFrom.y + e.touches[0].clientY - rect.top) / rect.height, 0), 1 - this.area.h)
}, },
stopTouchDrag () { stopTouchDrag () {
this.$el.getRootNode().removeEventListener('touchmove', this.touchDrag) this.$el.getRootNode().removeEventListener('touchmove', this.touchDrag)
@ -584,6 +663,47 @@ export default {
this.$emit('stop-drag') this.$emit('stop-drag')
}, },
startMouseMove (e) {
if (e.target !== this.$refs.touchTarget) {
return
}
this.$refs?.name?.blur()
e.preventDefault()
this.isDragged = true
const rect = e.target.getBoundingClientRect()
this.selectedAreaRef.value = this.area
this.dragFrom = { x: rect.left - e.clientX, y: rect.top - e.clientY }
this.$el.getRootNode().addEventListener('mousemove', this.mouseMove)
this.$el.getRootNode().addEventListener('mouseup', this.stopMouseMove)
this.$emit('start-drag')
},
mouseMove (e) {
const page = this.$parent.$refs.mask.previousSibling
const rect = page.getBoundingClientRect()
this.area.x = Math.min(Math.max((this.dragFrom.x + e.clientX - rect.left) / rect.width, 0), 1 - this.area.w)
this.area.y = Math.min(Math.max((this.dragFrom.y + e.clientY - rect.top) / rect.height, 0), 1 - this.area.h)
},
stopMouseMove (e) {
this.$el.getRootNode().removeEventListener('mousemove', this.mouseMove)
this.$el.getRootNode().removeEventListener('mouseup', this.stopMouseMove)
if (this.isDragged) {
this.save()
}
this.isDragged = false
this.$emit('stop-drag')
},
stopDrag () { stopDrag () {
this.$el.getRootNode().removeEventListener('mousemove', this.drag) this.$el.getRootNode().removeEventListener('mousemove', this.drag)
this.$el.getRootNode().removeEventListener('mouseup', this.stopDrag) this.$el.getRootNode().removeEventListener('mouseup', this.stopDrag)

@ -1,4 +1,5 @@
const en = { const en = {
editable: 'Editable',
search_field: 'Search field', search_field: 'Search field',
field_not_found: 'Field not found', field_not_found: 'Field not found',
clear: 'Clear', clear: 'Clear',
@ -11,6 +12,7 @@ const en = {
display_title: 'Display title', display_title: 'Display title',
with_logo: 'With logo', with_logo: 'With logo',
unchecked: 'Unchecked', unchecked: 'Unchecked',
type_value: 'Type value',
equal: 'Equal', equal: 'Equal',
not_equal: 'Not equal', not_equal: 'Not equal',
contains: 'Contains', contains: 'Contains',

@ -27,8 +27,6 @@
:default-submitters="defaultSubmitters" :default-submitters="defaultSubmitters"
@start-resize="resizeDirection = $event" @start-resize="resizeDirection = $event"
@stop-resize="resizeDirection = null" @stop-resize="resizeDirection = null"
@start-drag="isMove = true"
@stop-drag="isMove = false"
@remove="$emit('remove-area', item.area)" @remove="$emit('remove-area', item.area)"
@scroll-to="$emit('scroll-to', $event)" @scroll-to="$emit('scroll-to', $event)"
/> />
@ -40,11 +38,11 @@
/> />
</div> </div>
<div <div
v-show="resizeDirection || isMove || isDrag || showMask || (drawField && isMobile) || fieldsDragFieldRef.value" v-show="resizeDirection || isDrag || showMask || (drawField && isMobile) || fieldsDragFieldRef.value"
id="mask" id="mask"
ref="mask" ref="mask"
class="top-0 bottom-0 left-0 right-0 absolute" class="top-0 bottom-0 left-0 right-0 absolute"
:class="{ 'z-10': !isMobile, 'cursor-grab': isDrag || isMove, 'cursor-nwse-resize': drawField, [resizeDirectionClasses[resizeDirection]]: !!resizeDirectionClasses }" :class="{ 'z-10': !isMobile, 'cursor-grab': isDrag, 'cursor-nwse-resize': drawField, [resizeDirectionClasses[resizeDirection]]: !!resizeDirectionClasses }"
@pointermove="onPointermove" @pointermove="onPointermove"
@pointerdown="onStartDraw" @pointerdown="onStartDraw"
@dragover.prevent @dragover.prevent
@ -122,7 +120,6 @@ export default {
return { return {
areaRefs: [], areaRefs: [],
showMask: false, showMask: false,
isMove: false,
resizeDirection: null, resizeDirection: null,
newArea: null newArea: null
} }

Loading…
Cancel
Save