Posts Tagged ‘ ExtJS

Menu em ExtJS com Permissões usando PHP e Mysql

Uma das coisas que mais me deu dor de cabeça quando comecei a trabalhar com ExtJS foi montar uma estrutura de Menu Dinâmico de acordo com as permissões do usuário logado. Por isso vou compartilhar minha solução:

Primeiro de tudo vamos criar o nosso banco de dados. Vamos precisar de duas tabelas: uma para o nosso menu e outra com as permissões de cada usuário.

A tabela do Menu terá os campos de id (o id do objeto no Extjs para facilitar manipulação posterior), o nome, o ícone, a pai (caso exista), a ordem e é claro a função que será chamada na ação do clique. Na segunda tabela vamos ter apenas duas chave, o id do usuário e o id do menu. Segue abaixo de exemplo a que eu utilizei:

MySQL

#
# Estrutura da Tabela Menu
#

CREATE TABLE /*!32312 IF NOT EXISTS*/ `menu` (
  `id_menu` int(3) NOT NULL AUTO_INCREMENT,
  `id` varchar(20) DEFAULT NULL,
  `menu` varchar(70) DEFAULT NULL,
  `ordem` int(3) DEFAULT NULL,
  `pai` int(3) DEFAULT NULL,
  `ico` varchar(50) DEFAULT NULL,
  `funcao` varchar(80) DEFAULT NULL,
  PRIMARY KEY (`id_menu`)
) TYPE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

#
# Estrutura da Tabela de Permissões
#

CREATE TABLE /*!32312 IF NOT EXISTS*/ `permissoes` (
  `id_usuario` int(3) NOT NULL DEFAULT '0',
  `id_menu` int(3) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id_menu`,`id_usuario`)
) TYPE=MyISAM DEFAULT CHARSET=latin1;

Dica: Vale lembrar que o ícone dos pais são definidos pelo nome da classe CSS e os filhos devemos especificar o caminho físico da imagem. Não sei por que, mas sub-menus não possuem o atributo “iconCls”. No PHP já vamos levar isso em conta.

A outra parte do nosso Menu é a montagem do Json que irá ser lido no ExtJS. Este método foi testado apenas com 1 sub-nível de menu, mas é fácil de modificar para funcionar com mais. Se alguém fizer, comente a experiência. O método é bem simples de entender. Basicamente buscamos os ítens do Menu principal e percorremos ele em busca de sub-menus alocando tudo em um array associativo.

PHP

		private function trataObjJson($strJson,$arrObjs)
		{
			foreach($arrObjs AS $obj)
				$strJson = str_replace("\"" . $obj . "\"",$obj,$strJson);
			return $strJson;
		}

		public function getMenu()
		{
			if($this->Search("SELECT id_usuario FROM usuarios WHERE id_usuario=" . $_SESSION['id_usuario']))
			{
				$menu = "";
				$tmpMenuPai = $this->Search("SELECT A.id_menu,id,menu,ordem,pai,ico,funcao FROM menu A JOIN permissoes B ON A.id_menu=B.id_menu WHERE A.pai=0 AND B.id_usuario=" . $_SESSION['id_usuario'] . " ORDER By A.ordem");
				$i=0;
				$funcoes = array();
				foreach($tmpMenuPai AS $item)
				{
					$menu[$i]['text'] 			= $item['menu'];
					$menu[$i]['iconCls'] 		= $item['ico'];
					$menu[$i]['tabIndex'] 		= $i;
					if($item['funcao']) {
						$menu[$i]['id'] 		= $item['id'];

						$menu[$i]['handler'] 	= $item['funcao'];
						$funcoes[] = $item['funcao'];
					}

					$tmpMenuFilho = $this->Search("SELECT A.id_menu,menu,id,ordem,ico,funcao FROM menu A JOIN permissoes B ON A.id_menu=B.id_menu WHERE A.pai=" . $item['id_menu'] . " AND B.id_usuario=" . $this->_id . " ORDER By A.ordem");
					$arrFilho = Array();
					$j=0;
					foreach($tmpMenuFilho AS $filho)
					{
						$arrFilho[$j]['text']			= $filho['menu'];
						$arrFilho[$j]['icon']			= $filho['ico'];
						if($filho['funcao']) {
							$arrFilho[$j]['id'] 		= $filho['id'];

							$arrFilho[$j]['handler'] 	= $filho['funcao'];
							$funcoes[] = $filho['funcao'];
						}
						$j++;
					}
					if($arrFilho)
						$menu[$i]['menu'] = $arrFilho;
					$i++;
				}
				header("Content-Type: application/json");
				echo $this->trataObjJson(json_encode($menu),$funcoes);
			}
		}

Observe que precisamos de um método auxiliar para tratar as funções. Isso se deve pelo fato da função json_encode do PHP colocar áspas em tudo, então para o ExtJS não interpretar nossa função como uma string e gerar um erro, utilizamos uma função para retira-las.

Agora que já temos a nossa estrutura de menu em Json, bastam poucas linhas em ExtJS para finalizar:

ExtJS

Ext.onReady(function(){
 	var conn = new Ext.data.Connection();
	conn.request({
		url: 'inc/php/menu.class.php',
		success: function(a){Ext.getCmp('menuPrincipal').bottomToolbar.add(Ext.util.JSON.decode(a.responseText));},
		failure: function(){Ext.MessageBox.alert('Erro', 'Erro ao carregar menu. Atualize a página.');}
	});
});

Espero ter ajudado.

Sistema de Autenticação com ExtJS

Vamos construir um sistema simples de autenticação utilizando o ExtJS. Feito o Download, vamos iniciar nosso sistema carregando a biblioteca do ExtJS para montarmos o nosso sistema de login. Nosso ponto de partida é o arquivo Index.php com a estrutura HTML a seguir:

Index.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
	<head>
	<link rel="stylesheet" type="text/css" href="/igs/includes/ext/resources/css/ext-all.css">
	<script type="text/javascript" src="/igs/includes/ext/adapter/ext/ext-base.js"></script>
	<script type="text/javascript" src="/igs/includes/ext/ext-all.js"></script>
	<script type="text/javascript" src="login.js"></script>
	</head>
	<body></body>
</html>
Obviamente, modifique os path de acordo com seu diretório EXT. Veremos o código do Login.js a seguir

Obviamente, modifique os paths de acordo com seu diretório EXT. Veremos o código do Login.js a seguir

Login.js

A seguir vem o login.js. Ele cria o formulário, renderiza uma janela popup, exibe a janela ao usuário, submete os dados via AJAX, e lida com o sucesso e o fracasso de resposta dependendo se o usuário inseriu os dados com sucesso.

Ext.onReady(function(){
    Ext.QuickTips.init();

	// Crie uma variável para armazenar nosso EXT Form Panel 
	// Assinamos várias opções de configuração	 
    var login = new Ext.FormPanel({
        labelWidth:80,
        url:'login.asp',
        frame:true,
        title:'Entre com seu Login',
        defaultType:'textfield',
	monitorValid:true,
	// Atributos específicos para os campos de usuário/senha. 
	// O atributo "name" define o nome da variável que será enviada do servidor.
        items:[{
                fieldLabel:'Usuário',
                name:'loginUsername',
                allowBlank:false
            },{
                fieldLabel:'Senha',
                name:'loginPassword',
                inputType:'password',
                allowBlank:false
            }],

	// Toda a mágica que acontece depois que o usuário clique no botão     
        buttons:[{
                text:'Login',
                formBind: true,
                // Função que é executada quando o usuário clicar no botão 
                handler:function(){
                    login.getForm().submit({
                        method:'POST',
                        waitTitle:'Conectando',
                        waitMsg:'Enviando dados...',

			// Função que executa (sucesso ou falha) quando o servidor responder. 
			// A que será executada é determinada pela 
			// responsta que virá do login.asp como mostrado abaixo. O servidor responde 
			// um JSON válido. 
			// Algo como: response.write "{ success: true}" ou
			// responde.write "{ success: false, errors: { reason: 'Falha no Login. Tente novamente.' }}" 
			// dependendo da lógica que contiver no código de retorno do servidor.
			// Se o sucesso ocorrer, o usuário será notificado com uma mensagem de alerta messagebox, 
			// e quando ele clicar em "Ok", então será redirecionado a qualquer página
			// que você tenha definido para redirecionamento. 

                        success:function(){
                        	Ext.Msg.alert('Status', 'Login Successful!', function(btn, text){
				   if (btn == 'ok'){
		                        var redirect = 'test.php';
		                        window.location = redirect;
                                   }
			        });
                        },

			// Função de falha, veja comentário sobre re: sucesso e falha. 
			// Você poderá ver aqui, se o login falhar, chama uma messagebox
			// com detalhes da falha  

                        failure:function(form, action){
                            if(action.failureType == 'server'){
                                obj = Ext.util.JSON.decode(action.response.responseText);
                                Ext.Msg.alert('Login Failed!', obj.errors.reason);
                            }else{
                                Ext.Msg.alert('Warning!', 'Authentication server is unreachable : ' + action.response.responseText);
                            }
                            login.getForm().reset();
                        }
                    });
                }
            }]
    });

	// Aqui é criado uma janela para agregar o formulário. 
	// O objeto login é passado como ítem desta janela.       
    var win = new Ext.Window({
        layout:'fit',
        width:300,
        height:150,
        closable: false,
        resizable: false,
        plain: true,
        border: false,
        items: [login]
	});
	win.show();
});

Login.php

Aqui é onde o servidor processa o seu login. Vou me apegar a colocar apenas um código simples para mostrar as respostas que serão retornadas, e tederminar que função o login.js executará (sucesso ou falha). Contanto, aqui é onde você deverá chamar seu banco de dados com o usuário/senha da variável, da autenticação, e por fim enviar uma das mensagens de resposta dependendo se o usuário digirou uma credencial válida.

<?php
$loginUsername = isset($_POST["loginUsername"]) ? $_POST["loginUsername"] : "";

if($loginUsername == "f"){
    echo "{success: true}";
} else {
    echo "{success: false, errors: { reason: 'Falha no login. Tente novamente.' }}";
}
?>

Ou, você pode usar PHP avançado com array associativo e a função json_encode, e renderizar a resposta em JSON. Isso pode ser útil para não ter trabalho braçal caso esteja utilizando um JSON mais complexo.

<?php
$loginUsername = isset($_POST["loginUsername"]) ? $_POST["loginUsername"] : "";

if($loginUsername == "f"){
    $result["success"] = true;
} else {
    $result["success"] = false;
    $result["errors"]["reason"] = "Falha no Login. Tente novamente.";
}
echo json_encode($result);
?>

Você vai notar uma linha no login.js que redireciona para text.php caso um login bem sucedido aconteça. Esta pode ser, obviamente, qualquer que seja a página principal de sua aplicação.

Baseado no original de David Fitch: Tutorial: Basic Login

Criando Rich Internet Applications com ExtJS

mb_extjs_splashExtJS é sem dúvida uma das ferramentas mais poderosas que temos hoje para se criar Aplicativos Web robustas, a grande vantagem é a facilitade de se criar elementos com boa usabilidade e instintivos.

Trata-se de um Framework Client-side para criar Rich Internet Applications (RIA). Com a variedade de funcionalidades existentes na versão 3.0 e as contribuições avulsas de usuários, ele se torna uma ferramenta completa para se criar diversos aplicativos complexos.

tasksO mais interessante, é o visual da aplicação. É possível criar aplicações que se passam por aplicações desktop devido a riqueza dos componentes. Isso faz com que usuários mais leigos tenham uma facilidade maior ao usar sua aplicação por estar habituado a usar softwares como o pacote do Office 2007, e outros softwares populares, tornando sua aplicação bem intuitiva. Na página de exemplos você pode ter uma noção do que pode ser feito.

Obviamente nem tudo são flores. Apesar de ter a possibilidade de personalizar o framework apenas com os módulos que você irá utilizar em sua aplicação (como o jQuery), o tamanho final da aplicação se torna um tanto quanto “pesada” se comparado a interfaces criadas diretamente com HTML acompanhado de JavaScript. Então antes de sair usando, é melhor botar na balança a real complexidade de seu aplicativo pois muitos podem se enganar com a facilidade de criar interfaces com boa aparência e acabar usando um canhão para matar uma mosca.

No entando, estamos lidando com uma estrura um pouco diferente. No ExtJS todas as interfaces são carregadas ao acessar a aplicação. O que na minha opinião é bem interessante, após carregado, sua aplicação web não fará nenhum reload na página para acessar qualquer área interna do seu sistema (sem contar que no próximo acesso, sua interface provavelmente estará no Cache do navegador).  Todos os dados de banco são carregados através de uma requisição HTTPrequest recebendo um XML ou Json como resposta, o que abre o leque para se trabalhar com WebService, ou fazer com que sua aplicação também esteja disponível Offline através do Google Gears.

Nos próximos posts vou explicar na prática como iniciar com ExtJS, colocar exemplos e indicar boas práticas de minhas experiências anteriores.

Aplicativos Web

Cloud Computing

A tendência mundial de Cloud Computing está se firmando a cada dia. Novos aplicativos plataforma web são lançados diariamente e nas mais diversas áreas.

Muita coisa boa vem sendo feita. Hoje praticamente para tudo que você precisar, você vai encontrar um aplicativo na web, desde um controle financeiro pessoal a gráficos na versão online do Photoshop.

Essa tendência de aplicativos nas nuvens não é por acaso, as tecnologias web (principalmente de interface) vem tendo uma evolução muito grande nos últimos tempos. Os navegadores estão alterando seus compiladores JavaScript para que eles se  tornem mais rápidos e confiáveis, os avanços do HTML5, CSS3, e é claro não podemos deixar de lembrar na convergência para o uso de padrões web que a cada dia que passa ganha mais força.

O uso de Frameworks sem dúvida alguma é algo que realmente enriquece a aplicação. Hoje o jQuery tem plugins para praticamente qualquer coisa que você precise, com a vantagem de um código cross-browser, organizado e de fácil personalização (ao contrário das ferramentas do Visual Studio .Net da Microsoft).

Outro framework que tenho utilizado para algumas aplicações web é o ExtJS, que está em sua terceira versão do Framework Javascript, e na minha opinião é o que tem elementos de interfaces mais ricas que as demais. Outra coisa que se destaca é a facilidade com que se cria elementos complexos como grid, menu e formulários. Já tem disponível desde a versão 2.0 a tradução para o português para calendário e outros elementos básicos. Outra vantagem é a facilidade de se abstrair o banco de dados podendo trabalhar com XML e Json. Vale lembrar que o ExtJS está licensiado pela GPL v3.0 e para uso comercial deve-se adquirir a licença.

Por último e não menos importante, vale ressaltar um grande avanço que está engatinhando e vem sendo impulsionado principalmente pelo Google que é o suporte offline de aplicações web. Isso vem sendo testado através do aplicativo Google Gears, que está em versão beta mas já trás módulos funcionais como:

  • LocalServer Recursos de aplicativo de armazenamento em cache e servidor local (HTML, JavaScript, imagens etc.);
  • Banco de dados Armazenamento local de dados em um banco de dados relacional que pode ser totalmente pesquisado;
  • WorkerPool Seus aplicativos de web ficam com maior capacidade de resposta, executando de forma assíncrona as operações com uso intenso de recursos.

A versão 0.4 trouxe ainda Geolocation, Acesso a arquivos da máquina, dentre outras coisas. Vale lembrar que o Gears já vem instalado por padrão no Chrome, mas pode ser instalado no Firefox, IE e Safari (windows, linux e Mac).

O Google Gears realmente abre um caminho fantástico para aplicativos que requerem uma dependência mais crítica. Mais informações estão disponíveis no site do desenvolvedor da API.

The Ubuntu Counter Project - user number # 31874