Search code examples
reactjsjsplumb

Hierarchical tree with loop connection


I'm trying to implement a Hierarchical tree (using React & JsPlumb) with a loop connection between nodes and connecting two nodes into a single node. The trouble is while connecting the positioning of the hierarchical tree is not properly working. In fact, the loop connection is overlapped with other nodes.

I tried to connect the end node to the start node in the Hierarchical tree with Bezier connector from the end node's Bottom anchor to start node's Top anchor without overlapping the nodes. But, the tree connected from end node's Top anchor to start node's Bottom anchor with overlapping the nodes.

Configs:

const layoutConfig = {
  type: 'Hierarchical',
  parameters: {
    padding: [120, 150],
    spacing: 'compress',
    orientation: 'horizontal',
    magnetize: true,
  },
};
export const viewConfig = {
  nodes: {
    singleTrigger: { component: SingleTriggerComponent, events },
    action: { component: ActionComponent, events },
    delay: { component: DelayComponent, events },
    decision: { component: DecisionComponent, events },
    fork: { component: SplitComponent, events },
    fork_path: { component: LabelComponent, events },
    if: { component: LabelComponent, events },
    else: { component: LabelComponent, events },
    exit: { component: ExitComponent, events },
    placeholder: { component: PlaceholderComponent, events },
  },
  edges: {
    default: { paintStyle: { lineWidth: 2, strokeStyle: '#d9e3eb' } },
    bezier: simpleBezierEdgeConfig(),
    straight: straightEdgeConfig(),
    straightWithoutEndPoint: straightEdgeConfigWithoutEndPoint(),
  },
};
export const renderConfig = {
  layout: layoutConfig,
  refreshLayoutOnEdgeConnect: true,
  zoomToFit: false,
  zoomRange: [minZoom, maxZoom],
  consumeRightClick: false,
  elementsDraggable: false,
  enablePan: true,
  enableWheelZoom: false,
  enablePanButtons: false,
  jsPlumb: {
    Anchors: ['Bottom', 'Top'],
    Endpoints: ['Dot', 'Blank'],
  },
};

Hierarchical Graph:

"{"nodes":[{"id":"2813","type":"singleTrigger","data":{"workflow":[{"id":2813,"component_type":"root","parent_id":null,"properties":{},"active_people_count":0,"completed_people_count":1},{"id":2815,"component_type":"trigger","parent_id":null,"properties":{"campaign_id":575,"trigger_type":"unsubscribed_contact","display_values":{"campaign":{"id":575,"name":"Test for clicked link workflow","status":"live"}},"unsubscription_type":"campaign"},"active_people_count":0,"completed_people_count":1}]}},{"id":"2953","type":"action","data":{"id":2953,"component_type":"action","parent_id":2813,"properties":{"action_type":"move_from_one_campaign_to_another","parent_type":"root","display_values":{"to_campaign":{"id":572,"name":"Workflow test by me","status":"live"},"from_campaign":{"id":487,"name":"email 08(Copy) 1213 23","status":"live"}},"to_campaign_id":572,"from_campaign_id":487},"active_people_count":0,"completed_people_count":0}},{"id":"2952","type":"action","data":{"id":2952,"component_type":"action","parent_id":2953,"properties":{"action_type":"send_broadcast_mail","parent_type":"action","display_values":{"mail_filter":{"id":2517,"name":"Test ","status":"draft"}},"mail_filter_id":2517,"send_multiple_times":false},"active_people_count":0,"completed_people_count":0}},{"id":"2869","type":"action","data":{"id":2869,"component_type":"action","parent_id":2952,"properties":{"tag_id":1042,"action_type":"apply_tag","parent_type":"action","display_values":{"tag":{"id":1042,"name":"CSV Import - 2019-04-16 06:23:30 UTC","status":"present"}}},"active_people_count":0,"completed_people_count":0}},{"id":"2871","type":"fork","data":{"id":2871,"component_type":"fork","parent_id":2869,"properties":{"parent_type":"action"},"active_people_count":0,"completed_people_count":0}},{"id":"2872","type":"fork_path","data":{"id":2872,"component_type":"fork_path","parent_id":2871,"properties":{"position":1,"parent_type":"fork"},"active_people_count":0,"completed_people_count":0}},{"id":"2875","type":"decision","data":{"id":2875,"component_type":"decision","parent_id":2872,"properties":{"filters":[{"criteria":[{"key":"name","value":"test","condition":"contains","display_values":{}}]}],"parent_type":"fork_path","display_values":{}},"active_people_count":0,"completed_people_count":0}},{"id":"2876","type":"else","data":{"id":2876,"component_type":"else","parent_id":2875,"properties":{"parent_type":"decision"},"active_people_count":0,"completed_people_count":0}},{"id":"2870","type":"delay","data":{"id":2870,"component_type":"delay","parent_id":2876,"properties":{"delay_type":"timed_delay","parent_type":"else","interval_unit":"mins","interval_value":5,"processable_days":[0,1,2,3,4,5,6]},"active_people_count":0,"completed_people_count":0}},{"id":"2814","type":"exit","data":{"id":2814,"component_type":"exit","parent_id":2870,"properties":{"parent_type":"delay"},"active_people_count":0,"completed_people_count":1}},{"id":"2877","type":"if","data":{"id":2877,"component_type":"if","parent_id":2875,"properties":{"parent_type":"decision"},"active_people_count":0,"completed_people_count":0}},{"id":"2878","type":"exit","data":{"id":2878,"component_type":"exit","parent_id":2877,"properties":{"parent_type":"if"},"active_people_count":0,"completed_people_count":0}},{"id":"2873","type":"fork_path","data":{"id":2873,"component_type":"fork_path","parent_id":2871,"properties":{"position":2,"parent_type":"fork"},"active_people_count":0,"completed_people_count":0}},{"id":"2874","type":"exit","data":{"id":2874,"component_type":"exit","parent_id":2873,"properties":{"parent_type":"fork_path"},"active_people_count":0,"completed_people_count":0}}],"edges":[{"source":"2813","target":"2953","data":{"type":"straight","id":2953,"component_type":"action","parent_id":2813,"properties":{"action_type":"move_from_one_campaign_to_another","parent_type":"root","display_values":{"to_campaign":{"id":572,"name":"Workflow test by me","status":"live"},"from_campaign":{"id":487,"name":"email 08(Copy) 1213 23","status":"live"}},"to_campaign_id":572,"from_campaign_id":487},"active_people_count":0,"completed_people_count":0}},{"source":"2953","target":"2952","data":{"type":"straight","id":2952,"component_type":"action","parent_id":2953,"properties":{"action_type":"send_broadcast_mail","parent_type":"action","display_values":{"mail_filter":{"id":2517,"name":"Test ","status":"draft"}},"mail_filter_id":2517,"send_multiple_times":false},"active_people_count":0,"completed_people_count":0}},{"source":"2952","target":"2869","data":{"type":"straight","id":2869,"component_type":"action","parent_id":2952,"properties":{"tag_id":1042,"action_type":"apply_tag","parent_type":"action","display_values":{"tag":{"id":1042,"name":"CSV Import - 2019-04-16 06:23:30 UTC","status":"present"}}},"active_people_count":0,"completed_people_count":0}},{"source":"2869","target":"2871","data":{"type":"straight","id":2871,"component_type":"fork","parent_id":2869,"properties":{"parent_type":"action"},"active_people_count":0,"completed_people_count":0}},{"source":"2871","target":"2872","data":{"type":"bezier","id":2872,"component_type":"fork_path","parent_id":2871,"properties":{"position":1,"parent_type":"fork"},"active_people_count":0,"completed_people_count":0}},{"source":"2871","target":"2873","data":{"type":"bezier","id":2873,"component_type":"fork_path","parent_id":2871,"properties":{"position":2,"parent_type":"fork"},"active_people_count":0,"completed_people_count":0}},{"source":"2872","target":"2875","data":{"type":"straightWithoutEndPoint","id":2875,"component_type":"decision","parent_id":2872,"properties":{"filters":[{"criteria":[{"key":"name","value":"test","condition":"contains","display_values":{}}]}],"parent_type":"fork_path","display_values":{}},"active_people_count":0,"completed_people_count":0}},{"source":"2875","target":"2876","data":{"type":"bezier","id":2876,"component_type":"else","parent_id":2875,"properties":{"parent_type":"decision"},"active_people_count":0,"completed_people_count":0}},{"source":"2875","target":"2877","data":{"type":"bezier","id":2877,"component_type":"if","parent_id":2875,"properties":{"parent_type":"decision"},"active_people_count":0,"completed_people_count":0}},{"source":"2876","target":"2870","data":{"type":"straightWithoutEndPoint","id":2870,"component_type":"delay","parent_id":2876,"properties":{"delay_type":"timed_delay","parent_type":"else","interval_unit":"mins","interval_value":5,"processable_days":[0,1,2,3,4,5,6]},"active_people_count":0,"completed_people_count":0}},{"source":"2870","target":"2814","data":{"type":"straight","id":2814,"component_type":"exit","parent_id":2870,"properties":{"parent_type":"delay"},"active_people_count":0,"completed_people_count":1}},{"source":"2877","target":"2878","data":{"type":"straightWithoutEndPoint","id":2878,"component_type":"exit","parent_id":2877,"properties":{"parent_type":"if"},"active_people_count":0,"completed_people_count":0}},{"source":"2873","target":"2874","data":{"type":"straightWithoutEndPoint","id":2874,"component_type":"exit","parent_id":2873,"properties":{"parent_type":"fork_path"},"active_people_count":0,"completed_people_count":0}}],"ports":[],"groups":[]}"

Function:

toolkit.addEdge({source: '2813', target: '2874'});

I expect the end node to be connected from bottom to start with curved edges without overlapping the nodes.


Solution

  • If we use toolkit.addEdge({source, target}) method for making the connection in Hierarchical tree layout, the nodes present in the Hierarchical tree gets misaligned and the tree doesn't look good aesthetically. So, jsPlumb supports another method called jsPlumb.connect({source, target}) for making inter-node connections. This connection is not considered as edges. So, the solution is to use

    Function:

    jsPlumb.connect({source: '2813', target: '2874'});

    Note: To avoid overlapping we need to use FlowChat connector.