Experimente a demonstração ao vivo
Admiral é uma estrutura de frontend para criação de back office em React. Ele fornece componentes e ferramentas prontos para uso que tornam o desenvolvimento de uma interface administrativa fácil e rápido.
Feito com? por dev.family
Requisitos:
Existem várias opções para instalar o Admiral:
Para usar npx, certifique-se de ter Node.js
npx create-admiral-app@latest
Ao inserir este comando no console, você verá 2 opções de instalação:
Se você escolher " Instalar o modelo com configuração de backend no Express.js ", você instalará o modelo totalmente customizado com backend no Express.js.
Instruções detalhadas de instalação e inicialização
Todas as variáveis de ambiente serão definidas automaticamente. Caso queira configurá-los manualmente, vá até a pasta do projeto e abra o .env. Você terá 1 CRUDs desde o início - Users . Para encontrá-los, passe pelo caminho - admiral/src/crud/users/index.tsx
Se você escolher " Instalar o modelo sem configuração de backend ", você obterá apenas o shell frontend do Admiral na pasta almirante com CRUD - Users . Para encontrá-lo, passe pelo caminho - admiral/src/crud/users/index.tsx
. Para usar seu backend, leia a documentação
O Almirante está disponível em http://localhost:3000. Se a porta 3000 estiver ocupada, qualquer outra porta livre será selecionada.
No console você verá algo assim
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.
Instruções detalhadas de instalação e inicialização estão em cada um dos exemplos.
Abra seu navegador e acesse http://localhost:3000.
Sim, está certo. Você pode simplesmente clonar este repositório e inserir os seguintes comandos:
yarn
yarn dev
Então vá para http://localhost:3000. O Almirante com dados simulados já está disponível para você.
O arquivo App.tsx é o ponto de entrada no aplicativo. É onde a biblioteca é inicializada e onde os componentes são renderizados 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
O principal contrato para autorização no sistema é a 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
}
Exemplo de implementação A própria interface pode ser customizada ao seu gosto, mas é importante respeitar o contrato que ela oferece. Descrição detalhada do contrato
Vejamos os métodos básicos de implementação:
Método | Nome | Descrição | Parâmetros | Valor de retorno |
---|---|---|---|---|
Conecte-se | Autenticação de usuário | Faz uma solicitação POST para /api/login e armazena o campo token em localStorage, que é usado em solicitações posteriores | params - objeto com os campos username e password | Um objeto com um campo token e um objeto user com campos email e name |
sair | Sair do usuário | Faz uma solicitação POST para /api/logout e remove o campo token do localStorage | void | |
verificarAuth | Verificação de autorização do usuário | Faz uma solicitação GET para /api/checkAuth e verifica a validade do token, espera um código de status - 200. Usado sempre que a API é usada | token ao portador | Código de status 200 |
obterIdentidade | Recebendo dados do usuário | Faz uma solicitação GET para /api/getIdentity e retorna um objeto com dados do usuário | token ao portador | Objeto user com os campos email e name |
oauthLogin | Autorização via OAuth | Faz uma solicitação GET para /api/auth/social-login/${provider} e retorna um objeto com o campo redirect , que é usado para o redirecionamento | provider - provedor OAuth | Objeto com redirect de campo |
oauthCallback | Autorização de retorno de chamada via OAuth | Faz uma solicitação POST para /api/auth/social-login/${provider}/callback e armazena o campo token em localStorage, que é usado em solicitações posteriores | provider - provedor OAuth, data - dados recebidos do provedor OAuth onde existe o campo token | Objeto com o token de campo |
O principal contrato para trabalhar com dados representa a 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
}
Exemplo de implementação Descrição detalhada do contrato
Vejamos os métodos básicos de implementação:
Método | Nome | Descrição | Parâmetros |
---|---|---|---|
getList | Obtendo uma lista de entidades | Faz uma solicitação GET para /api/${resource} e retorna um objeto com dados para serem usados no componente List | resource - nome do recurso, params - objeto com parâmetros de consulta |
reordenarLista | Alterando a ordem das entidades | Faz uma solicitação POST para /api/${resource}/reorder e retorna um objeto com dados a serem usados no componente List | resource - nome do recurso, params - objeto com parâmetros de consulta |
pegueUm | Obtendo uma entidade | Faz uma solicitação GET para /api/${resource}/${id} e retorna um objeto com dados para serem usados no componente Show | resource - nome do recurso, id - identificador da entidade |
getCreateFormData | Obtendo dados para um formulário de criação de entidade (Select, AjaxSelect) | Faz uma solicitação GET para /api/${resource}/create e retorna um objeto com dados para ser usado no componente Create | resource - nome do recurso |
getFiltersFormData | Recebendo dados para filtros | Faz uma solicitação GET para /api/${resource}/filters e retorna um objeto com dados para serem usados no componente Filters | resource - nome do recurso, urlState - objeto com parâmetros da url a ser utilizada no componente Filters |
criar | Criando uma Entidade | Faz uma solicitação POST para /api/${resource} e retorna um objeto com dados para ser usado no componente Create | resource - nome do recurso, params - objeto de dados da entidade |
getUpdateFormData | Obtendo dados para um formulário de edição de entidade (Select, AjaxSelect) | Faz uma solicitação GET para /api/${resource}/${id}/update e retorna um objeto com dados para serem usados no componente Edit | resource - nome do recurso, id - identificador da entidade |
atualizar | Atualizando uma entidade | Faz uma solicitação POST para /api/${resource}/${id} e retorna um objeto com os dados a serem usados no componente Edit | resource - nome do recurso, id - identificador da entidade, params - objeto de dados da entidade |
excluir | Excluindo uma entidade | Faz solicitação DELETE para /api/${resource}/${id} e retorna um objeto com dados para serem usados no componente Delete | resource - nome do recurso, id - identificador da entidade |
Consulta:
http://localhost/admin/users?page=1&perPage=10&filter%5Bid%5D=1
Resultado:
{
"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
}
}
Consulta:
http://localhost/admin/users/1/update?id=1
Resultado:
{
"data" : {
"id" : 1 ,
"name" : " Dev family " ,
"email" : " [email protected] " ,
"role_id" : 1
},
"values" : {
"role_id" : [
{
"label" : " Administrator " ,
"value" : 1
}
]
}
}
❗ Observação : utilizamos o código de status HTTP 422 Entidade Não Processável para lidar com erros de validação.
{
"errors" : {
"name" : [ " Field 'name' is invalid. " ],
"email" : [ " Field 'email' is invalid. " ]
},
"message" : " Validation failed "
}
A paginação funciona com o método getList
. Você pode passar os parâmetros page
e perPage
para o método getList
, e ele retornará o objeto PaginationResult
com items
e meta
.
Os filtros funcionam com o método getList
. Você pode passar filter[$field]
para o método getList
e ele retornará o objeto PaginationResult
com items
e meta
.
A classificação funciona com o método getList
. Você pode passar o parâmetro sort[$field]
para o método getList
e ele retornará o objeto PaginationResult
com items
e meta
.
O Admiral possui um roteador baseado em sistema de arquivos .
Uma página é um componente React exportado de um arquivo .js, .jsx, .ts ou .tsx no diretório das páginas. Quando um arquivo é adicionado ao diretório das páginas, ele fica automaticamente disponível como rota. react-router-dom é usado nos bastidores.
O roteador roteará automaticamente os arquivos denominados index para a raiz do diretório.
pages/index.ts → /
pages/users/index.ts → /users
O roteador oferece suporte a arquivos aninhados. Se você criar uma estrutura de pastas aninhada, os arquivos serão roteados automaticamente da mesma maneira.
pages/users/create.ts → /users/create
Para corresponder a um segmento dinâmico, você pode usar a sintaxe de colchetes. Isso permite que você corresponda aos parâmetros nomeados.
pages/users/[id].ts → /users/:id (/users/42)
Este componente é o mais importante no seu painel de administração. Com ele, você pode definir as definições e configurações fundamentais da sua aplicação, como: navegação, logotipo, API para solicitações a um servidor, autorização de API, localização, tema e outras coisas.
Exemplo de uso:
< Admin
dataProvider = { dataProvider ( apiUrl ) }
authProvider = { authProvider ( apiUrl ) }
menu = { Menu }
oauthProviders = { [
OAuthProvidersEnum . Google ,
OAuthProvidersEnum . Github ,
OAuthProvidersEnum . Jira ,
] }
>
< Routes />
</ Admin >
O componente aceita os seguintes adereços:
menu
Aqui você pode personalizar sua navegação. Você deve usar componentes especiais do nosso pacote: Menu, MenuItemLink, SubMenu. Você pode encontrar um exemplo aqui.
logotipo
Você pode alterar o logotipo exibido na barra de navegação lateral. A prop aceita um link para um svg, componente JSX ou um arquivo com o formato svg.
loginLogo
Você pode alterar o logotipo exibido no formulário de autorização. A prop aceita um link para um svg, componente JSX ou um arquivo com o formato svg.
aparteConteúdo
Com esta ferramenta, você pode adicionar o conteúdo necessário à barra de navegação lateral abaixo dos links. Você tem que passar pelo ReactNode.
provedor de dados
O principal contrato para trabalhar com dados. Você pode obter mais informações em nossa documentação.
provedor de autorização
O principal contrato para autorização no sistema. Você pode obter mais informações em nossa documentação.
temaPresets
Você pode personalizar o tema de cores do seu aplicativo. Você pode obter mais informações em nossa documentação.
localidade
O esquema de localização do seu painel de administração, que você pode obter usando o gancho useLocaleProvider. Você pode encontrar um exemplo do esquema aqui.
oauthProviders
Use a autorização OAuth usando estes adereços. Passe o nome do provedor necessário na matriz usando o enum OAuthProvidersEnum do almirante.
baseAppUrl
Adicione os adereços para alterar o caminho base do aplicativo.
Um menu é uma matriz de objetos que possuem a seguinte estrutura:
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
Nosso aplicativo usa ganchos React. Você pode usá-los de qualquer lugar do aplicativo dentro dos componentes React. Estes são os ganchos que você pode usar:
Este gancho permite receber e gerenciar o status da barra de navegação
import { useNav } from '@devfamily/admiral'
const { collapsed , toggleCollapsed , visible , toggle , open , close } = useNav ( )
Este gancho permite obter valores de formulário e gerenciar o estado do formulário. O gancho pode ser utilizado em componentes utilizados em "form" dentro da configuração da função createCRUD.
import { useForm } from '@devfamily/admiral'
const {
values ,
options ,
errors ,
setErrors ,
setValues ,
setOptions ,
isSubmitting ,
isFetching ,
locale ,
} = useForm ( )
Este gancho permite receber e gerenciar o estado do tema.
import { useTheme } from '@devfamily/admiral'
const { themeName , setTheme } = useTheme ( )
Um gancho que permite obter o estado obtido chamando AuthProvider.getIdentity()
import { useGetIdentty } from '@devfamily/admiral'
const { identity , loading , loaded , error } = useGetIdentty ( )
Os ícones usados no Admiral são do React Icons.
ThemeProvider usa o componente @consta/uikit Theme nos bastidores.
Você pode passar suas predefinições para o componente Admin
com a propriedade 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 >
)
}
Crie um diretório para predefinições. Dentro, crie pastas para cada modificador - o mesmo que no componente Tema.
Crie arquivos CSS. Nas pastas com os modificadores coloque os arquivos CSS que serão responsáveis por esses modificadores.
Você obterá algo semelhante:
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
Configure as variáveis em arquivos CSS.
Crie arquivos predefinidos (themeLight, themeDark).
Importe os arquivos CSS que você irá usar.
Crie um objeto predefinido. Especifique quais valores (ou seja, arquivos CSS) para quais modificadores usar na predefinição. Você obterá algo semelhante:
// 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' ,
}
Passe suas predefinições para o componente Admin
como no exemplo acima.
❗ Nota : plugins postcss são usados para transformação de cores no exemplo de predefinições de almirante. Se você deseja reproduzir, configure o postcss e o plugin postcss-color-mod-function.
Caso queira participar do desenvolvimento do Admiral, faça um Fork do repositório, faça as alterações desejadas e envie um pull request. Teremos o maior prazer em considerar suas sugestões!
Esta biblioteca é distribuída sob a licença do MIT.
Se você tiver alguma dúvida, entre em contato conosco: [email protected] Ficaremos sempre felizes em receber seus comentários!