segunda-feira, 9 de maio de 2011

TreeView com Controle de Acesso

Após um tempinho no ar da versão de montagem de menus em formato de árvore, chegaram muitos pedidos para agregar uma condição de segurança, isso de forma a filtrar somente os itens possíveis de serem abertos a um determinado grupo de usuários.

Então, para não ficar chato e repetitivo, vamos aplicar o mesmo conceito dos menus recursivos, mas desta vez gerando uma TreeView, que também opera do mesmo modo do JsCookMenu.

ara entender o funcionamento de menus do tipo recursivo, recomendo uma leitura do post anterior (http://profdouglasoliveira.blogspot.com/2010/10/criando-um-menu-recursivo.html) que trata mais profundamente da questão comportamental de menus hierárquicos, os nós, e outros elementos, nesse post estaremos apenas discutindo o TreeView e o parâmetro de segurança.

Tree View


Na versão X o Genexus inovou com a possibilidade de agregar User Controls para aprimorar os resultados da interface web.  Tree View é um dos mais interessantes, e tem por objetivo listar opções de seleção em um formato tipicamente de árvore. Nosso objetivo é produzir um menu que seja filtrado nas operações possíveis de serem realizadas conforme o grupo de usuários. 


 Um WebPanel pode ser programado com os seguintes eventos, sendo que o &PerfilId consiste em um Dynamic Combo Box que permite selecionar o perfil do usuário, e ao ser clicado, se chama a carga do menu.

Event Start
     &selectedTreeNode.Expanded   = 1
EndEvent

Event &PerfilId.Click
     &treeNodeCollectionData      = MenuTreeDP(2, &PerfilId)
EndEvent

O Web Panel, é construído de forma simples, com o Dynamic Combo e o Tree View logo abaixo.


Transações

Nesse exemplo são necessárias duas transações, uma para conter os dados do menu e outra para conter os dados do perfil, conforme apresentamos no diagrama de tabelas abaixo.  MenuTitulo e MenuLink são do tipo Char.


O elemento PaiMenuId é definido como um subtipo de MenuId, ou seja, torna a tabela Menu recursiva.  PaiMenuId deve possuir o Nullable=true na definição desta estrutura.


Para realizar a carga nas tabelas teríamos que definir a de Perfil, com seus diversos grupos de usuários.

E a tabela de Menu com os itens em cada um dos grupos. Essa tabela poderia inclusive ser melhorada para um modelo 1-N, para evitar a repetição dos itens, mas deixemos esse assunto pra lá, a idéia aqui é didática e não otimização.


Data Provider (DP)

Finalmente, para carregar os dados da tabela e apresentar no Tree View necessitamos de um objeto Data Provider. E o mecanismo também é simples, obedecendo a estrutura do TreeNodeCollection SDT, carregando os valores de Id, Name, Link e Target, conforme os valores armazenados na tabela Menu.

TreeNodeCollection
where PaiMenuId = &PaiMenuId
where PerfilId  = &PerfilId when &PerfilId<>0
{
     TreeNode
     {
          Id            = MenuId.ToString()
          Name          = MenuTitulo
          Link          = MenuLink
          LinkTarget    = '_self'
          Nodes         = MenuTreeDP(MenuId, &PerfilId)
     }
}

A linha a seguir, gera a chamada recursiva, ao próprio DP, que no nosso caso se chama MenuTreeDP.
          Nodes         = MenuTreeDP(MenuId, &PerfilId)

Diferente da primeira versão, nessa será necessário fornecer ao DP duas informações, a raiz (&PaiMenuId) e o perfil (&PerfilId) a ser filtrado os itens do respectivo usuário. Portanto,  não se esqueça da regra Parm nesse DP.

parm(
     &PaiMenuId,
     &PerfilId
     );


Conclusão

Esse exemplo é basicamente um complemento do primeiro post, e com poucos ajustes, permite controlar um pouco melhor o menu.

Não se esqueça que o usuário poderá chamar no endereço do Browser os itens que não aparecem no menu, portanto, algo a mais deve ser incorporado nos objetos chamados para evitar acessos indevidos.

E também se faz necessário um pouquinho de WebSession ou Cookie, para gravar o perfil de acesso do usuário, provavelmente definido no login.

Boa programação...