diff --git a/src/components/WorkflowEditor.js b/src/components/WorkflowEditor.js
index a130c55..117aed3 100644
--- a/src/components/WorkflowEditor.js
+++ b/src/components/WorkflowEditor.js
@@ -9,6 +9,7 @@ import ReactFlow, {
ReactFlowProvider,
SelectionMode,
useReactFlow,
+ useViewport,
} from 'reactflow';
import 'reactflow/dist/style.css';
@@ -24,15 +25,6 @@ import JsonImporter from './JsonImporter';
import { useHistory } from '../hooks/useHistory';
import './WorkflowEditor.css';
-const nodeTypes = {
- operation: OperationNode,
- switch: SwitchNode,
- start: StartNode,
- end: EndNode,
- event: EventNode,
- sleep: SleepNode,
-};
-
const STORAGE_KEY = 'serverless-workflow-editor-state';
const defaultInitialNodes = [
@@ -82,6 +74,17 @@ function WorkflowEditor() {
const reactFlowWrapper = useRef(null);
const [reactFlowBounds, setReactFlowBounds] = useState(null);
const [isDragOver, setIsDragOver] = useState(false);
+ const { zoom } = useViewport();
+
+ // Node types with zoom prop
+ const nodeTypes = useMemo(() => ({
+ operation: (props) => ,
+ switch: (props) => ,
+ start: (props) => ,
+ end: (props) => ,
+ event: (props) => ,
+ sleep: (props) => ,
+ }), [zoom]);
// History management for undo/redo
const {
diff --git a/src/components/nodes/EventNode.js b/src/components/nodes/EventNode.js
index 469277e..0150f3e 100644
--- a/src/components/nodes/EventNode.js
+++ b/src/components/nodes/EventNode.js
@@ -3,9 +3,15 @@ import { Handle, Position } from 'reactflow';
import { Zap } from 'lucide-react';
import './NodeStyles.css';
-const EventNode = ({ data, selected }) => {
+const EventNode = ({ data, selected, zoom = 1 }) => {
+ const [isHovered, setIsHovered] = React.useState(false);
+ const shouldShowDetails = zoom > 1.5 && isHovered;
return (
-
+
setIsHovered(true)}
+ onMouseLeave={() => setIsHovered(false)}
+ >
@@ -27,6 +33,18 @@ const EventNode = ({ data, selected }) => {
Timeout: Yes
)}
+
+ {/* Show detailed event info when highly zoomed AND hovered */}
+ {shouldShowDetails && data.events && data.events.map((event, index) => (
+
+
• Event {index + 1}
+ {event.eventRefs && (
+
+ {JSON.stringify(event.eventRefs)}
+
+ )}
+
+ ))}
diff --git a/src/components/nodes/NodeStyles.css b/src/components/nodes/NodeStyles.css
index 80ddc45..933ada5 100644
--- a/src/components/nodes/NodeStyles.css
+++ b/src/components/nodes/NodeStyles.css
@@ -161,3 +161,69 @@
.sleep-node .node-header {
color: #0891b2;
}
+
+/* Detailed view styles for high zoom levels */
+.detailed-action {
+ margin-top: 8px;
+ padding: 6px;
+ background: rgba(255, 255, 255, 0.5);
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ font-size: 10px;
+}
+
+.action-name {
+ font-weight: 600;
+ color: var(--text-color);
+ margin-bottom: 2px;
+}
+
+.action-function {
+ color: var(--text-secondary);
+ font-style: italic;
+ margin-bottom: 4px;
+}
+
+.action-args {
+ margin: 4px 0;
+}
+
+.action-args code {
+ font-size: 9px;
+ background: var(--bg-secondary);
+ padding: 2px 4px;
+ border-radius: 2px;
+ color: var(--text-color);
+ display: block;
+ white-space: pre-wrap;
+ word-break: break-word;
+ max-width: 200px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.action-retry {
+ font-size: 9px;
+ color: var(--success-color);
+ font-weight: 500;
+}
+
+/* Condition detail styles for switch nodes */
+.condition-detail {
+ margin-top: 4px;
+ font-size: 9px;
+ color: var(--text-secondary);
+}
+
+.condition-detail code {
+ font-size: 8px;
+ background: var(--bg-secondary);
+ padding: 1px 3px;
+ border-radius: 2px;
+ color: var(--text-color);
+ white-space: nowrap;
+ max-width: 150px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: inline-block;
+}
diff --git a/src/components/nodes/OperationNode.js b/src/components/nodes/OperationNode.js
index 966fca5..abbebd7 100644
--- a/src/components/nodes/OperationNode.js
+++ b/src/components/nodes/OperationNode.js
@@ -3,9 +3,41 @@ import { Handle, Position, useReactFlow } from 'reactflow';
import { Play } from 'lucide-react';
import './NodeStyles.css';
-const OperationNode = ({ data, selected }) => {
+const OperationNode = ({ data, selected, zoom = 1 }) => {
+ const [isHovered, setIsHovered] = React.useState(false);
+ const shouldShowDetails = zoom > 1.5 && isHovered; // Show details only when zoomed AND hovered
+
+ // Use React Flow's useReactFlow hook to manipulate node z-index
+ const { setNodes } = useReactFlow();
+
+ React.useEffect(() => {
+ if (shouldShowDetails) {
+ setNodes((nds) =>
+ nds.map((node) => {
+ if (node.data === data) {
+ return { ...node, style: { ...node.style, zIndex: 9999 } };
+ }
+ return node;
+ })
+ );
+ } else {
+ setNodes((nds) =>
+ nds.map((node) => {
+ if (node.data === data) {
+ return { ...node, style: { ...node.style, zIndex: 1 } };
+ }
+ return node;
+ })
+ );
+ }
+ }, [shouldShowDetails, setNodes, data]);
+
return (
-
+
setIsHovered(true)}
+ onMouseLeave={() => setIsHovered(false)}
+ >
@@ -22,6 +54,22 @@ const OperationNode = ({ data, selected }) => {
Actions: {data.actions.length}
)}
+
+ {/* Show detailed action info when highly zoomed AND hovered */}
+ {shouldShowDetails && data.actions && data.actions.map((action, index) => (
+
+
• {action.name}
+
{action.functionRef?.refName || 'No function'}
+ {action.functionRef?.arguments && Object.keys(action.functionRef.arguments).length > 0 && (
+
+ {JSON.stringify(action.functionRef.arguments)}
+
+ )}
+ {action.retryRef && (
+
🔄 Retry enabled
+ )}
+
+ ))}
diff --git a/src/components/nodes/SwitchNode.js b/src/components/nodes/SwitchNode.js
index a7460d0..f82d238 100644
--- a/src/components/nodes/SwitchNode.js
+++ b/src/components/nodes/SwitchNode.js
@@ -3,7 +3,9 @@ import { Handle, Position } from 'reactflow';
import { GitBranch } from 'lucide-react';
import './NodeStyles.css';
-const SwitchNode = ({ data, selected }) => {
+const SwitchNode = ({ data, selected, zoom = 1 }) => {
+ const [isHovered, setIsHovered] = React.useState(false);
+ const shouldShowDetails = zoom > 1.5 && isHovered; // Show details only when zoomed AND hovered
const dataConditions = data.dataConditions || [];
const eventConditions = data.eventConditions || [];
const conditions = dataConditions.length > 0 ? dataConditions : eventConditions;
@@ -12,7 +14,11 @@ const SwitchNode = ({ data, selected }) => {
const totalHandles = conditions.length + (hasDefault ? 1 : 0);
return (
-
+
setIsHovered(true)}
+ onMouseLeave={() => setIsHovered(false)}
+ >
@@ -41,6 +47,16 @@ const SwitchNode = ({ data, selected }) => {
{conditions.map((condition, index) => (
{condition.name || condition.eventRef || condition.condition || `condition${index + 1}`}
+ {shouldShowDetails && conditionType === 'data' && condition.condition && (
+
+ {condition.condition}
+
+ )}
+ {shouldShowDetails && conditionType === 'event' && condition.eventRef && (
+
+ Event: {condition.eventRef}
+
+ )}