Enhance Process Flow and Store Management with Node Handling Improvements

- Added functionality to handle node additions from drag & drop in ProcessFlowCanvas, ensuring immediate visual feedback and persistence in application state.
- Implemented logic in the process store to prevent duplicate nodes when adding new nodes from the canvas.
- Enhanced server-side logging to track process updates, including node and edge counts for better debugging.
- Improved node extraction logic in the process builder store to create placeholder nodes from edge references when no nodes are present.
- Added debug logging for saving process data to facilitate better tracking of changes in the application state.
This commit is contained in:
Afiq 2025-06-11 12:23:52 +08:00
parent cf3a2c1a58
commit 00d8341f3a
4 changed files with 111 additions and 1 deletions

View File

@ -493,13 +493,21 @@ const onDrop = (event) => {
id: `${componentData.type}-${Date.now()}`, id: `${componentData.type}-${Date.now()}`,
type: componentData.type, type: componentData.type,
position, position,
label: componentData.label,
data: { data: {
...componentData.data, ...componentData.data,
label: componentData.label label: componentData.label
} }
}; };
// Add to Vue Flow for immediate visual feedback
addNodes([newNode]); addNodes([newNode]);
// IMPORTANT: Also emit the node to be added to the process store
// This ensures the node persists in the application state and can be saved
emit('nodesChange', [{ type: 'add', id: newNode.id, item: newNode }], nodes.value);
console.log('🎯 Node dropped and added:', newNode.type, newNode.id);
} catch (error) { } catch (error) {
console.error('Error handling drop:', error); console.error('Error handling drop:', error);
} }

View File

@ -380,6 +380,21 @@ const handleConditionUpdate = (conditions) => {
const onNodesChange = (changes, currentNodes) => { const onNodesChange = (changes, currentNodes) => {
if (!changes || !currentNodes) return; if (!changes || !currentNodes) return;
// Handle node additions (from drag & drop)
const addedNodes = changes.filter(change => change.type === 'add' && change.item);
if (addedNodes.length > 0) {
addedNodes.forEach(change => {
// Check if node already exists in store to prevent duplicates
const existingNode = processStore.currentProcess?.nodes?.find(n => n.id === change.item.id);
if (!existingNode) {
console.log('🔥 Adding node to store from canvas:', change.item);
processStore.addNode(change.item);
} else {
console.log('⚠️ Node already exists in store, skipping:', change.item.id);
}
});
}
// Handle node removals // Handle node removals
const removedNodes = changes const removedNodes = changes
.filter(change => change.type === 'remove') .filter(change => change.type === 'remove')

View File

@ -85,6 +85,15 @@ export default defineEventHandler(async (event) => {
} }
}); });
// Debug logging to see what we received
console.log('🔥 Server received process update:', {
processId,
nodeCount: (body.nodes || []).length,
edgeCount: (body.edges || []).length,
nodes: (body.nodes || []).map(n => ({ id: n.id, type: n.type, label: n.label })),
edges: (body.edges || []).map(e => ({ id: e.id, source: e.source, target: e.target }))
});
// Prepare process definition // Prepare process definition
const processDefinition = { const processDefinition = {
nodes: body.nodes || [], nodes: body.nodes || [],

View File

@ -133,7 +133,7 @@ export const useProcessBuilderStore = defineStore('processBuilder', {
if (nodes.length === 0 && edges.length > 0) { if (nodes.length === 0 && edges.length > 0) {
const nodeMap = new Map(); const nodeMap = new Map();
// Extract unique nodes from edge sourceNode and targetNode // First try to extract unique nodes from edge sourceNode and targetNode if they exist
edges.forEach(edge => { edges.forEach(edge => {
if (edge.sourceNode) { if (edge.sourceNode) {
nodeMap.set(edge.sourceNode.id, { nodeMap.set(edge.sourceNode.id, {
@ -156,6 +156,68 @@ export const useProcessBuilderStore = defineStore('processBuilder', {
} }
}); });
// If no nodes were extracted from embedded data, create placeholder nodes from edge references
if (nodeMap.size === 0) {
const nodeIds = new Set();
edges.forEach(edge => {
if (edge.source) nodeIds.add(edge.source);
if (edge.target) nodeIds.add(edge.target);
});
let nodePosition = { x: 100, y: 100 };
const spacing = 200;
nodeIds.forEach((nodeId, index) => {
// Determine node type from ID prefix
let nodeType = 'task'; // default
let label = nodeId;
let icon = 'schedule';
if (nodeId.includes('start-')) {
nodeType = 'start';
label = 'Start Point';
icon = 'play_circle_filled';
} else if (nodeId.includes('end-')) {
nodeType = 'end';
label = 'End Point';
icon = 'stop_circle';
} else if (nodeId.includes('form-')) {
nodeType = 'form';
label = 'Form';
icon = 'description';
} else if (nodeId.includes('api-')) {
nodeType = 'api';
label = 'API Call';
icon = 'api';
} else if (nodeId.includes('gateway-')) {
nodeType = 'gateway';
label = 'Decision Point';
icon = 'call_split';
} else if (nodeId.includes('script-')) {
nodeType = 'script';
label = 'Script';
icon = 'code';
}
nodeMap.set(nodeId, {
id: nodeId,
type: nodeType,
label: label,
position: {
x: nodePosition.x + (index % 3) * spacing,
y: nodePosition.y + Math.floor(index / 3) * spacing
},
data: {
label: label,
description: `Recovered ${nodeType} node`,
icon: icon
}
});
});
console.warn('Process had edges but no nodes. Created placeholder nodes from edge references:', Array.from(nodeIds));
}
// Convert to array // Convert to array
nodes = Array.from(nodeMap.values()); nodes = Array.from(nodeMap.values());
@ -259,6 +321,15 @@ export const useProcessBuilderStore = defineStore('processBuilder', {
// Status changes should only happen through explicit publish/unpublish actions // Status changes should only happen through explicit publish/unpublish actions
}; };
// Debug logging to see what we're actually sending
console.log('💾 Saving process data:', {
processId: this.currentProcess.id,
nodeCount: processData.nodes.length,
edgeCount: processData.edges.length,
nodes: processData.nodes.map(n => ({ id: n.id, type: n.type, label: n.label })),
edges: processData.edges.map(e => ({ id: e.id, source: e.source, target: e.target }))
});
const response = await $fetch(`/api/process/${this.currentProcess.id}`, { const response = await $fetch(`/api/process/${this.currentProcess.id}`, {
method: 'PUT', method: 'PUT',
body: processData body: processData
@ -488,6 +559,13 @@ export const useProcessBuilderStore = defineStore('processBuilder', {
addNode(node) { addNode(node) {
if (!this.currentProcess) return; if (!this.currentProcess) return;
// Check if node already exists to prevent duplicates
const existingNode = this.currentProcess.nodes.find(n => n.id === node.id);
if (existingNode) {
console.warn('Node already exists in store:', node.id);
return existingNode;
}
const newNode = { const newNode = {
id: node.id || uuidv4(), id: node.id || uuidv4(),
type: node.type, type: node.type,