@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.
- package/TRANSLATION_FIX_SUMMARY.md +118 -0
- package/apps/diagramming/src/DiagramTabs.tsx +205 -205
- package/apps/diagramming/src/sample-workflow-content.ts +55 -54
- package/package.json +116 -116
- package/packages/diagrams/I18N_SETUP.md +126 -0
- package/packages/diagrams/NODE_DATA_UPDATE_API.md +430 -430
- package/packages/diagrams/README.md +443 -3
- package/packages/diagrams/UNDO_REDO_API.md +306 -306
- package/packages/diagrams/locales/en/translation.json +713 -0
- package/packages/diagrams/package.json +5 -23
- package/packages/diagrams/pnpm-lock.yaml +2606 -0
- package/packages/diagrams/project.json +42 -38
- package/packages/diagrams/rollup.config.js +5 -10
- package/packages/diagrams/src/index.ts +116 -113
- package/packages/diagrams/src/lib/atoms/CardEditableTitle.tsx +76 -76
- package/packages/diagrams/src/lib/components/automation/AutomationApiNode.tsx +24 -3
- package/packages/diagrams/src/lib/components/automation/AutomationEndNode.tsx +23 -2
- package/packages/diagrams/src/lib/components/automation/AutomationFormattingNode.tsx +24 -3
- package/packages/diagrams/src/lib/components/automation/AutomationStartNode.tsx +24 -3
- package/packages/diagrams/src/lib/contexts/onWorkflowNodeDelete.ts +1 -1
- package/packages/diagrams/src/lib/i18n.ts +42 -0
- package/packages/diagrams/src/lib/organisms/CustomEdge/useCreateBendPoint.tsx +121 -119
- package/packages/diagrams/src/lib/organisms/WorkFlowNode/NodeActionButtons.tsx +1 -1
- package/packages/diagrams/src/lib/templates/node-forms/CallForm.tsx +370 -370
- package/packages/diagrams/src/lib/types/node-types.ts +29 -29
- package/packages/diagrams/src/lib/utils/AutomationExecutionEngine.ts +1168 -1162
- package/packages/diagrams/tsconfig.lib.json +1 -3
- package/tsconfig.base.json +1 -1
|
@@ -1,306 +1,306 @@
|
|
|
1
|
-
# Undo/Redo API Documentation
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
The diagramming library provides comprehensive undo/redo functionality for all diagram types, including automation diagrams. This document explains how to expose and use undo/redo controls externally when using the library.
|
|
6
|
-
|
|
7
|
-
## How Undo/Redo Works
|
|
8
|
-
|
|
9
|
-
### Internal Implementation
|
|
10
|
-
|
|
11
|
-
1. **History Management**: The system maintains a `history` array and `historyIndex` in the DiagramStore
|
|
12
|
-
2. **Change Tracking**: Every change to nodes/edges is tracked and stored as `HistoryEvent` objects
|
|
13
|
-
3. **State Restoration**: Changes are applied in reverse (undo) or forward (redo) direction
|
|
14
|
-
4. **Keyboard Shortcuts**: Ctrl+Z (undo) and Ctrl+Y/Cmd+Shift+Z (redo) work automatically
|
|
15
|
-
|
|
16
|
-
### Key Components
|
|
17
|
-
|
|
18
|
-
- **DiagramProvider**: Contains the main store with `undo()` and `redo()` methods
|
|
19
|
-
- **History System**: Tracks all changes with forward/backward operations
|
|
20
|
-
- **DownloadPanel**: Built-in undo/redo buttons (can be hidden)
|
|
21
|
-
|
|
22
|
-
## External Undo/Redo Control
|
|
23
|
-
|
|
24
|
-
### Method 1: Using Ref-based API (Recommended)
|
|
25
|
-
|
|
26
|
-
The `DiagrammingPage` component now supports a ref that exposes undo/redo functionality:
|
|
27
|
-
|
|
28
|
-
```typescript
|
|
29
|
-
import React, { useRef } from 'react';
|
|
30
|
-
import { DiagrammingPage, DiagrammingPageRef } from '@flowuent-
|
|
31
|
-
|
|
32
|
-
const MyComponent = () => {
|
|
33
|
-
const diagramRef = useRef<DiagrammingPageRef>(null);
|
|
34
|
-
|
|
35
|
-
const handleUndo = () => {
|
|
36
|
-
if (diagramRef.current?.canUndo()) {
|
|
37
|
-
diagramRef.current.undo();
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const handleRedo = () => {
|
|
42
|
-
if (diagramRef.current?.canRedo()) {
|
|
43
|
-
diagramRef.current.redo();
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
return (
|
|
48
|
-
<div>
|
|
49
|
-
{/* Your external undo/redo buttons */}
|
|
50
|
-
<button onClick={handleUndo} disabled={!diagramRef.current?.canUndo()}>
|
|
51
|
-
Undo
|
|
52
|
-
</button>
|
|
53
|
-
<button onClick={handleRedo} disabled={!diagramRef.current?.canRedo()}>
|
|
54
|
-
Redo
|
|
55
|
-
</button>
|
|
56
|
-
|
|
57
|
-
{/* The diagram */}
|
|
58
|
-
<DiagrammingPage
|
|
59
|
-
ref={diagramRef}
|
|
60
|
-
diagramType="automation"
|
|
61
|
-
defaultNodes={nodes}
|
|
62
|
-
defaultEdges={edges}
|
|
63
|
-
availableFunctions={[]}
|
|
64
|
-
id={1}
|
|
65
|
-
/>
|
|
66
|
-
</div>
|
|
67
|
-
);
|
|
68
|
-
};
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### Available Methods
|
|
72
|
-
|
|
73
|
-
The `DiagrammingPageRef` interface provides these methods:
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
interface DiagrammingPageRef {
|
|
77
|
-
undo: () => void; // Perform undo operation
|
|
78
|
-
redo: () => void; // Perform redo operation
|
|
79
|
-
canUndo: () => boolean; // Check if undo is available
|
|
80
|
-
canRedo: () => boolean; // Check if redo is available
|
|
81
|
-
reset: () => void; // Clear the diagram
|
|
82
|
-
getHistoryLength: () => number; // Get total history length
|
|
83
|
-
getHistoryIndex: () => number; // Get current history index
|
|
84
|
-
}
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### Method 2: Using DownloadPanel with Hidden Built-in Controls
|
|
88
|
-
|
|
89
|
-
You can hide the built-in undo/redo buttons and use your own:
|
|
90
|
-
|
|
91
|
-
```typescript
|
|
92
|
-
import { DiagrammingPage, DownloadPanel } from '@flowuent-
|
|
93
|
-
|
|
94
|
-
const MyComponent = () => {
|
|
95
|
-
return (
|
|
96
|
-
<DiagrammingPage
|
|
97
|
-
diagramType="automation"
|
|
98
|
-
defaultNodes={nodes}
|
|
99
|
-
defaultEdges={edges}
|
|
100
|
-
availableFunctions={[]}
|
|
101
|
-
id={1}
|
|
102
|
-
>
|
|
103
|
-
{/* Hide built-in undo/redo buttons */}
|
|
104
|
-
<DownloadPanel
|
|
105
|
-
hideUndo={true}
|
|
106
|
-
hideRedo={true}
|
|
107
|
-
position="top-left"
|
|
108
|
-
/>
|
|
109
|
-
|
|
110
|
-
{/* Your custom controls */}
|
|
111
|
-
<YourCustomControls />
|
|
112
|
-
</DiagrammingPage>
|
|
113
|
-
);
|
|
114
|
-
};
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
## Complete Example
|
|
118
|
-
|
|
119
|
-
Here's a complete example showing how to implement external undo/redo controls:
|
|
120
|
-
|
|
121
|
-
```typescript
|
|
122
|
-
import React, { useRef, useState, useEffect } from 'react';
|
|
123
|
-
import { Button, Box, Typography, IconButton } from '@mui/material';
|
|
124
|
-
import { UndoIcon, RedoIcon, ClearIcon } from '@mui/icons-material';
|
|
125
|
-
import { DiagrammingPage, DiagrammingPageRef } from '@flowuent-
|
|
126
|
-
import { ICardNode } from '@flowuent-
|
|
127
|
-
import { Edge } from '@xyflow/react';
|
|
128
|
-
|
|
129
|
-
const AutomationDiagramWithExternalControls: React.FC = () => {
|
|
130
|
-
const diagramRef = useRef<DiagrammingPageRef>(null);
|
|
131
|
-
const [canUndo, setCanUndo] = useState(false);
|
|
132
|
-
const [canRedo, setCanRedo] = useState(false);
|
|
133
|
-
const [historyInfo, setHistoryInfo] = useState({ index: 0, length: 0 });
|
|
134
|
-
|
|
135
|
-
// Sample automation diagram data
|
|
136
|
-
const defaultNodes: ICardNode[] = [
|
|
137
|
-
{
|
|
138
|
-
id: '1',
|
|
139
|
-
type: 'AutomationStartNode',
|
|
140
|
-
position: { x: 100, y: 100 },
|
|
141
|
-
data: { label: 'Start Process' }
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
id: '2',
|
|
145
|
-
type: 'AutomationApiNode',
|
|
146
|
-
position: { x: 300, y: 100 },
|
|
147
|
-
data: { label: 'API Call' }
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
id: '3',
|
|
151
|
-
type: 'AutomationEndNode',
|
|
152
|
-
position: { x: 500, y: 100 },
|
|
153
|
-
data: { label: 'End Process' }
|
|
154
|
-
}
|
|
155
|
-
];
|
|
156
|
-
|
|
157
|
-
const defaultEdges: Edge[] = [
|
|
158
|
-
{ id: 'e1-2', source: '1', target: '2' },
|
|
159
|
-
{ id: 'e2-3', source: '2', target: '3' }
|
|
160
|
-
];
|
|
161
|
-
|
|
162
|
-
const updateButtonStates = () => {
|
|
163
|
-
if (diagramRef.current) {
|
|
164
|
-
setCanUndo(diagramRef.current.canUndo());
|
|
165
|
-
setCanRedo(diagramRef.current.canRedo());
|
|
166
|
-
setHistoryInfo({
|
|
167
|
-
index: diagramRef.current.getHistoryIndex(),
|
|
168
|
-
length: diagramRef.current.getHistoryLength()
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
const handleUndo = () => {
|
|
174
|
-
if (diagramRef.current?.canUndo()) {
|
|
175
|
-
diagramRef.current.undo();
|
|
176
|
-
updateButtonStates();
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
const handleRedo = () => {
|
|
181
|
-
if (diagramRef.current?.canRedo()) {
|
|
182
|
-
diagramRef.current.redo();
|
|
183
|
-
updateButtonStates();
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
const handleReset = () => {
|
|
188
|
-
diagramRef.current?.reset();
|
|
189
|
-
updateButtonStates();
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
// Update button states when diagram changes
|
|
193
|
-
useEffect(() => {
|
|
194
|
-
const interval = setInterval(updateButtonStates, 100);
|
|
195
|
-
return () => clearInterval(interval);
|
|
196
|
-
}, []);
|
|
197
|
-
|
|
198
|
-
return (
|
|
199
|
-
<Box sx={{ height: '100vh', display: 'flex', flexDirection: 'column' }}>
|
|
200
|
-
{/* External Controls Toolbar */}
|
|
201
|
-
<Box sx={{
|
|
202
|
-
p: 2,
|
|
203
|
-
bgcolor: '#f5f5f5',
|
|
204
|
-
borderBottom: '1px solid #ddd',
|
|
205
|
-
display: 'flex',
|
|
206
|
-
gap: 2,
|
|
207
|
-
alignItems: 'center',
|
|
208
|
-
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
|
|
209
|
-
}}>
|
|
210
|
-
<Typography variant="h6" sx={{ fontWeight: 'bold' }}>
|
|
211
|
-
Automation Diagram Controls
|
|
212
|
-
</Typography>
|
|
213
|
-
|
|
214
|
-
<Box sx={{ display: 'flex', gap: 1, ml: 2 }}>
|
|
215
|
-
<IconButton
|
|
216
|
-
onClick={handleUndo}
|
|
217
|
-
disabled={!canUndo}
|
|
218
|
-
sx={{
|
|
219
|
-
bgcolor: canUndo ? '#1976d2' : '#e0e0e0',
|
|
220
|
-
color: canUndo ? 'white' : '#9e9e9e',
|
|
221
|
-
'&:hover': {
|
|
222
|
-
bgcolor: canUndo ? '#1565c0' : '#e0e0e0'
|
|
223
|
-
}
|
|
224
|
-
}}
|
|
225
|
-
>
|
|
226
|
-
<UndoIcon />
|
|
227
|
-
</IconButton>
|
|
228
|
-
|
|
229
|
-
<IconButton
|
|
230
|
-
onClick={handleRedo}
|
|
231
|
-
disabled={!canRedo}
|
|
232
|
-
sx={{
|
|
233
|
-
bgcolor: canRedo ? '#1976d2' : '#e0e0e0',
|
|
234
|
-
color: canRedo ? 'white' : '#9e9e9e',
|
|
235
|
-
'&:hover': {
|
|
236
|
-
bgcolor: canRedo ? '#1565c0' : '#e0e0e0'
|
|
237
|
-
}
|
|
238
|
-
}}
|
|
239
|
-
>
|
|
240
|
-
<RedoIcon />
|
|
241
|
-
</IconButton>
|
|
242
|
-
|
|
243
|
-
<IconButton
|
|
244
|
-
onClick={handleReset}
|
|
245
|
-
sx={{
|
|
246
|
-
bgcolor: '#d32f2f',
|
|
247
|
-
color: 'white',
|
|
248
|
-
'&:hover': {
|
|
249
|
-
bgcolor: '#c62828'
|
|
250
|
-
}
|
|
251
|
-
}}
|
|
252
|
-
>
|
|
253
|
-
<ClearIcon />
|
|
254
|
-
</IconButton>
|
|
255
|
-
</Box>
|
|
256
|
-
|
|
257
|
-
<Typography variant="body2" sx={{ ml: 'auto', color: '#666' }}>
|
|
258
|
-
History: {historyInfo.index} / {historyInfo.length}
|
|
259
|
-
</Typography>
|
|
260
|
-
</Box>
|
|
261
|
-
|
|
262
|
-
{/* Diagram */}
|
|
263
|
-
<Box sx={{ flex: 1 }}>
|
|
264
|
-
<DiagrammingPage
|
|
265
|
-
ref={diagramRef}
|
|
266
|
-
diagramType="automation"
|
|
267
|
-
defaultNodes={defaultNodes}
|
|
268
|
-
defaultEdges={defaultEdges}
|
|
269
|
-
availableFunctions={[]}
|
|
270
|
-
id={1}
|
|
271
|
-
onChange={() => {
|
|
272
|
-
// Update button states when diagram changes
|
|
273
|
-
setTimeout(updateButtonStates, 100);
|
|
274
|
-
}}
|
|
275
|
-
/>
|
|
276
|
-
</Box>
|
|
277
|
-
</Box>
|
|
278
|
-
);
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
export default AutomationDiagramWithExternalControls;
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
## Integration Steps for Your Team Member
|
|
285
|
-
|
|
286
|
-
1. **Install the updated library** with the new ref-based API
|
|
287
|
-
2. **Create a ref** to the DiagrammingPage component
|
|
288
|
-
3. **Add external buttons** that call the ref methods
|
|
289
|
-
4. **Handle state updates** to enable/disable buttons appropriately
|
|
290
|
-
5. **Test the functionality** with various diagram operations
|
|
291
|
-
|
|
292
|
-
## Key Benefits
|
|
293
|
-
|
|
294
|
-
- **Full Control**: Complete control over undo/redo UI and behavior
|
|
295
|
-
- **State Awareness**: Know when undo/redo is available
|
|
296
|
-
- **History Information**: Access to history length and current index
|
|
297
|
-
- **Keyboard Support**: Built-in keyboard shortcuts still work
|
|
298
|
-
- **Flexible Integration**: Works with any UI framework or custom components
|
|
299
|
-
|
|
300
|
-
## Notes
|
|
301
|
-
|
|
302
|
-
- The undo/redo functionality works automatically for all diagram types
|
|
303
|
-
- History is maintained per diagram instance
|
|
304
|
-
- Changes are tracked for node/edge additions, deletions, modifications, and movements
|
|
305
|
-
- The system prevents infinite loops and handles edge cases gracefully
|
|
306
|
-
- Keyboard shortcuts (Ctrl+Z, Ctrl+Y) work alongside external controls
|
|
1
|
+
# Undo/Redo API Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The diagramming library provides comprehensive undo/redo functionality for all diagram types, including automation diagrams. This document explains how to expose and use undo/redo controls externally when using the library.
|
|
6
|
+
|
|
7
|
+
## How Undo/Redo Works
|
|
8
|
+
|
|
9
|
+
### Internal Implementation
|
|
10
|
+
|
|
11
|
+
1. **History Management**: The system maintains a `history` array and `historyIndex` in the DiagramStore
|
|
12
|
+
2. **Change Tracking**: Every change to nodes/edges is tracked and stored as `HistoryEvent` objects
|
|
13
|
+
3. **State Restoration**: Changes are applied in reverse (undo) or forward (redo) direction
|
|
14
|
+
4. **Keyboard Shortcuts**: Ctrl+Z (undo) and Ctrl+Y/Cmd+Shift+Z (redo) work automatically
|
|
15
|
+
|
|
16
|
+
### Key Components
|
|
17
|
+
|
|
18
|
+
- **DiagramProvider**: Contains the main store with `undo()` and `redo()` methods
|
|
19
|
+
- **History System**: Tracks all changes with forward/backward operations
|
|
20
|
+
- **DownloadPanel**: Built-in undo/redo buttons (can be hidden)
|
|
21
|
+
|
|
22
|
+
## External Undo/Redo Control
|
|
23
|
+
|
|
24
|
+
### Method 1: Using Ref-based API (Recommended)
|
|
25
|
+
|
|
26
|
+
The `DiagrammingPage` component now supports a ref that exposes undo/redo functionality:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import React, { useRef } from 'react';
|
|
30
|
+
import { DiagrammingPage, DiagrammingPageRef } from '@flowuent-labs/diagrams';
|
|
31
|
+
|
|
32
|
+
const MyComponent = () => {
|
|
33
|
+
const diagramRef = useRef<DiagrammingPageRef>(null);
|
|
34
|
+
|
|
35
|
+
const handleUndo = () => {
|
|
36
|
+
if (diagramRef.current?.canUndo()) {
|
|
37
|
+
diagramRef.current.undo();
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const handleRedo = () => {
|
|
42
|
+
if (diagramRef.current?.canRedo()) {
|
|
43
|
+
diagramRef.current.redo();
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div>
|
|
49
|
+
{/* Your external undo/redo buttons */}
|
|
50
|
+
<button onClick={handleUndo} disabled={!diagramRef.current?.canUndo()}>
|
|
51
|
+
Undo
|
|
52
|
+
</button>
|
|
53
|
+
<button onClick={handleRedo} disabled={!diagramRef.current?.canRedo()}>
|
|
54
|
+
Redo
|
|
55
|
+
</button>
|
|
56
|
+
|
|
57
|
+
{/* The diagram */}
|
|
58
|
+
<DiagrammingPage
|
|
59
|
+
ref={diagramRef}
|
|
60
|
+
diagramType="automation"
|
|
61
|
+
defaultNodes={nodes}
|
|
62
|
+
defaultEdges={edges}
|
|
63
|
+
availableFunctions={[]}
|
|
64
|
+
id={1}
|
|
65
|
+
/>
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Available Methods
|
|
72
|
+
|
|
73
|
+
The `DiagrammingPageRef` interface provides these methods:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
interface DiagrammingPageRef {
|
|
77
|
+
undo: () => void; // Perform undo operation
|
|
78
|
+
redo: () => void; // Perform redo operation
|
|
79
|
+
canUndo: () => boolean; // Check if undo is available
|
|
80
|
+
canRedo: () => boolean; // Check if redo is available
|
|
81
|
+
reset: () => void; // Clear the diagram
|
|
82
|
+
getHistoryLength: () => number; // Get total history length
|
|
83
|
+
getHistoryIndex: () => number; // Get current history index
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Method 2: Using DownloadPanel with Hidden Built-in Controls
|
|
88
|
+
|
|
89
|
+
You can hide the built-in undo/redo buttons and use your own:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { DiagrammingPage, DownloadPanel } from '@flowuent-labs/diagrams';
|
|
93
|
+
|
|
94
|
+
const MyComponent = () => {
|
|
95
|
+
return (
|
|
96
|
+
<DiagrammingPage
|
|
97
|
+
diagramType="automation"
|
|
98
|
+
defaultNodes={nodes}
|
|
99
|
+
defaultEdges={edges}
|
|
100
|
+
availableFunctions={[]}
|
|
101
|
+
id={1}
|
|
102
|
+
>
|
|
103
|
+
{/* Hide built-in undo/redo buttons */}
|
|
104
|
+
<DownloadPanel
|
|
105
|
+
hideUndo={true}
|
|
106
|
+
hideRedo={true}
|
|
107
|
+
position="top-left"
|
|
108
|
+
/>
|
|
109
|
+
|
|
110
|
+
{/* Your custom controls */}
|
|
111
|
+
<YourCustomControls />
|
|
112
|
+
</DiagrammingPage>
|
|
113
|
+
);
|
|
114
|
+
};
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Complete Example
|
|
118
|
+
|
|
119
|
+
Here's a complete example showing how to implement external undo/redo controls:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import React, { useRef, useState, useEffect } from 'react';
|
|
123
|
+
import { Button, Box, Typography, IconButton } from '@mui/material';
|
|
124
|
+
import { UndoIcon, RedoIcon, ClearIcon } from '@mui/icons-material';
|
|
125
|
+
import { DiagrammingPage, DiagrammingPageRef } from '@flowuent-labs/diagrams';
|
|
126
|
+
import { ICardNode } from '@flowuent-labs/diagrams';
|
|
127
|
+
import { Edge } from '@xyflow/react';
|
|
128
|
+
|
|
129
|
+
const AutomationDiagramWithExternalControls: React.FC = () => {
|
|
130
|
+
const diagramRef = useRef<DiagrammingPageRef>(null);
|
|
131
|
+
const [canUndo, setCanUndo] = useState(false);
|
|
132
|
+
const [canRedo, setCanRedo] = useState(false);
|
|
133
|
+
const [historyInfo, setHistoryInfo] = useState({ index: 0, length: 0 });
|
|
134
|
+
|
|
135
|
+
// Sample automation diagram data
|
|
136
|
+
const defaultNodes: ICardNode[] = [
|
|
137
|
+
{
|
|
138
|
+
id: '1',
|
|
139
|
+
type: 'AutomationStartNode',
|
|
140
|
+
position: { x: 100, y: 100 },
|
|
141
|
+
data: { label: 'Start Process' }
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
id: '2',
|
|
145
|
+
type: 'AutomationApiNode',
|
|
146
|
+
position: { x: 300, y: 100 },
|
|
147
|
+
data: { label: 'API Call' }
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
id: '3',
|
|
151
|
+
type: 'AutomationEndNode',
|
|
152
|
+
position: { x: 500, y: 100 },
|
|
153
|
+
data: { label: 'End Process' }
|
|
154
|
+
}
|
|
155
|
+
];
|
|
156
|
+
|
|
157
|
+
const defaultEdges: Edge[] = [
|
|
158
|
+
{ id: 'e1-2', source: '1', target: '2' },
|
|
159
|
+
{ id: 'e2-3', source: '2', target: '3' }
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
const updateButtonStates = () => {
|
|
163
|
+
if (diagramRef.current) {
|
|
164
|
+
setCanUndo(diagramRef.current.canUndo());
|
|
165
|
+
setCanRedo(diagramRef.current.canRedo());
|
|
166
|
+
setHistoryInfo({
|
|
167
|
+
index: diagramRef.current.getHistoryIndex(),
|
|
168
|
+
length: diagramRef.current.getHistoryLength()
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const handleUndo = () => {
|
|
174
|
+
if (diagramRef.current?.canUndo()) {
|
|
175
|
+
diagramRef.current.undo();
|
|
176
|
+
updateButtonStates();
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const handleRedo = () => {
|
|
181
|
+
if (diagramRef.current?.canRedo()) {
|
|
182
|
+
diagramRef.current.redo();
|
|
183
|
+
updateButtonStates();
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const handleReset = () => {
|
|
188
|
+
diagramRef.current?.reset();
|
|
189
|
+
updateButtonStates();
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// Update button states when diagram changes
|
|
193
|
+
useEffect(() => {
|
|
194
|
+
const interval = setInterval(updateButtonStates, 100);
|
|
195
|
+
return () => clearInterval(interval);
|
|
196
|
+
}, []);
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<Box sx={{ height: '100vh', display: 'flex', flexDirection: 'column' }}>
|
|
200
|
+
{/* External Controls Toolbar */}
|
|
201
|
+
<Box sx={{
|
|
202
|
+
p: 2,
|
|
203
|
+
bgcolor: '#f5f5f5',
|
|
204
|
+
borderBottom: '1px solid #ddd',
|
|
205
|
+
display: 'flex',
|
|
206
|
+
gap: 2,
|
|
207
|
+
alignItems: 'center',
|
|
208
|
+
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
|
|
209
|
+
}}>
|
|
210
|
+
<Typography variant="h6" sx={{ fontWeight: 'bold' }}>
|
|
211
|
+
Automation Diagram Controls
|
|
212
|
+
</Typography>
|
|
213
|
+
|
|
214
|
+
<Box sx={{ display: 'flex', gap: 1, ml: 2 }}>
|
|
215
|
+
<IconButton
|
|
216
|
+
onClick={handleUndo}
|
|
217
|
+
disabled={!canUndo}
|
|
218
|
+
sx={{
|
|
219
|
+
bgcolor: canUndo ? '#1976d2' : '#e0e0e0',
|
|
220
|
+
color: canUndo ? 'white' : '#9e9e9e',
|
|
221
|
+
'&:hover': {
|
|
222
|
+
bgcolor: canUndo ? '#1565c0' : '#e0e0e0'
|
|
223
|
+
}
|
|
224
|
+
}}
|
|
225
|
+
>
|
|
226
|
+
<UndoIcon />
|
|
227
|
+
</IconButton>
|
|
228
|
+
|
|
229
|
+
<IconButton
|
|
230
|
+
onClick={handleRedo}
|
|
231
|
+
disabled={!canRedo}
|
|
232
|
+
sx={{
|
|
233
|
+
bgcolor: canRedo ? '#1976d2' : '#e0e0e0',
|
|
234
|
+
color: canRedo ? 'white' : '#9e9e9e',
|
|
235
|
+
'&:hover': {
|
|
236
|
+
bgcolor: canRedo ? '#1565c0' : '#e0e0e0'
|
|
237
|
+
}
|
|
238
|
+
}}
|
|
239
|
+
>
|
|
240
|
+
<RedoIcon />
|
|
241
|
+
</IconButton>
|
|
242
|
+
|
|
243
|
+
<IconButton
|
|
244
|
+
onClick={handleReset}
|
|
245
|
+
sx={{
|
|
246
|
+
bgcolor: '#d32f2f',
|
|
247
|
+
color: 'white',
|
|
248
|
+
'&:hover': {
|
|
249
|
+
bgcolor: '#c62828'
|
|
250
|
+
}
|
|
251
|
+
}}
|
|
252
|
+
>
|
|
253
|
+
<ClearIcon />
|
|
254
|
+
</IconButton>
|
|
255
|
+
</Box>
|
|
256
|
+
|
|
257
|
+
<Typography variant="body2" sx={{ ml: 'auto', color: '#666' }}>
|
|
258
|
+
History: {historyInfo.index} / {historyInfo.length}
|
|
259
|
+
</Typography>
|
|
260
|
+
</Box>
|
|
261
|
+
|
|
262
|
+
{/* Diagram */}
|
|
263
|
+
<Box sx={{ flex: 1 }}>
|
|
264
|
+
<DiagrammingPage
|
|
265
|
+
ref={diagramRef}
|
|
266
|
+
diagramType="automation"
|
|
267
|
+
defaultNodes={defaultNodes}
|
|
268
|
+
defaultEdges={defaultEdges}
|
|
269
|
+
availableFunctions={[]}
|
|
270
|
+
id={1}
|
|
271
|
+
onChange={() => {
|
|
272
|
+
// Update button states when diagram changes
|
|
273
|
+
setTimeout(updateButtonStates, 100);
|
|
274
|
+
}}
|
|
275
|
+
/>
|
|
276
|
+
</Box>
|
|
277
|
+
</Box>
|
|
278
|
+
);
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
export default AutomationDiagramWithExternalControls;
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Integration Steps for Your Team Member
|
|
285
|
+
|
|
286
|
+
1. **Install the updated library** with the new ref-based API
|
|
287
|
+
2. **Create a ref** to the DiagrammingPage component
|
|
288
|
+
3. **Add external buttons** that call the ref methods
|
|
289
|
+
4. **Handle state updates** to enable/disable buttons appropriately
|
|
290
|
+
5. **Test the functionality** with various diagram operations
|
|
291
|
+
|
|
292
|
+
## Key Benefits
|
|
293
|
+
|
|
294
|
+
- **Full Control**: Complete control over undo/redo UI and behavior
|
|
295
|
+
- **State Awareness**: Know when undo/redo is available
|
|
296
|
+
- **History Information**: Access to history length and current index
|
|
297
|
+
- **Keyboard Support**: Built-in keyboard shortcuts still work
|
|
298
|
+
- **Flexible Integration**: Works with any UI framework or custom components
|
|
299
|
+
|
|
300
|
+
## Notes
|
|
301
|
+
|
|
302
|
+
- The undo/redo functionality works automatically for all diagram types
|
|
303
|
+
- History is maintained per diagram instance
|
|
304
|
+
- Changes are tracked for node/edge additions, deletions, modifications, and movements
|
|
305
|
+
- The system prevents infinite loops and handles edge cases gracefully
|
|
306
|
+
- Keyboard shortcuts (Ctrl+Z, Ctrl+Y) work alongside external controls
|