Conn2Flow
Navegação das docs

SDD

req-043: Curadoria Manual no publisher-index, Novos Templates com Imagem, Variável de Widget no CRUD e Suporte Inline no Editor

Este documento especifica os requisitos para correções e melhorias nos módulos de widgets (publisher-index, publisher-highlights, menus e galleries) e integração do editor visual.

Este documento especifica os requisitos para correções e melhorias nos módulos de widgets (publisher-index, publisher-highlights, menus e galleries) e integração do editor visual.


1. Regra de Alimentação Manual no publisher-index

1.1 Problema

Ao definir a regra de alimentação como "Manual (curadoria por item)" (rule = "manual") no CRUD de publisher-index, o widget publicado e o pré-visualizador continuam realizando buscas dinâmicas automáticas de publicações em vez de exibir apenas os itens explicitamente selecionados na curadoria.

1.2 Solução no Backend (publisher-index.widget.php e AJAX)

  • Leitura da Curadoria: Nos pontos de renderização (page load e AJAX de paginação/busca em publisher_index_render_ajax), extrair rule e selected_items (array de IDs) do $schema de configurações do índice.

  • Lógica de Busca (publisher_index_widget_buscar_publicacoes):

    • Se rule === 'manual':

    • Se selected_items estiver vazio, retornar array vazio [] imediatamente.

    • Na query SQL, aplicar o filtro restritivo de ID: AND p.id IN ('ID1', 'ID2', ...) (usando banco_escape_field em cada ID).

    • Não aplicar ordenação ou limite na query SQL.

    • No PHP, mapear os registros retornados por page_id e reordenar a lista resultante para respeitar exatamente a ordem contida no array selected_items.

    • Caso exista um termo de busca (busca não vazio), filtrar os registros em PHP de forma case-insensitive comparando com o título (titulo) ou campos customizados do registro.

    • Aplicar a paginação (offset e limit) em PHP sobre a lista ordenada resultante usando array_slice().

  • Lógica de Contagem (publisher_index_widget_contar_publicacoes):

    • Se rule === 'manual':

    • Se selected_items estiver vazio, retornar 0.

    • Caso exista um termo de busca (busca), retornar a quantidade de itens em selected_items que casam com o termo (filtrando conforme a lógica de busca). Caso contrário, retornar o count($selected_items).


2. Novos Modelos (Templates) com Imagem Destaque

2.1 Requisitos

Criar 4 novos modelos visuais (2 em português, 2 em inglês) para o módulo publisher-index que contenham suporte a imagens de destaque, utilizando a variável de item @[[item#imagem]]@.

2.2 Modelos a Criar

  1. Grade com Imagem Destaque:

    • ID: publisher-index-grid-imagem

    • Nome (pt-br): Publicador Índice - Grade com Imagem Destaque

    • Nome (en): Publisher Index - Card Grid with Featured Image

    • Layout: Estrutura em cards estilo grid, exibindo a imagem destaque (@[[item#imagem]]@) no topo de cada card, seguida de título, data e resumo.

  2. Lista com Imagem Destaque:

    • ID: publisher-index-lista-imagem

    • Nome (pt-br): Publicador Índice - Lista com Imagem Destaque

    • Nome (en): Publisher Index - List with Featured Image

    • Layout: Estrutura horizontal de lista, exibindo uma imagem destaque pequena/média alinhada à esquerda, e o conteúdo (título, resumo, data) alinhado à direita.

2.3 Registro

  • Registrar os 4 novos templates nas seções templates correspondentes a pt-br e en do arquivo publisher-index.json, utilizando versão 1.0 e checksums vazios (deixados para recálculo do pipeline).


3. Variável de Widget no CRUD e Visualização Combinada

3.1 Módulos Afetados

  • publisher-index, publisher-highlights, menus e galleries.

3.2 HTML do CRUD (adicionar.html, editar.html, clonar.html em pt-br/en dos 4 módulos)

  • Na aba de código do widget (data-tab="hep-widget"), reorganizar a estrutura para conter:

    1. O bloco informativo existente (ui message info).

    2. Um novo campo visual para a Variável do Widget:

      • Label: Variável do Widget (ou Widget Variable)

      • Input: Campo de texto de leitura (readonly) com ID #hep-widget-val.

      • Botão: Botão de ação Fomantic UI à direita com ID btn-copy-widget-val, classe .teal, ícone copy e texto Copiar (ou Copy).

    3. Um cabeçalho visual para o Código HTML:

      • Label/Header: Código HTML (ou HTML Code)

      • O editor CodeMirror existente #hep-widget-code posicionado logo abaixo.

3.3 Javascript Administrativo (.js dos 4 módulos)

  • Na função updateWidgetCodeTab(), gerar a assinatura do widget correspondente em formato de variável, por exemplo: [[widgets#MODULO_ID->render({"grupo_slug": "REGISTRO_SLUG"})]]

  • Setar o valor gerado no input #hep-widget-val.

  • Adicionar o listener de clique no botão #btn-copy-widget-val para copiar o conteúdo do input para a área de transferência do usuário via navigator.clipboard.writeText() (com fallback para elemento temporário).


4. Suporte a Variáveis Inline no Editor Visual e Pré-visualizador

4.1 Pré-visualizador (html-editor-interface.js)

  • Na função widgetPreviewBootstrap(), no início de renderWidgets(), converter ocorrências de variáveis de widget inline ([[widgets#...]] ou @[[widgets#...]]@) em blocos de comentários equivalentes antes do TreeWalker de comentários rodar:

    var bodyHtml = document.body.innerHTML;
    var varRe = /@?\[\[widgets#(.+?)\]\]@?/gi;
    if (varRe.test(bodyHtml)) {
      document.body.innerHTML = bodyHtml.replace(varRe, '<!-- widgets#$1 < --><!-- widgets#$1 > -->');
    }

4.2 Editor Visual (html-editor.js)

  • Na função convertWidgetCommentsToWrappers(), realizar a mesma substituição de variáveis inline no HTML do body do editor antes de prosseguir com a varredura e conversão de nós de comentários:

    let bodyHtml = document.body.innerHTML;
    const varRe = /@?\[\[widgets#(.+?)\]\]@?/gi;
    if (varRe.test(bodyHtml)) {
      document.body.innerHTML = bodyHtml.replace(varRe, '<!-- widgets#$1 < --><!-- widgets#$1 > -->');
    }

5. Correção de Falha de Teste Unitário JS (Vitest)

5.1 Problema

Ao rodar a suíte de testes JS via Vitest (npm run test / vitest run), ocorrem falhas no arquivo tests/Unit/JS/publisher-index.widget.test.js devido a chamadas aos métodos .children() e .not() no objeto jQuery do contêiner de itens. O stub de testes simplificado de jQuery (jquery-stub.js) não possui essas funções implementadas, resultando no erro TypeError: $items.children is not a function.

5.2 Solução

  • No arquivo de stubs de testes jquery-stub.js, adicionar os métodos .children() e .not() na classe interna JQueryCollection para simular o comportamento básico do jQuery:

    • children(selector): Retorna uma nova JQueryCollection contendo os nós filhos directos dos elementos colecionados, opcionalmente filtrados por um seletor.

    • not(selector): Retorna uma nova JQueryCollection filtrando os elementos da coleção atual que não correspondem ao seletor informado.


6. Prefixagem Dinâmica de URL Raiz para Campos de Imagem

6.1 Problema

Ao montar os itens para os widgets (publisher-index e publisher-highlights), os valores dos campos customizados (como caminhos de imagem) salvos na tabela publisher_pages.fields_values contêm caminhos relativos (ex: /arquivos/imagem.png). Os novos templates que utilizam imagem destaque precisam renderizar o caminho absoluto ou a partir da raiz do site. Para isso, é necessário prependir dinamicamente a URL raiz ($_GESTOR['url-raiz']) a esses valores. Como os tipos dos campos não são definidos na tabela publisher_pages e sim no campo fields_schema da tabela publisher, precisamos recuperar dinamicamente se o campo customizado é do tipo 'image'.

6.2 Solução no Backend

  • Consulta ao Schema do Publicador (Cache Estático):

    • Recuperar a coluna fields_schema da tabela publisher filtrando por id = $publisher_id e language = $_GESTOR['linguagem-codigo'].

    • Mapear a lista de campos (fields no JSON) associando cada ID do campo ao seu respectivo type.

    • Como otimização para evitar múltiplas consultas ao banco de dados no mesmo request, os tipos de campos por publicador devem ser cacheados em uma variável estática/memória no script PHP.

  • Módulo publisher-index (publisher-index.widget.php):

    • Atualizar a assinatura da função helper de montagem de itens: function publisher_index_widget_montar_itens($rows, $publisher_id = null)

    • Atualizar todas as chamadas de publisher_index_widget_montar_itens para passar o respectivo $publisher_id (dentro de publisher_index_widget_buscar_publicacoes e publisher_index_widget_lista_manual).

    • Em publisher_index_widget_montar_itens, caso o $publisher_id seja fornecido:

    • Obter a relação de tipos de campo do publicador.

    • Para cada campo customizado em fields_values do registro, verificar se seu ID está mapeado como tipo 'image'.

    • Se for do tipo 'image' e o valor não estiver vazio, prependir $_GESTOR['url-raiz'] ao valor retornado.

  • Módulo publisher-highlights (publisher-highlights.widget.php):

    • Na função publisher_highlights_widget_buscar_publicacoes, aplicar a mesma lógica de consulta ao fields_schema da tabela publisher.

    • Ao processar cada campo customizado de fields_values do registro, verificar se o ID do campo está mapeado como tipo 'image'.

    • Se for do tipo 'image' e o valor não estiver vazio, prependir $_GESTOR['url-raiz'] ao valor retornado.

O Futuro é Híbrido: Humano + IA.

O Conn2Flow é a ferramenta. Se você precisa do Arquiteto para desenhar a estratégia da sua empresa usando essa tecnologia...

Contrate Consultoria Especializada