DEV Community

Cover image for Let's create a React File Manager Chapter XVII: Create Nodes List
Hasan Zohdy
Hasan Zohdy

Posted on

Let's create a React File Manager Chapter XVII: Create Nodes List

We're continuing in our list directory route.

We now listed the node files and directories, but we need to make each child as proper node.

Let's get the same Node type that we did in our React Project and import it.

// src/utils/node.ts
// 👇🏻 import the Node type from the client directory xD
import { Node } from "./../../../client/src/apps/front-office/file-manager/Kernel/Kernel.types";

export type { Node };

/**
 * Generate a node object to the given path,
 * the given path should be relative to the data directory
 */
export default function makeNode(path: string, children: string[]): Node {

}
Enter fullscreen mode Exit fullscreen mode

Now we imported the same node type from our client directory, we can use it in our server.

Then we created a makeNode function to generate a new node object, lets do it.

// src/utils/node.ts

// 👇🏻 import the Node type from the client directory xD

import { Node } from "./../../../client/src/apps/front-office/file-manager/Kernel/Kernel.types";

import { isDirectory, size } from "@mongez/fs";
import { dataPath } from "./paths";

export type { Node };

/**
 * Generate a node object to the given path,
 * the given path should be relative to the data directory
 */
export default function makeNode(path: string, children?: string[]): Node {
  // get the full path of the node
  const fullPath = dataPath(path);

  const node: Node = {
    path,
    name: path.split("/")?.pop() || "/",
    isDirectory: isDirectory(fullPath),
    size: size(fullPath),
  };

  if (node.isDirectory && children?.length) {
    node.children = children.map((child) =>
      makeNode((path === "/" ? path : path + "/") + child)
    );
  }

  return node;
Enter fullscreen mode Exit fullscreen mode

So the path will be the relative path to data directory, so if its the root then the path will be /.

The name will be the last segment of the path so we split the path by / and get the last segment.

The given children are the children list of the node, so we map over them and generate a new node for each child.

If there are children then we'll loop over them and generate a new node for each child.

Don't forget the given children is list of names for the given node path, so we need to add the child name to the path.

The isDirectory will be the result of isDirectory function that we imported from @mongez/fs package, we need to pass the full path of the node path so we used fullPath to get the full path using dataPath.

The size will be the result of size function that we imported from @mongez/fs package, we need to pass the full path of the node path so we used fullPath to get the full path using dataPath.

Calling the function

Now let's head to our listDirectory route and call the makeNode function.

import fs from "@mongez/fs";
import makeNode from "app/utils/node";
import { dataPath } from "app/utils/paths";
import { Request, Response } from "express";

/**
 *List directories
 */
export default async function listDirectory(
  request: Request,
  response: Response
) {
  // get the directory path from the request query string
  // let's set `/` as the default path
  const path = (request.query.path as string) || "/";
  const directoryPath = dataPath(path); // the full path to the directory

  if (!fs.isDirectory(directoryPath)) {
    return response.status(404).json({
      message: "Directory not found",
    });
  }

  // get the directory content
  const children = fs.list(directoryPath);

  return response.json({
    node: makeNode(path, children),
  });
}
Enter fullscreen mode Exit fullscreen mode

Now let's run the server and see it again.

Server

Walaa, It works!.

Actually we can always return children with empty array if the node is an array, because we may later add another feature to set the depth of the children, so we can return the children of the children.

// src/utils/node.ts

/**
 * Generate a node object to the given path,
 * the given path should be relative to the data directory
 */
export default function makeNode(path: string, children?: string[]): Node {
  // get the full path of the node
  const fullPath = dataPath(path);

  const node: Node = {
    path,
    name: path.split("/")?.pop() || "/",
    isDirectory: isDirectory(fullPath),
    size: size(fullPath),
  };

   // 👇🏻 we can always return children with empty array if the node is a directory
  if (node.isDirectory) {
    node.children = (children || []).map((child) =>
    // 👇🏻 we need to check if the path is the root then we will just append it to the child
    // if its not the root then we need to append `/` to the path and then append the child    
      makeNode((path === "/" ? path : path + "/") + child)
    );
  }

  return node;
}
Enter fullscreen mode Exit fullscreen mode

Now we can try any route to check if it works properly.

  • http://localhost:3000/file-manager?path=/ will return the root directory.
  • http://localhost:3000/file-manager?path=/Application will return the Application directory.

Next Chapter

In the next chapter we'll implement this api in our React project to make it more real.

Article Repository

You can see chapter files in Github Repository

Don't forget the main branch has the latest updated code.

Tell me where you are now

If you're following up with me this series, tell me where are you now and what you're struggling with, i'll try to help you as much as i can.

Salam.

Top comments (0)