diff --git a/components/ProcessTemplatesModal.vue b/components/ProcessTemplatesModal.vue index f36c6cc..c58579f 100644 --- a/components/ProcessTemplatesModal.vue +++ b/components/ProcessTemplatesModal.vue @@ -256,7 +256,8 @@ const categories = [ { id: 'onboarding', name: 'Onboarding' }, { id: 'support', name: 'Support & Service' }, { id: 'business', name: 'Business Operations' }, - { id: 'automation', name: 'Automation' } + { id: 'automation', name: 'Automation' }, + { id: 'data-driven', name: 'Data-Driven Workflows' } ]; // Active category @@ -1207,6 +1208,832 @@ const templates = [ { id: 'e40', source: 'form-10', target: 'notification-11', sourceHandle: 'form-10-bottom', targetHandle: 'notification-11-top', type: 'smoothstep' }, { id: 'e41', source: 'notification-11', target: 'end-6', sourceHandle: 'notification-11-bottom', targetHandle: 'end-6-top', type: 'smoothstep' } ] + }, + { + id: 'url-data-capture', + name: 'URL Data Capture & Form Pre-fill', + description: 'Capture user ID from URL parameters, fetch user data via API, and pre-fill a form for editing.', + category: 'data-driven', + complexity: 'Simple', + nodeCount: 4, + edgeCount: 3, + variables: [ + { + name: 'userId', + type: 'string', + scope: 'global', + description: 'User ID captured from URL parameter', + defaultValue: '', + captureFromUrl: true, + urlParameterName: 'id' + }, + { + name: 'userData', + type: 'object', + scope: 'global', + description: 'User data retrieved from API', + defaultValue: {} + }, + { + name: 'formSubmissionResult', + type: 'object', + scope: 'global', + description: 'Result of form submission', + defaultValue: {} + } + ], + nodes: [ + { + id: 'start-url-1', + type: 'start', + position: { x: 100, y: 100 }, + data: { + label: 'Start', + description: 'Begin URL data capture process', + backgroundColor: '#dcfce7', + borderColor: '#10b981', + textColor: '#065f46', + shape: 'circle' + } + }, + { + id: 'api-fetch-user', + type: 'api', + position: { x: 300, y: 100 }, + data: { + label: 'Fetch User Data', + description: 'Retrieve user information from API', + apiMethod: 'GET', + apiUrl: '/api/users/{userId}', + headers: [ + { key: 'Content-Type', value: 'application/json' }, + { key: 'Authorization', value: 'Bearer YOUR_API_TOKEN' } + ], + outputVariable: 'userData', + errorVariable: 'apiError', + continueOnError: false, + backgroundColor: '#eff6ff', + borderColor: '#3b82f6', + textColor: '#1e40af', + shape: 'rectangle' + } + }, + { + id: 'form-edit-user', + type: 'form', + position: { x: 500, y: 100 }, + data: { + label: 'Edit User Information', + description: 'Form pre-filled with user data for editing', + formId: null, + formName: 'User Information Form', + inputMappings: [ + { processVariable: 'userData.name', formField: 'fullName' }, + { processVariable: 'userData.email', formField: 'email' }, + { processVariable: 'userData.phone', formField: 'phoneNumber' } + ], + outputMappings: [ + { formField: 'fullName', processVariable: 'updatedName' }, + { formField: 'email', processVariable: 'updatedEmail' }, + { formField: 'phoneNumber', processVariable: 'updatedPhone' } + ], + backgroundColor: '#faf5ff', + borderColor: '#9333ea', + textColor: '#6b21a8', + shape: 'rectangle' + } + }, + { + id: 'end-url-1', + type: 'end', + position: { x: 700, y: 100 }, + data: { + label: 'End', + description: 'Process completed', + backgroundColor: '#fee2e2', + borderColor: '#dc2626', + textColor: '#991b1b', + shape: 'circle' + } + } + ], + edges: [ + { id: 'e-url-1', source: 'start-url-1', target: 'api-fetch-user', sourceHandle: 'start-url-1-bottom', targetHandle: 'api-fetch-user-top', type: 'smoothstep' }, + { id: 'e-url-2', source: 'api-fetch-user', target: 'form-edit-user', sourceHandle: 'api-fetch-user-bottom', targetHandle: 'form-edit-user-top', type: 'smoothstep' }, + { id: 'e-url-3', source: 'form-edit-user', target: 'end-url-1', sourceHandle: 'form-edit-user-bottom', targetHandle: 'end-url-1-top', type: 'smoothstep' } + ] + }, + { + id: 'dynamic-survey', + name: 'Dynamic Survey with Conditional Logic', + description: 'Multi-step survey with conditional questions based on URL parameters and previous answers.', + category: 'data-driven', + complexity: 'Medium', + nodeCount: 6, + edgeCount: 7, + variables: [ + { + name: 'surveyType', + type: 'string', + scope: 'global', + description: 'Type of survey from URL parameter', + defaultValue: 'general', + captureFromUrl: true, + urlParameterName: 'type' + }, + { + name: 'userRole', + type: 'string', + scope: 'global', + description: 'User role from URL parameter', + defaultValue: 'user', + captureFromUrl: true, + urlParameterName: 'role' + }, + { + name: 'basicInfo', + type: 'object', + scope: 'global', + description: 'Basic information from first form', + defaultValue: {} + }, + { + name: 'isManager', + type: 'boolean', + scope: 'global', + description: 'Whether user is in management role', + defaultValue: false + }, + { + name: 'surveyResults', + type: 'object', + scope: 'global', + description: 'Complete survey results', + defaultValue: {} + } + ], + nodes: [ + { + id: 'start-survey', + type: 'start', + position: { x: 100, y: 200 }, + data: { + label: 'Start Survey', + description: 'Begin dynamic survey process', + backgroundColor: '#dcfce7', + borderColor: '#10b981', + textColor: '#065f46', + shape: 'circle' + } + }, + { + id: 'form-basic-info', + type: 'form', + position: { x: 300, y: 200 }, + data: { + label: 'Basic Information', + description: 'Collect basic user information', + formId: null, + formName: 'Basic Information Form', + outputMappings: [ + { formField: 'name', processVariable: 'basicInfo.name' }, + { formField: 'department', processVariable: 'basicInfo.department' }, + { formField: 'experience', processVariable: 'basicInfo.experience' } + ], + backgroundColor: '#faf5ff', + borderColor: '#9333ea', + textColor: '#6b21a8', + shape: 'rectangle' + } + }, + { + id: 'business-rule-role-check', + type: 'business-rule', + position: { x: 500, y: 200 }, + data: { + label: 'Check User Role', + description: 'Determine if user is manager based on role parameter', + ruleGroups: [ + { + name: 'Manager Check', + conditions: [ + { + variable: 'userRole', + operator: 'eq', + value: 'manager', + minValue: null, + maxValue: null + } + ], + actions: [ + { + type: 'set_variable', + variable: 'isManager', + value: 'true' + } + ] + } + ], + backgroundColor: '#fdf4ff', + borderColor: '#a855f7', + textColor: '#7c3aed', + shape: 'rectangle' + } + }, + { + id: 'gateway-manager-check', + type: 'gateway', + position: { x: 700, y: 200 }, + data: { + label: 'Is Manager?', + description: 'Route based on manager status', + conditions: [ + { + variable: 'isManager', + operator: 'eq', + value: 'true', + output: 'Manager Path' + } + ], + defaultPath: 'Employee Path', + backgroundColor: '#fff7ed', + borderColor: '#f97316', + textColor: '#c2410c', + shape: 'diamond' + } + }, + { + id: 'form-manager-questions', + type: 'form', + position: { x: 900, y: 150 }, + data: { + label: 'Manager Questions', + description: 'Additional questions for managers', + formId: null, + formName: 'Manager Survey Form', + outputMappings: [ + { formField: 'teamSize', processVariable: 'surveyResults.teamSize' }, + { formField: 'managementStyle', processVariable: 'surveyResults.managementStyle' }, + { formField: 'budgetResponsibility', processVariable: 'surveyResults.budgetResponsibility' } + ], + backgroundColor: '#faf5ff', + borderColor: '#9333ea', + textColor: '#6b21a8', + shape: 'rectangle' + } + }, + { + id: 'form-employee-questions', + type: 'form', + position: { x: 900, y: 250 }, + data: { + label: 'Employee Questions', + description: 'Questions for regular employees', + formId: null, + formName: 'Employee Survey Form', + outputMappings: [ + { formField: 'jobSatisfaction', processVariable: 'surveyResults.satisfaction' }, + { formField: 'workloadRating', processVariable: 'surveyResults.workload' }, + { formField: 'careerGoals', processVariable: 'surveyResults.goals' } + ], + backgroundColor: '#faf5ff', + borderColor: '#9333ea', + textColor: '#6b21a8', + shape: 'rectangle' + } + }, + { + id: 'end-survey', + type: 'end', + position: { x: 1100, y: 200 }, + data: { + label: 'Survey Complete', + description: 'Survey completed successfully', + backgroundColor: '#fee2e2', + borderColor: '#dc2626', + textColor: '#991b1b', + shape: 'circle' + } + } + ], + edges: [ + { id: 'e-survey-1', source: 'start-survey', target: 'form-basic-info', sourceHandle: 'start-survey-bottom', targetHandle: 'form-basic-info-top', type: 'smoothstep' }, + { id: 'e-survey-2', source: 'form-basic-info', target: 'business-rule-role-check', sourceHandle: 'form-basic-info-bottom', targetHandle: 'business-rule-role-check-top', type: 'smoothstep' }, + { id: 'e-survey-3', source: 'business-rule-role-check', target: 'gateway-manager-check', sourceHandle: 'business-rule-role-check-bottom', targetHandle: 'gateway-manager-check-top', type: 'smoothstep' }, + { id: 'e-survey-4', source: 'gateway-manager-check', target: 'form-manager-questions', sourceHandle: 'gateway-manager-check-right', targetHandle: 'form-manager-questions-left', type: 'smoothstep', label: 'Manager Path' }, + { id: 'e-survey-5', source: 'gateway-manager-check', target: 'form-employee-questions', sourceHandle: 'gateway-manager-check-bottom', targetHandle: 'form-employee-questions-left', type: 'smoothstep', label: 'Employee Path' }, + { id: 'e-survey-6', source: 'form-manager-questions', target: 'end-survey', sourceHandle: 'form-manager-questions-bottom', targetHandle: 'end-survey-top', type: 'smoothstep' }, + { id: 'e-survey-7', source: 'form-employee-questions', target: 'end-survey', sourceHandle: 'form-employee-questions-bottom', targetHandle: 'end-survey-left', type: 'smoothstep' } + ] + }, + { + id: 'order-processing', + name: 'Order Processing with Status Updates', + description: 'Process orders with automatic status updates and notifications based on order ID from URL.', + category: 'business', + complexity: 'Medium', + nodeCount: 7, + edgeCount: 8, + variables: [ + { + name: 'orderId', + type: 'string', + scope: 'global', + description: 'Order ID from URL parameter', + defaultValue: '', + captureFromUrl: true, + urlParameterName: 'orderId' + }, + { + name: 'priority', + type: 'string', + scope: 'global', + description: 'Order priority from URL parameter', + defaultValue: 'normal', + captureFromUrl: true, + urlParameterName: 'priority' + }, + { + name: 'orderData', + type: 'object', + scope: 'global', + description: 'Order details from API', + defaultValue: {} + }, + { + name: 'isHighPriority', + type: 'boolean', + scope: 'global', + description: 'Whether order is high priority', + defaultValue: false + }, + { + name: 'processingResult', + type: 'object', + scope: 'global', + description: 'Result of order processing', + defaultValue: {} + } + ], + nodes: [ + { + id: 'start-order', + type: 'start', + position: { x: 100, y: 300 }, + data: { + label: 'Start Processing', + description: 'Begin order processing', + backgroundColor: '#dcfce7', + borderColor: '#10b981', + textColor: '#065f46', + shape: 'circle' + } + }, + { + id: 'api-get-order', + type: 'api', + position: { x: 300, y: 300 }, + data: { + label: 'Fetch Order', + description: 'Get order details from system', + apiMethod: 'GET', + apiUrl: '/api/orders/{orderId}', + headers: [ + { key: 'Content-Type', value: 'application/json' }, + { key: 'Authorization', value: 'Bearer YOUR_API_TOKEN' } + ], + outputVariable: 'orderData', + errorVariable: 'orderError', + continueOnError: false, + backgroundColor: '#eff6ff', + borderColor: '#3b82f6', + textColor: '#1e40af', + shape: 'rectangle' + } + }, + { + id: 'business-rule-priority', + type: 'business-rule', + position: { x: 500, y: 300 }, + data: { + label: 'Check Priority', + description: 'Determine processing priority', + ruleGroups: [ + { + name: 'High Priority Check', + conditions: [ + { + variable: 'priority', + operator: 'eq', + value: 'high', + minValue: null, + maxValue: null + } + ], + actions: [ + { + type: 'set_variable', + variable: 'isHighPriority', + value: 'true' + } + ] + } + ], + backgroundColor: '#fdf4ff', + borderColor: '#a855f7', + textColor: '#7c3aed', + shape: 'rectangle' + } + }, + { + id: 'gateway-priority-check', + type: 'gateway', + position: { x: 700, y: 300 }, + data: { + label: 'High Priority?', + description: 'Route based on priority', + conditions: [ + { + variable: 'isHighPriority', + operator: 'eq', + value: 'true', + output: 'Express Processing' + } + ], + defaultPath: 'Standard Processing', + backgroundColor: '#fff7ed', + borderColor: '#f97316', + textColor: '#c2410c', + shape: 'diamond' + } + }, + { + id: 'api-express-process', + type: 'api', + position: { x: 900, y: 250 }, + data: { + label: 'Express Processing', + description: 'Process high priority order', + apiMethod: 'POST', + apiUrl: '/api/orders/{orderId}/process-express', + requestBody: '{"orderId": "{orderId}", "priority": "high"}', + headers: [ + { key: 'Content-Type', value: 'application/json' } + ], + outputVariable: 'processingResult', + backgroundColor: '#eff6ff', + borderColor: '#3b82f6', + textColor: '#1e40af', + shape: 'rectangle' + } + }, + { + id: 'api-standard-process', + type: 'api', + position: { x: 900, y: 350 }, + data: { + label: 'Standard Processing', + description: 'Process regular order', + apiMethod: 'POST', + apiUrl: '/api/orders/{orderId}/process-standard', + requestBody: '{"orderId": "{orderId}", "priority": "normal"}', + headers: [ + { key: 'Content-Type', value: 'application/json' } + ], + outputVariable: 'processingResult', + backgroundColor: '#eff6ff', + borderColor: '#3b82f6', + textColor: '#1e40af', + shape: 'rectangle' + } + }, + { + id: 'notification-complete', + type: 'notification', + position: { x: 1100, y: 300 }, + data: { + label: 'Notify Completion', + description: 'Send processing complete notification', + notificationType: 'success', + recipientType: 'email', + recipientEmail: '{orderData.customerEmail}', + subject: 'Order Processing Complete', + message: 'Your order {orderId} has been processed successfully.', + priority: 'medium', + backgroundColor: '#f0f9ff', + borderColor: '#0ea5e9', + textColor: '#0284c7', + shape: 'rectangle' + } + }, + { + id: 'end-order', + type: 'end', + position: { x: 1300, y: 300 }, + data: { + label: 'Complete', + description: 'Order processing complete', + backgroundColor: '#fee2e2', + borderColor: '#dc2626', + textColor: '#991b1b', + shape: 'circle' + } + } + ], + edges: [ + { id: 'e-order-1', source: 'start-order', target: 'api-get-order', sourceHandle: 'start-order-bottom', targetHandle: 'api-get-order-top', type: 'smoothstep' }, + { id: 'e-order-2', source: 'api-get-order', target: 'business-rule-priority', sourceHandle: 'api-get-order-bottom', targetHandle: 'business-rule-priority-top', type: 'smoothstep' }, + { id: 'e-order-3', source: 'business-rule-priority', target: 'gateway-priority-check', sourceHandle: 'business-rule-priority-bottom', targetHandle: 'gateway-priority-check-top', type: 'smoothstep' }, + { id: 'e-order-4', source: 'gateway-priority-check', target: 'api-express-process', sourceHandle: 'gateway-priority-check-right', targetHandle: 'api-express-process-left', type: 'smoothstep', label: 'Express Processing' }, + { id: 'e-order-5', source: 'gateway-priority-check', target: 'api-standard-process', sourceHandle: 'gateway-priority-check-bottom', targetHandle: 'api-standard-process-left', type: 'smoothstep', label: 'Standard Processing' }, + { id: 'e-order-6', source: 'api-express-process', target: 'notification-complete', sourceHandle: 'api-express-process-bottom', targetHandle: 'notification-complete-top', type: 'smoothstep' }, + { id: 'e-order-7', source: 'api-standard-process', target: 'notification-complete', sourceHandle: 'api-standard-process-bottom', targetHandle: 'notification-complete-left', type: 'smoothstep' }, + { id: 'e-order-8', source: 'notification-complete', target: 'end-order', sourceHandle: 'notification-complete-bottom', targetHandle: 'end-order-top', type: 'smoothstep' } + ] + }, + { + id: 'customer-feedback-analysis', + name: 'Customer Feedback Analysis', + description: 'Automated feedback collection and analysis with sentiment detection and response routing.', + category: 'automation', + complexity: 'Complex', + nodeCount: 8, + edgeCount: 10, + variables: [ + { + name: 'customerId', + type: 'string', + scope: 'global', + description: 'Customer ID from URL parameter', + defaultValue: '', + captureFromUrl: true, + urlParameterName: 'customer' + }, + { + name: 'feedbackType', + type: 'string', + scope: 'global', + description: 'Type of feedback from URL parameter', + defaultValue: 'general', + captureFromUrl: true, + urlParameterName: 'type' + }, + { + name: 'customerData', + type: 'object', + scope: 'global', + description: 'Customer information from API', + defaultValue: {} + }, + { + name: 'feedbackData', + type: 'object', + scope: 'global', + description: 'Feedback form submission data', + defaultValue: {} + }, + { + name: 'sentimentAnalysis', + type: 'object', + scope: 'global', + description: 'AI sentiment analysis results', + defaultValue: {} + }, + { + name: 'isNegativeFeedback', + type: 'boolean', + scope: 'global', + description: 'Whether feedback is negative', + defaultValue: false + }, + { + name: 'escalationRequired', + type: 'boolean', + scope: 'global', + description: 'Whether escalation is needed', + defaultValue: false + } + ], + nodes: [ + { + id: 'start-feedback', + type: 'start', + position: { x: 100, y: 400 }, + data: { + label: 'Start Feedback', + description: 'Begin feedback collection process', + backgroundColor: '#dcfce7', + borderColor: '#10b981', + textColor: '#065f46', + shape: 'circle' + } + }, + { + id: 'api-get-customer', + type: 'api', + position: { x: 300, y: 400 }, + data: { + label: 'Get Customer Info', + description: 'Fetch customer details', + apiMethod: 'GET', + apiUrl: '/api/customers/{customerId}', + headers: [ + { key: 'Content-Type', value: 'application/json' }, + { key: 'Authorization', value: 'Bearer YOUR_API_TOKEN' } + ], + outputVariable: 'customerData', + errorVariable: 'customerError', + continueOnError: false, + backgroundColor: '#eff6ff', + borderColor: '#3b82f6', + textColor: '#1e40af', + shape: 'rectangle' + } + }, + { + id: 'form-feedback', + type: 'form', + position: { x: 500, y: 400 }, + data: { + label: 'Feedback Form', + description: 'Collect customer feedback', + formId: null, + formName: 'Customer Feedback Form', + inputMappings: [ + { processVariable: 'customerData.name', formField: 'customerName' }, + { processVariable: 'customerData.email', formField: 'customerEmail' }, + { processVariable: 'feedbackType', formField: 'feedbackCategory' } + ], + outputMappings: [ + { formField: 'rating', processVariable: 'feedbackData.rating' }, + { formField: 'comments', processVariable: 'feedbackData.comments' }, + { formField: 'improvementSuggestions', processVariable: 'feedbackData.suggestions' } + ], + backgroundColor: '#faf5ff', + borderColor: '#9333ea', + textColor: '#6b21a8', + shape: 'rectangle' + } + }, + { + id: 'api-sentiment-analysis', + type: 'api', + position: { x: 700, y: 400 }, + data: { + label: 'Analyze Sentiment', + description: 'AI-powered sentiment analysis', + apiMethod: 'POST', + apiUrl: '/api/ai/sentiment-analysis', + requestBody: '{"text": "{feedbackData.comments}", "context": "customer_feedback"}', + headers: [ + { key: 'Content-Type', value: 'application/json' }, + { key: 'X-API-Key', value: 'YOUR_AI_API_KEY' } + ], + outputVariable: 'sentimentAnalysis', + backgroundColor: '#eff6ff', + borderColor: '#3b82f6', + textColor: '#1e40af', + shape: 'rectangle' + } + }, + { + id: 'business-rule-sentiment', + type: 'business-rule', + position: { x: 900, y: 400 }, + data: { + label: 'Evaluate Sentiment', + description: 'Determine if feedback requires escalation', + ruleGroups: [ + { + name: 'Negative Sentiment', + conditions: [ + { + variable: 'sentimentAnalysis.sentiment', + operator: 'eq', + value: 'negative', + minValue: null, + maxValue: null + } + ], + actions: [ + { + type: 'set_variable', + variable: 'isNegativeFeedback', + value: 'true' + } + ] + }, + { + name: 'Low Rating', + conditions: [ + { + variable: 'feedbackData.rating', + operator: 'lte', + value: '2', + minValue: null, + maxValue: null + } + ], + actions: [ + { + type: 'set_variable', + variable: 'escalationRequired', + value: 'true' + } + ] + } + ], + backgroundColor: '#fdf4ff', + borderColor: '#a855f7', + textColor: '#7c3aed', + shape: 'rectangle' + } + }, + { + id: 'gateway-escalation', + type: 'gateway', + position: { x: 1100, y: 400 }, + data: { + label: 'Needs Escalation?', + description: 'Check if escalation is required', + conditions: [ + { + variable: 'escalationRequired', + operator: 'eq', + value: 'true', + output: 'Escalate' + } + ], + defaultPath: 'Standard Response', + backgroundColor: '#fff7ed', + borderColor: '#f97316', + textColor: '#c2410c', + shape: 'diamond' + } + }, + { + id: 'notification-escalate', + type: 'notification', + position: { x: 1300, y: 350 }, + data: { + label: 'Escalate to Manager', + description: 'Notify manager of negative feedback', + notificationType: 'warning', + recipientType: 'role', + recipientRole: 'customer_success_manager', + subject: 'Urgent: Negative Customer Feedback', + message: 'Customer {customerData.name} has provided negative feedback requiring immediate attention.', + priority: 'high', + backgroundColor: '#f0f9ff', + borderColor: '#0ea5e9', + textColor: '#0284c7', + shape: 'rectangle' + } + }, + { + id: 'notification-standard', + type: 'notification', + position: { x: 1300, y: 450 }, + data: { + label: 'Thank Customer', + description: 'Send standard thank you message', + notificationType: 'success', + recipientType: 'variable', + recipientVariable: 'customerData.email', + subject: 'Thank you for your feedback', + message: 'Thank you for taking the time to provide feedback. We appreciate your input.', + priority: 'medium', + backgroundColor: '#f0f9ff', + borderColor: '#0ea5e9', + textColor: '#0284c7', + shape: 'rectangle' + } + }, + { + id: 'end-feedback', + type: 'end', + position: { x: 1500, y: 400 }, + data: { + label: 'Complete', + description: 'Feedback processing complete', + backgroundColor: '#fee2e2', + borderColor: '#dc2626', + textColor: '#991b1b', + shape: 'circle' + } + } + ], + edges: [ + { id: 'e-feedback-1', source: 'start-feedback', target: 'api-get-customer', sourceHandle: 'start-feedback-bottom', targetHandle: 'api-get-customer-top', type: 'smoothstep' }, + { id: 'e-feedback-2', source: 'api-get-customer', target: 'form-feedback', sourceHandle: 'api-get-customer-bottom', targetHandle: 'form-feedback-top', type: 'smoothstep' }, + { id: 'e-feedback-3', source: 'form-feedback', target: 'api-sentiment-analysis', sourceHandle: 'form-feedback-bottom', targetHandle: 'api-sentiment-analysis-top', type: 'smoothstep' }, + { id: 'e-feedback-4', source: 'api-sentiment-analysis', target: 'business-rule-sentiment', sourceHandle: 'api-sentiment-analysis-bottom', targetHandle: 'business-rule-sentiment-top', type: 'smoothstep' }, + { id: 'e-feedback-5', source: 'business-rule-sentiment', target: 'gateway-escalation', sourceHandle: 'business-rule-sentiment-bottom', targetHandle: 'gateway-escalation-top', type: 'smoothstep' }, + { id: 'e-feedback-6', source: 'gateway-escalation', target: 'notification-escalate', sourceHandle: 'gateway-escalation-right', targetHandle: 'notification-escalate-left', type: 'smoothstep', label: 'Escalate' }, + { id: 'e-feedback-7', source: 'gateway-escalation', target: 'notification-standard', sourceHandle: 'gateway-escalation-bottom', targetHandle: 'notification-standard-left', type: 'smoothstep', label: 'Standard Response' }, + { id: 'e-feedback-8', source: 'notification-escalate', target: 'end-feedback', sourceHandle: 'notification-escalate-bottom', targetHandle: 'end-feedback-top', type: 'smoothstep' }, + { id: 'e-feedback-9', source: 'notification-standard', target: 'end-feedback', sourceHandle: 'notification-standard-bottom', targetHandle: 'end-feedback-left', type: 'smoothstep' } + ] } ]; @@ -1246,7 +2073,8 @@ const getTemplateIcon = (template) => { 'onboarding': 'material-symbols:person-add-outline', 'support': 'material-symbols:support-agent', 'business': 'material-symbols:business-center-outline', - 'automation': 'material-symbols:precision-manufacturing-outline' + 'automation': 'material-symbols:precision-manufacturing-outline', + 'data-driven': 'material-symbols:data-usage' }; return icons[template.category] || 'material-symbols:account-tree'; diff --git a/components/process-flow/VariableManager.vue b/components/process-flow/VariableManager.vue index 5b8a1c4..1e85907 100644 --- a/components/process-flow/VariableManager.vue +++ b/components/process-flow/VariableManager.vue @@ -479,6 +479,28 @@ help="A clear description helps others understand the purpose of this variable" /> + + + +
Cancel @@ -512,7 +534,9 @@ const variableForm = ref({ type: "string", scope: "global", description: "", - defaultValue: "" + defaultValue: "", + captureFromUrl: false, + urlParameterName: "" }); // Variable type options with descriptions @@ -1498,7 +1522,9 @@ const resetForm = () => { type: "string", scope: "global", description: "", - defaultValue: "" + defaultValue: "", + captureFromUrl: false, + urlParameterName: "" }; editingVariable.value = null; }; @@ -1532,7 +1558,9 @@ const saveVariable = async (formData) => { type: formData.type, scope: "global", description: formData.description, - value: processedDefaultValue + value: processedDefaultValue, + captureFromUrl: formData.captureFromUrl || false, + urlParameterName: formData.urlParameterName || "" }; if (editingVariable.value) { diff --git a/pages/workflow/[id].vue b/pages/workflow/[id].vue index 4fd067c..4ed96ab 100644 --- a/pages/workflow/[id].vue +++ b/pages/workflow/[id].vue @@ -83,6 +83,84 @@ watch(isProcessComplete, (newValue) => { } }); +// Capture URL parameters for variables that are configured to do so +const captureUrlParameters = () => { + try { + console.log('[Workflow] Capturing URL parameters...'); + + // Get current URL parameters + const urlParams = new URLSearchParams(window.location.search); + console.log('[Workflow] Available URL parameters:', Object.fromEntries(urlParams.entries())); + + // Check if we have process variables defined + const variableSource = process.value?.variables || process.value?.processVariables; + if (!variableSource) { + console.log('[Workflow] No process variables defined, skipping URL parameter capture'); + return; + } + + // Iterate through process variables to find ones configured for URL capture + Object.entries(variableSource).forEach(([variableName, variableConfig]) => { + if (variableConfig && variableConfig.captureFromUrl && variableConfig.urlParameterName) { + const paramName = variableConfig.urlParameterName; + const paramValue = urlParams.get(paramName); + + if (paramValue !== null) { + // Convert the parameter value based on the variable type + let convertedValue = paramValue; + + switch (variableConfig.type) { + case 'number': + case 'int': + case 'decimal': + convertedValue = Number(paramValue); + if (isNaN(convertedValue)) { + console.warn(`[Workflow] Could not convert URL parameter "${paramName}" value "${paramValue}" to number for variable "${variableName}"`); + convertedValue = variableConfig.value || 0; // Use default value + } + break; + case 'boolean': + convertedValue = paramValue.toLowerCase() === 'true' || paramValue === '1'; + break; + case 'object': + try { + convertedValue = JSON.parse(paramValue); + } catch (e) { + console.warn(`[Workflow] Could not parse URL parameter "${paramName}" value "${paramValue}" as JSON for variable "${variableName}"`); + convertedValue = variableConfig.value || {}; // Use default value + } + break; + case 'date': + case 'datetime': + const dateValue = new Date(paramValue); + if (isNaN(dateValue.getTime())) { + console.warn(`[Workflow] Could not parse URL parameter "${paramName}" value "${paramValue}" as date for variable "${variableName}"`); + convertedValue = variableConfig.value || null; // Use default value + } else { + convertedValue = variableConfig.type === 'date' ? dateValue.toISOString().split('T')[0] : dateValue.toISOString(); + } + break; + case 'string': + default: + convertedValue = String(paramValue); + break; + } + + // Set the variable value + processVariables.value[variableName] = convertedValue; + console.log(`[Workflow] Captured URL parameter "${paramName}" = "${paramValue}" -> variable "${variableName}" = `, convertedValue); + } else { + console.log(`[Workflow] URL parameter "${paramName}" not found for variable "${variableName}"`); + } + } + }); + + console.log('[Workflow] Final process variables after URL capture:', processVariables.value); + } catch (err) { + console.error('[Workflow] Error capturing URL parameters:', err); + } +}; + // Load process data const loadProcess = async () => { try { @@ -94,7 +172,6 @@ const loadProcess = async () => { if (response.success) { process.value = response.process; // includes processDefinition - console.log('[Workflow] Process loaded:', process.value.processName, process.value.processDefinition); // Check if process is published const status = process.value.processStatus || process.value.status || 'draft'; @@ -103,8 +180,20 @@ const loadProcess = async () => { return; } - // Initialize process variables from DB (process.processVariables) - processVariables.value = process.value.processVariables ? { ...process.value.processVariables } : {}; + // Initialize process variables from DB - extract values from variable definitions + processVariables.value = {}; + + // Try both possible property names for variables + const variableSource = process.value.variables || process.value.processVariables; + if (variableSource) { + Object.entries(variableSource).forEach(([name, variableDefinition]) => { + // Set the actual value, defaulting to the variable's default value or empty string + processVariables.value[name] = variableDefinition.value || variableDefinition.defaultValue || ''; + }); + } + + // Capture URL parameters for variables configured to do so + captureUrlParameters(); // Start the process execution (case instance) await startProcessExecution(); diff --git a/stores/processBuilder.js b/stores/processBuilder.js index 8f0545e..63543bf 100644 --- a/stores/processBuilder.js +++ b/stores/processBuilder.js @@ -1159,7 +1159,9 @@ export const useProcessBuilderStore = defineStore('processBuilder', { type: variable.type || 'string', scope: variable.scope || 'global', value: variable.value, - description: variable.description || '' + description: variable.description || '', + captureFromUrl: variable.captureFromUrl || false, + urlParameterName: variable.urlParameterName || '' }; this.unsavedChanges = true;