Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@devfamily/admiral

Package Overview
Dependencies
Maintainers
3
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@devfamily/admiral

Admiral is a frontend framework for creating back office using React. It provides out-of-the-box components and tools that make developing an admin interface easy and fast.

  • 5.7.0
  • Source
  • npm
  • Socket score

Version published
Maintainers
3
Created
Source

Admiral logo

Revolutionize Your Workflow with Admiral: A Powerful Solution for Tailored Admin Panels and Business Applications

Try live demo


Twitter Downloads Version License


Admiral Administration panel

Admiral is a frontend framework for creating back office in React. It provides out-of-the-box components and tools that make developing an admin interface easy and fast.

Made with :purple_heart: by dev.family

📖 Table of Contents

✨ Features

  • 📀 Out-of-the-box React components used.
  • 🛡 It is written in TypeScript and has built-in typing.
  • 👨‍💻 Adaptive design: The library interface scales to any screen size. This is convenient when used on mobile devices.
  • 🌍 Localization: we support different languages.
  • 👨‍🎨 An interface that is intuitively easy to work with.
  • 🎨 Different design themes: you can change the color scheme of the interface to suit your needs.

🚨What problems do we solve

  • Development complexity. Development complexity. We have collected ready-made components and tools to simplify and speed up development. Especially for those who are new to React.
  • Inconsistent design. We created a unified design and style for all components so that you don't have any trouble generating new ones.
  • Support complexity. We gathered all the necessary components and tools in one library, so that you don't waste your time looking for them.
  • Low performance. We use modern technologies such as React Hooks, Redux, and GraphQL to achieve high performance and fast responsiveness of the interface. Your admin area will no longer be slowed down by the large number of requests to the server and complex operations on the client.
  • CRUD. We have prepared tools to quickly create CRUD (Create, Read, Update, Delete) interfaces. Generate tables with data, forms for creating and editing objects, and components for deleting objects - in 5 minutes.

🔨 Installation

Requirements:

  • Node.js >=v14.21.3 <=20.3.0

There are several options for installing Admiral:

📦 NPX

To use npx, make sure you have Node.js

npx create-admiral-app@latest

When you enter this command into the console, you will see 2 installation options:

  • Install the template with backend on Express.js.
  • Install the template without backend.

If you choose "Install the template with the backend setting on Express.js", you will install the fully customized template with backend on Express.js.

Detailed installation and startup instructions

All environment variables will be set automatically. If you want to configure them manually, go to the project folder and open the .env. You will have 1 CRUDs from the start - Users. To find them pass the way - admiral/src/crud/users/index.tsx

If you choose "Install the template without backend setting", you get just the frontend shell of Admiral in the admiral folder with CRUD - Users. To find it pass the way - admiral/src/crud/users/index.tsx. To use your backend, read the Documentation

Admiral is available at http://localhost:3000. If port 3000 is busy, any other free port will be selected.

In the console you will see something like this

Port 3000 is in use, trying another one...

vite v2.9.15 dev server running at:

> Local:    http://localhost:3001/
> Network:  http://192.168.100.82:3001/

ready in 459ms.

📦 Use one of our examples

Detailed installation and startup instructions are in each of the examples.

Open your browser and go to http://localhost:3000.

📦 Git Clone

Yes, that's right. You can just clone this repository and enter the following commands:

yarn
yarn dev

Then go to http://localhost:3000. The Admiral with mock data is now available to you.

📦 Usage

The App.tsx file is the entry point into the application. It is where the library is initialized and where the components are rendered Admin.

import React from 'react'
import { Admin, createRoutesFrom, OAuthProvidersEnum } from '../admiral'
import Menu from './config/menu'
import dataProvider from './dataProvider'
import authProvider from './authProvider'

const apiUrl = '/api'
// import all pages from pages folder and create routes
const Routes = createRoutesFrom(import.meta.globEager('../pages/**/*'))

function App() {
    return (
        <Admin
            dataProvider={dataProvider(apiUrl)}
            authProvider={authProvider(apiUrl)}
            menu={Menu}
            oauthProviders={[
                OAuthProvidersEnum.Google,
                OAuthProvidersEnum.Github,
                OAuthProvidersEnum.Jira,
            ]}
        >
            <Routes />
        </Admin>
    )
}

export default App

Interaction with API

Auth - AuthProvider

The main contract for authorization in the system is the interface AuthProvider.

export interface AuthProvider {
    login: (params: any) => Promise<any>
    logout: (params: any) => Promise<void | false | string>
    checkAuth: (params: any) => Promise<void>
    getIdentity: () => Promise<UserIdentity>
    oauthLogin?: (provider: OAuthProvidersEnum) => Promise<{ redirect: string }>
    oauthCallback?: (provider: OAuthProvidersEnum, data: string) => Promise<any>

    [key: string]: any
}

Example of implementation The interface itself can be customized to your liking, but it is important to respect the contract it provides. Detailed contract description

Let's look at the basic methods of implementation:

MethodNameDescriptionParametersReturn value
loginUser AuthenticationMakes a POST request to /api/login and stores the token field in localStorage, which is used in further requestsparams - object with the fields username and passwordAn object with a token field and a user object with email and name fields
logoutUser LogoutMakes a POST request to /api/logout and removes the token field from localStoragevoid
checkAuthUser authorization checkMakes a GET request to /api/checkAuth and checks token validity, expects a status code - 200. Used every time the API is usedBearer tokenStatus code 200
getIdentityReceiving user dataMakes a GET request to /api/getIdentity and returns an object with user dataBearer tokenObject user with the fields email and name
oauthLoginAuthorization via OAuthMakes a GET request to /api/auth/social-login/${provider} and returns an object with the redirect field, which is used for the redirectprovider - OAuth providerObject with the field redirect
oauthCallbackCallback authorization via OAuthMakes a POST request to /api/auth/social-login/${provider}/callback and stores the token field in localStorage, which is used in further requestsprovider - OAuth provider, data - data received from OAuth provider where the token field existsObject with the field token
CRUD DataProvider

The main contract for working with data represents the interface DataProvider.

export interface DataProvider {
    getList: (
        resource: string,
        params: Partial<GetListParams>,
    ) => Promise<GetListResult<RecordType>>
    reorderList: (resource: string, params: ReorderParams) => Promise<void>
    getOne: (resource: string, params: GetOneParams) => Promise<GetOneResult<RecordType>>
    getCreateFormData: (resource: string) => Promise<GetFormDataResult<RecordType>>
    getFiltersFormData: (
        resource: string,
        urlState?: Record<string, any>,
    ) => Promise<GetFiltersFormDataResult>
    create: (resource: string, params: CreateParams) => Promise<CreateResult<RecordType>>
    getUpdateFormData: (
        resource: string,
        params: GetOneParams,
    ) => Promise<GetFormDataResult<RecordType>>
    update: (resource: string, params: UpdateParams) => Promise<UpdateResult<RecordType>>
    deleteOne: (resource: string, params: DeleteParams) => Promise<DeleteResult<RecordType>>

    [key: string]: any
}

Example of implementation Detailed contract description

Let's look at the basic methods of implementation:

MethodNameDescriptionParameters
getListGetting a list of entitiesMakes a GET request to /api/${resource} and returns an object with data to be used in the List componentresource - resource name, params - object with query parameters
reorderListChanging the order of entitiesMakes a POST request to /api/${resource}/reorder and returns an object with data to be used in the List componentresource - resource name, params - object with query parameters
getOneObtaining an entityMakes a GET request to /api/${resource}/${id} and returns an object with data to be used in the Show componentresource - resource name, id - entity identifier
getCreateFormDataGetting data for an entity creation form (Select, AjaxSelect)Makes a GET request to /api/${resource}/create and returns an object with data to be used in the Create componentresource - resource name
getFiltersFormDataReceiving data for filtersMakes a GET request to /api/${resource}/filters and returns an object with data to be used in the Filters componentresource - resource name, urlState - object with parameters from the url to be used in the component Filters
createCreating an EntityMakes a POST request to /api/${resource} and returns an object with data to be used in the component Createresource - resource name, params - entity data object
getUpdateFormDataGetting data for an entity edit form (Select, AjaxSelect)Makes a GET request to /api/${resource}/${id}/update and returns an object with data to be used in the component Editresource - resource name, id - entity identifier
updateUpdating an entityMakes a POST request to /api/${resource}/${id} and returns an object with the data to be used in the component Editresource - resource name, id - entity identifier, params - entity data object
deleteDeleting an EntityДелает DELETE запрос на /api/${resource}/${id} и возвращает объект с данными, которые будут использоваться в компоненте Deleteresource - resource name, id - entity identifier
getList Query Example [Receive 10 Users per page with filter by id=1]

Query:

http://localhost/admin/users?page=1&perPage=10&filter%5Bid%5D=1

Result:

{
    "items": [
        {
            "id": 1,
            "name": "Dev family",
            "email": "info@dev.family",
            "role": "Administrator",
            "created_at": "2023-05-05 14:17:51"
        }
    ],
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "per_page": 10,
        "to": 1,
        "total": 1
    }
}
getOne Query Example [Receive User where id=1]

Query:

http://localhost/admin/users/1/update?id=1

Result:

{
    "data": {
        "id": 1,
        "name": "Dev family",
        "email": "info@dev.family",
        "role_id": 1
    },
    "values": {
        "role_id": [
            {
                "label": "Administrator",
                "value": 1
            }
        ]
    }
}

Note: We utilize the HTTP status code 422 Unprocessable Entity to handle validation errors.

Example Validation Error
{
    "errors": {
        "name": ["Field 'name' is invalid."],
        "email": ["Field 'email' is invalid."]
    },
    "message": "Validation failed"
}
Pagination

Pagination work with getList method. You can pass page and perPage params to getList method, and it will return PaginationResult object with items and meta fields.

Filters

Filters work with getList method. You can pass filter[$field] param to getList method, and it will return PaginationResult object with items and meta fields.

Sorting

Sorting work with getList method. You can pass sort[$field] param to getList method, and it will return PaginationResult object with items and meta fields.

Routing

Admiral has a file-system based router.

A page is a React Component exported from a .js, .jsx, .ts, or .tsx file in the pages' directory. When a file is added to the pages' directory, it's automatically available as a route. react-router-dom is used under the hood.

Index routes

The router will automatically route files named index to the root of the directory.

pages/index.ts → / pages/users/index.ts → /users

Nested routes

The router supports nested files. If you create a nested folder structure, files will automatically be routed in the same way still.

pages/users/create.ts → /users/create

Dynamic route segments

To match a dynamic segment, you can use the bracket syntax. This allows you to match named parameters.

pages/users/[id].ts → /users/:id (/users/42)


Menu

A menu is an array of objects that have the following structure:

import { Menu, SubMenu, MenuItemLink } from '../../admiral'

const CustomMenu = () => {
    return (
        <Menu>
            <MenuItemLink icon="FiCircle" name="First Menu Item" to="/first" />
            <SubMenu icon="FiCircle" name="Second Menu Item">
                <MenuItemLink icon="FiCircle" name="Sub Menu Item" to="/second" />
            </SubMenu>
        </Menu>
    )
}

export default CustomMenu

Hooks

Our application uses React hooks. You can use them from anywhere in the application inside the React components. These are the hooks you can use:

useNav

This hook allows you to receive and manage the status of the navigation bar

import { useNav } from '@devfamily/admiral'
const { collapsed, toggleCollapsed, visible, toggle, open, close } = useNav()
  • collapsed - a variable containing the state of the navigation panel (collapsed or not)
  • toggleCollapsed - a method that allows you to control the state of the navigation panel.
  • visible - a variable containing the state of the burger menu (open-closed).
  • toggle - a method that allows you to manage the state of the burger menu (opening-closing).
  • open - a method that allows you to open the burger menu.
  • close - a method that allows you to close the burger menu.
useForm

This hook allows you to get form values and manage the state of the form. The hook can be used in components used in "form" inside the configuration of the createCRUD function.

import { useForm } from '@devfamily/admiral'
const {
    values,
    options,
    errors,
    setErrors,
    setValues,
    setOptions,
    isSubmitting,
    isFetching,
    locale,
} = useForm()
  • options - options, which are returned from the server for this form.
  • errors - errors, which are returned from the server when initializing the form, or when submitting the form.
  • setErrors - a method for recording the errors.
  • setValues - a method for recording the values.
  • setOptions - a method for recording the options.
  • isSubmitting - form submitting status.
  • isFetching - form initialization status.
  • locale - localization configuration for the form.
useTheme

This hook allows you to receive and manage the state of theme.

import { useTheme } from '@devfamily/admiral'
const { themeName, setTheme } = useTheme()
  • themeName - name of the active theme.
  • setTheme - a method to change the theme, you need to pass argument name as 'dark' or 'light.
useGetIdentty

A hook that allows you to get the state obtained by calling AuthProvider.getIdentity()

import { useGetIdentty } from '@devfamily/admiral'
const { identity, loading, loaded, error } = useGetIdentty()
  • identity - a variable containing the state.
  • loading - a state initialization status.
  • loaded - a variable that indicates that the state has been initialized.
  • error - a object of errors.

Icons

Icons used in Admiral are from React Icons.

Custom theme

ThemeProvider uses @consta/uikit Theme component under the hood.

You can pass your presets to Admin component with themePresets prop:

import React from 'react'
import { Admin, createRoutesFrom } from '../admiral'
import Menu from './config/menu'
import dataProvider from './dataProvider'
import authProvider from './authProvider'
import themeLight from './theme/presets/themeLight'
import themeDark from './theme/presets/themeDark'

const apiUrl = '/api'
const Routes = createRoutesFrom(import.meta.globEager('../pages/**/*'))

function App() {
    return (
        <Admin
            dataProvider={dataProvider(apiUrl)}
            authProvider={authProvider(apiUrl)}
            menu={Menu}
            themePresets={{ light: themeLight, dark: themeDark }}
        >
            <Routes />
        </Admin>
    )
}
To create your own preset:
  1. Create a directory for presets. Inside make folders for each modifier - the same as in the Theme component.

  2. Create CSS files. In the folders with the modifiers put the CSS files that will be responsible for those modifiers.
    You will get something similar:

    presets/
      _color/
        _Theme_color_themeDark.css
        _Theme_color_themeLight.css
      _control/
        _Theme_control_themeLight.css
      _font/
        _Theme_font_themeLight.css
      _size/
        _Theme_size_themeLight.css
      _space/
        _Theme_space_themeLight.css
      _shadow/
        _Theme_shadow_themeLight.css
      themeLight.ts
      themeDark.ts
    
  3. Configure the variables in CSS files.

  4. Create a preset files (themeLight, themeDark).
    Import the CSS files you are going to use.
    Create a preset object. Specify which values (i.e. CSS files) for which modifiers to use in the preset. You will get something similar:

    // in presets/themeLight.ts
    import './_color/_Theme_color_themeLight.css'
    import './_color/_Theme_color_themeDark.css'
    import './_control/_Theme_control_themeLight.css'
    import './_font/_Theme_font_themeLight.css'
    import './_size/_Theme_size_themeLight.css'
    import './_space/_Theme_space_themeLight.css'
    import './_shadow/_Theme_shadow_themeLight.css'
    
    export default {
        color: {
            primary: 'themeLight',
            accent: 'themeDark',
            invert: 'themeDark',
        },
        control: 'themeLight',
        font: 'themeLight',
        size: 'themeLight',
        space: 'themeLight',
        shadow: 'themeLight',
    }
    
  5. Pass your presets to Admin component as in the example above.

Note: postcss plugins are used for color transformation in admiral presets example. If you want to reproduce, setup postcss and postcss-color-mod-function plugin.

🗺️ Roadmap

  • Routing
  • Menu
  • Icons
  • Custom theme
  • OAuth
  • Documentation
  • Custom login page
  • Laravel Example
  • Websockets

🏆 How can I support the developers?

  • Star our GitHub repo ⭐
  • Create pull requests, submit bugs, suggest new features or documentation updates 🔧
  • Read us on Medium
  • Follow us on Twitter 🐾
  • Like our page on LinkedIn 👍

🤝 Contributing

If you want to participate in the development of Admiral, make a Fork of the repository, make the desired changes and send a pull request. We will be glad to consider your suggestions!

©️ License

This library is distributed under the MIT license.

📚 Contact

If you have any questions, please contact us at: admiral@dev.family We're always happy to receive your feedback!

Keywords

FAQs

Package last updated on 15 Sep 2023

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc