diff --git a/app/javascript/application.scss b/app/javascript/application.scss index 4c705821..f830fe31 100644 --- a/app/javascript/application.scss +++ b/app/javascript/application.scss @@ -131,7 +131,7 @@ label.primary-button { :root { --tooltip-color: black; - --employee-color: #FFD687; + --employee-color: #fed7aa; --manager-color: #D6E4FD; } diff --git a/app/javascript/template_builder/area.vue b/app/javascript/template_builder/area.vue index 8d53b67a..32667158 100644 --- a/app/javascript/template_builder/area.vue +++ b/app/javascript/template_builder/area.vue @@ -162,7 +162,8 @@ ref="touchValueTarget" class="flex h-full w-full field-area" 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" > 1) { return false diff --git a/app/javascript/template_builder/builder.vue b/app/javascript/template_builder/builder.vue index be439d14..e8024ddc 100644 --- a/app/javascript/template_builder/builder.vue +++ b/app/javascript/template_builder/builder.vue @@ -350,8 +350,9 @@ import MobileFields from './mobile_fields' import FieldSubmitter from './field_submitter' import { IconPlus, IconUsersPlus, IconDeviceFloppy, IconChevronDown, IconEye, IconWritingSign, IconInnerShadowTop, IconInfoCircle, IconAdjustments } from '@tabler/icons-vue' import { v4 } from 'uuid' -import { ref, computed, toRaw } from 'vue' +import { ref, computed, toRaw, watch } from 'vue' import * as i18n from './i18n' +import { countDefaultFieldNames } from './default_field_highlight' export default { name: 'TemplateBuilder', components: { @@ -780,6 +781,15 @@ export default { 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 () { document.removeEventListener('keyup', this.onKeyUp) diff --git a/app/javascript/template_builder/default_field_highlight.js b/app/javascript/template_builder/default_field_highlight.js new file mode 100644 index 00000000..0cf270bc --- /dev/null +++ b/app/javascript/template_builder/default_field_highlight.js @@ -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)) +} diff --git a/app/javascript/template_builder/field.vue b/app/javascript/template_builder/field.vue index 8f71f418..4ac1ccac 100644 --- a/app/javascript/template_builder/field.vue +++ b/app/javascript/template_builder/field.vue @@ -4,7 +4,8 @@ >
{ acc[item.attachment_uuid] = index