diff --git a/client/components/forms/LogicConfirmationModal.vue b/client/components/forms/LogicConfirmationModal.vue
new file mode 100644
index 00000000..8174f2cd
--- /dev/null
+++ b/client/components/forms/LogicConfirmationModal.vue
@@ -0,0 +1,103 @@
+
+
+
+ Incomplete Form Logic
+
+
+
+
+
+
+ Some logic rules are incomplete or invalid and will be cleaned up to ensure that the form works correctly.
+
+
+
+
+
+
+
+
+ Field: {{ error.fieldName }}
+
+
+
+
+
+
+
+
+
+
+ Cancel
+
+
+ Save Anyway (Remove Invalid Logic)
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/components/open/forms/components/FormEditor.vue b/client/components/open/forms/components/FormEditor.vue
index 7ad0e10b..4bb77f64 100644
--- a/client/components/open/forms/components/FormEditor.vue
+++ b/client/components/open/forms/components/FormEditor.vue
@@ -84,6 +84,14 @@
:validation-error-response="validationErrorResponse"
@close="showFormErrorModal = false"
/>
+
+
+
0) {
+ this.showLogicConfirmationModal = true
+ return
+ }
+
+ this.proceedWithSave()
+ },
+ proceedWithSave() {
+ if (this.logicErrors.length > 0) {
+ // Clean invalid logic before saving using the comprehensive validator
+ const { validatePropertiesLogic } = useFormLogic()
+ this.form.properties = validatePropertiesLogic(this.form.properties)
+ }
+
if (this.isGuest) {
this.saveFormGuest()
} else if (this.isEdit) {
@@ -247,6 +276,13 @@ export default {
this.saveFormCreate()
}
},
+ handleLogicConfirmationCancel() {
+ this.showLogicConfirmationModal = false
+ },
+ handleLogicConfirmationConfirm() {
+ this.showLogicConfirmationModal = false
+ this.proceedWithSave()
+ },
saveFormEdit() {
if (this.updateFormLoading) return
diff --git a/client/composables/forms/useFormLogic.js b/client/composables/forms/useFormLogic.js
new file mode 100644
index 00000000..cdfa32af
--- /dev/null
+++ b/client/composables/forms/useFormLogic.js
@@ -0,0 +1,141 @@
+import FormPropertyLogicRule from '~/lib/forms/FormPropertyLogicRule.js'
+
+export const useFormLogic = () => {
+ const validateCondition = (condition, properties, fieldId, errors, parentIndex = null) => {
+ if (condition.operatorIdentifier) {
+ // This is a group condition (and/or)
+ if (!Array.isArray(condition.children)) {
+ errors.push({
+ fieldId,
+ error: 'INVALID_CONDITION_GROUP',
+ message: 'Condition group must have children array'
+ })
+ return
+ }
+
+ condition.children.forEach((childCondition, index) => {
+ validateCondition(childCondition, properties, fieldId, errors, parentIndex || index)
+ })
+ } else {
+ // This is a leaf condition
+ const referencedField = properties.find(p => p.id === condition.value?.property_meta?.id)
+ if (!referencedField) {
+ errors.push({
+ fieldId,
+ ruleIndex: parentIndex,
+ error: 'INVALID_FIELD_REFERENCE',
+ referencedFieldId: condition.value?.property_meta?.id,
+ message: `Referenced field ${condition.value?.property_meta?.id} no longer exists`
+ })
+ }
+ }
+ }
+
+ const getLogicErrors = (properties) => {
+ const errors = []
+
+ properties.forEach((field) => {
+ // Skip if field has no logic configured at all
+ if (!field.logic) return
+
+ // Skip if field has default empty logic (null conditions and empty actions)
+ if (field.logic.conditions === null && (!field.logic.actions || field.logic.actions.length === 0)) return
+
+ // Now validate if logic is configured but missing required parts
+ if (!field.logic.conditions) {
+ errors.push({
+ fieldId: field.id,
+ fieldName: field.name,
+ error: 'MISSING_CONDITIONS',
+ message: 'No conditions specified'
+ })
+ }
+
+ if (!field.logic.actions || field.logic.actions.length === 0) {
+ errors.push({
+ fieldId: field.id,
+ fieldName: field.name,
+ error: 'MISSING_ACTIONS',
+ message: 'No actions specified'
+ })
+ }
+
+ // Validate conditions structure and field references
+ if (field.logic.conditions) {
+ validateCondition(field.logic.conditions, properties, field.id, errors)
+ }
+
+ // Apply comprehensive validation from FormPropertyLogicRule
+ const logicRule = new FormPropertyLogicRule(field)
+ if (!logicRule.isValid()) {
+ errors.push({
+ fieldId: field.id,
+ fieldName: field.name,
+ error: 'INVALID_LOGIC_RULE',
+ message: logicRule.isConditionCorrect ?
+ 'Invalid action configuration' :
+ 'Invalid condition configuration'
+ })
+ }
+ })
+
+ return errors
+ }
+
+ const cleanInvalidLogic = (properties) => {
+ // Create a deep copy to avoid mutating the original
+ const cleanedProperties = JSON.parse(JSON.stringify(properties))
+
+ // Get all validation errors
+ const errors = getLogicErrors(cleanedProperties)
+
+ // Group errors by fieldId for efficient processing
+ const errorsByField = errors.reduce((acc, error) => {
+ if (!acc[error.fieldId]) {
+ acc[error.fieldId] = []
+ }
+ acc[error.fieldId].push(error)
+ return acc
+ }, {})
+
+ // Clean invalid logic for each field
+ cleanedProperties.forEach((field) => {
+ const fieldErrors = errorsByField[field.id]
+
+ // If field has any errors, reset its logic
+ if (fieldErrors?.length > 0) {
+ field.logic = {
+ conditions: null,
+ actions: [],
+ }
+ }
+ })
+
+ return cleanedProperties
+ }
+
+ // Direct implementation of the previous validatePropertiesLogic function
+ const validatePropertiesLogic = (properties) => {
+ // Create a deep copy to avoid mutating the original
+ const validatedProperties = JSON.parse(JSON.stringify(properties))
+
+ validatedProperties.forEach((field) => {
+ const isValid = new FormPropertyLogicRule(field).isValid()
+ if (!isValid) {
+ field.logic = {
+ conditions: null,
+ actions: [],
+ }
+ }
+ })
+
+ return validatedProperties
+ }
+
+ return {
+ validateCondition,
+ getLogicErrors,
+ cleanInvalidLogic,
+ validatePropertiesLogic
+ }
+}
\ No newline at end of file
diff --git a/client/composables/forms/validatePropertiesLogic.js b/client/composables/forms/validatePropertiesLogic.js
deleted file mode 100644
index d9b6d625..00000000
--- a/client/composables/forms/validatePropertiesLogic.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import FormPropertyLogicRule from "~/lib/forms/FormPropertyLogicRule.js"
-
-export const validatePropertiesLogic = (properties) => {
- properties.forEach((field) => {
- const isValid = new FormPropertyLogicRule(field).isValid()
- if (!isValid) {
- field.logic = {
- conditions: null,
- actions: [],
- }
- }
- })
- return properties
-}