@flowuent-org/diagramming-core 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/TRANSLATION_FIX_SUMMARY.md +118 -0
  2. package/apps/diagramming/src/DiagramTabs.tsx +205 -205
  3. package/apps/diagramming/src/sample-workflow-content.ts +55 -54
  4. package/package.json +116 -116
  5. package/packages/diagrams/I18N_SETUP.md +126 -0
  6. package/packages/diagrams/NODE_DATA_UPDATE_API.md +430 -430
  7. package/packages/diagrams/README.md +443 -3
  8. package/packages/diagrams/UNDO_REDO_API.md +306 -306
  9. package/packages/diagrams/locales/en/translation.json +713 -0
  10. package/packages/diagrams/package.json +5 -23
  11. package/packages/diagrams/pnpm-lock.yaml +2606 -0
  12. package/packages/diagrams/project.json +42 -38
  13. package/packages/diagrams/rollup.config.js +5 -10
  14. package/packages/diagrams/src/index.ts +116 -113
  15. package/packages/diagrams/src/lib/atoms/CardEditableTitle.tsx +76 -76
  16. package/packages/diagrams/src/lib/components/automation/AutomationApiNode.tsx +24 -3
  17. package/packages/diagrams/src/lib/components/automation/AutomationEndNode.tsx +23 -2
  18. package/packages/diagrams/src/lib/components/automation/AutomationFormattingNode.tsx +24 -3
  19. package/packages/diagrams/src/lib/components/automation/AutomationStartNode.tsx +24 -3
  20. package/packages/diagrams/src/lib/contexts/onWorkflowNodeDelete.ts +1 -1
  21. package/packages/diagrams/src/lib/i18n.ts +42 -0
  22. package/packages/diagrams/src/lib/organisms/CustomEdge/useCreateBendPoint.tsx +121 -119
  23. package/packages/diagrams/src/lib/organisms/WorkFlowNode/NodeActionButtons.tsx +1 -1
  24. package/packages/diagrams/src/lib/templates/node-forms/CallForm.tsx +370 -370
  25. package/packages/diagrams/src/lib/types/node-types.ts +29 -29
  26. package/packages/diagrams/src/lib/utils/AutomationExecutionEngine.ts +1168 -1162
  27. package/packages/diagrams/tsconfig.lib.json +1 -3
  28. package/tsconfig.base.json +1 -1
@@ -1,430 +1,430 @@
1
- # Node Data Update API Documentation
2
-
3
- ## Overview
4
-
5
- The diagramming library provides comprehensive node data management functionality that allows external applications to read and update node configurations dynamically. This is particularly useful for automation diagrams where nodes contain configuration data like API endpoints, AI model settings, authentication keys, and other execution parameters.
6
-
7
- ## How Node Data Management Works
8
-
9
- ### Internal Implementation
10
-
11
- 1. **Node Data Storage**: Each node contains a `data` property that holds its configuration
12
- 2. **State Management**: Node data is managed through the Zustand store
13
- 3. **Real-time Updates**: Changes are immediately reflected in the diagram
14
- 4. **History Tracking**: Node data changes are tracked in the undo/redo system
15
-
16
- ### Key Components
17
-
18
- - **DiagrammingPageRef**: Exposes node data management methods
19
- - **Node Data Types**: Structured interfaces for different node types
20
- - **Update Methods**: Functions to modify node data externally
21
-
22
- ## External Node Data Control
23
-
24
- ### Method 1: Using Ref-based API (Recommended)
25
-
26
- The `DiagrammingPage` component exposes node data management through a ref:
27
-
28
- ```typescript
29
- import React, { useRef, useState, useEffect } from 'react';
30
- import { DiagrammingPage, DiagrammingPageRef } from '@flowuent-org/diagrams';
31
-
32
- const MyComponent = () => {
33
- const diagramRef = useRef<DiagrammingPageRef>(null);
34
- const [selectedNodeId, setSelectedNodeId] = useState<string | null>(null);
35
- const [nodeData, setNodeData] = useState<any>(null);
36
-
37
- // Monitor node selection changes
38
- useEffect(() => {
39
- const interval = setInterval(() => {
40
- if (diagramRef.current) {
41
- const currentSelected = diagramRef.current.getSelectedNode();
42
- if (currentSelected !== selectedNodeId) {
43
- setSelectedNodeId(currentSelected);
44
- if (currentSelected) {
45
- const data = diagramRef.current.getNodeData(currentSelected);
46
- setNodeData(data);
47
- }
48
- }
49
- }
50
- }, 100);
51
-
52
- return () => clearInterval(interval);
53
- }, [selectedNodeId]);
54
-
55
- const handleUpdateNode = (newData: any) => {
56
- if (selectedNodeId && diagramRef.current) {
57
- const success = diagramRef.current.updateNodeData(selectedNodeId, newData);
58
- if (success) {
59
- console.log('Node updated successfully');
60
- }
61
- }
62
- };
63
-
64
- return (
65
- <div>
66
- {/* Your external configuration panel */}
67
- <YourConfigurationPanel
68
- nodeData={nodeData}
69
- onUpdate={handleUpdateNode}
70
- />
71
-
72
- {/* The diagram */}
73
- <DiagrammingPage
74
- ref={diagramRef}
75
- diagramType="automation"
76
- defaultNodes={nodes}
77
- defaultEdges={edges}
78
- availableFunctions={[]}
79
- id={1}
80
- />
81
- </div>
82
- );
83
- };
84
- ```
85
-
86
- ### Available Methods
87
-
88
- The `DiagrammingPageRef` interface provides these node data management methods:
89
-
90
- ```typescript
91
- interface DiagrammingPageRef {
92
- // Undo/Redo methods (from previous API)
93
- undo: () => void;
94
- redo: () => void;
95
- canUndo: () => boolean;
96
- canRedo: () => boolean;
97
- reset: () => void;
98
- getHistoryLength: () => number;
99
- getHistoryIndex: () => number;
100
-
101
- // Node data management methods
102
- getNodeData: (nodeId: string) => any | null; // Get node data by ID
103
- updateNodeData: (nodeId: string, data: any) => boolean; // Update node data
104
- getSelectedNode: () => string | null; // Get currently selected node ID
105
- getNodes: () => any[]; // Get all nodes
106
- getEdges: () => any[]; // Get all edges
107
- }
108
- ```
109
-
110
- ## Node Data Structure Examples
111
-
112
- ### Automation API Node
113
- ```typescript
114
- interface AutomationApiNodeData {
115
- label: string;
116
- description: string;
117
- method: 'GET' | 'POST' | 'PUT' | 'DELETE';
118
- url: string;
119
- headers: Array<{
120
- key: string;
121
- value: string;
122
- enabled: boolean;
123
- }>;
124
- queryParams: Array<{
125
- key: string;
126
- value: string;
127
- enabled: boolean;
128
- }>;
129
- body?: string;
130
- timeout: number;
131
- retryCount: number;
132
- // ... other API-specific fields
133
- }
134
- ```
135
-
136
- ### Automation AI Formatting Node
137
- ```typescript
138
- interface AutomationFormattingNodeData {
139
- label: string;
140
- description: string;
141
- formattingType: 'basic' | 'ai-powered' | 'template';
142
- aiConfig?: {
143
- apiUrl: string;
144
- apiKey: string;
145
- model: string; // e.g., "GPT-5 Thinking mini"
146
- instruction: string;
147
- temperature: number; // e.g., 0.95
148
- maxTokens?: number; // e.g., 2048
149
- systemPrompt?: string;
150
- };
151
- outputVariable: string;
152
- outputDataType: 'String' | 'Object' | 'Array';
153
- // ... other formatting-specific fields
154
- }
155
- ```
156
-
157
- ### Automation Start Node
158
- ```typescript
159
- interface AutomationStartNodeData {
160
- label: string;
161
- description: string;
162
- triggerType: 'manual' | 'scheduled' | 'event';
163
- scheduleConfig?: {
164
- frequency: 'hourly' | 'daily' | 'weekly' | 'monthly';
165
- time?: string;
166
- cron?: string;
167
- timezone?: string;
168
- };
169
- eventConfig?: {
170
- webhookUrl?: string;
171
- eventType?: string;
172
- filters?: Array<{
173
- key: string;
174
- value: string;
175
- operator: 'equals' | 'contains' | 'startsWith' | 'endsWith';
176
- }>;
177
- };
178
- // ... other start-specific fields
179
- }
180
- ```
181
-
182
- ## Complete Example: AI Model Configuration Panel
183
-
184
- Here's a complete example showing how to create an external configuration panel for AI model settings:
185
-
186
- ```typescript
187
- import React, { useRef, useState, useEffect } from 'react';
188
- import {
189
- Box,
190
- Typography,
191
- TextField,
192
- Button,
193
- Card,
194
- CardContent,
195
- Grid,
196
- Select,
197
- MenuItem,
198
- FormControl,
199
- InputLabel,
200
- Chip,
201
- Alert
202
- } from '@mui/material';
203
- import { DiagrammingPage, DiagrammingPageRef } from '@flowuent-org/diagrams';
204
-
205
- const AIModelConfigurationPanel: React.FC = () => {
206
- const diagramRef = useRef<DiagrammingPageRef>(null);
207
- const [selectedNodeId, setSelectedNodeId] = useState<string | null>(null);
208
- const [nodeData, setNodeData] = useState<any>(null);
209
- const [formData, setFormData] = useState<any>({});
210
- const [updateStatus, setUpdateStatus] = useState<'idle' | 'success' | 'error'>('idle');
211
-
212
- // Monitor node selection changes
213
- useEffect(() => {
214
- const interval = setInterval(() => {
215
- if (diagramRef.current) {
216
- const currentSelected = diagramRef.current.getSelectedNode();
217
- if (currentSelected !== selectedNodeId) {
218
- setSelectedNodeId(currentSelected);
219
- if (currentSelected) {
220
- const data = diagramRef.current.getNodeData(currentSelected);
221
- setNodeData(data);
222
- setFormData(data || {});
223
- }
224
- }
225
- }
226
- }, 100);
227
-
228
- return () => clearInterval(interval);
229
- }, [selectedNodeId]);
230
-
231
- const handleFormChange = (field: string, value: any) => {
232
- setFormData(prev => ({
233
- ...prev,
234
- [field]: value
235
- }));
236
- };
237
-
238
- const handleUpdateNode = () => {
239
- if (!selectedNodeId || !diagramRef.current) return;
240
-
241
- const success = diagramRef.current.updateNodeData(selectedNodeId, formData);
242
- if (success) {
243
- setUpdateStatus('success');
244
- setTimeout(() => setUpdateStatus('idle'), 2000);
245
- } else {
246
- setUpdateStatus('error');
247
- setTimeout(() => setUpdateStatus('idle'), 2000);
248
- }
249
- };
250
-
251
- const renderAIConfiguration = () => {
252
- if (!selectedNodeId || !nodeData) {
253
- return (
254
- <Card>
255
- <CardContent>
256
- <Typography variant="h6" color="text.secondary">
257
- Select an AI Formatting node to configure
258
- </Typography>
259
- </CardContent>
260
- </Card>
261
- );
262
- }
263
-
264
- return (
265
- <Card>
266
- <CardContent>
267
- <Typography variant="h6" gutterBottom>
268
- AI Model Configuration
269
- </Typography>
270
-
271
- <Chip
272
- label={`Node ID: ${selectedNodeId}`}
273
- size="small"
274
- sx={{ mb: 2 }}
275
- />
276
-
277
- {updateStatus === 'success' && (
278
- <Alert severity="success" sx={{ mb: 2 }}>
279
- Configuration updated successfully!
280
- </Alert>
281
- )}
282
-
283
- <Grid container spacing={2}>
284
- <Grid item xs={12}>
285
- <TextField
286
- fullWidth
287
- label="Model"
288
- value={formData.aiConfig?.model || ''}
289
- onChange={(e) => handleFormChange('aiConfig', {
290
- ...formData.aiConfig,
291
- model: e.target.value
292
- })}
293
- />
294
- </Grid>
295
-
296
- <Grid item xs={6}>
297
- <TextField
298
- fullWidth
299
- label="Max Tokens"
300
- type="number"
301
- value={formData.aiConfig?.maxTokens || 2048}
302
- onChange={(e) => handleFormChange('aiConfig', {
303
- ...formData.aiConfig,
304
- maxTokens: parseInt(e.target.value)
305
- })}
306
- />
307
- </Grid>
308
-
309
- <Grid item xs={6}>
310
- <TextField
311
- fullWidth
312
- label="Temperature"
313
- type="number"
314
- step="0.1"
315
- value={formData.aiConfig?.temperature || 0.95}
316
- onChange={(e) => handleFormChange('aiConfig', {
317
- ...formData.aiConfig,
318
- temperature: parseFloat(e.target.value)
319
- })}
320
- />
321
- </Grid>
322
-
323
- <Grid item xs={12}>
324
- <TextField
325
- fullWidth
326
- label="Instruction"
327
- multiline
328
- rows={3}
329
- value={formData.aiConfig?.instruction || ''}
330
- onChange={(e) => handleFormChange('aiConfig', {
331
- ...formData.aiConfig,
332
- instruction: e.target.value
333
- })}
334
- />
335
- </Grid>
336
-
337
- <Grid item xs={12}>
338
- <TextField
339
- fullWidth
340
- label="API Key"
341
- type="password"
342
- value={formData.aiConfig?.apiKey || ''}
343
- onChange={(e) => handleFormChange('aiConfig', {
344
- ...formData.aiConfig,
345
- apiKey: e.target.value
346
- })}
347
- />
348
- </Grid>
349
- </Grid>
350
-
351
- <Box sx={{ mt: 3 }}>
352
- <Button
353
- variant="contained"
354
- onClick={handleUpdateNode}
355
- fullWidth
356
- >
357
- Update Configuration
358
- </Button>
359
- </Box>
360
- </CardContent>
361
- </Card>
362
- );
363
- };
364
-
365
- return (
366
- <Box sx={{ height: '100vh', display: 'flex' }}>
367
- {/* Configuration Panel */}
368
- <Box sx={{
369
- width: 400,
370
- borderRight: '1px solid #ddd',
371
- bgcolor: '#fafafa',
372
- overflow: 'auto'
373
- }}>
374
- {renderAIConfiguration()}
375
- </Box>
376
-
377
- {/* Diagram */}
378
- <Box sx={{ flex: 1 }}>
379
- <DiagrammingPage
380
- ref={diagramRef}
381
- diagramType="automation"
382
- defaultNodes={nodes}
383
- defaultEdges={edges}
384
- availableFunctions={[]}
385
- id={1}
386
- />
387
- </Box>
388
- </Box>
389
- );
390
- };
391
-
392
- export default AIModelConfigurationPanel;
393
- ```
394
-
395
- ## Integration Steps for Your Team Member
396
-
397
- 1. **Install the updated library** with the new node data management API
398
- 2. **Create a ref** to the DiagrammingPage component
399
- 3. **Monitor node selection** to detect when a node is selected
400
- 4. **Read node data** using `getNodeData(nodeId)` method
401
- 5. **Create configuration UI** based on the node type and data structure
402
- 6. **Update node data** using `updateNodeData(nodeId, newData)` method
403
- 7. **Handle success/error states** appropriately
404
-
405
- ## Key Benefits
406
-
407
- - **Real-time Updates**: Changes are immediately reflected in the diagram
408
- - **Type Safety**: Structured data interfaces for different node types
409
- - **Flexible Configuration**: Support for any node data structure
410
- - **History Integration**: Node data changes are tracked in undo/redo
411
- - **Selection Awareness**: Know which node is currently selected
412
- - **Error Handling**: Methods return success/failure status
413
-
414
- ## Common Use Cases
415
-
416
- 1. **AI Model Configuration**: Update model, tokens, temperature, instructions
417
- 2. **API Configuration**: Modify endpoints, headers, authentication
418
- 3. **Workflow Settings**: Change trigger types, schedules, conditions
419
- 4. **Data Formatting**: Update formatting rules, templates, variables
420
- 5. **Authentication**: Manage API keys, tokens, credentials
421
- 6. **Execution Parameters**: Modify timeouts, retry counts, error handling
422
-
423
- ## Notes
424
-
425
- - Node data updates are immediately reflected in the diagram
426
- - Changes are tracked in the undo/redo history
427
- - The API supports partial updates (only changed fields need to be provided)
428
- - Node selection changes are detected automatically
429
- - The system handles invalid node IDs gracefully
430
- - All node types are supported with their specific data structures
1
+ # Node Data Update API Documentation
2
+
3
+ ## Overview
4
+
5
+ The diagramming library provides comprehensive node data management functionality that allows external applications to read and update node configurations dynamically. This is particularly useful for automation diagrams where nodes contain configuration data like API endpoints, AI model settings, authentication keys, and other execution parameters.
6
+
7
+ ## How Node Data Management Works
8
+
9
+ ### Internal Implementation
10
+
11
+ 1. **Node Data Storage**: Each node contains a `data` property that holds its configuration
12
+ 2. **State Management**: Node data is managed through the Zustand store
13
+ 3. **Real-time Updates**: Changes are immediately reflected in the diagram
14
+ 4. **History Tracking**: Node data changes are tracked in the undo/redo system
15
+
16
+ ### Key Components
17
+
18
+ - **DiagrammingPageRef**: Exposes node data management methods
19
+ - **Node Data Types**: Structured interfaces for different node types
20
+ - **Update Methods**: Functions to modify node data externally
21
+
22
+ ## External Node Data Control
23
+
24
+ ### Method 1: Using Ref-based API (Recommended)
25
+
26
+ The `DiagrammingPage` component exposes node data management through a ref:
27
+
28
+ ```typescript
29
+ import React, { useRef, useState, useEffect } from 'react';
30
+ import { DiagrammingPage, DiagrammingPageRef } from '@flowuent-labs/diagrams';
31
+
32
+ const MyComponent = () => {
33
+ const diagramRef = useRef<DiagrammingPageRef>(null);
34
+ const [selectedNodeId, setSelectedNodeId] = useState<string | null>(null);
35
+ const [nodeData, setNodeData] = useState<any>(null);
36
+
37
+ // Monitor node selection changes
38
+ useEffect(() => {
39
+ const interval = setInterval(() => {
40
+ if (diagramRef.current) {
41
+ const currentSelected = diagramRef.current.getSelectedNode();
42
+ if (currentSelected !== selectedNodeId) {
43
+ setSelectedNodeId(currentSelected);
44
+ if (currentSelected) {
45
+ const data = diagramRef.current.getNodeData(currentSelected);
46
+ setNodeData(data);
47
+ }
48
+ }
49
+ }
50
+ }, 100);
51
+
52
+ return () => clearInterval(interval);
53
+ }, [selectedNodeId]);
54
+
55
+ const handleUpdateNode = (newData: any) => {
56
+ if (selectedNodeId && diagramRef.current) {
57
+ const success = diagramRef.current.updateNodeData(selectedNodeId, newData);
58
+ if (success) {
59
+ console.log('Node updated successfully');
60
+ }
61
+ }
62
+ };
63
+
64
+ return (
65
+ <div>
66
+ {/* Your external configuration panel */}
67
+ <YourConfigurationPanel
68
+ nodeData={nodeData}
69
+ onUpdate={handleUpdateNode}
70
+ />
71
+
72
+ {/* The diagram */}
73
+ <DiagrammingPage
74
+ ref={diagramRef}
75
+ diagramType="automation"
76
+ defaultNodes={nodes}
77
+ defaultEdges={edges}
78
+ availableFunctions={[]}
79
+ id={1}
80
+ />
81
+ </div>
82
+ );
83
+ };
84
+ ```
85
+
86
+ ### Available Methods
87
+
88
+ The `DiagrammingPageRef` interface provides these node data management methods:
89
+
90
+ ```typescript
91
+ interface DiagrammingPageRef {
92
+ // Undo/Redo methods (from previous API)
93
+ undo: () => void;
94
+ redo: () => void;
95
+ canUndo: () => boolean;
96
+ canRedo: () => boolean;
97
+ reset: () => void;
98
+ getHistoryLength: () => number;
99
+ getHistoryIndex: () => number;
100
+
101
+ // Node data management methods
102
+ getNodeData: (nodeId: string) => any | null; // Get node data by ID
103
+ updateNodeData: (nodeId: string, data: any) => boolean; // Update node data
104
+ getSelectedNode: () => string | null; // Get currently selected node ID
105
+ getNodes: () => any[]; // Get all nodes
106
+ getEdges: () => any[]; // Get all edges
107
+ }
108
+ ```
109
+
110
+ ## Node Data Structure Examples
111
+
112
+ ### Automation API Node
113
+ ```typescript
114
+ interface AutomationApiNodeData {
115
+ label: string;
116
+ description: string;
117
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE';
118
+ url: string;
119
+ headers: Array<{
120
+ key: string;
121
+ value: string;
122
+ enabled: boolean;
123
+ }>;
124
+ queryParams: Array<{
125
+ key: string;
126
+ value: string;
127
+ enabled: boolean;
128
+ }>;
129
+ body?: string;
130
+ timeout: number;
131
+ retryCount: number;
132
+ // ... other API-specific fields
133
+ }
134
+ ```
135
+
136
+ ### Automation AI Formatting Node
137
+ ```typescript
138
+ interface AutomationFormattingNodeData {
139
+ label: string;
140
+ description: string;
141
+ formattingType: 'basic' | 'ai-powered' | 'template';
142
+ aiConfig?: {
143
+ apiUrl: string;
144
+ apiKey: string;
145
+ model: string; // e.g., "GPT-5 Thinking mini"
146
+ instruction: string;
147
+ temperature: number; // e.g., 0.95
148
+ maxTokens?: number; // e.g., 2048
149
+ systemPrompt?: string;
150
+ };
151
+ outputVariable: string;
152
+ outputDataType: 'String' | 'Object' | 'Array';
153
+ // ... other formatting-specific fields
154
+ }
155
+ ```
156
+
157
+ ### Automation Start Node
158
+ ```typescript
159
+ interface AutomationStartNodeData {
160
+ label: string;
161
+ description: string;
162
+ triggerType: 'manual' | 'scheduled' | 'event';
163
+ scheduleConfig?: {
164
+ frequency: 'hourly' | 'daily' | 'weekly' | 'monthly';
165
+ time?: string;
166
+ cron?: string;
167
+ timezone?: string;
168
+ };
169
+ eventConfig?: {
170
+ webhookUrl?: string;
171
+ eventType?: string;
172
+ filters?: Array<{
173
+ key: string;
174
+ value: string;
175
+ operator: 'equals' | 'contains' | 'startsWith' | 'endsWith';
176
+ }>;
177
+ };
178
+ // ... other start-specific fields
179
+ }
180
+ ```
181
+
182
+ ## Complete Example: AI Model Configuration Panel
183
+
184
+ Here's a complete example showing how to create an external configuration panel for AI model settings:
185
+
186
+ ```typescript
187
+ import React, { useRef, useState, useEffect } from 'react';
188
+ import {
189
+ Box,
190
+ Typography,
191
+ TextField,
192
+ Button,
193
+ Card,
194
+ CardContent,
195
+ Grid,
196
+ Select,
197
+ MenuItem,
198
+ FormControl,
199
+ InputLabel,
200
+ Chip,
201
+ Alert
202
+ } from '@mui/material';
203
+ import { DiagrammingPage, DiagrammingPageRef } from '@flowuent-labs/diagrams';
204
+
205
+ const AIModelConfigurationPanel: React.FC = () => {
206
+ const diagramRef = useRef<DiagrammingPageRef>(null);
207
+ const [selectedNodeId, setSelectedNodeId] = useState<string | null>(null);
208
+ const [nodeData, setNodeData] = useState<any>(null);
209
+ const [formData, setFormData] = useState<any>({});
210
+ const [updateStatus, setUpdateStatus] = useState<'idle' | 'success' | 'error'>('idle');
211
+
212
+ // Monitor node selection changes
213
+ useEffect(() => {
214
+ const interval = setInterval(() => {
215
+ if (diagramRef.current) {
216
+ const currentSelected = diagramRef.current.getSelectedNode();
217
+ if (currentSelected !== selectedNodeId) {
218
+ setSelectedNodeId(currentSelected);
219
+ if (currentSelected) {
220
+ const data = diagramRef.current.getNodeData(currentSelected);
221
+ setNodeData(data);
222
+ setFormData(data || {});
223
+ }
224
+ }
225
+ }
226
+ }, 100);
227
+
228
+ return () => clearInterval(interval);
229
+ }, [selectedNodeId]);
230
+
231
+ const handleFormChange = (field: string, value: any) => {
232
+ setFormData(prev => ({
233
+ ...prev,
234
+ [field]: value
235
+ }));
236
+ };
237
+
238
+ const handleUpdateNode = () => {
239
+ if (!selectedNodeId || !diagramRef.current) return;
240
+
241
+ const success = diagramRef.current.updateNodeData(selectedNodeId, formData);
242
+ if (success) {
243
+ setUpdateStatus('success');
244
+ setTimeout(() => setUpdateStatus('idle'), 2000);
245
+ } else {
246
+ setUpdateStatus('error');
247
+ setTimeout(() => setUpdateStatus('idle'), 2000);
248
+ }
249
+ };
250
+
251
+ const renderAIConfiguration = () => {
252
+ if (!selectedNodeId || !nodeData) {
253
+ return (
254
+ <Card>
255
+ <CardContent>
256
+ <Typography variant="h6" color="text.secondary">
257
+ Select an AI Formatting node to configure
258
+ </Typography>
259
+ </CardContent>
260
+ </Card>
261
+ );
262
+ }
263
+
264
+ return (
265
+ <Card>
266
+ <CardContent>
267
+ <Typography variant="h6" gutterBottom>
268
+ AI Model Configuration
269
+ </Typography>
270
+
271
+ <Chip
272
+ label={`Node ID: ${selectedNodeId}`}
273
+ size="small"
274
+ sx={{ mb: 2 }}
275
+ />
276
+
277
+ {updateStatus === 'success' && (
278
+ <Alert severity="success" sx={{ mb: 2 }}>
279
+ Configuration updated successfully!
280
+ </Alert>
281
+ )}
282
+
283
+ <Grid container spacing={2}>
284
+ <Grid item xs={12}>
285
+ <TextField
286
+ fullWidth
287
+ label="Model"
288
+ value={formData.aiConfig?.model || ''}
289
+ onChange={(e) => handleFormChange('aiConfig', {
290
+ ...formData.aiConfig,
291
+ model: e.target.value
292
+ })}
293
+ />
294
+ </Grid>
295
+
296
+ <Grid item xs={6}>
297
+ <TextField
298
+ fullWidth
299
+ label="Max Tokens"
300
+ type="number"
301
+ value={formData.aiConfig?.maxTokens || 2048}
302
+ onChange={(e) => handleFormChange('aiConfig', {
303
+ ...formData.aiConfig,
304
+ maxTokens: parseInt(e.target.value)
305
+ })}
306
+ />
307
+ </Grid>
308
+
309
+ <Grid item xs={6}>
310
+ <TextField
311
+ fullWidth
312
+ label="Temperature"
313
+ type="number"
314
+ step="0.1"
315
+ value={formData.aiConfig?.temperature || 0.95}
316
+ onChange={(e) => handleFormChange('aiConfig', {
317
+ ...formData.aiConfig,
318
+ temperature: parseFloat(e.target.value)
319
+ })}
320
+ />
321
+ </Grid>
322
+
323
+ <Grid item xs={12}>
324
+ <TextField
325
+ fullWidth
326
+ label="Instruction"
327
+ multiline
328
+ rows={3}
329
+ value={formData.aiConfig?.instruction || ''}
330
+ onChange={(e) => handleFormChange('aiConfig', {
331
+ ...formData.aiConfig,
332
+ instruction: e.target.value
333
+ })}
334
+ />
335
+ </Grid>
336
+
337
+ <Grid item xs={12}>
338
+ <TextField
339
+ fullWidth
340
+ label="API Key"
341
+ type="password"
342
+ value={formData.aiConfig?.apiKey || ''}
343
+ onChange={(e) => handleFormChange('aiConfig', {
344
+ ...formData.aiConfig,
345
+ apiKey: e.target.value
346
+ })}
347
+ />
348
+ </Grid>
349
+ </Grid>
350
+
351
+ <Box sx={{ mt: 3 }}>
352
+ <Button
353
+ variant="contained"
354
+ onClick={handleUpdateNode}
355
+ fullWidth
356
+ >
357
+ Update Configuration
358
+ </Button>
359
+ </Box>
360
+ </CardContent>
361
+ </Card>
362
+ );
363
+ };
364
+
365
+ return (
366
+ <Box sx={{ height: '100vh', display: 'flex' }}>
367
+ {/* Configuration Panel */}
368
+ <Box sx={{
369
+ width: 400,
370
+ borderRight: '1px solid #ddd',
371
+ bgcolor: '#fafafa',
372
+ overflow: 'auto'
373
+ }}>
374
+ {renderAIConfiguration()}
375
+ </Box>
376
+
377
+ {/* Diagram */}
378
+ <Box sx={{ flex: 1 }}>
379
+ <DiagrammingPage
380
+ ref={diagramRef}
381
+ diagramType="automation"
382
+ defaultNodes={nodes}
383
+ defaultEdges={edges}
384
+ availableFunctions={[]}
385
+ id={1}
386
+ />
387
+ </Box>
388
+ </Box>
389
+ );
390
+ };
391
+
392
+ export default AIModelConfigurationPanel;
393
+ ```
394
+
395
+ ## Integration Steps for Your Team Member
396
+
397
+ 1. **Install the updated library** with the new node data management API
398
+ 2. **Create a ref** to the DiagrammingPage component
399
+ 3. **Monitor node selection** to detect when a node is selected
400
+ 4. **Read node data** using `getNodeData(nodeId)` method
401
+ 5. **Create configuration UI** based on the node type and data structure
402
+ 6. **Update node data** using `updateNodeData(nodeId, newData)` method
403
+ 7. **Handle success/error states** appropriately
404
+
405
+ ## Key Benefits
406
+
407
+ - **Real-time Updates**: Changes are immediately reflected in the diagram
408
+ - **Type Safety**: Structured data interfaces for different node types
409
+ - **Flexible Configuration**: Support for any node data structure
410
+ - **History Integration**: Node data changes are tracked in undo/redo
411
+ - **Selection Awareness**: Know which node is currently selected
412
+ - **Error Handling**: Methods return success/failure status
413
+
414
+ ## Common Use Cases
415
+
416
+ 1. **AI Model Configuration**: Update model, tokens, temperature, instructions
417
+ 2. **API Configuration**: Modify endpoints, headers, authentication
418
+ 3. **Workflow Settings**: Change trigger types, schedules, conditions
419
+ 4. **Data Formatting**: Update formatting rules, templates, variables
420
+ 5. **Authentication**: Manage API keys, tokens, credentials
421
+ 6. **Execution Parameters**: Modify timeouts, retry counts, error handling
422
+
423
+ ## Notes
424
+
425
+ - Node data updates are immediately reflected in the diagram
426
+ - Changes are tracked in the undo/redo history
427
+ - The API supports partial updates (only changed fields need to be provided)
428
+ - Node selection changes are detected automatically
429
+ - The system handles invalid node IDs gracefully
430
+ - All node types are supported with their specific data structures