# Process Builder Technical Appendix
This document provides technical implementation details for developers working with the Process Builder system.
> For user documentation and usage guidelines, please refer to [Process Builder Documentation](PROCESS_BUILDER_DOCUMENTATION.md)
## Architecture Overview
### Technology Stack
- **Frontend Framework**: Nuxt 3 / Vue 3
- **State Management**: Pinia
- **Flow Visualization**: Vue Flow
- **UI Framework**: Tailwind CSS
- **Icons**: Material Design Icons
- **Validation**: Zod
### Key Dependencies
```json
{
"@vue-flow/core": "^1.42.5",
"@vue-flow/background": "^1.3.2",
"@vue-flow/controls": "^1.1.2",
"@vue-flow/minimap": "^1.5.3",
"@pinia/nuxt": "^0.4.11",
"uuid": "^10.0.0",
"zod": "^3.22.2"
}
```
## Project Structure
```
pages/
├── process-builder/
│ ├── index.vue # Main builder interface
│ └── manage.vue # Process management
components/
├── process-flow/
│ ├── ProcessFlowCanvas.vue # Flow canvas
│ └── ProcessFlowNodes.js # Custom node types
stores/
└── processBuilder.js # State management
composables/
└── useProcessValidation.js # Process validation
types/
└── process-builder.d.ts # TypeScript definitions
```
## Component Architecture
### Core Components
1. **ProcessFlowCanvas.vue**
```vue
```
2. **ProcessFlowNodes.js**
```javascript
import { h, markRaw } from 'vue';
import { Handle, Position } from '@vue-flow/core';
// Custom node renderer with handles
const CustomNode = markRaw({
template: `
`,
props: ['id', 'type', 'label', 'data'],
components: { Handle }
});
// Node type definitions
export const nodeTypes = markRaw({
task: TaskNode,
start: StartNode,
end: EndNode,
gateway: GatewayNode,
form: FormNode,
script: ScriptNode
});
```
## State Management
### Process Builder Store
```typescript
export const useProcessBuilderStore = defineStore('processBuilder', {
state: () => ({
processes: [],
currentProcess: null,
selectedNodeId: null,
selectedEdgeId: null,
unsavedChanges: false
}),
actions: {
createProcess(name, description) {
const process = {
id: uuidv4(),
name,
description,
nodes: [],
edges: [],
createdAt: new Date().toISOString()
};
this.processes.push(process);
this.currentProcess = process;
},
updateNode(nodeData) {
if (!this.currentProcess || !nodeData.id) return;
const nodeIndex = this.currentProcess.nodes.findIndex(
node => node.id === nodeData.id
);
if (nodeIndex > -1) {
this.currentProcess.nodes[nodeIndex] = {
...this.currentProcess.nodes[nodeIndex],
...nodeData
};
this.unsavedChanges = true;
}
},
// Additional actions...
}
});
```
## Node Types and Styles
### Node Configuration
```typescript
interface NodeConfig {
type: 'start' | 'end' | 'task' | 'form' | 'script' | 'gateway';
label: string;
icon: string;
iconColor: string;
data: {
description?: string;
assignee?: string;
formName?: string;
language?: string;
conditions?: string[];
};
}
const nodeConfigs: Record = {
start: {
type: 'start',
label: 'Start',
icon: 'play_circle_filled',
iconColor: 'text-green-500',
data: { description: 'Process starts here' }
},
task: {
type: 'task',
label: 'Task',
icon: 'assignment',
iconColor: 'text-blue-500',
data: { description: 'Task node', assignee: '' }
},
// Additional node configurations...
};
```
## Connection Handling
### Connection Logic
```typescript
// Connection validation
function validateConnection(connection: Connection): boolean {
if (!connection.source || !connection.target) return false;
if (connection.source === connection.target) return false;
const sourceNode = nodes.value.find(n => n.id === connection.source);
const targetNode = nodes.value.find(n => n.id === connection.target);
if (!sourceNode || !targetNode) return false;
// Prevent connecting to start node's input or from end node's output
if (targetNode.type === 'start') return false;
if (sourceNode.type === 'end') return false;
return true;
}
// Create new connection
function createConnection(connection: Connection): Edge {
return {
id: `${connection.source}-${connection.target}`,
source: connection.source,
target: connection.target,
type: 'smoothstep',
animated: true,
style: { stroke: '#555' }
};
}
```
## Event Handling
### Node Events
```typescript
// Node selection
function onNodeClick(node: Node): void {
selectedNode.value = node;
emit('nodeSelected', node);
}
// Node deletion
function onNodeDelete(nodes: Node[]): void {
removeNodes(nodes);
emit('nodesChange', nodes.value);
}
// Node dragging
function onNodeDragStop(node: Node): void {
updateNodePosition(node);
emit('nodePositionChange', node);
}
```
## Development Guidelines
### Best Practices
1. Use Vue Flow's built-in features instead of custom implementations
2. Handle all node/edge updates through the store
3. Maintain proper typings for all components
4. Follow Vue 3 Composition API patterns
5. Implement proper validation for all process changes
### Performance Considerations
1. Use `markRaw` for node components
2. Minimize reactive wrapping of node data
3. Use proper key bindings for lists
4. Implement efficient node filtering
5. Optimize canvas rendering
### Error Handling
1. Validate all connections before creation
2. Handle edge cases in node operations
3. Provide meaningful error messages
4. Implement proper error boundaries
5. Log errors appropriately
---
For user documentation and usage guidelines, please refer to [Process Builder Documentation](PROCESS_BUILDER_DOCUMENTATION.md).
Last updated: May 15, 2024