opnform-host-nginx/client/components/open/forms/OpenForm.vue

734 lines
22 KiB
Vue
Raw Normal View History

2023-12-09 15:47:03 +01:00
<template>
<div v-if="isAutoSubmit">
<p class="text-center p-4">
2023-12-11 11:56:21 +01:00
<Loader class="h-6 w-6 text-nt-blue mx-auto" />
2023-12-09 15:47:03 +01:00
</p>
</div>
<form
v-else-if="dataForm"
2024-08-08 12:00:36 +02:00
:style="computedStyle"
@submit.prevent=""
>
<FormTimer
ref="form-timer"
:form="form"
/>
<template v-if="form.show_progress_bar">
<div
v-if="isIframe"
class="mb-4 p-2"
>
<div class="w-full h-2 bg-gray-200 dark:bg-gray-600 relative border rounded-full overflow-hidden">
<div
class="h-full transition-all duration-300 rounded-r-full"
:class="{ 'w-0': formProgress === 0 }"
:style="{ width: formProgress + '%', background: form.color }"
/>
</div>
</div>
<div
v-else
class="fixed top-0 left-0 right-0 z-50"
>
<div class="w-full h-[0.2rem] bg-gray-200 dark:bg-gray-600 relative overflow-hidden">
<div
class="h-full transition-all duration-300"
:class="{ 'w-0': formProgress === 0 }"
:style="{ width: formProgress + '%', background: form.color }"
/>
</div>
</div>
</template>
<transition
name="fade"
mode="out-in"
>
<div
:key="formPageIndex"
class="form-group flex flex-wrap w-full"
>
<draggable
:list="currentFields"
group="form-elements"
item-key="id"
2024-05-14 17:17:28 +02:00
class="grid grid-cols-12 relative transition-all w-full"
:class="{'rounded-md bg-blue-50 dark:bg-gray-800':draggingNewBlock}"
ghost-class="ghost-item"
filter=".not-draggable"
:animation="200"
Decouple title from title block (#696) * Decouple title from title block * fix lint * remove dry run for FormTitleMigration * Skip form title migration for forms with hidden titles * Refactor AI Form Generation with Dedicated Prompt Services - Extract AI form generation logic from GenerateTemplate command into dedicated prompt service classes - Update GenerateAiForm job to use new prompt generation services - Improve GptCompleter with more robust error handling and token tracking - Add error field to AiFormCompletion model for better error logging - Simplify command signature from 'ai:make-form-template' to 'form:generate' * Consolidate Template Metadata Generation with Unified Prompt Service - Create GenerateTemplateMetadataPrompt to centralize template metadata generation - Update GenerateTemplate command to use new consolidated metadata generation approach - Enhance GptCompleter to support strict JSON schema validation - Increase form prompt max length to support more complex form descriptions - Refactor form generation to simplify metadata extraction and processing * Implement Form Mode Strategy for Flexible Form Rendering - Introduce FormModeStrategy to centralize form rendering logic - Add support for different form modes: LIVE, PREVIEW, TEST, EDIT, PREFILL - Refactor components to use mode-based rendering strategy - Remove legacy boolean props like adminPreview and creating - Enhance form component flexibility and reusability * Refine Form Mode Strategy Display Behavior - Update FormModeStrategy to hide hidden fields in PREVIEW mode - Add FormMode getter in UrlFormPrefill component for mode-specific rendering - Clarify mode-specific validation and display logic in form strategies * Enhance Form Template Generation with Advanced Field Options - Update GenerateTemplate command to use front_url for template URL output - Expand GenerateFormPrompt with comprehensive field configuration options - Add support for advanced field types: date with time, toggle switches, radio/checkbox selections - Introduce field width configuration and HTML formatting for text elements - Re-enable select, multi-select, and matrix field type definitions with enhanced configurations * Remove Deprecated Template Metadata Generation Services - Delete multiple AI prompt services related to template metadata generation - Simplify GenerateTemplate command to use default values instead of complex metadata generation - Remove GenerateTemplateMetadataPrompt and related classes like GenerateTemplateDescriptionPrompt, GenerateTemplateImageKeywordsPrompt, etc. - Update form template generation to use basic fallback metadata generation approach * Restore GenerateTemplateMetadataPrompt for Comprehensive Template Generation - Reintroduce GenerateTemplateMetadataPrompt to replace default metadata generation - Update GenerateTemplate command to use consolidated metadata generation approach - Extract detailed metadata components including title, description, industries, and image search query - Improve template generation with more dynamic and AI-generated metadata * Refactor Template Preview Section Layout - Remove unnecessary nested div in template preview section - Simplify HTML structure for the template preview component - Maintain existing styling and functionality while improving code readability * Refactor Constructor and Code Formatting in AI Form Generation and Prompt Classes - Updated the constructor in GenerateAiForm.php to use a block structure for improved readability and consistency. - Added a blank line in the Prompt.php file to enhance code formatting and maintain consistency with PHP coding standards. - Modified the migration file to use a more concise class declaration syntax, improving clarity. These changes aim to enhance code readability and maintainability across the affected files. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2025-03-21 16:59:18 +01:00
:disabled="!formModeStrategy.admin.allowDragging"
@change="handleDragDropped"
2023-12-09 15:47:03 +01:00
>
<template #item="{element}">
<open-form-field
:field="element"
:show-hidden="showHidden"
:form="form"
:data-form="dataForm"
:data-form-value="dataFormValue"
:theme="theme"
:dark-mode="darkMode"
Decouple title from title block (#696) * Decouple title from title block * fix lint * remove dry run for FormTitleMigration * Skip form title migration for forms with hidden titles * Refactor AI Form Generation with Dedicated Prompt Services - Extract AI form generation logic from GenerateTemplate command into dedicated prompt service classes - Update GenerateAiForm job to use new prompt generation services - Improve GptCompleter with more robust error handling and token tracking - Add error field to AiFormCompletion model for better error logging - Simplify command signature from 'ai:make-form-template' to 'form:generate' * Consolidate Template Metadata Generation with Unified Prompt Service - Create GenerateTemplateMetadataPrompt to centralize template metadata generation - Update GenerateTemplate command to use new consolidated metadata generation approach - Enhance GptCompleter to support strict JSON schema validation - Increase form prompt max length to support more complex form descriptions - Refactor form generation to simplify metadata extraction and processing * Implement Form Mode Strategy for Flexible Form Rendering - Introduce FormModeStrategy to centralize form rendering logic - Add support for different form modes: LIVE, PREVIEW, TEST, EDIT, PREFILL - Refactor components to use mode-based rendering strategy - Remove legacy boolean props like adminPreview and creating - Enhance form component flexibility and reusability * Refine Form Mode Strategy Display Behavior - Update FormModeStrategy to hide hidden fields in PREVIEW mode - Add FormMode getter in UrlFormPrefill component for mode-specific rendering - Clarify mode-specific validation and display logic in form strategies * Enhance Form Template Generation with Advanced Field Options - Update GenerateTemplate command to use front_url for template URL output - Expand GenerateFormPrompt with comprehensive field configuration options - Add support for advanced field types: date with time, toggle switches, radio/checkbox selections - Introduce field width configuration and HTML formatting for text elements - Re-enable select, multi-select, and matrix field type definitions with enhanced configurations * Remove Deprecated Template Metadata Generation Services - Delete multiple AI prompt services related to template metadata generation - Simplify GenerateTemplate command to use default values instead of complex metadata generation - Remove GenerateTemplateMetadataPrompt and related classes like GenerateTemplateDescriptionPrompt, GenerateTemplateImageKeywordsPrompt, etc. - Update form template generation to use basic fallback metadata generation approach * Restore GenerateTemplateMetadataPrompt for Comprehensive Template Generation - Reintroduce GenerateTemplateMetadataPrompt to replace default metadata generation - Update GenerateTemplate command to use consolidated metadata generation approach - Extract detailed metadata components including title, description, industries, and image search query - Improve template generation with more dynamic and AI-generated metadata * Refactor Template Preview Section Layout - Remove unnecessary nested div in template preview section - Simplify HTML structure for the template preview component - Maintain existing styling and functionality while improving code readability * Refactor Constructor and Code Formatting in AI Form Generation and Prompt Classes - Updated the constructor in GenerateAiForm.php to use a block structure for improved readability and consistency. - Added a blank line in the Prompt.php file to enhance code formatting and maintain consistency with PHP coding standards. - Modified the migration file to use a more concise class declaration syntax, improving clarity. These changes aim to enhance code readability and maintainability across the affected files. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2025-03-21 16:59:18 +01:00
:mode="mode"
2023-12-09 15:47:03 +01:00
/>
</template>
</draggable>
</div>
</transition>
<!-- Captcha -->
Add reCAPTCHA support and update captcha provider handling (#647) * Add reCAPTCHA support and update captcha provider handling - Introduced reCAPTCHA as an additional captcha provider alongside hCaptcha. - Updated form request validation to handle different captcha providers based on user selection. - Added a new validation rule for reCAPTCHA. - Modified the forms model to include a 'captcha_provider' field. - Created a migration to add the 'captcha_provider' column to the forms table. - Updated frontend components to support dynamic rendering of captcha based on the selected provider. - Enhanced tests to cover scenarios for both hCaptcha and reCAPTCHA. These changes improve the flexibility of captcha options available to users, enhancing form security and user experience. * fix pint * change comment text * Refactor captcha implementation and integrate new captcha components - Removed the old RecaptchaV2 component and replaced it with a new implementation that supports both reCAPTCHA and hCaptcha through a unified CaptchaInput component. - Updated the OpenForm component to utilize the new CaptchaInput for dynamic captcha rendering based on user-selected provider. - Cleaned up the package.json by removing the deprecated @hcaptcha/vue3-hcaptcha dependency. - Enhanced form initialization to set a default captcha provider. - Improved error handling and cleanup for both reCAPTCHA and hCaptcha scripts. These changes streamline captcha integration, improve maintainability, and enhance user experience by providing a more flexible captcha solution. * Refactor captcha error messages and localization support * Refactor registration process to integrate reCAPTCHA - Replaced hCaptcha implementation with reCAPTCHA in RegisterController and related test cases. - Updated validation rules to utilize g-recaptcha-response instead of h-captcha-response. - Modified RegisterForm component to support reCAPTCHA, including changes to the form data structure and component references. - Enhanced test cases to reflect the new reCAPTCHA integration, ensuring proper validation and response handling. These changes improve security and user experience during the registration process by adopting a more widely used captcha solution. * Fix reCAPTCHA configuration and update RegisterForm styling - Corrected the configuration key for reCAPTCHA in RegisterController from 'services.recaptcha.secret_key' to 'services.re_captcha.secret_key'. - Updated the styling of the Captcha input section in RegisterForm.vue to improve layout consistency. These changes ensure proper reCAPTCHA functionality and enhance the user interface during the registration process. * Fix reCAPTCHA configuration in RegisterTest to use the correct key format - Updated the configuration key for reCAPTCHA in RegisterTest from 'services.recaptcha.secret_key' to 'services.re_captcha.secret_key' to ensure proper functionality during tests. This change aligns the test setup with the recent updates in the reCAPTCHA integration, improving the accuracy of the registration process tests. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2024-12-18 16:35:09 +01:00
<div class="mb-3 px-2 mt-4 mx-auto w-max">
<CaptchaInput
v-if="form.use_captcha && isLastPage && hasCaptchaProviders && isCaptchaProviderAvailable"
Add reCAPTCHA support and update captcha provider handling (#647) * Add reCAPTCHA support and update captcha provider handling - Introduced reCAPTCHA as an additional captcha provider alongside hCaptcha. - Updated form request validation to handle different captcha providers based on user selection. - Added a new validation rule for reCAPTCHA. - Modified the forms model to include a 'captcha_provider' field. - Created a migration to add the 'captcha_provider' column to the forms table. - Updated frontend components to support dynamic rendering of captcha based on the selected provider. - Enhanced tests to cover scenarios for both hCaptcha and reCAPTCHA. These changes improve the flexibility of captcha options available to users, enhancing form security and user experience. * fix pint * change comment text * Refactor captcha implementation and integrate new captcha components - Removed the old RecaptchaV2 component and replaced it with a new implementation that supports both reCAPTCHA and hCaptcha through a unified CaptchaInput component. - Updated the OpenForm component to utilize the new CaptchaInput for dynamic captcha rendering based on user-selected provider. - Cleaned up the package.json by removing the deprecated @hcaptcha/vue3-hcaptcha dependency. - Enhanced form initialization to set a default captcha provider. - Improved error handling and cleanup for both reCAPTCHA and hCaptcha scripts. These changes streamline captcha integration, improve maintainability, and enhance user experience by providing a more flexible captcha solution. * Refactor captcha error messages and localization support * Refactor registration process to integrate reCAPTCHA - Replaced hCaptcha implementation with reCAPTCHA in RegisterController and related test cases. - Updated validation rules to utilize g-recaptcha-response instead of h-captcha-response. - Modified RegisterForm component to support reCAPTCHA, including changes to the form data structure and component references. - Enhanced test cases to reflect the new reCAPTCHA integration, ensuring proper validation and response handling. These changes improve security and user experience during the registration process by adopting a more widely used captcha solution. * Fix reCAPTCHA configuration and update RegisterForm styling - Corrected the configuration key for reCAPTCHA in RegisterController from 'services.recaptcha.secret_key' to 'services.re_captcha.secret_key'. - Updated the styling of the Captcha input section in RegisterForm.vue to improve layout consistency. These changes ensure proper reCAPTCHA functionality and enhance the user interface during the registration process. * Fix reCAPTCHA configuration in RegisterTest to use the correct key format - Updated the configuration key for reCAPTCHA in RegisterTest from 'services.recaptcha.secret_key' to 'services.re_captcha.secret_key' to ensure proper functionality during tests. This change aligns the test setup with the recent updates in the reCAPTCHA integration, improving the accuracy of the registration process tests. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2024-12-18 16:35:09 +01:00
ref="captcha"
:provider="form.captcha_provider"
:form="dataForm"
:language="form.language"
:dark-mode="darkMode"
/>
</div>
2023-12-09 15:47:03 +01:00
<!-- Submit, Next and previous buttons -->
<div class="flex flex-wrap justify-center w-full">
<open-form-button
v-if="formPageIndex>0 && previousFieldsPageBreak && !loading"
native-type="button"
:color="form.color"
:theme="theme"
class="mt-2 px-8 mx-1"
@click="previousPage"
2023-12-09 15:47:03 +01:00
>
{{ previousFieldsPageBreak.previous_btn_text }}
</open-form-button>
<slot
v-if="isLastPage"
name="submit-btn"
:submit-form="submitForm"
/>
<open-form-button
v-else-if="currentFieldsPageBreak"
native-type="button"
:color="form.color"
:theme="theme"
class="mt-2 px-8 mx-1"
:loading="dataForm.busy"
@click.stop="nextPage"
2023-12-09 15:47:03 +01:00
>
{{ currentFieldsPageBreak.next_btn_text }}
</open-form-button>
<div v-if="!currentFieldsPageBreak && !isLastPage">
{{ $t('forms.wrong_form_structure') }}
2023-12-09 15:47:03 +01:00
</div>
</div>
</form>
</template>
<script>
import draggable from 'vuedraggable'
import OpenFormButton from './OpenFormButton.vue'
Add reCAPTCHA support and update captcha provider handling (#647) * Add reCAPTCHA support and update captcha provider handling - Introduced reCAPTCHA as an additional captcha provider alongside hCaptcha. - Updated form request validation to handle different captcha providers based on user selection. - Added a new validation rule for reCAPTCHA. - Modified the forms model to include a 'captcha_provider' field. - Created a migration to add the 'captcha_provider' column to the forms table. - Updated frontend components to support dynamic rendering of captcha based on the selected provider. - Enhanced tests to cover scenarios for both hCaptcha and reCAPTCHA. These changes improve the flexibility of captcha options available to users, enhancing form security and user experience. * fix pint * change comment text * Refactor captcha implementation and integrate new captcha components - Removed the old RecaptchaV2 component and replaced it with a new implementation that supports both reCAPTCHA and hCaptcha through a unified CaptchaInput component. - Updated the OpenForm component to utilize the new CaptchaInput for dynamic captcha rendering based on user-selected provider. - Cleaned up the package.json by removing the deprecated @hcaptcha/vue3-hcaptcha dependency. - Enhanced form initialization to set a default captcha provider. - Improved error handling and cleanup for both reCAPTCHA and hCaptcha scripts. These changes streamline captcha integration, improve maintainability, and enhance user experience by providing a more flexible captcha solution. * Refactor captcha error messages and localization support * Refactor registration process to integrate reCAPTCHA - Replaced hCaptcha implementation with reCAPTCHA in RegisterController and related test cases. - Updated validation rules to utilize g-recaptcha-response instead of h-captcha-response. - Modified RegisterForm component to support reCAPTCHA, including changes to the form data structure and component references. - Enhanced test cases to reflect the new reCAPTCHA integration, ensuring proper validation and response handling. These changes improve security and user experience during the registration process by adopting a more widely used captcha solution. * Fix reCAPTCHA configuration and update RegisterForm styling - Corrected the configuration key for reCAPTCHA in RegisterController from 'services.recaptcha.secret_key' to 'services.re_captcha.secret_key'. - Updated the styling of the Captcha input section in RegisterForm.vue to improve layout consistency. These changes ensure proper reCAPTCHA functionality and enhance the user interface during the registration process. * Fix reCAPTCHA configuration in RegisterTest to use the correct key format - Updated the configuration key for reCAPTCHA in RegisterTest from 'services.recaptcha.secret_key' to 'services.re_captcha.secret_key' to ensure proper functionality during tests. This change aligns the test setup with the recent updates in the reCAPTCHA integration, improving the accuracy of the registration process tests. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2024-12-18 16:35:09 +01:00
import CaptchaInput from '~/components/forms/components/CaptchaInput.vue'
import OpenFormField from './OpenFormField.vue'
2024-01-16 15:00:22 +01:00
import {pendingSubmission} from "~/composables/forms/pendingSubmission.js"
import FormLogicPropertyResolver from "~/lib/forms/FormLogicPropertyResolver.js"
import CachedDefaultTheme from "~/lib/forms/themes/CachedDefaultTheme.js"
import FormTimer from './FormTimer.vue'
import { storeToRefs } from 'pinia'
Decouple title from title block (#696) * Decouple title from title block * fix lint * remove dry run for FormTitleMigration * Skip form title migration for forms with hidden titles * Refactor AI Form Generation with Dedicated Prompt Services - Extract AI form generation logic from GenerateTemplate command into dedicated prompt service classes - Update GenerateAiForm job to use new prompt generation services - Improve GptCompleter with more robust error handling and token tracking - Add error field to AiFormCompletion model for better error logging - Simplify command signature from 'ai:make-form-template' to 'form:generate' * Consolidate Template Metadata Generation with Unified Prompt Service - Create GenerateTemplateMetadataPrompt to centralize template metadata generation - Update GenerateTemplate command to use new consolidated metadata generation approach - Enhance GptCompleter to support strict JSON schema validation - Increase form prompt max length to support more complex form descriptions - Refactor form generation to simplify metadata extraction and processing * Implement Form Mode Strategy for Flexible Form Rendering - Introduce FormModeStrategy to centralize form rendering logic - Add support for different form modes: LIVE, PREVIEW, TEST, EDIT, PREFILL - Refactor components to use mode-based rendering strategy - Remove legacy boolean props like adminPreview and creating - Enhance form component flexibility and reusability * Refine Form Mode Strategy Display Behavior - Update FormModeStrategy to hide hidden fields in PREVIEW mode - Add FormMode getter in UrlFormPrefill component for mode-specific rendering - Clarify mode-specific validation and display logic in form strategies * Enhance Form Template Generation with Advanced Field Options - Update GenerateTemplate command to use front_url for template URL output - Expand GenerateFormPrompt with comprehensive field configuration options - Add support for advanced field types: date with time, toggle switches, radio/checkbox selections - Introduce field width configuration and HTML formatting for text elements - Re-enable select, multi-select, and matrix field type definitions with enhanced configurations * Remove Deprecated Template Metadata Generation Services - Delete multiple AI prompt services related to template metadata generation - Simplify GenerateTemplate command to use default values instead of complex metadata generation - Remove GenerateTemplateMetadataPrompt and related classes like GenerateTemplateDescriptionPrompt, GenerateTemplateImageKeywordsPrompt, etc. - Update form template generation to use basic fallback metadata generation approach * Restore GenerateTemplateMetadataPrompt for Comprehensive Template Generation - Reintroduce GenerateTemplateMetadataPrompt to replace default metadata generation - Update GenerateTemplate command to use consolidated metadata generation approach - Extract detailed metadata components including title, description, industries, and image search query - Improve template generation with more dynamic and AI-generated metadata * Refactor Template Preview Section Layout - Remove unnecessary nested div in template preview section - Simplify HTML structure for the template preview component - Maintain existing styling and functionality while improving code readability * Refactor Constructor and Code Formatting in AI Form Generation and Prompt Classes - Updated the constructor in GenerateAiForm.php to use a block structure for improved readability and consistency. - Added a blank line in the Prompt.php file to enhance code formatting and maintain consistency with PHP coding standards. - Modified the migration file to use a more concise class declaration syntax, improving clarity. These changes aim to enhance code readability and maintainability across the affected files. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2025-03-21 16:59:18 +01:00
import { FormMode, createFormModeStrategy } from "~/lib/forms/FormModeStrategy.js"
2023-12-09 15:47:03 +01:00
export default {
name: 'OpenForm',
Add reCAPTCHA support and update captcha provider handling (#647) * Add reCAPTCHA support and update captcha provider handling - Introduced reCAPTCHA as an additional captcha provider alongside hCaptcha. - Updated form request validation to handle different captcha providers based on user selection. - Added a new validation rule for reCAPTCHA. - Modified the forms model to include a 'captcha_provider' field. - Created a migration to add the 'captcha_provider' column to the forms table. - Updated frontend components to support dynamic rendering of captcha based on the selected provider. - Enhanced tests to cover scenarios for both hCaptcha and reCAPTCHA. These changes improve the flexibility of captcha options available to users, enhancing form security and user experience. * fix pint * change comment text * Refactor captcha implementation and integrate new captcha components - Removed the old RecaptchaV2 component and replaced it with a new implementation that supports both reCAPTCHA and hCaptcha through a unified CaptchaInput component. - Updated the OpenForm component to utilize the new CaptchaInput for dynamic captcha rendering based on user-selected provider. - Cleaned up the package.json by removing the deprecated @hcaptcha/vue3-hcaptcha dependency. - Enhanced form initialization to set a default captcha provider. - Improved error handling and cleanup for both reCAPTCHA and hCaptcha scripts. These changes streamline captcha integration, improve maintainability, and enhance user experience by providing a more flexible captcha solution. * Refactor captcha error messages and localization support * Refactor registration process to integrate reCAPTCHA - Replaced hCaptcha implementation with reCAPTCHA in RegisterController and related test cases. - Updated validation rules to utilize g-recaptcha-response instead of h-captcha-response. - Modified RegisterForm component to support reCAPTCHA, including changes to the form data structure and component references. - Enhanced test cases to reflect the new reCAPTCHA integration, ensuring proper validation and response handling. These changes improve security and user experience during the registration process by adopting a more widely used captcha solution. * Fix reCAPTCHA configuration and update RegisterForm styling - Corrected the configuration key for reCAPTCHA in RegisterController from 'services.recaptcha.secret_key' to 'services.re_captcha.secret_key'. - Updated the styling of the Captcha input section in RegisterForm.vue to improve layout consistency. These changes ensure proper reCAPTCHA functionality and enhance the user interface during the registration process. * Fix reCAPTCHA configuration in RegisterTest to use the correct key format - Updated the configuration key for reCAPTCHA in RegisterTest from 'services.recaptcha.secret_key' to 'services.re_captcha.secret_key' to ensure proper functionality during tests. This change aligns the test setup with the recent updates in the reCAPTCHA integration, improving the accuracy of the registration process tests. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2024-12-18 16:35:09 +01:00
components: {draggable, OpenFormField, OpenFormButton, CaptchaInput, FormTimer},
2023-12-09 15:47:03 +01:00
props: {
form: {
type: Object,
required: true
},
theme: {
type: Object, default: () => {
const theme = inject("theme", null)
if (theme) {
return theme.value
}
return CachedDefaultTheme.getInstance()
}
},
2023-12-09 15:47:03 +01:00
loading: {
type: Boolean,
required: true
},
fields: {
type: Array,
required: true
},
defaultDataForm: { type: [Object, null] },
Decouple title from title block (#696) * Decouple title from title block * fix lint * remove dry run for FormTitleMigration * Skip form title migration for forms with hidden titles * Refactor AI Form Generation with Dedicated Prompt Services - Extract AI form generation logic from GenerateTemplate command into dedicated prompt service classes - Update GenerateAiForm job to use new prompt generation services - Improve GptCompleter with more robust error handling and token tracking - Add error field to AiFormCompletion model for better error logging - Simplify command signature from 'ai:make-form-template' to 'form:generate' * Consolidate Template Metadata Generation with Unified Prompt Service - Create GenerateTemplateMetadataPrompt to centralize template metadata generation - Update GenerateTemplate command to use new consolidated metadata generation approach - Enhance GptCompleter to support strict JSON schema validation - Increase form prompt max length to support more complex form descriptions - Refactor form generation to simplify metadata extraction and processing * Implement Form Mode Strategy for Flexible Form Rendering - Introduce FormModeStrategy to centralize form rendering logic - Add support for different form modes: LIVE, PREVIEW, TEST, EDIT, PREFILL - Refactor components to use mode-based rendering strategy - Remove legacy boolean props like adminPreview and creating - Enhance form component flexibility and reusability * Refine Form Mode Strategy Display Behavior - Update FormModeStrategy to hide hidden fields in PREVIEW mode - Add FormMode getter in UrlFormPrefill component for mode-specific rendering - Clarify mode-specific validation and display logic in form strategies * Enhance Form Template Generation with Advanced Field Options - Update GenerateTemplate command to use front_url for template URL output - Expand GenerateFormPrompt with comprehensive field configuration options - Add support for advanced field types: date with time, toggle switches, radio/checkbox selections - Introduce field width configuration and HTML formatting for text elements - Re-enable select, multi-select, and matrix field type definitions with enhanced configurations * Remove Deprecated Template Metadata Generation Services - Delete multiple AI prompt services related to template metadata generation - Simplify GenerateTemplate command to use default values instead of complex metadata generation - Remove GenerateTemplateMetadataPrompt and related classes like GenerateTemplateDescriptionPrompt, GenerateTemplateImageKeywordsPrompt, etc. - Update form template generation to use basic fallback metadata generation approach * Restore GenerateTemplateMetadataPrompt for Comprehensive Template Generation - Reintroduce GenerateTemplateMetadataPrompt to replace default metadata generation - Update GenerateTemplate command to use consolidated metadata generation approach - Extract detailed metadata components including title, description, industries, and image search query - Improve template generation with more dynamic and AI-generated metadata * Refactor Template Preview Section Layout - Remove unnecessary nested div in template preview section - Simplify HTML structure for the template preview component - Maintain existing styling and functionality while improving code readability * Refactor Constructor and Code Formatting in AI Form Generation and Prompt Classes - Updated the constructor in GenerateAiForm.php to use a block structure for improved readability and consistency. - Added a blank line in the Prompt.php file to enhance code formatting and maintain consistency with PHP coding standards. - Modified the migration file to use a more concise class declaration syntax, improving clarity. These changes aim to enhance code readability and maintainability across the affected files. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2025-03-21 16:59:18 +01:00
mode: {
type: String,
default: FormMode.LIVE,
validator: (value) => Object.values(FormMode).includes(value)
},
darkMode: {
type: Boolean,
default: false
}
2023-12-09 15:47:03 +01:00
},
emits: ['submit'],
setup(props) {
2023-12-09 15:47:03 +01:00
const recordsStore = useRecordsStore()
const workingFormStore = useWorkingFormStore()
const dataForm = ref(useForm())
const config = useRuntimeConfig()
const hasCaptchaProviders = computed(() => {
return config.public.hCaptchaSiteKey || config.public.recaptchaSiteKey
})
2023-12-09 15:47:03 +01:00
return {
dataForm,
2023-12-09 15:47:03 +01:00
recordsStore,
workingFormStore,
2024-08-08 12:00:36 +02:00
isIframe: useIsIframe(),
draggingNewBlock: computed(() => workingFormStore.draggingNewBlock),
pendingSubmission: pendingSubmission(props.form),
formPageIndex: storeToRefs(workingFormStore).formPageIndex,
// Used for admin previews
selectedFieldIndex: computed(() => workingFormStore.selectedFieldIndex),
showEditFieldSidebar: computed(() => workingFormStore.showEditFieldSidebar),
hasCaptchaProviders
2023-12-09 15:47:03 +01:00
}
},
data() {
2023-12-09 15:47:03 +01:00
return {
isAutoSubmit: false,
isInitialLoad: true,
// Flag to prevent recursion in field group updates
isUpdatingFieldGroups: false,
2023-12-09 15:47:03 +01:00
}
},
computed: {
/**
* Create field groups (or Page) using page breaks if any
*/
fieldGroups() {
2023-12-09 15:47:03 +01:00
if (!this.fields) return []
const groups = []
let currentGroup = []
this.fields.forEach((field) => {
if (field.type === 'nf-page-break' && this.isFieldHidden(field)) return
currentGroup.push(field)
if (field.type === 'nf-page-break') {
groups.push(currentGroup)
currentGroup = []
}
})
groups.push(currentGroup)
return groups
},
Decouple title from title block (#696) * Decouple title from title block * fix lint * remove dry run for FormTitleMigration * Skip form title migration for forms with hidden titles * Refactor AI Form Generation with Dedicated Prompt Services - Extract AI form generation logic from GenerateTemplate command into dedicated prompt service classes - Update GenerateAiForm job to use new prompt generation services - Improve GptCompleter with more robust error handling and token tracking - Add error field to AiFormCompletion model for better error logging - Simplify command signature from 'ai:make-form-template' to 'form:generate' * Consolidate Template Metadata Generation with Unified Prompt Service - Create GenerateTemplateMetadataPrompt to centralize template metadata generation - Update GenerateTemplate command to use new consolidated metadata generation approach - Enhance GptCompleter to support strict JSON schema validation - Increase form prompt max length to support more complex form descriptions - Refactor form generation to simplify metadata extraction and processing * Implement Form Mode Strategy for Flexible Form Rendering - Introduce FormModeStrategy to centralize form rendering logic - Add support for different form modes: LIVE, PREVIEW, TEST, EDIT, PREFILL - Refactor components to use mode-based rendering strategy - Remove legacy boolean props like adminPreview and creating - Enhance form component flexibility and reusability * Refine Form Mode Strategy Display Behavior - Update FormModeStrategy to hide hidden fields in PREVIEW mode - Add FormMode getter in UrlFormPrefill component for mode-specific rendering - Clarify mode-specific validation and display logic in form strategies * Enhance Form Template Generation with Advanced Field Options - Update GenerateTemplate command to use front_url for template URL output - Expand GenerateFormPrompt with comprehensive field configuration options - Add support for advanced field types: date with time, toggle switches, radio/checkbox selections - Introduce field width configuration and HTML formatting for text elements - Re-enable select, multi-select, and matrix field type definitions with enhanced configurations * Remove Deprecated Template Metadata Generation Services - Delete multiple AI prompt services related to template metadata generation - Simplify GenerateTemplate command to use default values instead of complex metadata generation - Remove GenerateTemplateMetadataPrompt and related classes like GenerateTemplateDescriptionPrompt, GenerateTemplateImageKeywordsPrompt, etc. - Update form template generation to use basic fallback metadata generation approach * Restore GenerateTemplateMetadataPrompt for Comprehensive Template Generation - Reintroduce GenerateTemplateMetadataPrompt to replace default metadata generation - Update GenerateTemplate command to use consolidated metadata generation approach - Extract detailed metadata components including title, description, industries, and image search query - Improve template generation with more dynamic and AI-generated metadata * Refactor Template Preview Section Layout - Remove unnecessary nested div in template preview section - Simplify HTML structure for the template preview component - Maintain existing styling and functionality while improving code readability * Refactor Constructor and Code Formatting in AI Form Generation and Prompt Classes - Updated the constructor in GenerateAiForm.php to use a block structure for improved readability and consistency. - Added a blank line in the Prompt.php file to enhance code formatting and maintain consistency with PHP coding standards. - Modified the migration file to use a more concise class declaration syntax, improving clarity. These changes aim to enhance code readability and maintainability across the affected files. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2025-03-21 16:59:18 +01:00
/**
* Gets the comprehensive strategy based on the form mode
*/
formModeStrategy() {
return createFormModeStrategy(this.mode)
},
/**
* Determines if hidden fields should be shown based on the mode
*/
showHidden() {
return this.formModeStrategy.display.showHiddenFields
},
/**
* Determines if the form is in admin preview mode
*/
isAdminPreview() {
return this.formModeStrategy.admin.showAdminControls
},
formProgress() {
const requiredFields = this.fields.filter(field => field.required)
if (requiredFields.length === 0) {
return 100
}
const completedFields = requiredFields.filter(field => ![null, undefined, ''].includes(this.dataFormValue[field.id]))
const progress = (completedFields.length / requiredFields.length) * 100
return Math.round(progress)
},
2023-12-09 15:47:03 +01:00
currentFields: {
get() {
return this.fieldGroups[this.formPageIndex]
2023-12-09 15:47:03 +01:00
},
set(val) {
2023-12-09 15:47:03 +01:00
// On re-order from the form, set the new order
// Add the previous groups and next to val, and set the properties on working form
const newFields = []
this.fieldGroups.forEach((group, index) => {
if (index < this.formPageIndex) {
2023-12-09 15:47:03 +01:00
newFields.push(...group)
} else if (index === this.formPageIndex) {
2023-12-09 15:47:03 +01:00
newFields.push(...val)
} else {
newFields.push(...group)
}
})
// set the properties on working_form store
this.workingFormStore.setProperties(newFields)
}
},
/**
* Returns the page break block for the current group of fields
*/
currentFieldsPageBreak() {
2024-01-17 12:43:52 +01:00
// Last block from current group
2024-02-10 12:20:45 +01:00
if (!this.currentFields?.length) return null
2023-12-09 15:47:03 +01:00
const block = this.currentFields[this.currentFields.length - 1]
if (block && block.type === 'nf-page-break') return block
return null
},
previousFieldsPageBreak() {
if (this.formPageIndex === 0) return null
const previousFields = this.fieldGroups[this.formPageIndex - 1]
2023-12-09 15:47:03 +01:00
const block = previousFields[previousFields.length - 1]
if (block && block.type === 'nf-page-break') return block
return null
},
/**
* Returns true if we're on the last page
* @returns {boolean}xs
*/
isLastPage() {
return this.formPageIndex === (this.fieldGroups.length - 1)
2023-12-09 15:47:03 +01:00
},
isPublicFormPage() {
return this.$route.name === 'forms-slug'
2023-12-09 15:47:03 +01:00
},
dataFormValue() {
2023-12-09 15:47:03 +01:00
// For get values instead of Id for select/multi select options
const data = this.dataForm.data()
const selectionFields = this.fields.filter((field) => {
return ['select', 'multi_select'].includes(field.type)
})
selectionFields.forEach((field) => {
if (data[field.id] !== undefined && data[field.id] !== null && Array.isArray(data[field.id])) {
data[field.id] = data[field.id].map(option_nfid => {
const tmpop = field[field.type].options.find((op) => {
return (op.id === option_nfid)
})
return (tmpop) ? tmpop.name : option_nfid
})
}
})
return data
2024-08-08 12:00:36 +02:00
},
computedStyle() {
return {
'--form-color': this.form.color
2024-08-08 12:00:36 +02:00
}
},
isCaptchaProviderAvailable() {
const config = useRuntimeConfig()
if (this.form.captcha_provider === 'recaptcha') {
return !!config.public.recaptchaSiteKey
} else if (this.form.captcha_provider === 'hcaptcha') {
return !!config.public.hCaptchaSiteKey
}
return false
2023-12-09 15:47:03 +01:00
}
},
watch: {
// Monitor only critical changes that require full reinitialization
'form.database_id': function() {
// Only reinitialize when database changes
this.initForm()
2023-12-09 15:47:03 +01:00
},
'fields.length': function() {
// Only reinitialize when fields are added or removed
this.updateFieldGroupsSafely()
},
// Watch for changes to individual field properties
'fields': {
2023-12-09 15:47:03 +01:00
deep: true,
handler() {
// Skip update if only triggered by internal fieldGroups changes
if (this.isUpdatingFieldGroups) return
// Safely update field groups without causing recursive updates
this.updateFieldGroupsSafely()
2023-12-09 15:47:03 +01:00
}
},
dataFormValue: {
2023-12-09 15:47:03 +01:00
deep: true,
handler() {
if (this.isPublicFormPage && this.form && this.form.auto_save) {
this.pendingSubmission.set(this.dataFormValue)
2023-12-09 15:47:03 +01:00
}
}
},
// These watchers ensure the form shows the correct page for the field being edited in admin preview
selectedFieldIndex: {
handler(newIndex) {
Decouple title from title block (#696) * Decouple title from title block * fix lint * remove dry run for FormTitleMigration * Skip form title migration for forms with hidden titles * Refactor AI Form Generation with Dedicated Prompt Services - Extract AI form generation logic from GenerateTemplate command into dedicated prompt service classes - Update GenerateAiForm job to use new prompt generation services - Improve GptCompleter with more robust error handling and token tracking - Add error field to AiFormCompletion model for better error logging - Simplify command signature from 'ai:make-form-template' to 'form:generate' * Consolidate Template Metadata Generation with Unified Prompt Service - Create GenerateTemplateMetadataPrompt to centralize template metadata generation - Update GenerateTemplate command to use new consolidated metadata generation approach - Enhance GptCompleter to support strict JSON schema validation - Increase form prompt max length to support more complex form descriptions - Refactor form generation to simplify metadata extraction and processing * Implement Form Mode Strategy for Flexible Form Rendering - Introduce FormModeStrategy to centralize form rendering logic - Add support for different form modes: LIVE, PREVIEW, TEST, EDIT, PREFILL - Refactor components to use mode-based rendering strategy - Remove legacy boolean props like adminPreview and creating - Enhance form component flexibility and reusability * Refine Form Mode Strategy Display Behavior - Update FormModeStrategy to hide hidden fields in PREVIEW mode - Add FormMode getter in UrlFormPrefill component for mode-specific rendering - Clarify mode-specific validation and display logic in form strategies * Enhance Form Template Generation with Advanced Field Options - Update GenerateTemplate command to use front_url for template URL output - Expand GenerateFormPrompt with comprehensive field configuration options - Add support for advanced field types: date with time, toggle switches, radio/checkbox selections - Introduce field width configuration and HTML formatting for text elements - Re-enable select, multi-select, and matrix field type definitions with enhanced configurations * Remove Deprecated Template Metadata Generation Services - Delete multiple AI prompt services related to template metadata generation - Simplify GenerateTemplate command to use default values instead of complex metadata generation - Remove GenerateTemplateMetadataPrompt and related classes like GenerateTemplateDescriptionPrompt, GenerateTemplateImageKeywordsPrompt, etc. - Update form template generation to use basic fallback metadata generation approach * Restore GenerateTemplateMetadataPrompt for Comprehensive Template Generation - Reintroduce GenerateTemplateMetadataPrompt to replace default metadata generation - Update GenerateTemplate command to use consolidated metadata generation approach - Extract detailed metadata components including title, description, industries, and image search query - Improve template generation with more dynamic and AI-generated metadata * Refactor Template Preview Section Layout - Remove unnecessary nested div in template preview section - Simplify HTML structure for the template preview component - Maintain existing styling and functionality while improving code readability * Refactor Constructor and Code Formatting in AI Form Generation and Prompt Classes - Updated the constructor in GenerateAiForm.php to use a block structure for improved readability and consistency. - Added a blank line in the Prompt.php file to enhance code formatting and maintain consistency with PHP coding standards. - Modified the migration file to use a more concise class declaration syntax, improving clarity. These changes aim to enhance code readability and maintainability across the affected files. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2025-03-21 16:59:18 +01:00
if (this.isAdminPreview && this.showEditFieldSidebar) {
this.setPageForField(newIndex)
}
}
},
showEditFieldSidebar: {
handler(newValue) {
Decouple title from title block (#696) * Decouple title from title block * fix lint * remove dry run for FormTitleMigration * Skip form title migration for forms with hidden titles * Refactor AI Form Generation with Dedicated Prompt Services - Extract AI form generation logic from GenerateTemplate command into dedicated prompt service classes - Update GenerateAiForm job to use new prompt generation services - Improve GptCompleter with more robust error handling and token tracking - Add error field to AiFormCompletion model for better error logging - Simplify command signature from 'ai:make-form-template' to 'form:generate' * Consolidate Template Metadata Generation with Unified Prompt Service - Create GenerateTemplateMetadataPrompt to centralize template metadata generation - Update GenerateTemplate command to use new consolidated metadata generation approach - Enhance GptCompleter to support strict JSON schema validation - Increase form prompt max length to support more complex form descriptions - Refactor form generation to simplify metadata extraction and processing * Implement Form Mode Strategy for Flexible Form Rendering - Introduce FormModeStrategy to centralize form rendering logic - Add support for different form modes: LIVE, PREVIEW, TEST, EDIT, PREFILL - Refactor components to use mode-based rendering strategy - Remove legacy boolean props like adminPreview and creating - Enhance form component flexibility and reusability * Refine Form Mode Strategy Display Behavior - Update FormModeStrategy to hide hidden fields in PREVIEW mode - Add FormMode getter in UrlFormPrefill component for mode-specific rendering - Clarify mode-specific validation and display logic in form strategies * Enhance Form Template Generation with Advanced Field Options - Update GenerateTemplate command to use front_url for template URL output - Expand GenerateFormPrompt with comprehensive field configuration options - Add support for advanced field types: date with time, toggle switches, radio/checkbox selections - Introduce field width configuration and HTML formatting for text elements - Re-enable select, multi-select, and matrix field type definitions with enhanced configurations * Remove Deprecated Template Metadata Generation Services - Delete multiple AI prompt services related to template metadata generation - Simplify GenerateTemplate command to use default values instead of complex metadata generation - Remove GenerateTemplateMetadataPrompt and related classes like GenerateTemplateDescriptionPrompt, GenerateTemplateImageKeywordsPrompt, etc. - Update form template generation to use basic fallback metadata generation approach * Restore GenerateTemplateMetadataPrompt for Comprehensive Template Generation - Reintroduce GenerateTemplateMetadataPrompt to replace default metadata generation - Update GenerateTemplate command to use consolidated metadata generation approach - Extract detailed metadata components including title, description, industries, and image search query - Improve template generation with more dynamic and AI-generated metadata * Refactor Template Preview Section Layout - Remove unnecessary nested div in template preview section - Simplify HTML structure for the template preview component - Maintain existing styling and functionality while improving code readability * Refactor Constructor and Code Formatting in AI Form Generation and Prompt Classes - Updated the constructor in GenerateAiForm.php to use a block structure for improved readability and consistency. - Added a blank line in the Prompt.php file to enhance code formatting and maintain consistency with PHP coding standards. - Modified the migration file to use a more concise class declaration syntax, improving clarity. These changes aim to enhance code readability and maintainability across the affected files. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2025-03-21 16:59:18 +01:00
if (this.isAdminPreview && newValue) {
this.setPageForField(this.selectedFieldIndex)
}
}
2023-12-09 15:47:03 +01:00
}
},
beforeMount() {
2023-12-09 15:47:03 +01:00
this.initForm()
},
mounted() {
2025-01-28 09:23:11 +01:00
nextTick(() => {
if (this.$refs['form-timer']) {
this.$refs['form-timer'].startTimer()
}
})
if (import.meta.client && window.location.href.includes('auto_submit=true')) {
2023-12-09 15:47:03 +01:00
this.isAutoSubmit = true
this.submitForm()
}
},
methods: {
submitForm() {
if (!this.isAutoSubmit && this.formPageIndex !== this.fieldGroups.length - 1) return
2023-12-09 15:47:03 +01:00
if (this.form.use_captcha && import.meta.client) {
Add reCAPTCHA support and update captcha provider handling (#647) * Add reCAPTCHA support and update captcha provider handling - Introduced reCAPTCHA as an additional captcha provider alongside hCaptcha. - Updated form request validation to handle different captcha providers based on user selection. - Added a new validation rule for reCAPTCHA. - Modified the forms model to include a 'captcha_provider' field. - Created a migration to add the 'captcha_provider' column to the forms table. - Updated frontend components to support dynamic rendering of captcha based on the selected provider. - Enhanced tests to cover scenarios for both hCaptcha and reCAPTCHA. These changes improve the flexibility of captcha options available to users, enhancing form security and user experience. * fix pint * change comment text * Refactor captcha implementation and integrate new captcha components - Removed the old RecaptchaV2 component and replaced it with a new implementation that supports both reCAPTCHA and hCaptcha through a unified CaptchaInput component. - Updated the OpenForm component to utilize the new CaptchaInput for dynamic captcha rendering based on user-selected provider. - Cleaned up the package.json by removing the deprecated @hcaptcha/vue3-hcaptcha dependency. - Enhanced form initialization to set a default captcha provider. - Improved error handling and cleanup for both reCAPTCHA and hCaptcha scripts. These changes streamline captcha integration, improve maintainability, and enhance user experience by providing a more flexible captcha solution. * Refactor captcha error messages and localization support * Refactor registration process to integrate reCAPTCHA - Replaced hCaptcha implementation with reCAPTCHA in RegisterController and related test cases. - Updated validation rules to utilize g-recaptcha-response instead of h-captcha-response. - Modified RegisterForm component to support reCAPTCHA, including changes to the form data structure and component references. - Enhanced test cases to reflect the new reCAPTCHA integration, ensuring proper validation and response handling. These changes improve security and user experience during the registration process by adopting a more widely used captcha solution. * Fix reCAPTCHA configuration and update RegisterForm styling - Corrected the configuration key for reCAPTCHA in RegisterController from 'services.recaptcha.secret_key' to 'services.re_captcha.secret_key'. - Updated the styling of the Captcha input section in RegisterForm.vue to improve layout consistency. These changes ensure proper reCAPTCHA functionality and enhance the user interface during the registration process. * Fix reCAPTCHA configuration in RegisterTest to use the correct key format - Updated the configuration key for reCAPTCHA in RegisterTest from 'services.recaptcha.secret_key' to 'services.re_captcha.secret_key' to ensure proper functionality during tests. This change aligns the test setup with the recent updates in the reCAPTCHA integration, improving the accuracy of the registration process tests. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2024-12-18 16:35:09 +01:00
this.$refs.captcha?.reset()
2023-12-09 15:47:03 +01:00
}
if (this.form.editable_submissions && this.form.submission_id) {
this.dataForm.submission_id = this.form.submission_id
}
this.$refs['form-timer'].stopTimer()
this.dataForm.completion_time = this.$refs['form-timer'].completionTime
Decouple title from title block (#696) * Decouple title from title block * fix lint * remove dry run for FormTitleMigration * Skip form title migration for forms with hidden titles * Refactor AI Form Generation with Dedicated Prompt Services - Extract AI form generation logic from GenerateTemplate command into dedicated prompt service classes - Update GenerateAiForm job to use new prompt generation services - Improve GptCompleter with more robust error handling and token tracking - Add error field to AiFormCompletion model for better error logging - Simplify command signature from 'ai:make-form-template' to 'form:generate' * Consolidate Template Metadata Generation with Unified Prompt Service - Create GenerateTemplateMetadataPrompt to centralize template metadata generation - Update GenerateTemplate command to use new consolidated metadata generation approach - Enhance GptCompleter to support strict JSON schema validation - Increase form prompt max length to support more complex form descriptions - Refactor form generation to simplify metadata extraction and processing * Implement Form Mode Strategy for Flexible Form Rendering - Introduce FormModeStrategy to centralize form rendering logic - Add support for different form modes: LIVE, PREVIEW, TEST, EDIT, PREFILL - Refactor components to use mode-based rendering strategy - Remove legacy boolean props like adminPreview and creating - Enhance form component flexibility and reusability * Refine Form Mode Strategy Display Behavior - Update FormModeStrategy to hide hidden fields in PREVIEW mode - Add FormMode getter in UrlFormPrefill component for mode-specific rendering - Clarify mode-specific validation and display logic in form strategies * Enhance Form Template Generation with Advanced Field Options - Update GenerateTemplate command to use front_url for template URL output - Expand GenerateFormPrompt with comprehensive field configuration options - Add support for advanced field types: date with time, toggle switches, radio/checkbox selections - Introduce field width configuration and HTML formatting for text elements - Re-enable select, multi-select, and matrix field type definitions with enhanced configurations * Remove Deprecated Template Metadata Generation Services - Delete multiple AI prompt services related to template metadata generation - Simplify GenerateTemplate command to use default values instead of complex metadata generation - Remove GenerateTemplateMetadataPrompt and related classes like GenerateTemplateDescriptionPrompt, GenerateTemplateImageKeywordsPrompt, etc. - Update form template generation to use basic fallback metadata generation approach * Restore GenerateTemplateMetadataPrompt for Comprehensive Template Generation - Reintroduce GenerateTemplateMetadataPrompt to replace default metadata generation - Update GenerateTemplate command to use consolidated metadata generation approach - Extract detailed metadata components including title, description, industries, and image search query - Improve template generation with more dynamic and AI-generated metadata * Refactor Template Preview Section Layout - Remove unnecessary nested div in template preview section - Simplify HTML structure for the template preview component - Maintain existing styling and functionality while improving code readability * Refactor Constructor and Code Formatting in AI Form Generation and Prompt Classes - Updated the constructor in GenerateAiForm.php to use a block structure for improved readability and consistency. - Added a blank line in the Prompt.php file to enhance code formatting and maintain consistency with PHP coding standards. - Modified the migration file to use a more concise class declaration syntax, improving clarity. These changes aim to enhance code readability and maintainability across the affected files. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2025-03-21 16:59:18 +01:00
// Add validation strategy check
if (!this.formModeStrategy.validation.validateOnSubmit) {
this.$emit('submit', this.dataForm, this.onSubmissionFailure)
return
}
2023-12-09 15:47:03 +01:00
this.$emit('submit', this.dataForm, this.onSubmissionFailure)
},
/**
* Handle form submission failure
2023-12-09 15:47:03 +01:00
*/
onSubmissionFailure() {
this.$refs['form-timer'].startTimer()
2023-12-09 15:47:03 +01:00
this.isAutoSubmit = false
if (this.fieldGroups.length > 1) {
this.showFirstPageWithError()
2023-12-09 15:47:03 +01:00
}
this.scrollToFirstError()
},
showFirstPageWithError() {
for (let i = 0; i < this.fieldGroups.length; i++) {
if (this.fieldGroups[i].some(field => this.dataForm.errors.has(field.id))) {
this.formPageIndex = i
break
}
}
},
scrollToFirstError() {
if (import.meta.server) return
const firstErrorElement = document.querySelector('.has-error')
if (firstErrorElement) {
2023-12-09 15:47:03 +01:00
window.scroll({
top: window.scrollY + firstErrorElement.getBoundingClientRect().top - 60,
2023-12-09 15:47:03 +01:00
behavior: 'smooth'
})
}
},
async getSubmissionData() {
2023-12-09 15:47:03 +01:00
if (!this.form || !this.form.editable_submissions || !this.form.submission_id) {
return null
}
await this.recordsStore.loadRecord(
opnFetch('/forms/' + this.form.slug + '/submissions/' + this.form.submission_id).then((data) => {
return {submission_id: this.form.submission_id, id: this.form.submission_id, ...data.data}
}).catch((error) => {
if (error?.data?.errors) {
useAlert().formValidationError(error.data)
} else {
useAlert().error(error?.data?.message || 'Something went wrong')
}
return null
2023-12-09 15:47:03 +01:00
})
)
return this.recordsStore.getByKey(this.form.submission_id)
2023-12-09 15:47:03 +01:00
},
/**
* Form initialization
*/
async initForm() {
// Only do a full initialization when necessary
// Store current page index and form data to avoid overwriting existing values
const currentFormData = this.dataForm ? clonedeep(this.dataForm.data()) : {}
// Handle special cases first
if (this.defaultDataForm) {
// If we have default data form, initialize with that
await nextTick(() => {
this.dataForm.resetAndFill(this.defaultDataForm)
})
this.updateFieldGroupsSafely()
return
}
// Initialize the field groups without resetting form data
this.updateFieldGroupsSafely()
// Check if we need to handle form submission states
if (await this.checkForEditableSubmission()) {
return
}
if (this.checkForPendingSubmission()) {
return
}
// Standard initialization with default values
this.initFormWithDefaultValues(currentFormData)
},
checkForEditableSubmission() {
return this.tryInitFormFromEditableSubmission()
},
checkForPendingSubmission() {
if (this.tryInitFormFromPendingSubmission()) {
this.updateFieldGroupsSafely()
return true
}
return false
},
async tryInitFormFromEditableSubmission() {
2023-12-09 15:47:03 +01:00
if (this.isPublicFormPage && this.form.editable_submissions) {
const submissionId = useRoute().query?.submission_id
if (submissionId) {
this.form.submission_id = submissionId
2023-12-09 15:47:03 +01:00
const data = await this.getSubmissionData()
if (data) {
this.dataForm.resetAndFill(data)
return true
2023-12-09 15:47:03 +01:00
}
}
}
return false
},
tryInitFormFromPendingSubmission() {
2023-12-09 15:47:03 +01:00
if (this.isPublicFormPage && this.form.auto_save) {
const pendingData = this.pendingSubmission.get()
if (pendingData && Object.keys(pendingData).length !== 0) {
this.updatePendingDataFields(pendingData)
this.dataForm.resetAndFill(pendingData)
return true
2023-12-09 15:47:03 +01:00
}
}
return false
},
updatePendingDataFields(pendingData) {
this.fields.forEach(field => {
if (field.type === 'date' && field.prefill_today) {
pendingData[field.id] = new Date().toISOString()
2023-12-09 15:47:03 +01:00
}
})
},
initFormWithDefaultValues(currentFormData = {}) {
// Only set page 0 on first load, otherwise maintain current position
if (this.formPageIndex === undefined || this.isInitialLoad) {
this.formPageIndex = 0
this.isInitialLoad = false
}
// Initialize form data with default values
const formData = { ...currentFormData }
const urlPrefill = this.isPublicFormPage ? new URLSearchParams(window.location.search) : null
2023-12-09 15:47:03 +01:00
this.fields.forEach(field => {
if (field.type.startsWith('nf-') && !['nf-page-body-input', 'nf-page-logo', 'nf-page-cover'].includes(field.type)) return
this.handleUrlPrefill(field, formData, urlPrefill)
this.handleDefaultPrefill(field, formData)
2023-12-09 15:47:03 +01:00
})
// Reset form with new data
this.dataForm.resetAndFill(formData)
2023-12-09 15:47:03 +01:00
},
handleUrlPrefill(field, formData, urlPrefill) {
if (!urlPrefill) return
const prefillValue = (() => {
const val = urlPrefill.get(field.id)
try {
return typeof val === 'string' && val.startsWith('{') ? JSON.parse(val) : val
} catch (e) {
return val
}
})()
const arrayPrefillValue = urlPrefill.getAll(field.id + '[]')
if (typeof prefillValue === 'object' && prefillValue !== null) {
formData[field.id] = { ...prefillValue }
} else if (prefillValue !== null) {
formData[field.id] = field.type === 'checkbox' ? this.parseBooleanValue(prefillValue) : prefillValue
} else if (arrayPrefillValue.length > 0) {
formData[field.id] = arrayPrefillValue
}
},
parseBooleanValue(value) {
return value === 'true' || value === '1'
},
handleDefaultPrefill(field, formData) {
if (field.type === 'date' && field.prefill_today) {
formData[field.id] = new Date().toISOString()
} else if (field.type === 'matrix' && !formData[field.id]) {
formData[field.id] = {...field.prefill}
} else if (!(field.id in formData)) {
formData[field.id] = field.prefill
}
},
/**
* Page Navigation
*/
previousPage() {
this.formPageIndex--
this.scrollToTop()
2023-12-09 15:47:03 +01:00
},
nextPage() {
Decouple title from title block (#696) * Decouple title from title block * fix lint * remove dry run for FormTitleMigration * Skip form title migration for forms with hidden titles * Refactor AI Form Generation with Dedicated Prompt Services - Extract AI form generation logic from GenerateTemplate command into dedicated prompt service classes - Update GenerateAiForm job to use new prompt generation services - Improve GptCompleter with more robust error handling and token tracking - Add error field to AiFormCompletion model for better error logging - Simplify command signature from 'ai:make-form-template' to 'form:generate' * Consolidate Template Metadata Generation with Unified Prompt Service - Create GenerateTemplateMetadataPrompt to centralize template metadata generation - Update GenerateTemplate command to use new consolidated metadata generation approach - Enhance GptCompleter to support strict JSON schema validation - Increase form prompt max length to support more complex form descriptions - Refactor form generation to simplify metadata extraction and processing * Implement Form Mode Strategy for Flexible Form Rendering - Introduce FormModeStrategy to centralize form rendering logic - Add support for different form modes: LIVE, PREVIEW, TEST, EDIT, PREFILL - Refactor components to use mode-based rendering strategy - Remove legacy boolean props like adminPreview and creating - Enhance form component flexibility and reusability * Refine Form Mode Strategy Display Behavior - Update FormModeStrategy to hide hidden fields in PREVIEW mode - Add FormMode getter in UrlFormPrefill component for mode-specific rendering - Clarify mode-specific validation and display logic in form strategies * Enhance Form Template Generation with Advanced Field Options - Update GenerateTemplate command to use front_url for template URL output - Expand GenerateFormPrompt with comprehensive field configuration options - Add support for advanced field types: date with time, toggle switches, radio/checkbox selections - Introduce field width configuration and HTML formatting for text elements - Re-enable select, multi-select, and matrix field type definitions with enhanced configurations * Remove Deprecated Template Metadata Generation Services - Delete multiple AI prompt services related to template metadata generation - Simplify GenerateTemplate command to use default values instead of complex metadata generation - Remove GenerateTemplateMetadataPrompt and related classes like GenerateTemplateDescriptionPrompt, GenerateTemplateImageKeywordsPrompt, etc. - Update form template generation to use basic fallback metadata generation approach * Restore GenerateTemplateMetadataPrompt for Comprehensive Template Generation - Reintroduce GenerateTemplateMetadataPrompt to replace default metadata generation - Update GenerateTemplate command to use consolidated metadata generation approach - Extract detailed metadata components including title, description, industries, and image search query - Improve template generation with more dynamic and AI-generated metadata * Refactor Template Preview Section Layout - Remove unnecessary nested div in template preview section - Simplify HTML structure for the template preview component - Maintain existing styling and functionality while improving code readability * Refactor Constructor and Code Formatting in AI Form Generation and Prompt Classes - Updated the constructor in GenerateAiForm.php to use a block structure for improved readability and consistency. - Added a blank line in the Prompt.php file to enhance code formatting and maintain consistency with PHP coding standards. - Modified the migration file to use a more concise class declaration syntax, improving clarity. These changes aim to enhance code readability and maintainability across the affected files. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2025-03-21 16:59:18 +01:00
if (!this.formModeStrategy.validation.validateOnNextPage) {
this.formPageIndex++
this.scrollToTop()
return false
}
Decouple title from title block (#696) * Decouple title from title block * fix lint * remove dry run for FormTitleMigration * Skip form title migration for forms with hidden titles * Refactor AI Form Generation with Dedicated Prompt Services - Extract AI form generation logic from GenerateTemplate command into dedicated prompt service classes - Update GenerateAiForm job to use new prompt generation services - Improve GptCompleter with more robust error handling and token tracking - Add error field to AiFormCompletion model for better error logging - Simplify command signature from 'ai:make-form-template' to 'form:generate' * Consolidate Template Metadata Generation with Unified Prompt Service - Create GenerateTemplateMetadataPrompt to centralize template metadata generation - Update GenerateTemplate command to use new consolidated metadata generation approach - Enhance GptCompleter to support strict JSON schema validation - Increase form prompt max length to support more complex form descriptions - Refactor form generation to simplify metadata extraction and processing * Implement Form Mode Strategy for Flexible Form Rendering - Introduce FormModeStrategy to centralize form rendering logic - Add support for different form modes: LIVE, PREVIEW, TEST, EDIT, PREFILL - Refactor components to use mode-based rendering strategy - Remove legacy boolean props like adminPreview and creating - Enhance form component flexibility and reusability * Refine Form Mode Strategy Display Behavior - Update FormModeStrategy to hide hidden fields in PREVIEW mode - Add FormMode getter in UrlFormPrefill component for mode-specific rendering - Clarify mode-specific validation and display logic in form strategies * Enhance Form Template Generation with Advanced Field Options - Update GenerateTemplate command to use front_url for template URL output - Expand GenerateFormPrompt with comprehensive field configuration options - Add support for advanced field types: date with time, toggle switches, radio/checkbox selections - Introduce field width configuration and HTML formatting for text elements - Re-enable select, multi-select, and matrix field type definitions with enhanced configurations * Remove Deprecated Template Metadata Generation Services - Delete multiple AI prompt services related to template metadata generation - Simplify GenerateTemplate command to use default values instead of complex metadata generation - Remove GenerateTemplateMetadataPrompt and related classes like GenerateTemplateDescriptionPrompt, GenerateTemplateImageKeywordsPrompt, etc. - Update form template generation to use basic fallback metadata generation approach * Restore GenerateTemplateMetadataPrompt for Comprehensive Template Generation - Reintroduce GenerateTemplateMetadataPrompt to replace default metadata generation - Update GenerateTemplate command to use consolidated metadata generation approach - Extract detailed metadata components including title, description, industries, and image search query - Improve template generation with more dynamic and AI-generated metadata * Refactor Template Preview Section Layout - Remove unnecessary nested div in template preview section - Simplify HTML structure for the template preview component - Maintain existing styling and functionality while improving code readability * Refactor Constructor and Code Formatting in AI Form Generation and Prompt Classes - Updated the constructor in GenerateAiForm.php to use a block structure for improved readability and consistency. - Added a blank line in the Prompt.php file to enhance code formatting and maintain consistency with PHP coding standards. - Modified the migration file to use a more concise class declaration syntax, improving clarity. These changes aim to enhance code readability and maintainability across the affected files. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2025-03-21 16:59:18 +01:00
const fieldsToValidate = this.currentFields.map(f => f.id)
this.dataForm.busy = true
this.dataForm.validate('POST', '/forms/' + this.form.slug + '/answer', {}, fieldsToValidate)
.then(() => {
this.formPageIndex++
this.dataForm.busy = false
this.scrollToTop()
}).catch(this.handleValidationError)
return false
2023-12-09 15:47:03 +01:00
},
scrollToTop() {
window.scrollTo({ top: 0, behavior: 'smooth' })
},
handleValidationError(error) {
console.error(error)
if (error?.data) {
useAlert().formValidationError(error.data)
}
this.dataForm.busy = false
},
isFieldHidden(field) {
2023-12-09 15:47:03 +01:00
return (new FormLogicPropertyResolver(field, this.dataFormValue)).isHidden()
},
2024-08-08 12:00:36 +02:00
getTargetFieldIndex(currentFieldPageIndex) {
return this.formPageIndex > 0
? this.fieldGroups.slice(0, this.formPageIndex).reduce((sum, group) => sum + group.length, 0) + currentFieldPageIndex
: currentFieldPageIndex
2023-12-09 15:47:03 +01:00
},
handleDragDropped(data) {
if (data.added) {
const targetIndex = this.getTargetFieldIndex(data.added.newIndex)
this.workingFormStore.addBlock(data.added.element, targetIndex, false)
}
if (data.moved) {
const oldTargetIndex = this.getTargetFieldIndex(data.moved.oldIndex)
const newTargetIndex = this.getTargetFieldIndex(data.moved.newIndex)
this.workingFormStore.moveField(oldTargetIndex, newTargetIndex)
}
2024-08-08 12:00:36 +02:00
},
setPageForField(fieldIndex) {
if (fieldIndex === -1) return
let currentIndex = 0
for (let i = 0; i < this.fieldGroups.length; i++) {
currentIndex += this.fieldGroups[i].length
if (currentIndex > fieldIndex) {
this.formPageIndex = i
return
}
2024-08-08 12:00:36 +02:00
}
this.formPageIndex = this.fieldGroups.length - 1
},
// New method for updating field groups
updateFieldGroups() {
if (!this.fields || this.fields.length === 0) return
// Preserve the current page index if possible
const currentPageIndex = this.formPageIndex
// Use a local variable instead of directly modifying computed property
// We'll use this to determine totalPages and currentPageIndex
const calculatedGroups = this.fields.reduce((groups, field, index) => {
// If the field is a page break, start a new group
if (field.type === 'nf-page-break' && index !== 0) {
groups.push([])
}
// Add the field to the current group
if (groups.length === 0) groups.push([])
groups[groups.length - 1].push(field)
return groups
}, [])
// If we don't have any groups (shouldn't happen), create a default group
if (calculatedGroups.length === 0) {
calculatedGroups.push([])
}
// Update page navigation
const totalPages = calculatedGroups.length
// Try to maintain the current page index if valid
if (currentPageIndex !== undefined && currentPageIndex < totalPages) {
this.formPageIndex = currentPageIndex
} else {
this.formPageIndex = 0
}
// Force a re-render of the component, which will update fieldGroups computed property
this.$forceUpdate()
},
// Helper method to prevent recursive updates
updateFieldGroupsSafely() {
// Set flag to prevent recursive updates
this.isUpdatingFieldGroups = true
// Call the actual update method
this.updateFieldGroups()
// Clear the flag after a short delay to allow Vue to process the update
this.$nextTick(() => {
this.isUpdatingFieldGroups = false
})
}
2023-12-09 15:47:03 +01:00
}
}
</script>
<style lang='scss' scoped>
.ghost-item {
@apply bg-blue-100 dark:bg-blue-900 rounded-md;
}
</style>