Skip to content

Latest commit

 

History

History
139 lines (108 loc) · 4.56 KB

File metadata and controls

139 lines (108 loc) · 4.56 KB

Loop Implementation

This document describes how loop nodes are implemented in our workflow builder, following ActivePieces' architecture.

Overview

Loop nodes allow iterating over arrays of items, executing a sequence of actions for each item in the array. Each loop node can contain nested actions, including other loops and routers.

Data Structure

Loop Node Type

export interface LoopOnItemsAction extends FlowAction {
  type: FlowActionType.LOOP_ON_ITEMS
  settings: {
    items: string // Expression that evaluates to an array
  }
  firstLoopAction?: FlowAction // First action inside the loop
}

Visual Components

1. Loop Node

  • Standard step node with "Loop" action type
  • Displays loop icon and configured array expression
  • Width: 260px, Height: 70px

2. Loop Edges

The loop implementation uses two specialized edge types:

Loop Start Edge (ApLoopStartEdge)

  • Connects the loop node to its first child action
  • Features a curved path that goes right then down
  • Includes an add button for adding the first action when loop is empty

Loop Return Edge (ApLoopReturnEdge)

  • Creates the visual "loop back" connection
  • Two-segment path with:
    • Left curve from last action to return node
    • Right-pointing arrow indicating loop direction
    • Vertical line back to the loop's end
  • Includes add button for adding actions after the last item

3. Loop Return Node

  • Special invisible node that marks the end of loop execution
  • Positioned to the left of the loop's child actions
  • Acts as the target for the return edge

Layout Algorithm

Child Graph Positioning

  1. Build Child Graph: Recursively build the graph for all actions inside the loop
  2. Calculate Bounding Box: Determine the total size of the child graph
  3. Horizontal Offset: Position child actions to the right of the loop node
  4. Return Node Positioning: Place return node to the left, centered vertically

Key Spacing Constants

VERTICAL_OFFSET_BETWEEN_LOOP_AND_CHILD = VERTICAL_SPACE_BETWEEN_STEPS * 1.5 + 2 * ARC_LENGTH
HORIZONTAL_SPACE_BETWEEN_NODES = 120px

Nested Loops and Routers

The implementation properly handles nested structures:

  • Nested loops maintain proper spacing and alignment
  • Routers inside loops follow standard branch layout
  • Bounding box calculations account for all nested structures

Edge Path Calculations

Loop Start Edge Path

M [sourceX] [startY] 
v[verticalDistance/2]
arc-right-down 
h[horizontalDistance]
arc-right 
v[verticalDistance]
arrow-down (if not empty)

Loop Return Edge Path

Complex two-segment path:

  1. Return Path: From last action to return node with left curve
  2. Arrow Segment: Horizontal line with right-pointing arrow
  3. Vertical Return: Line back to loop end position

Adding Actions to Loops

Empty Loop

  • Shows a big add button inside the loop area
  • Clicking creates the first action with firstLoopAction property

Adding Between Actions

  • Plus buttons appear on edges between actions
  • New actions are inserted in the action chain

Adding After Last Action

  • Plus button on the return edge
  • Actions added maintain the loop structure

Configuration

Loop Settings Panel

  • Items Expression: JavaScript expression that evaluates to an array
  • Examples:
    • [1, 2, 3, 4, 5] - Static array
    • trigger.items - Array from trigger data
    • previousStep.data.results - Array from previous step

Implementation Details

Graph Building (buildLoopChildGraph)

  1. Create child graph from firstLoopAction or empty graph
  2. Calculate positioning offsets based on child graph size
  3. Create loop return node at calculated position
  4. Create subgraph end node for proper spacing
  5. Generate loop edges with proper data attributes
  6. Return merged graph with correct node ordering

Important Calculations

  • verticalSpaceBetweenReturnNodeStartAndEnd: Uses child graph height + vertical spacing
  • Subgraph end Y position: Includes ARC_LENGTH for proper curve alignment
  • Node ordering: [loopReturnNode, ...childNodes, subgraphEndNode]

Best Practices

  1. Expression Validation: Ensure loop items expression evaluates to an array
  2. Nested Structures: Test loops containing routers and other loops
  3. Empty State: Handle empty loops gracefully with clear UI
  4. Performance: Consider limits for very large arrays

Related Components

  • ApLoopStartEdge.tsx: Loop start edge rendering
  • ApLoopReturnEdge.tsx: Loop return edge with arrow
  • LoopSettings.tsx: Configuration panel for loop items
  • graphUtils.ts: Contains buildLoopChildGraph function