Incorporated Unified Node Styling, ExporttoCSV testing Node, and new node description logic.
This commit is contained in:
parent
c930f310eb
commit
3887a78602
@ -322,8 +322,17 @@ export default function App() {
|
||||
{category}
|
||||
</Typography>
|
||||
</Divider>
|
||||
{items.map(({ type, label }) => (
|
||||
<Tooltip key={`${category}-${type}`} title="Drag & Drop into Editor" placement="right">
|
||||
{items.map(({ type, label, description }) => (
|
||||
<Tooltip
|
||||
key={`${category}-${type}`}
|
||||
title={
|
||||
<span style={{ whiteSpace: "pre-line", wordWrap: "break-word", maxWidth: 220 }}>
|
||||
{description || "Drag & Drop into Editor"}
|
||||
</span>
|
||||
}
|
||||
placement="right"
|
||||
arrow
|
||||
>
|
||||
<Button
|
||||
fullWidth
|
||||
sx={sidebarBtnStyle}
|
||||
|
@ -5,6 +5,7 @@
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
|
||||
/* Blue Gradient Overlay */
|
||||
.flow-editor-container::before {
|
||||
content: "";
|
||||
@ -22,9 +23,42 @@
|
||||
z-index: -1; /* Ensures it stays behind the React Flow elements */
|
||||
}
|
||||
|
||||
|
||||
/* Emphasize Drag & Drop Node Functionality */
|
||||
.sidebar-button:hover {
|
||||
background-color: #2a2a2a !important;
|
||||
box-shadow: 0 0 5px rgba(88, 166, 255, 0.3);
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
|
||||
/* Borealis Node Styling */
|
||||
.borealis-node {
|
||||
background: #2c2c2c;
|
||||
border: 1px solid #3a3a3a;
|
||||
border-radius: 4px;
|
||||
color: #ccc;
|
||||
font-size: 12px;
|
||||
min-width: 160px;
|
||||
max-width: 260px;
|
||||
position: relative;
|
||||
box-shadow: 0 0 5px rgba(88, 166, 255, 0.15), 0 0 10px rgba(88, 166, 255, 0.15);
|
||||
transition: box-shadow 0.3s ease-in-out;
|
||||
}
|
||||
.borealis-node-header {
|
||||
background: #232323;
|
||||
padding: 6px 10px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
font-weight: bold;
|
||||
font-size: 10px;
|
||||
}
|
||||
.borealis-node-content {
|
||||
padding: 10px;
|
||||
font-size: 9px;
|
||||
}
|
||||
.borealis-handle {
|
||||
background: #58a6ff;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
@ -1,65 +1,19 @@
|
||||
// src/nodes/General Purpose/CustomNode.jsx
|
||||
import React from "react";
|
||||
import { Handle, Position } from "reactflow";
|
||||
|
||||
const experimentalNode = ({ data }) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
background: "#2c2c2c",
|
||||
border: "1px solid #3a3a3a",
|
||||
borderRadius: "6px",
|
||||
color: "#ccc",
|
||||
fontSize: "12px",
|
||||
minWidth: "160px",
|
||||
maxWidth: "260px",
|
||||
boxShadow: `
|
||||
0 0 5px rgba(88, 166, 255, 0.1),
|
||||
0 0 10px rgba(88, 166, 255, 0.1)
|
||||
`,
|
||||
position: "relative",
|
||||
transition: "box-shadow 0.3s ease-in-out"
|
||||
}}
|
||||
>
|
||||
<Handle
|
||||
type="target"
|
||||
position={Position.Left}
|
||||
style={{
|
||||
background: "#58a6ff",
|
||||
width: 10,
|
||||
height: 10
|
||||
}}
|
||||
/>
|
||||
<Handle
|
||||
type="source"
|
||||
position={Position.Right}
|
||||
style={{
|
||||
background: "#58a6ff",
|
||||
width: 10,
|
||||
height: 10
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
background: "#232323",
|
||||
padding: "6px 10px",
|
||||
borderTopLeftRadius: "6px",
|
||||
borderTopRightRadius: "6px",
|
||||
fontWeight: "bold",
|
||||
fontSize: "13px"
|
||||
}}
|
||||
>
|
||||
{data.label || "Experimental Node"}
|
||||
</div>
|
||||
<div style={{ padding: "10px" }}>
|
||||
{data.content || "Placeholder Experimental Content"}
|
||||
</div>
|
||||
<div className="borealis-node">
|
||||
<Handle type="target" position={Position.Left} className="borealis-handle" />
|
||||
<Handle type="source" position={Position.Right} className="borealis-handle" />
|
||||
<div className="borealis-node-header">{data.label || "Experimental Node"}</div>
|
||||
<div className="borealis-node-content">{data.content || "Placeholder Experimental Content"}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default {
|
||||
type: "experimentalNode", // Must match the type used in nodeTypes
|
||||
type: "experimentalNode",
|
||||
label: "Experimental Node",
|
||||
defaultContent: "Placeholder Node",
|
||||
component: experimentalNode
|
||||
|
@ -1,65 +1,19 @@
|
||||
// src/nodes/General Purpose/CustomNode.jsx
|
||||
import React from "react";
|
||||
import { Handle, Position } from "reactflow";
|
||||
|
||||
const flyffNode = ({ data }) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
background: "#2c2c2c",
|
||||
border: "1px solid #3a3a3a",
|
||||
borderRadius: "6px",
|
||||
color: "#ccc",
|
||||
fontSize: "12px",
|
||||
minWidth: "160px",
|
||||
maxWidth: "260px",
|
||||
boxShadow: `
|
||||
0 0 5px rgba(88, 166, 255, 0.1),
|
||||
0 0 10px rgba(88, 166, 255, 0.1)
|
||||
`,
|
||||
position: "relative",
|
||||
transition: "box-shadow 0.3s ease-in-out"
|
||||
}}
|
||||
>
|
||||
<Handle
|
||||
type="target"
|
||||
position={Position.Left}
|
||||
style={{
|
||||
background: "#58a6ff",
|
||||
width: 10,
|
||||
height: 10
|
||||
}}
|
||||
/>
|
||||
<Handle
|
||||
type="source"
|
||||
position={Position.Right}
|
||||
style={{
|
||||
background: "#58a6ff",
|
||||
width: 10,
|
||||
height: 10
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
background: "#232323",
|
||||
padding: "6px 10px",
|
||||
borderTopLeftRadius: "6px",
|
||||
borderTopRightRadius: "6px",
|
||||
fontWeight: "bold",
|
||||
fontSize: "13px"
|
||||
}}
|
||||
>
|
||||
{data.label || "Flyff Node"}
|
||||
</div>
|
||||
<div style={{ padding: "10px" }}>
|
||||
{data.content || "Placeholder Flyff Content"}
|
||||
</div>
|
||||
<div className="borealis-node">
|
||||
<Handle type="target" position={Position.Left} className="borealis-handle" />
|
||||
<Handle type="source" position={Position.Right} className="borealis-handle" />
|
||||
<div className="borealis-node-header">{data.label || "Flyff Node"}</div>
|
||||
<div className="borealis-node-content">{data.content || "Placeholder Flyff Content"}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default {
|
||||
type: "flyffNode", // Must match the type used in nodeTypes
|
||||
type: "flyffNode",
|
||||
label: "Flyff Node",
|
||||
defaultContent: "Placeholder Node",
|
||||
component: flyffNode
|
||||
|
@ -1,66 +1,21 @@
|
||||
// src/nodes/General Purpose/CustomNode.jsx
|
||||
import React from "react";
|
||||
import { Handle, Position } from "reactflow";
|
||||
|
||||
const dataNode = ({ data }) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
background: "#2c2c2c",
|
||||
border: "1px solid #3a3a3a",
|
||||
borderRadius: "6px",
|
||||
color: "#ccc",
|
||||
fontSize: "12px",
|
||||
minWidth: "160px",
|
||||
maxWidth: "260px",
|
||||
boxShadow: `
|
||||
0 0 5px rgba(88, 166, 255, 0.1),
|
||||
0 0 10px rgba(88, 166, 255, 0.1)
|
||||
`,
|
||||
position: "relative",
|
||||
transition: "box-shadow 0.3s ease-in-out"
|
||||
}}
|
||||
>
|
||||
<Handle
|
||||
type="target"
|
||||
position={Position.Left}
|
||||
style={{
|
||||
background: "#58a6ff",
|
||||
width: 10,
|
||||
height: 10
|
||||
}}
|
||||
/>
|
||||
<Handle
|
||||
type="source"
|
||||
position={Position.Right}
|
||||
style={{
|
||||
background: "#58a6ff",
|
||||
width: 10,
|
||||
height: 10
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
background: "#232323",
|
||||
padding: "6px 10px",
|
||||
borderTopLeftRadius: "6px",
|
||||
borderTopRightRadius: "6px",
|
||||
fontWeight: "bold",
|
||||
fontSize: "13px"
|
||||
}}
|
||||
>
|
||||
{data.label || "Data Node"}
|
||||
</div>
|
||||
<div style={{ padding: "10px" }}>
|
||||
{data.content || "Placeholder Data Content"}
|
||||
</div>
|
||||
<div className="borealis-node">
|
||||
<Handle type="target" position={Position.Left} className="borealis-handle" />
|
||||
<Handle type="source" position={Position.Right} className="borealis-handle" />
|
||||
<div className="borealis-node-header">{data.label || "Data Node"}</div>
|
||||
<div className="borealis-node-content">{data.content || "Placeholder Data Content"}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default {
|
||||
type: "dataNode", // Must match the type used in nodeTypes
|
||||
type: "dataNode",
|
||||
label: "Data Node",
|
||||
description: "This node acts as a baseline foundational example for all nodes to follow.",
|
||||
defaultContent: "Placeholder Node",
|
||||
component: dataNode
|
||||
};
|
||||
|
@ -1,66 +0,0 @@
|
||||
// src/nodes/General Purpose/CustomNode.jsx
|
||||
import React from "react";
|
||||
import { Handle, Position } from "reactflow";
|
||||
|
||||
const nodeGroupBox = ({ data }) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
background: "#2c2c2c",
|
||||
border: "1px solid #3a3a3a",
|
||||
borderRadius: "6px",
|
||||
color: "#ccc",
|
||||
fontSize: "12px",
|
||||
minWidth: "160px",
|
||||
maxWidth: "260px",
|
||||
boxShadow: `
|
||||
0 0 5px rgba(88, 166, 255, 0.1),
|
||||
0 0 10px rgba(88, 166, 255, 0.1)
|
||||
`,
|
||||
position: "relative",
|
||||
transition: "box-shadow 0.3s ease-in-out"
|
||||
}}
|
||||
>
|
||||
<Handle
|
||||
type="target"
|
||||
position={Position.Left}
|
||||
style={{
|
||||
background: "#58a6ff",
|
||||
width: 10,
|
||||
height: 10
|
||||
}}
|
||||
/>
|
||||
<Handle
|
||||
type="source"
|
||||
position={Position.Right}
|
||||
style={{
|
||||
background: "#58a6ff",
|
||||
width: 10,
|
||||
height: 10
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
background: "#232323",
|
||||
padding: "6px 10px",
|
||||
borderTopLeftRadius: "6px",
|
||||
borderTopRightRadius: "6px",
|
||||
fontWeight: "bold",
|
||||
fontSize: "13px"
|
||||
}}
|
||||
>
|
||||
{data.label || "Node Group Box"}
|
||||
</div>
|
||||
<div style={{ padding: "10px" }}>
|
||||
{data.content || "Placeholder Group Box Content"}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default {
|
||||
type: "nodeGroupBox", // Must match the type used in nodeTypes
|
||||
label: "Node Group Box",
|
||||
defaultContent: "Placeholder Node",
|
||||
component: nodeGroupBox
|
||||
};
|
@ -1,66 +1,143 @@
|
||||
// src/nodes/General Purpose/CustomNode.jsx
|
||||
import React from "react";
|
||||
import React, { useRef, useState } from "react";
|
||||
import { Handle, Position } from "reactflow";
|
||||
import { Button, Snackbar } from "@mui/material";
|
||||
|
||||
/**
|
||||
* ExportToCSVNode
|
||||
* ----------------
|
||||
* Simplified version:
|
||||
* - No output connector
|
||||
* - Removed "Export to Disk" checkbox
|
||||
* - Only function is export to disk (manual trigger)
|
||||
*/
|
||||
const ExportToCSVNode = ({ data }) => {
|
||||
const [exportPath, setExportPath] = useState("");
|
||||
const [appendMode, setAppendMode] = useState(false);
|
||||
const [snackbarOpen, setSnackbarOpen] = useState(false);
|
||||
const fileInputRef = useRef(null);
|
||||
|
||||
const handleExportClick = () => setSnackbarOpen(true);
|
||||
const handleSnackbarClose = () => setSnackbarOpen(false);
|
||||
|
||||
const handlePathClick = async () => {
|
||||
if (window.showDirectoryPicker) {
|
||||
try {
|
||||
const dirHandle = await window.showDirectoryPicker();
|
||||
setExportPath(dirHandle.name || "Selected Directory");
|
||||
} catch (err) {
|
||||
console.warn("Directory Selection Cancelled:", err);
|
||||
}
|
||||
} else {
|
||||
fileInputRef.current?.click();
|
||||
}
|
||||
};
|
||||
|
||||
const handleFakePicker = (event) => {
|
||||
const files = event.target.files;
|
||||
if (files.length > 0) {
|
||||
const fakePath = files[0].webkitRelativePath?.split("/")[0];
|
||||
setExportPath(fakePath || "Selected Folder");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
background: "#2c2c2c",
|
||||
border: "1px solid #3a3a3a",
|
||||
borderRadius: "6px",
|
||||
color: "#ccc",
|
||||
fontSize: "12px",
|
||||
minWidth: "160px",
|
||||
maxWidth: "260px",
|
||||
boxShadow: `
|
||||
0 0 5px rgba(88, 166, 255, 0.1),
|
||||
0 0 10px rgba(88, 166, 255, 0.1)
|
||||
`,
|
||||
position: "relative",
|
||||
transition: "box-shadow 0.3s ease-in-out"
|
||||
}}
|
||||
>
|
||||
<Handle
|
||||
type="target"
|
||||
position={Position.Left}
|
||||
style={{
|
||||
background: "#58a6ff",
|
||||
width: 10,
|
||||
height: 10
|
||||
}}
|
||||
/>
|
||||
<Handle
|
||||
type="source"
|
||||
position={Position.Right}
|
||||
style={{
|
||||
background: "#58a6ff",
|
||||
width: 10,
|
||||
height: 10
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
background: "#232323",
|
||||
padding: "6px 10px",
|
||||
borderTopLeftRadius: "6px",
|
||||
borderTopRightRadius: "6px",
|
||||
fontWeight: "bold",
|
||||
fontSize: "13px"
|
||||
}}
|
||||
>
|
||||
<div className="borealis-node">
|
||||
<Handle type="target" position={Position.Left} className="borealis-handle" />
|
||||
|
||||
<div className="borealis-node-header">
|
||||
{data.label || "Export to CSV"}
|
||||
</div>
|
||||
<div style={{ padding: "10px" }}>
|
||||
{data.content || "Placeholder CSV Content"}
|
||||
|
||||
<div className="borealis-node-content">
|
||||
<div style={{ marginBottom: "8px" }}>
|
||||
{data.content || "Export Input Data to CSV File"}
|
||||
</div>
|
||||
|
||||
<label style={{ fontSize: "9px", display: "block", marginTop: "6px" }}>
|
||||
Export Path:
|
||||
</label>
|
||||
<div style={{ display: "flex", gap: "4px", alignItems: "center", marginBottom: "6px" }}>
|
||||
<input
|
||||
type="text"
|
||||
readOnly
|
||||
value={exportPath}
|
||||
placeholder="Click to Select Folder"
|
||||
onClick={handlePathClick}
|
||||
style={{
|
||||
flex: 1,
|
||||
fontSize: "9px",
|
||||
padding: "3px",
|
||||
background: "#1e1e1e",
|
||||
color: "#ccc",
|
||||
border: "1px solid #444",
|
||||
borderRadius: "2px",
|
||||
cursor: "pointer"
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
variant="outlined"
|
||||
size="small"
|
||||
onClick={handleExportClick}
|
||||
sx={{
|
||||
fontSize: "9px",
|
||||
padding: "2px 8px",
|
||||
minWidth: "unset",
|
||||
borderColor: "#58a6ff",
|
||||
color: "#58a6ff"
|
||||
}}
|
||||
>
|
||||
Export
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<label style={{ fontSize: "9px", display: "block", marginTop: "4px" }}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={appendMode}
|
||||
onChange={(e) => setAppendMode(e.target.checked)}
|
||||
style={{ marginRight: "4px" }}
|
||||
/>
|
||||
Append CSV Data if Headers Match
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
type="file"
|
||||
webkitdirectory="true"
|
||||
directory=""
|
||||
multiple
|
||||
style={{ display: "none" }}
|
||||
onChange={handleFakePicker}
|
||||
/>
|
||||
|
||||
<Snackbar
|
||||
open={snackbarOpen}
|
||||
autoHideDuration={1000}
|
||||
onClose={handleSnackbarClose}
|
||||
message="Feature Coming Soon..."
|
||||
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default {
|
||||
type: "ExportToCSVNode", // Must match the type used in nodeTypes
|
||||
type: "ExportToCSVNode",
|
||||
label: "Export to CSV",
|
||||
defaultContent: "Placeholder Node",
|
||||
description: `
|
||||
Reporting Node
|
||||
This node lets the user choose a folder to export CSV data to disk.
|
||||
|
||||
When the "Export" button is clicked, CSV content (from upstream logic) is intended to be saved
|
||||
to the selected directory. This is a placeholder for future file system interaction.
|
||||
|
||||
Inputs:
|
||||
- Structured Table Data (via upstream node)
|
||||
|
||||
Outputs:
|
||||
- None (writes directly to disk in future)
|
||||
`.trim(),
|
||||
defaultContent: "Export Input Data to CSV File",
|
||||
component: ExportToCSVNode
|
||||
};
|
||||
|
86
Workflows/workflow.json
Normal file
86
Workflows/workflow.json
Normal file
@ -0,0 +1,86 @@
|
||||
{
|
||||
"nodes": [
|
||||
{
|
||||
"id": "node-1743545354663",
|
||||
"type": "dataNode",
|
||||
"position": {
|
||||
"x": 177.26666259765625,
|
||||
"y": 122.66666666666667
|
||||
},
|
||||
"data": {
|
||||
"label": "Data Node",
|
||||
"content": "Placeholder Node"
|
||||
},
|
||||
"width": 160,
|
||||
"height": 63
|
||||
},
|
||||
{
|
||||
"id": "node-1743545357071",
|
||||
"type": "dataNode",
|
||||
"position": {
|
||||
"x": 506.59999593098956,
|
||||
"y": 232
|
||||
},
|
||||
"data": {
|
||||
"label": "Data Node",
|
||||
"content": "Placeholder Node"
|
||||
},
|
||||
"width": 160,
|
||||
"height": 63,
|
||||
"selected": true,
|
||||
"positionAbsolute": {
|
||||
"x": 506.59999593098956,
|
||||
"y": 232
|
||||
},
|
||||
"dragging": false
|
||||
},
|
||||
{
|
||||
"id": "node-1743545361694",
|
||||
"type": "ExportToCSVNode",
|
||||
"position": {
|
||||
"x": 187.2666625976562,
|
||||
"y": 316.66666666666663
|
||||
},
|
||||
"data": {
|
||||
"label": "Export to CSV",
|
||||
"content": "Placeholder Node"
|
||||
},
|
||||
"width": 160,
|
||||
"height": 63,
|
||||
"selected": false,
|
||||
"positionAbsolute": {
|
||||
"x": 187.2666625976562,
|
||||
"y": 316.66666666666663
|
||||
},
|
||||
"dragging": false
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"source": "node-1743545354663",
|
||||
"sourceHandle": null,
|
||||
"target": "node-1743545357071",
|
||||
"targetHandle": null,
|
||||
"type": "smoothstep",
|
||||
"animated": true,
|
||||
"style": {
|
||||
"strokeDasharray": "6 3",
|
||||
"stroke": "#58a6ff"
|
||||
},
|
||||
"id": "reactflow__edge-node-1743545354663-node-1743545357071"
|
||||
},
|
||||
{
|
||||
"source": "node-1743545354663",
|
||||
"sourceHandle": null,
|
||||
"target": "node-1743545361694",
|
||||
"targetHandle": null,
|
||||
"type": "smoothstep",
|
||||
"animated": true,
|
||||
"style": {
|
||||
"strokeDasharray": "6 3",
|
||||
"stroke": "#58a6ff"
|
||||
},
|
||||
"id": "reactflow__edge-node-1743545354663-node-1743545361694"
|
||||
}
|
||||
]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user