@flowuent-org/diagramming-core 1.0.8 → 1.1.1
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 +22 -0
- package/apps/diagramming/src/components/AddNodeView.tsx +252 -252
- package/apps/diagramming/src/main.tsx +463 -463
- package/apps/diagramming/src/node-data.ts +664 -664
- package/apps/diagramming/src/stencil-items.ts +31 -31
- package/apps/diagramming/src/vite-env.d.ts +1 -1
- package/package.json +1 -1
- package/packages/diagrams/NODE_DATA_UPDATE_API.md +430 -430
- package/packages/diagrams/README.md +7 -463
- package/packages/diagrams/UNDO_REDO_API.md +306 -306
- package/packages/diagrams/package.json +27 -27
- package/packages/diagrams/project.json +42 -42
- package/packages/diagrams/rollup.config.js +26 -26
- package/packages/diagrams/src/DiagramFlow.tsx +7 -7
- package/packages/diagrams/src/index.ts +116 -116
- package/packages/diagrams/src/index.ts.bak +99 -99
- package/packages/diagrams/src/lib/atoms/CardEditableTitle.tsx +76 -76
- package/packages/diagrams/src/lib/atoms/ExpressionInput.tsx +437 -437
- package/packages/diagrams/src/lib/components/DiagramPanel.tsx +331 -331
- package/packages/diagrams/src/lib/components/automation/AISuggestionsModal.tsx +269 -0
- package/packages/diagrams/src/lib/components/automation/AISuggestionsPanel.tsx +227 -0
- package/packages/diagrams/src/lib/components/automation/AutomationAISuggestionNode.tsx +178 -115
- package/packages/diagrams/src/lib/components/automation/AutomationApiNode.tsx +133 -27
- package/packages/diagrams/src/lib/components/automation/AutomationEndNode.tsx +134 -28
- package/packages/diagrams/src/lib/components/automation/AutomationFormattingNode.tsx +132 -27
- package/packages/diagrams/src/lib/components/automation/AutomationNoteNode.tsx +124 -17
- package/packages/diagrams/src/lib/components/automation/AutomationSheetsNode.tsx +122 -15
- package/packages/diagrams/src/lib/components/automation/index.ts +3 -0
- package/packages/diagrams/src/lib/contexts/onWorkflowNodeDelete.ts +65 -65
- package/packages/diagrams/src/lib/organisms/CustomEdge/useCreateBendPoint.tsx +121 -121
- package/packages/diagrams/src/lib/organisms/WorkFlowNode/NodeActionButtons.tsx +45 -45
- package/packages/diagrams/src/lib/templates/node-forms/CallForm.tsx +370 -370
- package/packages/diagrams/src/lib/templates/systemFlow/components/FloatingEdge.tsx +219 -219
- package/packages/diagrams/src/lib/types/card-node.ts +68 -68
- package/packages/diagrams/src/lib/types/node-types.ts +29 -29
- package/packages/diagrams/src/lib/utils/AutomationExecutionEngine.ts +1179 -1179
- package/packages/diagrams/tsconfig.lib.json +25 -25
- package/tsconfig.base.json +29 -30
- package/TRANSLATION_FIX_SUMMARY.md +0 -118
- package/packages/diagrams/I18N_SETUP.md +0 -126
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import React, { useEffect, useState, useRef } from 'react';
|
|
2
2
|
import { createRoot } from 'react-dom/client';
|
|
3
3
|
import { Handle, Position, useNodeId } from '@xyflow/react';
|
|
4
|
-
import { Box, Typography, Chip, IconButton, Card, CardContent } from '@mui/material';
|
|
5
|
-
import { AccessTime as AccessTimeIcon, Visibility as VisibilityIcon, Save as SaveIcon, Send as SendIcon } from '@mui/icons-material';
|
|
4
|
+
import { Box, Typography, Chip, IconButton, Card, CardContent, Button } from '@mui/material';
|
|
5
|
+
import { AccessTime as AccessTimeIcon, Visibility as VisibilityIcon, Save as SaveIcon, Send as SendIcon, Lightbulb as LightbulbIcon } from '@mui/icons-material';
|
|
6
6
|
import { RiCloseLine, RiUser2Line } from 'react-icons/ri';
|
|
7
7
|
import ReactJson from 'react-json-view';
|
|
8
8
|
import { getIconByName } from '../../utils/iconMapper';
|
|
9
9
|
import { useTranslation } from 'react-i18next';
|
|
10
10
|
import { useDiagram } from '../../contexts/DiagramProvider';
|
|
11
|
+
import { AISuggestion } from './AISuggestionsModal';
|
|
12
|
+
import { AISuggestionsPanel } from './AISuggestionsPanel';
|
|
11
13
|
|
|
12
14
|
interface AutomationEndNodeProps {
|
|
13
15
|
data: {
|
|
@@ -26,7 +28,10 @@ interface AutomationEndNodeProps {
|
|
|
26
28
|
textColor: string;
|
|
27
29
|
borderColor: string;
|
|
28
30
|
iconName?: string; // Add iconName to the interface
|
|
29
|
-
formData?:
|
|
31
|
+
formData?: {
|
|
32
|
+
aiSuggestionsCount?: number; // Number of AI suggestions available
|
|
33
|
+
[key: string]: any;
|
|
34
|
+
}; // Include formData for configuration
|
|
30
35
|
};
|
|
31
36
|
selected?: boolean;
|
|
32
37
|
}
|
|
@@ -34,6 +39,7 @@ interface AutomationEndNodeProps {
|
|
|
34
39
|
export const AutomationEndNode: React.FC<AutomationEndNodeProps> = ({ data, selected }) => {
|
|
35
40
|
const { t } = useTranslation();
|
|
36
41
|
const [isJsonOpen, setIsJsonOpen] = useState(false);
|
|
42
|
+
const [showSuggestions, setShowSuggestions] = useState(false);
|
|
37
43
|
const rootRef = useRef<any>(null);
|
|
38
44
|
const portalRef = useRef<HTMLDivElement | null>(null);
|
|
39
45
|
const nodeRef = useRef<HTMLDivElement | null>(null);
|
|
@@ -194,35 +200,42 @@ export const AutomationEndNode: React.FC<AutomationEndNodeProps> = ({ data, sele
|
|
|
194
200
|
|
|
195
201
|
return (
|
|
196
202
|
<Box
|
|
197
|
-
ref={nodeRef}
|
|
198
203
|
sx={{
|
|
199
|
-
width: '336px',
|
|
200
|
-
minHeight: '150px',
|
|
201
|
-
backgroundColor: '#181C25', // New background color from image
|
|
202
|
-
border: selected ? '2px solid #3b82f6' : '1px solid #1e293b',
|
|
203
|
-
borderRadius: '12px',
|
|
204
|
-
color: '#ffffff',
|
|
205
204
|
position: 'relative',
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
cursor: 'pointer',
|
|
209
|
-
overflow: 'hidden',
|
|
210
|
-
...(data.status === 'Running' && {
|
|
211
|
-
animation: 'pulse-glow 2s ease-in-out infinite',
|
|
212
|
-
'@keyframes pulse-glow': {
|
|
213
|
-
'0%, 100%': {
|
|
214
|
-
boxShadow: '0 0 20px rgba(251, 191, 36, 0.4), 0 0 40px rgba(251, 191, 36, 0.2)',
|
|
215
|
-
borderColor: 'rgba(251, 191, 36, 0.6)',
|
|
216
|
-
},
|
|
217
|
-
'50%': {
|
|
218
|
-
boxShadow: '0 0 30px rgba(251, 191, 36, 0.6), 0 0 60px rgba(251, 191, 36, 0.3)',
|
|
219
|
-
borderColor: 'rgba(251, 191, 36, 0.9)',
|
|
220
|
-
},
|
|
221
|
-
},
|
|
222
|
-
}),
|
|
205
|
+
width: '336px',
|
|
206
|
+
overflow: 'visible',
|
|
223
207
|
}}
|
|
224
|
-
onClick={handleJsonClick}
|
|
225
208
|
>
|
|
209
|
+
<Box
|
|
210
|
+
ref={nodeRef}
|
|
211
|
+
sx={{
|
|
212
|
+
width: '336px',
|
|
213
|
+
minHeight: '150px',
|
|
214
|
+
backgroundColor: '#181C25', // New background color from image
|
|
215
|
+
border: selected ? '2px solid #3b82f6' : '1px solid #1e293b',
|
|
216
|
+
borderRadius: '12px',
|
|
217
|
+
color: '#ffffff',
|
|
218
|
+
position: 'relative',
|
|
219
|
+
boxShadow: selected ? '0 0 0 2px rgba(59, 130, 246, 0.5)' : '0 4px 8px rgba(0, 0, 0, 0.3)',
|
|
220
|
+
transition: 'all 0.2s ease',
|
|
221
|
+
cursor: 'pointer',
|
|
222
|
+
overflow: 'hidden',
|
|
223
|
+
...(data.status === 'Running' && {
|
|
224
|
+
animation: 'pulse-glow 2s ease-in-out infinite',
|
|
225
|
+
'@keyframes pulse-glow': {
|
|
226
|
+
'0%, 100%': {
|
|
227
|
+
boxShadow: '0 0 20px rgba(251, 191, 36, 0.4), 0 0 40px rgba(251, 191, 36, 0.2)',
|
|
228
|
+
borderColor: 'rgba(251, 191, 36, 0.6)',
|
|
229
|
+
},
|
|
230
|
+
'50%': {
|
|
231
|
+
boxShadow: '0 0 30px rgba(251, 191, 36, 0.6), 0 0 60px rgba(251, 191, 36, 0.3)',
|
|
232
|
+
borderColor: 'rgba(251, 191, 36, 0.9)',
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
}),
|
|
236
|
+
}}
|
|
237
|
+
onClick={handleJsonClick}
|
|
238
|
+
>
|
|
226
239
|
{/* Top Header Section */}
|
|
227
240
|
<Box sx={{
|
|
228
241
|
backgroundColor: "rgba(67, 93, 132, 0.1)",
|
|
@@ -334,6 +347,99 @@ export const AutomationEndNode: React.FC<AutomationEndNodeProps> = ({ data, sele
|
|
|
334
347
|
opacity: 0, // Hidden but functional
|
|
335
348
|
}}
|
|
336
349
|
/>
|
|
350
|
+
</Box>
|
|
351
|
+
|
|
352
|
+
{/* AI Suggestions Button - Positioned below the node box */}
|
|
353
|
+
{data.formData?.aiSuggestionsCount !== undefined && data.formData.aiSuggestionsCount > 0 && (
|
|
354
|
+
<Box
|
|
355
|
+
sx={{
|
|
356
|
+
position: 'absolute',
|
|
357
|
+
top: '100%',
|
|
358
|
+
left: '50%',
|
|
359
|
+
transform: 'translateX(-50%)',
|
|
360
|
+
marginTop: '12px',
|
|
361
|
+
zIndex: 10,
|
|
362
|
+
whiteSpace: 'nowrap',
|
|
363
|
+
}}
|
|
364
|
+
onClick={(e) => {
|
|
365
|
+
e.stopPropagation();
|
|
366
|
+
// Toggle AI Suggestions panel
|
|
367
|
+
setShowSuggestions(!showSuggestions);
|
|
368
|
+
}}
|
|
369
|
+
>
|
|
370
|
+
<Button
|
|
371
|
+
variant="contained"
|
|
372
|
+
startIcon={<LightbulbIcon sx={{ fontSize: '12px' }} />}
|
|
373
|
+
sx={{
|
|
374
|
+
backgroundColor: '#2563EB',
|
|
375
|
+
color: '#ffffff',
|
|
376
|
+
borderRadius: '20px',
|
|
377
|
+
textTransform: 'none',
|
|
378
|
+
fontSize: '10px',
|
|
379
|
+
fontWeight: 400,
|
|
380
|
+
padding: '8px 16px',
|
|
381
|
+
whiteSpace: 'nowrap',
|
|
382
|
+
display: 'inline-flex',
|
|
383
|
+
alignItems: 'center',
|
|
384
|
+
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.3)',
|
|
385
|
+
'&:hover': {
|
|
386
|
+
backgroundColor: '#2563eb',
|
|
387
|
+
},
|
|
388
|
+
'& .MuiButton-startIcon': {
|
|
389
|
+
marginRight: '8px',
|
|
390
|
+
}
|
|
391
|
+
}}
|
|
392
|
+
>
|
|
393
|
+
AI Suggestions
|
|
394
|
+
<Box
|
|
395
|
+
component="span"
|
|
396
|
+
sx={{
|
|
397
|
+
marginLeft: '8px',
|
|
398
|
+
backgroundColor: '#FFFFFF26',
|
|
399
|
+
color: '#ffffff',
|
|
400
|
+
fontSize: '10px',
|
|
401
|
+
fontWeight: 400,
|
|
402
|
+
minWidth: '18px',
|
|
403
|
+
height: '18px',
|
|
404
|
+
borderRadius: '9px',
|
|
405
|
+
display: 'inline-flex',
|
|
406
|
+
alignItems: 'center',
|
|
407
|
+
justifyContent: 'center',
|
|
408
|
+
padding: '0 6px',
|
|
409
|
+
border: '1px solid rgba(255, 255, 255, 0.2)',
|
|
410
|
+
}}
|
|
411
|
+
>
|
|
412
|
+
{data.formData.aiSuggestionsCount}
|
|
413
|
+
</Box>
|
|
414
|
+
</Button>
|
|
415
|
+
</Box>
|
|
416
|
+
)}
|
|
417
|
+
|
|
418
|
+
{/* AI Suggestions Panel - Rendered on canvas below the button */}
|
|
419
|
+
{showSuggestions && data.formData?.aiSuggestionsCount !== undefined && data.formData.aiSuggestionsCount > 0 && nodeId && (
|
|
420
|
+
<AISuggestionsPanel
|
|
421
|
+
suggestions={data.formData?.aiSuggestions || [
|
|
422
|
+
{
|
|
423
|
+
id: '1',
|
|
424
|
+
title: 'Add Citation Extraction',
|
|
425
|
+
description: 'Automatically extract and format citations from article content.',
|
|
426
|
+
tags: ['classification', 'enhancement'],
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
id: '2',
|
|
430
|
+
title: 'Generate Bullet Summary',
|
|
431
|
+
description: 'Create a concise bullet-point summary of the article\'s main points.',
|
|
432
|
+
tags: ['classification', 'enhancement'],
|
|
433
|
+
},
|
|
434
|
+
]}
|
|
435
|
+
parentNodeId={nodeId}
|
|
436
|
+
onSuggestionClick={(suggestion) => {
|
|
437
|
+
console.log('Suggestion clicked:', suggestion);
|
|
438
|
+
// Handle suggestion selection here
|
|
439
|
+
}}
|
|
440
|
+
onClose={() => setShowSuggestions(false)}
|
|
441
|
+
/>
|
|
442
|
+
)}
|
|
337
443
|
</Box>
|
|
338
444
|
);
|
|
339
445
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useState, useRef } from 'react';
|
|
2
2
|
import { createRoot } from 'react-dom/client';
|
|
3
3
|
import { Handle, Position, useNodeId } from '@xyflow/react';
|
|
4
|
-
import { Box, Typography, Chip, IconButton, Card, CardContent } from '@mui/material';
|
|
4
|
+
import { Box, Typography, Chip, IconButton, Card, CardContent, Button } from '@mui/material';
|
|
5
5
|
import {
|
|
6
6
|
Psychology as PsychologyIcon,
|
|
7
7
|
AccessTime as AccessTimeIcon,
|
|
@@ -9,13 +9,16 @@ import {
|
|
|
9
9
|
FilterList as FilterIcon,
|
|
10
10
|
Send as SendIcon,
|
|
11
11
|
Settings as SettingsIcon,
|
|
12
|
-
Storage as StorageIcon
|
|
12
|
+
Storage as StorageIcon,
|
|
13
|
+
Lightbulb as LightbulbIcon
|
|
13
14
|
} from '@mui/icons-material';
|
|
14
15
|
import { RiCloseLine, RiUser2Line } from 'react-icons/ri';
|
|
15
16
|
import ReactJson from 'react-json-view';
|
|
16
17
|
import { getIconByName } from '../../utils/iconMapper';
|
|
17
18
|
import { useTranslation } from 'react-i18next';
|
|
18
19
|
import { useDiagram } from '../../contexts/DiagramProvider';
|
|
20
|
+
import { AISuggestion } from './AISuggestionsModal';
|
|
21
|
+
import { AISuggestionsPanel } from './AISuggestionsPanel';
|
|
19
22
|
|
|
20
23
|
interface AutomationFormattingNodeProps {
|
|
21
24
|
data: {
|
|
@@ -51,6 +54,7 @@ interface AutomationFormattingNodeProps {
|
|
|
51
54
|
label: string;
|
|
52
55
|
iconColor: string;
|
|
53
56
|
}>;
|
|
57
|
+
aiSuggestionsCount?: number; // Number of AI suggestions available
|
|
54
58
|
[key: string]: any;
|
|
55
59
|
}; // Include formData for configuration
|
|
56
60
|
};
|
|
@@ -60,6 +64,7 @@ interface AutomationFormattingNodeProps {
|
|
|
60
64
|
export const AutomationFormattingNode: React.FC<AutomationFormattingNodeProps> = ({ data, selected }) => {
|
|
61
65
|
const { t } = useTranslation();
|
|
62
66
|
const [isJsonOpen, setIsJsonOpen] = useState(false);
|
|
67
|
+
const [showSuggestions, setShowSuggestions] = useState(false);
|
|
63
68
|
const rootRef = useRef<any>(null);
|
|
64
69
|
const portalRef = useRef<HTMLDivElement | null>(null);
|
|
65
70
|
const nodeRef = useRef<HTMLDivElement | null>(null);
|
|
@@ -269,35 +274,42 @@ export const AutomationFormattingNode: React.FC<AutomationFormattingNodeProps> =
|
|
|
269
274
|
|
|
270
275
|
return (
|
|
271
276
|
<Box
|
|
272
|
-
ref={nodeRef}
|
|
273
277
|
sx={{
|
|
274
|
-
width: '336px',
|
|
275
|
-
minHeight: '150px',
|
|
276
|
-
backgroundColor: '#181C25', // New background color from image
|
|
277
|
-
border: selected ? '2px solid #3b82f6' : '1px solid #1e293b',
|
|
278
|
-
borderRadius: '12px',
|
|
279
|
-
color: '#ffffff',
|
|
280
278
|
position: 'relative',
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
cursor: 'pointer',
|
|
284
|
-
overflow: 'hidden',
|
|
285
|
-
...(data.status === 'Running' && {
|
|
286
|
-
animation: 'pulse-glow 2s ease-in-out infinite',
|
|
287
|
-
'@keyframes pulse-glow': {
|
|
288
|
-
'0%, 100%': {
|
|
289
|
-
boxShadow: '0 0 20px rgba(251, 191, 36, 0.4), 0 0 40px rgba(251, 191, 36, 0.2)',
|
|
290
|
-
borderColor: 'rgba(251, 191, 36, 0.6)',
|
|
291
|
-
},
|
|
292
|
-
'50%': {
|
|
293
|
-
boxShadow: '0 0 30px rgba(251, 191, 36, 0.6), 0 0 60px rgba(251, 191, 36, 0.3)',
|
|
294
|
-
borderColor: 'rgba(251, 191, 36, 0.9)',
|
|
295
|
-
},
|
|
296
|
-
},
|
|
297
|
-
}),
|
|
279
|
+
width: '336px',
|
|
280
|
+
overflow: 'visible',
|
|
298
281
|
}}
|
|
299
|
-
onClick={handleJsonClick}
|
|
300
282
|
>
|
|
283
|
+
<Box
|
|
284
|
+
ref={nodeRef}
|
|
285
|
+
sx={{
|
|
286
|
+
width: '336px',
|
|
287
|
+
minHeight: '150px',
|
|
288
|
+
backgroundColor: '#181C25', // New background color from image
|
|
289
|
+
border: selected ? '2px solid #3b82f6' : '1px solid #1e293b',
|
|
290
|
+
borderRadius: '12px',
|
|
291
|
+
color: '#ffffff',
|
|
292
|
+
position: 'relative',
|
|
293
|
+
boxShadow: selected ? '0 0 0 2px rgba(59, 130, 246, 0.5)' : '0 4px 8px rgba(0, 0, 0, 0.3)',
|
|
294
|
+
transition: 'all 0.2s ease',
|
|
295
|
+
cursor: 'pointer',
|
|
296
|
+
overflow: 'hidden',
|
|
297
|
+
...(data.status === 'Running' && {
|
|
298
|
+
animation: 'pulse-glow 2s ease-in-out infinite',
|
|
299
|
+
'@keyframes pulse-glow': {
|
|
300
|
+
'0%, 100%': {
|
|
301
|
+
boxShadow: '0 0 20px rgba(251, 191, 36, 0.4), 0 0 40px rgba(251, 191, 36, 0.2)',
|
|
302
|
+
borderColor: 'rgba(251, 191, 36, 0.6)',
|
|
303
|
+
},
|
|
304
|
+
'50%': {
|
|
305
|
+
boxShadow: '0 0 30px rgba(251, 191, 36, 0.6), 0 0 60px rgba(251, 191, 36, 0.3)',
|
|
306
|
+
borderColor: 'rgba(251, 191, 36, 0.9)',
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
}),
|
|
310
|
+
}}
|
|
311
|
+
onClick={handleJsonClick}
|
|
312
|
+
>
|
|
301
313
|
{/* Top Header Section */}
|
|
302
314
|
<Box sx={{
|
|
303
315
|
backgroundColor: "rgba(67, 93, 132, 0.1)",
|
|
@@ -573,6 +585,99 @@ export const AutomationFormattingNode: React.FC<AutomationFormattingNodeProps> =
|
|
|
573
585
|
opacity: 0, // Hidden but functional
|
|
574
586
|
}}
|
|
575
587
|
/>
|
|
588
|
+
</Box>
|
|
589
|
+
|
|
590
|
+
{/* AI Suggestions Button - Positioned below the node box */}
|
|
591
|
+
{data.formData?.aiSuggestionsCount !== undefined && data.formData.aiSuggestionsCount > 0 && (
|
|
592
|
+
<Box
|
|
593
|
+
sx={{
|
|
594
|
+
position: 'absolute',
|
|
595
|
+
top: '100%',
|
|
596
|
+
left: '50%',
|
|
597
|
+
transform: 'translateX(-50%)',
|
|
598
|
+
marginTop: '12px',
|
|
599
|
+
zIndex: 10,
|
|
600
|
+
whiteSpace: 'nowrap',
|
|
601
|
+
}}
|
|
602
|
+
onClick={(e) => {
|
|
603
|
+
e.stopPropagation();
|
|
604
|
+
// Toggle AI Suggestions panel
|
|
605
|
+
setShowSuggestions(!showSuggestions);
|
|
606
|
+
}}
|
|
607
|
+
>
|
|
608
|
+
<Button
|
|
609
|
+
variant="contained"
|
|
610
|
+
startIcon={<LightbulbIcon sx={{ fontSize: '12px' }} />}
|
|
611
|
+
sx={{
|
|
612
|
+
backgroundColor: '#2563EB',
|
|
613
|
+
color: '#ffffff',
|
|
614
|
+
borderRadius: '20px',
|
|
615
|
+
textTransform: 'none',
|
|
616
|
+
fontSize: '10px',
|
|
617
|
+
fontWeight: 400,
|
|
618
|
+
padding: '8px 16px',
|
|
619
|
+
whiteSpace: 'nowrap',
|
|
620
|
+
display: 'inline-flex',
|
|
621
|
+
alignItems: 'center',
|
|
622
|
+
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.3)',
|
|
623
|
+
'&:hover': {
|
|
624
|
+
backgroundColor: '#2563eb',
|
|
625
|
+
},
|
|
626
|
+
'& .MuiButton-startIcon': {
|
|
627
|
+
marginRight: '8px',
|
|
628
|
+
}
|
|
629
|
+
}}
|
|
630
|
+
>
|
|
631
|
+
AI Suggestions
|
|
632
|
+
<Box
|
|
633
|
+
component="span"
|
|
634
|
+
sx={{
|
|
635
|
+
marginLeft: '8px',
|
|
636
|
+
backgroundColor: '#FFFFFF26',
|
|
637
|
+
color: '#ffffff',
|
|
638
|
+
fontSize: '10px',
|
|
639
|
+
fontWeight: 400,
|
|
640
|
+
minWidth: '18px',
|
|
641
|
+
height: '18px',
|
|
642
|
+
borderRadius: '9px',
|
|
643
|
+
display: 'inline-flex',
|
|
644
|
+
alignItems: 'center',
|
|
645
|
+
justifyContent: 'center',
|
|
646
|
+
padding: '0 6px',
|
|
647
|
+
border: '1px solid rgba(255, 255, 255, 0.2)',
|
|
648
|
+
}}
|
|
649
|
+
>
|
|
650
|
+
{data.formData.aiSuggestionsCount}
|
|
651
|
+
</Box>
|
|
652
|
+
</Button>
|
|
653
|
+
</Box>
|
|
654
|
+
)}
|
|
655
|
+
|
|
656
|
+
{/* AI Suggestions Panel - Rendered on canvas below the button */}
|
|
657
|
+
{showSuggestions && data.formData?.aiSuggestionsCount !== undefined && data.formData.aiSuggestionsCount > 0 && nodeId && (
|
|
658
|
+
<AISuggestionsPanel
|
|
659
|
+
suggestions={data.formData?.aiSuggestions || [
|
|
660
|
+
{
|
|
661
|
+
id: '1',
|
|
662
|
+
title: 'Add Citation Extraction',
|
|
663
|
+
description: 'Automatically extract and format citations from article content.',
|
|
664
|
+
tags: ['classification', 'enhancement'],
|
|
665
|
+
},
|
|
666
|
+
{
|
|
667
|
+
id: '2',
|
|
668
|
+
title: 'Generate Bullet Summary',
|
|
669
|
+
description: 'Create a concise bullet-point summary of the article\'s main points.',
|
|
670
|
+
tags: ['classification', 'enhancement'],
|
|
671
|
+
},
|
|
672
|
+
]}
|
|
673
|
+
parentNodeId={nodeId}
|
|
674
|
+
onSuggestionClick={(suggestion) => {
|
|
675
|
+
console.log('Suggestion clicked:', suggestion);
|
|
676
|
+
// Handle suggestion selection here
|
|
677
|
+
}}
|
|
678
|
+
onClose={() => setShowSuggestions(false)}
|
|
679
|
+
/>
|
|
680
|
+
)}
|
|
576
681
|
</Box>
|
|
577
682
|
);
|
|
578
683
|
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import React, { useEffect, useRef } from 'react';
|
|
2
|
-
import { Handle, Position } from '@xyflow/react';
|
|
3
|
-
import { Box, Typography } from '@mui/material';
|
|
4
|
-
import { Description as DescriptionIcon } from '@mui/icons-material';
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { Handle, Position, useNodeId } from '@xyflow/react';
|
|
3
|
+
import { Box, Typography, Button } from '@mui/material';
|
|
4
|
+
import { Description as DescriptionIcon, Lightbulb as LightbulbIcon } from '@mui/icons-material';
|
|
5
5
|
import { getIconByName } from '../../utils/iconMapper';
|
|
6
|
+
import { AISuggestion } from './AISuggestionsModal';
|
|
7
|
+
import { AISuggestionsPanel } from './AISuggestionsPanel';
|
|
6
8
|
|
|
7
9
|
interface AutomationNoteNodeProps {
|
|
8
10
|
data: {
|
|
@@ -13,13 +15,18 @@ interface AutomationNoteNodeProps {
|
|
|
13
15
|
borderColor?: string;
|
|
14
16
|
iconName?: string;
|
|
15
17
|
noteType?: 'info' | 'warning' | 'note' | 'purpose';
|
|
16
|
-
formData?:
|
|
18
|
+
formData?: {
|
|
19
|
+
aiSuggestionsCount?: number; // Number of AI suggestions available
|
|
20
|
+
[key: string]: any;
|
|
21
|
+
};
|
|
17
22
|
};
|
|
18
23
|
selected?: boolean;
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
export const AutomationNoteNode: React.FC<AutomationNoteNodeProps> = ({ data, selected }) => {
|
|
22
27
|
const nodeRef = useRef<HTMLDivElement | null>(null);
|
|
28
|
+
const [showSuggestions, setShowSuggestions] = useState(false);
|
|
29
|
+
const nodeId = useNodeId();
|
|
23
30
|
|
|
24
31
|
// Get the icon component based on the iconName, default to DescriptionIcon
|
|
25
32
|
const IconComponent = getIconByName(data.iconName || 'Description');
|
|
@@ -63,22 +70,29 @@ export const AutomationNoteNode: React.FC<AutomationNoteNodeProps> = ({ data, se
|
|
|
63
70
|
|
|
64
71
|
return (
|
|
65
72
|
<Box
|
|
66
|
-
ref={nodeRef}
|
|
67
73
|
sx={{
|
|
68
|
-
width: '336px',
|
|
69
|
-
minHeight: '150px',
|
|
70
|
-
backgroundColor: colors.backgroundColor,
|
|
71
|
-
border: selected ? `2px solid ${colors.borderColor}` : `1px solid ${colors.borderColor}`,
|
|
72
|
-
borderRadius: '12px',
|
|
73
|
-
padding: '0',
|
|
74
|
-
color: colors.textColor,
|
|
75
74
|
position: 'relative',
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
cursor: 'pointer',
|
|
79
|
-
overflow: 'hidden',
|
|
75
|
+
width: '336px',
|
|
76
|
+
overflow: 'visible',
|
|
80
77
|
}}
|
|
81
78
|
>
|
|
79
|
+
<Box
|
|
80
|
+
ref={nodeRef}
|
|
81
|
+
sx={{
|
|
82
|
+
width: '336px',
|
|
83
|
+
minHeight: '150px',
|
|
84
|
+
backgroundColor: colors.backgroundColor,
|
|
85
|
+
border: selected ? `2px solid ${colors.borderColor}` : `1px solid ${colors.borderColor}`,
|
|
86
|
+
borderRadius: '12px',
|
|
87
|
+
padding: '0',
|
|
88
|
+
color: colors.textColor,
|
|
89
|
+
position: 'relative',
|
|
90
|
+
boxShadow: selected ? `0 0 0 2px rgba(59, 130, 246, 0.5)` : '0 4px 8px rgba(0, 0, 0, 0.3)',
|
|
91
|
+
transition: 'all 0.2s ease',
|
|
92
|
+
cursor: 'pointer',
|
|
93
|
+
overflow: 'hidden',
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
82
96
|
{/* Header */}
|
|
83
97
|
<Box sx={{
|
|
84
98
|
display: 'flex',
|
|
@@ -163,6 +177,99 @@ export const AutomationNoteNode: React.FC<AutomationNoteNodeProps> = ({ data, se
|
|
|
163
177
|
opacity: 0, // Hidden but functional
|
|
164
178
|
}}
|
|
165
179
|
/>
|
|
180
|
+
</Box>
|
|
181
|
+
|
|
182
|
+
{/* AI Suggestions Button - Positioned below the node box */}
|
|
183
|
+
{data.formData?.aiSuggestionsCount !== undefined && data.formData.aiSuggestionsCount > 0 && (
|
|
184
|
+
<Box
|
|
185
|
+
sx={{
|
|
186
|
+
position: 'absolute',
|
|
187
|
+
top: '100%',
|
|
188
|
+
left: '50%',
|
|
189
|
+
transform: 'translateX(-50%)',
|
|
190
|
+
marginTop: '12px',
|
|
191
|
+
zIndex: 10,
|
|
192
|
+
whiteSpace: 'nowrap',
|
|
193
|
+
}}
|
|
194
|
+
onClick={(e) => {
|
|
195
|
+
e.stopPropagation();
|
|
196
|
+
// Toggle AI Suggestions panel
|
|
197
|
+
setShowSuggestions(!showSuggestions);
|
|
198
|
+
}}
|
|
199
|
+
>
|
|
200
|
+
<Button
|
|
201
|
+
variant="contained"
|
|
202
|
+
startIcon={<LightbulbIcon sx={{ fontSize: '12px' }} />}
|
|
203
|
+
sx={{
|
|
204
|
+
backgroundColor: '#2563EB',
|
|
205
|
+
color: '#ffffff',
|
|
206
|
+
borderRadius: '20px',
|
|
207
|
+
textTransform: 'none',
|
|
208
|
+
fontSize: '10px',
|
|
209
|
+
fontWeight: 400,
|
|
210
|
+
padding: '8px 16px',
|
|
211
|
+
whiteSpace: 'nowrap',
|
|
212
|
+
display: 'inline-flex',
|
|
213
|
+
alignItems: 'center',
|
|
214
|
+
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.3)',
|
|
215
|
+
'&:hover': {
|
|
216
|
+
backgroundColor: '#2563eb',
|
|
217
|
+
},
|
|
218
|
+
'& .MuiButton-startIcon': {
|
|
219
|
+
marginRight: '8px',
|
|
220
|
+
}
|
|
221
|
+
}}
|
|
222
|
+
>
|
|
223
|
+
AI Suggestions
|
|
224
|
+
<Box
|
|
225
|
+
component="span"
|
|
226
|
+
sx={{
|
|
227
|
+
marginLeft: '8px',
|
|
228
|
+
backgroundColor: '#FFFFFF26',
|
|
229
|
+
color: '#ffffff',
|
|
230
|
+
fontSize: '10px',
|
|
231
|
+
fontWeight: 400,
|
|
232
|
+
minWidth: '18px',
|
|
233
|
+
height: '18px',
|
|
234
|
+
borderRadius: '9px',
|
|
235
|
+
display: 'inline-flex',
|
|
236
|
+
alignItems: 'center',
|
|
237
|
+
justifyContent: 'center',
|
|
238
|
+
padding: '0 6px',
|
|
239
|
+
border: '1px solid rgba(255, 255, 255, 0.2)',
|
|
240
|
+
}}
|
|
241
|
+
>
|
|
242
|
+
{data.formData.aiSuggestionsCount}
|
|
243
|
+
</Box>
|
|
244
|
+
</Button>
|
|
245
|
+
</Box>
|
|
246
|
+
)}
|
|
247
|
+
|
|
248
|
+
{/* AI Suggestions Panel - Rendered on canvas below the button */}
|
|
249
|
+
{showSuggestions && data.formData?.aiSuggestionsCount !== undefined && data.formData.aiSuggestionsCount > 0 && nodeId && (
|
|
250
|
+
<AISuggestionsPanel
|
|
251
|
+
suggestions={data.formData?.aiSuggestions || [
|
|
252
|
+
{
|
|
253
|
+
id: '1',
|
|
254
|
+
title: 'Add Citation Extraction',
|
|
255
|
+
description: 'Automatically extract and format citations from article content.',
|
|
256
|
+
tags: ['classification', 'enhancement'],
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
id: '2',
|
|
260
|
+
title: 'Generate Bullet Summary',
|
|
261
|
+
description: 'Create a concise bullet-point summary of the article\'s main points.',
|
|
262
|
+
tags: ['classification', 'enhancement'],
|
|
263
|
+
},
|
|
264
|
+
]}
|
|
265
|
+
parentNodeId={nodeId}
|
|
266
|
+
onSuggestionClick={(suggestion) => {
|
|
267
|
+
console.log('Suggestion clicked:', suggestion);
|
|
268
|
+
// Handle suggestion selection here
|
|
269
|
+
}}
|
|
270
|
+
onClose={() => setShowSuggestions(false)}
|
|
271
|
+
/>
|
|
272
|
+
)}
|
|
166
273
|
</Box>
|
|
167
274
|
);
|
|
168
275
|
};
|