Esta especificação define a evolução do módulo de menus para suportar itens multi-nível (pais e filhos), múltiplos tipos de itens (páginas, links livres, cabeçalhos, ações programáticas), um editor drag-and-drop vertical/horizontal para organizar a estrutura hierárquica e filtros por tipo de página no autocomplete.
1. Escopo das Modificações
1.1 Tipos de Itens do Menu
Cada item adicionado ao menu deve possuir uma tipagem bem definida que controla seu comportamento no frontend e backend:
-
Página (
pagina): Vincula a uma página física existente do site (carregada via AJAX depaginas). O link é resolvido dinamicamente no renderizador. -
Link Externo/Livre (
link-custom): O usuário digita de forma livre o texto (Rótulo/Label) e a URL completa (ex:[REDACTED]ou/contato/). -
Cabeçalho/Contêiner (
cabecalho): Apenas rótulo textual, sem link (URL vazia ou#). Usado para agrupar e abrir submenus suspensos. -
Link de Ação / CSS Personalizado (
link-action): Permite que o usuário insira classes CSS personalizadas no item de menu para que o desenvolvedor possa disparar modais ou scripts programáticos no frontend. -
Divisor / Separador (
separador) (Sugestão do Arquiteto): Apenas uma linha horizontal divisória sem texto ou link.
1.2 Filtro de Tipo de Página no Autocomplete
-
Contexto: No Conn2Flow, as páginas do site registradas na tabela
paginaspossuem tipos diferenciados na colunatipo(principalmente'pagina'e'sistema'). -
Filtro Visual: Quando o usuário selecionar o tipo de menu
pagina, deve ser exibido um conjunto de campos de rádio (inline radio checkboxes) do Fomantic UI contendo as opções:-
Página (
value="pagina"): Pesquisa apenas páginas de conteúdo padrão. -
Sistema (
value="sistema"): Pesquisa apenas páginas de rotinas/funcionalidades do sistema. -
Ambos (
value="ambos"): Pesquisa qualquer tipo de página.
-
-
Comportamento: A opção padrão selecionada deve ser Página. A alteração dessa seleção deve recarregar os dados do autocomplete enviando o parâmetro correto ao AJAX.
1.3 Estrutura de Células de Template no Widget (Recursão)
No motor de widgets (menus.widget.php), os itens de menu serão processados como uma árvore hierárquica (JSON recursivo) em vez de uma lista plana.
Para renderizar menus multiníveis, os templates em resources/{pt-br,en}/templates/ suportarão três delimitadores:
-
no-item(<!-- no-item < --> ... <!-- no-item > -->): Renderizado quando o menu não possuir nenhum item. -
item(<!-- item < --> ... <!-- item > -->): Célula padrão para itens finais (folhas, sem sub-itens). -
item-parent(<!-- item-parent < --> ... <!-- item-parent > -->): Célula para itens que possuem filhos. Deve renderizar os dados do item pai e incluir o placeholder especial[[item#children]]para injetar a renderização recursiva da lista de sub-itens filhos.
2. Detalhes de Implementação no Administrador
2.1 Interface de Adição de Itens (CRUD e Autocomplete)
-
Formulário de Entrada:
-
Nas páginas
adicionar.html,editar.htmleclonar.htmldo módulomenus, expandir a seção de curadoria. -
Adicionar o seletor de "Tipo de Item" (Dropdown do Fomantic UI): Páginas, Link Customizado, Cabeçalho, Link com Classe CSS ou Separador.
-
Adicionar a estrutura de rádio inline para filtrar o tipo de página (inicialmente oculta, aparecendo apenas quando o tipo de item for
pagina):<div class="field" id="page-type-filter-wrapper" style="display:none; margin-bottom: 12px;"> <div class="inline fields"> <label>Tipo de Página</label> <div class="field"> <div class="ui radio checkbox" data-tooltip="Clique para mostrar tipo Página" data-position="top left" data-inverted=""> <input type="radio" name="page_search_type" value="pagina" checked="checked"> <label>Página</label> </div> </div> <div class="field"> <div class="ui radio checkbox" data-tooltip="Clique para mostrar tipo Sistema" data-position="top left" data-inverted=""> <input type="radio" name="page_search_type" value="sistema"> <label>Sistema</label> </div> </div> <div class="field"> <div class="ui radio checkbox" data-tooltip="Clique para mostrar ambos" data-position="top left" data-inverted=""> <input type="radio" name="page_search_type" value="ambos"> <label>Ambos</label> </div> </div> </div> </div> -
Dependendo do tipo escolhido, exibir os campos de entrada corretos:
-
Para
pagina: Exibir o filtro de tipo de página, e o campo de busca autocomplete AJAX (#manual_search_input). -
Para
link-custom: Inputs textuais "Rótulo do Menu" e "URL". -
Para
cabecalho: Input textual "Rótulo do Menu" apenas. -
Para
link-action: Inputs "Rótulo", "URL" e "Classes CSS Personalizadas". -
Para
separador: Sem inputs adicionais (botão "Adicionar Separador").
-
-
Local de Inserção:
-
Se houver um item atualmente clicado/selecionado na lista de menus, o novo item deve ser adicionado imediatamente abaixo dele (como irmão ou como filho). Se não houver nenhum selecionado, adicionar no final da raiz.
-
2.2 Drag-and-Drop Multinível (menus.js)
-
Comportamento Hierárquico (Estilo WordPress):
-
As tags selecionadas passam a se organizar em uma lista vertical estruturada (ex: elementos
<li>ordenáveis dentro de um<ol>). -
Arrastar um item horizontalmente/verticalmente serve tanto para definir a ordenação (quem vem antes ou depois) quanto para recuar/avançar o recuo e definir o aninhamento como filho (
children) do item imediatamente acima. -
Uso do Sortable.js: Configurar o
Sortable.jscom instâncias aninhadas (nested groups comgroup: 'nested') permitindo que sub-listas aceitem elementos arrastados, ou integrar um plugin leve de jQuery compatível (comonestedSortable) que facilite o arraste bidimensional (vertical e recuo horizontal) para construir a árvore. -
Edição In-line: Cada item da árvore deve exibir:
-
Um botão/ícone de edição para abrir um pequeno modal/painel in-line que permita alterar o Rótulo, URL ou Classes CSS do item específico. No caso de item tipo página, ao ser selecionada pelo autocomplete, ela preenche o rótulo/título automaticamente, mas permite que o usuário altere ou resuma o rótulo livremente.
-
O botão de exclusão ("x") que remove o item e todos os seus filhos recursivamente da árvore.
-
2.3 Persistência do Schema
-
O array
schema.selected_itemspassa a salvar a árvore hierárquica completa em JSON estruturado de objetos:[ { "id": "item_17497491", "type": "cabecalho", "label": "Notícias", "url": "#", "css_classes": "", "children": [ { "id": "item_17497495", "type": "pagina", "label": "Economia", "url": "/economia/", "page_id": "pagina-economia", "children": [] } ] } ] -
No submit do formulário e no AJAX do preview, serializar a árvore em
fields_schemade forma que o widget receba a estrutura hierárquica correta.
3. Detalhes de Implementação no Backend (menus.php / menus.widget.php)
3.1 Filtro de Páginas no AJAX de Busca
-
Local:
gestor/modulos/menus/menus.php -
Lógica:
-
Na função
menus_ajax_pages_search(), extrair o parâmetrotipoenviado pelo frontend (ex:$_REQUEST['params']['tipo']ou$_REQUEST['tipo']). -
Se
tipofor'pagina'ou'sistema', concatenar no filtro SQL:AND p.tipo = '<VALOR>'. -
Se
tipofor'ambos', não filtrar por tipo (trazer qualquer página ativa). -
Caso o parâmetro seja omitido, aplicar o filtro por padrão como
tipo = 'pagina'.
-
3.2 Lógica Recursiva no Renderizador
-
Local:
gestor/modulos/menus/menus.widget.php -
Lógica:
-
Na função de renderização, decodificar
fields_schemaobtendo a árvore de itens de menu. -
Implementar uma função recursiva
menus_render_level($items, $templates)que:-
Percorra os itens do nível atual.
-
Para cada item sem filhos, carregue e substitua as variáveis no delimitador
item(expondo[[item#label]],[[item#url]],[[item#slug]]e[[item#css_classes]]). -
Para cada item com filhos, carregue o delimitador
item-parent, resolva suas variáveis, renderize recursivamente seus filhos viamenus_render_level($item['children'], ...)e substitua a saída renderizada no placeholder[[item#children]]. -
Concatene o HTML resultante e o devolva.
-
-
-
Resolução de Links:
-
Para o tipo
pagina, buscar dinamicamente o link da página do banco usando opage_id(slug) e a linguagem ativa para garantir links canônicos sempre atualizados.
-
4. Regras e Versionamento
-
TASK DE RECURSOS: Ao finalizar a implementação e migrações, executar
php ./gestor/controladores/agents/arquitetura/atualizacao-dados-recursos.phppara validar as modificações. -
ATENÇÃO: NÃO realizar commits (
git commit) ou envios (git push) de forma autônoma. As alterações do executor devem permanecer locais para aprovação manual.