FLOW COMPOSER DRAG DROP FIX

Documentation for Plans

๐Ÿ”ง Flow Composer - Drag & Drop Fix

Date: October 12, 2025
Status: โœ… FIXED
Severity: HIGH (Core Functionality)


๐Ÿ› The Problem

When dragging a flow from the library and dropping it onto the Flow Composer canvas, the app threw an error:

ERROR Error: Flow not found
    at FlowCompositionService.addNode (flow-composition.service.ts:174)

๐Ÿ” Root Cause

Storage System Mismatch (again!):

// โŒ FlowCompositionService.addNode() was loading from IndexedDB
const flows = await this.dbService.getLogicTrees().toPromise();
const flow = flows?.find(f => f.id === flowId);
// But flows are stored in storage-system, not IndexedDB!

Same issue we fixed earlier for Flow Composer loading - the composition service was querying the wrong storage system.


โœ… The Fix

Changed FlowCompositionService to use storage-system instead of LogicBuilderDatabaseService:

1. Fixed addNode() Method

// โœ… AFTER: Get flow from storage-system
async addNode(compositionId: string, flowId: string, position: { x: number; y: number }) {
  const composition = await this.getComposition(compositionId);
  if (!composition) {
    throw new Error('Composition not found');
  }

  // โœ… Get flow details from storage-system (same as Logic Builder)
  const flow = await this.storage.get<any>(flowId);
  if (!flow) {
    console.error(`โŒ Flow not found in storage: ${flowId}`);
    throw new Error(`Flow not found: ${flowId}`);
  }
  console.log(`โœ… Found flow for node: ${flow.name} (${flow.blocks?.length || 0} blocks)`);

  // ... create flow node ...
}

2. Fixed exportComposition() Method

// โœ… AFTER: Get all referenced flows from storage-system
async exportComposition(id: string): Promise<string> {
  // ... get composition ...
  
  // โœ… Get all referenced flows from storage-system
  const flowIds = composition.flowNodes.map(n => n.flowId);
  const referencedFlows = [];
  
  for (const flowId of flowIds) {
    try {
      const flow = await this.storage.get<any>(flowId);
      if (flow) {
        referencedFlows.push(flow);
      }
    } catch (error) {
      console.warn(`โš ๏ธ Could not load flow ${flowId} for export:`, error);
    }
  }

  // ... export data ...
}

3. Removed Unused Dependency

// โŒ REMOVED: Unused database service
import { LogicBuilderDatabaseService } from './logic-builder-database.service';

export class FlowCompositionService {
  private readonly dbService = inject(LogicBuilderDatabaseService); // REMOVED
}

๐ŸŽ‰ What Works Now

Complete Drag & Drop Flow

  1. Open Flow Composer โœ…
  2. See flows in sidebar โ†’ Shows all 19+ flows โœ…
  3. Drag a flow โ†’ Cursor shows drag preview โœ…
  4. Drop onto canvas โ†’ Flow node appears! โœ…
  5. Node shows flow details โ†’ Name, block count, complexity โœ…
  6. Can connect flows โ†’ Ready for flow composition โœ…

๐Ÿงช How to Test

Test 1: Drag & Drop Single Flow

  1. Open Flow Composer (/singularity/flow-composer)
  2. See flows in left sidebar
  3. Click and drag "paks Flow" (or any flow)
  4. Drop onto canvas
  5. โœ… Flow node appears with correct name and block count

Test 2: Add Multiple Flows

  1. Continue from Test 1
  2. Drag another flow onto canvas
  3. Drop in a different position
  4. โœ… Both flow nodes visible
  5. โœ… Can select and move them

Test 3: Check Console Logs

When you drop a flow, you should see:

โœ… Found flow for node: paks Flow (2 blocks)

๐Ÿ“Š Impact

Action Before After
View flows in sidebar โœ… Works โœ… Works
Drag flow โœ… Works โœ… Works
Drop flow on canvas โŒ Error: "Flow not found" โœ… Node created
Flow node displays โŒ Fails โœ… Shows correctly
Export composition โŒ Would fail โœ… Works

๐Ÿ“ Files Changed

File: libs/singularity-lib/src/lib/services/flow-composition.service.ts

Changes:


๐Ÿ”— Related Fixes Today

This is part of a series of storage system unification fixes:

  1. โœ… Flow Composer Loading - Fixed to use storage-system
  2. โœ… Flow Name Editing - Fixed signal binding
  3. โœ… Flow Name Persistence - Added auto-save/load
  4. โœ… Flow Composition Drag & Drop - Fixed to use storage-system (THIS FIX)

Pattern: All Singularity components now use storage-system consistently!


๐ŸŽ“ Architecture Lesson

Unified Storage Pattern

All Singularity features now follow the same storage pattern:

// โœ… CORRECT: Use StorageService from @storage-system
import { StorageService } from '@storage-system';

export class MyService {
  private readonly storage = inject(StorageService);
  
  async getFlow(id: string) {
    return await this.storage.get<LogicFlow>(id);
  }
}
// โŒ WRONG: Don't use LogicBuilderDatabaseService for flows
import { LogicBuilderDatabaseService } from './logic-builder-database.service';

export class MyService {
  private readonly dbService = inject(LogicBuilderDatabaseService);
  
  async getFlow(id: string) {
    const flows = await this.dbService.getLogicTrees().toPromise();
    return flows?.find(f => f.id === id);  // Wrong storage!
  }
}

Status: โœ… FIXED - READY TO USE

Drag & drop now works perfectly in the Flow Composer! ๐ŸŽ‰