Incorporated Unified Node Styling, ExporttoCSV testing Node, and new node description logic.

This commit is contained in:
Nicole Rappe 2025-04-01 17:16:36 -06:00
parent c930f310eb
commit 3887a78602
8 changed files with 278 additions and 275 deletions

View File

@ -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}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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
};

View File

@ -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
};

View File

@ -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
View 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"
}
]
}