
Estruturação
Para facilitar o entendimento, podemos dividir nosso frontend em 3 partes:
Primeira parte (azul)
Aqui é onde nos comunicamos com o backend, fazendo requisições e obtendo respostas.
-
SDK: A responsabilidade da SDK é fazer a comunicação com as APIs REST da aplicação, é como se nossas requisições ao backend ficassem mockados no SDK e ele faz todo o trabalho para nós. Nessa camada, está automatizada a padronização dos nomes das variáveis (de
snake_case
paracamelCase
). Além disso essa parte cuida da autenticação e normalização dos erros. -
Socket.io: O
Socket.io
é responsável por fazer a comunicação em tempo real com o backend, é como se fizemos uma requisição a cada N segundos, mas nesse caso só precisamos “abrir” uma única vez essa ponte de acesso.
Segunda parte (verde)
- Store (VUEX): O store é responsável por armazenar os dados da aplicação. Praticamente toda a lógica de consulta e alteração nos dados se concentra nele. O Store é uma das partes mais importantes para o frontend. Por esse motivo, nele estão concentrados a maior parte dos testes unitários. Nele que testamos as regras de negócio quando necessário.
Terceira parte (amarelo)
-
Módulos: São diretórios/pastas onde ficam concentrados todos os arquivos responsáveis por uma parte da aplicação, por exemplo, se você quer criar um Dashboard, tudo relacionado a ele ficaria no módulo dele, como as rotas, componentes, store e por aí vai.
-
Modulo/Views: As views são rotas do sistema, envolvem todos os componentes para montar uma página referente à rota. Elas tem acesso ao store, para poder repassar para seus componentes as informações necessárias, são chamadas de componentes inteligentes por isso.
-
Modulo/Components/Form.vue: O Form é uma dialog que contém sua lógica dentro dele. Ao contrário dos outros componentes da pasta, formulários tem acesso ao store, também é um componente inteligente por conta disso. Como o padrão é desenvolver formulários em dialog, se expõe os métodos
open
eclose
para quem está utilizando eles. -
Modulo/Components: São componentes específicos do módulo. Geralmente são criados com um dos seguintes objetivos: reutilização de código, melhor separação de responsabilidades ou separação da visualização e lógica de negócio, esses são os componentes burros, estes componentes não tem acesso ao store (com exceção de dialogs), eles só recebem props.
-
Web-Components: São os componentes da Aplicação. Estes componentes podem ter acesso ao store. São específicos da aplicação e contém lógica específica da aplicação.
-
It-Components: Os IT-Components é a nossa biblioteca de componentes. Nela são disponibilizados diversos componentes para que as telas sejam construídas. Ao alterar ou criar componentes
it-
, é importante manter a documentação atualizada e cuida para não quebrar compatibilidade com os outros sistemas.
Exemplos
Para tentar facilitar ainda mais o entendimento, aqui está um exemplo de uma estrutura que temos hoje no nosso produto (nossos módulos sofrem uma constante mudança de acordo com novas regras de negócio, então, há grande possibilidade de ele não estar mais 100% da maneira como está mostrada no exemplo).
O nosso módulo Cluster, hoje em dia, tem apenas uma página, uma rota /cluster.
Ele é estruturado da seguinte maneira:
SDK
O SDK fica dentro das pastas pkgs/@itflex
, e as requisições referentes aos módulos dentro de modules

Módulo
Todos os nossos módulos, ficam dentro da pasta src/pages
.
O nosso módulo do Cluster é um dos únicos que não tem outras pastas dentro dele separando funcionalidades, pois ele tem apenas uma rota. O mais comum é ter outras pastas com estruturas de módulos. Sabemos que terão essas pastas separadas quando temos mais de uma rota, separamos em outros módulos dentro de um contexto.

Como criar um módulo novo
Adicionar estrutura de pasta do módulo
O primeiro passo é adicionar os seguintes arquivos que fazem parte de um módulo:
server/frontend/admin/src/pages/[módulo]/
server/frontend/admin/src/pages/[módulo]/index.js`
server/frontend/admin/src/pages/[módulo]/store.js`
server/frontend/admin/src/pages/[módulo]/[entidade]/`
server/frontend/admin/src/pages/[módulo]/[entidade]/store.js`
server/frontend/admin/src/pages/[módulo]/[entidade]/schemas.js`
server/frontend/admin/src/pages/[módulo]/[entidade]/views/`
server/frontend/admin/src/pages/[módulo]/[entidade]/components/`
Base do store
No store do módulo, é necessário adicionar o básico, esse seria o store “global” do módulo, onde vc exporta todas as outras stores utilizadas para facilitar que elas sejam usadas em outros módulos se necessário, e até mesmo dentro do próprio.
// server/frontend/admin/src/pages/[módulo]/store.js
import entidade from "./entidade/store";
export default {
namespaced: true,
modules: {
entidade,
},
};
Criar Módulo no index.js
O Módulo em si é uma classe que é responsável por expor as opções do menu que irão ficar disponíveis, as rotas para as páginas e os escopos de permissão para que seja possível criar perfis.
Esse módulo é utilizado pelo ApplicationManager
e deve implementar
a seguinte lógica:
import DefaultLayout from "@/layouts/Default.vue";
import store from "./store";
import { MODULES, Module } from "@/module";
const EntityList = () =>
import(/* webpackChunkName: "entity" */ "./entity/view/UsersList");
const EntityDetails = () =>
import(/* webpackChunkName: "entity" */ "./entity/view/RolesList.vue");
export default class NewModule extends Module {
constructor({ product }) {
super({ product });
this.active = false;
}
get name() {
return MODULES.moduleName;
}
get routes() {
return [
{
path: "/module",
name: "module",
component: DefaultLayout,
children: [
{
path: "entity",
name: "module-entities",
component: EntityList,
meta: {
product: this.product,
title: "entity",
},
},
{
path: "entity/:id",
name: "module-entity-id",
component: EntityDetails,
meta: {
product: this.product,
title: "entity",
},
},
],
},
];
}
get store() {
return store;
}
makeMenuOptions() {
return [
{
title: "module", // Nome da opção do menu
icon: "some_icon", // Ícone para ser utilizado
weight: 50, // Peso para o menu, quanto menor mais em cima fica
group: "admin", // Subgrupo no menu
options: [
{
route: "module-enitty", // Rota que vai ser chamada
title: "entity", // Título do menu
scope: "moduleEntity", // Escopo necessário para a opção aparecer
options: [],
},
],
},
];
}
get scopes() {
return {
"module.entity": { description: "entity", module: this.name },
};
}
}
Os itens podem ser entendidos como:
-
scopes: Os escopos que existem nesse módulo. Sua descrição e módulo que faz parte.
-
routes: Rotas disponíveis para essse módulo. Elas serão adicionadas se esse módulo estiver ativo. Padrão utilizado é do
vue-router
-
makeMenuOptions: Método chamado para construir as opções do menu.
Registrar Index
No arquivo de gerenciador de aplicação, é necessário registrar o módulo criado. Ele deve ser registrado passando o produto que ele faz parte. Um módulo pode estar em mais de um produto se fizer sentido.
// server/frontend/admin/src/application.js
export const itflexApplication = new ApplicationManager({
modules: [
// Core - Sempre carregam
new AlertsModule({ product: PRODUCTS.core }),
new AuditModule({ product: PRODUCTS.core }),
new GraphsModule({ product: PRODUCTS.core }),
new LoginModule({ product: PRODUCTS.core }),
new WizardModule({ product: PRODUCTS.core }),
// Administração
new DashboardModule({ product: PRODUCTS.admin }),
new DiagnosticsModule({ product: PRODUCTS.admin }),
new ClusterModule({ product: PRODUCTS.admin }),
new SystemModule({ product: PRODUCTS.admin }),
new NewModule({ product: PRODUCTS.admin }),
],
});