Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[suggestion] flatNodes and treeNodes #46

Open
fabricioloupias opened this issue Mar 12, 2025 · 6 comments
Open

[suggestion] flatNodes and treeNodes #46

fabricioloupias opened this issue Mar 12, 2025 · 6 comments

Comments

@fabricioloupias
Copy link

I see that the nodes (FlowNodeJSON) don't have an attribute like "path" that indicates their position in the tree.

This is very useful when we need to save all the nodes in a database. Let's imagine a scenario where we have many flows, and each flow can contain many nodes.
To save in the database, each node (a Document) can have infinite nested nodes, and each Document can have a storage limit.

So, having a flatNodes(treeNodes) function that converts the tree into a complete list of nodes (each node having its own 'path') would be much simpler and more optimal for saving in the database. Each node would be a Document (without nesting).

So, when we need to retrieve the nodes for a certain flowId, what we would do is use another function, treeNodes(flatNodes), to convert the list to a tree.

flatNodes (same level, to save in db):

|->node1
|->node2
|->node2_1
|->node2_2
|->node3

treeNodes (to use in component):

|->node1
|->node2
      |->node2_1
      |->node2_2
|->node3
@dragooncjw
Copy link
Collaborator

Are you using a free layout or a fixed layout?

@xiamidaxia
Copy link
Collaborator

xiamidaxia commented Mar 13, 2025

In fixed layout mode, we have a tree inside us, and we have a ctx.document.traverse method to traverse the depth of the tree, or ctx.document.getAllNodes() can be used to get flatten nodes.

class FlowDocument {
   /**
   *   R
   *   |
   *   +---1
   *   |   |
   *   |   +---1.1
   *   |   |
   *   |   +---1.2
   *   |   |
   *   |   +---1.3
   *   |   |    |
   *   |   |    +---1.3.1
   *   |   |    |
   *   |   |    +---1.3.2
   *   |   |
   *   |   +---1.4
   *   |
   *   +---2
   *       |
   *       +---2.1
   *
   *  sort: [1, 1.1, 1.2, 1.3, 1.3.1, 1.3.2, 1.4, 2, 2.1]
   * @param fn
   * @param node
   * @param depth
   * @return isBreak
   */
  traverse(
    fn: (node: FlowNodeEntity, depth: number, index: number) => boolean | void,
    node = this.root,
    depth = 0
  ): boolean | void {
    return this.originTree.traverse(fn, node, depth);
  }
}

@fabricioloupias
Copy link
Author

The problem is that getAllNodes() returns FlowNodeEntity[] and it has no plain information to save in a database.

I was thinking of using the toJson() of each node to save it in the database, for example:
save(clientContext.document.getAllNodes().map(node => node.toJSON()))

interface FlowNodeJSON {
    id: string;
    type?: FlowNodeType;
    data?: Record<string, any>;
    meta?: FlowNodeMeta;
    blocks?: FlowNodeJSON[];
}

maybe to get the flat node node.toFlatJSON()

interface FlatNodeJSON {
    id: string;
    type?: FlowNodeType;
    data?: Record<string, any>;
    meta?: FlowNodeMeta;
    path?: string[]; // This is used to rebuild the tree by recovering all the nodes from the base.
}

The problem is that toJson() has blocks, which wouldn't need to be stored in the database.
I also see that it's also missing the path in the tree, so that when we get all the nodes in the database, we can rebuild the tree.

Does the tool already have something to get all the flat nodes that can be stored in a database? (Each node would be a document.)

If so, I didn't find it.
How do you recommend saving nodes in a database? Keep in mind that it wouldn't be good practice to save child nodes in a blocks attribute, as the list could be very large.

The tool has a reverse path to build the tree by passing a list of flat nodes?

@xiamidaxia
Copy link
Collaborator

xiamidaxia commented Mar 14, 2025

In our business, we don't store each node as a separate document in the database. Since nodes are frequently added and deleted, I would recommend storing the entire document.toJSON in a single database record.

We haven't encountered issues with JSON being too large to store yet, because the workflow needs to be visible to users. If the nodes become too large and numerous, making it unintuitive, they will be split into something similar to sub-workflows.

@xiamidaxia
Copy link
Collaborator

xiamidaxia commented Mar 14, 2025

Your question is very good. Currently, we haven't provided such methods, but we can consider it for future development. If you really want to get the path of each node, you can only do it through document.traverse, though it might be a bit complicated as there are some hidden nodes prefixed with "$".

@fabricioloupias
Copy link
Author

Okay, well, let's see how I manage each flow.

This implementation method is used because it could be useful in the future to make the canvas collaborative? (Multiple users editing nodes at the same time)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants