- Introduced a new 'Page Wrapper' node type to allow multiple components (forms, HTML, tables) to be rendered as a single page, enhancing the flexibility of the process builder. - Implemented child node management within the Page Wrapper, including adding, updating, and removing child nodes through the process store. - Enhanced the ProcessFlowCanvas to support the new Page Wrapper node, including event handling for child node interactions and configuration. - Updated the workflow page to handle submissions and interactions for Page Wrapper nodes, ensuring seamless integration with existing process flows. - Improved documentation in CLAUDE.md to provide guidance on the new Page Wrapper architecture and its components. - Refactored related components and store logic to accommodate the new functionality, ensuring a cohesive user experience across the application.
41 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
AI Guidance
- This documentation is for AI memory/context. Use it to answer questions, generate code, and reason about the system.
- Always follow the schema and field descriptions exactly as written.
- When in doubt, refer to the code locations provided in this file.
- Do not invent new fields, types, or patterns unless explicitly documented here.
- If a field or pattern is ambiguous, prefer the most common usage as shown in the codebase.
- For process definitions, ensure there is exactly one start and one end node.
- For form components, only use 'options' for select/radio/checkbox types.
- If you encounter a new node/component type, check
/components/
for its implementation. - Avoid anti-patterns: do not use fields in the wrong context (e.g., 'options' in a text field), do not omit required fields, and do not mix node types inappropriately.
- If unsure, ask for clarification or check the referenced code files.
Getting Started
- Clone the repo and run
yarn install
to install dependencies. - Start the dev server with
yarn dev
. - For database setup, see the Database Operations section below.
- Explore
/pages/
for main app entry points. - See
/docs/json/
for sample process and form definitions. - For custom components, see
/components/
. - For API endpoints, see
/server/api/
. - For contributing, follow project conventions and see comments in code.
Common Development Commands
Development Server
yarn dev # Start development server
yarn build # Build for production
yarn build:new # Build with pre/post-build scripts
yarn preview # Preview production build
yarn generate # Generate static site
Database Operations
yarn prisma # Pull DB schema, generate client, and start dev server
npx prisma generate # Generate Prisma client only
npx prisma db pull # Pull database schema
npx prisma studio # Open Prisma Studio for database management
Code Quality
npx eslint . # Run ESLint
npx prettier --write . # Format code with Prettier
Architecture Overview
Technology Stack
- Framework: Nuxt 3 with Vue 3 Composition API
- Database: MySQL with Prisma ORM
- State Management: Pinia stores
- UI Framework: Tailwind CSS + Custom Rose UI components
- Forms: FormKit with custom extensions
- Process Visualization: Vue Flow for BPMN diagrams
- Authentication: JWT-based with custom middleware
Core System Components
This is a Business Process Management (BPM) platform with two primary modules:
1. Process Builder (/process-builder/
)
Professional BPMN-compliant workflow designer with comprehensive node types and sophisticated integration capabilities:
Main Pages:
- index.vue: Main process designer (drag-and-drop BPMN editor, ~40k tokens)
- manage.vue: Process management dashboard with metrics and CRUD operations
- analytics/[id].vue: Process analytics and journey visualization
Available Node Types:
- Start/End Points: Define process boundaries; start or finish a process.
- Form Tasks: User input forms; integrate with form builder.
- API Calls: Call external/internal APIs; supports authentication and error handling.
- Script Tasks: Run JavaScript code; map input/output variables.
- Business Rules: Evaluate conditions and set variables; supports AND/OR logic.
- Gateways: Decision points; branch process flow based on conditions.
- Notifications: Send messages (email, SMS, in-app) to users/roles.
- HTML Content: Display custom HTML/CSS/JS content in the process.
- Sub Processes: Run nested processes; supports variable mapping.
- Design Elements: Visual aids (swimlanes, shapes, text annotations).
Node type implementations:
/components/process-flow/ProcessFlowNodes.js
and related Vue components.
2. Form Builder (/form-builder/
)
Dynamic form creator with conditional logic, validation, and JavaScript API integration.
Form Component Types:
- Text: Single-line input.
- Select: Dropdown selection.
- Radio: Single-choice radio buttons.
- Checkbox: Multi-choice checkboxes.
- Date: Date picker.
- Repeating Group: Dynamic list of grouped fields.
- Heading: Section titles.
- Static/Display: Read-only or info fields.
See
/components/FormBuilderComponents.vue
and/components/formkit/
for implementations.
State Management Architecture
Primary Stores:
processBuilder.js
: Process design, node management, auto-save, history trackingformBuilder.js
: Form components, validation, custom scripts, preview datavariableStore.js
: Global process variables and data flow managementuser.js
: Authentication and user session management
Store Patterns:
- All stores use Pinia with persistence
- Reactive state updates trigger UI changes automatically
- Centralized error handling and loading states
- Auto-save functionality prevents data loss
Database Schema (Prisma)
Core Entities:
- process: BPMN process definitions (JSON schema, versioning, templates).
- form: Dynamic form configurations (fields, scripts, validation).
- caseInstance: Tracks process execution instances and status.
- task: User tasks within process cases.
- user/role/userrole: Authentication and RBAC system.
See
/prisma/schema.prisma
for schema details.
Key Relationships:
- Forms can be embedded in process tasks.
- Process variables flow between forms and process nodes.
- Complete audit trail through
processHistory
andformHistory
. - Case timeline tracking for process execution monitoring.
RBAC & Permissions System
- Roles: Define user access levels (e.g., admin, manager, user).
- Permissions: Assigned to roles; control access to features and data.
- UserRole: Maps users to roles.
- Where to find:
/prisma/schema.prisma
(models),/server/api/role/
(API),/stores/user.js
(frontend usage).
API Architecture (/server/api/
)
RESTful Structure:
/api/forms/
: CRUD for forms, with history./api/process/
: Process management, publishing, execution./api/tasks/
: Task assignment and completion./api/devtool/
: Dev utilities (ORM, code editor, etc).
API Request/Response:
- Most endpoints accept/return JSON.
- Auth via JWT in headers.
- For request/response shapes, see handler files in
/server/api/
or use browser dev tools. - For OpenAPI/Swagger docs, see project root if available.
Special Endpoints:
- Form field extraction:
/api/forms/[formId]/fields.get.js
- Process analytics:
/api/process/dashboard/summary.get.js
- Version management:
/api/forms/[id]/history.get.js
Process Execution Flow
- User starts a process (via UI or API).
- System creates a case instance and assigns initial tasks.
- User(s) complete form tasks, triggering API/script/business rule nodes as defined.
- Variables are updated and routed through gateways/conditions.
- Notifications and HTML content nodes are processed as needed.
- Process continues until end node is reached; case is closed.
For execution logic, see
/server/api/process/
and/components/process-flow/
.
Configuration Files (/docs/json/
)
Critical System Configurations:
formComponents.json
: Complete form structure for Malaysian Asnaf registration systemprocessDefinition.json
: BPMN process flow definitions with nodes and edgesprocessVariables.json
: 100+ process variables for data managementcustomScript.js
: Form conditional logic and field visibility rules
These JSON files define a production Malaysian welfare application system with complex business rules.
JSON Data Structure Schemas
Process Definition Schema
- nodes: Array (required) — List of all process steps.
- Node:
- id: String (required) — Unique node identifier.
- type: String (required) — Node type (e.g., 'form', 'api', 'start', etc.).
- label: String (optional) — Display label for the node.
- position: { x: Number, y: Number } (required) — Canvas position.
- data: Object — Type-specific config (see below).
- For 'form': formId, formName, assignedRoles, etc.
- For 'api': apiUrl, apiMethod, headers, etc.
- For 'gateway': conditions, defaultPath, etc.
- Node:
- edges: Array (required) — Connections between nodes.
- Edge:
- id: String (required) — Unique edge identifier.
- type: String (required) — Edge type (usually 'custom').
- source: String (required) — Source node id.
- target: String (required) — Target node id.
- sourceHandle: String (optional) — Source connection handle.
- targetHandle: String (optional) — Target connection handle.
- animated: Boolean (optional) — Animate edge.
- label: String (optional) — Edge label.
- data: Object (optional) — Extra edge metadata.
- Edge:
- viewport: { x: Number, y: Number, zoom: Number } (required) — Canvas viewport settings.
For real-world examples, see
/docs/json/process-builder/
and/components/process-flow/
.
Process Variable Schema
- variableName: Object (key is variable name)
- type: String (required, e.g. string, number, boolean, object, array) — Data type.
- value: Any (optional) — Initial value.
- description: String (optional) — Human-readable description.
- scope: String (optional, e.g. 'global') — Variable scope.
- name: String (optional, usually matches the key).
Form Builder Custom Component Schema
- type: String (required) — Component type (e.g., 'text', 'select', 'repeating-group').
- props: Object (required) — Component properties.
- name: String (required) — Field name (unique).
- label: String (required) — Field label.
- type: String (required) — Should match component type.
- placeholder: String (optional) — Placeholder text.
- validation: String (optional) — Validation rules (e.g., 'required').
- help: String (optional) — Helper text.
- width: String (optional) — Field width (e.g., '100%').
- gridColumn: String (optional) — Grid layout column span.
- options: Array<{ label: String, value: Any }> (optional, for select/radio/checkbox) — Choices for selection fields.
- conditionalLogic: { action: String, enabled: Boolean, operator: String, conditions: Array } (optional) — Show/hide logic.
- fields: Array (optional, for repeating-group) — Nested fields.
- maxItems: Number (optional, for repeating-group) — Max items allowed.
- minItems: Number (optional, for repeating-group) — Min items required.
- buttonText: String (optional, for repeating-group) — Add button label.
- removeText: String (optional, for repeating-group) — Remove button label.
- level: Number (optional, for heading components) — Heading level.
- value: Any (optional, for static fields) — Static value.
Some fields are required only for certain types (e.g., 'options' for select/radio, 'fields' for repeating-group). For more, see
/docs/json/form/
and/components/FormBuilder*
.
Custom Script Schema
- JavaScript using these helpers (in form script context):
- this.hideField(fieldName) — Hide a field.
- this.showField(fieldName) — Show a field.
- this.onFieldChange(fieldName, callback) — Run callback on field change.
- getField(fieldName) — Get field value.
- hideField(fieldName) — (Global) Hide a field.
- showField(fieldName) — (Global) Show a field.
- onFieldChange(fieldName, callback) — (Global) Field change handler.
- Scripts run in the form context;
this
refers to the script engine. Global helpers are also available. - Use for field visibility, conditional logic, and dynamic form behavior.
For script examples, see
/docs/json/form/customScript.js
and/components/FormScriptEngine.vue
.
Development Patterns
Vue 3 Composition API Usage:
- Use
ref()
for primitive reactive data - Use
shallowRef()
for large objects (like Vue Flow nodes) to avoid deep reactivity - Implement proper cleanup in
onUnmounted()
for timers and event listeners - Use
watch()
for complex reactive logic,computed()
for derived state
State Management Patterns:
- Store actions handle all business logic and API calls
- Components focus on presentation and user interaction
- Use store getters for computed values across components
- Implement optimistic updates with error rollback
Form Builder Patterns:
- FormKit schema generation from component configurations
- Conditional logic engine evaluates field visibility in real-time
- JavaScript API provides hooks for custom calculations and validations
- Custom script execution sandbox for security
Process Builder Patterns:
- Vue Flow integration for professional BPMN rendering with Vue 3 Composition API
- Node configuration through specialized modal components for each node type
- Smart connection system with 4-directional handles and type validation
- Auto-save with debouncing to prevent data loss (2-second intervals)
- History tracking for undo/redo functionality with change descriptions
- Real-time variable usage tracking and dependency analysis
- Drag-and-drop component palette with visual feedback
- Mobile-responsive design with collapsible panels and touch support
Process-Form Integration Patterns:
- Bidirectional data flow: Process variables ↔ Form fields
- Dynamic form behavior based on process state and variables
- Shared variable system with type validation and scope management
- Real-time synchronization between process nodes and form configurations
- Form field mapping in process tasks with input/output variable assignment
Security Considerations
Authentication:
- JWT tokens with refresh mechanism
- Role-based access control (RBAC) through
user/role/userrole
models - Route-level middleware protection
Data Security:
- XSS protection disabled for specific API routes (devtool, forms)
- Rate limiting: 200 requests per minute
- Input validation through FormKit and Prisma
- SQL injection protection through Prisma ORM
Script Execution:
- Form custom scripts run in 'safe' mode by default
- Script execution sandbox prevents direct DOM access
- Advanced mode available for power users with additional permissions
Key Implementation Details
Auto-save System:
- Debounced saves every 2 seconds after changes
- Unsaved changes protection with navigation guards
- Visual indicators for save status
Process Execution:
- BPMN-compliant process engine with standards-based execution
- Task assignment and routing based on process definition and business rules
- Variable management throughout process lifecycle with type safety
- Integration points for external APIs and services with authentication
- Case instance tracking with complete audit trail
- Dynamic user/role assignment with conditional logic
- Decision logic with complex branching (AND/OR condition combinations)
- Sub-process execution with variable inheritance and mapping
Form System:
- Dynamic component rendering from JSON schema
- Real-time validation and conditional logic
- Preview mode for form testing
- Import/export functionality for form templates
Performance Optimizations:
- Lazy loading for heavy components (modals, editors)
- Virtual scrolling for large lists
- Optimized API calls with loading states
- Bundle splitting for reduced initial load times
Development Tips
Working with Large Files:
pages/process-builder/index.vue
is ~40k tokens - consider code splitting- Use component lazy loading for modal components
- Implement proper loading states for better UX
Database Changes:
- Always run
npx prisma generate
after schema changes - Use migrations for production database updates
- Test with realistic data volumes
Testing Process Flows:
- Use the process management dashboard for testing and monitoring
- Create test cases in
/execution/
interface with realistic data - Monitor variables through the Variable Manager with real-time updates
- Test node configurations through specialized modal interfaces
- Validate API integrations with authentication and error handling
- Test conditional logic and gateway decision paths
- Verify form-process integration with variable mapping
- Use process analytics for performance monitoring and optimization
Custom Scripts:
- Test in 'safe' mode first before enabling 'advanced' mode
- Use the JavaScript API documentation for available functions
- Implement proper error handling for custom scripts
This codebase represents a sophisticated, production-ready BPM platform with comprehensive process design, form building, and execution capabilities.
Process Builder Node Architecture Details
Node Connection System:
- Handle Types: 4-directional connection points (top, bottom, left, right)
- Connection Validation: Type-safe connections with business rule enforcement
- Edge Management: Interactive edges with labels, conditions, and repositioning
- Smart Routing: Automatic handle assignment based on node type and flow direction
Variable System Integration:
- Variable Types: String, Integer, Decimal, Boolean, Date, DateTime, Object
- Scoping: Global process-level variables with inheritance to sub-processes
- Usage Tracking: Real-time analysis of where variables are used across nodes
- Type Validation: Constraint enforcement and automatic type conversion
- Dependency Analysis: Visual indication of variable dependencies between nodes
Advanced Process Features:
- Template System: Reusable process templates with variable mapping
- Version Control: Process versioning with rollback capability and change tracking
- Export/Import: Process definition portability with JSON schema validation
- Process Analytics: Execution metrics, performance tracking, and bottleneck analysis
- Integration Capabilities: RESTful API calls, database operations, webhook support
- Notification System: Multi-channel messaging with template support and user preferences
Mobile and Responsive Design:
- Collapsible Panels: Left (components) and right (properties) panels with toggle controls
- Touch Support: Mobile-optimized drag-and-drop with gesture recognition
- Keyboard Shortcuts: Ctrl+1/2/3 for panel management, standard undo/redo support
- Responsive Canvas: Adaptive grid layout with zoom and pan capabilities
- Device Preview: Mobile, tablet, and desktop preview modes for form integration testing
Process Node Architecture Deep Dive
Node Creation and Registration System
Available Node Types (/components/process-flow/ProcessBuilderComponents.vue
):
- Core Node Types: start, end, form, api, gateway, notification, business-rule, script, html, subprocess
- Design Elements: swimlane-horizontal, swimlane-vertical, rectangle-shape, text-annotation
Node Definition Structure:
{
type: 'node-type', // Required: Unique node type identifier
name: 'Display Name', // Required: Human-readable name for UI
category: 'Core|Shape', // Required: Category for component palette
icon: 'material-symbols:icon', // Required: Icon for component palette
description: 'Node purpose', // Required: Tooltip description
defaultProps: { // Required: Default node configuration
label: 'Node Label', // Default label shown on canvas
data: { // Node-specific configuration data
// Core properties (all nodes)
description: 'Description', // Node description for tooltips
shape: 'rectangle|diamond|circle', // Visual shape
backgroundColor: '#ffffff', // Background color
borderColor: '#000000', // Border color
textColor: '#000000', // Text color
// Node-type specific properties
// (varies by node type - see specific node schemas below)
}
}
}
Node Implementation Components
Vue Component Structure (all in /components/process-flow/custom/
):
- Node Rendering:
[NodeType]Node.vue
(e.g.,FormNode.vue
,ApiNode.vue
) - Configuration Modal:
[NodeType]NodeConfigurationModal.vue
- Configuration Component:
[NodeType]NodeConfiguration.vue
Required Node Component Structure:
<script setup>
import { Handle, Position } from '@vue-flow/core'
import { useProcessBuilderStore } from '~/stores/processBuilder'
import ValidationIndicator from '../ValidationIndicator.vue'
// Standard props all nodes receive
const props = defineProps([
'id', // Node ID (string)
'type', // Node type (string)
'label', // Node label (string)
'selected', // Selection state (boolean)
'data' // Custom data object
])
// Standard validation integration
const processStore = useProcessBuilderStore()
const validationIssues = computed(() => {
return processStore.getNodeValidation(props.id)
})
// Standard node styling
const nodeStyle = computed(() => ({
'--node-bg-color': props.data?.backgroundColor || '#ffffff',
'--node-border-color': props.data?.borderColor || '#000000',
'--node-text-color': props.data?.textColor || '#000000',
backgroundColor: props.data?.backgroundColor || '#ffffff',
borderColor: props.data?.borderColor || '#000000',
color: props.data?.textColor || '#000000'
}))
// Standard click handler
const emit = defineEmits(['node-click'])
const onClick = () => emit('node-click', props.id)
</script>
<template>
<div
:class="['custom-node', `node-${type}`, `shape-${data?.shape || 'rectangle'}`, { 'selected': selected }]"
:style="nodeStyle"
@click="onClick"
>
<!-- Required: 4-directional handles for all functional nodes -->
<Handle type="target" :position="Position.Top" :id="`${id}-top`" />
<Handle type="target" :position="Position.Left" :id="`${id}-left`" />
<Handle type="source" :position="Position.Right" :id="`${id}-right`" />
<Handle type="source" :position="Position.Bottom" :id="`${id}-bottom`" />
<!-- Required: Validation indicator -->
<ValidationIndicator :node-id="id" :validation-issues="validationIssues" />
<!-- Node content -->
<div class="custom-node-content">
<!-- Node-specific content -->
</div>
</div>
</template>
Node Data Schemas by Type
Form Node (type: 'form'
)
data: {
// Required fields
formId: null, // Form ID reference
formName: null, // Form name for display
// Assignment configuration
assignedRoles: [], // Array of role IDs
assignedUsers: [], // Array of user IDs
assignmentType: 'role', // 'role' | 'user' | 'variable'
assignmentVariable: '', // Variable name for dynamic assignment
// Variable mapping
inputMappings: [], // Array of { processVar, formField } mappings
outputMappings: [], // Array of { formField, processVar } mappings
// Timing configuration
dueDate: null, // Due date for task
dueDateVariable: '', // Variable for dynamic due date
priority: 'medium', // 'low' | 'medium' | 'high'
// Visual properties (inherited from base)
shape: 'rectangle',
backgroundColor: '#faf5ff',
borderColor: '#9333ea',
textColor: '#6b21a8'
}
API Node (type: 'api'
)
data: {
// Required API configuration
apiMethod: 'GET', // HTTP method
apiUrl: '', // API endpoint URL
// Request configuration
requestBody: '', // JSON request body
headers: '{"Content-Type": "application/json"}', // Request headers (JSON string)
// Authentication
authType: 'none', // 'none' | 'bearer' | 'basic' | 'apikey'
authToken: '', // Auth token/API key
authUsername: '', // Basic auth username
authPassword: '', // Basic auth password
// Response handling
outputVariable: 'apiResponse', // Variable to store response
errorVariable: 'apiError', // Variable to store errors
continueOnError: false, // Continue process flow on API error
// Timeout configuration
timeout: 30000, // Request timeout in milliseconds
// Visual properties
shape: 'rectangle',
backgroundColor: '#eff6ff',
borderColor: '#3b82f6',
textColor: '#1e40af'
}
Gateway Node (type: 'gateway'
)
data: {
// Decision logic
conditions: [], // Array of condition objects:
// [{
// id: string,
// variable: string,
// operator: '==' | '!=' | '>' | '<' | '>=' | '<=' | 'contains' | 'startsWith' | 'endsWith',
// value: any,
// logicalOperator: 'AND' | 'OR',
// path: string // Edge label for this condition
// }]
defaultPath: 'Default', // Default path when no conditions match
evaluationMode: 'sequential', // 'sequential' | 'parallel'
// Visual properties
shape: 'diamond',
backgroundColor: '#fff7ed',
borderColor: '#f97316',
textColor: '#c2410c'
}
Business Rule Node (type: 'business-rule'
)
data: {
// Rule groups for complex business logic
ruleGroups: [], // Array of rule group objects:
// [{
// id: string,
// name: string,
// operator: 'AND' | 'OR',
// rules: [{
// id: string,
// condition: string, // JavaScript expression
// action: 'SET' | 'CALCULATE' | 'VALIDATE',
// variable: string, // Target variable
// value: any, // Value to set/calculate
// errorMessage: string // Error message for validation
// }]
// }]
priority: 'medium', // Execution priority
executionMode: 'sequential', // 'sequential' | 'parallel'
continueOnError: false, // Continue on rule failure
// Visual properties
shape: 'rectangle',
backgroundColor: '#fdf4ff',
borderColor: '#a855f7',
textColor: '#7c3aed'
}
Script Node (type: 'script'
)
data: {
// Script configuration
scriptCode: '', // JavaScript code to execute
scriptLanguage: 'javascript', // Currently only 'javascript' supported
// Variable mapping
inputVariables: [], // Array of variable names to pass to script
outputVariables: [], // Array of variable names to extract from script
// Execution configuration
timeout: 30000, // Script execution timeout
sandbox: true, // Execute in sandboxed environment
// Visual properties
shape: 'rectangle',
backgroundColor: '#f9fafb',
borderColor: '#6b7280',
textColor: '#374151'
}
Notification Node (type: 'notification'
)
data: {
// Notification configuration
notificationType: 'info', // 'info' | 'warning' | 'error' | 'success'
// Recipients
recipientType: 'user', // 'user' | 'role' | 'email' | 'variable'
recipientUser: '', // User ID for 'user' type
recipientRole: '', // Role ID for 'role' type
recipientVariable: '', // Variable name for 'variable' type
recipientEmail: '', // Email address for 'email' type
// Message content
subject: '', // Notification subject/title
message: '', // Notification message body
// Delivery options
deliveryOptions: {
inApp: true, // In-app notification
email: false, // Email notification
sms: false // SMS notification
},
// Timing
priority: 'medium', // 'low' | 'medium' | 'high' | 'urgent'
expiration: {
enabled: false, // Enable expiration
value: 24, // Expiration value
unit: 'hours' // 'minutes' | 'hours' | 'days'
},
// Visual properties
shape: 'rectangle',
backgroundColor: '#f0f9ff',
borderColor: '#0ea5e9',
textColor: '#0284c7'
}
HTML Node (type: 'html'
)
data: {
// Content configuration
htmlCode: '<!-- HTML content -->', // HTML content
cssCode: '', // CSS styles
jsCode: '', // JavaScript code
// Variable integration
inputVariables: [], // Variables to pass to HTML context
outputVariables: [], // Variables to extract from HTML
allowVariableAccess: true, // Allow HTML to access process variables
// Behavior
autoRefresh: false, // Auto-refresh content
refreshInterval: 30000, // Refresh interval in milliseconds
// Visual properties
shape: 'rectangle',
backgroundColor: '#e0f2fe',
borderColor: '#0ea5e9',
textColor: '#0c4a6e'
}
Subprocess Node (type: 'subprocess'
)
data: {
// Subprocess configuration
subprocessId: null, // Target subprocess ID
subprocessName: '', // Subprocess name for display
// Variable mapping
inputMappings: [], // Map parent variables to subprocess
outputMappings: [], // Map subprocess variables to parent
// Execution configuration
executionMode: 'synchronous', // 'synchronous' | 'asynchronous'
inheritVariables: true, // Inherit parent process variables
// Visual properties
shape: 'rectangle',
backgroundColor: '#f0fdfa',
borderColor: '#14b8a6',
textColor: '#134e4a'
}
Node Store Management (/stores/processBuilder.js
)
Key Node Operations:
addNode(node)
: Add node to process (lines 700-752)updateNode(nodeId, updates)
: Update existing node (lines 757-766)deleteNode(nodeId)
: Remove node and connected edges (lines 771-814)getNodeValidation(nodeId)
: Get validation issues for node (lines 78-80)
Node State Management:
- Nodes stored in
currentProcess.nodes
array - Selection tracked in
selectedNodeId
- Validation results in
validationResults
Map - Auto-save triggers on node changes with 2-second debounce
Adding New Node Types
Step 1: Define Node Type in ProcessBuilderComponents.vue
// Add to availableComponents array
{
type: 'your-node-type',
name: 'Your Node Name',
category: 'Core',
icon: 'material-symbols:your-icon',
description: 'Node description',
defaultProps: {
label: 'Your Node',
data: {
// Your node-specific data structure
// Always include visual properties:
shape: 'rectangle',
backgroundColor: '#ffffff',
borderColor: '#000000',
textColor: '#000000'
}
}
}
Step 2: Create Node Vue Component
Create /components/process-flow/custom/YourNodeTypeNode.vue
following the standard node component structure.
Step 3: Create Configuration Components
/components/process-flow/YourNodeTypeConfiguration.vue
- Configuration UI/components/process-flow/YourNodeTypeConfigurationModal.vue
- Modal wrapper
Step 4: Register in Main Process Builder
Add imports and modal state management in /pages/process-builder/index.vue
.
Step 5: Add Validation Rules (Optional) Implement validation logic in the process store's validation system.
Node Connection System
Handle Configuration:
- All functional nodes must have 4 directional handles: top, bottom, left, right
- Handle IDs follow pattern:
${nodeId}-${direction}
- Use Vue Flow's Handle component with proper positioning
- Connection validation via
isValidConnection
callback
Edge Management:
- Edges stored in
currentProcess.edges
array - Edge IDs typically follow pattern:
${sourceNodeId}-${targetNodeId}
- Support for conditional edges with labels on gateway nodes
- Automatic cleanup when nodes are deleted
Node Validation System
Validation Integration:
- Each node can have validation issues (errors, warnings, info)
- ValidationIndicator component shows issues visually
- Validation results stored in process store's validationResults Map
- Real-time validation updates trigger UI changes
Common Validation Patterns:
- Required field validation (formId for form nodes, apiUrl for API nodes)
- Connection validation (start/end node requirements)
- Variable reference validation
- Configuration completeness checks
PageWrapper Architecture
Overview
The PageWrapper node is a revolutionary approach to page rendering that allows multiple child components (FormNode, HtmlNode, TableNode) to be rendered together as a single page. This replaces the previous one-node-per-page limitation.
Key Concepts
- Container-based Rendering: PageWrapper acts as a container that manages multiple child components
- Conditional Logic: Each child component can have its own show/hide conditions based on process variables
- Variable Mapping: Independent input/output variable mapping for each child component
- Flexible Layouts: Grid, flex, and stacked layout options with responsive design
- Backward Compatibility: Existing standalone FormNode and HtmlNode continue to work
PageWrapper Node Structure
{
type: 'page-wrapper',
data: {
// Layout configuration
layout: 'grid', // 'grid' | 'flex' | 'stacked'
columns: 2, // for grid layout
gap: '1rem', // spacing between components
padding: '1rem', // container padding
// Child components configuration
childNodes: [
{
id: 'child-1', // Unique child ID
type: 'form', // 'form' | 'html' | 'table'
nodeId: 'form-123', // Reference to actual form/html/table node
position: { row: 1, col: 1 }, // Grid position (for grid layout)
conditionalLogic: {
enabled: true,
variable: 'showForm',
operator: '==',
value: true
},
variableMapping: {
inputs: [{ processVar: 'userName', childVar: 'name' }],
outputs: [{ childVar: 'email', processVar: 'userEmail' }]
}
}
],
// Page-level settings
title: 'Multi-Component Page',
backgroundColor: '#ffffff',
customCSS: '', // Page-level CSS
customJS: '', // Page-level JavaScript
pageVariables: {} // Page-scoped variables
}
}
Child Component Types
Form Child Component
- Purpose: Renders a form within the PageWrapper
- Configuration: References an existing form by
nodeId
- Variable Mapping: Maps process variables to form fields and vice versa
- Conditional Display: Can be shown/hidden based on process variables
HTML Child Component
- Purpose: Renders HTML content within the PageWrapper
- Configuration: Contains HTML, CSS, and JavaScript code
- Variable Integration: HTML can access and update process variables
- Interactive Elements: Supports buttons, forms, and custom interactions
Table Child Component (Future)
- Purpose: Renders tabular data within the PageWrapper
- Configuration: Data source, columns, filtering, sorting options
- Actions: Row selection, inline editing, custom actions
Implementation Architecture
Core Components
-
PageWrapperNode.vue (
/components/process-flow/custom/
)- Visual representation in process builder
- Shows child component count and layout type
- Handles selection and configuration access
-
PageWrapperConfiguration.vue (
/components/process-flow/
)- Configuration UI for PageWrapper settings
- Child component management (add, remove, configure)
- Layout and styling options
-
PageWrapperConfigurationModal.vue (
/components/process-flow/
)- Modal wrapper for configuration
- Layout preview functionality
- Integration with process builder
-
PageWrapperRenderer.vue (
/components/process-flow/
)- Runtime rendering engine for PageWrapper execution
- Handles child component rendering and layout
- Manages variable mapping and conditional logic
- Coordinates form submissions and HTML interactions
Child Renderers
-
ChildFormRenderer.vue (
/components/process-flow/
)- Renders form components within PageWrapper
- Handles form validation and submission
- Applies input/output variable mappings
- Supports conditional logic and field states
-
ChildHtmlRenderer.vue (
/components/process-flow/
)- Renders HTML content within PageWrapper
- Executes custom CSS and JavaScript
- Handles HTML interactions and variable updates
- Provides safe execution context for custom scripts
Process Store Integration
Parent-Child Node Management
addChildNode(parentId, childNodeConfig)
: Add child to PageWrapperupdateChildNode(parentId, childId, updates)
: Update child configurationremoveChildNode(parentId, childId)
: Remove child from PageWrappergetChildNodes(parentId)
: Get all children of PageWrappergetChildNode(parentId, childId)
: Get specific child configuration
Enhanced Node Operations
deleteNodeWithChildren(nodeId)
: Handles PageWrapper deletion with cleanupisChildNode(nodeId)
: Check if node is referenced as childgetParentNodeId(childNodeId)
: Find parent PageWrapper for child reference
Workflow Execution Integration
Execution Flow
- Process Reaches PageWrapper: Node type 'page-wrapper' detected
- Child Component Loading: Each child component loads its referenced content
- Variable Mapping: Process variables mapped to child components as inputs
- Conditional Rendering: Child components shown/hidden based on conditions
- User Interaction: Users interact with forms, HTML, tables simultaneously
- Data Collection: Variable mappings collect outputs from child components
- Page Submission: All child data merged and process continues
Event Handling
handlePageWrapperSubmit
: Processes page-level submissionhandleChildFormSubmit
: Handles individual form submissions within pagehandleChildHtmlAction
: Processes HTML interactions (buttons, forms)handleVariableUpdate
: Updates process variables from child componentshandleValidationError
: Manages validation errors across child components
Layout System
Grid Layout
- Columns: Configurable number of columns (1-6)
- Positioning: Child components specify row and column
- Responsive: Automatically stacks on mobile devices
- Gap: Configurable spacing between grid items
Flex Layout
- Direction: Horizontal with wrap support
- Responsive: Components adapt to available width
- Alignment: Flexible arrangement with equal spacing
- Mobile-friendly: Stacks vertically on small screens
Stacked Layout
- Vertical: All components arranged vertically
- Full-width: Each component takes full container width
- Spacing: Consistent vertical spacing between components
- Simple: No complex positioning required
Variable Management
Input Mapping
- Maps process variables to child component fields
- Applied when PageWrapper loads
- Supports type conversion and default values
- Real-time updates when process variables change
Output Mapping
- Maps child component fields to process variables
- Applied on form submission or HTML interaction
- Supports data transformation and validation
- Merges data from multiple child components
Page-level Variables
- Scoped to the PageWrapper instance
- Shared between child components
- Can be used for component coordination
- Persisted during page interaction
Conditional Logic System
Variable-based Conditions
- Show/hide child components based on process variables
- Supports multiple operators: ==, !=, >, <, >=, <=
- Works with string, number, and boolean values
- Real-time evaluation when variables change
Complex Logic (Future)
- AND/OR combinations
- Multiple condition groups
- JavaScript expressions
- Time-based conditions
Migration Strategy
From Standalone Nodes
- Assessment: Identify processes with sequential form/HTML nodes
- Grouping: Group related nodes into logical pages
- Configuration: Create PageWrapper with child components
- Variable Mapping: Set up input/output mappings
- Testing: Verify functionality matches original flow
Backward Compatibility
- Existing processes continue to work unchanged
- Standalone FormNode and HtmlNode still supported
- Gradual migration path available
- No breaking changes to existing functionality
Development Guidelines
Creating Child Components
- Reference Existing Nodes: Child components reference existing form/HTML nodes
- Variable Mapping: Always configure input/output mappings
- Conditional Logic: Use for dynamic UI behavior
- Layout Consideration: Design for responsive layouts
- Testing: Test with various screen sizes and variable combinations
Performance Considerations
- Lazy Loading: Child components load content on demand
- Conditional Rendering: Hidden components don't render
- Variable Watching: Efficient reactivity system
- Memory Management: Proper cleanup on component destruction
Best Practices
- Logical Grouping: Group related functionality into single PageWrapper
- Clear Naming: Use descriptive titles and IDs for child components
- Variable Scope: Use appropriate variable mapping to avoid conflicts
- Layout Planning: Consider mobile-first design approach
- Testing: Validate with realistic data and user scenarios