Bom, ilustrações fonográficas à parte, quando se trata de um sistema precisamos de gerar vários regitros com qualquer tipo de informação contanto ele preencha certos requisitos. Por exemplo: o cpf tem que ser válido.
Incluimos no YeAPF 0.8.61-170 uma pequena função que pode fazer a diferença na hora de criar esses dados: fillFieldsWithJunk()
Você pode usa-la para criar apenas um único campo ou um registro inteiro.
Mas um exemplo pode ser mais util que mil palavras. Digamos que quero gerar um registro com dados aleatórios. Isto (que chamarei de testar-geracao-dados.php) resolve:
require_once "yeapf.php";
$campos = array(     
  array(
      "id" => "nome",
      "type" => "text",
      "className" => "male name",
      "maxlength" => "25"
    ),
    array(
      "id" => "cpf",
      "type" => "text",
      "className" => "cpf"
    ),
    array(
      "id" => "endereco",
      "type" => "text",
      "maxlength" => "70"
    ),
    array(
      "id" => "site",
      "type" => "url"
    ),
    array(
      "id" => "telefone",
      "type" => "tel"
    ),
    array(
      "id" => "email",
      "type" => "email"
    ),
    array(
      "id" => "cep",
      "type" => "text",
      "className" => "cep-cliente"
    )
  );
/* gero os dados */
$dados = fillFieldsWithJunk($campos);
/* imprimo na tela */
print_r($dados);
Agora, desde a linha de comando executamos ele usando o php
$ php testar-geracao-dados.php
Pronto, cada vez que rodemos, obteremos um novo conjunto de dados.
O seguinte exemplo geraremos esses dados em JSON. Pelo bem da simplicidade apenas mostraremos as linhas modificadas (que são as últimas)
/* gero os dados */ $dados = fillFieldsWithJunk($campos); /* imprimo na tela como JSON */ echo json_encode($dados);
E finalmente, faremos um teste preenchedo 2378 registros de uma tabela que chamaremos clientes (foje ao escopo deste artigo mostrar criação de tabelas, conexão com o banco de dados, etc)
Novamente, mostraremos as linhas modificadas que são as últimas:
$quantidadeRegistros = 2378;
while ($quantidadeRegistros-->0) {
  $dados = fillFieldsWithJunk($campos);
  $sql=save_form_sql($dados, "clientes", "id");
  db_sql($sql);
}
Pronto, seu banco já está cheio de…. bom, o que fillFieldsWithJunk() conseguir gerar.
]]>
Mas antes disso, é bom deixar claro como funciona ele sem instalar.
A todos os efeitos, vamos supor que você fez download da última versão do YeAPF e o colocou na pasta ~/Downloads/YeAPF/ e que o usuário no qual o Apache2 roda, chama-se www-data
Caso você queira usar o YeAPF apenas do lado do servidor (mesmo que depois vá a consumir sua API com ou sem YeAPF ou que vá a construir uma serie de páginas semi-estáticas) a forma mais simples de fazer isso é copiando alguns arquivos e a pasta includes dentro do seu aplicativo.
$ cd /var/www/html $ mkdir -p MeuAplicativo/includes $ cd MeuAplicativo $ rsync -rvt ~/Downloads/YeAPF/includes/* includes/ $ cd ~/Downloads/YeAPF/skel/webApp/ $ cp index.php body.php configure.php yeapf.db.ini /var/www/html/MeuAplicativo/ $ cd /var/www/html $ chown -fR www-data.www-data MeuAplicativo
Feito isto, você modifica o yeapf.db.ini para indicar como é sua conexão ao banco de dados e depois chama o configure.php. Se o configure tem direitos suficientes para escrever na pasta /var/www/html/MeuAplicativo/ então seu aplicativo está pronto para ser produzido/usado.
Você pode instalar as ferramentas do YeAPF e usa-las para criar seu aplicativo
$ cd ~/Downloads/YeAPF/tools $ sudo ./install.sh
Agora a criação de um aplicativo
$ cd /var/www/html $ yapp MeuAplicativoSimples --create --appType --webApp --template bs4
As ferramentas abrangem três secções claramente diferenciáveis:
Na gestão de aplicativos, temos alguns scripts que ajudam na construção e manutenção dos aplicativos
| yapp | permite criar e atualizar aplicativos usando a linha de comandos | 
| ydbgflags | para gestionar as bandeiras de depuração e registro | 
| ydbviewconfig | serve para visualizar o jeito em que a pasta está configurada | 
| ysetdbconn | permite mudar a configuração da conexão com o banco pela linha de comando | 
No ajudante de desenvolvimento mobile temos as seguintes ferramentas. Os nomes nem sempre são os melhores pois às vezes não usamos o adb e sim apenas o cordova. Mas ficou assim e vamos enfrente.
| adb-build | Serve para construir um aplicativo cordova | 
| adb-compile | Serve para compilar (não limpar) um aplicativo cordova | 
| adb-debug | Permite ver o console do aplicativo construido com cordova (precisa adb) | 
| adb-install | Instala um aplicativo cordova no dispositivo conectado (fisico ou virtual. Precisa adb) | 
| adb-newversion | Incrementa o numero pequeno de versão de um aplicativo cordova. É compatível com Google Play Store | 
| adb-photo | Tira uma foto do aplicativo rodando no dispositivo (precisa adb) | 
| adb-release | Aumenta o numero grande de versão, e compila o aplicativo cordova. | 
| adb-run | Executa o aplicativo no dispositivo (requer cordova) | 
| adb-set-chrome-debug | Levanta ou Baixa a bandeira de depuração no APK criado com cordova. Serve apenas para KitKat e superior. | 
| adb-uninstall | Desinstala um APK do dispositivo. | 
Finalmente no grupo de ferramentas de uso geral temos algumas de poder variado
| ycheckproject | Verifica se todos os arquivos dentro de uma pasta estão com o charset desejado | 
| yconvertcharset | Converte uma pasta inteira de ISO-8859-1 para UTF8 substituindo as acentuações por entidades html (Quase que estou marcando ele como obsoleto)  | 
| ycreatewebappevent | Cria um gestor de evento numa webapp do lado do servidor | 
| ydbcreateform | Cria um formulario para fazer CRUD. Você pode usar uma tabela ou um comando sql para selecionar os campos que deseja criar. | 
| ydbmigrate | 
 A cereja do bolo. Exporta um banco para csv e sql. Importa arquivos csv, sql e txt. O txt pode ser um produto de uma conversão de PDF para TXT. Reconhece as colunas que ocupam varias linhas, títulos, rodapés, etc. Foi feito para importar arquivos da TUSS… e eles distribuem em PDF, ai já viu. Se você tem um TXT ou um CSV, mas não tem a estrutura da tabela, ele cria uma estrutura por aproximação e depois altera os tipos (e larguras) dos campos para melhor conter os dados entregues no arquivo de entrada. Pode fazer assim: Firebird -> MySql por exemplo usando um arquivo intermediário.  | 
]]>
Saladas são boas. Por isso o título mistura três coisas que já sozinhas são boas.
O node te permite escrever aplicativos do lado do servidor ou do cliente usando a mesma linguagem: JavaScript. Neste vamos usa-lo para criar um aplicativo do lado cliente com técnicas de web (HTML5, CSS3 e JS6). Esta aproximação nos permite ter acesso ao hardware local, coisa que com o navegador é impossível (e esperemos que continue assim)
Já o ElectronJS nos permite empacotar isso tudo e distribuir em multiplataforma. Ou seja, o mesmo código rodando em Windows, Linux, OSX, etc. Seria bom dar uma olhada aqui: https://electronjs.org/docs/tutorial/first-app
YeAPF uniformiza o jeito de acessar a informação, promove melhores padrões de desenvolvimento e permite integrar seu aplicativo com outros.
Aqui há um caminho apenas. Você pode escolher outra forma mas mostramos esta por ser a mais simples – desde nosso ponto de vista – de criar um aplicativo.
Partimos da base que tem o NPM instalado assim como as ferramentas do YeAPF.
Há duas formas de fazer isto. Use a que lhe seja mais conveniente.
$ cd ~/Documents $ mkdir MeuProjeto $ cd MeuProjeto $ npm init
Depois modifique o package.json para que main aponte para “main.js”.
Pode tb deixar do jeito que está que electron vai procurar por “index.js”
Depois instale o electron nessa pasta
$ npm install --save-dev electron
Agora coloque o aplicativo de exemplo do YeAPF nele
$ yapp ./ --create --appType electron
Finalmente rode o aplicativo
$ npm start
O mesmo efeito anterior, pode ser obtido com a seguinte sequencia de comandos:
$ cd ~/Documents $ yapp MeuSegundoProjeto --create --appType electron $ cd MeuSegundoProjeto $ npm install $ npm start
Se tudo deu certo, você terá um outro aplicativo aberto mostrando o conteúdo do index.html que foi colocado lá pelo YeAPF.
Mantendo ele aberto, você pode modificar o index.html e recarregar o aplicativo sem fecha-lo (ctrl-R, F5, etc) ao final das contas o que vc está rodando é um Chrome.
Se um arrepio correu pelas suas costas, é que vc já entendeu o potencial.
Se nada disso lhe deu nem tchum, talvez não saiba o complicado que é produzir software para mais de uma plataforma e – pior – que rode na primeira. Com um pouco mais de tempo chegará a observar a importância disto.
]]>Como já sabem, não podemos trazer uma tabela inteira para a tela a não ser que ela seja pequena. Com tabelas acima de 30, 50 registros a história muda e precisamos segmentar a puxada.
Com YeAPF isso é bem fácil de fazer bastando apenas fazer várias chamadas seguidas incrementando xq_start a cada chamada. Estamos preparando ainda o yinterface.js que permitirá fazer isso tudo sem se preocupar (puxada completa, paginação, formulários dinâmicos, etc) se bem que -ao meu ver- é uma prática desaconselhável.
Mas voltando ao problema, eu fiz a mudança solicitada e coloquei 300 registros por página divididos em puxadas de 50 registros. Isso permite ao usuário revisar linha por linha a planilha (de um total de mais de 1000 páginas) em blocos administráveis durante o dia.
Só que isso me deixou com um problema, eu precisava indicar a carga e não tinha criado um waitIcon para entreter o usuário enquanto os dados viajam pelo cyberespaço.
Fazer um waitIcon com YeAPF é bem fácil e relato isso neste post. Porém, o problema é que piscava entre as requisições y eso – sinceramente- me molesta.
Então a solução foi a seguinte:1) No html criei um waitIcon no inicio do body
<body>
  <div id='waitIcon'>
    <img src="img/carregando.gif" height="64px">
  </div>
  ...
</body>
Depois alterei o CSS para deixar ele fixo e permitir transições suaves
#waitIcon {
    position: fixed;
    right: 8px;
    top: 135px;
    z-index: 1000;
    display: none;
    transition: all 0.5s linear;
}
Pronto… sem graça e simples
]]>Para uma tabela única, o comando é o seguinte
~/www/YeAPF/tools/ydbcreateform --db 192.168.56.250:nossoConsultorio_teste --user esteban --pass senha --type mysqli --table clinicas --name "clinicas"
Ai modifiquei o ydbcreateform para que funcionasse com um comando sql. Neste caso a sintaxe fica assim:
~/www/YeAPF/tools/ydbcreateform --db 192.168.56.250:nossoConsultorio_teste --user esteban --pass senha --type mysqli --sql "select c.id, c.email, c.data_alteracao, c.status_clinica, c.pessoa_juridica, c.CNES, c.DDD, c.telefone, c.DDD_cel, c.telefone_cel, pj.CNPJ, pj.nome_fantasia, pj.razao_social, pj.tipo_logradouro, pj.endereco, pj.numero, pj.complemento, pj.cidade, pj.UF, pj.CNAE from clinicas c left join pessoas_juridicas pj on pj.id = c.pessoa_juridica" --name "clinicas"
Para salvar os dados, o programador precisa modificar o código produzido. Mas o restante, já está pronto.
Ele produz os mesmos arquivos: clinicas.php, clinicas.json, clinicas.form f_clinicas.html e js/clinicas.js
O programador não precisa usar todos eles.
Por exemplo, f_clinicas.html e clinicas.json são mutuamente excludentes. Ao passo que clinicas.json funciona junto com js/clinicas.js e o interface.js (que ainda não foi incluso na distribuição).
Assim, gerando uma boa tabela no seu banco (ou uma view, por exemplo) o CRUD está praticamente pronto.
]]>Esse é exatamente o jeito em que trabalhamos porque nos permite mantermos nossas bases de testes separadas por individuo ou testarmos as coisas juntos dependendo do momento.
Mas aí me encontrei com o problema de ter que puxar a base, definir a conexão de novo… Puxar a base e restaurar no outro servidor não teve como fugir. Mas para a configuração acabei desenvolvendo uma ferramentinha que acho ficou bem útil: ysetdbconn.
Ela vai (a partir da versão 0.8.59-166) dentro da pasta tools e é instalada no seu sistema usando tools/install.sh como sempre.
1) A primeira forma de aplicação é quando migramos um projeto para uma pasta e queremos criar o yeapf.db.ini. Nesse caso, o processo é o seguinte:
$ cd www/meuApp $ ysetdbconn --db 192.168.1.78 --user esteban --pass teste --type mysqli
Isso vai criar um yeapf.db.ini mínimo com os campos preenchidos para estabelecer a conexão com seu banco
2) A segunda forma de aplicação é quando você já tem o yeapf.db.ini e deseja apenas mudar um ou vários campos. Nesse caso o processo fica assim:
$ cd www/meuApp $ ysetdbconn --update --dontWorkUntil 201804112359 --cfgDebugIP=192.168.1.7
Ou seja, podemos mudar qualquer valor do yeapf.db.ini apenas indicando seu nome seguido de um valor.
Só três coisas: 1) se o yeapf.db.ini já existe, deve usar –update para forçar a mudançca. 2) para mudar a conexão com o banco, tem que indicar todos os parámetros e no formato dado pelo –help (isso para evitar mudanças indesejadas) e 3) lembre que mudar o yeapf.db.ini não modifica sua conexão, para isso tem que usar o configure.php
]]>
function qTeste($a) {
  global $u, $xq_start;
  $useColNames = true;
  $xq_count=999;
  $ret='';
  // publish query variables as local variables
  extract(xq_extractValuesFromQuery());
  $xq_start=isset($xq_start)?intval($xq_start):0;
  switch($a) {
    case "puxarEstruturaDiretoria":
      $ret="select c.id, c.cargo, c.descricao,
                   o.cpf, o.nome
            from cargos c, ocupacao o
            where o.cargo=c.id
            order by cargo, nome";
      break;
      }
  }
  xq_produceReturnLines($ret, $useColNames, $xq_count);
}
Todavia, tem vezes em que precisamos (ou queremos) devolver uma estrutura hierárquica. É o caso quando temos uma tabela diretriz seguida de seus filhos e queremos trazer isso tudo de uma vez.
É obvio que isso não é recomendável para tabelas grandes, mas para pequenas (digamos até 200 registros na tabela filha) pode ser mais simples puxar tudo de uma vez.
É aqui que usar db_queryAndFillArray() pode ser de grande utilidade.
function qTeste($a) {
 global $u, $xq_start;
 $useColNames = true;
 $xq_count=999;
 $ret='';
 // publish query variables as local variables
 extract(xq_extractValuesFromQuery());
 $xq_start=isset($xq_start)?intval($xq_start):0;
 switch($a) {
   case "puxarEstruturaDiretoria":
     $sql="select cargo, descricao, id
           from cargos 
           where nivel<=2
           order by cargo";
     $listaCargos=db_queryAndFillArray($sql, 'cargo', false);
     // agora usamos a tabela de cargos para gerar -manualmente- o retorno 
     $ret=array();
     foreach($listaCargos as $cargo=>$infoC) {
       $idCargo = $infoC['id'];
       $ret[$cargo]=db_queryAndFillArray("select nome, cpf from ocupacao where cargo='$idCargo'", 'cpf');
     }
 
     break;
 }
  xq_produceReturnLines($ret, $useColNames, $xq_count);
}
Nem se fala que a primeira solução é mais simples de expressar e implementar. Também não é mais complicada na hora de receber os dados.
Todavia, em favor da segunda devemos dizer que às vezes o volume de informação que viaja na primeira, é maior que na segunda opção, já que cada linha inclui vários dados repetidos em vários registros que são hierarquicamente do mesmo nível.
Seja lá como for, você pode produzir resultados de forma diferente usando o db_queryAndFillArray()
Ele recebe tres parámetros: o sql, um string com os campos chaves (não do banco mas do vetor de retorno) e a possibilidade ou não de contar os registros que compõem o resultado (especialmente útil em funções de agregação)
]]>
São elas as que nos permitem uma mudança rápida na tela sem que por isso seja necessário carrega-las do servidor já que se encontram numa mesma e imensa página HTML5.
Uma das coisas bonitas que se podem fazer é reagir à mudança de forma mais automática. Ou seja, tipicamente o que costumamos fazer é mudar a tela pelo acionamento de um botão ou item de menu e nessa mudança puxamos os dados necessários para essa tela.
Nada contra essa aproximação, mas digamos que você construiu um pequeno framework sobre o YeAPF e quer esquecer das mudanças de telas, carregamento de tabelas e formulários (o CRUD bendito) mas quer uma forma simpática de fazer algum processo sem ter que hackear seu próprio e belo framework.
Uma forma fácil de fazer isso é respondendo aos eventos que o mTabNav gera no objeto window.
mTabNav dispara os seguintes eventos:
tabchange, tabblur, tabfocus e tabshow
Você pode se pendurar deles assim:
function myShowTabHandler() {
  alert("Aba mudada para "+mTabNav.getCurrentTabId());
}
addOnLoadManager(
  function() {
    window.addEventListener('tabshow', myShowTabHandler, true);
  }
);
Eu acho simples…
]]>
O YePAF inclui um exemplo na pasta samples/key-admin que pode ser usado como modelo para criar seus próprios gestores de chaves de forma tal que um dispositivo tenha ou não acesso a um recurso no serviço.
O propósito deste artigo é apenas mostrar como copiar e configurar ele para sua situação cabendo ao programador configurar bancos de dados e elementos de segurança necessários para o correto uso do mesmo. Também, cabe ao programador criar o código necessário para autenticar o dispositivo.
Digamos que seu projeto vai se chamar gestaoChaves. E que faremos um projeto webApp/bootstrap3
$ cd www $ yapp gestaoChaves --create --appType webApp --template bs3
Agora copiemos o exemplo para dentro da pasta
$ cp -r www/YeAPF/samples/key-admin/* www/gestaoChaves/
Modifique seu yeapf.db.ini para forçar um login controlado pelo arquivo .htpasswd na pasta. Por ser um projeto que visa a segurança e não requer o uso do banco de dados, indique que você utilizará a segurança fornecida pelo serviror web (Geralmente o Apache2) colocando a variável cfgHtPasswdRequired em ‘yes‘
Com isso, o seu aplicativo passará a exigir que as requisições sejamm feitas apenas usando SSL, ou seja, usando https em lugar de http. Escapa ao escopo deste artigo ensinar como configurar seu apache para operar sobre SSL, mas aqui pode encontrar um bom exemplo: http://www.onlamp.com/pub/a/onlamp/2008/03/04/step-by-step-configuring-ssl-under-apache.html
Rode o configure.php na pasta, lembrando que se já tem um db.csv, pode ser melhor destruir esse arquivo e deixar que o configure.php gere um novo a partir do yeapf.db.ini
Crie um arquivo .htaccess dentro da www/gestaoChaves com o seguinte conteúdo:
AuthType Basic AuthName "restricted area" AuthUserFile /var/www/html/gestaoChaves/.htpasswd require valid-user
Agora crie o arquivo /var/www/html/gestaoChaves/.htpasswd (Obvio que a pasta depende da sua distribuição e configuração local do servidor de páginas)
O conteúdo do .htpasswd pode ser gerado online neste atalho: http://www.htaccesstools.com/htpasswd-generator/
Altere os nomes dos arquivos que tem a palavra ‘default’ no nome pois eles serão sobre-escritos na atualização do YeAPF.
Assim, e_index_default.html vira e_index.html e keys.config.default.php vira keys.config.php por citar dois exemplos. Repita com os outros arquivos que tenham _default.
Fazendo assim, as suas versões do exemplo serão mantidas caso atualize a pasta usando rsync, cp ou unzip.
O arquivo labels.default.inc (que deve já ter sido renomado para labels.inc) possui todas as etiquetas que o aplicativo usa para identificar as diferentes partes do aplicativo para o usuário.
Por exemplo, a global lblProjects vem por padrão com o valor ‘Projects’ mas poderia ser chamado de ‘Secções’ pelo programador que seria isso que o usuário iria visualizar na tela.
Esses valores podem ser trocados a qualquer momento, então faça seus testes até ficar do jeito que você quer.
Internamente, porém, o aplicativo entende que são dispositivos dentro de um projeto. É por isso que no keys.config.php a nomenclatura interna é ‘Project’ e ‘Device’. Neste arquivo você controle os tamanhos das chaves geradas, só isso.
É responsabilidade do programador criar o serviço que serve as chaves e o cliente que as utilizará. Tanto faz se é um aplicativo desktop, web ou mobile.
A forma mais simples é por restful. Nesse caso seu cliente deve ser configurado para conectar-se com a pasta criada. Digamos que seu ip de serviço é 172.18.32.45 com um certificado ssl bem configurado (ou seja, não pode ser auto-assinado senão o consumidor não sai do lugar) o seu javascript na inicialização do projeto teria alguma coisa como:
ycomm.setDataLocation("https://172.18.32.45/gestaoChaves/rest.php");
Do lado do servidor, o programador pode utilizar algumas funções para verificar os valores passados pelo cliente.
| Função | Parametros | Funcionamento | 
|---|---|---|
| _projectExists() | projectKey | Devolve TRUE ou FALSE indicando se o projeto indicado existe | 
| _verifyDeviceExistsInProject() | projectKey deviceId  | 
Devolve TRUE ou FALSE para indicar se o dispositivo existe no projeto | 
| _registerDeviceIntoProject() | projectKey deviceId  | 
Registra um dispositivo no projeto | 
| _verifyDeviceBond() | projectKey deviceId deviceKey  | 
Devolve ‘Y’ se a chave de dispositivo é a gerada para o par (projectKey:deviceId) na tela de gestão | 
| _do_login | projectId deviceId  | 
Gera um identificador de sessão com o qual o dispositivo pode fazer suas requisições. | 
| _do_logoff | deviceId | Desconecta um dispositivo do sistema (mas sem perder as credenciais). Repare que não usa o sessionId gerado pelo _do_login | 
| _recreateDeviceKey | projectKey deviceId createSequence=false, &a &b  | 
Gera uma nova chave para o dispositivo. É o equivalente a clicar no botão de gerar chave de dispositivo na tela de gestão. | 
| 
 Os parâmetros createSequence, a e b servem para gerar (ou não) a sequência de controle. Essa sequência serve para controlar requisições de validação do cliente quando se está querendo evitar a clonagem de um nó em um ambiente de servidores distribuidos. Então em um aplicativo de autenticação pode ser obviado.  | 
||
]]>
Todavia, nem sempre isso resolve o problema de mostrar a informação de forma consistente. Pense no caso de ter varias pessoas com o mesmo nome inicial. Apenas cortar não resolve.
Então temos que abreviar.
YeAPF 0.8.56 inclui no String.prototype uma função chamada ‘abbreviate()’ que ajuda nestas situações.
Usando o yloader.js você pode fazer os seguintes testes no console:
> s="Ana Maria da Rocha Pereira"; < undefined > s.abbreviate(2) < "A." > s.abbreviate(10) < "Ana M. R.P." > s.abbreviate(15) < "Ana M. R.Pereira"
Esta é uma daquelas que também podem ser usadas com ycomm.dom.fillElement(). Então uma tabela poderia ficar assim:
<tbody>
  <tr>
    <td align=right>%(codigo)</td>
   <td>%abbreviate(nome, 30)</td>
  </tr>
</tbody>
Isso mais um pouco de controle no css pode fazer com que a informação mantenha a inteligibilidade (palavra complicada apenas para dizer que a pessoa lê e entende na hora) da informação
De outa forma (apenas com overflow: hidden por exemplo) pode facilitar a confusão.
]]>