custom fields
This commit is contained in:
@@ -0,0 +1,33 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AccountCustomFieldsController < ApplicationController
|
||||||
|
before_action :load_account_config, only: :create
|
||||||
|
|
||||||
|
def create
|
||||||
|
authorize!(:create, Template)
|
||||||
|
|
||||||
|
@account_config.update!(account_config_params)
|
||||||
|
|
||||||
|
render json: @account_config.value
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def load_account_config
|
||||||
|
@account_config =
|
||||||
|
AccountConfig.find_or_initialize_by(account: current_account, key: AccountConfig::TEMPLATE_CUSTOM_FIELDS_KEY)
|
||||||
|
end
|
||||||
|
|
||||||
|
def account_config_params
|
||||||
|
params.permit(
|
||||||
|
value: [[:uuid, :name, :type,
|
||||||
|
:required, :readonly, :default_value,
|
||||||
|
:title, :description,
|
||||||
|
{ preferences: {},
|
||||||
|
default_value: [],
|
||||||
|
options: [%i[value uuid]],
|
||||||
|
validation: %i[message pattern min max step],
|
||||||
|
areas: [%i[x y w h cell_w option_uuid]] }]]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -155,6 +155,7 @@ safeRegisterElement('template-builder', class extends HTMLElement {
|
|||||||
|
|
||||||
this.app = createApp(TemplateBuilder, {
|
this.app = createApp(TemplateBuilder, {
|
||||||
template: reactive(JSON.parse(this.dataset.template)),
|
template: reactive(JSON.parse(this.dataset.template)),
|
||||||
|
customFields: reactive(JSON.parse(this.dataset.customFields || '[]')),
|
||||||
backgroundColor: '#faf7f5',
|
backgroundColor: '#faf7f5',
|
||||||
locale: this.dataset.locale,
|
locale: this.dataset.locale,
|
||||||
withPhone: this.dataset.withPhone === 'true',
|
withPhone: this.dataset.withPhone === 'true',
|
||||||
@@ -164,6 +165,7 @@ safeRegisterElement('template-builder', class extends HTMLElement {
|
|||||||
withFieldsDetection: this.dataset.withFieldsDetection === 'true',
|
withFieldsDetection: this.dataset.withFieldsDetection === 'true',
|
||||||
editable: this.dataset.editable !== 'false',
|
editable: this.dataset.editable !== 'false',
|
||||||
authenticityToken: document.querySelector('meta[name="csrf-token"]')?.content,
|
authenticityToken: document.querySelector('meta[name="csrf-token"]')?.content,
|
||||||
|
withCustomFields: true,
|
||||||
withPayment: this.dataset.withPayment === 'true',
|
withPayment: this.dataset.withPayment === 'true',
|
||||||
isPaymentConnected: this.dataset.isPaymentConnected === 'true',
|
isPaymentConnected: this.dataset.isPaymentConnected === 'true',
|
||||||
withFormula: this.dataset.withFormula === 'true',
|
withFormula: this.dataset.withFormula === 'true',
|
||||||
|
|||||||
@@ -145,7 +145,9 @@
|
|||||||
@click-formula="isShowFormulaModal = true"
|
@click-formula="isShowFormulaModal = true"
|
||||||
@click-font="isShowFontModal = true"
|
@click-font="isShowFontModal = true"
|
||||||
@click-description="isShowDescriptionModal = true"
|
@click-description="isShowDescriptionModal = true"
|
||||||
|
@add-custom-field="$emit('add-custom-field')"
|
||||||
@click-condition="isShowConditionsModal = true"
|
@click-condition="isShowConditionsModal = true"
|
||||||
|
@save="save"
|
||||||
@scroll-to="[selectedAreasRef.value = [$event], $emit('scroll-to', $event)]"
|
@scroll-to="[selectedAreasRef.value = [$event], $emit('scroll-to', $event)]"
|
||||||
/>
|
/>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -471,7 +473,7 @@ export default {
|
|||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['start-resize', 'stop-resize', 'start-drag', 'stop-drag', 'remove', 'scroll-to'],
|
emits: ['start-resize', 'stop-resize', 'start-drag', 'stop-drag', 'remove', 'scroll-to', 'add-custom-field'],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
isShowFormulaModal: false,
|
isShowFormulaModal: false,
|
||||||
|
|||||||
@@ -20,8 +20,9 @@
|
|||||||
/>
|
/>
|
||||||
<DragPlaceholder
|
<DragPlaceholder
|
||||||
ref="dragPlaceholder"
|
ref="dragPlaceholder"
|
||||||
:field="fieldsDragFieldRef.value || toRaw(dragField)"
|
:field="customDragFieldRef.value || fieldsDragFieldRef.value || toRaw(dragField)"
|
||||||
:is-field="template.fields.includes(fieldsDragFieldRef.value)"
|
:is-field="template.fields.includes(fieldsDragFieldRef.value)"
|
||||||
|
:is-custom="!!customDragFieldRef.value"
|
||||||
:is-default="defaultFields.includes(toRaw(dragField))"
|
:is-default="defaultFields.includes(toRaw(dragField))"
|
||||||
:is-required="defaultRequiredFields.includes(toRaw(dragField))"
|
:is-required="defaultRequiredFields.includes(toRaw(dragField))"
|
||||||
/>
|
/>
|
||||||
@@ -362,7 +363,7 @@
|
|||||||
:is-drag="!!dragField"
|
:is-drag="!!dragField"
|
||||||
:input-mode="inputMode"
|
:input-mode="inputMode"
|
||||||
:default-fields="[...defaultRequiredFields, ...defaultFields]"
|
:default-fields="[...defaultRequiredFields, ...defaultFields]"
|
||||||
:allow-draw="!onlyDefinedFields || drawField"
|
:allow-draw="!onlyDefinedFields || drawField || drawCustomField"
|
||||||
:with-signature-id="withSignatureId"
|
:with-signature-id="withSignatureId"
|
||||||
:with-prefillable="withPrefillable"
|
:with-prefillable="withPrefillable"
|
||||||
:data-document-uuid="document.uuid"
|
:data-document-uuid="document.uuid"
|
||||||
@@ -371,14 +372,16 @@
|
|||||||
:with-field-placeholder="withFieldPlaceholder"
|
:with-field-placeholder="withFieldPlaceholder"
|
||||||
:draw-field="drawField"
|
:draw-field="drawField"
|
||||||
:draw-field-type="drawFieldType"
|
:draw-field-type="drawFieldType"
|
||||||
|
:draw-custom-field="drawCustomField"
|
||||||
:editable="editable"
|
:editable="editable"
|
||||||
:base-url="baseUrl"
|
:base-url="baseUrl"
|
||||||
:with-fields-detection="withFieldsDetection"
|
:with-fields-detection="withFieldsDetection"
|
||||||
@draw="[onDraw($event), withSelectedFieldType ? '' : drawFieldType = '', showDrawField = false]"
|
@draw="[onDraw($event), withSelectedFieldType ? '' : drawFieldType = '', drawCustomField = null, showDrawField = false]"
|
||||||
@drop-field="onDropfield"
|
@drop-field="onDropfield"
|
||||||
@remove-area="removeArea"
|
@remove-area="removeArea"
|
||||||
@paste-field="pasteField"
|
@paste-field="pasteField"
|
||||||
@copy-field="copyField"
|
@copy-field="copyField"
|
||||||
|
@add-custom-field="addCustomField"
|
||||||
@copy-selected-areas="copySelectedAreas"
|
@copy-selected-areas="copySelectedAreas"
|
||||||
@delete-selected-areas="deleteSelectedAreas"
|
@delete-selected-areas="deleteSelectedAreas"
|
||||||
@align-selected-areas="alignSelectedAreas"
|
@align-selected-areas="alignSelectedAreas"
|
||||||
@@ -436,15 +439,15 @@
|
|||||||
v-if="withFieldsList && !isMobile"
|
v-if="withFieldsList && !isMobile"
|
||||||
id="fields_list_container"
|
id="fields_list_container"
|
||||||
class="relative w-80 flex-none mt-1 pr-4 pl-0.5 hidden md:block fields-list-container"
|
class="relative w-80 flex-none mt-1 pr-4 pl-0.5 hidden md:block fields-list-container"
|
||||||
:class="drawField ? 'overflow-hidden' : 'overflow-y-auto overflow-x-hidden'"
|
:class="drawField || drawCustomField ? 'overflow-hidden' : 'overflow-y-auto overflow-x-hidden'"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="showDrawField || drawField"
|
v-if="showDrawField || drawField || drawCustomField"
|
||||||
class="sticky inset-0 h-full z-20"
|
class="sticky inset-0 h-full z-20"
|
||||||
:style="{ backgroundColor }"
|
:style="{ backgroundColor }"
|
||||||
>
|
>
|
||||||
<div class="bg-base-200 rounded-lg p-5 text-center space-y-4 draw-field-container">
|
<div class="bg-base-200 rounded-lg p-5 text-center space-y-4 draw-field-container">
|
||||||
<p v-if="(drawField?.type || drawFieldType) === 'strikethrough'">
|
<p v-if="(drawField?.type || drawFieldType || drawCustomField?.type) === 'strikethrough'">
|
||||||
{{ t('draw_strikethrough_the_document') }}
|
{{ t('draw_strikethrough_the_document') }}
|
||||||
</p>
|
</p>
|
||||||
<p v-else>
|
<p v-else>
|
||||||
@@ -458,10 +461,10 @@
|
|||||||
{{ t('cancel') }}
|
{{ t('cancel') }}
|
||||||
</button>
|
</button>
|
||||||
<a
|
<a
|
||||||
v-if="!drawField && !drawOption && !['stamp', 'signature', 'initials', 'heading', 'strikethrough'].includes(drawField?.type || drawFieldType)"
|
v-if="!drawField && !drawOption && !['stamp', 'signature', 'initials', 'heading', 'strikethrough'].includes(drawField?.type || drawFieldType || drawCustomField?.type)"
|
||||||
href="#"
|
href="#"
|
||||||
class="link block mt-3 text-sm"
|
class="link block mt-3 text-sm"
|
||||||
@click.prevent="[addField(drawFieldType), drawField = null, drawOption = null, withSelectedFieldType ? '' : drawFieldType = '', showDrawField = false]"
|
@click.prevent="drawCustomField ? addCustomFieldWithoutDraw() : [addField(drawFieldType), drawField = null, drawOption = null, withSelectedFieldType ? '' : drawFieldType = '', showDrawField = false]"
|
||||||
>
|
>
|
||||||
{{ t('or_add_field_without_drawing') }}
|
{{ t('or_add_field_without_drawing') }}
|
||||||
</a>
|
</a>
|
||||||
@@ -477,6 +480,8 @@
|
|||||||
:with-help="withHelp"
|
:with-help="withHelp"
|
||||||
:default-submitters="defaultSubmitters"
|
:default-submitters="defaultSubmitters"
|
||||||
:draw-field-type="drawFieldType"
|
:draw-field-type="drawFieldType"
|
||||||
|
:custom-fields="customFields"
|
||||||
|
:with-custom-fields="withCustomFields"
|
||||||
:with-fields-search="withFieldsSearch"
|
:with-fields-search="withFieldsSearch"
|
||||||
:default-fields="[...defaultRequiredFields, ...defaultFields]"
|
:default-fields="[...defaultRequiredFields, ...defaultFields]"
|
||||||
:template="template"
|
:template="template"
|
||||||
@@ -493,6 +498,7 @@
|
|||||||
@set-draw="[drawField = $event.field, drawOption = $event.option]"
|
@set-draw="[drawField = $event.field, drawOption = $event.option]"
|
||||||
@select-submitter="selectedSubmitter = $event"
|
@select-submitter="selectedSubmitter = $event"
|
||||||
@set-draw-type="[drawFieldType = $event, showDrawField = true]"
|
@set-draw-type="[drawFieldType = $event, showDrawField = true]"
|
||||||
|
@set-draw-custom-field="[drawCustomField = $event, showDrawField = true]"
|
||||||
@set-drag="dragField = $event"
|
@set-drag="dragField = $event"
|
||||||
@set-drag-placeholder="$refs.dragPlaceholder.dragPlaceholder = $event"
|
@set-drag-placeholder="$refs.dragPlaceholder.dragPlaceholder = $event"
|
||||||
@change-submitter="selectedSubmitter = $event"
|
@change-submitter="selectedSubmitter = $event"
|
||||||
@@ -632,10 +638,12 @@ export default {
|
|||||||
isPaymentConnected: this.isPaymentConnected,
|
isPaymentConnected: this.isPaymentConnected,
|
||||||
withFormula: this.withFormula,
|
withFormula: this.withFormula,
|
||||||
withConditions: this.withConditions,
|
withConditions: this.withConditions,
|
||||||
|
withCustomFields: this.withCustomFields,
|
||||||
isInlineSize: this.isInlineSize,
|
isInlineSize: this.isInlineSize,
|
||||||
defaultDrawFieldType: this.defaultDrawFieldType,
|
defaultDrawFieldType: this.defaultDrawFieldType,
|
||||||
selectedAreasRef: computed(() => this.selectedAreasRef),
|
selectedAreasRef: computed(() => this.selectedAreasRef),
|
||||||
fieldsDragFieldRef: computed(() => this.fieldsDragFieldRef),
|
fieldsDragFieldRef: computed(() => this.fieldsDragFieldRef),
|
||||||
|
customDragFieldRef: computed(() => this.customDragFieldRef),
|
||||||
isSelectModeRef: computed(() => this.isSelectModeRef),
|
isSelectModeRef: computed(() => this.isSelectModeRef),
|
||||||
isCmdKeyRef: computed(() => this.isCmdKeyRef)
|
isCmdKeyRef: computed(() => this.isCmdKeyRef)
|
||||||
}
|
}
|
||||||
@@ -705,6 +713,16 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
|
withCustomFields: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
customFields: {
|
||||||
|
type: Array,
|
||||||
|
required: false,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
withAddPageButton: {
|
withAddPageButton: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -902,6 +920,7 @@ export default {
|
|||||||
pendingFieldAttachmentUuids: [],
|
pendingFieldAttachmentUuids: [],
|
||||||
drawField: null,
|
drawField: null,
|
||||||
drawFieldType: null,
|
drawFieldType: null,
|
||||||
|
drawCustomField: null,
|
||||||
drawOption: null,
|
drawOption: null,
|
||||||
dragField: null,
|
dragField: null,
|
||||||
isDragFile: false
|
isDragFile: false
|
||||||
@@ -912,6 +931,7 @@ export default {
|
|||||||
isSelectModeRef: () => ref(false),
|
isSelectModeRef: () => ref(false),
|
||||||
isCmdKeyRef: () => ref(false),
|
isCmdKeyRef: () => ref(false),
|
||||||
fieldsDragFieldRef: () => ref(),
|
fieldsDragFieldRef: () => ref(),
|
||||||
|
customDragFieldRef: () => ref(),
|
||||||
selectedAreasRef: () => ref([]),
|
selectedAreasRef: () => ref([]),
|
||||||
language () {
|
language () {
|
||||||
return this.locale.split('-')[0].toLowerCase()
|
return this.locale.split('-')[0].toLowerCase()
|
||||||
@@ -1062,6 +1082,30 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toRaw,
|
toRaw,
|
||||||
|
addCustomField (field) {
|
||||||
|
return this.$refs.fields.addCustomField(field)
|
||||||
|
},
|
||||||
|
addCustomFieldWithoutDraw () {
|
||||||
|
const customField = this.drawCustomField
|
||||||
|
|
||||||
|
const field = JSON.parse(JSON.stringify(customField))
|
||||||
|
|
||||||
|
field.uuid = v4()
|
||||||
|
field.submitter_uuid = this.selectedSubmitter.uuid
|
||||||
|
field.areas = []
|
||||||
|
|
||||||
|
if (field.options?.length) {
|
||||||
|
field.options = field.options.map(opt => ({ ...opt, uuid: v4() }))
|
||||||
|
}
|
||||||
|
|
||||||
|
delete field.conditions
|
||||||
|
|
||||||
|
this.insertField(field)
|
||||||
|
this.save()
|
||||||
|
|
||||||
|
this.drawCustomField = null
|
||||||
|
this.showDrawField = false
|
||||||
|
},
|
||||||
toggleSelectMode () {
|
toggleSelectMode () {
|
||||||
this.isSelectModeRef.value = !this.isSelectModeRef.value
|
this.isSelectModeRef.value = !this.isSelectModeRef.value
|
||||||
|
|
||||||
@@ -1514,6 +1558,7 @@ export default {
|
|||||||
clearDrawField () {
|
clearDrawField () {
|
||||||
this.drawField = null
|
this.drawField = null
|
||||||
this.drawOption = null
|
this.drawOption = null
|
||||||
|
this.drawCustomField = null
|
||||||
this.showDrawField = false
|
this.showDrawField = false
|
||||||
|
|
||||||
if (!this.withSelectedFieldType) {
|
if (!this.withSelectedFieldType) {
|
||||||
@@ -1951,6 +1996,10 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onDraw ({ area, isTooSmall }) {
|
onDraw ({ area, isTooSmall }) {
|
||||||
|
if (this.drawCustomField) {
|
||||||
|
return this.onDrawCustomField(area)
|
||||||
|
}
|
||||||
|
|
||||||
if (this.drawField) {
|
if (this.drawField) {
|
||||||
if (this.drawOption) {
|
if (this.drawOption) {
|
||||||
const areaWithoutOption = this.drawField.areas?.find((a) => !a.option_uuid)
|
const areaWithoutOption = this.drawField.areas?.find((a) => !a.option_uuid)
|
||||||
@@ -2061,6 +2110,10 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.customDragFieldRef.value) {
|
||||||
|
return this.dropCustomField(area)
|
||||||
|
}
|
||||||
|
|
||||||
const field = this.fieldsDragFieldRef.value || {
|
const field = this.fieldsDragFieldRef.value || {
|
||||||
name: '',
|
name: '',
|
||||||
uuid: v4(),
|
uuid: v4(),
|
||||||
@@ -2153,6 +2206,122 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
dropCustomField (area) {
|
||||||
|
const customField = this.customDragFieldRef.value
|
||||||
|
const customAreas = customField.areas || []
|
||||||
|
|
||||||
|
const field = JSON.parse(JSON.stringify(customField))
|
||||||
|
|
||||||
|
field.uuid = v4()
|
||||||
|
field.submitter_uuid = this.selectedSubmitter.uuid
|
||||||
|
field.areas = []
|
||||||
|
|
||||||
|
if (field.options?.length) {
|
||||||
|
field.options = field.options.map(opt => ({ ...opt, uuid: v4() }))
|
||||||
|
}
|
||||||
|
|
||||||
|
delete field.conditions
|
||||||
|
|
||||||
|
const dropX = (area.x - 6) / area.maskW
|
||||||
|
const dropY = area.y / area.maskH
|
||||||
|
|
||||||
|
if (customAreas.length > 0) {
|
||||||
|
const refArea = customAreas[0]
|
||||||
|
|
||||||
|
customAreas.forEach((customArea) => {
|
||||||
|
const fieldArea = {
|
||||||
|
x: dropX + (customArea.x - refArea.x),
|
||||||
|
y: dropY + (customArea.y - refArea.y) - (customArea.h / 2),
|
||||||
|
w: customArea.w,
|
||||||
|
h: customArea.h,
|
||||||
|
page: area.page,
|
||||||
|
attachment_uuid: area.attachment_uuid
|
||||||
|
}
|
||||||
|
|
||||||
|
if (customArea.cell_w) {
|
||||||
|
fieldArea.cell_w = customArea.cell_w
|
||||||
|
}
|
||||||
|
|
||||||
|
if (customArea.option_uuid && field.options?.length) {
|
||||||
|
const optionIndex = customField.options.findIndex(o => o.uuid === customArea.option_uuid)
|
||||||
|
if (optionIndex !== -1) {
|
||||||
|
fieldArea.option_uuid = field.options[optionIndex].uuid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
field.areas.push(fieldArea)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const fieldArea = {
|
||||||
|
x: dropX,
|
||||||
|
y: dropY,
|
||||||
|
page: area.page,
|
||||||
|
attachment_uuid: area.attachment_uuid
|
||||||
|
}
|
||||||
|
|
||||||
|
this.assignDropAreaSize(fieldArea, field, area)
|
||||||
|
|
||||||
|
field.areas.push(fieldArea)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectedAreasRef.value = [field.areas[0]]
|
||||||
|
|
||||||
|
this.insertField(field)
|
||||||
|
this.save()
|
||||||
|
|
||||||
|
document.activeElement?.blur()
|
||||||
|
},
|
||||||
|
onDrawCustomField (area) {
|
||||||
|
const customField = this.drawCustomField
|
||||||
|
const customAreas = customField.areas || []
|
||||||
|
|
||||||
|
const field = JSON.parse(JSON.stringify(customField))
|
||||||
|
|
||||||
|
field.uuid = v4()
|
||||||
|
field.submitter_uuid = this.selectedSubmitter.uuid
|
||||||
|
field.areas = []
|
||||||
|
|
||||||
|
if (field.options?.length) {
|
||||||
|
field.options = field.options.map(opt => ({ ...opt, uuid: v4() }))
|
||||||
|
}
|
||||||
|
|
||||||
|
delete field.conditions
|
||||||
|
|
||||||
|
const firstArea = {
|
||||||
|
x: area.x,
|
||||||
|
y: area.y,
|
||||||
|
w: area.w || customAreas[0]?.w,
|
||||||
|
h: area.h || customAreas[0]?.h,
|
||||||
|
page: area.page,
|
||||||
|
attachment_uuid: area.attachment_uuid
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!firstArea.w || !firstArea.h) {
|
||||||
|
if (customAreas[0]) {
|
||||||
|
firstArea.w = customAreas[0].w
|
||||||
|
firstArea.h = customAreas[0].h
|
||||||
|
} else {
|
||||||
|
this.setDefaultAreaSize(firstArea, field.type)
|
||||||
|
}
|
||||||
|
|
||||||
|
firstArea.x -= firstArea.w / 2
|
||||||
|
firstArea.y -= firstArea.h / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field.options?.length) {
|
||||||
|
firstArea.option_uuid = field.options[0].uuid
|
||||||
|
}
|
||||||
|
|
||||||
|
field.areas.push(firstArea)
|
||||||
|
|
||||||
|
this.selectedAreasRef.value = [field.areas[0]]
|
||||||
|
|
||||||
|
this.insertField(field)
|
||||||
|
this.save()
|
||||||
|
|
||||||
|
this.drawCustomField = null
|
||||||
|
this.showDrawField = false
|
||||||
|
},
|
||||||
assignDropAreaSize (fieldArea, field, area) {
|
assignDropAreaSize (fieldArea, field, area) {
|
||||||
const fieldType = field.type || 'text'
|
const fieldType = field.type || 'text'
|
||||||
|
|
||||||
|
|||||||
@@ -6,18 +6,24 @@
|
|||||||
<span
|
<span
|
||||||
ref="contenteditable"
|
ref="contenteditable"
|
||||||
dir="auto"
|
dir="auto"
|
||||||
:contenteditable="editable"
|
:contenteditable="editable && (!editableOnButton || isEditable)"
|
||||||
style="min-width: 2px"
|
:data-placeholder="placeholder"
|
||||||
:class="[iconInline ? 'inline' : 'block', hideIcon ? 'focus:block' : '']"
|
:data-empty="isEmpty"
|
||||||
class="peer outline-none"
|
:style="{ minWidth }"
|
||||||
|
:class="[iconInline ? (isEmpty ? 'inline-block' : 'inline') : 'block', hideIcon ? 'focus:block' : '']"
|
||||||
|
class="peer relative inline-block outline-none before:pointer-events-none before:absolute before:left-0 before:top-0 before:select-none before:whitespace-pre before:text-neutral-400 before:content-[attr(data-placeholder)] before:opacity-0 data-[empty=true]:before:opacity-100"
|
||||||
@paste.prevent="onPaste"
|
@paste.prevent="onPaste"
|
||||||
@keydown.enter.prevent="blurContenteditable"
|
@keydown.enter.prevent="blurContenteditable"
|
||||||
|
@input="updateInputValue"
|
||||||
|
@cut="updateInputValue"
|
||||||
@focus="$emit('focus', $event)"
|
@focus="$emit('focus', $event)"
|
||||||
@blur="onBlur"
|
@blur="onBlur"
|
||||||
|
@click="editable && (!editableOnButton || isEditable) ? '' : $emit('click-contenteditable')"
|
||||||
>
|
>
|
||||||
{{ value }}
|
{{ value }}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
|
v-if="withButton"
|
||||||
class="relative inline"
|
class="relative inline"
|
||||||
:class="{ 'peer-focus:hidden': hideIcon, 'peer-focus:invisible': !hideIcon }"
|
:class="{ 'peer-focus:hidden': hideIcon, 'peer-focus:invisible': !hideIcon }"
|
||||||
>
|
>
|
||||||
@@ -28,7 +34,7 @@
|
|||||||
:class="{ invisible: !editable, 'absolute top-1/2 -translate-y-1/2': !iconInline || floatIcon, 'inline align-bottom': iconInline, 'left-0': floatIcon }"
|
:class="{ invisible: !editable, 'absolute top-1/2 -translate-y-1/2': !iconInline || floatIcon, 'inline align-bottom': iconInline, 'left-0': floatIcon }"
|
||||||
:width="iconWidth + 4"
|
:width="iconWidth + 4"
|
||||||
:stroke-width="iconStrokeWidth"
|
:stroke-width="iconStrokeWidth"
|
||||||
@click="[focusContenteditable(), selectOnEditClick && selectContent()]"
|
@click="clickEdit"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -49,6 +55,16 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
withButton: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
iconInline: {
|
iconInline: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -74,6 +90,16 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
|
editableOnButton: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
minWidth: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: '2px'
|
||||||
|
},
|
||||||
editable: {
|
editable: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -85,21 +111,34 @@ export default {
|
|||||||
default: 2
|
default: 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['update:model-value', 'focus', 'blur'],
|
emits: ['update:model-value', 'focus', 'blur', 'click-contenteditable'],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
isEditable: false,
|
||||||
|
inputValue: '',
|
||||||
value: ''
|
value: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
isEmpty () {
|
||||||
|
return !this.inputValue.replace(/\u200B/g, '').replace(/\u00A0/g, ' ').trim()
|
||||||
|
}
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
handler (value) {
|
handler (value) {
|
||||||
this.value = value
|
this.value = value || ''
|
||||||
},
|
},
|
||||||
immediate: true
|
immediate: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted () {
|
||||||
|
this.updateInputValue()
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
updateInputValue () {
|
||||||
|
this.inputValue = this.$refs.contenteditable?.textContent || ''
|
||||||
|
},
|
||||||
onPaste (e) {
|
onPaste (e) {
|
||||||
const text = (e.clipboardData || window.clipboardData).getData('text/plain')
|
const text = (e.clipboardData || window.clipboardData).getData('text/plain')
|
||||||
|
|
||||||
@@ -110,6 +149,20 @@ export default {
|
|||||||
selection.getRangeAt(0).insertNode(document.createTextNode(text))
|
selection.getRangeAt(0).insertNode(document.createTextNode(text))
|
||||||
selection.collapseToEnd()
|
selection.collapseToEnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.updateInputValue()
|
||||||
|
},
|
||||||
|
clickEdit (e) {
|
||||||
|
this.focusContenteditable()
|
||||||
|
|
||||||
|
if (this.selectOnEditClick) {
|
||||||
|
this.selectContent()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setText (text) {
|
||||||
|
this.$refs.contenteditable.innerText = text
|
||||||
|
|
||||||
|
this.updateInputValue()
|
||||||
},
|
},
|
||||||
selectContent () {
|
selectContent () {
|
||||||
const el = this.$refs.contenteditable
|
const el = this.$refs.contenteditable
|
||||||
@@ -129,10 +182,18 @@ export default {
|
|||||||
this.value = this.$refs.contenteditable.innerText.trim() || this.modelValue
|
this.value = this.$refs.contenteditable.innerText.trim() || this.modelValue
|
||||||
this.$emit('update:model-value', this.value)
|
this.$emit('update:model-value', this.value)
|
||||||
this.$emit('blur', e)
|
this.$emit('blur', e)
|
||||||
|
|
||||||
|
this.isEditable = false
|
||||||
}, 1)
|
}, 1)
|
||||||
},
|
},
|
||||||
focusContenteditable () {
|
focusContenteditable () {
|
||||||
this.$refs.contenteditable.focus()
|
this.isEditable = true
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.contenteditable.focus()
|
||||||
|
|
||||||
|
this.updateInputValue()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
blurContenteditable () {
|
blurContenteditable () {
|
||||||
this.$refs.contenteditable.blur()
|
this.$refs.contenteditable.blur()
|
||||||
|
|||||||
@@ -0,0 +1,267 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="list-field group"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="border border-dashed border-base-300 hover:border-base-content/20 rounded relative group fields-list-item transition-colors"
|
||||||
|
:style="{ backgroundColor: backgroundColor }"
|
||||||
|
>
|
||||||
|
<div class="flex items-center justify-between relative group/contenteditable-container">
|
||||||
|
<div
|
||||||
|
v-if="!isNew"
|
||||||
|
class="absolute top-0 bottom-0 right-0 left-0 cursor-pointer"
|
||||||
|
@click="$emit('click', field)"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="absolute top-0 bottom-0 left-0 flex items-center transition-all cursor-grab group-hover:bg-base-200/50"
|
||||||
|
@click="$emit('click', field)"
|
||||||
|
>
|
||||||
|
<IconDrag style="margin-left: 1px" />
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center p-1 pl-6 space-x-1">
|
||||||
|
<FieldType
|
||||||
|
v-model="field.type"
|
||||||
|
:editable="false"
|
||||||
|
:button-width="20"
|
||||||
|
@click="$emit('click', field)"
|
||||||
|
/>
|
||||||
|
<Contenteditable
|
||||||
|
ref="name"
|
||||||
|
:model-value="field.name"
|
||||||
|
:placeholder="'Field Name'"
|
||||||
|
:icon-inline="true"
|
||||||
|
:icon-width="18"
|
||||||
|
:min-width="isNew ? '100px' : '2px'"
|
||||||
|
:icon-stroke-width="1.6"
|
||||||
|
:editable-on-button="!isNew"
|
||||||
|
:with-button="!isNew"
|
||||||
|
:class="{ 'cursor-pointer': !isNew }"
|
||||||
|
@click-contenteditable="$emit('click', field)"
|
||||||
|
@focus="onNameFocus"
|
||||||
|
@blur="onNameBlur"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex items-center space-x-1"
|
||||||
|
>
|
||||||
|
<PaymentSettings
|
||||||
|
v-if="field.type === 'payment' && !isNew"
|
||||||
|
:field="field"
|
||||||
|
:with-condition="false"
|
||||||
|
@click-description="isShowDescriptionModal = true"
|
||||||
|
@click-formula="isShowFormulaModal = true"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
v-else-if="!isNew"
|
||||||
|
class="dropdown dropdown-end field-settings-dropdown"
|
||||||
|
@mouseenter="renderDropdown = true"
|
||||||
|
@touchstart="renderDropdown = true"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
tabindex="0"
|
||||||
|
:title="t('settings')"
|
||||||
|
class="cursor-pointer text-transparent group-hover:text-base-content"
|
||||||
|
>
|
||||||
|
<IconSettings
|
||||||
|
:width="18"
|
||||||
|
:stroke-width="1.6"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<ul
|
||||||
|
v-if="renderDropdown"
|
||||||
|
tabindex="0"
|
||||||
|
class="mt-1.5 dropdown-content menu menu-xs p-2 shadow rounded-box w-52 z-10"
|
||||||
|
:style="{ backgroundColor: dropdownBgColor }"
|
||||||
|
draggable="true"
|
||||||
|
@dragstart.prevent.stop
|
||||||
|
@click="closeDropdown"
|
||||||
|
>
|
||||||
|
<FieldSettings
|
||||||
|
:field="field"
|
||||||
|
:with-signature-id="withSignatureId"
|
||||||
|
:with-prefillable="withPrefillable"
|
||||||
|
:background-color="dropdownBgColor"
|
||||||
|
:with-areas="false"
|
||||||
|
:with-copy-to-all-pages="false"
|
||||||
|
:with-condition="false"
|
||||||
|
@click-formula="isShowFormulaModal = true"
|
||||||
|
@click-font="isShowFontModal = true"
|
||||||
|
@click-description="isShowDescriptionModal = true"
|
||||||
|
@save="$emit('save')"
|
||||||
|
/>
|
||||||
|
</ul>
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
v-if="isNew && !$refs.name"
|
||||||
|
class="relative text-base-content pr-1 field-save-button"
|
||||||
|
:title="t('save')"
|
||||||
|
@click="field.name ? $emit('save', field) : focusName()"
|
||||||
|
>
|
||||||
|
<IconCheck
|
||||||
|
:width="18"
|
||||||
|
:stroke-width="2"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="relative group-hover:text-base-content pr-1 field-remove-button"
|
||||||
|
:class="isNew ? 'text-base-content' : 'text-transparent group-hover:text-base-content'"
|
||||||
|
:title="t('remove')"
|
||||||
|
@click="onRemoveClick"
|
||||||
|
>
|
||||||
|
<IconTrashX
|
||||||
|
:width="18"
|
||||||
|
:stroke-width="1.6"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Teleport
|
||||||
|
v-if="isShowFormulaModal"
|
||||||
|
:to="modalContainerEl"
|
||||||
|
>
|
||||||
|
<FormulaModal
|
||||||
|
:field="field"
|
||||||
|
:default-field="defaultField"
|
||||||
|
:build-default-name="buildDefaultName"
|
||||||
|
@close="isShowFormulaModal = false"
|
||||||
|
/>
|
||||||
|
</Teleport>
|
||||||
|
<Teleport
|
||||||
|
v-if="isShowFontModal"
|
||||||
|
:to="modalContainerEl"
|
||||||
|
>
|
||||||
|
<FontModal
|
||||||
|
:field="field"
|
||||||
|
:default-field="defaultField"
|
||||||
|
:build-default-name="buildDefaultName"
|
||||||
|
@close="isShowFontModal = false"
|
||||||
|
/>
|
||||||
|
</Teleport>
|
||||||
|
<Teleport
|
||||||
|
v-if="isShowDescriptionModal"
|
||||||
|
:to="modalContainerEl"
|
||||||
|
>
|
||||||
|
<DescriptionModal
|
||||||
|
:field="field"
|
||||||
|
:default-field="defaultField"
|
||||||
|
:build-default-name="buildDefaultName"
|
||||||
|
@close="isShowDescriptionModal = false"
|
||||||
|
/>
|
||||||
|
</Teleport>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Contenteditable from './contenteditable'
|
||||||
|
import FieldType from './field_type'
|
||||||
|
import PaymentSettings from './payment_settings'
|
||||||
|
import FieldSettings from './field_settings'
|
||||||
|
import FormulaModal from './formula_modal'
|
||||||
|
import FontModal from './font_modal'
|
||||||
|
import DescriptionModal from './description_modal'
|
||||||
|
import { IconTrashX, IconSettings, IconCheck } from '@tabler/icons-vue'
|
||||||
|
import IconDrag from './icon_drag'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CustomField',
|
||||||
|
components: {
|
||||||
|
Contenteditable,
|
||||||
|
IconSettings,
|
||||||
|
IconCheck,
|
||||||
|
FieldSettings,
|
||||||
|
PaymentSettings,
|
||||||
|
IconDrag,
|
||||||
|
FormulaModal,
|
||||||
|
FontModal,
|
||||||
|
DescriptionModal,
|
||||||
|
IconTrashX,
|
||||||
|
FieldType
|
||||||
|
},
|
||||||
|
inject: ['template', 'backgroundColor', 'selectedAreasRef', 't', 'locale'],
|
||||||
|
props: {
|
||||||
|
field: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
isNew: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
withSignatureId: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
withPrefillable: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emits: ['remove', 'save', 'click'],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
isShowFormulaModal: false,
|
||||||
|
isShowFontModal: false,
|
||||||
|
isShowDescriptionModal: false,
|
||||||
|
renderDropdown: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
dropdownBgColor () {
|
||||||
|
return ['', null, 'transparent'].includes(this.backgroundColor) ? 'white' : this.backgroundColor
|
||||||
|
},
|
||||||
|
modalContainerEl () {
|
||||||
|
return this.$el.getRootNode().querySelector('#docuseal_modal_container')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.field.preferences ||= {}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
if (this.isNew) {
|
||||||
|
this.focusName()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
buildDefaultName () {
|
||||||
|
return this.t('custom')
|
||||||
|
},
|
||||||
|
focusName () {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$refs.name.clickEdit()
|
||||||
|
}, 1)
|
||||||
|
},
|
||||||
|
onNameFocus (e) {
|
||||||
|
if (!this.field.name) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$refs.name.$refs.contenteditable.innerText = ' '
|
||||||
|
}, 1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
closeDropdown () {
|
||||||
|
this.$el.getRootNode().activeElement.blur()
|
||||||
|
},
|
||||||
|
onRemoveClick () {
|
||||||
|
if (this.isNew || window.confirm(this.t('are_you_sure_'))) {
|
||||||
|
this.$emit('remove', this.field)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onNameBlur (e) {
|
||||||
|
const text = this.$refs.name.$refs.contenteditable.innerText.trim()
|
||||||
|
|
||||||
|
if (text) {
|
||||||
|
this.field.name = text
|
||||||
|
} else {
|
||||||
|
this.$refs.name.setText(this.field.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.field.name) {
|
||||||
|
this.$emit('save')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
:default-submitters="defaultSubmitters"
|
:default-submitters="defaultSubmitters"
|
||||||
:draw-field="drawField"
|
:draw-field="drawField"
|
||||||
:draw-field-type="drawFieldType"
|
:draw-field-type="drawFieldType"
|
||||||
|
:draw-custom-field="drawCustomField"
|
||||||
:selected-submitter="selectedSubmitter"
|
:selected-submitter="selectedSubmitter"
|
||||||
:total-pages="sortedPreviewImages.length"
|
:total-pages="sortedPreviewImages.length"
|
||||||
:image="image"
|
:image="image"
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
@remove-area="$emit('remove-area', $event)"
|
@remove-area="$emit('remove-area', $event)"
|
||||||
@copy-field="$emit('copy-field', $event)"
|
@copy-field="$emit('copy-field', $event)"
|
||||||
@paste-field="$emit('paste-field', { ...$event, attachment_uuid: document.uuid })"
|
@paste-field="$emit('paste-field', { ...$event, attachment_uuid: document.uuid })"
|
||||||
|
@add-custom-field="$emit('add-custom-field', $event)"
|
||||||
@copy-selected-areas="$emit('copy-selected-areas')"
|
@copy-selected-areas="$emit('copy-selected-areas')"
|
||||||
@delete-selected-areas="$emit('delete-selected-areas')"
|
@delete-selected-areas="$emit('delete-selected-areas')"
|
||||||
@align-selected-areas="$emit('align-selected-areas', $event)"
|
@align-selected-areas="$emit('align-selected-areas', $event)"
|
||||||
@@ -115,6 +117,11 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: null
|
default: null
|
||||||
},
|
},
|
||||||
|
drawCustomField: {
|
||||||
|
type: Object,
|
||||||
|
required: false,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
baseUrl: {
|
baseUrl: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -131,7 +138,7 @@ export default {
|
|||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['draw', 'drop-field', 'remove-area', 'paste-field', 'copy-field', 'copy-selected-areas', 'delete-selected-areas', 'align-selected-areas', 'autodetect-fields'],
|
emits: ['draw', 'drop-field', 'remove-area', 'paste-field', 'copy-field', 'copy-selected-areas', 'delete-selected-areas', 'align-selected-areas', 'autodetect-fields', 'add-custom-field'],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
pageRefs: []
|
pageRefs: []
|
||||||
|
|||||||
@@ -8,6 +8,13 @@
|
|||||||
class="fixed z-20 pointer-events-none"
|
class="fixed z-20 pointer-events-none"
|
||||||
:editable="false"
|
:editable="false"
|
||||||
/>
|
/>
|
||||||
|
<CustomField
|
||||||
|
v-else-if="dragPlaceholder && isCustom && !isMask && field"
|
||||||
|
ref="dragPlaceholder"
|
||||||
|
:style="dragPlaceholderStyle"
|
||||||
|
:field="field"
|
||||||
|
class="fixed z-20 pointer-events-none opacity-90"
|
||||||
|
/>
|
||||||
<div
|
<div
|
||||||
v-else-if="dragPlaceholder && (isDefault || isRequired) && !isMask && field"
|
v-else-if="dragPlaceholder && (isDefault || isRequired) && !isMask && field"
|
||||||
ref="dragPlaceholder"
|
ref="dragPlaceholder"
|
||||||
@@ -57,6 +64,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Field from './field'
|
import Field from './field'
|
||||||
|
import CustomField from './custom_field'
|
||||||
import IconDrag from './icon_drag'
|
import IconDrag from './icon_drag'
|
||||||
import FieldType from './field_type'
|
import FieldType from './field_type'
|
||||||
|
|
||||||
@@ -64,6 +72,7 @@ export default {
|
|||||||
name: 'DragPlaceholder',
|
name: 'DragPlaceholder',
|
||||||
components: {
|
components: {
|
||||||
Field,
|
Field,
|
||||||
|
CustomField,
|
||||||
IconDrag
|
IconDrag
|
||||||
},
|
},
|
||||||
inject: ['t', 'backgroundColor'],
|
inject: ['t', 'backgroundColor'],
|
||||||
@@ -87,6 +96,11 @@ export default {
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
isCustom: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="list-field group mb-2"
|
class="list-field group"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="border border-base-300 rounded relative group fields-list-item"
|
class="border border-base-300 rounded relative group fields-list-item"
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
:button-width="20"
|
:button-width="20"
|
||||||
:menu-classes="'mt-1.5'"
|
:menu-classes="'mt-1.5'"
|
||||||
:menu-style="{ backgroundColor: dropdownBgColor }"
|
:menu-style="{ backgroundColor: dropdownBgColor }"
|
||||||
@update:model-value="[maybeUpdateOptions(), save()]"
|
@update:model-value="[maybeUpdateOptions(), $emit('save')]"
|
||||||
@click="scrollToFirstArea"
|
@click="scrollToFirstArea"
|
||||||
/>
|
/>
|
||||||
<Contenteditable
|
<Contenteditable
|
||||||
@@ -92,9 +92,12 @@
|
|||||||
<PaymentSettings
|
<PaymentSettings
|
||||||
v-if="field.type === 'payment'"
|
v-if="field.type === 'payment'"
|
||||||
:field="field"
|
:field="field"
|
||||||
|
:with-custom-fields="withCustomFields"
|
||||||
@click-condition="isShowConditionsModal = true"
|
@click-condition="isShowConditionsModal = true"
|
||||||
@click-description="isShowDescriptionModal = true"
|
@click-description="isShowDescriptionModal = true"
|
||||||
|
@add-custom-field="$emit('add-custom-field', $event)"
|
||||||
@click-formula="isShowFormulaModal = true"
|
@click-formula="isShowFormulaModal = true"
|
||||||
|
@save="$emit('save')"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
v-else
|
v-else
|
||||||
@@ -128,12 +131,15 @@
|
|||||||
:with-signature-id="withSignatureId"
|
:with-signature-id="withSignatureId"
|
||||||
:with-prefillable="withPrefillable"
|
:with-prefillable="withPrefillable"
|
||||||
:background-color="dropdownBgColor"
|
:background-color="dropdownBgColor"
|
||||||
|
:with-custom-fields="withCustomFields"
|
||||||
@click-formula="isShowFormulaModal = true"
|
@click-formula="isShowFormulaModal = true"
|
||||||
@click-font="isShowFontModal = true"
|
@click-font="isShowFontModal = true"
|
||||||
@click-description="isShowDescriptionModal = true"
|
@click-description="isShowDescriptionModal = true"
|
||||||
@click-condition="isShowConditionsModal = true"
|
@click-condition="isShowConditionsModal = true"
|
||||||
@set-draw="$emit('set-draw', $event)"
|
@set-draw="$emit('set-draw', $event)"
|
||||||
|
@add-custom-field="$emit('add-custom-field', $event)"
|
||||||
@remove-area="removeArea"
|
@remove-area="removeArea"
|
||||||
|
@save="$emit('save')"
|
||||||
@scroll-to="$emit('scroll-to', $event)"
|
@scroll-to="$emit('scroll-to', $event)"
|
||||||
/>
|
/>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -186,7 +192,7 @@
|
|||||||
required
|
required
|
||||||
:placeholder="`${t('option')} ${index + 1}`"
|
:placeholder="`${t('option')} ${index + 1}`"
|
||||||
@keydown.enter="option.value ? addOptionAt(index + 1) : null"
|
@keydown.enter="option.value ? addOptionAt(index + 1) : null"
|
||||||
@blur="save"
|
@blur="$emit('save')"
|
||||||
@paste="onOptionPaste($event, index)"
|
@paste="onOptionPaste($event, index)"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
@@ -211,7 +217,7 @@
|
|||||||
dir="auto"
|
dir="auto"
|
||||||
@keydown.enter="option.value ? addOptionAt(index + 1) : null"
|
@keydown.enter="option.value ? addOptionAt(index + 1) : null"
|
||||||
@focus="maybeFocusOnOptionArea(option)"
|
@focus="maybeFocusOnOptionArea(option)"
|
||||||
@blur="save"
|
@blur="$emit('save')"
|
||||||
@paste="onOptionPaste($event, index)"
|
@paste="onOptionPaste($event, index)"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
@@ -334,7 +340,7 @@ export default {
|
|||||||
IconMathFunction,
|
IconMathFunction,
|
||||||
FieldType
|
FieldType
|
||||||
},
|
},
|
||||||
inject: ['template', 'save', 'backgroundColor', 'selectedAreasRef', 't', 'locale'],
|
inject: ['template', 'backgroundColor', 'selectedAreasRef', 't', 'locale'],
|
||||||
props: {
|
props: {
|
||||||
field: {
|
field: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -345,6 +351,11 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: null
|
default: null
|
||||||
},
|
},
|
||||||
|
withCustomFields: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
withPrefillable: {
|
withPrefillable: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -366,12 +377,11 @@ export default {
|
|||||||
default: true
|
default: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['set-draw', 'remove', 'scroll-to'],
|
emits: ['set-draw', 'remove', 'scroll-to', 'save', 'add-custom-field'],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
isExpandOptions: false,
|
isExpandOptions: false,
|
||||||
isNameFocus: false,
|
isNameFocus: false,
|
||||||
showPaymentModal: false,
|
|
||||||
isShowFormulaModal: false,
|
isShowFormulaModal: false,
|
||||||
isShowFontModal: false,
|
isShowFontModal: false,
|
||||||
isShowConditionsModal: false,
|
isShowConditionsModal: false,
|
||||||
@@ -420,7 +430,7 @@ export default {
|
|||||||
removeArea (area) {
|
removeArea (area) {
|
||||||
this.field.areas.splice(this.field.areas.indexOf(area), 1)
|
this.field.areas.splice(this.field.areas.indexOf(area), 1)
|
||||||
|
|
||||||
this.save()
|
this.$emit('save')
|
||||||
},
|
},
|
||||||
buildDefaultName (field, fields) {
|
buildDefaultName (field, fields) {
|
||||||
if (field.type === 'payment' && field.preferences?.price && !field.preferences?.formula) {
|
if (field.type === 'payment' && field.preferences?.price && !field.preferences?.formula) {
|
||||||
@@ -489,7 +499,7 @@ export default {
|
|||||||
inputs[index + newOptions.length]?.focus()
|
inputs[index + newOptions.length]?.focus()
|
||||||
})
|
})
|
||||||
|
|
||||||
this.save()
|
this.$emit('save')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -506,7 +516,7 @@ export default {
|
|||||||
inputs[insertAt]?.focus()
|
inputs[insertAt]?.focus()
|
||||||
})
|
})
|
||||||
|
|
||||||
this.save()
|
this.$emit('save')
|
||||||
},
|
},
|
||||||
removeOption (option) {
|
removeOption (option) {
|
||||||
this.field.options.splice(this.field.options.indexOf(option), 1)
|
this.field.options.splice(this.field.options.indexOf(option), 1)
|
||||||
@@ -517,7 +527,7 @@ export default {
|
|||||||
this.field.areas.splice(this.field.areas.findIndex((a) => a.option_uuid === option.uuid), 1)
|
this.field.areas.splice(this.field.areas.findIndex((a) => a.option_uuid === option.uuid), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.save()
|
this.$emit('save')
|
||||||
},
|
},
|
||||||
maybeUpdateOptions () {
|
maybeUpdateOptions () {
|
||||||
delete this.field.default_value
|
delete this.field.default_value
|
||||||
@@ -559,7 +569,7 @@ export default {
|
|||||||
|
|
||||||
this.isNameFocus = false
|
this.isNameFocus = false
|
||||||
|
|
||||||
this.save()
|
this.$emit('save')
|
||||||
},
|
},
|
||||||
onOptionDragstart (event, option) {
|
onOptionDragstart (event, option) {
|
||||||
this.optionDragRef = option
|
this.optionDragRef = option
|
||||||
@@ -620,7 +630,7 @@ export default {
|
|||||||
if (newOrder.length === this.field.options.length) {
|
if (newOrder.length === this.field.options.length) {
|
||||||
this.field.options.splice(0, this.field.options.length, ...newOrder)
|
this.field.options.splice(0, this.field.options.length, ...newOrder)
|
||||||
|
|
||||||
this.save()
|
this.$emit('save')
|
||||||
}
|
}
|
||||||
|
|
||||||
this.optionDragRef = null
|
this.optionDragRef = null
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<select
|
<select
|
||||||
:placeholder="t('method')"
|
:placeholder="t('method')"
|
||||||
class="select select-bordered select-xs font-normal w-full max-w-xs !h-7 !outline-0 bg-transparent"
|
class="select select-bordered select-xs font-normal w-full max-w-xs !h-7 !outline-0 bg-transparent"
|
||||||
@change="[field.preferences ||= {}, field.preferences.method = $event.target.value, save()]"
|
@change="[field.preferences ||= {}, field.preferences.method = $event.target.value, $emit('save')]"
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
v-for="method in ['QeS', 'AeS']"
|
v-for="method in ['QeS', 'AeS']"
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
>
|
>
|
||||||
<select
|
<select
|
||||||
class="select select-bordered select-xs w-full max-w-xs h-7 !outline-0 font-normal bg-transparent"
|
class="select select-bordered select-xs w-full max-w-xs h-7 !outline-0 font-normal bg-transparent"
|
||||||
@change="[field.preferences ||= {}, field.preferences.align = $event.target.value, save()]"
|
@change="[field.preferences ||= {}, field.preferences.align = $event.target.value, $emit('save')]"
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
v-for="value in ['left', 'right', field.type === 'cells' ? null : 'center'].filter(Boolean)"
|
v-for="value in ['left', 'right', field.type === 'cells' ? null : 'center'].filter(Boolean)"
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
:placeholder="t('default_value')"
|
:placeholder="t('default_value')"
|
||||||
dir="auto"
|
dir="auto"
|
||||||
class="select select-bordered select-xs w-full max-w-xs h-7 !outline-0 font-normal bg-transparent"
|
class="select select-bordered select-xs w-full max-w-xs h-7 !outline-0 font-normal bg-transparent"
|
||||||
@change="[field.default_value = $event.target.value, !field.default_value && delete field.default_value, save()]"
|
@change="[field.default_value = $event.target.value, !field.default_value && delete field.default_value, $emit('save')]"
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
value=""
|
value=""
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
dir="auto"
|
dir="auto"
|
||||||
:type="field.type"
|
:type="field.type"
|
||||||
class="input input-bordered input-xs w-full max-w-xs h-7 !outline-0 bg-transparent"
|
class="input input-bordered input-xs w-full max-w-xs h-7 !outline-0 bg-transparent"
|
||||||
@blur="save"
|
@blur="$emit('save')"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
v-if="field.default_value"
|
v-if="field.default_value"
|
||||||
@@ -159,7 +159,7 @@
|
|||||||
:value="lengthValidation.min"
|
:value="lengthValidation.min"
|
||||||
class="input input-bordered w-full input-xs h-7 !outline-0 bg-transparent"
|
class="input input-bordered w-full input-xs h-7 !outline-0 bg-transparent"
|
||||||
@input="field.validation.pattern = `.{${$event.target.value || 0},${lengthValidation.max || ''}}`"
|
@input="field.validation.pattern = `.{${$event.target.value || 0},${lengthValidation.max || ''}}`"
|
||||||
@blur="save"
|
@blur="$emit('save')"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
v-if="lengthValidation.min"
|
v-if="lengthValidation.min"
|
||||||
@@ -178,7 +178,7 @@
|
|||||||
class="input input-bordered w-full input-xs h-7 !outline-0 bg-transparent"
|
class="input input-bordered w-full input-xs h-7 !outline-0 bg-transparent"
|
||||||
:value="lengthValidation.max"
|
:value="lengthValidation.max"
|
||||||
@input="field.validation.pattern = `.{${lengthValidation.min},${$event.target.value || ''}}`"
|
@input="field.validation.pattern = `.{${lengthValidation.min},${$event.target.value || ''}}`"
|
||||||
@blur="save"
|
@blur="$emit('save')"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
v-if="lengthValidation.max"
|
v-if="lengthValidation.max"
|
||||||
@@ -203,7 +203,7 @@
|
|||||||
:value="field.validation?.min"
|
:value="field.validation?.min"
|
||||||
class="input input-bordered w-full input-xs h-7 !outline-0 bg-transparent"
|
class="input input-bordered w-full input-xs h-7 !outline-0 bg-transparent"
|
||||||
@input="[field.validation ||= {}, $event.target.value ? field.validation.min = $event.target.value : delete field.validation.min]"
|
@input="[field.validation ||= {}, $event.target.value ? field.validation.min = $event.target.value : delete field.validation.min]"
|
||||||
@blur="save"
|
@blur="$emit('save')"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
v-if="field.validation?.min"
|
v-if="field.validation?.min"
|
||||||
@@ -222,7 +222,7 @@
|
|||||||
class="input input-bordered w-full input-xs h-7 !outline-0 bg-transparent"
|
class="input input-bordered w-full input-xs h-7 !outline-0 bg-transparent"
|
||||||
:value="field.validation?.max"
|
:value="field.validation?.max"
|
||||||
@input="[field.validation ||= {}, $event.target.value ? field.validation.max = $event.target.value : delete field.validation.max]"
|
@input="[field.validation ||= {}, $event.target.value ? field.validation.max = $event.target.value : delete field.validation.max]"
|
||||||
@blur="save"
|
@blur="$emit('save')"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
v-if="field.validation?.max"
|
v-if="field.validation?.max"
|
||||||
@@ -242,7 +242,7 @@
|
|||||||
<select
|
<select
|
||||||
:placeholder="t('format')"
|
:placeholder="t('format')"
|
||||||
class="select select-bordered select-xs font-normal w-full max-w-xs !h-7 !outline-0 bg-transparent"
|
class="select select-bordered select-xs font-normal w-full max-w-xs !h-7 !outline-0 bg-transparent"
|
||||||
@change="[field.preferences ||= {}, field.preferences.format = $event.target.value, save()]"
|
@change="[field.preferences ||= {}, field.preferences.format = $event.target.value, $emit('save')]"
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
v-for="format in numberFormats"
|
v-for="format in numberFormats"
|
||||||
@@ -272,7 +272,7 @@
|
|||||||
:placeholder="t('regexp_validation')"
|
:placeholder="t('regexp_validation')"
|
||||||
dir="auto"
|
dir="auto"
|
||||||
class="input input-bordered input-xs w-full max-w-xs h-7 !outline-0 bg-transparent"
|
class="input input-bordered input-xs w-full max-w-xs h-7 !outline-0 bg-transparent"
|
||||||
@blur="save"
|
@blur="$emit('save')"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
v-if="field.validation.pattern"
|
v-if="field.validation.pattern"
|
||||||
@@ -293,7 +293,7 @@
|
|||||||
:placeholder="t('error_message')"
|
:placeholder="t('error_message')"
|
||||||
dir="auto"
|
dir="auto"
|
||||||
class="input input-bordered input-xs w-full max-w-xs h-7 !outline-0 bg-transparent"
|
class="input input-bordered input-xs w-full max-w-xs h-7 !outline-0 bg-transparent"
|
||||||
@blur="save"
|
@blur="$emit('save')"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
v-if="field.validation.message"
|
v-if="field.validation.message"
|
||||||
@@ -313,7 +313,7 @@
|
|||||||
v-model="field.preferences.format"
|
v-model="field.preferences.format"
|
||||||
:placeholder="t('format')"
|
:placeholder="t('format')"
|
||||||
class="select select-bordered select-xs font-normal w-full max-w-xs !h-7 !outline-0 bg-transparent"
|
class="select select-bordered select-xs font-normal w-full max-w-xs !h-7 !outline-0 bg-transparent"
|
||||||
@change="save"
|
@change="$emit('save')"
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
v-for="format in dateFormats"
|
v-for="format in dateFormats"
|
||||||
@@ -339,7 +339,7 @@
|
|||||||
<select
|
<select
|
||||||
:placeholder="t('format')"
|
:placeholder="t('format')"
|
||||||
class="select select-bordered select-xs font-normal w-full max-w-xs !h-7 !outline-0 bg-transparent"
|
class="select select-bordered select-xs font-normal w-full max-w-xs !h-7 !outline-0 bg-transparent"
|
||||||
@change="[field.preferences.format = $event.target.value, save()]"
|
@change="[field.preferences.format = $event.target.value, $emit('save')]"
|
||||||
>
|
>
|
||||||
<option
|
<option
|
||||||
value="any"
|
value="any"
|
||||||
@@ -374,7 +374,7 @@
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
:disabled="!editable || (defaultField && [true, false].includes(defaultField.required))"
|
:disabled="!editable || (defaultField && [true, false].includes(defaultField.required))"
|
||||||
class="toggle toggle-xs"
|
class="toggle toggle-xs"
|
||||||
@change="[field.preferences ||= {}, field.preferences.with_signature_id = $event.target.checked, save()]"
|
@change="[field.preferences ||= {}, field.preferences.with_signature_id = $event.target.checked, $emit('save')]"
|
||||||
>
|
>
|
||||||
<span class="label-text">{{ t('signature_id') }}</span>
|
<span class="label-text">{{ t('signature_id') }}</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -389,7 +389,7 @@
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
:disabled="!editable || (defaultField && [true, false].includes(defaultField.required))"
|
:disabled="!editable || (defaultField && [true, false].includes(defaultField.required))"
|
||||||
class="toggle toggle-xs"
|
class="toggle toggle-xs"
|
||||||
@update:model-value="save"
|
@update:model-value="$emit('save')"
|
||||||
>
|
>
|
||||||
<span class="label-text">{{ t('required') }}</span>
|
<span class="label-text">{{ t('required') }}</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -403,7 +403,7 @@
|
|||||||
:checked="field.preferences?.with_logo != false"
|
:checked="field.preferences?.with_logo != false"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="toggle toggle-xs"
|
class="toggle toggle-xs"
|
||||||
@change="[field.preferences ||= {}, field.preferences.with_logo = field.preferences.with_logo == false, save()]"
|
@change="[field.preferences ||= {}, field.preferences.with_logo = field.preferences.with_logo == false, $emit('save')]"
|
||||||
>
|
>
|
||||||
<span class="label-text">{{ t('with_logo') }}</span>
|
<span class="label-text">{{ t('with_logo') }}</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -417,7 +417,7 @@
|
|||||||
v-model="field.default_value"
|
v-model="field.default_value"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="toggle toggle-xs"
|
class="toggle toggle-xs"
|
||||||
@update:model-value="[field.default_value = $event, field.readonly = $event, save()]"
|
@update:model-value="[field.default_value = $event, field.readonly = $event, $emit('save')]"
|
||||||
>
|
>
|
||||||
<span class="label-text">{{ t('checked') }}</span>
|
<span class="label-text">{{ t('checked') }}</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -431,7 +431,7 @@
|
|||||||
v-model="field.readonly"
|
v-model="field.readonly"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="toggle toggle-xs"
|
class="toggle toggle-xs"
|
||||||
@update:model-value="[field.default_value = $event ? '{{date}}' : null, field.readonly = $event, save()]"
|
@update:model-value="[field.default_value = $event ? '{{date}}' : null, field.readonly = $event, $emit('save')]"
|
||||||
>
|
>
|
||||||
<span class="label-text">{{ t('set_signing_date') }}</span>
|
<span class="label-text">{{ t('set_signing_date') }}</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -446,7 +446,7 @@
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="toggle toggle-xs"
|
class="toggle toggle-xs"
|
||||||
:disabled="!editable || (defaultField && [true, false].includes(defaultField.readonly))"
|
:disabled="!editable || (defaultField && [true, false].includes(defaultField.readonly))"
|
||||||
@update:model-value="save"
|
@update:model-value="$emit('save')"
|
||||||
>
|
>
|
||||||
<span class="label-text">{{ t('read_only') }}</span>
|
<span class="label-text">{{ t('read_only') }}</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -461,7 +461,7 @@
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
:disabled="!editable || (defaultField && [true, false].includes(defaultField.prefillable))"
|
:disabled="!editable || (defaultField && [true, false].includes(defaultField.prefillable))"
|
||||||
class="toggle toggle-xs"
|
class="toggle toggle-xs"
|
||||||
@update:model-value="save"
|
@update:model-value="$emit('save')"
|
||||||
>
|
>
|
||||||
<span class="label-text">{{ t('prefillable') }}</span>
|
<span class="label-text">{{ t('prefillable') }}</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -499,7 +499,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
v-if="field.type != 'stamp' && field.type != 'heading'"
|
v-if="withCondition && field.type != 'stamp' && field.type != 'heading'"
|
||||||
>
|
>
|
||||||
<label
|
<label
|
||||||
class="label-text cursor-pointer text-center w-full flex items-center"
|
class="label-text cursor-pointer text-center w-full flex items-center"
|
||||||
@@ -526,7 +526,10 @@
|
|||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<hr class="pb-0.5 mt-0.5">
|
<hr
|
||||||
|
v-if="withCopyToAllPages || withAreas || withCustomFields"
|
||||||
|
class="pb-0.5 mt-0.5"
|
||||||
|
>
|
||||||
<template v-if="withAreas">
|
<template v-if="withAreas">
|
||||||
<li
|
<li
|
||||||
v-for="(area, index) in sortedAreas"
|
v-for="(area, index) in sortedAreas"
|
||||||
@@ -564,7 +567,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
<li v-if="field.areas?.length === 1 && ['date', 'signature', 'initials', 'text', 'cells', 'stamp'].includes(field.type)">
|
<li v-if="withCopyToAllPages && field.areas?.length === 1 && ['date', 'signature', 'initials', 'text', 'cells', 'stamp'].includes(field.type)">
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="#"
|
||||||
class="text-sm py-1 px-2"
|
class="text-sm py-1 px-2"
|
||||||
@@ -577,10 +580,23 @@
|
|||||||
{{ t('copy_to_all_pages') }}
|
{{ t('copy_to_all_pages') }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li v-if="withCustomFields">
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="text-sm py-1 px-2"
|
||||||
|
@click.prevent="$emit('add-custom-field', field)"
|
||||||
|
>
|
||||||
|
<IconForms
|
||||||
|
:width="20"
|
||||||
|
:stroke-width="1.6"
|
||||||
|
/>
|
||||||
|
{{ t('save_as_custom_field') }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { IconRouteAltLeft, IconTypography, IconShape, IconX, IconMathFunction, IconNewSection, IconInfoCircle, IconCopy } from '@tabler/icons-vue'
|
import { IconRouteAltLeft, IconTypography, IconShape, IconX, IconMathFunction, IconNewSection, IconInfoCircle, IconCopy, IconForms } from '@tabler/icons-vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'FieldSettings',
|
name: 'FieldSettings',
|
||||||
@@ -589,17 +605,33 @@ export default {
|
|||||||
IconInfoCircle,
|
IconInfoCircle,
|
||||||
IconMathFunction,
|
IconMathFunction,
|
||||||
IconRouteAltLeft,
|
IconRouteAltLeft,
|
||||||
|
IconForms,
|
||||||
IconCopy,
|
IconCopy,
|
||||||
IconNewSection,
|
IconNewSection,
|
||||||
IconTypography,
|
IconTypography,
|
||||||
IconX
|
IconX
|
||||||
},
|
},
|
||||||
inject: ['template', 'save', 't'],
|
inject: ['template', 't'],
|
||||||
props: {
|
props: {
|
||||||
field: {
|
field: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
withCondition: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
withCustomFields: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
withCopyToAllPages: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
withSignatureId: {
|
withSignatureId: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -636,7 +668,7 @@ export default {
|
|||||||
default: true
|
default: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['set-draw', 'scroll-to', 'click-formula', 'click-description', 'click-condition', 'click-font', 'remove-area'],
|
emits: ['set-draw', 'scroll-to', 'click-formula', 'click-description', 'click-condition', 'click-font', 'remove-area', 'save', 'add-custom-field'],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
selectedValidation: ''
|
selectedValidation: ''
|
||||||
@@ -730,7 +762,7 @@ export default {
|
|||||||
delete this.field.validation
|
delete this.field.validation
|
||||||
}
|
}
|
||||||
|
|
||||||
this.save()
|
this.$emit('save')
|
||||||
},
|
},
|
||||||
copyToAllPages (field) {
|
copyToAllPages (field) {
|
||||||
const areaString = JSON.stringify(field.areas[0])
|
const areaString = JSON.stringify(field.areas[0])
|
||||||
@@ -747,7 +779,7 @@ export default {
|
|||||||
|
|
||||||
this.$emit('scroll-to', this.field.areas[this.field.areas.length - 1])
|
this.$emit('scroll-to', this.field.areas[this.field.areas.length - 1])
|
||||||
|
|
||||||
this.save()
|
this.$emit('save')
|
||||||
},
|
},
|
||||||
formatNumber (number, format) {
|
formatNumber (number, format) {
|
||||||
if (format === 'comma') {
|
if (format === 'comma') {
|
||||||
|
|||||||
@@ -15,7 +15,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
ref="fields"
|
ref="fields"
|
||||||
class="fields mb-1 mt-2"
|
class="fields mt-2"
|
||||||
|
:class="{ 'mb-1': !withCustomFields || !customFields.length }"
|
||||||
@dragover.prevent="onFieldDragover"
|
@dragover.prevent="onFieldDragover"
|
||||||
@drop="fieldsDragFieldRef.value ? reorderFields() : null"
|
@drop="fieldsDragFieldRef.value ? reorderFields() : null"
|
||||||
>
|
>
|
||||||
@@ -30,7 +31,11 @@
|
|||||||
:with-prefillable="withPrefillable"
|
:with-prefillable="withPrefillable"
|
||||||
:default-field="defaultFieldsIndex[field.name]"
|
:default-field="defaultFieldsIndex[field.name]"
|
||||||
:draggable="editable"
|
:draggable="editable"
|
||||||
|
:with-custom-fields="withCustomFields"
|
||||||
|
class="mb-1.5"
|
||||||
|
@add-custom-field="addCustomField"
|
||||||
@dragstart="[fieldsDragFieldRef.value = field, removeDragOverlay($event), setDragPlaceholder($event)]"
|
@dragstart="[fieldsDragFieldRef.value = field, removeDragOverlay($event), setDragPlaceholder($event)]"
|
||||||
|
@save="save"
|
||||||
@dragend="[fieldsDragFieldRef.value = null, $emit('set-drag-placeholder', null)]"
|
@dragend="[fieldsDragFieldRef.value = null, $emit('set-drag-placeholder', null)]"
|
||||||
@remove="removeField"
|
@remove="removeField"
|
||||||
@scroll-to="$emit('scroll-to-area', $event)"
|
@scroll-to="$emit('scroll-to-area', $event)"
|
||||||
@@ -105,7 +110,92 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="editable && !onlyDefinedFields"
|
v-if="editable && withCustomFields && (customFields.length || newCustomField)"
|
||||||
|
class="tabs w-full mb-1.5"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
class="tab tab-bordered w-1/2 border-base-300"
|
||||||
|
:class="{ 'tab-active': !showCustomTab }"
|
||||||
|
:style="{ '--tab-border': showCustomTab ? '0px' : '0.5px' }"
|
||||||
|
@click="setFieldsTab('default')"
|
||||||
|
>{{ t('default') }}</a>
|
||||||
|
<a
|
||||||
|
class="tab tab-bordered w-1/2 border-base-300"
|
||||||
|
:class="{ 'tab-active': showCustomTab }"
|
||||||
|
:style="{ '--tab-border': showCustomTab ? '0.5px' : '0px' }"
|
||||||
|
@click="setFieldsTab('custom')"
|
||||||
|
>{{ t('custom') }}</a>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="showCustomTab && editable"
|
||||||
|
ref="customFields"
|
||||||
|
class="custom-fields"
|
||||||
|
@dragover.prevent="onCustomFieldDragover"
|
||||||
|
@drop="customDragFieldRef.value ? reorderCustomFields() : null"
|
||||||
|
>
|
||||||
|
<template v-if="isShowCustomFieldSearch">
|
||||||
|
<input
|
||||||
|
v-model="customFieldsSearch"
|
||||||
|
:placeholder="t('search_field')"
|
||||||
|
class="input input-ghost input-xs px-0 text-base mb-1 !outline-0 !rounded bg-transparent w-full"
|
||||||
|
>
|
||||||
|
<hr class="mb-2">
|
||||||
|
</template>
|
||||||
|
<div
|
||||||
|
ref="customFieldsList"
|
||||||
|
class="overflow-auto relative"
|
||||||
|
:style="{
|
||||||
|
maxHeight: isShowCustomFieldSearch ? '320px' : '',
|
||||||
|
minHeight: '320px'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="!filteredCustomFields.length && customFieldsSearch"
|
||||||
|
class="top-0 bottom-0 text-center absolute flex items-center justify-center w-full flex-col"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
{{ t('field_not_found') }}
|
||||||
|
</div>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="link"
|
||||||
|
@click.prevent="customFieldsSearch = ''"
|
||||||
|
>
|
||||||
|
{{ t('clear') }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<CustomField
|
||||||
|
v-if="newCustomField"
|
||||||
|
:key="newCustomField.uuid"
|
||||||
|
ref="newCustomField"
|
||||||
|
:data-uuid="newCustomField.uuid"
|
||||||
|
:is-new="true"
|
||||||
|
:field="newCustomField"
|
||||||
|
:draggable="false"
|
||||||
|
class="mb-1.5"
|
||||||
|
@save="onNewCustomFieldSave"
|
||||||
|
@remove="newCustomField = null"
|
||||||
|
/>
|
||||||
|
<CustomField
|
||||||
|
v-for="field in filteredCustomFields"
|
||||||
|
:key="field.uuid"
|
||||||
|
:data-uuid="field.uuid"
|
||||||
|
:field="field"
|
||||||
|
:draggable="true"
|
||||||
|
class="mb-1.5"
|
||||||
|
:with-signature-id="withSignatureId"
|
||||||
|
:with-prefillable="withPrefillable"
|
||||||
|
@save="saveCustomFields"
|
||||||
|
@click="$emit('set-draw-custom-field', field)"
|
||||||
|
@dragstart="[customDragFieldRef.value = field, removeDragOverlay($event), setDragPlaceholder($event)]"
|
||||||
|
@dragend="[customDragFieldRef.value = null, $emit('set-drag-placeholder', null)]"
|
||||||
|
@remove="removeCustomField"
|
||||||
|
@set-draw="$emit('set-draw', $event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="editable && !onlyDefinedFields && (!showCustomTab || (!customFields.length && !newCustomField))"
|
||||||
id="field-types-grid"
|
id="field-types-grid"
|
||||||
class="grid grid-cols-3 gap-1 pb-2 fields-grid"
|
class="grid grid-cols-3 gap-1 pb-2 fields-grid"
|
||||||
>
|
>
|
||||||
@@ -266,15 +356,18 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Field from './field'
|
import Field from './field'
|
||||||
|
import CustomField from './custom_field'
|
||||||
import FieldType from './field_type'
|
import FieldType from './field_type'
|
||||||
import FieldSubmitter from './field_submitter'
|
import FieldSubmitter from './field_submitter'
|
||||||
import { IconLock, IconCirclePlus, IconInnerShadowTop, IconSparkles } from '@tabler/icons-vue'
|
import { IconLock, IconCirclePlus, IconInnerShadowTop, IconSparkles } from '@tabler/icons-vue'
|
||||||
import IconDrag from './icon_drag'
|
import IconDrag from './icon_drag'
|
||||||
|
import { v4 } from 'uuid'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TemplateFields',
|
name: 'TemplateFields',
|
||||||
components: {
|
components: {
|
||||||
Field,
|
Field,
|
||||||
|
CustomField,
|
||||||
FieldType,
|
FieldType,
|
||||||
IconCirclePlus,
|
IconCirclePlus,
|
||||||
IconSparkles,
|
IconSparkles,
|
||||||
@@ -283,12 +376,22 @@ export default {
|
|||||||
IconDrag,
|
IconDrag,
|
||||||
IconLock
|
IconLock
|
||||||
},
|
},
|
||||||
inject: ['save', 'backgroundColor', 'withPhone', 'withVerification', 'withKba', 'withPayment', 't', 'fieldsDragFieldRef', 'baseFetch', 'selectedAreasRef'],
|
inject: ['save', 'backgroundColor', 'withPhone', 'withVerification', 'withKba', 'withPayment', 't', 'fieldsDragFieldRef', 'customDragFieldRef', 'baseFetch', 'selectedAreasRef'],
|
||||||
props: {
|
props: {
|
||||||
fields: {
|
fields: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
customFields: {
|
||||||
|
type: Array,
|
||||||
|
required: false,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
withCustomFields: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
withFieldsSearch: {
|
withFieldsSearch: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -372,12 +475,15 @@ export default {
|
|||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['add-field', 'set-draw', 'set-draw-type', 'set-drag', 'drag-end', 'scroll-to-area', 'change-submitter', 'set-drag-placeholder', 'select-submitter'],
|
emits: ['add-field', 'set-draw', 'set-draw-type', 'set-draw-custom-field', 'set-drag', 'drag-end', 'scroll-to-area', 'change-submitter', 'set-drag-placeholder', 'select-submitter'],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
fieldPagesLoaded: null,
|
fieldPagesLoaded: null,
|
||||||
analyzingProgress: 0,
|
analyzingProgress: 0,
|
||||||
defaultFieldsSearch: ''
|
newCustomField: null,
|
||||||
|
showCustomTab: false,
|
||||||
|
defaultFieldsSearch: '',
|
||||||
|
customFieldsSearch: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -430,6 +536,23 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
return this.submitterDefaultFields
|
return this.submitterDefaultFields
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
isShowCustomFieldSearch () {
|
||||||
|
return this.customFields.length > 8
|
||||||
|
},
|
||||||
|
filteredCustomFields () {
|
||||||
|
if (this.customFieldsSearch) {
|
||||||
|
return this.customFields.filter((f) => f.name.toLowerCase().includes(this.customFieldsSearch.toLowerCase()))
|
||||||
|
} else {
|
||||||
|
return this.customFields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
try {
|
||||||
|
this.showCustomTab = localStorage.getItem('docuseal_builder_tab') === 'custom'
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -440,6 +563,61 @@ export default {
|
|||||||
|
|
||||||
this.$emit('set-drag', field)
|
this.$emit('set-drag', field)
|
||||||
},
|
},
|
||||||
|
onNewCustomFieldSave () {
|
||||||
|
if (this.newCustomField.name) {
|
||||||
|
this.customFields.unshift(this.newCustomField)
|
||||||
|
this.newCustomField = null
|
||||||
|
|
||||||
|
this.saveCustomFields()
|
||||||
|
} else {
|
||||||
|
this.newCustomField = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addCustomField (field) {
|
||||||
|
const customField = JSON.parse(JSON.stringify(field))
|
||||||
|
|
||||||
|
customField.uuid = v4()
|
||||||
|
|
||||||
|
delete customField.submitter_uuid
|
||||||
|
delete customField.prefillable
|
||||||
|
delete customField.conditions
|
||||||
|
|
||||||
|
customField.areas?.forEach((area) => {
|
||||||
|
delete customField.attachment_uuid
|
||||||
|
delete customField.page
|
||||||
|
})
|
||||||
|
|
||||||
|
if (customField.name) {
|
||||||
|
this.customFields.unshift(customField)
|
||||||
|
this.saveCustomFields()
|
||||||
|
} else {
|
||||||
|
this.newCustomField = customField
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setFieldsTab('custom')
|
||||||
|
},
|
||||||
|
setFieldsTab (type) {
|
||||||
|
try {
|
||||||
|
localStorage.setItem('docuseal_builder_tab', type)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.showCustomTab = type === 'custom'
|
||||||
|
},
|
||||||
|
saveCustomFields () {
|
||||||
|
return this.baseFetch('/account_custom_fields', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
value: this.customFields
|
||||||
|
}),
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
}).then(async (resp) => {
|
||||||
|
const fields = await resp.json()
|
||||||
|
|
||||||
|
this.customFields.splice(0, this.customFields.length, ...fields)
|
||||||
|
})
|
||||||
|
},
|
||||||
detectFields () {
|
detectFields () {
|
||||||
const fields = []
|
const fields = []
|
||||||
|
|
||||||
@@ -617,6 +795,47 @@ export default {
|
|||||||
if (save) {
|
if (save) {
|
||||||
this.save()
|
this.save()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
removeCustomField (field) {
|
||||||
|
this.customFields.splice(this.customFields.indexOf(field), 1)
|
||||||
|
|
||||||
|
if (!this.customFields.length) {
|
||||||
|
this.setFieldsTab('default')
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveCustomFields()
|
||||||
|
},
|
||||||
|
onCustomFieldDragover (e) {
|
||||||
|
if (this.customDragFieldRef.value && this.customFields.includes(this.customDragFieldRef.value)) {
|
||||||
|
const container = this.$refs.customFieldsList
|
||||||
|
const targetField = e.target.closest('[data-uuid]')
|
||||||
|
const dragField = container.querySelector(`[data-uuid="${this.customDragFieldRef.value.uuid}"]`)
|
||||||
|
|
||||||
|
if (dragField && targetField && targetField !== dragField) {
|
||||||
|
const fields = Array.from(container.children)
|
||||||
|
const currentIndex = fields.indexOf(dragField)
|
||||||
|
const targetIndex = fields.indexOf(targetField)
|
||||||
|
|
||||||
|
if (currentIndex < targetIndex) {
|
||||||
|
targetField.after(dragField)
|
||||||
|
} else {
|
||||||
|
targetField.before(dragField)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
reorderCustomFields () {
|
||||||
|
if (!this.customFields.includes(this.customDragFieldRef.value)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const reorderedFields = Array.from(this.$refs.customFieldsList.children).map((el) => {
|
||||||
|
return this.customFields.find((f) => f.uuid === el.dataset.uuid)
|
||||||
|
}).filter(Boolean)
|
||||||
|
|
||||||
|
this.customFields.splice(0, this.customFields.length, ...reorderedFields)
|
||||||
|
|
||||||
|
this.saveCustomFields()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
const en = {
|
const en = {
|
||||||
|
default: 'Default',
|
||||||
|
save_as_custom_field: 'Save as Custom Field',
|
||||||
kba: 'KBA',
|
kba: 'KBA',
|
||||||
analyzing_: 'Analyzing...',
|
analyzing_: 'Analyzing...',
|
||||||
download: 'Download',
|
download: 'Download',
|
||||||
downloading_: 'Downloading...',
|
downloading_: 'Downloading...',
|
||||||
view: 'View',
|
view: 'View',
|
||||||
autodetect_fields: 'Autodetect fields',
|
autodetect_fields: 'Autodetect Fields',
|
||||||
payment_link: 'Payment link',
|
payment_link: 'Payment link',
|
||||||
strikeout: 'Strikeout',
|
strikeout: 'Strikeout',
|
||||||
draw_strikethrough_the_document: 'Draw strikethrough the document',
|
draw_strikethrough_the_document: 'Draw strikethrough the document',
|
||||||
@@ -200,6 +202,8 @@ const en = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const es = {
|
const es = {
|
||||||
|
default: 'Predeterminado',
|
||||||
|
save_as_custom_field: 'Guardar como personalizado',
|
||||||
kba: 'KBA',
|
kba: 'KBA',
|
||||||
autodetect_fields: 'Autodetectar campos',
|
autodetect_fields: 'Autodetectar campos',
|
||||||
analyzing_: 'Analizando...',
|
analyzing_: 'Analizando...',
|
||||||
@@ -401,6 +405,8 @@ const es = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const it = {
|
const it = {
|
||||||
|
default: 'Predefinito',
|
||||||
|
save_as_custom_field: 'Salva come personalizzato',
|
||||||
kba: 'KBA',
|
kba: 'KBA',
|
||||||
autodetect_fields: 'Rileva campi',
|
autodetect_fields: 'Rileva campi',
|
||||||
analyzing_: 'Analisi...',
|
analyzing_: 'Analisi...',
|
||||||
@@ -602,6 +608,8 @@ const it = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const pt = {
|
const pt = {
|
||||||
|
default: 'Padrão',
|
||||||
|
save_as_custom_field: 'Salvar como personalizado',
|
||||||
kba: 'KBA',
|
kba: 'KBA',
|
||||||
autodetect_fields: 'Detectar campos',
|
autodetect_fields: 'Detectar campos',
|
||||||
analyzing_: 'Analisando...',
|
analyzing_: 'Analisando...',
|
||||||
@@ -803,6 +811,8 @@ const pt = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fr = {
|
const fr = {
|
||||||
|
default: 'Par défaut',
|
||||||
|
save_as_custom_field: 'Enregistrer comme personnalisé',
|
||||||
kba: 'KBA',
|
kba: 'KBA',
|
||||||
autodetect_fields: 'Détecter les champs',
|
autodetect_fields: 'Détecter les champs',
|
||||||
analyzing_: 'Analyse...',
|
analyzing_: 'Analyse...',
|
||||||
@@ -1004,6 +1014,8 @@ const fr = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const de = {
|
const de = {
|
||||||
|
default: 'Standard',
|
||||||
|
save_as_custom_field: 'Als benutzerdefiniert speichern',
|
||||||
kba: 'KBA',
|
kba: 'KBA',
|
||||||
autodetect_fields: 'Felder erkennen',
|
autodetect_fields: 'Felder erkennen',
|
||||||
analyzing_: 'Analysiere...',
|
analyzing_: 'Analysiere...',
|
||||||
@@ -1205,6 +1217,8 @@ const de = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const nl = {
|
const nl = {
|
||||||
|
default: 'Standaard',
|
||||||
|
save_as_custom_field: 'Opslaan als aangepast',
|
||||||
kba: 'KBA',
|
kba: 'KBA',
|
||||||
autodetect_fields: 'Velden detecteren',
|
autodetect_fields: 'Velden detecteren',
|
||||||
analyzing_: 'Analyseren...',
|
analyzing_: 'Analyseren...',
|
||||||
|
|||||||
@@ -52,15 +52,22 @@
|
|||||||
@stop-resize="resizeDirection = null"
|
@stop-resize="resizeDirection = null"
|
||||||
@remove="$emit('remove-area', item.area)"
|
@remove="$emit('remove-area', item.area)"
|
||||||
@scroll-to="$emit('scroll-to', $event)"
|
@scroll-to="$emit('scroll-to', $event)"
|
||||||
|
@add-custom-field="$emit('add-custom-field', $event)"
|
||||||
@contextmenu="openAreaContextMenu($event, item.area, item.field)"
|
@contextmenu="openAreaContextMenu($event, item.area, item.field)"
|
||||||
/>
|
/>
|
||||||
<FieldArea
|
<FieldArea
|
||||||
v-if="newArea"
|
v-for="(area, index) in newAreas"
|
||||||
|
:key="index"
|
||||||
:is-draw="true"
|
:is-draw="true"
|
||||||
:page-width="width"
|
:page-width="width"
|
||||||
:page-height="height"
|
:page-height="height"
|
||||||
:field="{ submitter_uuid: selectedSubmitter.uuid, type: drawField?.type || dragFieldPlaceholder?.type || defaultFieldType }"
|
:field="{ submitter_uuid: selectedSubmitter.uuid, type: newAreaFieldType }"
|
||||||
:area="newArea"
|
:area="area"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-if="newAreas.length > 1"
|
||||||
|
class="absolute outline-dashed outline-gray-400 pointer-events-none z-20"
|
||||||
|
:style="newAreasBoxStyle"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-if="selectionRect"
|
v-if="selectionRect"
|
||||||
@@ -93,7 +100,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-show="resizeDirection || isDrag || showMask || (drawField && isMobile) || fieldsDragFieldRef.value || selectionRect"
|
v-show="resizeDirection || isDrag || showMask || (drawField && isMobile) || fieldsDragFieldRef.value || customDragFieldRef?.value || selectionRect"
|
||||||
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"
|
||||||
@@ -103,7 +110,7 @@
|
|||||||
@contextmenu="openContextMenu"
|
@contextmenu="openContextMenu"
|
||||||
@dragover.prevent="onDragover"
|
@dragover.prevent="onDragover"
|
||||||
@dragenter="onDragenter"
|
@dragenter="onDragenter"
|
||||||
@dragleave="newArea = null"
|
@dragleave="newAreas = []"
|
||||||
@drop="onDrop"
|
@drop="onDrop"
|
||||||
@pointerup="onPointerup"
|
@pointerup="onPointerup"
|
||||||
/>
|
/>
|
||||||
@@ -122,7 +129,7 @@ export default {
|
|||||||
ContextMenu,
|
ContextMenu,
|
||||||
SelectionBox
|
SelectionBox
|
||||||
},
|
},
|
||||||
inject: ['fieldTypes', 'defaultDrawFieldType', 'fieldsDragFieldRef', 'assignDropAreaSize', 'selectedAreasRef', 'template', 'isSelectModeRef'],
|
inject: ['fieldTypes', 'defaultDrawFieldType', 'fieldsDragFieldRef', 'customDragFieldRef', 'assignDropAreaSize', 'selectedAreasRef', 'template', 'isSelectModeRef'],
|
||||||
props: {
|
props: {
|
||||||
image: {
|
image: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -191,6 +198,11 @@ export default {
|
|||||||
required: false,
|
required: false,
|
||||||
default: null
|
default: null
|
||||||
},
|
},
|
||||||
|
drawCustomField: {
|
||||||
|
type: Object,
|
||||||
|
required: false,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
editable: {
|
editable: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -216,13 +228,13 @@ export default {
|
|||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['draw', 'drop-field', 'remove-area', 'copy-field', 'paste-field', 'scroll-to', 'copy-selected-areas', 'delete-selected-areas', 'align-selected-areas', 'autodetect-fields'],
|
emits: ['draw', 'drop-field', 'remove-area', 'copy-field', 'paste-field', 'scroll-to', 'copy-selected-areas', 'delete-selected-areas', 'align-selected-areas', 'autodetect-fields', 'add-custom-field'],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
areaRefs: [],
|
areaRefs: [],
|
||||||
showMask: false,
|
showMask: false,
|
||||||
resizeDirection: null,
|
resizeDirection: null,
|
||||||
newArea: null,
|
newAreas: [],
|
||||||
contextMenu: null,
|
contextMenu: null,
|
||||||
selectionRect: null,
|
selectionRect: null,
|
||||||
selectionContextMenu: null
|
selectionContextMenu: null
|
||||||
@@ -274,6 +286,14 @@ export default {
|
|||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {})
|
||||||
},
|
},
|
||||||
|
newAreaFieldType () {
|
||||||
|
if (this.drawField?.type) return this.drawField.type
|
||||||
|
if (this.drawCustomField?.type) return this.drawCustomField.type
|
||||||
|
if (this.dragFieldPlaceholder?.type) return this.dragFieldPlaceholder.type
|
||||||
|
if (this.customDragFieldRef?.value?.type) return this.customDragFieldRef.value.type
|
||||||
|
|
||||||
|
return this.defaultFieldType
|
||||||
|
},
|
||||||
defaultFieldType () {
|
defaultFieldType () {
|
||||||
if (this.drawFieldType) {
|
if (this.drawFieldType) {
|
||||||
return this.drawFieldType
|
return this.drawFieldType
|
||||||
@@ -302,6 +322,21 @@ export default {
|
|||||||
height () {
|
height () {
|
||||||
return this.image.metadata.height
|
return this.image.metadata.height
|
||||||
},
|
},
|
||||||
|
newAreasBoxStyle () {
|
||||||
|
if (this.newAreas.length < 2) return {}
|
||||||
|
|
||||||
|
const minX = Math.min(...this.newAreas.map(a => a.x))
|
||||||
|
const minY = Math.min(...this.newAreas.map(a => a.y))
|
||||||
|
const maxX = Math.max(...this.newAreas.map(a => a.x + a.w))
|
||||||
|
const maxY = Math.max(...this.newAreas.map(a => a.y + a.h))
|
||||||
|
|
||||||
|
return {
|
||||||
|
left: minX * 100 + '%',
|
||||||
|
top: minY * 100 + '%',
|
||||||
|
width: (maxX - minX) * 100 + '%',
|
||||||
|
height: (maxY - minY) * 100 + '%'
|
||||||
|
}
|
||||||
|
},
|
||||||
selectionRectStyle () {
|
selectionRectStyle () {
|
||||||
if (!this.selectionRect) return {}
|
if (!this.selectionRect) return {}
|
||||||
|
|
||||||
@@ -331,7 +366,7 @@ export default {
|
|||||||
|
|
||||||
const rect = this.$refs.image.getBoundingClientRect()
|
const rect = this.$refs.image.getBoundingClientRect()
|
||||||
|
|
||||||
this.newArea = null
|
this.newAreas = []
|
||||||
this.showMask = false
|
this.showMask = false
|
||||||
|
|
||||||
this.contextMenu = {
|
this.contextMenu = {
|
||||||
@@ -351,7 +386,7 @@ export default {
|
|||||||
|
|
||||||
const rect = this.$refs.image.getBoundingClientRect()
|
const rect = this.$refs.image.getBoundingClientRect()
|
||||||
|
|
||||||
this.newArea = null
|
this.newAreas = []
|
||||||
this.showMask = false
|
this.showMask = false
|
||||||
|
|
||||||
this.contextMenu = {
|
this.contextMenu = {
|
||||||
@@ -390,7 +425,7 @@ export default {
|
|||||||
},
|
},
|
||||||
closeContextMenu () {
|
closeContextMenu () {
|
||||||
this.contextMenu = null
|
this.contextMenu = null
|
||||||
this.newArea = null
|
this.newAreas = []
|
||||||
this.showMask = false
|
this.showMask = false
|
||||||
},
|
},
|
||||||
handleCopy () {
|
handleCopy () {
|
||||||
@@ -410,7 +445,7 @@ export default {
|
|||||||
this.closeContextMenu()
|
this.closeContextMenu()
|
||||||
},
|
},
|
||||||
handlePaste () {
|
handlePaste () {
|
||||||
this.newArea = null
|
this.newAreas = []
|
||||||
this.showMask = false
|
this.showMask = false
|
||||||
|
|
||||||
this.$emit('paste-field', {
|
this.$emit('paste-field', {
|
||||||
@@ -435,22 +470,66 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onDragenter (e) {
|
onDragenter (e) {
|
||||||
this.newArea = {}
|
const customField = this.customDragFieldRef?.value
|
||||||
|
const customAreas = customField?.areas || []
|
||||||
|
const dropX = (e.offsetX - 6) / this.$refs.mask.clientWidth
|
||||||
|
const dropY = e.offsetY / this.$refs.mask.clientHeight
|
||||||
|
|
||||||
this.assignDropAreaSize(this.newArea, this.dragFieldPlaceholder, {
|
if (customAreas.length > 1) {
|
||||||
maskW: this.$refs.mask.clientWidth,
|
const refArea = customAreas[0]
|
||||||
maskH: this.$refs.mask.clientHeight
|
|
||||||
})
|
|
||||||
|
|
||||||
this.newArea.x = (e.offsetX - 6) / this.$refs.mask.clientWidth
|
this.newAreas = customAreas.map((customArea) => ({
|
||||||
this.newArea.y = e.offsetY / this.$refs.mask.clientHeight - this.newArea.h / 2
|
x: dropX + (customArea.x - refArea.x),
|
||||||
|
y: dropY + (customArea.y - refArea.y) - (customArea.h / 2),
|
||||||
|
w: customArea.w,
|
||||||
|
h: customArea.h
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
const newArea = {}
|
||||||
|
|
||||||
|
if (customAreas.length === 1) {
|
||||||
|
newArea.w = customAreas[0].w
|
||||||
|
newArea.h = customAreas[0].h
|
||||||
|
} else if (customField) {
|
||||||
|
this.assignDropAreaSize(newArea, customField, {
|
||||||
|
maskW: this.$refs.mask.clientWidth,
|
||||||
|
maskH: this.$refs.mask.clientHeight
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.assignDropAreaSize(newArea, this.dragFieldPlaceholder, {
|
||||||
|
maskW: this.$refs.mask.clientWidth,
|
||||||
|
maskH: this.$refs.mask.clientHeight
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
newArea.x = dropX
|
||||||
|
newArea.y = dropY - newArea.h / 2
|
||||||
|
|
||||||
|
this.newAreas = [newArea]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onDragover (e) {
|
onDragover (e) {
|
||||||
this.newArea.x = (e.offsetX - 6) / this.$refs.mask.clientWidth
|
const customField = this.customDragFieldRef?.value
|
||||||
this.newArea.y = e.offsetY / this.$refs.mask.clientHeight - this.newArea.h / 2
|
const customAreas = customField?.areas || []
|
||||||
|
const dropX = (e.offsetX - 6) / this.$refs.mask.clientWidth
|
||||||
|
const dropY = e.offsetY / this.$refs.mask.clientHeight
|
||||||
|
|
||||||
|
if (customAreas.length > 1) {
|
||||||
|
const refArea = customAreas[0]
|
||||||
|
|
||||||
|
this.newAreas.forEach((newArea, index) => {
|
||||||
|
const customArea = customAreas[index]
|
||||||
|
|
||||||
|
newArea.x = dropX + (customArea.x - refArea.x)
|
||||||
|
newArea.y = dropY + (customArea.y - refArea.y) - (customArea.h / 2)
|
||||||
|
})
|
||||||
|
} else if (this.newAreas.length) {
|
||||||
|
this.newAreas[0].x = dropX
|
||||||
|
this.newAreas[0].y = dropY - this.newAreas[0].h / 2
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onDrop (e) {
|
onDrop (e) {
|
||||||
this.newArea = null
|
this.newAreas = []
|
||||||
|
|
||||||
this.$emit('drop-field', {
|
this.$emit('drop-field', {
|
||||||
x: e.offsetX,
|
x: e.offsetX,
|
||||||
@@ -479,7 +558,7 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isMobile && !this.drawField) {
|
if (this.isMobile && !this.drawField && !this.drawCustomField) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,14 +569,14 @@ export default {
|
|||||||
this.showMask = true
|
this.showMask = true
|
||||||
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.newArea = {
|
this.newAreas = [{
|
||||||
initialX: e.offsetX / this.$refs.mask.clientWidth,
|
initialX: e.offsetX / this.$refs.mask.clientWidth,
|
||||||
initialY: e.offsetY / this.$refs.mask.clientHeight,
|
initialY: e.offsetY / this.$refs.mask.clientHeight,
|
||||||
x: e.offsetX / this.$refs.mask.clientWidth,
|
x: e.offsetX / this.$refs.mask.clientWidth,
|
||||||
y: e.offsetY / this.$refs.mask.clientHeight,
|
y: e.offsetY / this.$refs.mask.clientHeight,
|
||||||
w: 0,
|
w: 0,
|
||||||
h: 0
|
h: 0
|
||||||
}
|
}]
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
startSelectionRect (e) {
|
startSelectionRect (e) {
|
||||||
@@ -563,28 +642,30 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.newArea) {
|
const drawArea = this.newAreas[0]
|
||||||
const dx = e.offsetX / this.$refs.mask.clientWidth - this.newArea.initialX
|
|
||||||
const dy = e.offsetY / this.$refs.mask.clientHeight - this.newArea.initialY
|
if (drawArea?.initialX !== undefined) {
|
||||||
|
const dx = e.offsetX / this.$refs.mask.clientWidth - drawArea.initialX
|
||||||
|
const dy = e.offsetY / this.$refs.mask.clientHeight - drawArea.initialY
|
||||||
|
|
||||||
if (dx > 0) {
|
if (dx > 0) {
|
||||||
this.newArea.x = this.newArea.initialX
|
drawArea.x = drawArea.initialX
|
||||||
} else {
|
} else {
|
||||||
this.newArea.x = e.offsetX / this.$refs.mask.clientWidth
|
drawArea.x = e.offsetX / this.$refs.mask.clientWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dy > 0) {
|
if (dy > 0) {
|
||||||
this.newArea.y = this.newArea.initialY
|
drawArea.y = drawArea.initialY
|
||||||
} else {
|
} else {
|
||||||
this.newArea.y = e.offsetY / this.$refs.mask.clientHeight
|
drawArea.y = e.offsetY / this.$refs.mask.clientHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((this.drawField?.type || this.drawFieldType) === 'cells') {
|
if ((this.drawField?.type || this.drawCustomField?.type || this.drawFieldType) === 'cells') {
|
||||||
this.newArea.cell_w = this.newArea.h * (this.$refs.mask.clientHeight / this.$refs.mask.clientWidth)
|
drawArea.cell_w = drawArea.h * (this.$refs.mask.clientHeight / this.$refs.mask.clientWidth)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.newArea.w = Math.abs(dx)
|
drawArea.w = Math.abs(dx)
|
||||||
this.newArea.h = Math.abs(dy)
|
drawArea.h = Math.abs(dy)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onPointerup (e) {
|
onPointerup (e) {
|
||||||
@@ -601,29 +682,33 @@ export default {
|
|||||||
})
|
})
|
||||||
|
|
||||||
this.selectionRect = null
|
this.selectionRect = null
|
||||||
} else if (this.newArea) {
|
} else {
|
||||||
const area = {
|
const drawArea = this.newAreas[0]
|
||||||
x: this.newArea.x,
|
|
||||||
y: this.newArea.y,
|
if (drawArea?.initialX !== undefined) {
|
||||||
w: this.newArea.w,
|
const area = {
|
||||||
h: this.newArea.h,
|
x: drawArea.x,
|
||||||
page: this.number
|
y: drawArea.y,
|
||||||
|
w: drawArea.w,
|
||||||
|
h: drawArea.h,
|
||||||
|
page: this.number
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('cell_w' in drawArea) {
|
||||||
|
area.cell_w = drawArea.cell_w
|
||||||
|
}
|
||||||
|
|
||||||
|
const dx = Math.abs(e.offsetX - this.$refs.mask.clientWidth * drawArea.initialX)
|
||||||
|
const dy = Math.abs(e.offsetY - this.$refs.mask.clientHeight * drawArea.initialY)
|
||||||
|
|
||||||
|
const isTooSmall = dx < 8 && dy < 8
|
||||||
|
|
||||||
|
this.$emit('draw', { area, isTooSmall })
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('cell_w' in this.newArea) {
|
|
||||||
area.cell_w = this.newArea.cell_w
|
|
||||||
}
|
|
||||||
|
|
||||||
const dx = Math.abs(e.offsetX - this.$refs.mask.clientWidth * this.newArea.initialX)
|
|
||||||
const dy = Math.abs(e.offsetY - this.$refs.mask.clientHeight * this.newArea.initialY)
|
|
||||||
|
|
||||||
const isTooSmall = dx < 8 && dy < 8
|
|
||||||
|
|
||||||
this.$emit('draw', { area, isTooSmall })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.showMask = false
|
this.showMask = false
|
||||||
this.newArea = null
|
this.newAreas = []
|
||||||
},
|
},
|
||||||
rectsOverlap (r1, r2) {
|
rectsOverlap (r1, r2) {
|
||||||
return !(
|
return !(
|
||||||
|
|||||||
@@ -231,7 +231,10 @@
|
|||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
<li class="mt-1">
|
<li
|
||||||
|
v-if="withCondition"
|
||||||
|
class="mt-1"
|
||||||
|
>
|
||||||
<label
|
<label
|
||||||
class="label-text cursor-pointer text-center w-full flex items-center"
|
class="label-text cursor-pointer text-center w-full flex items-center"
|
||||||
@click="$emit('click-condition')"
|
@click="$emit('click-condition')"
|
||||||
@@ -244,12 +247,29 @@
|
|||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
|
<hr
|
||||||
|
v-if="withCustomFields"
|
||||||
|
class="pb-0.5 mt-0.5"
|
||||||
|
>
|
||||||
|
<li v-if="withCustomFields">
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="text-sm py-1 px-2"
|
||||||
|
@click.prevent="$emit('add-custom-field', field)"
|
||||||
|
>
|
||||||
|
<IconForms
|
||||||
|
:width="20"
|
||||||
|
:stroke-width="1.6"
|
||||||
|
/>
|
||||||
|
{{ t('save_as_custom_field') }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { IconMathFunction, IconSettings, IconCircleCheck, IconInfoCircle, IconBrandStripe, IconInnerShadowTop, IconRouteAltLeft } from '@tabler/icons-vue'
|
import { IconMathFunction, IconSettings, IconCircleCheck, IconInfoCircle, IconBrandStripe, IconInnerShadowTop, IconRouteAltLeft, IconForms } from '@tabler/icons-vue'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
const isConnected = ref(false)
|
const isConnected = ref(false)
|
||||||
@@ -261,6 +281,7 @@ export default {
|
|||||||
IconCircleCheck,
|
IconCircleCheck,
|
||||||
IconRouteAltLeft,
|
IconRouteAltLeft,
|
||||||
IconInfoCircle,
|
IconInfoCircle,
|
||||||
|
IconForms,
|
||||||
IconMathFunction,
|
IconMathFunction,
|
||||||
IconInnerShadowTop,
|
IconInnerShadowTop,
|
||||||
IconBrandStripe
|
IconBrandStripe
|
||||||
@@ -270,9 +291,19 @@ export default {
|
|||||||
field: {
|
field: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true
|
required: true
|
||||||
|
},
|
||||||
|
withCustomFields: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
withCondition: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['click-condition', 'click-description', 'click-formula'],
|
emits: ['click-condition', 'click-description', 'click-formula', 'add-custom-field'],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
isLoading: false
|
isLoading: false
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ class AccountConfig < ApplicationRecord
|
|||||||
WITH_FIELD_LABELS_KEY = 'with_field_labels'
|
WITH_FIELD_LABELS_KEY = 'with_field_labels'
|
||||||
COMBINE_PDF_RESULT_KEY = 'combine_pdf_result_key'
|
COMBINE_PDF_RESULT_KEY = 'combine_pdf_result_key'
|
||||||
DOCUMENT_FILENAME_FORMAT_KEY = 'document_filename_format'
|
DOCUMENT_FILENAME_FORMAT_KEY = 'document_filename_format'
|
||||||
|
TEMPLATE_CUSTOM_FIELDS_KEY = 'template_custom_fields'
|
||||||
POLICY_LINKS_KEY = 'policy_links'
|
POLICY_LINKS_KEY = 'policy_links'
|
||||||
|
|
||||||
DEFAULT_VALUES = {
|
DEFAULT_VALUES = {
|
||||||
|
|||||||
@@ -6,4 +6,4 @@
|
|||||||
<%= button_to nil, user_configs_path, method: :post, params: { user_config: { key: UserConfig::SHOW_APP_TOUR, value: true } }, class: 'hidden', id: 'start_tour_button' %>
|
<%= button_to nil, user_configs_path, method: :post, params: { user_config: { key: UserConfig::SHOW_APP_TOUR, value: true } }, class: 'hidden', id: 'start_tour_button' %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<template-builder class="grid" data-template="<%= @template_data %>" data-with-sign-yourself-button="<%= !@template.archived_at? %>" data-with-fields-detection="true" data-with-send-button="<%= !@template.archived_at? && can?(:create, @template.submissions.new(account: current_account)) %>" data-locale="<%= I18n.locale %>" data-show-tour-start-form="<%= @show_tour_start_form %>"></template-builder>
|
<template-builder class="grid" data-template="<%= @template_data %>" data-custom-fields="<%= (current_account.account_configs.find_or_initialize_by(key: AccountConfig::TEMPLATE_CUSTOM_FIELDS_KEY).value || []).to_json %>" data-with-sign-yourself-button="<%= !@template.archived_at? %>" data-with-fields-detection="true" data-with-send-button="<%= !@template.archived_at? && can?(:create, @template.submissions.new(account: current_account)) %>" data-locale="<%= I18n.locale %>" data-show-tour-start-form="<%= @show_tour_start_form %>"></template-builder>
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ Rails.application.routes.draw do
|
|||||||
resources :verify_pdf_signature, only: %i[create]
|
resources :verify_pdf_signature, only: %i[create]
|
||||||
resource :mfa_setup, only: %i[show new edit create destroy], controller: 'mfa_setup'
|
resource :mfa_setup, only: %i[show new edit create destroy], controller: 'mfa_setup'
|
||||||
resources :account_configs, only: %i[create destroy]
|
resources :account_configs, only: %i[create destroy]
|
||||||
|
resources :account_custom_fields, only: %i[create]
|
||||||
resources :user_configs, only: %i[create]
|
resources :user_configs, only: %i[create]
|
||||||
resources :encrypted_user_configs, only: %i[destroy]
|
resources :encrypted_user_configs, only: %i[destroy]
|
||||||
resources :timestamp_server, only: %i[create]
|
resources :timestamp_server, only: %i[create]
|
||||||
|
|||||||
Reference in New Issue
Block a user