Arquitetura

Visão geral de alto nível

O EJ adota uma arquitetura monolítica com o servidor principal que controla a lógica de negócios e alguns serviços adicionais que complementam o aplicativo. A maneira recomendada para implantar o EJ é executar cada serviço em um contêiner separado a fim de proporcionar um bom nível de isolamento. Os serviços acima referidos são organizados em uma arquitetura simples de 3-camadas descrita abaixo:

../_images/ej_arch.svg
Nginx
O tráfego Web não deve ser tratado diretamente pelo serviço de aplicação. Gunicorn não é eficiente para servir arquivos estáticos, e um proxy reverso adicional também pode ser usado para aplicar políticas de segurança mais rigorosas cache mais eficiente. O EJ adota o Nginx. Ele serve arquivos estáticos e redireciona rotas dinâmicas para o serviço de aplicação descrito abaixo. O container Nginx deve compartilhar alguns volumes com o aplicativo Django para encontrar arquivos estáticos.
Aplicativo Django
O EJ é escrito principalmente em Python e usa o framework web Django. O serviço principal de aplicação é responsável por todas as rotas dinâmicas, que são geradas pelo Django usando a linguagem de template Jinja2. O aplicativo Django deve ser executado com um serviço compatível com WSGI como o Gunicorn. Esta é a abordagem padrão adotada no contêiner de aplicativo. A tarefa padrão usa um número de trabalhadores igual ao número de núcleos de CPU, que é geralmente a configuração recomendada.
Base de dados SQL
O EJ não usa nenhuma funcionalidade específica de banco de dados ou comandos SQL brutos. Isso significa que ele pode ser executado em qualquer banco de dados suportado pelo Django, como Postgres SQL, MariaDB, Sqlite3, etc. Recomendamos Postgres (v10.0), que é usado na instalação padrão. A conexão de banco de dados é controlada por a variável de ambiente DJANGO_DB_URL no contêiner principal do aplicativo.

Integração com o Rocket.Chat

Instâncias que implantam a integração opcional do Rocket.Chat devem considerar os serviços adicionais.

Rocket.Chat
Rocket.Chat é um aplicativo Node.js baseado no framework Meteor que serve arquivos estáticos e as rotas dinâmicas. EJ é compatível com o contêiner Rocket. chat oficial no Docker Hub, que é o recomendado método de implantação.
Mongo DB
A camada de persistência de Rocket.Chat utiliza o Mongo. O container Rocket.Chat é compatível com a imagem oficial do Docker Hub e requer configuração mínima.

Frontend

O Frontend do EJ é implementado usando a linguagem de templates Jinja2 e usa o conceito de melhora progressiva para incluir estilos através de CSS personalizado e comportamento com JavaScript. Os pontos a seguir apresentam uma breve visão geral das tecnologias usadas em cada uma dessas camadas:

CSS
CSS é implementado com Sass usando uma arquitetura inspirada em ITCSS (Inverse Triangle CSS). O módulo CSS é implementado usando o framework para CSS atómico Mendeleev.css e pode ser facilmente personalizado usando temas. Os arquivos CSS são estatisticamente compilados e servidos pelo Nginx. A compilação requer libsass, que é declarada nas dependências Python do aplicativo.
Javascript / Typescript
O EJ não adota nenhum framework JavaScript tradicional, mas depende de mecanismos de melhora progressiva para adicionar funcionalidades opcionais. O EJ usa Unpoly em conjunto com jQuery para fornecer a funcionalidade do núcleo. Componentes específicos do EJ são criados usando TypeScript e melhoram as tags anotadas com o atributo "is-component" com comportamentos e funcionalidades extras. A compilação de TypeScript requer o Gerenciador de Pacotes do Node (NPM) e Parcel.

Aplicação Django

Django divide um sistema web em módulos chamados "apps" que implementam modelos de banco de dados reusáveis, rotas e funcionalidades. Esta seção descreve todos os "apps" implementados em EJ.

Projeto EJ

O módulo ej não é propriamente um aplicativo, mas sim um pacote Python regular usado para coordenar apps definindo configurações, funcionalidades comuns e carregando arquivos estáticos como Javascript, CSS, imagens, temas etc. Segue uma visão geral dos principais sub-pacotes e módulos:

ej.all
Namespace útil para ser usado em uma seção interativa em from ej.all import *. Importa modelos e managers de todos os apps ej e exemplos no namespace global.
ej.components
Da mesma forma que ej.roles, este módulo define renderizadores para reutilização de elementos de UI. A diferença entre os dois módulos é que os componentes podem ter uma estrutura mais complicada e pode não estar diretamente associada a tipo de dados Python conhecidos.
ej.contrib
Local para incluir migrações ad-hoc. A maioria dos usuários e desenvolvedores nunca deve modificar isto.
ej.fixes
Módulos que realizam "mokey patch" para consertar problemas com EJ ou qualquer uma de suas dependências.
ej.forms
Classes base de formulário que são usadas em outros aplicativos EJ. Formulários são derivados de django.forms.
ej.jinja2
O EJ usa o Jinja2 como linguagem de template padrão. Este módulo configura o ambiente Jinja2 e define funções e filtros globais.
ej.roles
Funções que definem papéis Hyperpython. Os papéis são mapeamentos de (tipo, nome) -> HTML que definem como um determinado objeto deve ser renderizado em um determinado contexto ou papel. Este módulo define muitos elementos de interface reutilizáveis como funções Python.
ej.routes
Defina algumas funções de "view" global (como a página inicial) que não tem funcionalidade vinculada a qualquer app.
ej.services
Funções do Helper para inicializar conexões com serviços externos, como o banco de dados SQL do Postgres e redimensiona (se habilitado).
ej.settings
Módulo de configurações do Django. Define a configuração usando o framework de configuração do Django Boogie, no qual a configuração é definida em classes reutilizáveis em vez de um módulo Python.
ej/templates/jinja2
Contém modelos disponíveis globalmente. O modelo global base.jinja2 define a estrutura HTML da página base (barras de navegação, meta informações, etc) que é compartilhada entre a maioria das páginas do site.
ej.testing
Ferramentas de ajuda usadas em testes.
ej.tests
Testes globais. A maioria dos testes são implementados em pastas de teste específicas para cada app.
ej.urls
Mapeamento de URL para o projeto. A maioria das URLs está incluída no módulo routes.py do respectivo aplicativo.
ej.utils
Módulo de funções de úteis.
ej.wsgi
Django wrapper para a interface WSGI.

Aplicações

A listagem abaixo descreve todos os aplicativos implementados dentro da base de código do EJ.

ej_conversations
../_images/ej_conversations.svg

Este é o aplicativo principal e define modelos para conversas, comentários, e votos. O aplicativo ej_applications implementa a interface de usuário para criar, configurar e interagir com conversas.

ej_users
../_images/ej_users.svg

Este aplicativo define o modelo de usuário principal para EJ e todas as rotas relacionadas a autenticação e gerenciamento de conta (por exemplo, redefinir senhas, cancelar conta, etc.). O EJ pode ser usado com os usuários regulares do Django, embora isso não seja encorajado.

ej_profiles
../_images/ej_profiles.svg

Implementa interface de gerenciamento de perfil e define um modelo que armazena informações do perfil. Este app pode ser facilmente modificado para incluir campos de perfil extra ou para remover campos indesejados para alguma instalação específica.

ej_clusters
../_images/ej_clusters.svg

Implementa as rotinas matemáticas para classificar os usuários em grupos de opinião. O módulo ej_clusters.math implementa nosso algoritmo de K-means modificado que leva em conta "estereótipos de opinião" e também fornece interfaces para gerenciar esses estereótipos e os clusters resultantes.

ej_dataviz
../_images/ej_dataviz.svg

Implementa rotinas para visualizar dados sobre conversas. Gera relatórios estruturados e exporta dados para formatos compatíveis com planilhas. Este módulo também implementa técnicas de visualização como Word Cloud e Mapas de Pontos a partir das opiniões dos usuários.

ej_gamification
../_images/ej_gamification.svg

O aplicativo de gamificação implementa o sistema de pontos e medalhas no EJ. A maioria das interações na plataforma são recompensadas com pontos. Usuários que conseguem níveis pré-definidos de participação recebem medalhas que reconhecem diferentes tipos de interações, como a votação de comentários, a criação de conversas, etc.

ej_boards
../_images/ej_boards.svg

O aplicativo de quadros permite que usuários regulares tenham seu próprio "quadro" ou "linha do tempo" de conversas. O feed de conversas padrão em "/conversations/" pode somente ser gerenciado por usuários com permissões especiais.

ej_experiments
Este app opcional é responsável por criar e salvar dados de teste no banco de dados. É útil para o desenvolvimento, mas não está habilitado em instalações de produção.

Apps de terceiros

boogie.apps.fragments
O aplicativo de fragmentos do Boogie implementa textos configuráveis ou fragmentos HTML salvos em banco. Isto permite um maior nível de configuração permitindo que os usuários administrativos personalizem partes da plataforma sem precisar alterar código.
rules
Django-rules implementa um mecanismo para definir regras de negócio registrando funções de predicado simples. Este pacote integra-se com os próprios mecanismos de permissão do Django. As regras de negócio relevantes para cada aplicativo EJ são implementadas no respectivo módulo "rules.py de cada app Django e podem ser substituídas por aplicativos ou módulos de terceiros.
Django taggit
Django-taggit é um aplicativo Django que implementa tags para modelos arbitrários. É utilizado para adicionar tags às conversas do EJ.
rest_framework
O Django-Rest-Framework (DRF) é um poderoso conjunto de ferramentas para desenvolver APIs REST Web. O EJ usa DRF através do módulo rest_api do Django-Boogie.
allauth, allauth.account, allauth.socialaccount
O projeto allauth implementa fluxos de trabalho de autenticação e autorização e integração com provedores OAuth de terceiros como Google, Twitter e Facebook.

Estrutura dos apps

O EJ usa Django Boogie adopta uma arquitetura que pode ser ligeiramente diferente de um aplicativo Django típico. Um objetivo importante da arquitetura é fazer funções e views menos repetitivas. Isto é realizado movendo funcionalidade para a própria estrutura do Boogie ou criando mecanismos para dividir a funcionalidade em módulos separados.

Um aplicativo EJ típico tem a seguinte estrutura:

<app>.admin
Classes e funções do Django admin.
<app>.api
Define os campos e rotas API para os modelos definidos pelo app. Normalmente, funcionalidade implementada neste módulo simplesmente complementa as declarações principais da API que são criadas usando o decorador @rest_api diretamente nos modelos.
<app>.apps
Mecanismo AppConfig do Django. Apps do EJ geralmente devem substituir o método ready() da configuração do aplicativo e importar os módulos api, roles e rules.
<app>.enums
Este módulo define qualquer tipo de enum que eventualmente seja usado por modelos. Enums geralmente são importados para o namespace do app. Por isso, eles não devem depender de modelos.
<app>.forms
Formulários Django definidos para o aplicativo. Formulários normalmente herdam do ej.forms em vez de usar django.forms diretamente.
<app>.math
Todas as funções matemáticas devem ser definidas neste módulo. As transformações matemáticas complexas devem ser implementadas como transformações de ScikitLearn ou pipelines.
<app>.managers
No Django, classes de modelo define lógica de linha e gerentes e consultas implementa a lógica da tabela. Todos os métodos que consultam, criam instâncias ou filtram consultas devem ser implementados no módulo "managers"
<app>.models
Tal como em aplicativos Django padrão, este módulo define os modelos para o aplicativo. Modelos devem evitar implementar a lógica de negócios dentro deles e idealmente deve restringir as ações de banco de dados, como consultas, validação, etc.
<app>.mommy_recipes
O EJ usa o Model Mommy para criar recursos aleatórios para testes. Este módulo deve definir uma classe que derive de ej.testing.EjRecipes e implementa fixtures para cada modelo definido no aplicativo. Isto é usado apenas em testes.
<app>.routes
Os aplicativos regulares do Django têm um views.py e arquivos urls.py. Django Boogies incentiva a unir ambos os arquivos em um único routes.py que define o modo de exibição funções e mapeia-los para rotas usando decoradores.
<app>.rules
As regras de negócios são implementadas como funções regulares dentro deste módulo. Isto ajuda a evitar o anti-padrão "fat-models" que é comum em projetos Django. O módulo de regras pode definir tanto permissões (que são funções de predicado centradas no usuário) e "valores" regulares, que podem retornar valores não-booleanos (por exemplo, o número de comentários que o usuário ainda tem em conversa).
<app>.roles

Papéis Hyperpython são funções simples que renderizam objetos em contextos determinados. Por exemplo, podemos registrar um papel de “cartão” na classe Conversation que processa a conversa de entrada como um cartão em uma visualização de lista. Funções de papel devem ser associadas com um tipo e um nome e devem retornar uma estrutura Html Hyperpython.

Nos casos em que o Jinja2 é mais conveniente do que o Hyperpython, o ej.roles.com_template pode ser usado para associar o papel com um modelo Jinja.

<app>.tests
Testes unitários do aplicativo.
<app>.validators
Implementa as funções de validação usadas em campos de modelo ou campos de formulário dentro do aplicativo.

Templates

Os templates residem dentro da pasta <app>/jinja2/. Utilizamos a melhor prática do Django de salvar modelos específicos do aplicativo dentro de jinja2/<app-name>/<template-name>.jinja2. Os nomes dos templates geralmente espelham os nomes das funções de visualização no arquivo routes.py. Por exemplo, uma view de edição para alguma conversa seria declarada como:

urlpatterns = Router(template='ej_conversations/{name}.jinja2')

@urlpatterns.route("/<model:conversation>/edit/")
def edit(request, conversation):
    ... # Implementation

Essa função de exibição é automaticamente associada com o ej_conversations/edit. jinja2 modelo, a menos que especificado de outra forma.

A maioria dos modelos herda de um modelo base em src/ej/templates/jinja2/base. jinja2. Este template importa elementos de navegação, como menus e barras de ferramentas.