template builder adjustments

pull/105/head
Alex Turchyn 2 years ago
parent 7ccafa49bf
commit 00e3ee15ef

@ -6,7 +6,7 @@
@mousedown.stop="startDrag" @mousedown.stop="startDrag"
> >
<div <div
v-if="isSelected" v-if="isSelected || !field?.type"
class="top-0 bottom-0 right-0 left-0 absolute border border-1.5 pointer-events-none" class="top-0 bottom-0 right-0 left-0 absolute border border-1.5 pointer-events-none"
:class="borderColors[submitterIndex]" :class="borderColors[submitterIndex]"
/> />
@ -31,7 +31,7 @@
:button-width="27" :button-width="27"
:button-classes="'px-1'" :button-classes="'px-1'"
:menu-classes="'bg-white rounded-t-none'" :menu-classes="'bg-white rounded-t-none'"
@update:model-value="maybeDeleteOptions" @update:model-value="maybeUpdateOptions"
@click="selectedAreaRef.value = area" @click="selectedAreaRef.value = area"
/> />
<span <span
@ -45,10 +45,10 @@
@blur="onNameBlur" @blur="onNameBlur"
>{{ field.name || defaultName }}</span> >{{ field.name || defaultName }}</span>
<button <button
class="pl-0.5 pr-1.5" class="pr-1"
@click.prevent="$emit('remove')" @click.prevent="$emit('remove')"
> >
<span>&times;</span> <IconX width="14" />
</button> </button>
</div> </div>
<div <div
@ -57,16 +57,22 @@
> >
<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 h-full"
> >
<component :is="fieldIcons[field.type]" /> <component
:is="fieldIcons[field.type]"
width="100%"
height="100%"
class="max-h-10"
/>
</span> </span>
</div> </div>
<div <div
class="absolute top-0 bottom-0 right-0 left-0 cursor-pointer" class="absolute top-0 bottom-0 right-0 left-0 cursor-pointer"
/> />
<span <span
class="h-2.5 w-2.5 -right-1.5 rounded-full -bottom-1.5 bg-white shadow border absolute cursor-nwse-resize" v-if="field?.type"
class="h-2.5 w-2.5 -right-1 rounded-full -bottom-1 border-gray-400 bg-white shadow-md border absolute cursor-nwse-resize"
@mousedown.stop="startResize" @mousedown.stop="startResize"
/> />
</div> </div>
@ -76,12 +82,14 @@
import FieldSubmitter from './field_submitter' import FieldSubmitter from './field_submitter'
import FieldType from './field_type' import FieldType from './field_type'
import Field from './field' import Field from './field'
import { IconX } from '@tabler/icons-vue'
export default { export default {
name: 'FieldArea', name: 'FieldArea',
components: { components: {
FieldType, FieldType,
FieldSubmitter FieldSubmitter,
IconX
}, },
inject: ['template', 'selectedAreaRef'], inject: ['template', 'selectedAreaRef'],
props: { props: {
@ -160,10 +168,14 @@ export default {
}, 1) }, 1)
} }
}, },
maybeDeleteOptions () { maybeUpdateOptions () {
if (!['radio', 'select', 'checkbox'].includes(this.field.type)) { if (!['radio', 'checkbox', 'select'].includes(this.field.type)) {
delete this.field.options delete this.field.options
} }
if (this.field.type === 'select') {
this.field.options ||= ['']
}
}, },
onNameBlur (e) { onNameBlur (e) {
this.isNameFocus = false this.isNameFocus = false

@ -77,6 +77,7 @@
:selected-submitter="selectedSubmitter" :selected-submitter="selectedSubmitter"
:document="document" :document="document"
:is-drag="!!dragFieldType" :is-drag="!!dragFieldType"
:is-draw="!!drawField"
@draw="onDraw" @draw="onDraw"
@drop-field="onDropfield" @drop-field="onDropfield"
@remove-area="removeArea" @remove-area="removeArea"
@ -91,10 +92,19 @@
v-if="drawField" v-if="drawField"
class="sticky inset-0 bg-base-100 h-full" class="sticky inset-0 bg-base-100 h-full"
> >
Draw {{ drawField.name }} field on the page <div class="bg-base-300 rounded-lg p-5 text-center space-y-4">
<button @click="drawField = false"> <p>
Cancel Draw {{ drawField.name }} field on the document
</button> </p>
<p>
<button
class="base-button"
@click="drawField = false"
>
Cancel
</button>
</p>
</div>
</div> </div>
<div> <div>
<Fields <Fields
@ -244,12 +254,19 @@ export default {
const type = (pageMask.clientWidth * area.w) < 35 ? 'checkbox' : 'text' const type = (pageMask.clientWidth * area.w) < 35 ? 'checkbox' : 'text'
if (type === 'checkbox') { if (type === 'checkbox') {
const previousField = [...this.template.fields].reverse().find((f) => f.type === type)
const previousArea = previousField?.areas?.[previousField.areas.length - 1]
const areaW = previousArea?.w || (30 / pageMask.clientWidth)
const areaH = previousArea?.h || (30 / pageMask.clientHeight)
if ((pageMask.clientWidth * area.w) < 5) { if ((pageMask.clientWidth * area.w) < 5) {
area.x = area.x - (30 / pageMask.clientWidth) / 2 area.x = area.x - (areaW / 2)
area.y = area.y - (30 / pageMask.clientHeight) / 2 area.y = area.y - (areaH / 2)
} }
area.w = 30 / pageMask.clientWidth
area.h = 30 / pageMask.clientHeight area.w = areaW
area.h = areaH
} }
const field = { const field = {

@ -7,6 +7,7 @@
:number="index" :number="index"
:areas="areasIndex[index]" :areas="areasIndex[index]"
:is-drag="isDrag" :is-drag="isDrag"
:is-draw="isDraw"
:selected-submitter="selectedSubmitter" :selected-submitter="selectedSubmitter"
:image="image" :image="image"
@drop-field="$emit('drop-field', {...$event, attachment_uuid: document.uuid })" @drop-field="$emit('drop-field', {...$event, attachment_uuid: document.uuid })"
@ -37,6 +38,11 @@ export default {
type: Object, type: Object,
required: true required: true
}, },
isDraw: {
type: Boolean,
required: false,
default: false
},
isDrag: { isDrag: {
type: Boolean, type: Boolean,
required: false, required: false,

@ -1,17 +1,21 @@
<template> <template>
<div <div
class="group pb-2" class="group pb-2"
@click="field.areas?.[0] && $emit('scroll-to', field.areas[0])"
> >
<div <div
class="border border-base-300 rounded rounded-tr-none relative group" class="border border-base-300 rounded rounded-tr-none relative group"
> >
<div
class="absolute top-0 bottom-0 right-0 left-0 cursor-pointer"
@click="scrollToFirstArea"
/>
<div class="flex items-center justify-between space-x-1"> <div class="flex items-center justify-between space-x-1">
<div class="flex items-center p-1 space-x-1"> <div class="flex items-center p-1 space-x-1">
<FieldType <FieldType
v-model="field.type" v-model="field.type"
:button-width="20" :button-width="20"
@update:model-value="maybeDeleteOptions" @update:model-value="maybeUpdateOptions"
@click="scrollToFirstArea"
/> />
<Contenteditable <Contenteditable
ref="name" ref="name"
@ -19,7 +23,7 @@
:icon-inline="true" :icon-inline="true"
:icon-width="18" :icon-width="18"
:icon-stroke-width="1.6" :icon-stroke-width="1.6"
@focus="onNameFocus" @focus="[onNameFocus(), scrollToFirstArea()]"
@blur="onNameBlur" @blur="onNameBlur"
/> />
</div> </div>
@ -72,7 +76,7 @@
</ul> </ul>
</span> </span>
<button <button
class=" text-base-100 group-hover:text-base-content" class="relative text-base-100 group-hover:text-base-content"
title="Remove" title="Remove"
@click="$emit('remove', field)" @click="$emit('remove', field)"
> >
@ -84,6 +88,7 @@
<div class="flex flex-col pr-1 text-base-100 group-hover:text-base-content"> <div class="flex flex-col pr-1 text-base-100 group-hover:text-base-content">
<button <button
title="Up" title="Up"
class="relative"
style="font-size: 10px; margin-bottom: -2px" style="font-size: 10px; margin-bottom: -2px"
@click="$emit('move-up')" @click="$emit('move-up')"
> >
@ -91,6 +96,7 @@
</button> </button>
<button <button
title="Down" title="Down"
class="relative"
style="font-size: 10px; margin-top: -2px" style="font-size: 10px; margin-top: -2px"
@click="$emit('move-down')" @click="$emit('move-down')"
> >
@ -176,13 +182,20 @@ export default {
}, 1) }, 1)
} }
}, },
scrollToFirstArea () {
return this.field.areas?.[0] && this.$emit('scroll-to', this.field.areas[0])
},
closeDropdown () { closeDropdown () {
document.activeElement.blur() document.activeElement.blur()
}, },
maybeDeleteOptions () { maybeUpdateOptions () {
if (!['radio', 'select', 'checkbox'].includes(this.field.type)) { if (!['radio', 'checkbox', 'select'].includes(this.field.type)) {
delete this.field.options delete this.field.options
} }
if (this.field.type === 'select') {
this.field.options ||= ['']
}
}, },
onNameBlur (e) { onNameBlur (e) {
if (e.target.innerText.trim()) { if (e.target.innerText.trim()) {

@ -14,7 +14,7 @@
<label <label
v-else v-else
tabindex="0" tabindex="0"
class="rounded-md p-2 border border-base-300 w-full flex justify-between" class="cursor-pointer rounded-md p-2 border border-base-300 w-full flex justify-between"
> >
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<span <span
@ -23,6 +23,7 @@
/> />
<Contenteditable <Contenteditable
v-model="selectedSubmitter.name" v-model="selectedSubmitter.name"
class="cursor-text"
:icon-inline="true" :icon-inline="true"
:icon-width="18" :icon-width="18"
/> />
@ -126,6 +127,15 @@ export default {
'bg-purple-600' 'bg-purple-600'
] ]
}, },
names () {
return [
'First Submitter',
'Second Submitter',
'Third Submitter',
'Fourth Submitter',
'Fifth Submitter'
]
},
selectedSubmitter () { selectedSubmitter () {
return this.submitters.find((e) => e.uuid === this.modelValue) return this.submitters.find((e) => e.uuid === this.modelValue)
} }
@ -141,7 +151,7 @@ export default {
}, },
addSubmitter () { addSubmitter () {
const newSubmitter = { const newSubmitter = {
name: `Submitter ${this.submitters.length + 1}`, name: this.names[this.submitters.length],
uuid: v4() uuid: v4()
} }

@ -116,16 +116,21 @@ export default {
} }
}, },
move (field, direction) { move (field, direction) {
const currentIndex = this.fields.indexOf(field) const currentIndex = this.submitterFields.indexOf(field)
const fieldsIndex = this.fields.indexOf(field)
this.fields.splice(currentIndex, 1) this.fields.splice(fieldsIndex, 1)
if (currentIndex + direction > this.fields.length) { if (currentIndex + direction > this.submitterFields.length) {
this.fields.unshift(field) const firstIndex = this.fields.indexOf(this.submitterFields[0])
this.fields.splice(firstIndex, 0, field)
} else if (currentIndex + direction < 0) { } else if (currentIndex + direction < 0) {
this.fields.push(field) const lastIndex = this.fields.indexOf(this.submitterFields[this.submitterFields.length - 1])
this.fields.splice(lastIndex + 1, 0, field)
} else { } else {
this.fields.splice(currentIndex + direction, 0, field) this.fields.splice(fieldsIndex + direction, 0, field)
} }
}, },
removeField (field) { removeField (field) {

@ -35,7 +35,7 @@
id="mask" id="mask"
ref="mask" ref="mask"
class="top-0 bottom-0 left-0 right-0 absolute z-10" class="top-0 bottom-0 left-0 right-0 absolute z-10"
:class="{ 'cursor-grab': isDrag || isMove, ' cursor-nwse-resize': isResize }" :class="{ 'cursor-grab': isDrag || isMove, 'cursor-nwse-resize': isResize || isDraw }"
@pointermove="onPointermove" @pointermove="onPointermove"
@dragover.prevent @dragover.prevent
@drop="onDrop" @drop="onDrop"
@ -66,6 +66,11 @@ export default {
type: Object, type: Object,
required: true required: true
}, },
isDraw: {
type: Boolean,
required: false,
default: false
},
isDrag: { isDrag: {
type: Boolean, type: Boolean,
required: false, required: false,

@ -28,7 +28,7 @@
# fk_rails_... (author_id => users.id) # fk_rails_... (author_id => users.id)
# #
class Template < ApplicationRecord class Template < ApplicationRecord
DEFAULT_SUBMITTER_NAME = 'Submitter 1' DEFAULT_SUBMITTER_NAME = 'First Submitter'
belongs_to :author, class_name: 'User' belongs_to :author, class_name: 'User'
belongs_to :account belongs_to :account

Loading…
Cancel
Save