DEV Community

Cover image for Let's create a File Manager From Scratch With React And Typescript Chapter II: The File Manager
Hasan Zohdy
Hasan Zohdy

Posted on

Let's create a File Manager From Scratch With React And Typescript Chapter II: The File Manager

Now our setup is ready, let go with our file manager.

Creating the File Manager Module

Inside src/apps/front-office we'll create file-manager directory, but it will not have neither a provider nor a route as there will no page for the module, just a popup (modal) for it.

Now let's create a utils directory, inside it create FileManager.ts

In our FileManager.ts we'll establish a basic file manager class

export default class FileManager {

}
Enter fullscreen mode Exit fullscreen mode

So our structure will look like

File Manager

File Manager Workflow

Before we continue coding, let's make a small stop and think first, how this should work, what data will be used, and the requests, how we'll work with backend requests.

If we look at the file manager image in the cover image for the article, we can see there are toolbar with actions, so we will have list of commands that will be executed.

Also we have to list root directories, so we need to know the root path of the file manager.

By default the root directory will be the current directory that will be opened.

The current directory will have list of directories and files, we'll call it nodes, so the file will be considered as node and the directory as well.

Let's write these then continue with our flow

// FileManager.ts
export default class FileManager {
  /**
   * Root path
   */
  protected rootPath = "/";

  /**
   * Current directory path
   */
  protected currentDirectoryPath = "/";
}
Enter fullscreen mode Exit fullscreen mode

Nothing special here, we just defined the root path which is obviously / and the current directory which will be the opened one.

Now we add the current directory node, which will be just declared.

// FileManager.ts
export default class FileManager {
  /**
   * Root path
   */
  protected rootPath = "/";

  /**
   * Current directory path
   */
  protected currentDirectoryPath = "/";
  /**
   * Current directory node
   */
  protected currentDirectoryNode?: DirectoryNode;
}
Enter fullscreen mode Exit fullscreen mode

We defined our current directory node with type DirectoryNode, but it is not defined yet, let's create it.

In src/apps/front-office/file-manager create types directory and inside it create FileManager.types.ts

Now let's go to the types file

// file-manager/types/FileManager.types.ts
export type DirectoryNode = {
  //
};
Enter fullscreen mode Exit fullscreen mode

We'll create an empty type for now, this will be updated later, now let's head back to our FileManager file and import the type.

// FileManager.ts

import { DirectoryNode } from "../types/FileManager.types";

export default class FileManager {
  /**
   * Root path
   */
  protected rootPath = "/";

  /**
   * Current directory path
   */
  protected currentDirectoryPath = "/";

  /**
   * Current directory node
   */
  protected currentDirectoryNode?: DirectoryNode;
}
Enter fullscreen mode Exit fullscreen mode

So far so good, nothing hard..just not yet xD, now what is the next step?

File Manager Nodes

Before we go deeper, let's have a look at nodes, what possibly could be a node, or what should be included inside it?

For starter, we can add the name, the node path related to the root path, also we can define whether it is a directory or not, size maybe? let's add all of it

Going back to FileManager.types.ts file

// file-manager/types/FileManager.types.ts

export type Node = {
  /**
   * Node Name
   */
  name: string;
  /**
   * Node full path to root
   */
  path: string;
  /**
   * Node size in bits
   */
  size: number;
  /**
   * Is node directory
   */
  isDirectory: boolean;
};

export type DirectoryNode = {
  //
};
Enter fullscreen mode Exit fullscreen mode

Now created our Node with its primitives, the DirectoryNode is originally a Node, so let's extend it.

// file-manager/types/FileManager.types.ts

export type Node = {
  /**
   * Node Name
   */
  name: string;
  /**
   * Node full path to root
   */
  path: string;
  /**
   * Node size in bits
   */
  size: number;
  /**
   * Is node directory
   */
  isDirectory: boolean;
};

export type DirectoryNode = Node & {
  //
};
Enter fullscreen mode Exit fullscreen mode

What is the main difference between directories and files? well the main difference is directories have children, any child of a directory can be a directory or a file, so basically the directory children are either DirectoryNode or FileNode.

Oh i didn't define the FileNode, for the time being it will just equal to Node

export type Node = {
  /**
   * Node Name
   */
  name: string;
  /**
   * Node full path to root
   */
  path: string;
  /**
   * Node size in bits
   */
  size: number;
  /**
   * Is node directory
   */
  isDirectory: boolean;
};

export type FileNode = Node;

export type DirectoryNode = Node & {
  children: Node[];
};
Enter fullscreen mode Exit fullscreen mode

We added two lines FileNode type which equals to Node and the children type which is an array of DirectoryNode And/Or FileNode.

Let's add some comments over the types to make it more clear.

/**
 * File Manager node is the primary data structure for the File Manager.
 * It can be a directory or a file.
 * It contains the following properties:
 */
export type Node = {
  /**
   * Node Name
   */
  name: string;
  /**
   * Node full path to root
   */
  path: string;
  /**
   * Node size in bits
   */
  size: number;
  /**
   * Is node directory
   */
  isDirectory: boolean;
};

/**
 * FileNode is a node that represents a file.
 * It extends the `Node` type.
 */
export type FileNode = Node;

/**
 * DirectoryNode is a node that represents a directory.
 * It extends the `Node` type.
 */
export type DirectoryNode = Node & {
  /**
   * Directory children
   * It can be a list of `FileNode` and/or a `DirectoryNode`
   */
  children: Node[];
};
Enter fullscreen mode Exit fullscreen mode

Now our basic properties are defined, so the next step is to load current root nodes, that's what we're going to do in our next chapter.

You can see Chapter Two File in Github Repository

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

Top comments (0)