Essayez la démo en direct
Admiral est un framework frontend permettant de créer du back-office dans React. Il fournit des composants et des outils prêts à l'emploi qui facilitent et accélèrent le développement d'une interface d'administration.
Fabriqué avec ? par dev.family
Exigences:
Il existe plusieurs options pour installer Admiral :
Pour utiliser npx, assurez-vous d'avoir Node.js
npx create-admiral-app@latest
Lorsque vous entrez cette commande dans la console, vous verrez 2 options d'installation :
Si vous choisissez « Installer le modèle avec le paramètre backend sur Express.js », vous installerez le modèle entièrement personnalisé avec le backend sur Express.js.
Instructions détaillées d'installation et de démarrage
Toutes les variables d'environnement seront définies automatiquement. Si vous souhaitez les configurer manuellement, accédez au dossier du projet et ouvrez le .env. Vous aurez 1 CRUD dès le départ - Utilisateurs . Pour les trouver, passez le chemin - admiral/src/crud/users/index.tsx
Si vous choisissez " Installer le modèle sans paramètre backend ", vous obtenez uniquement le shell frontend d'Admiral dans le dossier amiral avec CRUD - Users . Pour le trouver, passez par - admiral/src/crud/users/index.tsx
. Pour utiliser votre backend, lisez la documentation
Admiral est disponible sur http://localhost:3000. Si le port 3000 est occupé, tout autre port libre sera sélectionné.
Dans la console, vous verrez quelque chose comme ceci
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.
Des instructions détaillées d'installation et de démarrage se trouvent dans chacun des exemples.
Ouvrez votre navigateur et accédez à http://localhost:3000.
Oui, c'est vrai. Vous pouvez simplement cloner ce référentiel et saisir les commandes suivantes :
yarn
yarn dev
Accédez ensuite à http://localhost:3000. L'Amiral avec des données simulées est désormais à votre disposition.
Le fichier App.tsx est le point d'entrée dans l'application. C'est là que la bibliothèque est initialisée et que les composants sont rendus 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
Le principal contrat d'autorisation dans le système est l'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
}
Exemple d'implémentation L'interface elle-même peut être personnalisée à votre guise, mais il est important de respecter le contrat qu'elle prévoit. Description détaillée du contrat
Examinons les méthodes de mise en œuvre de base :
Méthode | Nom | Description | Paramètres | Valeur de retour |
---|---|---|---|---|
se connecter | Authentification utilisateur | Effectue une requête POST vers /api/login et stocke le champ token dans localStorage, qui est utilisé dans d'autres requêtes. | params - objet avec les champs username et password | Un objet avec un champ token et un objet user avec des champs email et name |
déconnexion | Déconnexion de l'utilisateur | Fait une requête POST à /api/logout et supprime le champ token de localStorage | void | |
vérifierAuth | Vérification de l'autorisation de l'utilisateur | Effectue une requête GET à /api/checkAuth et vérifie la validité du jeton, attend un code d'état - 200. Utilisé à chaque fois que l'API est utilisée | token du porteur | Code d'état 200 |
obtenirIdentity | Réception des données utilisateur | Fait une requête GET à /api/getIdentity et renvoie un objet avec les données utilisateur | token du porteur | Objet user avec les champs email et name |
oauthConnexion | Autorisation via OAuth | Effectue une requête GET à /api/auth/social-login/${provider} et renvoie un objet avec le champ redirect , qui est utilisé pour la redirection | provider - Fournisseur OAuth | Objet avec la redirect du champ |
oauthRappel | Autorisation de rappel via OAuth | Effectue une requête POST à /api/auth/social-login/${provider}/callback et stocke le champ token dans localStorage, qui est utilisé dans d'autres requêtes | provider - fournisseur OAuth, data - données reçues du fournisseur OAuth où le champ token existe | Objet avec le token de champ |
Le contrat principal pour travailler avec des données représente l'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
}
Exemple de mise en œuvre Description détaillée du contrat
Examinons les méthodes de mise en œuvre de base :
Méthode | Nom | Description | Paramètres |
---|---|---|---|
obtenirListe | Obtenir une liste d'entités | Effectue une requête GET à /api/${resource} et renvoie un objet avec des données à utiliser dans le composant List | resource - nom de la ressource, params - objet avec paramètres de requête |
réorganiser la liste | Changer l'ordre des entités | Effectue une requête POST à /api/${resource}/reorder et renvoie un objet avec des données à utiliser dans le composant List | resource - nom de la ressource, params - objet avec paramètres de requête |
obtenirUn | Obtention d'une entité | Effectue une requête GET à /api/${resource}/${id} et renvoie un objet avec des données à utiliser dans le composant Show | resource - nom de la ressource, id - identifiant de l'entité |
getCreateFormData | Obtenir des données pour un formulaire de création d'entité (Select, AjaxSelect) | Effectue une requête GET à /api/${resource}/create et renvoie un objet avec des données à utiliser dans le composant Create | resource - nom de la ressource |
getFiltersFormData | Réception de données pour les filtres | Effectue une requête GET à /api/${resource}/filters et renvoie un objet avec des données à utiliser dans le composant Filters | resource - nom de la ressource, urlState - objet avec les paramètres de l'URL à utiliser dans le composant Filters |
créer | Créer une entité | Fait une requête POST à /api/${resource} et renvoie un objet avec des données à utiliser dans le composant Create | resource - nom de la ressource, params - objet de données d'entité |
getUpdateFormData | Obtenir des données pour un formulaire de modification d'entité (Select, AjaxSelect) | Fait une requête GET à /api/${resource}/${id}/update et renvoie un objet avec des données à utiliser dans le composant Edit | resource - nom de la ressource, id - identifiant de l'entité |
mise à jour | Mettre à jour une entité | Fait une requête POST à /api/${resource}/${id} et renvoie un objet avec les données à utiliser dans le composant Edit | resource - nom de la ressource, id - identifiant d'entité, params - objet de données d'entité |
supprimer | Supprimer une entité | Effectue une requête DELETE à /api/${resource}/${id} et renvoie un objet avec des données à utiliser dans le composant Delete | resource - nom de la ressource, id - identifiant de l'entité |
Requête:
http://localhost/admin/users?page=1&perPage=10&filter%5Bid%5D=1
Résultat:
{
"items" : [
{
"id" : 1 ,
"name" : " Dev family " ,
"email" : " [email protected] " ,
"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
}
}
Requête:
http://localhost/admin/users/1/update?id=1
Résultat:
{
"data" : {
"id" : 1 ,
"name" : " Dev family " ,
"email" : " [email protected] " ,
"role_id" : 1
},
"values" : {
"role_id" : [
{
"label" : " Administrator " ,
"value" : 1
}
]
}
}
❗ Remarque : Nous utilisons le code d'état HTTP 422 Unprocessable Entity pour gérer les erreurs de validation.
{
"errors" : {
"name" : [ " Field 'name' is invalid. " ],
"email" : [ " Field 'email' is invalid. " ]
},
"message" : " Validation failed "
}
La pagination fonctionne avec la méthode getList
. Vous pouvez transmettre les paramètres page
et perPage
à la méthode getList
, et elle renverra l'objet PaginationResult
avec items
et des champs meta
.
Les filtres fonctionnent avec la méthode getList
. Vous pouvez transmettre filter[$field]
à la méthode getList
, et il renverra l'objet PaginationResult
avec items
et des champs meta
.
Le tri fonctionne avec la méthode getList
. Vous pouvez transmettre le paramètre sort[$field]
à la méthode getList
, et il renverra l'objet PaginationResult
avec items
et des champs meta
.
Admiral dispose d'un routeur basé sur un système de fichiers .
Une page est un composant React exporté à partir d'un fichier .js, .jsx, .ts ou .tsx dans le répertoire des pages. Lorsqu'un fichier est ajouté au répertoire des pages, il est automatiquement disponible en tant que route. React-Router-Dom est utilisé sous le capot.
Le routeur acheminera automatiquement les fichiers nommés index vers la racine du répertoire.
pages/index.ts → /
pages/users/index.ts → /users
Le routeur prend en charge les fichiers imbriqués. Si vous créez une structure de dossiers imbriquée, les fichiers seront automatiquement acheminés de la même manière.
pages/users/create.ts → /users/create
Pour faire correspondre un segment dynamique, vous pouvez utiliser la syntaxe entre crochets. Cela vous permet de faire correspondre les paramètres nommés.
pages/users/[id].ts → /users/:id (/users/42)
Ce composant est le plus important de votre panneau d'administration. Avec lui, vous pouvez définir les paramètres et configurations fondamentaux de votre application, tels que : la navigation, le logo, l'API pour les requêtes vers un serveur, l'autorisation de l'API, la localisation, le thème et d'autres choses.
Exemple d'utilisation :
< Admin
dataProvider = { dataProvider ( apiUrl ) }
authProvider = { authProvider ( apiUrl ) }
menu = { Menu }
oauthProviders = { [
OAuthProvidersEnum . Google ,
OAuthProvidersEnum . Github ,
OAuthProvidersEnum . Jira ,
] }
>
< Routes />
</ Admin >
Le composant accepte les propriétés suivantes :
menu
Ici, vous pouvez personnaliser votre navigation. Vous devez utiliser des composants spéciaux de notre package : Menu, MenuItemLink, SubMenu. Vous pouvez trouver un exemple ici.
logo
Vous pouvez modifier le logo affiché dans la barre de navigation latérale. L'accessoire accepte un lien vers un composant svg, JSX ou un fichier au format svg.
connexionLogo
Vous pouvez modifier le logo affiché dans le formulaire d'autorisation. L'accessoire accepte un lien vers un composant svg, JSX ou un fichier au format svg.
de côtéContenu
Avec cet outil, vous pouvez ajouter le contenu nécessaire à la barre de navigation latérale sous les liens. Vous devez passer ReactNode.
fournisseur de données
Le contrat principal pour travailler avec des données. Vous pouvez obtenir plus d’informations dans notre documentation.
fournisseur d'authentification
Le contrat principal d'autorisation dans le système. Vous pouvez obtenir plus d’informations dans notre documentation.
thèmePréréglages
Vous pouvez personnaliser le thème de couleur de votre application. Vous pouvez obtenir plus d’informations dans notre documentation.
lieu
Le schéma de localisation de votre panneau d'administration, que vous pouvez obtenir à l'aide du hook useLocaleProvider. Vous pouvez trouver un exemple du schéma ici.
Fournisseurs oauth
Utilisez l'autorisation OAuth à l'aide de ces accessoires. Transmettez le nom du fournisseur requis dans le tableau à l'aide de l'énumération OAuthProvidersEnum de l'amiral.
baseAppUrl
Ajoutez les accessoires pour modifier le chemin de base de l'application.
Un menu est un tableau d'objets qui ont la structure suivante :
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
Notre application utilise des hooks React. Vous pouvez les utiliser depuis n'importe où dans l'application à l'intérieur des composants React. Voici les crochets que vous pouvez utiliser :
Ce hook permet de recevoir et de gérer l'état de la barre de navigation
import { useNav } from '@devfamily/admiral'
const { collapsed , toggleCollapsed , visible , toggle , open , close } = useNav ( )
Ce hook vous permet d'obtenir les valeurs du formulaire et de gérer l'état du formulaire. Le hook peut être utilisé dans les composants utilisés dans le "formulaire" dans la configuration de la fonction createCRUD.
import { useForm } from '@devfamily/admiral'
const {
values ,
options ,
errors ,
setErrors ,
setValues ,
setOptions ,
isSubmitting ,
isFetching ,
locale ,
} = useForm ( )
Ce hook permet de recevoir et de gérer l'état du thème.
import { useTheme } from '@devfamily/admiral'
const { themeName , setTheme } = useTheme ( )
Un hook qui permet d'obtenir l'état obtenu en appelant AuthProvider.getIdentity()
import { useGetIdentty } from '@devfamily/admiral'
const { identity , loading , loaded , error } = useGetIdentty ( )
Les icônes utilisées dans Admiral proviennent de React Icons.
ThemeProvider utilise le composant Thème @consta/uikit sous le capot.
Vous pouvez transmettre vos préréglages au composant Admin
avec la prop themePresets
:
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 >
)
}
Créez un répertoire pour les préréglages. À l'intérieur, créez des dossiers pour chaque modificateur - les mêmes que dans le composant Thème.
Créez des fichiers CSS. Dans les dossiers contenant les modificateurs, placez les fichiers CSS qui seront responsables de ces modificateurs.
Vous obtiendrez quelque chose de similaire :
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
Configurez les variables dans les fichiers CSS.
Créez des fichiers prédéfinis (themeLight, themeDark).
Importez les fichiers CSS que vous allez utiliser.
Créez un objet prédéfini. Spécifiez quelles valeurs (c'est-à-dire les fichiers CSS) pour quels modificateurs utiliser dans le préréglage. Vous obtiendrez quelque chose de similaire :
// 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' ,
}
Transmettez vos préréglages au composant Admin
comme dans l'exemple ci-dessus.
❗ Remarque : les plugins postcss sont utilisés pour la transformation des couleurs dans l'exemple des préréglages Amiral. Si vous souhaitez reproduire, configurez le plugin postcss et postcss-color-mod-function.
Si vous souhaitez participer au développement d'Admiral, faites un Fork du référentiel, apportez les modifications souhaitées et envoyez une pull request. Nous serons heureux de considérer vos suggestions!
Cette bibliothèque est distribuée sous licence MIT.
Si vous avez des questions, veuillez nous contacter à : [email protected] Nous sommes toujours heureux de recevoir vos commentaires !