@flowuent-org/diagramming-core 1.3.8 → 1.3.10
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/apps/diagramming/src/AutomationDiagramData.ts +46 -0
- package/package.json +1 -1
- package/packages/diagrams/src/lib/components/automation/AutomationApiNode.tsx +2 -0
- package/packages/diagrams/src/lib/components/automation/AutomationEmailNode.tsx +773 -0
- package/packages/diagrams/src/lib/components/automation/AutomationFormattingNode.tsx +19 -3
- package/packages/diagrams/src/lib/components/automation/AutomationGoogleServicesNode.tsx +8 -6
- package/packages/diagrams/src/lib/components/automation/AutomationInteractionNode.tsx +8 -6
- package/packages/diagrams/src/lib/components/automation/AutomationMonitoringNode.tsx +6 -8
- package/packages/diagrams/src/lib/components/automation/AutomationNavigationNode.tsx +14 -2
- package/packages/diagrams/src/lib/components/automation/AutomationSheetsNode.tsx +17 -0
- package/packages/diagrams/src/lib/components/automation/AutomationSlackNode.tsx +34 -12
- package/packages/diagrams/src/lib/components/automation/AutomationTelegramNode.tsx +34 -12
- package/packages/diagrams/src/lib/components/automation/index.ts +8 -0
- package/packages/diagrams/src/lib/types/node-types.ts +3 -0
- package/packages/molecules/src/lib/SvgIcons/icons.tsx +14 -14
|
@@ -749,6 +749,52 @@ export const automationDefaultNodes = [
|
|
|
749
749
|
measured: { width: 300, height: 200 },
|
|
750
750
|
},
|
|
751
751
|
// =====================================
|
|
752
|
+
// Email Node
|
|
753
|
+
// =====================================
|
|
754
|
+
{
|
|
755
|
+
id: 'email-node',
|
|
756
|
+
type: 'AutomationEmailNode',
|
|
757
|
+
position: { x: 2200, y: 450 },
|
|
758
|
+
data: {
|
|
759
|
+
label: 'Send Email',
|
|
760
|
+
description: 'Send an email notification',
|
|
761
|
+
operationType: 'send-email',
|
|
762
|
+
status: 'Ready',
|
|
763
|
+
parameters: {
|
|
764
|
+
to: ['recipient@example.com'],
|
|
765
|
+
cc: [],
|
|
766
|
+
bcc: [],
|
|
767
|
+
subject: 'Workflow Notification',
|
|
768
|
+
body: 'Your workflow has completed successfully!',
|
|
769
|
+
htmlBody: '',
|
|
770
|
+
attachments: [],
|
|
771
|
+
emailAccessToken: '',
|
|
772
|
+
emailTokenExpiresAt: undefined,
|
|
773
|
+
emailProvider: 'smtp',
|
|
774
|
+
emailAddress: '',
|
|
775
|
+
},
|
|
776
|
+
emailAuth: {
|
|
777
|
+
provider: 'smtp',
|
|
778
|
+
isAuthenticated: false,
|
|
779
|
+
isLoading: false,
|
|
780
|
+
email: '',
|
|
781
|
+
},
|
|
782
|
+
formData: {
|
|
783
|
+
nodeId: 'email-node',
|
|
784
|
+
title: 'Send Email',
|
|
785
|
+
type: 'email',
|
|
786
|
+
operationType: 'send-email',
|
|
787
|
+
to: ['recipient@example.com'],
|
|
788
|
+
subject: 'Workflow Notification',
|
|
789
|
+
body: 'Your workflow has completed successfully!',
|
|
790
|
+
},
|
|
791
|
+
lastRun: 'Never',
|
|
792
|
+
},
|
|
793
|
+
width: 300,
|
|
794
|
+
height: 200,
|
|
795
|
+
measured: { width: 300, height: 200 },
|
|
796
|
+
},
|
|
797
|
+
// =====================================
|
|
752
798
|
// Interaction Node
|
|
753
799
|
// =====================================
|
|
754
800
|
{
|
package/package.json
CHANGED
|
@@ -336,11 +336,13 @@ export const AutomationApiNode: React.FC<AutomationApiNodeProps> = ({ data, sele
|
|
|
336
336
|
sx={{
|
|
337
337
|
width: '32px',
|
|
338
338
|
height: '32px',
|
|
339
|
+
minWidth: '32px',
|
|
339
340
|
backgroundColor: '#1E3A8A',
|
|
340
341
|
borderRadius: '50%',
|
|
341
342
|
display: 'flex',
|
|
342
343
|
alignItems: 'center',
|
|
343
344
|
justifyContent: 'center',
|
|
345
|
+
flexShrink: 0,
|
|
344
346
|
}}
|
|
345
347
|
>
|
|
346
348
|
<ApiNodeIcon/>
|
|
@@ -0,0 +1,773 @@
|
|
|
1
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
2
|
+
import { createRoot } from 'react-dom/client';
|
|
3
|
+
import { Handle, Position, useNodeId } from '@xyflow/react';
|
|
4
|
+
import {
|
|
5
|
+
Box,
|
|
6
|
+
Typography,
|
|
7
|
+
Chip,
|
|
8
|
+
IconButton,
|
|
9
|
+
Card,
|
|
10
|
+
CardContent,
|
|
11
|
+
Button,
|
|
12
|
+
CircularProgress,
|
|
13
|
+
Tooltip,
|
|
14
|
+
LinearProgress,
|
|
15
|
+
} from '@mui/material';
|
|
16
|
+
import {
|
|
17
|
+
Email as EmailIcon,
|
|
18
|
+
Send as SendIcon,
|
|
19
|
+
AttachFile as AttachFileIcon,
|
|
20
|
+
AccessTime as AccessTimeIcon,
|
|
21
|
+
} from '@mui/icons-material';
|
|
22
|
+
import { RiCloseLine } from 'react-icons/ri';
|
|
23
|
+
import ReactJson from 'react-json-view';
|
|
24
|
+
import { useTranslation } from 'react-i18next';
|
|
25
|
+
import { useDiagram } from '../../contexts/DiagramProvider';
|
|
26
|
+
import { useSearch } from '../../contexts/SearchContext';
|
|
27
|
+
import { NodeActionButtons } from './NodeActionButtons';
|
|
28
|
+
import { showNodeAIAssistantPopup } from './NodeAIAssistantPopup';
|
|
29
|
+
import { getStatusColor } from './statusColors';
|
|
30
|
+
|
|
31
|
+
// ========================
|
|
32
|
+
// Types
|
|
33
|
+
// ========================
|
|
34
|
+
|
|
35
|
+
export type EmailOperationType =
|
|
36
|
+
| 'send-email'
|
|
37
|
+
| 'send-with-attachment'
|
|
38
|
+
| 'send-template'
|
|
39
|
+
| 'send-bulk'
|
|
40
|
+
| 'reply-to-email'
|
|
41
|
+
| 'forward-email';
|
|
42
|
+
|
|
43
|
+
export interface EmailTokenData {
|
|
44
|
+
accessToken: string;
|
|
45
|
+
expiresAt?: number;
|
|
46
|
+
email?: string;
|
|
47
|
+
provider?: 'smtp' | 'gmail' | 'outlook' | 'sendgrid' | 'mailgun';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface AutomationEmailNodeData {
|
|
51
|
+
label: string;
|
|
52
|
+
description: string;
|
|
53
|
+
operationType?: EmailOperationType;
|
|
54
|
+
status: 'Ready' | 'Running' | 'Completed' | 'Failed' | 'Need to Config' | 'authenticated';
|
|
55
|
+
parameters?: {
|
|
56
|
+
// Email operations
|
|
57
|
+
to?: string[];
|
|
58
|
+
cc?: string[];
|
|
59
|
+
bcc?: string[];
|
|
60
|
+
subject?: string;
|
|
61
|
+
body?: string;
|
|
62
|
+
htmlBody?: string;
|
|
63
|
+
attachments?: Array<{
|
|
64
|
+
filename: string;
|
|
65
|
+
content: string;
|
|
66
|
+
contentType?: string;
|
|
67
|
+
}>;
|
|
68
|
+
|
|
69
|
+
// Template operations
|
|
70
|
+
templateId?: string;
|
|
71
|
+
templateVariables?: Record<string, any>;
|
|
72
|
+
|
|
73
|
+
// Bulk operations
|
|
74
|
+
recipients?: Array<{
|
|
75
|
+
email: string;
|
|
76
|
+
variables?: Record<string, any>;
|
|
77
|
+
}>;
|
|
78
|
+
|
|
79
|
+
// Reply/Forward operations
|
|
80
|
+
replyTo?: string;
|
|
81
|
+
inReplyTo?: string;
|
|
82
|
+
forwardTo?: string[];
|
|
83
|
+
|
|
84
|
+
// Token data
|
|
85
|
+
emailAccessToken?: string;
|
|
86
|
+
emailTokenExpiresAt?: number;
|
|
87
|
+
emailProvider?: string;
|
|
88
|
+
emailAddress?: string;
|
|
89
|
+
|
|
90
|
+
[key: string]: any;
|
|
91
|
+
};
|
|
92
|
+
emailAuth?: {
|
|
93
|
+
provider?: string;
|
|
94
|
+
isAuthenticated?: boolean;
|
|
95
|
+
isLoading?: boolean;
|
|
96
|
+
email?: string;
|
|
97
|
+
};
|
|
98
|
+
formData?: {
|
|
99
|
+
nodeId?: string;
|
|
100
|
+
title?: string;
|
|
101
|
+
type?: string;
|
|
102
|
+
operationType?: string;
|
|
103
|
+
[key: string]: any;
|
|
104
|
+
};
|
|
105
|
+
lastRun?: string;
|
|
106
|
+
duration?: string;
|
|
107
|
+
executionResult?: {
|
|
108
|
+
success: boolean;
|
|
109
|
+
data?: any;
|
|
110
|
+
error?: string;
|
|
111
|
+
};
|
|
112
|
+
onEmailLogin?: () => void;
|
|
113
|
+
onEmailDisconnect?: () => void;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface AutomationEmailNodeProps {
|
|
117
|
+
data: AutomationEmailNodeData;
|
|
118
|
+
selected?: boolean;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ========================
|
|
122
|
+
// Operation Configuration
|
|
123
|
+
// ========================
|
|
124
|
+
|
|
125
|
+
const OPERATION_CONFIG: Record<
|
|
126
|
+
EmailOperationType,
|
|
127
|
+
{
|
|
128
|
+
icon: React.ElementType;
|
|
129
|
+
label: string;
|
|
130
|
+
color: string;
|
|
131
|
+
description: string;
|
|
132
|
+
}
|
|
133
|
+
> = {
|
|
134
|
+
'send-email': {
|
|
135
|
+
icon: SendIcon,
|
|
136
|
+
label: 'Send Email',
|
|
137
|
+
color: '#4285F4',
|
|
138
|
+
description: 'Send a simple email',
|
|
139
|
+
},
|
|
140
|
+
'send-with-attachment': {
|
|
141
|
+
icon: AttachFileIcon,
|
|
142
|
+
label: 'Send with Attachment',
|
|
143
|
+
color: '#34A853',
|
|
144
|
+
description: 'Send an email with file attachments',
|
|
145
|
+
},
|
|
146
|
+
'send-template': {
|
|
147
|
+
icon: EmailIcon,
|
|
148
|
+
label: 'Send Template',
|
|
149
|
+
color: '#FBBC04',
|
|
150
|
+
description: 'Send an email using a template',
|
|
151
|
+
},
|
|
152
|
+
'send-bulk': {
|
|
153
|
+
icon: EmailIcon,
|
|
154
|
+
label: 'Send Bulk',
|
|
155
|
+
color: '#EA4335',
|
|
156
|
+
description: 'Send bulk emails to multiple recipients',
|
|
157
|
+
},
|
|
158
|
+
'reply-to-email': {
|
|
159
|
+
icon: EmailIcon,
|
|
160
|
+
label: 'Reply to Email',
|
|
161
|
+
color: '#4285F4',
|
|
162
|
+
description: 'Reply to an existing email',
|
|
163
|
+
},
|
|
164
|
+
'forward-email': {
|
|
165
|
+
icon: EmailIcon,
|
|
166
|
+
label: 'Forward Email',
|
|
167
|
+
color: '#34A853',
|
|
168
|
+
description: 'Forward an email to recipients',
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// ========================
|
|
173
|
+
// Helper Functions
|
|
174
|
+
// ========================
|
|
175
|
+
|
|
176
|
+
const isTokenExpired = (expiresAt?: number): boolean => {
|
|
177
|
+
if (!expiresAt) return false;
|
|
178
|
+
return Date.now() > expiresAt;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const getTimeUntilExpiry = (expiresAt?: number): string => {
|
|
182
|
+
if (!expiresAt) return 'No expiry';
|
|
183
|
+
const diff = expiresAt - Date.now();
|
|
184
|
+
if (diff <= 0) return 'Expired';
|
|
185
|
+
const minutes = Math.floor(diff / 60000);
|
|
186
|
+
if (minutes < 60) return `${minutes}m`;
|
|
187
|
+
const hours = Math.floor(minutes / 60);
|
|
188
|
+
return `${hours}h ${minutes % 60}m`;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
// ========================
|
|
192
|
+
// Main Component
|
|
193
|
+
// ========================
|
|
194
|
+
|
|
195
|
+
export const AutomationEmailNode: React.FC<AutomationEmailNodeProps> = ({
|
|
196
|
+
data,
|
|
197
|
+
selected,
|
|
198
|
+
}) => {
|
|
199
|
+
const { t } = useTranslation();
|
|
200
|
+
const { highlightText } = useSearch();
|
|
201
|
+
const [isJsonOpen, setIsJsonOpen] = useState(false);
|
|
202
|
+
const rootRef = useRef<any>(null);
|
|
203
|
+
const portalRef = useRef<HTMLDivElement | null>(null);
|
|
204
|
+
const nodeRef = useRef<HTMLDivElement | null>(null);
|
|
205
|
+
const nodeId = useNodeId();
|
|
206
|
+
const setSelectedNode = useDiagram((state) => state.setSelectedNode);
|
|
207
|
+
const enableJson = useDiagram((state) => state.enableNodeJsonPopover ?? true);
|
|
208
|
+
const onNodesChange = useDiagram((state) => state.onNodesChange);
|
|
209
|
+
const nodes = useDiagram((state) => state.nodes);
|
|
210
|
+
const setNodes = useDiagram((state) => state.setNodes);
|
|
211
|
+
|
|
212
|
+
// Get operation configuration
|
|
213
|
+
const operationTypeRaw = data.operationType || data.formData?.operationType || 'send-email';
|
|
214
|
+
const operationType = (Object.keys(OPERATION_CONFIG).includes(operationTypeRaw) ? operationTypeRaw : 'send-email') as EmailOperationType;
|
|
215
|
+
const operationConfig = OPERATION_CONFIG[operationType];
|
|
216
|
+
const OperationIcon = operationConfig.icon;
|
|
217
|
+
|
|
218
|
+
// Auth state
|
|
219
|
+
const isAuthenticated = data.emailAuth?.isAuthenticated || !!data.parameters?.emailAccessToken;
|
|
220
|
+
const isAuthLoading = data.emailAuth?.isLoading || false;
|
|
221
|
+
const emailAddress = data.emailAuth?.email || data.parameters?.emailAddress;
|
|
222
|
+
const tokenExpired = isTokenExpired(data.parameters?.emailTokenExpiresAt);
|
|
223
|
+
|
|
224
|
+
// Execution state
|
|
225
|
+
const status = data.status || 'Ready';
|
|
226
|
+
const executionProgress = status === 'Running' ? 50 : 0;
|
|
227
|
+
|
|
228
|
+
// Status configuration - using centralized status colors
|
|
229
|
+
const statusConfig = getStatusColor(status, status === 'authenticated' ? 'authenticated' : 'ready');
|
|
230
|
+
|
|
231
|
+
// Handle JSON view
|
|
232
|
+
const handleJsonClick = () => {
|
|
233
|
+
if (nodeId) setSelectedNode(nodeId);
|
|
234
|
+
if (!enableJson) return;
|
|
235
|
+
setIsJsonOpen(!isJsonOpen);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
const handleClose = () => {
|
|
239
|
+
setIsJsonOpen(false);
|
|
240
|
+
// Clean up portal
|
|
241
|
+
if (rootRef.current) {
|
|
242
|
+
rootRef.current.unmount();
|
|
243
|
+
rootRef.current = null;
|
|
244
|
+
}
|
|
245
|
+
if (portalRef.current) {
|
|
246
|
+
document.body.removeChild(portalRef.current);
|
|
247
|
+
portalRef.current = null;
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
// Render email auth button
|
|
252
|
+
const renderEmailAuthButton = () => {
|
|
253
|
+
if (isAuthenticated && !tokenExpired) {
|
|
254
|
+
return (
|
|
255
|
+
<Button
|
|
256
|
+
onClick={data.onEmailDisconnect}
|
|
257
|
+
disabled={isAuthLoading}
|
|
258
|
+
fullWidth
|
|
259
|
+
sx={{
|
|
260
|
+
backgroundColor: '#4285F4',
|
|
261
|
+
borderRadius: '8px',
|
|
262
|
+
padding: '8px 12px',
|
|
263
|
+
gap: '8px',
|
|
264
|
+
color: '#FFFFFF',
|
|
265
|
+
textTransform: 'none',
|
|
266
|
+
fontSize: '13px',
|
|
267
|
+
fontWeight: 500,
|
|
268
|
+
'&:hover': {
|
|
269
|
+
backgroundColor: '#357ae8',
|
|
270
|
+
},
|
|
271
|
+
}}
|
|
272
|
+
>
|
|
273
|
+
<EmailIcon sx={{ fontSize: 18 }} />
|
|
274
|
+
{emailAddress ? emailAddress : 'Connected'}
|
|
275
|
+
</Button>
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return (
|
|
280
|
+
<Button
|
|
281
|
+
onClick={data.onEmailLogin}
|
|
282
|
+
disabled={isAuthLoading}
|
|
283
|
+
fullWidth
|
|
284
|
+
sx={{
|
|
285
|
+
backgroundColor: '#171C29',
|
|
286
|
+
border: '1px solid #374151',
|
|
287
|
+
borderRadius: '8px',
|
|
288
|
+
padding: '8px 12px',
|
|
289
|
+
gap: '8px',
|
|
290
|
+
color: '#B2BCD8',
|
|
291
|
+
textTransform: 'none',
|
|
292
|
+
fontSize: '13px',
|
|
293
|
+
fontWeight: 500,
|
|
294
|
+
'&:hover': {
|
|
295
|
+
backgroundColor: '#1F2937',
|
|
296
|
+
borderColor: '#4285F4',
|
|
297
|
+
},
|
|
298
|
+
'&:disabled': {
|
|
299
|
+
opacity: 0.6,
|
|
300
|
+
},
|
|
301
|
+
}}
|
|
302
|
+
>
|
|
303
|
+
{isAuthLoading ? (
|
|
304
|
+
<>
|
|
305
|
+
<CircularProgress size={16} sx={{ color: '#B2BCD8' }} />
|
|
306
|
+
Connecting...
|
|
307
|
+
</>
|
|
308
|
+
) : (
|
|
309
|
+
<>
|
|
310
|
+
<EmailIcon sx={{ fontSize: 18 }} />
|
|
311
|
+
Connect Email
|
|
312
|
+
</>
|
|
313
|
+
)}
|
|
314
|
+
</Button>
|
|
315
|
+
);
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
// Render status badge
|
|
319
|
+
const renderStatusBadge = () => {
|
|
320
|
+
return (
|
|
321
|
+
<Chip
|
|
322
|
+
label={status}
|
|
323
|
+
size="small"
|
|
324
|
+
sx={{
|
|
325
|
+
backgroundColor: statusConfig.bgColor,
|
|
326
|
+
color: statusConfig.color,
|
|
327
|
+
fontWeight: 500,
|
|
328
|
+
fontSize: '11px',
|
|
329
|
+
height: '22px',
|
|
330
|
+
borderRadius: '11px',
|
|
331
|
+
}}
|
|
332
|
+
/>
|
|
333
|
+
);
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
useEffect(() => {
|
|
337
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
338
|
+
if (isJsonOpen && !(event.target as Element).closest('#automation-json-popover')) {
|
|
339
|
+
handleClose();
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
343
|
+
return () => {
|
|
344
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
345
|
+
};
|
|
346
|
+
}, [isJsonOpen]);
|
|
347
|
+
|
|
348
|
+
useEffect(() => {
|
|
349
|
+
if (isJsonOpen) {
|
|
350
|
+
const portalRoot = document.createElement('div');
|
|
351
|
+
document.body.appendChild(portalRoot);
|
|
352
|
+
portalRef.current = portalRoot;
|
|
353
|
+
|
|
354
|
+
const root = createRoot(portalRoot);
|
|
355
|
+
rootRef.current = root;
|
|
356
|
+
|
|
357
|
+
root.render(
|
|
358
|
+
<Card
|
|
359
|
+
id="automation-json-popover"
|
|
360
|
+
sx={{
|
|
361
|
+
position: 'fixed',
|
|
362
|
+
top: 0,
|
|
363
|
+
right: 0,
|
|
364
|
+
zIndex: 9999,
|
|
365
|
+
width: '400px',
|
|
366
|
+
height: '100vh',
|
|
367
|
+
overflow: 'auto',
|
|
368
|
+
bgcolor: '#242424',
|
|
369
|
+
color: '#fff',
|
|
370
|
+
border: '1px solid #333',
|
|
371
|
+
'&::-webkit-scrollbar': {
|
|
372
|
+
width: '6px',
|
|
373
|
+
},
|
|
374
|
+
'&::-webkit-scrollbar-track': {
|
|
375
|
+
background: 'transparent',
|
|
376
|
+
},
|
|
377
|
+
'&::-webkit-scrollbar-thumb': {
|
|
378
|
+
background: '#444',
|
|
379
|
+
borderRadius: '3px',
|
|
380
|
+
'&:hover': {
|
|
381
|
+
background: '#666',
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
}}
|
|
385
|
+
>
|
|
386
|
+
<CardContent sx={{ bgcolor: '#242424', color: '#fff' }}>
|
|
387
|
+
<IconButton
|
|
388
|
+
aria-label="close"
|
|
389
|
+
onClick={handleClose}
|
|
390
|
+
sx={{
|
|
391
|
+
color: '#999',
|
|
392
|
+
'&:hover': {
|
|
393
|
+
color: '#fff',
|
|
394
|
+
bgcolor: 'rgba(255, 255, 255, 0.1)',
|
|
395
|
+
},
|
|
396
|
+
}}
|
|
397
|
+
>
|
|
398
|
+
<RiCloseLine />
|
|
399
|
+
</IconButton>
|
|
400
|
+
{/* Show execution result prominently if available */}
|
|
401
|
+
{data.formData?.executionResult && (
|
|
402
|
+
<Box sx={{ mb: 2 }}>
|
|
403
|
+
<Typography variant="h6" sx={{ color: '#fff', mb: 1 }}>
|
|
404
|
+
{t('automation.common.executionResult')}
|
|
405
|
+
</Typography>
|
|
406
|
+
<Box sx={{
|
|
407
|
+
bgcolor: data.formData.executionResult.success ? '#1e3a8a' : '#dc2626',
|
|
408
|
+
p: 1,
|
|
409
|
+
borderRadius: 1,
|
|
410
|
+
mb: 1
|
|
411
|
+
}}>
|
|
412
|
+
<Typography variant="body2" sx={{ color: '#fff' }}>
|
|
413
|
+
{t('automation.common.status')}: {data.formData.executionResult.success ? t('automation.common.success') : t('automation.common.failed')}
|
|
414
|
+
</Typography>
|
|
415
|
+
<Typography variant="body2" sx={{ color: '#fff' }}>
|
|
416
|
+
{t('automation.common.timestamp')}: {new Date(data.formData.executionResult.timestamp).toLocaleString()}
|
|
417
|
+
</Typography>
|
|
418
|
+
{data.formData.executionResult.error && (
|
|
419
|
+
<Typography variant="body2" sx={{ color: '#fff' }}>
|
|
420
|
+
{t('automation.common.error')}: {data.formData.executionResult.error}
|
|
421
|
+
</Typography>
|
|
422
|
+
)}
|
|
423
|
+
</Box>
|
|
424
|
+
<Typography variant="h6" sx={{ color: '#fff', mb: 1 }}>
|
|
425
|
+
{t('automation.emailNode.executionData')}
|
|
426
|
+
</Typography>
|
|
427
|
+
<ReactJson
|
|
428
|
+
theme={'monokai'}
|
|
429
|
+
src={data.formData.executionResult.data}
|
|
430
|
+
collapsed={false}
|
|
431
|
+
/>
|
|
432
|
+
</Box>
|
|
433
|
+
)}
|
|
434
|
+
|
|
435
|
+
{/* Show full node data */}
|
|
436
|
+
<Typography variant="h6" sx={{ color: '#fff', mb: 1 }}>
|
|
437
|
+
{t('automation.common.fullNodeData')}
|
|
438
|
+
</Typography>
|
|
439
|
+
<ReactJson theme={'monokai'} src={data.formData || data} collapsed={false} />
|
|
440
|
+
</CardContent>
|
|
441
|
+
</Card>
|
|
442
|
+
);
|
|
443
|
+
} else {
|
|
444
|
+
// Clean up when closing
|
|
445
|
+
if (rootRef.current) {
|
|
446
|
+
rootRef.current.unmount();
|
|
447
|
+
rootRef.current = null;
|
|
448
|
+
}
|
|
449
|
+
if (portalRef.current) {
|
|
450
|
+
document.body.removeChild(portalRef.current);
|
|
451
|
+
portalRef.current = null;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}, [isJsonOpen, data]);
|
|
455
|
+
|
|
456
|
+
// ========================
|
|
457
|
+
// Render
|
|
458
|
+
// ========================
|
|
459
|
+
return (
|
|
460
|
+
<Box
|
|
461
|
+
sx={{
|
|
462
|
+
position: 'relative',
|
|
463
|
+
width: '336px',
|
|
464
|
+
overflow: 'visible',
|
|
465
|
+
}}
|
|
466
|
+
>
|
|
467
|
+
<Box
|
|
468
|
+
ref={nodeRef}
|
|
469
|
+
sx={{
|
|
470
|
+
width: '336px',
|
|
471
|
+
minHeight: '150px',
|
|
472
|
+
backgroundColor: '#181C25',
|
|
473
|
+
border: selected ? '2px solid #3b82f6' : '1px solid #1e293b',
|
|
474
|
+
borderRadius: '12px',
|
|
475
|
+
color: '#ffffff',
|
|
476
|
+
position: 'relative',
|
|
477
|
+
boxShadow: selected ? '0 0 0 2px rgba(59, 130, 246, 0.5)' : '0 4px 8px rgba(0, 0, 0, 0.3)',
|
|
478
|
+
transition: 'all 0.2s ease',
|
|
479
|
+
cursor: 'pointer',
|
|
480
|
+
overflow: 'hidden',
|
|
481
|
+
...(status === 'Running' && {
|
|
482
|
+
animation: 'pulse-glow 2s ease-in-out infinite',
|
|
483
|
+
'@keyframes pulse-glow': {
|
|
484
|
+
'0%, 100%': {
|
|
485
|
+
boxShadow: '0 0 20px rgba(59, 130, 246, 0.4), 0 0 40px rgba(59, 130, 246, 0.2)',
|
|
486
|
+
borderColor: 'rgba(59, 130, 246, 0.6)',
|
|
487
|
+
},
|
|
488
|
+
'50%': {
|
|
489
|
+
boxShadow: '0 0 30px rgba(59, 130, 246, 0.6), 0 0 60px rgba(59, 130, 246, 0.3)',
|
|
490
|
+
borderColor: 'rgba(59, 130, 246, 0.9)',
|
|
491
|
+
},
|
|
492
|
+
},
|
|
493
|
+
}),
|
|
494
|
+
}}
|
|
495
|
+
onClick={handleJsonClick}
|
|
496
|
+
>
|
|
497
|
+
{/* Top Header Section */}
|
|
498
|
+
<Box sx={{
|
|
499
|
+
backgroundColor: "rgba(67, 93, 132, 0.1)",
|
|
500
|
+
padding: '8px 16px',
|
|
501
|
+
borderRadius: '12px 12px 0 0'
|
|
502
|
+
}}>
|
|
503
|
+
<Typography variant="body2" sx={{
|
|
504
|
+
color: '#ffffff',
|
|
505
|
+
fontSize: '12px',
|
|
506
|
+
fontWeight: 500
|
|
507
|
+
}}>
|
|
508
|
+
{highlightText(data.description || operationConfig.description)}
|
|
509
|
+
</Typography>
|
|
510
|
+
</Box>
|
|
511
|
+
|
|
512
|
+
{/* Main Content */}
|
|
513
|
+
<Box sx={{ padding: '16px' }}>
|
|
514
|
+
{/* Title Section */}
|
|
515
|
+
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 2 }}>
|
|
516
|
+
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
|
|
517
|
+
<Box
|
|
518
|
+
sx={{
|
|
519
|
+
width: '32px',
|
|
520
|
+
height: '32px',
|
|
521
|
+
backgroundColor: '#0ea5e9',
|
|
522
|
+
borderRadius: '50%',
|
|
523
|
+
display: 'flex',
|
|
524
|
+
alignItems: 'center',
|
|
525
|
+
justifyContent: 'center',
|
|
526
|
+
}}
|
|
527
|
+
>
|
|
528
|
+
<EmailIcon sx={{ fontSize: 18, color: '#FFFFFF' }} />
|
|
529
|
+
</Box>
|
|
530
|
+
<Typography variant="h6" sx={{ fontWeight: 600, fontSize: '16px' }}>
|
|
531
|
+
{highlightText(data.label || operationConfig.label)}
|
|
532
|
+
</Typography>
|
|
533
|
+
</Box>
|
|
534
|
+
<Chip
|
|
535
|
+
label={status}
|
|
536
|
+
size="small"
|
|
537
|
+
sx={{
|
|
538
|
+
backgroundColor: statusConfig.bgColor,
|
|
539
|
+
color: statusConfig.color,
|
|
540
|
+
fontWeight: 500,
|
|
541
|
+
fontSize: '12px',
|
|
542
|
+
height: '24px',
|
|
543
|
+
borderRadius: '12px',
|
|
544
|
+
}}
|
|
545
|
+
/>
|
|
546
|
+
</Box>
|
|
547
|
+
|
|
548
|
+
{/* Description Box */}
|
|
549
|
+
<Box sx={{
|
|
550
|
+
backgroundColor: '#1F2937',
|
|
551
|
+
borderRadius: '8px',
|
|
552
|
+
padding: '12px',
|
|
553
|
+
mb: 2,
|
|
554
|
+
border: '1px solid #374151'
|
|
555
|
+
}}>
|
|
556
|
+
{/* Inner text boundary box */}
|
|
557
|
+
<Box sx={{
|
|
558
|
+
backgroundColor: 'transparent',
|
|
559
|
+
borderRadius: '4px',
|
|
560
|
+
padding: '8px',
|
|
561
|
+
border: '1px solid #4B5563',
|
|
562
|
+
minHeight: '40px',
|
|
563
|
+
display: 'flex',
|
|
564
|
+
alignItems: 'center'
|
|
565
|
+
}}>
|
|
566
|
+
<Typography variant="body2" sx={{
|
|
567
|
+
color: '#9CA3AF',
|
|
568
|
+
fontSize: '12px',
|
|
569
|
+
lineHeight: 1.4,
|
|
570
|
+
margin: 0
|
|
571
|
+
}}>
|
|
572
|
+
{data.description || operationConfig.description}
|
|
573
|
+
</Typography>
|
|
574
|
+
</Box>
|
|
575
|
+
</Box>
|
|
576
|
+
|
|
577
|
+
{/* Email Auth Button */}
|
|
578
|
+
{renderEmailAuthButton()}
|
|
579
|
+
|
|
580
|
+
{/* Operation-specific Parameters Display */}
|
|
581
|
+
{(operationType === 'send-email' && (data.parameters?.to || data.parameters?.subject)) && (
|
|
582
|
+
<Box sx={{ mt: 2, mb: 1 }}>
|
|
583
|
+
{data.parameters?.to && (
|
|
584
|
+
<Typography variant="caption" sx={{ color: '#9CA3AF', fontSize: '11px', display: 'block' }}>
|
|
585
|
+
To: {data.parameters.to.join(', ')}
|
|
586
|
+
</Typography>
|
|
587
|
+
)}
|
|
588
|
+
{data.parameters?.subject && (
|
|
589
|
+
<Typography variant="caption" sx={{ color: '#9CA3AF', fontSize: '11px', display: 'block', mt: 0.5 }}>
|
|
590
|
+
Subject: {data.parameters.subject}
|
|
591
|
+
</Typography>
|
|
592
|
+
)}
|
|
593
|
+
</Box>
|
|
594
|
+
)}
|
|
595
|
+
|
|
596
|
+
{/* Last Run Info */}
|
|
597
|
+
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, mt: 1 }}>
|
|
598
|
+
<AccessTimeIcon sx={{ fontSize: '14px', color: '#9CA3AF' }} />
|
|
599
|
+
<Typography variant="body2" sx={{ color: '#9CA3AF', fontSize: '11px' }}>
|
|
600
|
+
{t('automation.common.lastRan')}: {data.lastRun || 'Never'}
|
|
601
|
+
</Typography>
|
|
602
|
+
</Box>
|
|
603
|
+
</Box>
|
|
604
|
+
|
|
605
|
+
{/* Connection Handles - Bidirectional (source + target at each position) */}
|
|
606
|
+
{/* Top - Source */}
|
|
607
|
+
<Handle
|
|
608
|
+
type="source"
|
|
609
|
+
position={Position.Top}
|
|
610
|
+
id="top-source"
|
|
611
|
+
className="connection-handle"
|
|
612
|
+
style={{
|
|
613
|
+
background: selected ? '#10B981' : '#1a1a2e',
|
|
614
|
+
width: '14px',
|
|
615
|
+
height: '14px',
|
|
616
|
+
border: '3px solid #10B981',
|
|
617
|
+
top: '-8px',
|
|
618
|
+
opacity: selected ? 1 : 0,
|
|
619
|
+
transition: 'all 0.2s ease-in-out',
|
|
620
|
+
cursor: 'crosshair',
|
|
621
|
+
zIndex: 10,
|
|
622
|
+
}}
|
|
623
|
+
/>
|
|
624
|
+
{/* Top - Target (hidden but functional) */}
|
|
625
|
+
<Handle
|
|
626
|
+
type="target"
|
|
627
|
+
position={Position.Top}
|
|
628
|
+
id="top-target"
|
|
629
|
+
style={{
|
|
630
|
+
background: 'transparent',
|
|
631
|
+
width: '14px',
|
|
632
|
+
height: '14px',
|
|
633
|
+
border: 'none',
|
|
634
|
+
top: '-8px',
|
|
635
|
+
opacity: 0,
|
|
636
|
+
pointerEvents: selected ? 'all' : 'none',
|
|
637
|
+
}}
|
|
638
|
+
/>
|
|
639
|
+
{/* Bottom - Source */}
|
|
640
|
+
<Handle
|
|
641
|
+
type="source"
|
|
642
|
+
position={Position.Bottom}
|
|
643
|
+
id="bottom-source"
|
|
644
|
+
className="connection-handle"
|
|
645
|
+
style={{
|
|
646
|
+
background: selected ? '#10B981' : '#1a1a2e',
|
|
647
|
+
width: '14px',
|
|
648
|
+
height: '14px',
|
|
649
|
+
border: '3px solid #10B981',
|
|
650
|
+
bottom: '-8px',
|
|
651
|
+
opacity: selected ? 1 : 0,
|
|
652
|
+
transition: 'all 0.2s ease-in-out',
|
|
653
|
+
cursor: 'crosshair',
|
|
654
|
+
zIndex: 10,
|
|
655
|
+
}}
|
|
656
|
+
/>
|
|
657
|
+
{/* Bottom - Target (hidden but functional) */}
|
|
658
|
+
<Handle
|
|
659
|
+
type="target"
|
|
660
|
+
position={Position.Bottom}
|
|
661
|
+
id="bottom-target"
|
|
662
|
+
style={{
|
|
663
|
+
background: 'transparent',
|
|
664
|
+
width: '14px',
|
|
665
|
+
height: '14px',
|
|
666
|
+
border: 'none',
|
|
667
|
+
bottom: '-8px',
|
|
668
|
+
opacity: 0,
|
|
669
|
+
pointerEvents: selected ? 'all' : 'none',
|
|
670
|
+
}}
|
|
671
|
+
/>
|
|
672
|
+
{/* Left - Source */}
|
|
673
|
+
<Handle
|
|
674
|
+
type="source"
|
|
675
|
+
position={Position.Left}
|
|
676
|
+
id="left-source"
|
|
677
|
+
className="connection-handle"
|
|
678
|
+
style={{
|
|
679
|
+
background: selected ? '#10B981' : '#1a1a2e',
|
|
680
|
+
width: '14px',
|
|
681
|
+
height: '14px',
|
|
682
|
+
border: '3px solid #10B981',
|
|
683
|
+
left: '-8px',
|
|
684
|
+
opacity: selected ? 1 : 0,
|
|
685
|
+
transition: 'all 0.2s ease-in-out',
|
|
686
|
+
cursor: 'crosshair',
|
|
687
|
+
zIndex: 10,
|
|
688
|
+
}}
|
|
689
|
+
/>
|
|
690
|
+
{/* Left - Target (hidden but functional) */}
|
|
691
|
+
<Handle
|
|
692
|
+
type="target"
|
|
693
|
+
position={Position.Left}
|
|
694
|
+
id="left-target"
|
|
695
|
+
style={{
|
|
696
|
+
background: 'transparent',
|
|
697
|
+
width: '14px',
|
|
698
|
+
height: '14px',
|
|
699
|
+
border: 'none',
|
|
700
|
+
left: '-8px',
|
|
701
|
+
opacity: 0,
|
|
702
|
+
pointerEvents: selected ? 'all' : 'none',
|
|
703
|
+
}}
|
|
704
|
+
/>
|
|
705
|
+
{/* Right - Source */}
|
|
706
|
+
<Handle
|
|
707
|
+
type="source"
|
|
708
|
+
position={Position.Right}
|
|
709
|
+
id="right-source"
|
|
710
|
+
className="connection-handle"
|
|
711
|
+
style={{
|
|
712
|
+
background: selected ? '#10B981' : '#1a1a2e',
|
|
713
|
+
width: '14px',
|
|
714
|
+
height: '14px',
|
|
715
|
+
border: '3px solid #10B981',
|
|
716
|
+
right: '-8px',
|
|
717
|
+
opacity: selected ? 1 : 0,
|
|
718
|
+
transition: 'all 0.2s ease-in-out',
|
|
719
|
+
cursor: 'crosshair',
|
|
720
|
+
zIndex: 10,
|
|
721
|
+
}}
|
|
722
|
+
/>
|
|
723
|
+
{/* Right - Target (hidden but functional) */}
|
|
724
|
+
<Handle
|
|
725
|
+
type="target"
|
|
726
|
+
position={Position.Right}
|
|
727
|
+
id="right-target"
|
|
728
|
+
style={{
|
|
729
|
+
background: 'transparent',
|
|
730
|
+
width: '14px',
|
|
731
|
+
height: '14px',
|
|
732
|
+
border: 'none',
|
|
733
|
+
right: '-8px',
|
|
734
|
+
opacity: 0,
|
|
735
|
+
pointerEvents: selected ? 'all' : 'none',
|
|
736
|
+
}}
|
|
737
|
+
/>
|
|
738
|
+
</Box>
|
|
739
|
+
|
|
740
|
+
{/* Node Action Buttons - Shows when selected */}
|
|
741
|
+
<NodeActionButtons
|
|
742
|
+
selected={selected}
|
|
743
|
+
onOpenAIAssistant={(buttonElement) => {
|
|
744
|
+
if (nodeId) {
|
|
745
|
+
showNodeAIAssistantPopup(nodeId, 'Email Node', buttonElement);
|
|
746
|
+
}
|
|
747
|
+
}}
|
|
748
|
+
onDelete={() => {
|
|
749
|
+
if (nodeId && onNodesChange) {
|
|
750
|
+
onNodesChange([{ id: nodeId, type: 'remove' }]);
|
|
751
|
+
}
|
|
752
|
+
}}
|
|
753
|
+
onDuplicate={() => {
|
|
754
|
+
if (nodeId) {
|
|
755
|
+
const currentNode = nodes.find(n => n.id === nodeId);
|
|
756
|
+
if (currentNode) {
|
|
757
|
+
const newNode = {
|
|
758
|
+
...currentNode,
|
|
759
|
+
id: `${currentNode.id}-copy-${Date.now()}`,
|
|
760
|
+
position: {
|
|
761
|
+
x: currentNode.position.x + 50,
|
|
762
|
+
y: currentNode.position.y + 50,
|
|
763
|
+
},
|
|
764
|
+
selected: false,
|
|
765
|
+
};
|
|
766
|
+
setNodes([...nodes, newNode]);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}}
|
|
770
|
+
/>
|
|
771
|
+
</Box>
|
|
772
|
+
);
|
|
773
|
+
};
|
|
@@ -338,9 +338,25 @@ export const AutomationFormattingNode: React.FC<AutomationFormattingNodeProps> =
|
|
|
338
338
|
{/* Title Section */}
|
|
339
339
|
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 2 }}>
|
|
340
340
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
341
|
+
<Box
|
|
342
|
+
sx={{
|
|
343
|
+
width: '32px',
|
|
344
|
+
height: '32px',
|
|
345
|
+
minWidth: '32px',
|
|
346
|
+
backgroundColor: '#1E3A8A',
|
|
347
|
+
borderRadius: '50%',
|
|
348
|
+
display: 'flex',
|
|
349
|
+
alignItems: 'center',
|
|
350
|
+
justifyContent: 'center',
|
|
351
|
+
flexShrink: 0,
|
|
352
|
+
}}
|
|
353
|
+
>
|
|
354
|
+
{isArticleAnalyzer ? (
|
|
355
|
+
<ArticleAnalyzerIcon size={18} color="#FFFFFF" />
|
|
356
|
+
) : (
|
|
357
|
+
<FormattingNodeIcon size={18} color="#FFFFFF" />
|
|
358
|
+
)}
|
|
359
|
+
</Box>
|
|
344
360
|
<Typography variant="h6" sx={{ fontWeight: 600, fontSize: '16px' }}>
|
|
345
361
|
{highlightText(data.label)}
|
|
346
362
|
</Typography>
|
|
@@ -463,7 +463,7 @@ export const AutomationGoogleServicesNode: React.FC<AutomationGoogleServicesNode
|
|
|
463
463
|
borderRadius: '12px',
|
|
464
464
|
color: '#ffffff',
|
|
465
465
|
position: 'relative',
|
|
466
|
-
boxShadow: selected ?
|
|
466
|
+
boxShadow: selected ? '0 0 0 2px rgba(59, 130, 246, 0.5)' : '0 4px 8px rgba(0, 0, 0, 0.3)',
|
|
467
467
|
transition: 'all 0.2s ease',
|
|
468
468
|
cursor: 'pointer',
|
|
469
469
|
overflow: 'hidden',
|
|
@@ -471,12 +471,12 @@ export const AutomationGoogleServicesNode: React.FC<AutomationGoogleServicesNode
|
|
|
471
471
|
animation: 'pulse-glow 2s ease-in-out infinite',
|
|
472
472
|
'@keyframes pulse-glow': {
|
|
473
473
|
'0%, 100%': {
|
|
474
|
-
boxShadow:
|
|
475
|
-
borderColor:
|
|
474
|
+
boxShadow: '0 0 20px rgba(59, 130, 246, 0.4), 0 0 40px rgba(59, 130, 246, 0.2)',
|
|
475
|
+
borderColor: 'rgba(59, 130, 246, 0.6)',
|
|
476
476
|
},
|
|
477
477
|
'50%': {
|
|
478
|
-
boxShadow:
|
|
479
|
-
borderColor:
|
|
478
|
+
boxShadow: '0 0 30px rgba(59, 130, 246, 0.6), 0 0 60px rgba(59, 130, 246, 0.3)',
|
|
479
|
+
borderColor: 'rgba(59, 130, 246, 0.9)',
|
|
480
480
|
},
|
|
481
481
|
},
|
|
482
482
|
}),
|
|
@@ -485,7 +485,7 @@ export const AutomationGoogleServicesNode: React.FC<AutomationGoogleServicesNode
|
|
|
485
485
|
>
|
|
486
486
|
{/* Top Header Section */}
|
|
487
487
|
<Box sx={{
|
|
488
|
-
backgroundColor:
|
|
488
|
+
backgroundColor: "rgba(67, 93, 132, 0.1)",
|
|
489
489
|
padding: '8px 16px',
|
|
490
490
|
borderRadius: '12px 12px 0 0'
|
|
491
491
|
}}>
|
|
@@ -507,11 +507,13 @@ export const AutomationGoogleServicesNode: React.FC<AutomationGoogleServicesNode
|
|
|
507
507
|
sx={{
|
|
508
508
|
width: '32px',
|
|
509
509
|
height: '32px',
|
|
510
|
+
minWidth: '32px',
|
|
510
511
|
backgroundColor: '#1E3A8A',
|
|
511
512
|
borderRadius: '50%',
|
|
512
513
|
display: 'flex',
|
|
513
514
|
alignItems: 'center',
|
|
514
515
|
justifyContent: 'center',
|
|
516
|
+
flexShrink: 0,
|
|
515
517
|
}}
|
|
516
518
|
>
|
|
517
519
|
<ServiceIcon sx={{ color: 'white', fontSize: '18px' }} />
|
|
@@ -403,7 +403,7 @@ export const AutomationInteractionNode: React.FC<AutomationInteractionNodeProps>
|
|
|
403
403
|
borderRadius: '12px',
|
|
404
404
|
color: '#ffffff',
|
|
405
405
|
position: 'relative',
|
|
406
|
-
boxShadow: selected ?
|
|
406
|
+
boxShadow: selected ? '0 0 0 2px rgba(59, 130, 246, 0.5)' : '0 4px 8px rgba(0, 0, 0, 0.3)',
|
|
407
407
|
transition: 'all 0.2s ease',
|
|
408
408
|
cursor: 'pointer',
|
|
409
409
|
overflow: 'hidden',
|
|
@@ -411,12 +411,12 @@ export const AutomationInteractionNode: React.FC<AutomationInteractionNodeProps>
|
|
|
411
411
|
animation: 'pulse-glow 2s ease-in-out infinite',
|
|
412
412
|
'@keyframes pulse-glow': {
|
|
413
413
|
'0%, 100%': {
|
|
414
|
-
boxShadow:
|
|
415
|
-
borderColor:
|
|
414
|
+
boxShadow: '0 0 20px rgba(59, 130, 246, 0.4), 0 0 40px rgba(59, 130, 246, 0.2)',
|
|
415
|
+
borderColor: 'rgba(59, 130, 246, 0.6)',
|
|
416
416
|
},
|
|
417
417
|
'50%': {
|
|
418
|
-
boxShadow:
|
|
419
|
-
borderColor:
|
|
418
|
+
boxShadow: '0 0 30px rgba(59, 130, 246, 0.6), 0 0 60px rgba(59, 130, 246, 0.3)',
|
|
419
|
+
borderColor: 'rgba(59, 130, 246, 0.9)',
|
|
420
420
|
},
|
|
421
421
|
},
|
|
422
422
|
}),
|
|
@@ -425,7 +425,7 @@ export const AutomationInteractionNode: React.FC<AutomationInteractionNodeProps>
|
|
|
425
425
|
>
|
|
426
426
|
{/* Top Header Section */}
|
|
427
427
|
<Box sx={{
|
|
428
|
-
backgroundColor:
|
|
428
|
+
backgroundColor: "rgba(67, 93, 132, 0.1)",
|
|
429
429
|
padding: '8px 16px',
|
|
430
430
|
borderRadius: '12px 12px 0 0'
|
|
431
431
|
}}>
|
|
@@ -447,11 +447,13 @@ export const AutomationInteractionNode: React.FC<AutomationInteractionNodeProps>
|
|
|
447
447
|
sx={{
|
|
448
448
|
width: '32px',
|
|
449
449
|
height: '32px',
|
|
450
|
+
minWidth: '32px',
|
|
450
451
|
backgroundColor: '#1E3A8A',
|
|
451
452
|
borderRadius: '50%',
|
|
452
453
|
display: 'flex',
|
|
453
454
|
alignItems: 'center',
|
|
454
455
|
justifyContent: 'center',
|
|
456
|
+
flexShrink: 0,
|
|
455
457
|
}}
|
|
456
458
|
>
|
|
457
459
|
<InteractionIcon sx={{ color: 'white', fontSize: '18px' }} />
|
|
@@ -190,24 +190,22 @@ export const AutomationMonitoringNode: React.FC<AutomationMonitoringNodeProps> =
|
|
|
190
190
|
sx={{
|
|
191
191
|
bgcolor: '#1E1E2E',
|
|
192
192
|
borderRadius: 2,
|
|
193
|
-
border: selected ?
|
|
193
|
+
border: selected ? '2px solid rgba(59, 130, 246, 0.5)' : '1px solid #374151',
|
|
194
194
|
minWidth: 280,
|
|
195
195
|
maxWidth: 320,
|
|
196
196
|
overflow: 'hidden',
|
|
197
|
-
boxShadow: selected
|
|
198
|
-
? `0 0 20px ${monitoringColor}30`
|
|
199
|
-
: '0 4px 12px rgba(0, 0, 0, 0.3)',
|
|
197
|
+
boxShadow: selected ? '0 0 0 2px rgba(59, 130, 246, 0.5)' : '0 4px 8px rgba(0, 0, 0, 0.3)',
|
|
200
198
|
transition: 'all 0.2s ease',
|
|
201
199
|
...(status === 'Running' && {
|
|
202
200
|
animation: 'pulse-glow 2s ease-in-out infinite',
|
|
203
201
|
'@keyframes pulse-glow': {
|
|
204
202
|
'0%, 100%': {
|
|
205
|
-
boxShadow:
|
|
206
|
-
borderColor:
|
|
203
|
+
boxShadow: '0 0 20px rgba(59, 130, 246, 0.4), 0 0 40px rgba(59, 130, 246, 0.2)',
|
|
204
|
+
borderColor: 'rgba(59, 130, 246, 0.6)',
|
|
207
205
|
},
|
|
208
206
|
'50%': {
|
|
209
|
-
boxShadow:
|
|
210
|
-
borderColor:
|
|
207
|
+
boxShadow: '0 0 30px rgba(59, 130, 246, 0.6), 0 0 60px rgba(59, 130, 246, 0.3)',
|
|
208
|
+
borderColor: 'rgba(59, 130, 246, 0.9)',
|
|
211
209
|
},
|
|
212
210
|
},
|
|
213
211
|
}),
|
|
@@ -295,9 +295,21 @@ export const AutomationNavigationNode: React.FC<AutomationNavigationNodeProps> =
|
|
|
295
295
|
{/* Title Section */}
|
|
296
296
|
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 2 }}>
|
|
297
297
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
|
|
298
|
-
|
|
298
|
+
<Box
|
|
299
|
+
sx={{
|
|
300
|
+
width: '32px',
|
|
301
|
+
height: '32px',
|
|
302
|
+
minWidth: '32px',
|
|
303
|
+
backgroundColor: '#8b5cf6',
|
|
304
|
+
borderRadius: '50%',
|
|
305
|
+
display: 'flex',
|
|
306
|
+
alignItems: 'center',
|
|
307
|
+
justifyContent: 'center',
|
|
308
|
+
flexShrink: 0,
|
|
309
|
+
}}
|
|
310
|
+
>
|
|
299
311
|
<NavigationIcon />
|
|
300
|
-
|
|
312
|
+
</Box>
|
|
301
313
|
<Typography variant="h6" sx={{ fontWeight: 600, fontSize: '16px' }}>
|
|
302
314
|
{highlightText(data.label)}
|
|
303
315
|
</Typography>
|
|
@@ -746,6 +746,21 @@ Data: ${JSON.stringify(data, null, 2)}
|
|
|
746
746
|
}}
|
|
747
747
|
onClick={handleJsonClick}
|
|
748
748
|
>
|
|
749
|
+
{/* Top Header Section */}
|
|
750
|
+
<Box sx={{
|
|
751
|
+
backgroundColor: "rgba(67, 93, 132, 0.1)",
|
|
752
|
+
padding: '8px 16px',
|
|
753
|
+
borderRadius: '12px 12px 0 0'
|
|
754
|
+
}}>
|
|
755
|
+
<Typography variant="body2" sx={{
|
|
756
|
+
color: '#ffffff',
|
|
757
|
+
fontSize: '12px',
|
|
758
|
+
fontWeight: 500
|
|
759
|
+
}}>
|
|
760
|
+
{data.description || 'Export data to Google Sheets'}
|
|
761
|
+
</Typography>
|
|
762
|
+
</Box>
|
|
763
|
+
|
|
749
764
|
{/* Header */}
|
|
750
765
|
<Box sx={{
|
|
751
766
|
display: 'flex',
|
|
@@ -759,11 +774,13 @@ Data: ${JSON.stringify(data, null, 2)}
|
|
|
759
774
|
sx={{
|
|
760
775
|
width: '32px',
|
|
761
776
|
height: '32px',
|
|
777
|
+
minWidth: '32px',
|
|
762
778
|
backgroundColor: '#1E3A8A',
|
|
763
779
|
borderRadius: '50%',
|
|
764
780
|
display: 'flex',
|
|
765
781
|
alignItems: 'center',
|
|
766
782
|
justifyContent: 'center',
|
|
783
|
+
flexShrink: 0,
|
|
767
784
|
}}
|
|
768
785
|
>
|
|
769
786
|
<IconComponent sx={{ color: 'white', fontSize: '18px' }} />
|
|
@@ -434,14 +434,25 @@ export const AutomationSlackNode: React.FC<AutomationSlackNodeProps> = ({
|
|
|
434
434
|
sx={{
|
|
435
435
|
bgcolor: '#1E1E2E',
|
|
436
436
|
borderRadius: 2,
|
|
437
|
-
border: selected ?
|
|
437
|
+
border: selected ? '2px solid rgba(59, 130, 246, 0.5)' : '1px solid #374151',
|
|
438
438
|
minWidth: 280,
|
|
439
439
|
maxWidth: 320,
|
|
440
440
|
overflow: 'hidden',
|
|
441
|
-
boxShadow: selected
|
|
442
|
-
? `0 0 20px ${operationConfig.color}30`
|
|
443
|
-
: '0 4px 12px rgba(0, 0, 0, 0.3)',
|
|
441
|
+
boxShadow: selected ? '0 0 0 2px rgba(59, 130, 246, 0.5)' : '0 4px 8px rgba(0, 0, 0, 0.3)',
|
|
444
442
|
transition: 'all 0.2s ease',
|
|
443
|
+
...(status === 'Running' && {
|
|
444
|
+
animation: 'pulse-glow 2s ease-in-out infinite',
|
|
445
|
+
'@keyframes pulse-glow': {
|
|
446
|
+
'0%, 100%': {
|
|
447
|
+
boxShadow: '0 0 20px rgba(59, 130, 246, 0.4), 0 0 40px rgba(59, 130, 246, 0.2)',
|
|
448
|
+
borderColor: 'rgba(59, 130, 246, 0.6)',
|
|
449
|
+
},
|
|
450
|
+
'50%': {
|
|
451
|
+
boxShadow: '0 0 30px rgba(59, 130, 246, 0.6), 0 0 60px rgba(59, 130, 246, 0.3)',
|
|
452
|
+
borderColor: 'rgba(59, 130, 246, 0.9)',
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
}),
|
|
445
456
|
}}
|
|
446
457
|
onClick={() => setSelectedNode(nodeId || '')}
|
|
447
458
|
>
|
|
@@ -457,11 +468,26 @@ export const AutomationSlackNode: React.FC<AutomationSlackNodeProps> = ({
|
|
|
457
468
|
}}
|
|
458
469
|
/>
|
|
459
470
|
|
|
471
|
+
{/* Top Header Section */}
|
|
472
|
+
<Box sx={{
|
|
473
|
+
backgroundColor: "rgba(67, 93, 132, 0.1)",
|
|
474
|
+
padding: '8px 16px',
|
|
475
|
+
borderRadius: '12px 12px 0 0'
|
|
476
|
+
}}>
|
|
477
|
+
<Typography variant="body2" sx={{
|
|
478
|
+
color: '#ffffff',
|
|
479
|
+
fontSize: '12px',
|
|
480
|
+
fontWeight: 500
|
|
481
|
+
}}>
|
|
482
|
+
{data.description || operationConfig.description}
|
|
483
|
+
</Typography>
|
|
484
|
+
</Box>
|
|
485
|
+
|
|
460
486
|
{/* Header */}
|
|
461
487
|
<Box
|
|
462
488
|
sx={{
|
|
463
|
-
bgcolor:
|
|
464
|
-
borderBottom: `1px solid
|
|
489
|
+
bgcolor: "rgba(67, 93, 132, 0.1)",
|
|
490
|
+
borderBottom: `1px solid rgba(67, 93, 132, 0.2)`,
|
|
465
491
|
px: 2,
|
|
466
492
|
py: 1.5,
|
|
467
493
|
display: 'flex',
|
|
@@ -474,11 +500,13 @@ export const AutomationSlackNode: React.FC<AutomationSlackNodeProps> = ({
|
|
|
474
500
|
sx={{
|
|
475
501
|
width: '32px',
|
|
476
502
|
height: '32px',
|
|
503
|
+
minWidth: '32px',
|
|
477
504
|
backgroundColor: '#1E3A8A',
|
|
478
505
|
borderRadius: '50%',
|
|
479
506
|
display: 'flex',
|
|
480
507
|
alignItems: 'center',
|
|
481
508
|
justifyContent: 'center',
|
|
509
|
+
flexShrink: 0,
|
|
482
510
|
}}
|
|
483
511
|
>
|
|
484
512
|
<OperationIcon sx={{ fontSize: 18, color: '#fff' }} />
|
|
@@ -490,12 +518,6 @@ export const AutomationSlackNode: React.FC<AutomationSlackNodeProps> = ({
|
|
|
490
518
|
>
|
|
491
519
|
{highlightText(data.label || operationConfig.label)}
|
|
492
520
|
</Typography>
|
|
493
|
-
<Typography
|
|
494
|
-
variant="caption"
|
|
495
|
-
sx={{ color: '#9CA3AF', fontSize: 10 }}
|
|
496
|
-
>
|
|
497
|
-
{data.description || operationConfig.description}
|
|
498
|
-
</Typography>
|
|
499
521
|
</Box>
|
|
500
522
|
</Box>
|
|
501
523
|
{renderStatusBadge()}
|
|
@@ -427,14 +427,25 @@ export const AutomationTelegramNode: React.FC<AutomationTelegramNodeProps> = ({
|
|
|
427
427
|
sx={{
|
|
428
428
|
bgcolor: '#1E1E2E',
|
|
429
429
|
borderRadius: 2,
|
|
430
|
-
border: selected ?
|
|
430
|
+
border: selected ? '2px solid rgba(59, 130, 246, 0.5)' : '1px solid #374151',
|
|
431
431
|
minWidth: 280,
|
|
432
432
|
maxWidth: 320,
|
|
433
433
|
overflow: 'hidden',
|
|
434
|
-
boxShadow: selected
|
|
435
|
-
? `0 0 20px ${operationConfig.color}30`
|
|
436
|
-
: '0 4px 12px rgba(0, 0, 0, 0.3)',
|
|
434
|
+
boxShadow: selected ? '0 0 0 2px rgba(59, 130, 246, 0.5)' : '0 4px 8px rgba(0, 0, 0, 0.3)',
|
|
437
435
|
transition: 'all 0.2s ease',
|
|
436
|
+
...(status === 'Running' && {
|
|
437
|
+
animation: 'pulse-glow 2s ease-in-out infinite',
|
|
438
|
+
'@keyframes pulse-glow': {
|
|
439
|
+
'0%, 100%': {
|
|
440
|
+
boxShadow: '0 0 20px rgba(59, 130, 246, 0.4), 0 0 40px rgba(59, 130, 246, 0.2)',
|
|
441
|
+
borderColor: 'rgba(59, 130, 246, 0.6)',
|
|
442
|
+
},
|
|
443
|
+
'50%': {
|
|
444
|
+
boxShadow: '0 0 30px rgba(59, 130, 246, 0.6), 0 0 60px rgba(59, 130, 246, 0.3)',
|
|
445
|
+
borderColor: 'rgba(59, 130, 246, 0.9)',
|
|
446
|
+
},
|
|
447
|
+
},
|
|
448
|
+
}),
|
|
438
449
|
}}
|
|
439
450
|
onClick={() => setSelectedNode(nodeId || '')}
|
|
440
451
|
>
|
|
@@ -450,11 +461,26 @@ export const AutomationTelegramNode: React.FC<AutomationTelegramNodeProps> = ({
|
|
|
450
461
|
}}
|
|
451
462
|
/>
|
|
452
463
|
|
|
464
|
+
{/* Top Header Section */}
|
|
465
|
+
<Box sx={{
|
|
466
|
+
backgroundColor: "rgba(67, 93, 132, 0.1)",
|
|
467
|
+
padding: '8px 16px',
|
|
468
|
+
borderRadius: '12px 12px 0 0'
|
|
469
|
+
}}>
|
|
470
|
+
<Typography variant="body2" sx={{
|
|
471
|
+
color: '#ffffff',
|
|
472
|
+
fontSize: '12px',
|
|
473
|
+
fontWeight: 500
|
|
474
|
+
}}>
|
|
475
|
+
{data.description || operationConfig.description}
|
|
476
|
+
</Typography>
|
|
477
|
+
</Box>
|
|
478
|
+
|
|
453
479
|
{/* Header */}
|
|
454
480
|
<Box
|
|
455
481
|
sx={{
|
|
456
|
-
bgcolor:
|
|
457
|
-
borderBottom: `1px solid
|
|
482
|
+
bgcolor: "rgba(67, 93, 132, 0.1)",
|
|
483
|
+
borderBottom: `1px solid rgba(67, 93, 132, 0.2)`,
|
|
458
484
|
px: 2,
|
|
459
485
|
py: 1.5,
|
|
460
486
|
display: 'flex',
|
|
@@ -467,11 +493,13 @@ export const AutomationTelegramNode: React.FC<AutomationTelegramNodeProps> = ({
|
|
|
467
493
|
sx={{
|
|
468
494
|
width: '32px',
|
|
469
495
|
height: '32px',
|
|
496
|
+
minWidth: '32px',
|
|
470
497
|
backgroundColor: '#1E3A8A',
|
|
471
498
|
borderRadius: '50%',
|
|
472
499
|
display: 'flex',
|
|
473
500
|
alignItems: 'center',
|
|
474
501
|
justifyContent: 'center',
|
|
502
|
+
flexShrink: 0,
|
|
475
503
|
}}
|
|
476
504
|
>
|
|
477
505
|
<OperationIcon sx={{ fontSize: 18, color: '#fff' }} />
|
|
@@ -483,12 +511,6 @@ export const AutomationTelegramNode: React.FC<AutomationTelegramNodeProps> = ({
|
|
|
483
511
|
>
|
|
484
512
|
{highlightText(data.label || operationConfig.label)}
|
|
485
513
|
</Typography>
|
|
486
|
-
<Typography
|
|
487
|
-
variant="caption"
|
|
488
|
-
sx={{ color: '#9CA3AF', fontSize: 10 }}
|
|
489
|
-
>
|
|
490
|
-
{data.description || operationConfig.description}
|
|
491
|
-
</Typography>
|
|
492
514
|
</Box>
|
|
493
515
|
</Box>
|
|
494
516
|
{renderStatusBadge()}
|
|
@@ -43,6 +43,14 @@ export type {
|
|
|
43
43
|
AutomationInteractionNodeData,
|
|
44
44
|
AutomationInteractionNodeProps,
|
|
45
45
|
} from './AutomationInteractionNode';
|
|
46
|
+
// Email Node
|
|
47
|
+
export { AutomationEmailNode } from './AutomationEmailNode';
|
|
48
|
+
export type {
|
|
49
|
+
EmailOperationType,
|
|
50
|
+
EmailTokenData,
|
|
51
|
+
AutomationEmailNodeData,
|
|
52
|
+
AutomationEmailNodeProps,
|
|
53
|
+
} from './AutomationEmailNode';
|
|
46
54
|
// Monitoring Node
|
|
47
55
|
export { AutomationMonitoringNode } from './AutomationMonitoringNode';
|
|
48
56
|
export type {
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
AutomationSlackNode,
|
|
17
17
|
AutomationTelegramNode,
|
|
18
18
|
AutomationInteractionNode,
|
|
19
|
+
AutomationEmailNode,
|
|
19
20
|
AutomationMonitoringNode,
|
|
20
21
|
} from '../components/automation';
|
|
21
22
|
|
|
@@ -46,6 +47,8 @@ export default {
|
|
|
46
47
|
AutomationTelegramNode,
|
|
47
48
|
// Interaction Node
|
|
48
49
|
AutomationInteractionNode,
|
|
50
|
+
// Email Node
|
|
51
|
+
AutomationEmailNode,
|
|
49
52
|
// Monitoring Node
|
|
50
53
|
AutomationMonitoringNode,
|
|
51
54
|
};
|
|
@@ -67,9 +67,9 @@ export const ArticleAnalyzerIcon: React.FC<SvgIconProps> = ({ size = 15, color =
|
|
|
67
67
|
export const StartNodeIcon: React.FC<SvgIconProps> = ({ size, color, style }) => (
|
|
68
68
|
<svg width="35" height="35" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
69
69
|
<path d="M0 14C0 6.26801 6.26801 0 14 0C21.732 0 28 6.26801 28 14C28 21.732 21.732 28 14 28C6.26801 28 0 21.732 0 14Z" fill="#1E3A8A"/>
|
|
70
|
-
<g
|
|
71
|
-
<path d="M14.0007 20.6663C17.6825 20.6663 20.6673 17.6816 20.6673 13.9997C20.6673 10.3178 17.6825 7.33301 14.0007 7.33301C10.3188 7.33301 7.33398 10.3178 7.33398 13.9997C7.33398 17.6816 10.3188 20.6663 14.0007 20.6663Z" stroke="#86EFAC"
|
|
72
|
-
<path d="M12.666 11.333L16.666 13.9997L12.666 16.6663V11.333Z" stroke="#86EFAC"
|
|
70
|
+
<g clipPath="url(#clip0_8650_35616)">
|
|
71
|
+
<path d="M14.0007 20.6663C17.6825 20.6663 20.6673 17.6816 20.6673 13.9997C20.6673 10.3178 17.6825 7.33301 14.0007 7.33301C10.3188 7.33301 7.33398 10.3178 7.33398 13.9997C7.33398 17.6816 10.3188 20.6663 14.0007 20.6663Z" stroke="#86EFAC" strokeLinecap="round" strokeLinejoin="round"/>
|
|
72
|
+
<path d="M12.666 11.333L16.666 13.9997L12.666 16.6663V11.333Z" stroke="#86EFAC" strokeLinecap="round" strokeLinejoin="round"/>
|
|
73
73
|
</g>
|
|
74
74
|
<defs>
|
|
75
75
|
<clipPath id="clip0_8650_35616">
|
|
@@ -85,10 +85,10 @@ export const StartNodeIcon: React.FC<SvgIconProps> = ({ size, color, style }) =>
|
|
|
85
85
|
export const NavigationIcon: React.FC<SvgIconProps> = ({ size, color, style }) => (
|
|
86
86
|
<svg width="35" height="35" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
87
87
|
<path d="M0 14C0 6.26801 6.26801 0 14 0C21.732 0 28 6.26801 28 14C28 21.732 21.732 28 14 28C6.26801 28 0 21.732 0 14Z" fill="#1E3A8A"/>
|
|
88
|
-
<g
|
|
89
|
-
<path d="M14.0007 20.6663C17.6825 20.6663 20.6673 17.6816 20.6673 13.9997C20.6673 10.3178 17.6825 7.33301 14.0007 7.33301C10.3188 7.33301 7.33398 10.3178 7.33398 13.9997C7.33398 17.6816 10.3188 20.6663 14.0007 20.6663Z" stroke="#93C5FD"
|
|
90
|
-
<path d="M14.0007 7.33301C12.2888 9.13044 11.334 11.5175 11.334 13.9997C11.334 16.4818 12.2888 18.8689 14.0007 20.6663C15.7125 18.8689 16.6673 16.4818 16.6673 13.9997C16.6673 11.5175 15.7125 9.13044 14.0007 7.33301Z" stroke="#93C5FD"
|
|
91
|
-
<path d="M7.33398 14H20.6673" stroke="#93C5FD"
|
|
88
|
+
<g clipPath="url(#clip0_8650_35642)">
|
|
89
|
+
<path d="M14.0007 20.6663C17.6825 20.6663 20.6673 17.6816 20.6673 13.9997C20.6673 10.3178 17.6825 7.33301 14.0007 7.33301C10.3188 7.33301 7.33398 10.3178 7.33398 13.9997C7.33398 17.6816 10.3188 20.6663 14.0007 20.6663Z" stroke="#93C5FD" strokeLinecap="round" strokeLinejoin="round"/>
|
|
90
|
+
<path d="M14.0007 7.33301C12.2888 9.13044 11.334 11.5175 11.334 13.9997C11.334 16.4818 12.2888 18.8689 14.0007 20.6663C15.7125 18.8689 16.6673 16.4818 16.6673 13.9997C16.6673 11.5175 15.7125 9.13044 14.0007 7.33301Z" stroke="#93C5FD" strokeLinecap="round" strokeLinejoin="round"/>
|
|
91
|
+
<path d="M7.33398 14H20.6673" stroke="#93C5FD" strokeLinecap="round" strokeLinejoin="round"/>
|
|
92
92
|
</g>
|
|
93
93
|
<defs>
|
|
94
94
|
<clipPath id="clip0_8650_35642">
|
|
@@ -269,7 +269,7 @@ export const EntityIcon: React.FC<SvgIconProps> = ({ size, color = '#86EFAC', st
|
|
|
269
269
|
export const EndNodeIcon: React.FC<SvgIconProps> = ({ size, color , style }) => (
|
|
270
270
|
<svg width="35" height="35" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
271
271
|
<path d="M0 14C0 6.26801 6.26801 0 14 0C21.732 0 28 6.26801 28 14C28 21.732 21.732 28 14 28C6.26801 28 0 21.732 0 14Z" fill="#1E3A8A"/>
|
|
272
|
-
<path d="M18.6667 8H9.33333C8.59695 8 8 8.59695 8 9.33333V18.6667C8 19.403 8.59695 20 9.33333 20H18.6667C19.403 20 20 19.403 20 18.6667V9.33333C20 8.59695 19.403 8 18.6667 8Z" stroke="#FCA5A5"
|
|
272
|
+
<path d="M18.6667 8H9.33333C8.59695 8 8 8.59695 8 9.33333V18.6667C8 19.403 8.59695 20 9.33333 20H18.6667C19.403 20 20 19.403 20 18.6667V9.33333C20 8.59695 19.403 8 18.6667 8Z" stroke="#FCA5A5" strokeLinecap="round" strokeLinejoin="round"/>
|
|
273
273
|
</svg>
|
|
274
274
|
|
|
275
275
|
);
|
|
@@ -277,16 +277,16 @@ export const EndNodeIcon: React.FC<SvgIconProps> = ({ size, color , style }) =>
|
|
|
277
277
|
export const FormattingNodeIcon: React.FC<SvgIconProps> = ({ size, color , style }) => (
|
|
278
278
|
<svg width="35" height="35" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
279
279
|
<path d="M0 14C0 6.26801 6.26801 0 14 0C21.732 0 28 6.26801 28 14C28 21.732 21.732 28 14 28C6.26801 28 0 21.732 0 14Z" fill="#1E3A8A"/>
|
|
280
|
-
<path d="M15.9993 7.33301H9.99935C9.64573 7.33301 9.30659 7.47348 9.05654 7.72353C8.80649 7.97358 8.66602 8.31272 8.66602 8.66634V19.333C8.66602 19.6866 8.80649 20.0258 9.05654 20.2758C9.30659 20.5259 9.64573 20.6663 9.99935 20.6663H17.9993C18.353 20.6663 18.6921 20.5259 18.9422 20.2758C19.1922 20.0258 19.3327 19.6866 19.3327 19.333V10.6663L15.9993 7.33301Z" stroke="#D8B4FE"
|
|
281
|
-
<path d="M15.334 7.33301V9.99967C15.334 10.3533 15.4745 10.6924 15.7245 10.9425C15.9746 11.1925 16.3137 11.333 16.6673 11.333H19.334" stroke="#D8B4FE"
|
|
282
|
-
<path d="M12.6673 12H11.334" stroke="#D8B4FE"
|
|
283
|
-
<path d="M16.6673 14.667H11.334" stroke="#D8B4FE"
|
|
284
|
-
<path d="M16.6673 17.333H11.334" stroke="#D8B4FE"
|
|
280
|
+
<path d="M15.9993 7.33301H9.99935C9.64573 7.33301 9.30659 7.47348 9.05654 7.72353C8.80649 7.97358 8.66602 8.31272 8.66602 8.66634V19.333C8.66602 19.6866 8.80649 20.0258 9.05654 20.2758C9.30659 20.5259 9.64573 20.6663 9.99935 20.6663H17.9993C18.353 20.6663 18.6921 20.5259 18.9422 20.2758C19.1922 20.0258 19.3327 19.6866 19.3327 19.333V10.6663L15.9993 7.33301Z" stroke="#D8B4FE" strokeLinecap="round" strokeLinejoin="round"/>
|
|
281
|
+
<path d="M15.334 7.33301V9.99967C15.334 10.3533 15.4745 10.6924 15.7245 10.9425C15.9746 11.1925 16.3137 11.333 16.6673 11.333H19.334" stroke="#D8B4FE" strokeLinecap="round" strokeLinejoin="round"/>
|
|
282
|
+
<path d="M12.6673 12H11.334" stroke="#D8B4FE" strokeLinecap="round" strokeLinejoin="round"/>
|
|
283
|
+
<path d="M16.6673 14.667H11.334" stroke="#D8B4FE" strokeLinecap="round" strokeLinejoin="round"/>
|
|
284
|
+
<path d="M16.6673 17.333H11.334" stroke="#D8B4FE" strokeLinecap="round" strokeLinejoin="round"/>
|
|
285
285
|
</svg>
|
|
286
286
|
);
|
|
287
287
|
|
|
288
288
|
export const ApiNodeIcon: React.FC<SvgIconProps> = ({ size, color , style }) => (
|
|
289
289
|
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
290
|
-
<path d="M3.89167 3.92167L2.66667 2.68583M10.4242 3.92167L11.6492 2.68583M2.66583 11.7525L3.89083 10.5158M7.1575 2.27417V0.625M2.2575 7.21917H0.625M12.1875 12.155L15.3658 10.9C15.4425 10.8693 15.5083 10.8164 15.5546 10.748C15.6009 10.6796 15.6256 10.5988 15.6256 10.5162C15.6256 10.4337 15.6009 10.3529 15.5546 10.2845C15.5083 10.2161 15.4425 10.1632 15.3658 10.1325L7.72833 7.12C7.65398 7.09123 7.57285 7.08475 7.49488 7.10138C7.4169 7.118 7.34547 7.157 7.28931 7.21359C7.23316 7.27019 7.19472 7.34193 7.17871 7.42003C7.1627 7.49813 7.16981 7.57921 7.19917 7.65333L10.1842 15.3625C10.3192 15.7125 10.8092 15.7125 10.9442 15.3625L12.1875 12.155Z" stroke="#FCFAFF"
|
|
290
|
+
<path d="M3.89167 3.92167L2.66667 2.68583M10.4242 3.92167L11.6492 2.68583M2.66583 11.7525L3.89083 10.5158M7.1575 2.27417V0.625M2.2575 7.21917H0.625M12.1875 12.155L15.3658 10.9C15.4425 10.8693 15.5083 10.8164 15.5546 10.748C15.6009 10.6796 15.6256 10.5988 15.6256 10.5162C15.6256 10.4337 15.6009 10.3529 15.5546 10.2845C15.5083 10.2161 15.4425 10.1632 15.3658 10.1325L7.72833 7.12C7.65398 7.09123 7.57285 7.08475 7.49488 7.10138C7.4169 7.118 7.34547 7.157 7.28931 7.21359C7.23316 7.27019 7.19472 7.34193 7.17871 7.42003C7.1627 7.49813 7.16981 7.57921 7.19917 7.65333L10.1842 15.3625C10.3192 15.7125 10.8092 15.7125 10.9442 15.3625L12.1875 12.155Z" stroke="#FCFAFF" strokeWidth="1.25" strokeLinecap="round" strokeLinejoin="round"/>
|
|
291
291
|
</svg>
|
|
292
292
|
);
|