From 0023ddebcf8a7a24c1529abef430b92d3217d323 Mon Sep 17 00:00:00 2001 From: Afiq Date: Wed, 6 Aug 2025 13:13:16 +0800 Subject: [PATCH] Enhance Iframe Integration in Form Builder - Added new iframe parameters in FormBuilderFieldSettingsModal, allowing users to configure debug mode, hide completion messages, apply themes, and set custom URL parameters for button components linked to processes. - Updated ComponentPreview.vue to generate dynamic workflow URLs with iframe parameters based on user settings, improving the flexibility of iframe integration. - Implemented a URL preview feature in FormBuilderFieldSettingsModal to display the generated iframe URL based on the current configuration, enhancing user experience and usability. - Enhanced form builder interface to include new settings for iframe integration, ensuring a more comprehensive configuration for button actions. --- components/ComponentPreview.vue | 33 ++++++- components/FormBuilderFieldSettingsModal.vue | 98 +++++++++++++++++++- pages/form-builder/index.vue | 63 +++++++++++++ 3 files changed, 190 insertions(+), 4 deletions(-) diff --git a/components/ComponentPreview.vue b/components/ComponentPreview.vue index ca0b492..d9d04d7 100644 --- a/components/ComponentPreview.vue +++ b/components/ComponentPreview.vue @@ -1265,15 +1265,42 @@ const saveNestedComponentSettings = (updatedComponent) => { const getButtonLink = () => { if (!props.component || props.component.type !== 'button') return null; - const { linkType, linkUrl, linkProcessId, linkTarget } = props.component.props; + const { linkType, linkUrl, linkProcessId, linkTarget, iframeDebug, iframeHideComplete, iframeTheme, iframeCustomParams } = props.component.props; if (linkType === 'url' && linkUrl) { return linkUrl; } if (linkType === 'process' && linkProcessId) { - // Generate the process workflow URL - return `${window.location.origin}/workflow/${linkProcessId}`; + // Generate the process workflow URL with iframe parameters + const baseUrl = `${window.location.origin}/workflow/${linkProcessId}`; + const params = new URLSearchParams(); + + // Add debug parameter (false = iframe mode, true = debug mode) + if (iframeDebug !== undefined) { + params.append('debug', iframeDebug ? 'true' : 'false'); + } + + // Add hideComplete parameter + if (iframeHideComplete) { + params.append('hideComplete', 'true'); + } + + // Add theme parameter + if (iframeTheme) { + params.append('theme', iframeTheme); + } + + // Add custom parameters + if (iframeCustomParams) { + const customParams = new URLSearchParams(iframeCustomParams); + customParams.forEach((value, key) => { + params.append(key, value); + }); + } + + const queryString = params.toString(); + return queryString ? `${baseUrl}?${queryString}` : baseUrl; } return null; diff --git a/components/FormBuilderFieldSettingsModal.vue b/components/FormBuilderFieldSettingsModal.vue index 012601b..cd1f8b2 100644 --- a/components/FormBuilderFieldSettingsModal.vue +++ b/components/FormBuilderFieldSettingsModal.vue @@ -637,6 +637,62 @@ help="Choose how the link should open" :classes="{ outer: 'field-wrapper' }" /> + + +
+
Iframe Integration Parameters
+ +
+ + + +
+ +
+ + + +
+ +
+ Generated URL Preview:
+ {{ getIframeUrlPreview() }} +
+
@@ -2007,6 +2063,42 @@ watch(() => props.component, (newComponent) => { } }, { immediate: true }) +// Generate iframe URL preview +const getIframeUrlPreview = () => { + if (!configModel.value.linkProcessId) { + return 'Select a process first...' + } + + const baseUrl = `${window.location.origin}/workflow/${configModel.value.linkProcessId}` + const params = new URLSearchParams() + + // Add debug parameter (false = iframe mode, true = debug mode) + if (configModel.value.iframeDebug !== undefined) { + params.append('debug', configModel.value.iframeDebug ? 'true' : 'false') + } + + // Add hideComplete parameter + if (configModel.value.iframeHideComplete) { + params.append('hideComplete', 'true') + } + + // Add theme parameter + if (configModel.value.iframeTheme) { + params.append('theme', configModel.value.iframeTheme) + } + + // Add custom parameters + if (configModel.value.iframeCustomParams) { + const customParams = new URLSearchParams(configModel.value.iframeCustomParams) + customParams.forEach((value, key) => { + params.append(key, value) + }) + } + + const queryString = params.toString() + return queryString ? `${baseUrl}?${queryString}` : baseUrl +} + // Type changing functionality const compatibilityGroups = { // Text-based inputs (can switch between each other) @@ -2738,7 +2830,11 @@ const getDefaultPropsForType = (type) => { linkType: 'none', // 'none', 'url', 'process' linkUrl: '', linkProcessId: '', - linkTarget: '_self' // '_self', '_blank' + linkTarget: '_self', // '_self', '_blank' + iframeDebug: false, // Show/hide debug UI + iframeHideComplete: false, // Hide completion message + iframeTheme: '', // Custom theme + iframeCustomParams: '' // Additional URL parameters } } diff --git a/pages/form-builder/index.vue b/pages/form-builder/index.vue index acf52cb..f147fa6 100644 --- a/pages/form-builder/index.vue +++ b/pages/form-builder/index.vue @@ -559,6 +559,61 @@ :classes="{ outer: 'mb-0', input: 'text-sm' }" /> + + +
+
+ +
+ +
+ +
+ +
+ + +
+ +
+ + +
+
@@ -2867,6 +2922,10 @@ watch(() => formStore.selectedComponent, (newComponent) => { linkType: newComponent.props.linkType || 'none', linkUrl: newComponent.props.linkUrl || '', linkProcessId: newComponent.props.linkProcessId || '', + iframeDebug: newComponent.props.iframeDebug || false, + iframeHideComplete: newComponent.props.iframeHideComplete || false, + iframeTheme: newComponent.props.iframeTheme || '', + iframeCustomParams: newComponent.props.iframeCustomParams || '', required: newComponent.props.validation?.includes('required') || false }; @@ -2894,6 +2953,10 @@ const showQuickField = (fieldName) => { linkType: ['button'], linkUrl: ['button'], linkProcessId: ['button'], + iframeDebug: ['button'], + iframeHideComplete: ['button'], + iframeTheme: ['button'], + iframeCustomParams: ['button'], width: ['text', 'textarea', 'number', 'email', 'password', 'url', 'tel', 'mask', 'select', 'checkbox', 'radio', 'switch', 'date', 'time', 'datetime-local', 'range', 'color', 'file', 'otp', 'dropzone', 'button', 'heading', 'paragraph', 'info-display'], required: ['text', 'textarea', 'number', 'email', 'password', 'url', 'tel', 'mask', 'select', 'checkbox', 'radio', 'date', 'time', 'datetime-local', 'file', 'otp', 'dropzone'] };