domingo, 17 de fevereiro de 2013

Genexus e Google Analytics

Genexus Google Analytics
Google Analytics é uma ferramente poderosa e gratuita que possibilita conhecer como os usuários de sua aplicação se comportam. A partir de estatísticas em tempo real e em períodos determinados, podemos saber entre muitas outras coisas, a quantidade de visitantes únicos por dia, quais páginas eles mais acessam, em qual horário e quanto tempo eles permaneceram na aplicação.

Para desfrutar desta API (Application Programming Interface) é necessário possuir uma conta no Google, qualquer conta, como Gmail, YouTube e Orkut, acessar o site da ferramente e clicar
sobre o botão "Criar Conta". Seguindo o passo a passo da criação você irá informar seu nome, a url da aplicação, país, entre outras coisas.

Após a sua conta ser criada, o Google irá fornecer um código javascript de monitoramento, é necessário incluir este código na Master Page da sua aplicação. Este código contém uma Id única, cada aplicação adicionada ao Analytics terá a sua própria Id, e é desta forma que o Google irá reconhecer a sua aplicação.

Este código poderá ser encontrado através do menu "Administrador" no canto superior direito do site, opção "Informações de acompanhamento", segunda aba apresentada.

Genexus Google Analytics
código que estamos procurando

Inserção de código na aplicação Genexus

Para adicionar o código, em projeto web crie um novo arquivo de extensão ".js" (analytics.js) dentro da pasta "web" do seu projeto, e, abra-o com o bloco de notas, ou qualquer editor que text que desejar.

Inclua o código fornecido pelo Google:

var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-99999999-9']);
_gaq.push(['_trackPageview']);

(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();

Agora, no objeto Master Page, inclua o código abaixo no evento Start:

Form.JScriptSrc.Add('analytics.js')

Após a publicação deste objeto Master Page em ambiente de Produção, já poderemos monitorar as estatísticas da aplicação. Por exemplo a quantidade de visitas x quantidade de páginas acessadas por visita nos últimos 30 dias:

Genexus Google Analytics


segunda-feira, 4 de fevereiro de 2013

Genexus - Grid Design

Genexus Grid Design
O Design aplicado ao Genexus

Quando trabalhamos em um projeto, a parte gráfica deste, seu design, imagens e estilos, é sempre a última tarefa a ser realizada. Isso, quando não aplicamos o design default disponível a partir da ferramenta Genexus.

Para nós analistas, o design pode parecer algo supérfluo, que não alterará em nada as aplicações. Porém para muitos usuários é algo essencial, a aplicação pode estar perfeita porém se o usuário não se interessar pelo seu design, a sua expectativa com relação ao sistema não terá sido alcançada.

Temos de ser racionais, e considerar que todas estas visões estão corretas. Não podemos transformar a parte gráfica das aplicações no principal processo de desenvolvimento, mas também, devemos considerar que a parte estética pode aumentar em muito a interação de nossas aplicação junto ao usuário final.

Hoje irei tratar de uma configuração simples, como transformar o design padrão dos grids em um grid igual ao da figura do topo do post, muito semelhante à biblioteca gxui. Acredito que a partir deste post podemos avançar para outros mais avançados, como, utilizar consideravelmente a biblioteca jquery em nossa MasterPage.

Configuração do Grid a partir do Tema

Primeiramente, iremos abrir o nosso tema padrão do projeto, a partir da pasta "Customization" - "Themes" (figura 2). Após aberto, precisamos criar uma nova classe do objeto "Grid". Para isso, clicamos com o botão direito sobre o objeto "Grid" e clicamos em "Add Class" (figura 3).

Genexus Folder View
figura 2 - Folder View
Genexus Tema
figura 3 - Adicionar Classe

OK, agora vamos começar a configurar suas propriedades gráficas. Abaixo irei listar cada propriedade, seu valor de configuração, e uma descrição explicativa:

PropriedadeValorDescrição
NameGridBlog(nome da classe)
Background Repeatrepeat-x(determina se a imagem de fundo irá se repetir horizontalmente, verticalmente)
Margin1pt 1pt 1pt 1pt(margem externa: acima, a direita, abaixo, a esquerda)
Padding1pt 5pt 1pt 5pt(margem interna: acima, a direita, abaixo, a esquerda)
Background ColorTransparent(cor de fundo do grid)
Background ImagemGridBackground(imagem de fundo do grid, disponível abaixo do post)
Border Color#1a67b8 #1a67b8 #1a67b8 #1a67b8(cores das bordas: acima, a direita, abaixo, a esquerda)
Border Stylesolid (estilo da borda, linha solida)
Border Width1px(largura da borda)
Line Back Colortransparent(cor das linhas impares)
Line Back Color EvenGainsboro (cor das linhas pares)
Line Font Stylenormal(estilo de fonte normal)
Line Font Size11px(tamanho da fonte das linhas)
Line Font FamilyArial (fonte das linhas)
Title Back Colortransparent (cor de fundo dos títulos das colunas)
Title Font Stylenormal(estilo de fonte normal)
Title Font Weightbold (peso da fonte dos títulos das colunas)
Title Font Size12px(tamanho da fonte dos títulos das colunas)
Title Font FamilyArial (fonte dos títulos das colunas)
Title Fore ColorBlack (cor dos títulos das colunas)
Custom CSS Propertiespadding-top:2pt;(margem interna aplicada ao topo)

Imagens Utilizadas

Neste exemplo estamos utilizando apenas 4 imagens. Imagens de ação (alteração, exclusão e visualização) e a principal e referenciada na propriedade da classe, a imagem de fundo do grid (degrade do topo). São elas:

alteração
alteração
Exclusão
Exclusão
Visualização
Visualização
Imagem GridBackground
Imagem GridBackground
Estas imagens são de escolha do desenvolvedor, indico um ótimo site de ícones. Muito bom para encontrar as imagens adequadas para a sua aplicação, o site é http://findicons.com/.

Definição de classe

Por fim, é necessário definir esta classe criada em nossos grids apresentados. Para isto, no objeto trabalhado (transação ou web panel), clique sobre o grid de modo a apresentar as suas propriedades à direita. No item "Appearance - Class", selecione o nome da classe criada, GridBlog, conforme a figura abaixo:

Genexus Grid Propriedades

quinta-feira, 17 de janeiro de 2013

Teste seu conhecimento #1 (lógica de programação)

Desafio
Nos primórdios de 2007, quando estava começando a entrar no mundo da TI, em meio a tantos currículos enviados fui convidado para fazer uma entrevista em uma empresa que desenvolvia softwares em php. Nessa primeira entrevista, todos os candidatos ficavam na mesma sala e recebiam cada um, uma folha contendo 5 questões de lógica de programação e conhecimentos da linguagem (métodos, funções, etc). 

Dentre estas questões, teve uma que dificilmente vou esquecer, era uma pergunta simples mas que fugia do cotidiano. Lanço um desafio para aqueles que desejarem participar e ver em quantos comandos são capazes de resolves. Mas sem colar... hahaha

A Missão

A proposta deste desafio é:

Dada duas variáveis A e B, sendo A = 3 e B = 5, escreva um código, sem utilizar uma terceira variável, capaz de trocar o valor entre elas. Ao fim, as variáveis deverão ser iguais a: A = 5 e B = 3......

Ah sim! Daqui a UM mês irei divulgar o resultado, então há tempo de sobra.

Gostaria muito de receber sua contribuição. Obrigado. :D

terça-feira, 15 de janeiro de 2013

Genexus - Envio de Email com Anexo

Essa matéria se propõem a analisar o método de envio de email com anexo adicionado, seja através de um caminho fixo do servidor, ou então a partir de uma variável blob. Esta variável, poderá por exemplo, vir de um atributo blob presente em alguma transação.

Trata-se de uma continuidade as tantas postagens a respeito deste assunto nos blogs da comunidade Genexus. Antes de continuar, sugiro uma leitura do post Genexus Mail, do excelente blog Genexando.
Para realizar este exemplo de envio de email, utilizarei 3 objetos Genexus: uma transação contendo os parâmetros de conexão com o host; uma web panel contendo três variáveis; e uma procedure.

Criação da Transação de Parâmetros

Geralmente quando iniciamos um projeto a transação de parâmetros estará presente na especificação do analista. É nesta transação que os dados de configurações do sistema serão registrados, e dentre estes registros possuímos os dados de conexão com o host smtp, responsável pelo envio de email através da aplicação.

Logo, nossa transação terá a seguinte estrutura:

Genexus Transação
Criação da Web Panel

Esta Web Panel criada não é essencial para o nosso exemplo, é apenas para demonstrar que poderemos passar o conteúdo deste email como parâmetro através de variáveis presentes em tela.

Então, apenas como exemplificação disto, adicionei na Form deste objeto três variáveis, além de outra que irei utilizar nos Eventos:
  1. (form) Assunto: VarChar(120);
  2. (form) Anexo: Blob;
  3. (form) TextoHTML: LongVarChar(2M);
  4. (eventos) SourceAnexo: VarChar(400);
Dessa forma, o usuário poderá determinar o Assunto e o Conteúdo da mensagem de email, além de anexar um documento. Ao clicar sobre o botão, o seguinte evento de usuário será executado:
Event Enter
//=====Captura o endereço gerado do documento anexado=====
&SourceAnexo = &Anexo.ToString()

//=====Chama Procedure de Envio de Email=====
EnviaEmail.Call(&Assunto,&TextoHTML,&SourceAnexo)
EndEvent
Criação da Procedure de Envio de Email

Por fim, precisamos programar a procedure que realizará o envio do email. Como este objeto não irá realizar gravação no banco de dados, podemos configurar a sua propriedade commit on exit, como "no".

Nesta procedure iremos receber os seguintes parâmetros (Rules):
parm(in:&Assunto,in:&TextoHTML,in:&SourceAnexo);
Estas variáveis recebidas possuem o mesmo DataType determinado na Web Panel anteriormente especificada.

Agora só nos falta programar os eventos, estes serão:
//=====Captura Dados de Conexão da Transação Parametros=====
for each
defined by ParametroId
//=====Host SMTP exemplo: smtp.live.com(outlook.com);
        //smtp.gmail.com(gmail.com)=====
&SMTPSession.Host = ParametroServidorSMTP.Trim()

//=====Autenticação: 1 (requer usuário e senha)=====
&SMTPSession.Authentication = ParametroAuthentication

//=====Dados de Login: Usuário e Senha=====
&SMTPSession.UserName = ParametroUserName.Trim()
&SMTPSession.Password = ParametroPassword.Trim()

//=====Remetente: Email e Nome=====
&SMTPSession.Sender.Address = ParametroSenderAdress.Trim()
&SMTPSession.Sender.Name = ParametroSenderName.Trim()
endfor

//=====Efetua o Login=====
&SMTPSession.Login()

//=====Verifica se ocorreu algum erro=====
if &SMTPSession.ErrCode <> 0
msg(&SMTPSession.ErrDescription)
else
//=====Insere o texto da mensagem=====
&MailMessage.HTMLText = &TextoHTML

//=====Insere o assunto da mensagem=====
&MailMessage.Subject = &Assunto

//=====Adiciona 1º Destinatário de email=====
&MailRecipient.Address = 'cicrano@hotmail.com'
&MailRecipient.Name = 'Cicrano'
&MailMessage.To.Add(&MailRecipient)

//=====Adiciona 2º Destinatário de email=====
&MailRecipient.Address = 'beltrano@outlook.com'
&MailRecipient.Name = 'Beltrano'
&MailMessage.To.Add(&MailRecipient)

//=====Adiciona email como Copia=====
&MailRecipient.Address = 'fulano@gmail.com'
&MailRecipient.Name = 'Fulano'
&MailMessage.CC.Add(&MailRecipient)

//=====Adiciona email como Copia Oculta=====
&MailRecipient.Address = 'genexus@outlook.com'
&MailRecipient.Name = 'Genexus'
&MailMessage.BCC.Add(&MailRecipient)

//=====Adiciona Anexo a partir de um caminho do servidor=====
&MailMessage.Attachments.Add('C:\Temp\VendaDiaria_20121217.csv')

//=====Adiciona Anexo a partir de uma variável Blob=====
if not &SourceAnexo.IsEmpty()
&MailMessage.Attachments.Add(&SourceAnexo)
endif

//=====Envia Email=====
&SMTPSession.Send(&MailMessage)

//=====Verifica se ocorreu erro=====
if &SMTPSession.ErrCode <> 0
msg(&SMTPSession.ErrDescription)
else
msg('Email enviado com sucesso!')
endif
endif
Observações

Duas observações a respeito deste código, o nome das variáveis são iguais aos seus tipos de dados. Por padrão a porta utilizada para o envio de email é a 25, normalmente utilizada pelos servidores SMTP. Caso seja necessário alterar esta porta, será preciso incluir o seguinte código antes de realizar o Login:
&SMTPSession.Port = 465

Pessoal, qualquer dúvida, incremento ou correção enviem através dos comentários ou pelo email genexus@outlook.com. Abraço.

sábado, 5 de janeiro de 2013

Genexus - Jogo da Velha

Lembro de um dia, em que ainda era um estagiário aprendendo a trabalhar com o Genexus, cada um tem sua própria história de como entrou nesse "mundo" e seria muito interessante escutar a de cada um, a minha um dia ainda conto.., mas nesse dia estava ocioso no meu canto da sala e pensei, será que seria possível realizar algum jogo a partir do Genexus??

É claro que nunca pensei em um jogo tipo mario ou call of duty hehehe, mas um jogo simples tipo aqueles de tabuleiro. Então nesse tal dia tentei realizar o jogo da velha... 

Bem, no fim, tirando a parte gráfica hahaha, consegui fazer um jogo da velha a partir de uma web panel usando variáveis bitmap e eventos de clique destas. Mas o melhor desse dia é que no fim disso tudo, consegui evoluir um pouco mais nos conhecimentos que tentava absorver.

Abaixo você poder ver uma pequena demonstração do resultado deste post:


Hoje vou passar um pouco disso pra galera que esta curiosa de saber.

Paint Brush - Desenhos

Bora lá, primeiro desenhei no Paint Brush mesmo, quatro desenhos:
  1. um quadrado com dimensões de 230x230px contendo o desenho clássico do jogo;
  2. um xis com dimensões de 66x66px;
  3. um círculo com dimensões de 66x66px;
  4. e uma tela branca com as mesmas dimensões de 66x66px;
Criação de nova classe Table

Após isso, iremos no Genexus criar uma nova classe de tabela, dentro do nosso tema trabalhado. A classe que criei, a nomeei de "TableFundoJogo", e nesta nova classe foram alteradas as seguintes propriedades:
        BackgroundRepeat: no-repeat
        Height: 230px
        Width: 230px
        BackgroundImagem: Fundo230 (nome da minha imagem de fundo)

Projetando nossa Web Panel 

Agora criaremos uma nova Web Panel (figura abaixo), iremos adicionar uma tabela de 3 Rows x 3 Columns. Esta tabela conterá a classe que criamos anteriormente, ou seja, já irá buscar suas propriedades definidas.

Genexus Web Panel

Nesta WebPanel iremos criar 21 variáveis, estas variáveis deverão ser apresentadas em Tela, na Form do objeto. As variáveis serão:
  1. Xis (Numeric(4)): placar do jogador da figura X;
  2. Circulo (Numeric(4)): placar do jogador da figura O;
  3. Contador (Numeric(4)): irá contar a quantidade de cliques realizados;
  4. um (Bitmap): variável posicionada na primeira célula da tabela;
  5. dois (Bitmap): variável posicionada na segunda célula da tabela;
  6. tres (Bitmap): variável posicionada na tereira célula da tabela;
  7. quatro (Bitmap): variável posicionada na quarta célula da tabela;
  8. cinco (Bitmap): variável posicionada na quinta célula da tabela;
  9. seis (Bitmap): variável posicionada na sexta célula da tabela;
  10. sete (Bitmap): variável posicionada na sétima célula da tabela;
  11. oito (Bitmap): variável posicionada na oitava célula da tabela;
  12. nove (Bitmap): variável posicionada na nona célula da tabela;
  13. umNome (Character(20)): irá reter o nome da imagem associada à variável um;
  14. doisNome (Character(20)): irá reter o nome da imagem associada à variável dois;
  15. tresNome (Character(20)): irá reter o nome da imagem associada à variável tres;
  16. quatroNome (Character(20)): irá reter o nome da imagem associada à variável quatro;
  17. cincoNome (Character(20)): irá reter o nome da imagem associada à variável cinco;
  18. seisNome (Character(20)): irá reter o nome da imagem associada à variável seis;
  19. seteNome (Character(20)): irá reter o nome da imagem associada à variável sete;
  20. oitoNome (Character(20)): irá reter o nome da imagem associada à variável oito;
  21. noveNome (Character(20)): irá reter o nome da imagem associada à variável nove;
Programando os Eventos

Bom, a idéia inicial é: teremos variáveis strings que irão controlar cada imagem do jogo, estão variáveis irão começar o jogo vazias, isto é sem xis e sem círculos. Por isso a quarta imagem criada no Paint (tela em branco) foi adicionada ao nosso projeto com o nome "Vazio". 

Como apenas 11 das 21 variáveis precisam ficar visíveis, as demais foram adicionadas dentro de uma outra tabela, e esta tabela nós deixamos invisível.
Event Start
//=====Inicializa variáveis nome da imagem como "Vazio"=====
&umNome = 'Vazio'
&doisNome = 'Vazio'
&tresNome = 'Vazio'
&quatroNome = 'Vazio'
&cincoNome = 'Vazio'
&seisNome = 'Vazio'
&seteNome = 'Vazio'
&oitoNome = 'Vazio'
&noveNome = 'Vazio'

//=====Inicializa contador de cliques e placar=====
&Contador = 0
&Xis = 0
&Circulo = 0

//=====Tabela com as variáveis de controle invisivel=====
TableVariaveis.Visible = 0
EndEvent
Agora, cada variável Bitmap irá conter um evento de Click. Neste evento iremos detectar se a sua variável de controle é "Vazio". Caso sim, iremos incrementar a variável de controles de cliques, e dividi-la por 2.

Se o resto desta divisão for 1, quem está clicando é o 1º jogador. Se o resto for igual a 0, quem está clicando será o segundo jogador.
Event &um.Click
//=====Se variável nao estiver definida (circulo ou xis)=====
if &umNome = 'Vazio'
//=====Controla nº de cliques=====
&Contador += 1

//=====Controla qual jogador clicou=====
if Mod(&Contador,2) = 1
&umNome = 'Xis'
else
&umNome = 'Circulo'
endif
endif
EndEvent
Bom, é no Evento Refresh que iremos utilizar o método "FromImage()", nesse caso, cada variável Bitmap esta recebendo como imagem a sua variável de controle. Esta variável de controle irá conter "Vazio" ou "Xis" ou "Circulo" (nome das variáveis adicionadas ao projeto).

Ainda neste evento, realizamos o controle de ganhador. Por exemplo, se o nome das variáveis de controle umNome, doisNome e tresNome forem iguais, algum jogador fechou a 1ª linha. Se houver ganhador a SubRotina "Fim" será realizada.
Event Refresh
//=====Define imagem para cada variável Bitmap=====
&um.FromImage(&umNome)
&dois.FromImage(&doisNome)
&tres.FromImage(&tresNome)
&quatro.FromImage(&quatroNome)
&cinco.FromImage(&cincoNome)
&seis.FromImage(&seisNome)
&sete.FromImage(&seteNome)
&oito.FromImage(&oitoNome)
&nove.FromImage(&noveNome)

//=====Controle se houve ganhador=====
do case
case &umNome <> 'Vazio' and &umNome = &doisNome and &umNome = &tresNome
&Ganhador = &umNome
do 'Fim'
case &umNome <> 'Vazio' and &umNome = &quatroNome and &umNome = &seteNome
&Ganhador &umNome
do 'Fim'
case &umNome <> 'Vazio' and &umNome = &cincoNome and &umNome = &noveNome
&Ganhador &umNome
do 'Fim'
case &doisNome <> 'Vazio' and &doisNome = &cincoNome and &doisNome = &oitoNome
&Ganhador = &doisNome
do 'Fim'
case &tresNome <> 'Vazio' and &tresNome = &seisNome and &tresNome = &noveNome
&Ganhador = &tresNome
do 'Fim'
case &tresNome <> 'Vazio' and &tresNome = &cincoNome and &tresNome = &seteNome
&Ganhador = &tresNome
do 'Fim'
case &quatroNome <> 'Vazio' and &quatroNome = &cincoNome and &quatroNome = &seisNome
&Ganhador = &quatroNome
do 'Fim'
case &seteNome <> 'Vazio' and &seteNome = &oitoNome and &seteNome = &noveNome
&Ganhador = &seteNome
do 'Fim'
endcase
EndEvent

Sub 'Fim'
//=====Mensagem de Fim de Jogo=====
msg('Fim de jogo, o '+&Ganhador.Trim()+' é o vencedor!')
//=====Marca Placar=====
if &Ganhador = 'Xis'
&Xis += 1
else
&Circulo += 1
endif

//=====Desabilita variáveis Bitmap=====
&um.Enabled = 0
&dois.Enabled = 0
&tres.Enabled = 0
&quatro.Enabled = 0
&cinco.Enabled = 0
&seis.Enabled = 0
&sete.Enabled = 0
&oito.Enabled = 0
&nove.Enabled = 0
EndSub
Abaixo, iremos adicionar os eventos dos botões "Novo Jogo" e "Zerar Placar":
Event 'NovoJogo'
//=====Inicializa variáveis nome da imagem como "Vazio"=====
&umNome = 'Vazio'
&doisNome'Vazio'
&tresNome'Vazio'
&quatroNome'Vazio'
&cincoNome'Vazio'
&seisNome'Vazio'
&seteNome'Vazio'
&oitoNome'Vazio'
&noveNome'Vazio'

//=====Inicializa contador de cliques e placar=====
&Contador = 0

//=====Habilita variáveis Bitmap=====
&um.Enabled = 1
&dois.Enabled = 1
&tres.Enabled = 1
&quatro.Enabled = 1
&cinco.Enabled = 1
&seis.Enabled = 1
&sete.Enabled = 1
&oito.Enabled = 1
&nove.Enabled = 1
EndEvent

Event 'ZerarPlacar'
//=====Zera variáveis do Placar=====
&Xis = 0
&Circulo = 0
EndEvent
Era isso pessoal, agora é só compilar e testar!! Abraço.