Conn2Flow
Navegação das docs

SDD

req-066: Registro Dinâmico de Widgets do Sistema e Carregamento sob Demanda no Editor HTML

Publisher Highlights (gestor/modulos/publisher-highlights/publisher-highlights.json - já existente): json "widgets": [ { "id": "publisher-highlights", "name": "Destaques", "icon"…

Descrição do Problema / Contexto

Atualmente, a barra de inserção de elementos no Editor HTML Visual (html-editor-add-panel em html-editor-visual-controls.js) possui uma lista estática (hardcoded) de 4 módulos de widgets do sistema (WIDGETS_MODULOS): Destaques, Menus, Galerias e Índice. Além disso, a verificação e carga de widgets no backend (html-editor.php -> html_editor_ajax_widgets_list()) também é baseada em um mapa estático das tabelas (menus, galleries, publisher_highlights, publisher_index, forms). Para permitir a extensão dinâmica do sistema por novos módulos que possam introduzir novos widgets, precisamos substituir essa abordagem rígida por um registro dinâmico no banco de dados através de uma tabela global widgets, cuja população será feita de forma automática via esteira de Sincronização de Recursos. Como o número de widgets ativos pode crescer significativamente, a interface de seleção no frontend deve migrar para um carregamento dinâmico (lazy loading) sob demanda via AJAX conforme o usuário interage (expande) as categorias no menu.


1. Estrutura do Banco de Dados (Phinx Migration)

Criar uma nova migração Phinx (ex: 20260708100000_create_widgets_table.php) para criar a tabela global widgets:

  • Tabela: widgets

  • Chave Primária: id_widgets (int, auto-incremento)

  • Colunas:

    • id (varchar 100, NOT NULL) -> O identificador lógico do widget / slug do módulo (ex: 'publisher-highlights')

    • name (varchar 255, NOT NULL) -> O rótulo amigável (label) da categoria (ex: 'Destaques')

    • icon (varchar 100, NOT NULL) -> O ícone CSS correspondente (ex: 'star')

    • tabela (varchar 100, NOT NULL) -> A tabela de banco de dados onde os registros de widgets desse tipo estão armazenados (ex: 'publisher_highlights')

    • coluna_where (varchar 100, NULL) -> Opcional. A coluna a ser utilizada como filtro na tabela alvo, caso aquele widget represente apenas um subconjunto (ex: 'type').

    • language (varchar 10, NOT NULL, default 'pt-br')

    • status (char 1, default 'A')

    • versao (int, default 1)

    • data_criacao (datetime, default CURRENT_TIMESTAMP)

    • data_modificacao (datetime, default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP)

    • user_modified (tinyint, default 0)

    • system_updated (tinyint, default 0)

    • project (varchar 255, NULL) -> Necessário para integridade de deploy de projetos.

  • Índice Único: ['id', 'language'].


2. Registro de Recursos nos Módulos e Configuração Global

2.1 Configuração Global de Sincronização (tables_config.json)

Adicionar a tabela widgets em gestor/resources/tables_config.json sob a chave "tabelas" para que seja reconhecida pela esteira de sincronização de banco de dados (atualizacoes-banco-de-dados.php via schema-metadata.json):

        "widgets": {
            "nome": "widgets",
            "id": "id",
            "id_numerico": "id_widgets",
            "config": {
                "strategy": "natural_key",
                "natural_key_columns": [
                    "language",
                    "id"
                ],
                "preserve_on_user_modified": [],
                "insert_only": false
            },
            "deletar": []
        }

2.2 Manifestos JSON dos Módulos

Adicionar a declaração de recursos "widgets" nos arquivos JSON descritores de módulos para alimentar a tabela global. (Nota: O primeiro registro já foi inserido no publisher-highlights.json pelo Engenheiro Chefe):

  1. Publisher Highlights (gestor/modulos/publisher-highlights/publisher-highlights.json - já existente):

    "widgets": [
       {
           "id": "publisher-highlights",
           "name": "Destaques",
           "icon": "star",
           "tabela": "publisher_highlights"
       }
    ]
  2. Menus (gestor/modulos/menus/menus.json - adicionar):

    "widgets": [
       {
           "id": "menus",
           "name": "Menus",
           "icon": "bars",
           "tabela": "menus"
       }
    ]
  3. Galerias (gestor/modulos/galleries/galleries.json - adicionar):

    "widgets": [
       {
           "id": "galleries",
           "name": "Galerias",
           "icon": "images",
           "tabela": "galleries"
       }
    ]
  4. Publisher Index (gestor/modulos/publisher-index/publisher-index.json - adicionar):

    "widgets": [
       {
           "id": "publisher-index",
           "name": "Índice",
           "icon": "list",
           "tabela": "publisher_index"
       }
    ]

3. Compilador de Recursos (atualizacao-dados-recursos.php)

Ajustar o script gestor/controladores/agents/arquitetura/atualizacao-dados-recursos.php para coletar o novo tipo de recurso widgets de dentro dos módulos:

  • Adicionar 'widgets' à lista de tipos processados no laço de varredura de módulos.

  • Se $tipo === 'widgets', ler a lista do array e salvar o registro estruturado (normalizando nome, id, icon, tabela, coluna_where, language, status = 'A', versao = 1, user_modified = 0) na pilha $widgets.

  • Saneamento de duplicidades: Usar índice $idxWidgets[$key] (chave lang|id) e enviar duplicados para o array de órfãos ($orphans['widgets']).

  • Salvar a lista consolidada no final gerando o arquivo serializado gestor/db/data/WidgetsData.json por meio de jsonWrite($DB_DATA_DIR.'WidgetsData.json', ...).

  • Incluir o tipo 'Widgets' na lista de limpeza/geração de órfãos no diretório db/orphans/.


4. Roteamento e Carga Dinâmica no Backend (html-editor.php)

No arquivo gestor/bibliotecas/html-editor.php:

4.1 Nova Rota: Lista de Categorias/Tipos de Widgets (html-editor-widget-types)

  • Criar a função AJAX html_editor_ajax_widget_types() (chamada pela rota html-editor-widget-types):

    • Consultar a tabela widgets para o idioma ativo de controle:

      SELECT id, name, icon FROM widgets WHERE status = 'A' AND language = :idioma ORDER BY name ASC
    • Retornar a lista em formato JSON [ { id: '...', name: '...', icon: '...' }, ... ].

4.2 Rota Atualizada: Registros de Widgets sob Demanda (html-editor-widgets-list)

  • Ajustar a função html_editor_ajax_widgets_list() para receber o parâmetro module (ou widget_type) do request.

  • Consultar a tabela widgets para carregar as definições do widget especificado:

    • Query: SELECT tabela, coluna_where FROM widgets WHERE id = :module AND language = :idioma AND status = 'A' LIMIT 1

    • Se não encontrar, retornar array vazio.

  • Executar uma consulta dinâmica na tabela alvo (tabela):

    • Validar se o nome da tabela (tabela) e o nome da coluna (coluna_where) contêm apenas caracteres seguros (alfanuméricos e underscore) para evitar SQL Injection.

    • Montar a cláusula WHERE:

    • Base: WHERE status = 'A' AND language = :idioma

    • Se coluna_where estiver preenchido: concatenar AND {coluna_where} = :module

    • Query final: SELECT id, name FROM {tabela} {WHERE} ORDER BY name ASC (Nota: Se a tabela alvo não possuir a coluna name (ou se o identificador for diferente), ler de forma compatível ou fallback para id).

    • Devolver os registros em formato JSON [ { id: '...', nome: '...' }, ... ].


5. Interface e Interação no Frontend (html-editor-visual-controls.js)

No arquivo gestor/assets/interface/html-editor-visual-controls.js:

  • Remover a variável hardcoded WIDGETS_MODULOS.

  • Fluxo de Carga Inicial:

    • Ao carregar/abrir o painel (abrirPainel()), se a lista de categorias não estiver em cache:

    • Realizar uma chamada AJAX para html-editor-widget-types.

    • Renderizar dinamicamente os grupos de categorias de widgets sob a seção "Widgets do Sistema" com o ícone e nome retornados.

    • Cada grupo (.he-add-widget-group) deve iniciar fechado/colapsado e conter a sublista com o texto "Carregando..." (.he-add-widget-list).

  • Fluxo de Expansão sob Demanda (Lazy Loading):

    • Adicionar/ajustar o evento de clique em .he-add-widget-head.

    • Ao expandir uma categoria (.he-add-widget-group), verificar se os itens dela já foram carregados.

    • Se ainda não carregados:

    • Disparar uma chamada AJAX para html-editor-widgets-list passando o parâmetro module correspondente.

    • Ao receber o retorno, renderizar os itens do widget no DOM (gerando elementos .he-add-widget-item com data-module, data-slug, data-name) e remover a mensagem de carregamento.

    • Salvar os itens carregados em um cache local (widgetsCache[module] = data) para evitar chamadas AJAX redundantes se o usuário fechar e reabrir a mesma categoria.


6. Validação e Testes

  1. Verificação de Sintaxe:

    • php -l gestor/controladores/agents/arquitetura/atualizacao-dados-recursos.php

    • php -l gestor/bibliotecas/html-editor.php

  2. Execução da Esteira de Recursos:

    • Executar a compilação local de recursos e verificar se o arquivo gestor/db/data/WidgetsData.json é gerado contendo os widgets dos 4 módulos.

    • Rodar a sincronização de banco de dados (atualizacoes-banco-de-dados.php) e garantir que a tabela widgets seja populada.

  3. Validação da Interface:

    • Abrir o Editor HTML Visual e clicar no botão "+".

    • Confirmar que as categorias (Destaques, Menus, Galerias, Índice) aparecem corretamente como grupos colapsados.

    • Clicar em uma categoria, verificar a chamada AJAX correspondente no Console/Network e constatar que os itens reais são listados somente após a interação.

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