Build full-stack applications with AdminJS

Building a custom admin panel for each Node.js project can be a time-consuming task for developers, especially given the number of projects they work on. Hence, there is a growing demand for alternative tools aimed at reducing the workload of developers.

JS logo

 This article highlights a feature of the open source Node.js admin panel that promises to do just that: AdminJS. The tutorial section of this article will demonstrate how to build a full-stack application using AdminJS.

  • What is AdminJS?

  • Why use AdminJS?

  • set new project

  • Add Express.js plugin

  • Add MongoDB adapter

  • Create blog model

    • Create resources

  • Create an action handler

    • backend operations

    • Actions with visible UI

  • Add user authentication

  • set front end

  • test application

What is AdminJS?

AdminJS, formerly known as AdminBro, is an open-source admin panel interface tailored to meet the needs of Node.js applications. This interface eliminates the time and effort required to develop custom admin pages. Instead, users can easily view and manage content using the AdminJS UI.

AdminJS is built using React and offers a range of customizability, it also provides a REST API that can be integrated into other applications.

Why use AdminJS?

Using AdminJS, users can quickly build and setup admin dashboards and applications. How to refresh the bios of the computer motherboard? Three minutes to complete the mainboard flash BIOS operation To help you evaluate whether you should consider using AdminJS for your application needs, here is a summary of its features:

  • Easy integration with other applications: AdminJS can be easily integrated into many other applications, such as SQL and NoSQL data sources and frameworks such as Express.js, NestJS and Fastify

  • Does not impose its database schema on users: AdminJS supports various ORMs and ODMs, enabling users to connect to the database of their choice

  • Backend agnostic: users can create, read, update and delete content regardless of the data source chosen

  • Advanced Filtering Capabilities: Users can easily track specific search queries by applying multiple criteria to quickly filter out unwanted results

  • Flexible user management: Different authorization levels can be set for users. This feature also enables the creation of roles and the ability to restrict certain actions, such as data modification, to specific users

  • Easy Customization: The visual appearance of the AdminJS UI can be modified to suit user needs

  • Customizable features: Many standard features such as file uploads, bulk edits, exports, user profiles, and password hashes can be applied to data sources; users can also create unique features as needed

set new project

To start with AdminJS, how to open the sql database file? How to open SQL files in Windows? We need to install the AdminJS core package and set it up with the plugins and adapters of our choice. In this tutorial, we'll use the Express.js plugin and the MongoDB adapter.

To install the AdminJS core package on your local machine, navigate to a directory of your choice and open the CLI. From the command line, install AdminJS using npm or Yarn with one of the following commands:

npm init
//select default options and fill out fields as desired
npm i adminjs
yarn init
//select default options and fill out fields as desired
yarn add adminjs

Add Express.js plugin

To add the Express plugin, we will use one of the following commands in the CLI:

npm i @adminjs/express                # for Express server
yarn add @adminjs/express                # for Express server

Add MongoDB adapter

Next, we'll add the MongoDB adapter to our application using one of the following commands:

npm i @adminjs/mongoose mongoose              # for Mongoose
yarn add @adminjs/mongoose mongoose               # for Mongoose

Once the installation is complete, we can complete the setup by connecting the installed plugins and adapters to our AdminJS package. First, we'll install Express.js:

//npm
npm i express tslib express-formidable express-session
//yarn
yarn add express tslib express-formidable express-session

Next, we'll set up a simple application using Express. In the files directory, we will create a new file and add the following content: App.js

const AdminJS = require('adminjs')
const AdminJSExpress = require('@adminjs/express')
const express = require('express')
const PORT = 3000
const startAdminJS = async () => {
  const app = express()
  const admin = new AdminJS({})
  const adminRouter = AdminJSExpress.buildRouter(admin)
  app.use(admin.options.rootPath, adminRouter)
  app.listen(PORT, () => {
    console.log(`Listening on port ${PORT}, AdminJS server started on URL: http://localhost:${PORT}${admin.options.rootPath}`)
  })
}
startAdminJS()

Here, we have created a simple AdminJS interface . In this tutorial, we'll add a MongoDB data source, add authentication to the AdminJS UI, and create a simple application using the database.

Create blog model

We will use MongoDB as the data source for the AdminJS panel. As a prerequisite, we need to create a database on MongoDB and connect our application to it using the Mongoose adapter.

To get started, log into MongoDB and select Create Organization:

Here, we have created an organization called "AdminJS Data Sources". Next, we'll add a new project to the organization; we'll name the project "Book Model":

Next, we will be prompted to create a new database. In this tutorial, we will build a shared cluster called "Books".

We will now create admin credentials for the cluster and add the localhost URL to the IP address field. To obtain connection credentials, click Connect and select Connect Using MongoDB Native Adapter. In a full-stack application, we can find the unique URI to connect our application to the database.

In the application's working directory, we'll create a folder and a file. In the file we will define the schema of the database: bookModel book.model.jsbook.model.js

const mongoose = require('mongoose');
const BookSchema = new mongoose.Schema({
    title: { type: String },
    author: { type: String },
});
const Book = mongoose.model('Book', BookSchema);
module.exports = {
    BookSchema,
    Book,
}

The defined schema will have the following fields: and . BookModel titleauthor

Create resources

Next, we add the model created in the previous section to our file, connect our application to MongoDB, and create an AdminJS instance. app.js

To do this, make the following modifications to the file: app.js

//previous libraries import
const mongoose = require("mongoose");
const AdminJSMongoose = require("@adminjs/mongoose");
const { Book } = require("./bookModel/book.model.js");
AdminJS.registerAdapter({
  Resource: AdminJSMongoose.Resource,
  Database: AdminJSMongoose.Database,
})
//port
const startAdminJS = async () => {
  const app = express();
  const mongooseDB = await mongoose
    .connect(
      "mongodb+srv://ZionDev:[email protected]/?retryWrites=true&w=majority",
      {
        useNewUrlParser: true,
        useUnifiedTopology: true,
      }
    )
    .then(() => console.log("database connected"))
    .catch((err) => console.log(err));
  const BookResourceOptions = {
    databases: [mongooseDB],
    resource: Book,
  };
  const adminOptions = {
    rootPath: "/admin",
    resources: [BookResourceOptions],
  };
  const admin = new AdminJS(adminOptions);
    //other code

Here we add the model as a resource to AdminJS. We also added a MongoDB database to automatically update whenever we perform CRUD operations in AdminJS. book

If we run the application with the command we will get the AdminJS default screen and the model will appear in the navigation section: node App.js``Book

Create an action handler

AdminJS provides the following actions: List, Search, New, Show, Edit, Delete and Bulk Delete. It also allows users to define custom actions when required. The operations to be created can be divided into two categories:

  • Actions that run on the backend without showing a visible UI

  • Operations that render components

The two operations are similar in that they are created with the same schema. The notable difference between the two modes is the addition of a prop. Let's see how to do both types of operations. component

backend operations

To create these actions, we'll use the following syntax:

const BookResourceOptions = {
    resource: Book,
    options: {
      actions: {
        GetJsonData: {
          actionType: "record",
          component: false,
          handler: (request, response, context) => {
            const { record, currentAdmin } = context;
            console.log("record", record);
            return {
              record: record.toJSON(currentAdmin),
              msg: "Hello world",
            };
          },
        },
      },
    },
  };

Here we are adding the . above command to set the property to . Therefore, no components will be rendered and the actions will run on the backend. The generated output will be the data of the selected records. BookResourceOption componentfalse

Actions with visible UI

Next, we need to create a component that the action will render. We then add the designed component to the property field. component

For example, suppose we have the following custom React component:

import React from 'react'
import { ActionProps } from 'adminjs'
const ShowRecord = (props) => {
  const { record } = props
  return (
    <Div>
      <h1>This is a simple component</h1>
    <p>Below are our records</p>
    <span>
      {JSON.stringify(record)}
    </span>
    </Div>
  )
}
export default ShowRecord

Once created, we can add it to the properties like so: component

component: AdminJS.bundle('./ShowRecord'),

Add user authentication

AdminJS can add user authentication to view and manage content; this helps to better protect data and limit unwanted access. We can add authentication to our AdminJS application using a plugin. To do this, we will make the following modification to the file: express``App.js

//other code

//login details
const DEFAULT_ADMIN = {
  email: '[email protected]',
  password: 'administrator',
}

// handle authentication
const authenticate = async (email, password) => {
  //condition to check for correct login details
  if (email === DEFAULT_ADMIN.email && password === DEFAULT_ADMIN.password) {
    //if the condition is true
    return Promise.resolve(DEFAULT_ADMIN)
  }
  //if the condition is false
  return null
}

Finally, we replace AdminJS with and pass authentication credentials to it: buildRouter``buildAuthenticatedRouter

const adminRouter = AdminJSExpress.buildAuthenticatedRouter(
    admin,
    {
      authenticate,
      cookieName: "AdminJS",
      cookiePassword: "Secret",
    },
    null,
    {
      store: mongooseDB,
      resave: true,
      saveUninitialized: true,
      secret: 'Secret',
      name: 'adminjs',
    }
  );

With this, we got a login page to access the AdminJS instance:

set front end

Next, we'll build a book list application using Next.js and Axios, connect the AdminJS interface to the application, and display the stored content. To access the AdminJS content, we'll create an API request to the URL instance running on the backend.

Inside the directory we will create a file: . Next, we'll make API requests to the resources in this file. The API endpoint for a resource has the following syntax: api getBooks.jsBooks

.../api/resources/{resourceId}/actions/{action}

In this case, our resource is and the action to perform is . This operation will return all data stored in the resource. Add the following code to the file: id Booklist ``getBooks.js

import axios from "axios";

export default async function handler(req, res) {
  await axios
    .get("http://localhost:3000/admin/api/resources/Book/actions/list")

    .then((response) => {
      return res.status(200).json(response.data.records);
    })
    .catch((error) => {
      console.log(error);
    });
}

The code above returns a response containing our resource data. We can access this data as in the front end of the file: static props``index.js

export default function Home(props) {
  console.log(props);
  return (
    <div style={
  
  {display:"flex", alignItems:"center", height:"100vvh", paddingTop:"55px", flexDirection:"column"}}>
      <h1>Book List Application</h1>
      <div style={
  
  {marginTop:"34px"}} >
        {/* book List container */}
        {props.books.map((book) => {
          return (
            <div style={
  
  {display:"flex", flexDirection:"column", border:"1px solid black", width:"500px", padding:"10px", margin:"10px"}}>
              <h2>{book.params.title}</h2>
              <p>{book.params.author}</p>
            </div>
          );
        }
        )}
      </div>
    </div>
  )
}

export const getStaticProps = async () => { 
  const res = await fetch('http://localhost:3001/api/getBooks');
  const data = await res.json();
  return {
    props: { books: data }
  }
}

We use to fetch data from the API route and pass it as . We can then access it on the frontend and return and for each array element in the response. getStaticProps propsprop titleauthor

test application

To test our application, we'll create entries using an AdminJS instance:

There are three entries in the dashboard list above, each containing a book title and author. If we navigate to the MongoDB collection on MongoDB Atlas, we can see the data resulting from the operation performed in the AdminJS instance: Books``Create

Now, when we run the Next.js application, we get the following result:

in conclusion

In this tutorial, we introduce AdminJS, review its many features, and then use it to build a full-stack Node.js application with Express.js and MongoDB. How will you use AdminJS in your next project?

Guess you like

Origin blog.csdn.net/weixin_47967031/article/details/132470290