template builder adjustments
This commit is contained in:
@@ -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>×</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
|
||||||
|
|||||||
Reference in New Issue
Block a user