ArchitectureFlows → Workflow

Architecture

Flows → Workflow

Understand how select, drag, and drop interactions translate into workflow updates.


Select, Drag and Drop

Interacting with the workflow view produces FlowsChange objects, each representing the event that occurred, whether a node was selected, dragged, or dropped.

// src/shared/lib/flows/types/flows-change.ts

// ...

export type FlowsChange<T extends NodeEntity, U extends EdgeEntity> =
  | NodeSelectChange<T, U>
  | NodeDragChange<T, U>
  | NodeDropChange<T, U>;

export interface NodeSelectChange<T extends NodeEntity, U extends EdgeEntity> {
  type: "select";
  node: FlowNode<T, U>;
  selected: boolean;
}

export interface NodeDragChange<T extends NodeEntity, U extends EdgeEntity> {
  type: "drag";
  node: FlowNode<T, U>;
  position: {
    x: number;
    y: number;
  };
  positionAbsolute: {
    x: number;
    y: number;
  };
}

export interface NodeDropChange<T extends NodeEntity, U extends EdgeEntity> {
  type: "drop";
  node: FlowNode<T, U>;
}

The node property of each object holds information about the node that triggered the event, which may include information about the workflow element it belongs to, its type, and more.

{
  "type": "select",
  "node": {
    "id": "fa87d235-b6a6-4e36-af2a-e360b4bddb1b/flow/block",
    "type": "component",
    "entity": {
      "type": "elementType/action/flow/block",
      "meta": {
        "type": "elementType",
        "elementType": "action",
        "mode": "flow",
        "item": "block",
        "id": "fa87d235-b6a6-4e36-af2a-e360b4bddb1b",
        "dropArea": false
      },
      "data": {
        "...": "..."
      }
    },
    "...": "..."
  },
  "selected": true
}

Workflow Changes

The properties of the FlowsChange object guide a chain of dispatcher functions toward the final handler, which is responsible for creating the WorkflowChange objects.

To Workflow Changes

These dispatcher functions are built using the zet utility function, as shown in this file.

// src/shared/kits/workflow/mvc/controller/controller/index.ts

// ...

interface Zet {
  object: TypedFlowsChange;
  nested: ["node", "entity"];
  filter: ["meta", "type"];
  params: [Workflow, TypedFlows];
  return: WorkflowChange[];
}

const dispatch = zet<Zet>(["node", "entity"], ["meta", "type"], {
  global: globalChangeToWorkflowChanges,
  elementType: elementTypeChangeToWorkflowChanges,
});

export function flowChangeToWorkflowChanges(
  change: TypedFlowsChange,
  workflow: Workflow,
  flows: TypedFlows,
): WorkflowChange[] {
  return dispatch(change, workflow, flows);
}

export type GlobalChange = Refine<{
  object: TypedFlowsChange;
  nested: ["node", "entity"];
  filter: ["meta", "type"];
  narrow: "global";
}>;

export type ElementTypeChange = Refine<{
  object: TypedFlowsChange;
  nested: ["node", "entity"];
  filter: ["meta", "type"];
  narrow: "elementType";
}>;

For an in-depth explanation of how this utility works, visit the following link.