DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 963,274 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for Build fast and customizable admin panel with NestJS.
Yıldıray Ünlü for refine

Posted on • Updated on • Originally published at refine.dev

Build fast and customizable admin panel with NestJS.

All the steps described are in this repo.

Intro

NestJS is a framework for building efficient, scalable Node.js server-side applications. With nestjsx/crud we can add CRUD functions quickly and effortlessly on this framework.

In this article, we will prepare a simple job-posting application. We will also use the refine framework for the admin panel. The project will consist of two parts, api and admin.

Β NestJS Rest Api

To start playing with NestJS you should have node (>= 10.13.0, except for v13) and npm installed.

Create Project Folder

mkdir job-posting-app
cd job-posting-app
Enter fullscreen mode Exit fullscreen mode

Setting up a new project is quite simple with the Nest CLI. With npm installed, you can create a new Nest project with the following commands in your OS terminal:

npm i -g @nestjs/cli
nest new api
Enter fullscreen mode Exit fullscreen mode

TypeORM is definitely the most mature ORM available in the node.js world. Since it's written in TypeScript, it works pretty well with the Nest framework. I chose mysql as database. TypeORM supports many databases (MySQL, MariaDB, Postgres etc.)

To start with this library we have to install all required dependencies:

npm install --save @nestjs/typeorm @nestjs/config typeorm mysql2
Enter fullscreen mode Exit fullscreen mode
  • Create an .env.example file. Here we will save the database information.
  • Create and configured a docker-compose file for MySQL.
  • Create a ormconfig.ts file for migrations.
  • Add the following scripts to the package.json file for migrations.
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js",
"db:migration:generate": "npm run typeorm -- migration:generate",
"db:migration:run": "npm run typeorm -- migration:run",
"db:migration:revert": "npm run typeorm -- migration:revert",
"db:refresh": "npm run typeorm schema:drop && npm run db:migration:run"
Enter fullscreen mode Exit fullscreen mode
  • Import the TypeOrmModule into the app.module.ts

Install nestjsx-crud
I used nestjsx-crud library because it makes crud functions easier.

npm i @nestjsx/crud @nestjsx/crud-typeorm class-transformer class-validator
Enter fullscreen mode Exit fullscreen mode

Since the steps to create Entities Contorllers, and services are very long, I do not explain step by step. You can check the repo for details.

It created these end-points automatically with nestjsx/crud.

Swagger

Now let's refine the admin panel. With Superplate, we can quickly create a refine project.

npx superplate-cli admin
Enter fullscreen mode Exit fullscreen mode

Answer as below:

βœ” Select your project type β€Ί refine
βœ” What will be the name of your app Β· admin
βœ” Do you want to customize theme?: Β· less
βœ” Data Provider: Β· nestjsx-crud-data-provider
βœ” Auth Provider: Β· none
βœ” Do you want to add an example page? Β· example-resource
βœ” Do you want to customize layout? Β· custom-layout
βœ” i18n - Internationalization: Β· no
Enter fullscreen mode Exit fullscreen mode
cd admin
npm run dev
Enter fullscreen mode Exit fullscreen mode

Refine's sample application will welcome you.

Refine

Change api url in admin/src/App.tsx

const API_URL = "http://localhost:3000";
Enter fullscreen mode Exit fullscreen mode

Let's add the listing page in refine for the companies crud end-point.

/admin/src/pages/companies/list.tsx

import {
  List,
  Table,
  TextField,
  useTable,
  IResourceComponentsProps,
  getDefaultSortOrder,
  Space,
  EditButton,
  DeleteButton,
  TagField,
  ShowButton,
} from "@pankod/refine";
import { ICompany } from "interfaces";

export const CompanyList: React.FC<IResourceComponentsProps> = () => {
  const { tableProps, sorter } = useTable<ICompany>({
    initialSorter: [
      {
        field: "id",
        order: "desc",
      },
    ],
  });

  return (
    <List>
      <Table {...tableProps} rowKey="id">
        <Table.Column
          dataIndex="id"
          key="id"
          title="ID"
          render={(value) => <TextField value={value} />}
          defaultSortOrder={getDefaultSortOrder("id", sorter)}
          sorter
        />
        <Table.Column
          dataIndex="name"
          key="name"
          title="Name"
          render={(value) => <TextField value={value} />}
          defaultSortOrder={getDefaultSortOrder("name", sorter)}
          sorter
        />
        <Table.Column
          dataIndex="location"
          key="location"
          title="Location"
          render={(value) => <TextField value={value} />}
          defaultSortOrder={getDefaultSortOrder("location", sorter)}
          sorter
        />
        <Table.Column
          dataIndex="isActive"
          key="isActive"
          title="Is Active"
          render={(value) => <TagField value={value} />}
          defaultSortOrder={getDefaultSortOrder("status", sorter)}
          sorter
        />
        <Table.Column<ICompany>
          title="Actions"
          dataIndex="actions"
          render={(_, record) => (
            <Space>
              <EditButton hideText size="small" recordItemId={record.id} />
              <ShowButton hideText size="small" recordItemId={record.id} />
              <DeleteButton hideText size="small" recordItemId={record.id} />
            </Space>
          )}
        />
      </Table>
    </List>
  );
};
Enter fullscreen mode Exit fullscreen mode

Similarly, let's add the create, edit and jobs crud pages under the pages folder.

Next, let's define the resources in <Refine> (App.tsx):

      <Refine
           dataProvider={dataProvider}
           ...
            resources={[
                {
                   name: "companies",
                   list: CompanyList,
                   create: CompanyCreate,
                   edit: CompanyEdit,
                   show: CompanyShow,
                },
                {
                   name: "jobs",
                   list: JobList,
                   create: JobCreate,
                   edit: JobEdit,
                   show: CompanyShow,
                },
           ]}
    />
Enter fullscreen mode Exit fullscreen mode

Refine

Top comments (0)

Take a look at this:

Settings

Go to your customization settings to nudge your home feed to show content more relevant to your developer experience level. πŸ›