pankod/refine

View on GitHub
packages/core/src/definitions/helpers/menu/create-tree.ts

Summary

Maintainability
A
2 hrs
Test Coverage
import { IResourceItem } from "../../../contexts/resource/types";
import { getParentResource } from "../router";
import { createResourceKey } from "./create-resource-key";

export type Tree = {
  item: IResourceItem;
  children: { [key: string]: Tree };
};

export type FlatTreeItem = IResourceItem & {
  key: string;
  children: FlatTreeItem[];
};

export const createTree = (
  resources: IResourceItem[],
  legacy = false,
): FlatTreeItem[] => {
  const root: Tree = {
    item: {
      name: "__root__",
    },
    children: {},
  };

  resources.forEach((resource) => {
    const parents: IResourceItem[] = [];

    let currentParent = getParentResource(resource, resources);
    while (currentParent) {
      parents.push(currentParent);
      currentParent = getParentResource(currentParent, resources);
    }
    parents.reverse();

    let currentTree = root;

    parents.forEach((parent) => {
      const key =
        (legacy ? parent.route : undefined) ?? parent.identifier ?? parent.name;

      if (!currentTree.children[key]) {
        currentTree.children[key] = {
          item: parent,
          children: {},
        };
      }
      currentTree = currentTree.children[key];
    });

    const key =
      (legacy ? resource.route : undefined) ??
      resource.identifier ??
      resource.name;

    if (!currentTree.children[key]) {
      currentTree.children[key] = {
        item: resource,
        children: {},
      };
    }
  });

  const flatten = (tree: Tree): FlatTreeItem[] => {
    const items: FlatTreeItem[] = [];

    Object.keys(tree.children).forEach((key) => {
      const itemKey = createResourceKey(
        tree.children[key].item,
        resources,
        legacy,
      );
      const item: FlatTreeItem = {
        ...tree.children[key].item,
        key: itemKey,
        children: flatten(tree.children[key]),
      };
      items.push(item);
    });

    return items;
  };

  return flatten(root);
};