Add LogicConfirmationModal Component and Integrate Logic Validation (#742)
* Add LogicConfirmationModal Component and Integrate Logic Validation - Introduced LogicConfirmationModal component to display validation errors related to form logic. - Integrated logic validation and cleaning functionalities into FormEditor, prompting users when invalid logic is detected. - Added useLogicValidation and useLogicCleaner composables for error checking and logic correction. - Removed deprecated validatePropertiesLogic function to streamline logic handling. These changes enhance user experience by providing clear feedback on form logic issues and ensuring that invalid logic is addressed before form submission. * Refactor Logic Handling in Form Components - Updated LogicConfirmationModal to improve user feedback by changing the title and icon colors, enhancing clarity on incomplete form logic. - Replaced useLogicValidation and useLogicCleaner with a new useFormLogic composable in FormEditor for streamlined logic validation and cleaning processes. - Removed deprecated useLogicCleaner and useLogicValidation files to simplify the codebase and improve maintainability. These changes enhance the user experience by providing clearer messages regarding form logic issues and ensuring that invalid logic is effectively managed before form submission. --------- Co-authored-by: JhumanJ <julien@nahum.net>
This commit is contained in:
141
client/composables/forms/useFormLogic.js
vendored
Normal file
141
client/composables/forms/useFormLogic.js
vendored
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user