@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
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Translation Fix Summary
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
Translation keys (like `tooltip.clear`, `button.save`) were showing instead of actual text when using the published npm library in another app.
|
|
5
|
+
|
|
6
|
+
## Root Cause
|
|
7
|
+
The translation files were in the `apps/workflow/locales` folder (not part of the library) and were not being bundled with the published npm package. The library code was using `useTranslation()` hooks but had no way to access the translation resources.
|
|
8
|
+
|
|
9
|
+
## Solution Implemented
|
|
10
|
+
|
|
11
|
+
### 1. Moved Translation Files to Library
|
|
12
|
+
- ✅ Created `packages/diagrams/locales/en/translation.json`
|
|
13
|
+
- ✅ Copied translation files from apps to library
|
|
14
|
+
|
|
15
|
+
### 2. Updated Build Configuration
|
|
16
|
+
- ✅ Modified `packages/diagrams/project.json` to include locales folder in build assets
|
|
17
|
+
- ✅ This ensures translations are bundled with the npm package
|
|
18
|
+
|
|
19
|
+
### 3. Created i18n Configuration
|
|
20
|
+
- ✅ Created `packages/diagrams/src/lib/i18n.ts` with:
|
|
21
|
+
- `initDiagramsI18n()` - Function to initialize translations
|
|
22
|
+
- `translationEN` - Export of translation resources
|
|
23
|
+
- Auto-initialization if i18n not already configured
|
|
24
|
+
|
|
25
|
+
### 4. Updated Package Dependencies
|
|
26
|
+
- ✅ Added `i18next` and `react-i18next` to package.json dependencies
|
|
27
|
+
|
|
28
|
+
### 5. Updated Exports
|
|
29
|
+
- ✅ Modified `packages/diagrams/src/index.ts` to export i18n functionality
|
|
30
|
+
|
|
31
|
+
### 6. Created Documentation
|
|
32
|
+
- ✅ Created `I18N_SETUP.md` with detailed setup instructions
|
|
33
|
+
- ✅ Updated `README.md` with quick start guide
|
|
34
|
+
|
|
35
|
+
## How Consumers Should Use the Library
|
|
36
|
+
|
|
37
|
+
### In their main.tsx or index.tsx (BEFORE rendering components):
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { initDiagramsI18n } from '@flowuent-labs/diagrams';
|
|
41
|
+
|
|
42
|
+
// Initialize i18n
|
|
43
|
+
initDiagramsI18n();
|
|
44
|
+
|
|
45
|
+
// Then render your app
|
|
46
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(<App />);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Next Steps
|
|
50
|
+
|
|
51
|
+
1. **Fix Build Issue** (Separate from i18n):
|
|
52
|
+
The build is failing due to TypeScript path configuration issues (mixing Unix `/Users` and Windows `C:` paths). This is a pre-existing issue unrelated to the i18n changes. You may need to:
|
|
53
|
+
- Check your `tsconfig.json` and `tsconfig.lib.json`
|
|
54
|
+
- Ensure consistent path separators
|
|
55
|
+
- Or build on a single platform (all Unix or all Windows paths)
|
|
56
|
+
|
|
57
|
+
2. **Test the Build**:
|
|
58
|
+
Once the path issue is resolved, rebuild:
|
|
59
|
+
```bash
|
|
60
|
+
nx build diagrams
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
3. **Verify Translation Files Are Included**:
|
|
64
|
+
After successful build, check `dist/packages/diagrams/locales/` exists
|
|
65
|
+
|
|
66
|
+
4. **Publish Updated Package**:
|
|
67
|
+
```bash
|
|
68
|
+
cd packages/diagrams
|
|
69
|
+
npm version patch # or minor/major
|
|
70
|
+
npm publish
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
5. **Update Consumer Apps**:
|
|
74
|
+
In apps using the library:
|
|
75
|
+
```bash
|
|
76
|
+
npm update @flowuent-labs/diagrams
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Then add initialization:
|
|
80
|
+
```typescript
|
|
81
|
+
import { initDiagramsI18n } from '@flowuent-labs/diagrams';
|
|
82
|
+
initDiagramsI18n(); // Add this before rendering
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Alternative: Quick Fix Without Rebuilding
|
|
86
|
+
|
|
87
|
+
If you need an immediate fix before resolving the build issues, consumers can manually add translations:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import i18n from 'i18next';
|
|
91
|
+
import { initReactI18next } from 'react-i18next';
|
|
92
|
+
|
|
93
|
+
// Manually import/copy the translation.json content
|
|
94
|
+
const translations = { /* paste translation.json content */ };
|
|
95
|
+
|
|
96
|
+
i18n.use(initReactI18next).init({
|
|
97
|
+
resources: {
|
|
98
|
+
en: {
|
|
99
|
+
translation: translations
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
fallbackLng: 'en',
|
|
103
|
+
interpolation: {
|
|
104
|
+
escapeValue: false
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Files Modified/Created
|
|
110
|
+
|
|
111
|
+
1. ✅ `packages/diagrams/locales/en/translation.json` (new)
|
|
112
|
+
2. ✅ `packages/diagrams/src/lib/i18n.ts` (new)
|
|
113
|
+
3. ✅ `packages/diagrams/src/index.ts` (modified)
|
|
114
|
+
4. ✅ `packages/diagrams/project.json` (modified - assets config)
|
|
115
|
+
5. ✅ `packages/diagrams/package.json` (modified - added i18n deps)
|
|
116
|
+
6. ✅ `packages/diagrams/README.md` (updated)
|
|
117
|
+
7. ✅ `packages/diagrams/I18N_SETUP.md` (new)
|
|
118
|
+
|
|
@@ -1,205 +1,205 @@
|
|
|
1
|
-
import React, { useEffect } from 'react';
|
|
2
|
-
import { Button, Card, IconButton, Tab, Tabs } from '@mui/material';
|
|
3
|
-
import CloseIcon from '@mui/icons-material/Close';
|
|
4
|
-
import {
|
|
5
|
-
DiagrammingPage,
|
|
6
|
-
DownloadPanel,
|
|
7
|
-
NodeForm,
|
|
8
|
-
PropertiesPane,
|
|
9
|
-
useDiagramEdges,
|
|
10
|
-
useDiagramId,
|
|
11
|
-
useDiagramNodes,
|
|
12
|
-
FunctionSignature,
|
|
13
|
-
FunctionParameter,
|
|
14
|
-
} from '@flowuent-labs/diagrams';
|
|
15
|
-
import { useTabStore } from './tabsStore'; // Import the Zustand store
|
|
16
|
-
import { AddNodeView } from './components/AddNodeView';
|
|
17
|
-
import { conditionBuilderData } from './node-data';
|
|
18
|
-
import DiagramTypes from '../../../packages/diagrams/src/lib/types/diagram-types';
|
|
19
|
-
import { AppBar, Toolbar, Box } from '@mui/material';
|
|
20
|
-
import HomeIcon from '@mui/icons-material/Home';
|
|
21
|
-
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
|
|
22
|
-
import { ICardNode } from '../../../packages/diagrams/src/lib/types/card-node';
|
|
23
|
-
import { Edge, Node } from '@xyflow/react';
|
|
24
|
-
import { Node as ReactFlowNode } from 'reactflow';
|
|
25
|
-
import { ICardNodeData } from '../../../packages/diagrams/src/lib/types/card-node';
|
|
26
|
-
import {
|
|
27
|
-
WorkflowNodeContentType,
|
|
28
|
-
RenderAddNodeViewType,
|
|
29
|
-
GetDefaultNodeDataType,
|
|
30
|
-
OnChangeEventHandler,
|
|
31
|
-
ConditionBuilderState,
|
|
32
|
-
} from '../../../packages/diagrams/src/lib/contexts/diagramStoreTypes';
|
|
33
|
-
import { AvailableVariable } from '../../../packages/diagrams/src/lib/types/available-variables';
|
|
34
|
-
|
|
35
|
-
// Define the interface for diagram page props
|
|
36
|
-
interface DiagramPageProps {
|
|
37
|
-
onChange?: OnChangeEventHandler;
|
|
38
|
-
availableFunctions: FunctionSignature[];
|
|
39
|
-
availableVariables?: AvailableVariable[];
|
|
40
|
-
id: number;
|
|
41
|
-
workflowNodeContent?: WorkflowNodeContentType;
|
|
42
|
-
renderAddNodeView?: RenderAddNodeViewType;
|
|
43
|
-
getDefaultNodeData?: GetDefaultNodeDataType;
|
|
44
|
-
conditionBuilderStates?: ConditionBuilderState;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Generic type for nodes that can be either ICardNode, Node from @xyflow/react, or Node from reactflow
|
|
48
|
-
type GenericNode = ICardNode | Node | ReactFlowNode;
|
|
49
|
-
|
|
50
|
-
const NodeGetter = () => {
|
|
51
|
-
const updateTabData = useTabStore.use.updateTabData();
|
|
52
|
-
const nodes = useDiagramNodes();
|
|
53
|
-
const edges = useDiagramEdges();
|
|
54
|
-
const id = useDiagramId();
|
|
55
|
-
useEffect(() => {
|
|
56
|
-
//updateTabData(id, nodes, edges);
|
|
57
|
-
}, [nodes, edges, id, updateTabData]);
|
|
58
|
-
|
|
59
|
-
return <div></div>;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
// Transform FunctionObject[] to FunctionSignature[]
|
|
63
|
-
const transformFunctions = (functionObjects: Array<{
|
|
64
|
-
id: string;
|
|
65
|
-
name: string;
|
|
66
|
-
args: string[];
|
|
67
|
-
code: string;
|
|
68
|
-
}>): FunctionSignature[] => {
|
|
69
|
-
return functionObjects.map(func => ({
|
|
70
|
-
id: func.id,
|
|
71
|
-
name: func.name,
|
|
72
|
-
code: func.code,
|
|
73
|
-
args: func.args.map((arg: string): FunctionParameter => ({
|
|
74
|
-
name: arg,
|
|
75
|
-
type: 'any'
|
|
76
|
-
}))
|
|
77
|
-
}));
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const DiagramTabs = ({
|
|
81
|
-
defaultNodes,
|
|
82
|
-
defaultEdges,
|
|
83
|
-
children,
|
|
84
|
-
diagramType,
|
|
85
|
-
diagramPageProps = {},
|
|
86
|
-
}: {
|
|
87
|
-
defaultNodes: GenericNode[];
|
|
88
|
-
defaultEdges: Edge[];
|
|
89
|
-
children?: React.ReactNode;
|
|
90
|
-
diagramType: DiagramTypes;
|
|
91
|
-
diagramPageProps?: Partial<DiagramPageProps>;
|
|
92
|
-
}) => {
|
|
93
|
-
const {
|
|
94
|
-
tabs,
|
|
95
|
-
currentTab,
|
|
96
|
-
addTab,
|
|
97
|
-
removeTab,
|
|
98
|
-
availableFunctions,
|
|
99
|
-
setCurrentTab,
|
|
100
|
-
setTabs,
|
|
101
|
-
} = useTabStore();
|
|
102
|
-
|
|
103
|
-
// Ensure the first tab is initialized with default nodes/edges
|
|
104
|
-
useEffect(() => {
|
|
105
|
-
if (
|
|
106
|
-
tabs.length === 1 &&
|
|
107
|
-
tabs[0].nodes.length === 0 &&
|
|
108
|
-
tabs[0].edges.length === 0 &&
|
|
109
|
-
(defaultNodes.length > 0 || defaultEdges.length > 0)
|
|
110
|
-
) {
|
|
111
|
-
setTabs([
|
|
112
|
-
{
|
|
113
|
-
...tabs[0],
|
|
114
|
-
nodes: defaultNodes,
|
|
115
|
-
edges: defaultEdges,
|
|
116
|
-
},
|
|
117
|
-
]);
|
|
118
|
-
}
|
|
119
|
-
}, [tabs, defaultNodes, defaultEdges, setTabs]);
|
|
120
|
-
|
|
121
|
-
// Reset tabs when diagramType changes
|
|
122
|
-
useEffect(() => {
|
|
123
|
-
setTabs([
|
|
124
|
-
{
|
|
125
|
-
id: Date.now(),
|
|
126
|
-
title: diagramType.charAt(0).toUpperCase() + diagramType.slice(1) + ' Diagram',
|
|
127
|
-
nodes: defaultNodes,
|
|
128
|
-
edges: defaultEdges,
|
|
129
|
-
},
|
|
130
|
-
]);
|
|
131
|
-
setCurrentTab(0);
|
|
132
|
-
}, [diagramType, defaultNodes, defaultEdges, setTabs, setCurrentTab]);
|
|
133
|
-
|
|
134
|
-
return (
|
|
135
|
-
<div>
|
|
136
|
-
{/* Tab Navigation - now using AppBar */}
|
|
137
|
-
<AppBar position="fixed" sx={{ bgcolor: '#1C1616', boxShadow: 2, borderBottom: '1px solid #23232a', top: 0, width: '100%', zIndex: 1000 }}>
|
|
138
|
-
<Toolbar sx={{ minHeight: 56, px: 2, display: 'flex', justifyContent: 'space-between' }}>
|
|
139
|
-
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
|
140
|
-
<IconButton edge="start" color="inherit" aria-label="home" sx={{ mr: 2 }}>
|
|
141
|
-
<HomeIcon sx={{ color: '#fff' }} />
|
|
142
|
-
</IconButton>
|
|
143
|
-
<Tabs
|
|
144
|
-
value={currentTab}
|
|
145
|
-
onChange={(_, newValue) => setCurrentTab(newValue)}
|
|
146
|
-
textColor="inherit"
|
|
147
|
-
indicatorColor="secondary"
|
|
148
|
-
sx={{ minHeight: 40, '& .MuiTab-root': { color: '#fff', minWidth: 120, borderRadius: 2, mx: 1, bgcolor: '#23232a', fontWeight: 500 }, '& .Mui-selected': { bgcolor: '#111', color: '#fff' }, }}
|
|
149
|
-
>
|
|
150
|
-
{tabs.map((tab, index) => (
|
|
151
|
-
<Tab
|
|
152
|
-
key={tab.id}
|
|
153
|
-
label={
|
|
154
|
-
<div style={{ display: 'flex', alignItems: 'center' }}>
|
|
155
|
-
<span>{tab.title}</span>
|
|
156
|
-
<IconButton
|
|
157
|
-
size="small"
|
|
158
|
-
onClick={(e) => {
|
|
159
|
-
e.stopPropagation();
|
|
160
|
-
removeTab(index);
|
|
161
|
-
}}
|
|
162
|
-
style={{ marginLeft: '8px', padding: '2px' }}
|
|
163
|
-
>
|
|
164
|
-
<CloseIcon fontSize="small" />
|
|
165
|
-
</IconButton>
|
|
166
|
-
</div>
|
|
167
|
-
}
|
|
168
|
-
sx={{ textTransform: 'none', fontSize: 16 }}
|
|
169
|
-
/>
|
|
170
|
-
))}
|
|
171
|
-
</Tabs>
|
|
172
|
-
<Button onClick={() => addTab(defaultNodes, defaultEdges)} sx={{ ml: 2, bgcolor: '#6B04F1', color: '#fff', borderRadius: 2, px: 2, fontWeight: 600, textTransform: 'none', boxShadow: 'none', '&:hover': { bgcolor: '#a084ff' } }}>
|
|
173
|
-
Add Tab
|
|
174
|
-
</Button>
|
|
175
|
-
</Box>
|
|
176
|
-
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
|
177
|
-
<Button variant="contained" sx={{ bgcolor: '#6B04F1', color: '#fff', borderRadius: 2, px: 3, fontWeight: 600, textTransform: 'none', boxShadow: 'none', '&:hover': { bgcolor: '#a084ff' } }}>Share</Button>
|
|
178
|
-
<IconButton color="inherit">
|
|
179
|
-
<AccountCircleIcon sx={{ color: '#fff' }} />
|
|
180
|
-
</IconButton>
|
|
181
|
-
</Box>
|
|
182
|
-
</Toolbar>
|
|
183
|
-
</AppBar>
|
|
184
|
-
|
|
185
|
-
{/* Render Active Diagram */}
|
|
186
|
-
{tabs.map((tab, index) =>
|
|
187
|
-
index === currentTab ? (
|
|
188
|
-
<DiagrammingPage
|
|
189
|
-
availableFunctions={transformFunctions(availableFunctions)}
|
|
190
|
-
id={tab.id}
|
|
191
|
-
key={tab.id}
|
|
192
|
-
defaultNodes={tab.nodes as ICardNode[]}
|
|
193
|
-
defaultEdges={tab.edges}
|
|
194
|
-
diagramType={diagramType}
|
|
195
|
-
{...diagramPageProps}
|
|
196
|
-
>
|
|
197
|
-
{children}
|
|
198
|
-
</DiagrammingPage>
|
|
199
|
-
) : null,
|
|
200
|
-
)}
|
|
201
|
-
</div>
|
|
202
|
-
);
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
export default DiagramTabs;
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { Button, Card, IconButton, Tab, Tabs } from '@mui/material';
|
|
3
|
+
import CloseIcon from '@mui/icons-material/Close';
|
|
4
|
+
import {
|
|
5
|
+
DiagrammingPage,
|
|
6
|
+
DownloadPanel,
|
|
7
|
+
NodeForm,
|
|
8
|
+
PropertiesPane,
|
|
9
|
+
useDiagramEdges,
|
|
10
|
+
useDiagramId,
|
|
11
|
+
useDiagramNodes,
|
|
12
|
+
FunctionSignature,
|
|
13
|
+
FunctionParameter,
|
|
14
|
+
} from '@flowuent-labs/diagrams';
|
|
15
|
+
import { useTabStore } from './tabsStore'; // Import the Zustand store
|
|
16
|
+
import { AddNodeView } from './components/AddNodeView';
|
|
17
|
+
import { conditionBuilderData } from './node-data';
|
|
18
|
+
import DiagramTypes from '../../../packages/diagrams/src/lib/types/diagram-types';
|
|
19
|
+
import { AppBar, Toolbar, Box } from '@mui/material';
|
|
20
|
+
import HomeIcon from '@mui/icons-material/Home';
|
|
21
|
+
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
|
|
22
|
+
import { ICardNode } from '../../../packages/diagrams/src/lib/types/card-node';
|
|
23
|
+
import { Edge, Node } from '@xyflow/react';
|
|
24
|
+
import { Node as ReactFlowNode } from 'reactflow';
|
|
25
|
+
import { ICardNodeData } from '../../../packages/diagrams/src/lib/types/card-node';
|
|
26
|
+
import {
|
|
27
|
+
WorkflowNodeContentType,
|
|
28
|
+
RenderAddNodeViewType,
|
|
29
|
+
GetDefaultNodeDataType,
|
|
30
|
+
OnChangeEventHandler,
|
|
31
|
+
ConditionBuilderState,
|
|
32
|
+
} from '../../../packages/diagrams/src/lib/contexts/diagramStoreTypes';
|
|
33
|
+
import { AvailableVariable } from '../../../packages/diagrams/src/lib/types/available-variables';
|
|
34
|
+
|
|
35
|
+
// Define the interface for diagram page props
|
|
36
|
+
interface DiagramPageProps {
|
|
37
|
+
onChange?: OnChangeEventHandler;
|
|
38
|
+
availableFunctions: FunctionSignature[];
|
|
39
|
+
availableVariables?: AvailableVariable[];
|
|
40
|
+
id: number;
|
|
41
|
+
workflowNodeContent?: WorkflowNodeContentType;
|
|
42
|
+
renderAddNodeView?: RenderAddNodeViewType;
|
|
43
|
+
getDefaultNodeData?: GetDefaultNodeDataType;
|
|
44
|
+
conditionBuilderStates?: ConditionBuilderState;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Generic type for nodes that can be either ICardNode, Node from @xyflow/react, or Node from reactflow
|
|
48
|
+
type GenericNode = ICardNode | Node | ReactFlowNode;
|
|
49
|
+
|
|
50
|
+
const NodeGetter = () => {
|
|
51
|
+
const updateTabData = useTabStore.use.updateTabData();
|
|
52
|
+
const nodes = useDiagramNodes();
|
|
53
|
+
const edges = useDiagramEdges();
|
|
54
|
+
const id = useDiagramId();
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
//updateTabData(id, nodes, edges);
|
|
57
|
+
}, [nodes, edges, id, updateTabData]);
|
|
58
|
+
|
|
59
|
+
return <div></div>;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Transform FunctionObject[] to FunctionSignature[]
|
|
63
|
+
const transformFunctions = (functionObjects: Array<{
|
|
64
|
+
id: string;
|
|
65
|
+
name: string;
|
|
66
|
+
args: string[];
|
|
67
|
+
code: string;
|
|
68
|
+
}>): FunctionSignature[] => {
|
|
69
|
+
return functionObjects.map(func => ({
|
|
70
|
+
id: func.id,
|
|
71
|
+
name: func.name,
|
|
72
|
+
code: func.code,
|
|
73
|
+
args: func.args.map((arg: string): FunctionParameter => ({
|
|
74
|
+
name: arg,
|
|
75
|
+
type: 'any'
|
|
76
|
+
}))
|
|
77
|
+
}));
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const DiagramTabs = ({
|
|
81
|
+
defaultNodes,
|
|
82
|
+
defaultEdges,
|
|
83
|
+
children,
|
|
84
|
+
diagramType,
|
|
85
|
+
diagramPageProps = {},
|
|
86
|
+
}: {
|
|
87
|
+
defaultNodes: GenericNode[];
|
|
88
|
+
defaultEdges: Edge[];
|
|
89
|
+
children?: React.ReactNode;
|
|
90
|
+
diagramType: DiagramTypes;
|
|
91
|
+
diagramPageProps?: Partial<DiagramPageProps>;
|
|
92
|
+
}) => {
|
|
93
|
+
const {
|
|
94
|
+
tabs,
|
|
95
|
+
currentTab,
|
|
96
|
+
addTab,
|
|
97
|
+
removeTab,
|
|
98
|
+
availableFunctions,
|
|
99
|
+
setCurrentTab,
|
|
100
|
+
setTabs,
|
|
101
|
+
} = useTabStore();
|
|
102
|
+
|
|
103
|
+
// Ensure the first tab is initialized with default nodes/edges
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
if (
|
|
106
|
+
tabs.length === 1 &&
|
|
107
|
+
tabs[0].nodes.length === 0 &&
|
|
108
|
+
tabs[0].edges.length === 0 &&
|
|
109
|
+
(defaultNodes.length > 0 || defaultEdges.length > 0)
|
|
110
|
+
) {
|
|
111
|
+
setTabs([
|
|
112
|
+
{
|
|
113
|
+
...tabs[0],
|
|
114
|
+
nodes: defaultNodes,
|
|
115
|
+
edges: defaultEdges,
|
|
116
|
+
},
|
|
117
|
+
]);
|
|
118
|
+
}
|
|
119
|
+
}, [tabs, defaultNodes, defaultEdges, setTabs]);
|
|
120
|
+
|
|
121
|
+
// Reset tabs when diagramType changes
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
setTabs([
|
|
124
|
+
{
|
|
125
|
+
id: Date.now(),
|
|
126
|
+
title: diagramType.charAt(0).toUpperCase() + diagramType.slice(1) + ' Diagram',
|
|
127
|
+
nodes: defaultNodes,
|
|
128
|
+
edges: defaultEdges,
|
|
129
|
+
},
|
|
130
|
+
]);
|
|
131
|
+
setCurrentTab(0);
|
|
132
|
+
}, [diagramType, defaultNodes, defaultEdges, setTabs, setCurrentTab]);
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<div>
|
|
136
|
+
{/* Tab Navigation - now using AppBar */}
|
|
137
|
+
<AppBar position="fixed" sx={{ bgcolor: '#1C1616', boxShadow: 2, borderBottom: '1px solid #23232a', top: 0, width: '100%', zIndex: 1000 }}>
|
|
138
|
+
<Toolbar sx={{ minHeight: 56, px: 2, display: 'flex', justifyContent: 'space-between' }}>
|
|
139
|
+
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
|
140
|
+
<IconButton edge="start" color="inherit" aria-label="home" sx={{ mr: 2 }}>
|
|
141
|
+
<HomeIcon sx={{ color: '#fff' }} />
|
|
142
|
+
</IconButton>
|
|
143
|
+
<Tabs
|
|
144
|
+
value={currentTab}
|
|
145
|
+
onChange={(_, newValue) => setCurrentTab(newValue)}
|
|
146
|
+
textColor="inherit"
|
|
147
|
+
indicatorColor="secondary"
|
|
148
|
+
sx={{ minHeight: 40, '& .MuiTab-root': { color: '#fff', minWidth: 120, borderRadius: 2, mx: 1, bgcolor: '#23232a', fontWeight: 500 }, '& .Mui-selected': { bgcolor: '#111', color: '#fff' }, }}
|
|
149
|
+
>
|
|
150
|
+
{tabs.map((tab, index) => (
|
|
151
|
+
<Tab
|
|
152
|
+
key={tab.id}
|
|
153
|
+
label={
|
|
154
|
+
<div style={{ display: 'flex', alignItems: 'center' }}>
|
|
155
|
+
<span>{tab.title}</span>
|
|
156
|
+
<IconButton
|
|
157
|
+
size="small"
|
|
158
|
+
onClick={(e) => {
|
|
159
|
+
e.stopPropagation();
|
|
160
|
+
removeTab(index);
|
|
161
|
+
}}
|
|
162
|
+
style={{ marginLeft: '8px', padding: '2px' }}
|
|
163
|
+
>
|
|
164
|
+
<CloseIcon fontSize="small" />
|
|
165
|
+
</IconButton>
|
|
166
|
+
</div>
|
|
167
|
+
}
|
|
168
|
+
sx={{ textTransform: 'none', fontSize: 16 }}
|
|
169
|
+
/>
|
|
170
|
+
))}
|
|
171
|
+
</Tabs>
|
|
172
|
+
<Button onClick={() => addTab(defaultNodes, defaultEdges)} sx={{ ml: 2, bgcolor: '#6B04F1', color: '#fff', borderRadius: 2, px: 2, fontWeight: 600, textTransform: 'none', boxShadow: 'none', '&:hover': { bgcolor: '#a084ff' } }}>
|
|
173
|
+
Add Tab
|
|
174
|
+
</Button>
|
|
175
|
+
</Box>
|
|
176
|
+
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
|
177
|
+
<Button variant="contained" sx={{ bgcolor: '#6B04F1', color: '#fff', borderRadius: 2, px: 3, fontWeight: 600, textTransform: 'none', boxShadow: 'none', '&:hover': { bgcolor: '#a084ff' } }}>Share</Button>
|
|
178
|
+
<IconButton color="inherit">
|
|
179
|
+
<AccountCircleIcon sx={{ color: '#fff' }} />
|
|
180
|
+
</IconButton>
|
|
181
|
+
</Box>
|
|
182
|
+
</Toolbar>
|
|
183
|
+
</AppBar>
|
|
184
|
+
|
|
185
|
+
{/* Render Active Diagram */}
|
|
186
|
+
{tabs.map((tab, index) =>
|
|
187
|
+
index === currentTab ? (
|
|
188
|
+
<DiagrammingPage
|
|
189
|
+
availableFunctions={transformFunctions(availableFunctions)}
|
|
190
|
+
id={tab.id}
|
|
191
|
+
key={tab.id}
|
|
192
|
+
defaultNodes={tab.nodes as ICardNode[]}
|
|
193
|
+
defaultEdges={tab.edges}
|
|
194
|
+
diagramType={diagramType}
|
|
195
|
+
{...diagramPageProps}
|
|
196
|
+
>
|
|
197
|
+
{children}
|
|
198
|
+
</DiagrammingPage>
|
|
199
|
+
) : null,
|
|
200
|
+
)}
|
|
201
|
+
</div>
|
|
202
|
+
);
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export default DiagramTabs;
|
|
@@ -1,54 +1,55 @@
|
|
|
1
|
-
// Define the structure of the form data
|
|
2
|
-
import { FormElementBase } from '@flowuent-labs/diagrams';
|
|
3
|
-
|
|
4
|
-
export const sampleWorkflowContent: FormElementBase = {
|
|
5
|
-
type:
|
|
6
|
-
props: {
|
|
7
|
-
title:
|
|
8
|
-
children: [
|
|
9
|
-
/*{
|
|
10
|
-
type: "TextField",
|
|
11
|
-
props: {
|
|
12
|
-
name: "fullName",
|
|
13
|
-
label: "Full Name",
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
type: "TextField",
|
|
18
|
-
props: {
|
|
19
|
-
name: "email",
|
|
20
|
-
label: "Email Address",
|
|
21
|
-
type: "email",
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
type: "TextField",
|
|
26
|
-
props: {
|
|
27
|
-
name: "age",
|
|
28
|
-
label: "Age",
|
|
29
|
-
type: "number",
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
type: "Switch",
|
|
34
|
-
props: {
|
|
35
|
-
name: "notifications",
|
|
36
|
-
label: "Enable Notifications",
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
type: "Select",
|
|
41
|
-
props: {
|
|
42
|
-
name: "country",
|
|
43
|
-
label: "Country",
|
|
44
|
-
options: [
|
|
45
|
-
{ value: "us", label: "United States" },
|
|
46
|
-
{ value: "ca", label: "Canada" },
|
|
47
|
-
{ value: "uk", label: "United Kingdom" },
|
|
48
|
-
{ value: "au", label: "Australia" },
|
|
49
|
-
],
|
|
50
|
-
},
|
|
51
|
-
},*/
|
|
52
|
-
],
|
|
53
|
-
},
|
|
54
|
-
};
|
|
1
|
+
// Define the structure of the form data
|
|
2
|
+
import { FormElementBase } from '@flowuent-labs/diagrams';
|
|
3
|
+
|
|
4
|
+
export const sampleWorkflowContent: FormElementBase = {
|
|
5
|
+
type: "Form",
|
|
6
|
+
props: {
|
|
7
|
+
title: "User Registration", // Title for the form
|
|
8
|
+
children: [
|
|
9
|
+
/*{
|
|
10
|
+
type: "TextField",
|
|
11
|
+
props: {
|
|
12
|
+
name: "fullName",
|
|
13
|
+
label: "Full Name",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
type: "TextField",
|
|
18
|
+
props: {
|
|
19
|
+
name: "email",
|
|
20
|
+
label: "Email Address",
|
|
21
|
+
type: "email",
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
type: "TextField",
|
|
26
|
+
props: {
|
|
27
|
+
name: "age",
|
|
28
|
+
label: "Age",
|
|
29
|
+
type: "number",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
type: "Switch",
|
|
34
|
+
props: {
|
|
35
|
+
name: "notifications",
|
|
36
|
+
label: "Enable Notifications",
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
type: "Select",
|
|
41
|
+
props: {
|
|
42
|
+
name: "country",
|
|
43
|
+
label: "Country",
|
|
44
|
+
options: [
|
|
45
|
+
{ value: "us", label: "United States" },
|
|
46
|
+
{ value: "ca", label: "Canada" },
|
|
47
|
+
{ value: "uk", label: "United Kingdom" },
|
|
48
|
+
{ value: "au", label: "Australia" },
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
},*/
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|