Merge pull request #51 from CareerPlug/CP-12034

CP-12034 - Update Docuseal fields if they have default names
pull/608/head
Bernardo Anderson 1 month ago committed by GitHub
commit 909948f312
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -131,7 +131,7 @@ label.primary-button {
:root { :root {
--tooltip-color: black; --tooltip-color: black;
--employee-color: #FFD687; --employee-color: #fed7aa;
--manager-color: #D6E4FD; --manager-color: #D6E4FD;
} }

@ -162,7 +162,8 @@
ref="touchValueTarget" ref="touchValueTarget"
class="flex h-full w-full field-area" class="flex h-full w-full field-area"
dir="auto" dir="auto"
:class="[isValueInput ? 'bg-opacity-50' : 'bg-opacity-80', field.type === 'heading' ? 'bg-gray-50' : bgColors[submitterIndex % bgColors.length], isDefaultValuePresent || isValueInput || (withFieldPlaceholder && field.areas) ? fontClasses : 'justify-center items-center']" :class="[isValueInput ? 'bg-opacity-50' : 'bg-opacity-80', field.type === 'heading' ? 'bg-gray-50' : bgColors[submitterIndex % bgColors.length], isDefaultValuePresent || isValueInput || (withFieldPlaceholder && field.areas) ? fontClasses : 'justify-center items-center', fieldHighlightClasses]"
:style="fieldHighlightStyles"
@click="focusValueInput" @click="focusValueInput"
> >
<span <span
@ -300,6 +301,7 @@ import ConditionsModal from './conditions_modal'
import DescriptionModal from './description_modal' import DescriptionModal from './description_modal'
import { IconX, IconCheck, IconDotsVertical } from '@tabler/icons-vue' import { IconX, IconCheck, IconDotsVertical } from '@tabler/icons-vue'
import { v4 } from 'uuid' import { v4 } from 'uuid'
import { isDefaultFieldName, getDefaultFieldHighlightClasses, getDefaultFieldHighlightStyles } from './default_field_highlight'
export default { export default {
name: 'FieldArea', name: 'FieldArea',
@ -385,6 +387,15 @@ export default {
fieldNames: FieldType.computed.fieldNames, fieldNames: FieldType.computed.fieldNames,
fieldLabels: FieldType.computed.fieldLabels, fieldLabels: FieldType.computed.fieldLabels,
fieldIcons: FieldType.computed.fieldIcons, fieldIcons: FieldType.computed.fieldIcons,
isDefaultFieldName () {
return isDefaultFieldName(this.field?.name || this.defaultName)
},
fieldHighlightClasses () {
return this.isDefaultFieldName ? getDefaultFieldHighlightClasses() : ''
},
fieldHighlightStyles () {
return this.isDefaultFieldName ? getDefaultFieldHighlightStyles() : {}
},
isDefaultValuePresent () { isDefaultValuePresent () {
if (this.field?.type === 'radio' && this.field?.areas?.length > 1) { if (this.field?.type === 'radio' && this.field?.areas?.length > 1) {
return false return false

@ -350,8 +350,9 @@ import MobileFields from './mobile_fields'
import FieldSubmitter from './field_submitter' import FieldSubmitter from './field_submitter'
import { IconPlus, IconUsersPlus, IconDeviceFloppy, IconChevronDown, IconEye, IconWritingSign, IconInnerShadowTop, IconInfoCircle, IconAdjustments } from '@tabler/icons-vue' import { IconPlus, IconUsersPlus, IconDeviceFloppy, IconChevronDown, IconEye, IconWritingSign, IconInnerShadowTop, IconInfoCircle, IconAdjustments } from '@tabler/icons-vue'
import { v4 } from 'uuid' import { v4 } from 'uuid'
import { ref, computed, toRaw } from 'vue' import { ref, computed, toRaw, watch } from 'vue'
import * as i18n from './i18n' import * as i18n from './i18n'
import { countDefaultFieldNames } from './default_field_highlight'
export default { export default {
name: 'TemplateBuilder', name: 'TemplateBuilder',
components: { components: {
@ -780,6 +781,15 @@ export default {
this.pendingFieldAttachmentUuids.push(item.attachment_uuid) this.pendingFieldAttachmentUuids.push(item.attachment_uuid)
} }
}) })
watch(() => this.template.fields, (fields) => {
const hasDefaultFields = countDefaultFieldNames(fields) > 0
window.parent.postMessage({
type: 'DOCUSEAL_BUILDER_HAVE_DEFAULT_FIELDS',
value: hasDefaultFields
}, '*')
}, { deep: true, immediate: true })
}, },
unmounted () { unmounted () {
document.removeEventListener('keyup', this.onKeyUp) document.removeEventListener('keyup', this.onKeyUp)

@ -0,0 +1,106 @@
/**
* Default Field Name Highlighting
*
* This module provides utilities for detecting and highlighting fields with default names.
* Default names follow the pattern "[Field Type] Field [Number]" (e.g., "Text Field 1", "Signature Field 2")
* or "[Field Type] [Number]" for headings (e.g., "Heading 1", "Heading 2")
*/
/**
* Regular expression to match default field names
* Matches patterns like:
* - "Text Field 1", "Text Field 2", etc.
* - "Signature Field 1", "Signature Field 2", etc.
* - "Heading 1", "Heading 2", etc.
* - "Initials Field 1", "Initials Field 2", etc.
* - "Date Field 1", "Date Field 2", etc.
* - "Number Field 1", "Number Field 2", etc.
* - "Image Field 1", "Image Field 2", etc.
* - "File Field 1", "File Field 2", etc.
* - "Select Field 1", "Select Field 2", etc.
* - "Checkbox Field 1", "Checkbox Field 2", etc.
* - "Multiple Field 1", "Multiple Field 2", etc.
* - "Radio Field 1", "Radio Field 2", etc.
* - "Cells Field 1", "Cells Field 2", etc.
* - "Stamp Field 1", "Stamp Field 2", etc.
* - "Payment Field 1", "Payment Field 2", etc.
* - "Phone Field 1", "Phone Field 2", etc.
* - "Verify ID Field 1", "Verify ID Field 2", etc.
*/
export const DEFAULT_FIELD_NAME_REGEX = /^(Text|Signature|Initials|Date|Number|Image|File|Select|Checkbox|Multiple|Radio|Cells|Stamp|Payment|Phone|Verify ID).*?\s+\d+$|^Heading\s+\d+$/i
/**
* Check if a field name is a default name
* @param {string} fieldName - The field name to check
* @returns {boolean} True if the field name matches the default pattern
*/
export function isDefaultFieldName (fieldName) {
if (!fieldName || typeof fieldName !== 'string' || fieldName.trim() === '') {
return true
}
const isDefault = DEFAULT_FIELD_NAME_REGEX.test(fieldName)
return isDefault
}
/**
* Get the CSS classes for highlighting a default-named field
* @returns {string} CSS classes for indigo highlighting
*/
export function getDefaultFieldHighlightClasses () {
return '!border-yellow-500 !bg-yellow-200'
}
/**
* Get the inline styles for highlighting a default-named field
* @returns {Object} Inline styles for indigo highlighting
*/
export function getDefaultFieldHighlightStyles () {
return {
borderWidth: '3px',
borderStyle: 'solid'
}
}
/**
* Get the tooltip message for default-named fields
* @returns {string} Tooltip message explaining why the field is highlighted
*/
export function getDefaultFieldTooltipMessage () {
return 'This field has a default name. Please rename it to something more descriptive for a better form filling experience.'
}
/**
* Get the warning message for templates with default-named fields
* @param {number} count - Number of fields with default names
* @returns {string} Warning message
*/
export function getDefaultFieldWarningMessage (count) {
if (count === 1) {
return 'You have 1 field with a default name. Please rename it to something more descriptive for a better form filling experience.'
}
return `You have ${count} fields with default names. Please rename them to something more descriptive for a better form filling experience.`
}
/**
* Count fields with default names
* @param {Array} fields - Array of field objects
* @returns {number} Count of fields with default names
*/
export function countDefaultFieldNames (fields) {
if (!Array.isArray(fields)) {
return 0
}
return fields.filter(field => isDefaultFieldName(field.name)).length
}
/**
* Get all fields with default names
* @param {Array} fields - Array of field objects
* @returns {Array} Array of fields with default names
*/
export function getDefaultFieldNames (fields) {
if (!Array.isArray(fields)) {
return []
}
return fields.filter(field => isDefaultFieldName(field.name))
}

@ -4,7 +4,8 @@
> >
<div <div
class="border border-base-300 rounded relative group fields-list-item" class="border border-base-300 rounded relative group fields-list-item"
:style="{ backgroundColor: backgroundColor }" :class="fieldHighlightClasses"
:style="{ backgroundColor: backgroundColor, ...fieldHighlightStyles }"
> >
<div class="flex items-center justify-between relative group/contenteditable-container"> <div class="flex items-center justify-between relative group/contenteditable-container">
<div <div
@ -277,6 +278,7 @@ import ConditionsModal from './conditions_modal'
import DescriptionModal from './description_modal' import DescriptionModal from './description_modal'
import { IconRouteAltLeft, IconMathFunction, IconNewSection, IconTrashX, IconSettings } from '@tabler/icons-vue' import { IconRouteAltLeft, IconMathFunction, IconNewSection, IconTrashX, IconSettings } from '@tabler/icons-vue'
import { v4 } from 'uuid' import { v4 } from 'uuid'
import { isDefaultFieldName, getDefaultFieldHighlightClasses, getDefaultFieldHighlightStyles } from './default_field_highlight'
export default { export default {
name: 'TemplateField', name: 'TemplateField',
@ -335,6 +337,15 @@ export default {
dropdownBgColor () { dropdownBgColor () {
return ['', null, 'transparent'].includes(this.backgroundColor) ? 'white' : this.backgroundColor return ['', null, 'transparent'].includes(this.backgroundColor) ? 'white' : this.backgroundColor
}, },
isDefaultFieldName () {
return isDefaultFieldName(this.field.name || this.defaultName)
},
fieldHighlightClasses () {
return this.isDefaultFieldName ? getDefaultFieldHighlightClasses() : ''
},
fieldHighlightStyles () {
return this.isDefaultFieldName ? getDefaultFieldHighlightStyles() : {}
},
schemaAttachmentsIndexes () { schemaAttachmentsIndexes () {
return (this.template.schema || []).reduce((acc, item, index) => { return (this.template.schema || []).reduce((acc, item, index) => {
acc[item.attachment_uuid] = index acc[item.attachment_uuid] = index

Loading…
Cancel
Save