29 Dicas de Plone 6 e Volto
Rodrigo Carvalho Benevides edited this page 3 weeks ago

Dicas para Uso de Plone 6/Volto

Algumas anotações enquanto estudava Plone 6 e Volto. Não pretende ser 100% completa, mas indicar onde conseguir mais ajuda sobre alguns tópicos.

A documentação aqui pode estar desatualizada em virtude da grande velocidade de desenvolvimento do Plone/Volto!

Projeto

A instalação do Plone cria um projeto "monorepo", contendo backend, frontend e devops.

Vários comandos make podem ser disparados da raiz do projeto ou de dentro do diretório correspondente. Por exemplo, para iniciar o backend:

# da raiz
~/projeto$ make backend-start
# do diretório backend
~/projeto/backend$ make start

Addons

A filosofia do desenvolvimento Plone é que todo o desenvolvimento deve feito dentro de addons.

O monorepo é criado seguindo esta filosofia, conforme a tabela abaixo:

/backend Configuração para subir o backend: porta, dependências, addons externos, etc
/backend/src Addons internos ao repositório
/backend/src/<nome-projeto> Addon principal, criado na instalação
/frontend Configuração para subir o frontend: dependências, addons externos, etc
/frontend/packages Addons internos ao repositório
/frontend/packages/volto-<nome-projeto> Addon principal, criado na instalação

Addons de backend normalmente (via de regra?) são instalados na interface web do site para fazer seus efeitos.

Uma dúvida minha é se isto é estritamente necessário ou apenas recomendado

Criando um novo projeto

pipx run cookieplone project
make install

Docs - Install Plone with cookieplone Training - Plone Deployment

Backend

O backend é o verdadeiro plone. Escrito em python, tem como base o conjunto de bibliotecas zope.

A documentação é sofrida e espalhada entre os sites do plone e as várias bibliotecas zope. Be afraid.

ZCML

Boa parte da configuração do backend é através de arquivos XML com extensão zcml.

O arquivo configure.zcml do diretório base de cada addon é lido automaticamente. Outros arquivos .zcml do addon deve ser incluídos a partir deste, usando a diretiva <include>.

Algumas diretivas usadas:

<include> Indica outro arquivo zcml a ser lido
<genericsetup:registerProfile> Define um conjunto de zcml que vai ser executado quando o addon for instalado ou desinstalado
<configlet> Cria um item de painel de controle.
<browser:page> Define uma "página". Até o momento, só sei que se usa para indicar o conteúdo de um item de painel de controle criado com <configlet>
<records> Cria dados no registry do Plone. Por exemplo, dados referentes a um item customizado de painel de controle.
<plone:service> Define um endpoint de api

Permissões

Em algumas das diretivas, é necessário especificar a permissão que o item sendo definido terá. As permissões mais comuns são:

Permissão Descrição
zope2.View Visualizar conteúdo. Não precisa estar logado no site. Comum em chamadas de API.
cmf.ManagePortal Gerenciar portal. Comum em itens de painel de controle.
cmf.ModifyPortalContent Gerenciar conteúdo. Permite criar e alterar páginas, etc.

Documentação na versão 5 do plone

Arquivos De Interesse

instance.yaml Use para gerenciar addons
mx.ini Use para incluir repositórios git externos ao monorepo na estrutura de diretórios

Receitas

Apontando para repositório externo

Ao desenvolver um addon reutilizável, o próprio costuma ter um repositório git separado. Para isto, usa-se o mxdev.

Passos:

  1. Configure o arquivo backend/requirements.txt, colocando o nome do add-on:

    interlegis.barra-acessibilidade-backend

  2. Configure o arquivo backend/instance.yaml:

    default_context:
        zcml_package_includes: project_title, interlegis.barra-acessibilidade-backend
    
  3. Configure o arquivo backend/mx.ini:

    [interlegis.barra-acessibilidade-backend]
    url = https://github.com/collective/example.contenttype.git
    pushurl = git@github.com:collective/example.contenttype.git
    extras = test
    branch = feature-7
    ´´´
    
    
  4. make backend-build na raiz do projeto para baixar o conteúdo do git.

docs, install an add-on from source

Instalar Addon

  1. Adicionar uma linha em backend/pyproject.toml para o addon, no item dependencies.

  2. Acrescente <include package="plonegovbr.socialmedia" /> no arquivo dependencies.zcml (fica dentro do seu addon padrão, no diretório src)

  3. make backend-build (no diretório raiz)

  4. Para adicionar o addon automaticamente, sem precisar refazer a base de dados, acrescente a seguinte linha no arquivo metadata.xml, dentro de profiles:

<dependency>profile-plonegovbr.socialmedia:default</dependency>

Note o profile- e :default. São obrigatórios.

Na documentação, ao invés do passo2, recomenda-se acrescentar o addon em backend/instance.yaml, no item zcml_package_includes. Mas isto mexe na base do projeto e o recomendável é incluir o addon no seu addon padrão.

Documentação

Criando item de painel de controle

Frequentemente é necessário também criar um endpoint para acessar o que foi configurado no painel de controle.

Há duas formas de definir algo no painel de controle:

  1. Definir interface detalhando os dados do painel de controle

    Não consegui achar um projeto com exemplo desta forma, mas é a forma que está explicada na documentação e nos treinamentos.

    Checklist típica (os arquivos não precisam ser exatamente esses, é só uma sugestão):

    • Criar um schema no arquivo interfaces.py, detalhando os campos desejados.
    • Incluir uma tag <configlet> nos profiles de instalação e desinstalação do item de painel de controle, arquivo controlpanel.xml. O atributo appId deve coincidir nos dois arquivos.
    • Criar um registro no Registry para a configuração, nos profiles de instalação e desinstalação. Arquivo registry.xml ou registry/main.xml. Usa-se a tag <records>.
    • Criar uma página pra responder o item, arquivo controlpanel/configure.zcml (tag browser:page) e controlpanel/controlpanel.py.
    • Criar um adapter pro Volto conseguir ver o item. Crie a tag <adapter>, em geral no arquivo restapi/configure.zcml.

    Documentação, Control Panels Training "Mastering Plone", add custom control panel Documentação dos tipos

  2. Definir interface apenas com uma string, de forma que os dados sejam guardados como json. Neste caso, define-se um widget no frontend para editar este json. Esta forma é mais comum nos addons do "Awesome Volto".

    Checklist típica (os arquivos não precisam ser exatamente esses, é só uma sugestão):

    • Criar um schema no arquivo interfaces.py. Neste caso, o schema só contém um item, so tipo SourceText.
    • Incluir uma tag <configlet> nos profiles de instalação e desinstalação do item de painel de controle, arquivo controlpanel.xml. O atributo appId deve coincidir nos dois arquivos.
    • Criar um registro no Registry para a configuração, nos profiles de instalação e desinstalação. Arquivo registry.xml ou registry/main.xml. Usa-se a tag <records>.
    • Criar uma página pra responder o item, arquivo controlpanel/configure.zcml (tag browser:page) e controlpanel/controlpanel.py.
    • Criar um adapter pro Volto conseguir ver o item. Crie a tag <adapter>, em geral no arquivo restapi/configure.zcml.

    Projetos de exemplo:

Mastering Plone 6 Training

Docs, Control Panels (bem limitado)

Troubleshooting
  • Item aparece no plone clássico e não aparece no Volto.

    O Volto exige os atributos action_id e appId da tag <configlet>. Além disso, não se esqueça do <adapter>.

Criando um endpoint para ser usado no frontend

Passos, grosso modo. Veja os exemplos para ter uma ideia melhor.

  1. Se já não existir, crie um diretório restapi dentro da raiz do backend. O nome não importa, mas restapi segue o padrão dos projetos que vi.

  2. Use <include> no configure.zcml da raiz para incluir o diretório recém-criado.

  3. Crie um arquivo configure.zcml dentro do diretório. Use a diretiva <plone:service> para criar o endpoint.

  4. Crie um arquivo python, exemplo get.py, dentro do diretório. Lá deve ser implementada uma classe para devolver os dados desejados.

  5. No caso de dados guardados em como string e que se deseja servir como json, pode ser necessário um serializer/deserializer. Ainda não sei como funcionam....

Projetos de exemplo:

Behaviors para configuração do site

"Behaviors" são schemas que pode ser atachados em tipos de conteúdo, acrescentando campos a eles. São excelentes para acrescentar configuração ao tipo de conteúdo Plone Site, que representa o site como um todo. Desta forma, não é necessário mexer com itens de painel de controle.

Passo-a-passo para incluir configuração no Plone Site:

  1. Crie o schema com a configuração a ser incluída. É comum criar um diretório behaviors no seu addon padrão.
# tema.py
from plone.autoform.interfaces import IFormFieldProvider
from plone.supermodel import model
from zope.interface import provider
from zope import schema
from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm

THEMES = SimpleVocabulary([
    SimpleTerm(value="modern", title="Modern"),
    SimpleTerm(value="solarized", title="Solarized"),
    SimpleTerm(value="darcula", title="Darcula"),
])

@provider(IFormFieldProvider)
class IThemeSettings(model.Schema):

    theme = schema.Choice(
        title="Tema do portal",
        vocabulary=THEMES,
        required=True,
        description="Tema do Portal",
        default="modern"
    )
  1. Crie um arquivo configure.zcml para registrar o seu behavior:
<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:browser="http://namespaces.zope.org/browser"
    xmlns:plone="http://namespaces.plone.org/plone"
    xmlns:zcml="http://namespaces.zope.org/zcml"
    i18n_domain="kitconcept.intranet"
    >
  <!-- este include é necessário para "habilitar" a funcionalidade de behaviors  -->
  <include
      package="plone.behavior"
      file="meta.zcml"
      />

  <plone:behavior
      name="portalmodelo.tema"
      title="Tema do Portal"
      description="Escolhe o tema do portal"
      provides=".tema.IThemeSettings"
      />

</configure>
  • em provides, coloque o nome do arquivo python ("tema" neste caso) e do schema (IThemeSettings)
  • em name, coloque um identificador para o behavior. Será usado no passo de atachar o behavior.
  1. Acrescente o diretório behaviors no configure.zcml da raiz do seu addon padrão:
<include package=".behaviours" />

Não é óbvio, mas o ponto de entrada do diretório "behaviors" é o arquivo behaviors/configure.zcml

  1. Atache o behavior no tipo de conteúdo. Para isto, crie um arquivo em profiles/default/types/Plone_Site.xml

O nome do arquivo é uma pegadinha. Tem de usar "_" no lugar de " ", se o tipo de conteúdo tiver espaços.

Use o name do behavior na tag element

<?xml version="1.0"?>
<!-- aqui dentro do XML, deve ser usado o nome do tipo de conteúdo com " ", não com "_" -->
<object name="Plone Site" meta_type="Dexterity FTI">
  <property name="behaviors" purge="false">
    <element value="portalmodelo.tema" />
  </property>
</object>

Como tudo que mexe dentro de profiles, é necessário ou recriar o site (DELETE_EXISTING=1 make backend-create-site) ou fazer um passo de atualização de dados (migration)

Mais coisas são possíveis na definição do schema (sub-títulos, usar widgets customizados, etc). Veja o código do volto-light-theme para ideias.

Documentação

Frontend (Volto)

O frontend é chamado de Volto. Escrito em react/javascript, é feito para substituir o antigo frontend do plone (feito em python, direto no backend).

Arquivos De Interesse

package.json Use para gerenciar addons
volto.config.js Também usado para gerenciar addons
index.ts ou index.js Ponto para aplicar configuração (applyConfig)

Receitas

Apontando para repositório externo

Ao desenvolver um addon reutilizável, o próprio costuma ter um repositório git separado. Para isto, usa-se o mrs developer.

Passos:

  1. Configure o arquivo frontend/package.json:

    {
       "name": "my-volto-project",
       "addons": [
         "name-of-add-on"
       ]
     }
    

    ``

  2. Configure o arquivo frontend/mrs.developer.json:

    {
      ... outros ...,
    
      "meu-addon": {
    	"output": "./packages/barra-acessibilidade",
    	"package": "<nome do package, exemplo '@interlegis/barra-acessibilidade'",
    	"url": "git@github.com:interlegis/barra-acessibilidade.git",
    	"https": "https://github.com/interlegis/barra-acessibilidade.git",
    	"tag": "<versão, exemplo '1.0'>"
      }
    }
    ´´´
    
    
  3. make install no diretório frontend.

Docs, Install an add-on in development mode in Volto 18

Instalar Addon

  1. Acrescente o addon em frontend/packages/<seu addon base>/package.json.

    "addons": [
      "@kitconcept/volto-light-theme"
    ],
    "dependencies": {
       ""@kitconcept/volto-light-theme": "7.0.0-alpha.25"
     },
    
  2. Se for um tema, como o volto-light-theme, faça-o ser o tema default, em frontend/volto.config.js:

    const theme = '@kitconcept/volto-light-theme';
    
  3. No diretório do frontend, use make install.

Documentação"

Na documentação, tá um pouco diferente, mas coloquei aqui a forma como aprendemos no treinamento.

Utilizando uma API definida no backend

O Volto utiliza react-redux para acessar o backend.

Passos (usando o projeto volto-banner como exemplos:

  1. Crie um novo reducer.

  2. Acrescente o novo reducer na configuração do addon.

  3. Crie uma nova action.

  4. Use a action no seu addon (com useEffect).

Colocando um componente em todas as páginas

Use a opção appExtras ao configurar o add-on. Veja no exemplo do addon volto-banner abaixo.

O componente é incluído no final da página, por default (acho). Se quiser posicionar em outro lugar, use react-portal, como no exemplo.

Docs, appextras

Exemplo: addon volto-banner:

Colocando um componente em todas as páginas, com slots

Mais simples, especialmente se estiver usando volto-light-theme:

No seu ponto de instalação de configuração (´index.ts´, por exemplo), use:

config.registerSlotComponent({
  name: 'BarraAcessibilidade',
  slot: 'aboveHeader',
  component: BarraAcessibilidade,
});

Documentação base Documentação do volto light theme

Definindo interface de painel de controle no frontend

A criação de painel de controle normalmente é através de interface no backend e o Volto monta os controles necessários para a edição dos itens desta interface.

Uma outra opção é definir no backend a interface como uma string (contendo um json) e definir no frontend um widget para editar este json. Esta opção possibilita layouts mais complexos.

Exemplos:

CSS customizado

O volto tem dois arquivos que são pontos para inclusão de CSS customizado, localizados dentro do seu pacote, em src/theme:

Arquivo Nota
_main.scss CSS geral e importação de outros arquivos
_variables.scss definição de variáveis CSS
Importação de arquivos

Use: @import '_arquivo'

Este comando procura por _arquivo.scss (SASS) ou _arquivo.css. O underscore na frente é uma convenção, para dizer que o arquivo é só para import.

Variáveis de Volto Light Theme

Além dos behaviors de tema explicados mais abaixo, pode-se configurar as cores do volto-light-theme definindo algumas variáveis de CSS. Listo algumas abaixo:

Variável Nota
--header-background, --header-foreground Cores do cabeçalho
--footer-background, --footer-foreground Cores do rodapé
--accent-color, --accent-foreground-color Cor de destaque, usado para definir variáveis para o menu de hamburguer, breadcrumbs e search

E várias outras. Use o developer tools para descobrir mais. Não tem documentação.

Cores dos blocos (isto é do corpo da página)

Por default, é definido hard-coded e para serem alteradas, deve-se usar a configuração em index.ts:

  config.blocks.themes = [
    {
      style: {
        '--theme-color': 'var(--body-background-color)', // Block Wrapper
        '--theme-high-contrast-color': '#ecebeb', // Cards in Grid block
        '--theme-foreground-color': 'var(--body-foreground-color)',
        '--theme-low-contrast-foreground-color': '#555555',
      },
      name: 'default',
      label: 'Default',
    },
    {
      style: {
        '--theme-color': '#ecebeb',
        '--theme-high-contrast-color': '#fff',
        '--theme-foreground-color': '#000',
        '--theme-low-contrast-foreground-color': '#555555',
      },
      name: 'grey',
      label: 'Grey',
    },
  ];

Se forem usadas variáveis de CSS nesta parte, as variáveis podem ser definidas nos arquivos CSS descritos acima, mantendo o código mais organizado.

Retirando partes da tela no volto-light-theme

O volto-light-theme facilita a customização do site, retirando partes da tela, como o "colophon" (onde tem a licença, etc). Para isto, use:

config.unRegisterSlotComponent('postFooter', 'Colophon', 0);

Para ver o que pode ser retirado, olhe o arquivo slots.ts no código-fonte.

Insights

Itens de Painel de Controle

Os itens de painel de controle que aparecem no Volto não são simplesmente os itens definidos no backend. Uma parte foi redesenvolvida em React e está hard-coded e outra parte vem do backend.

Itens Oriundos do Backend

Estes itens estão definidos em controlpanel.xml do produto base CMFPlone. Note que nem todos os itens listados aqui são servidos pela API. Por exemplo, os painéis marcados com permissão Manage Portal não estavam sendo retornados nos meus testes. O endereço da API é ++api++/@controlpanels.

Estes itens também são filtrados no Volto, após o fetch. Para fazer uma filtragem customizada, coloque a função de filtragem na configuração do Volto. Exemplo abaixo:

const filterControlPanels = (controlpanels = []) => {
  const HIDDEN_CONTROL_PANELS = ['markup', 'content-rules', 'language', 'security'];

  return controlpanels.filter(
    (controlpanel) =>
      !HIDDEN_CONTROL_PANELS.includes(controlpanel['@id'].split('/').pop()),
  );
};


// Na instalação do seu addon (index.ts, por exemplo)
function applyConfig(config: ConfigType) {
  config.settings.filterControlPanels = filterControlPanels;
}

Por default, o Volto filtra os itens "markup" e "content-rules"

Itens de Painel de Controle que normalmente aparecem no Volto e vem do backend:

Nome Url Id Permission
Buscar search SearchSettings Plone Site Setup: Search
Data e Hora date-and-time DateAndTime Plone Site Setup: Site
E-Mail mail MailHost Plone Site Setup: Mail
Idioma language LanguageSettings Plone Site Setup: Language
Navegação navigation NavigationSettings Plone Site Setup: Navigation
Site site PloneReconfig Plone Site Setup: Site
Volto Settings volto-settings VoltoSettings Manage Portal
Editar editing EditingSettings Plone Site Setup: Editing
Manipulação de Imagem imaging ImagingSettings Plone Site Setup: Imaging
Tipos de Conteúdo dexterity-types dexterity-types Manage Portal
Configurações de Usuários e Grupos usergroup UsersGroupsSettings Plone Site Setup: Users And Groups
Segurança security SecuritySettings Plone Site Setup: Security
Mudando permissões de itens

Uma outra forma de restringir o acesso aos itens é mudar sua permissão no backend. Para isto, crie um arquivo ´controlpanel.xml´ no seu profile, repetindo o item de painel de controle, mas mudando a permissão:

<?xml version="1.0" encoding="utf-8"?>
<object xmlns:i18n="http://xml.zope.org/namespaces/i18n" name="portal_controlpanel">

  <configlet action_id="LanguageSettings"
            appId="Plone"
            category="plone-general"
            condition_expr=""
            icon_expr="string:flag"
            title="Language"
            url_expr="string:${portal_url}/@@language-controlpanel"
            visible="True"
            i18n:attributes="title"
  >
    <!-- Era "Plone Site Setup: Language" no original -->
    <permission>Manage portal</permission>
  </configlet>
</object>

Como toda alteração de profile, isto requer reiniciar o banco de dados ou criar uma passo de atualização de dados.

Itens hard-coded

Uma parte dos itens é feita diretamente em React. Alguns são itens que existem no Plone Clássico e outras não.

Nome Id
Complementos addons
Regras de conteúdo rules
Gerenciamento de URL aliases
Relacionamentos relations
Moderar comentários moderate-comments
Usuários users
Participação de Usuários em Grupos usergroupmembership
Grupos groups
Banco de dados database
Desfazer undo

Para filtrar estes itens, é necessário sobrepor ("shadowing") o código original do Volto. Para isto:

  1. Crie um arquivo Controlpanels.jsx´ no diretório ´src/customizations/volto/components/manage/Controlpanels.
  2. Copie o código original do volto lá. Você pode pegar o conteúdo aqui.
  3. Procure por um item no formato abaixo e comente:
/* Filtrando o item de painel de controle "database" (Banco de Dados)
      {
        '@id': '/database',
        group: intl.formatMessage(messages.general),
        title: intl.formatMessage(messages.database),
      }
*/

Configurações de Tema do Volto Light Theme

As novas versões do Volto Light Theme permitem a configuração de cor, logo do site, etc.

Por algum motivo, esta configuração não é default! É necessário acrescentar os behaviors no tipo Plone Site (que representa o site inteiro).

Para isto, crie o arquivo descrito aqui.

É necessário recriar o site para que tenha efeito.