===============
xMova - JS
===============
O projeto xMovaJS é um framework para criar aplicativos móveis usando JSON e JavaScript.
===
API
===
---------------
Modelo de Dados
---------------
O xMova interpreta o modelo de dados para criar as telas do fluxo. No modelo define-se todas as entidades
e seus campos. Em cada entidade e campo pode-se definir atributos e eventos.
Formato
=======
O modelo é definido da seguinte forma:
**Model JS**::
{
app:{
id:7885,
name:'Nome do Aplicativo',
version:'1.0.53',
intVersion:37,
appCode:'L',
dynamicQuery:1,
serverUrl:'http://xmova-server-dev.simova.ws/serverjs/m',
thirdServerUrl:'http://url.do.app/',
screens:{
Main:{
type:'main', fields:['descricaoFilial'],
actions: {
Entidade1: {type:'Main', position:'Menu'},
Sincronizar: {event:'sync()'},
Limpar: {event:'dropDbAndExit()'},
Sair: {type:'Back', position:'Menu', event:'exit()'}
}
}
}
},
entities:{
Auth:{
fields:{
idFilial: {fk:'Filial'}
}
},
AuthInput:{
fields:{
id:{},
idFilial: {fk:'Filial'},
descricaoFilial: {type:'text', autoFill:'this.idFilial.descricao'}
}
},
Teste:{
fields:{
id: {},
campo1: {}
}
},
Filial:{
label:'Filial',
fields:{
id: {},
descricao: {type:'text'}
}
}
},
lang:{
AuthInput:'Configuração',
AuthInput_descricaoFilial:'Filial'
}
}
Tipo de Sincronismo da Entidade
===============================
Em cada entidade pode-se definir o tipo de sincronismo. Quando o app faz um sync com o servidor
cada entidade será analisada para verificar se os dados dela serão enviados ou recebidos do servidor,
ou se a entidade será ignorada no sync.
``sync:'in'``: O servidor retornará os dados desta entidade em todos os sync Foreground.
``sync:'out'``: Em todos os Sync, Foreground ou Background, os dados dessa tabela serão enviados ao servidor.
``sync:['in', 'install']``: O servidor retornará os dados desta entidade apenas no primeiro sync ANTES da
instalação do app. Serve para fluxos em que seja necessário exibir lista de opções durante o processo
de configuração inicial do fluxo.
=======
EVENTOS
=======
------------------
Eventos Principais
------------------
**Model JS**:
**Sincronizar** ``sync()``: ::
{event:'sync()'}
**Sair** ``exit()``: ::
{event:'exit()', type:'Back'}
**Limpar** ``dropDbAndExit()``: ::
{event:'dropDbAndExit()'}
-------------------
Eventos de Entidade
-------------------
``afterFinish``: Evento chamado após finalizar o preenchimento de uma entidade. Quando o evento terminar, o fluxo precisa chamar crud.afterFinish()
**App JS**::
Nome_da_Entidade.afterFinish: crud
... ...
crud.afterFinish();
``afterSave``: Evento chamado após finalizar o preenchimento de uma entidade.
``beforeSave``: Evento chamado antes de salvar um registro da entidade.
``onOpenMenu``: Evento chamado ao abrir um menu. Quando o evento terminar, o fluxo precisa chamar crud.showMenu().
**App JS**::
Nome_da_Entidade.onOpenMenu_: crud
... ...
crud.showMenu();
``onShowInfo``: Evento usado para alterar a barra de info na entidade e em seus campos, conforme eles são exibidos. Caso seja passado null para o afterOnShowInfo, a barra não é exibida.
**App JS**::
Nome_da_Entidade.onShowInfo_: mgrs
... ...
mgrs.afterOnShowInfo('Texto informativo');
----------------
Eventos de Campo
----------------
Note que quando os eventos são em background (simbolizados por terem um underline no fim do nome do evento), o retorno deve ser feito através de mgr.resume('valor');
``autoFill``: Preenchimento automático do campo com o valor retornado. Se tiver autoFill, pula a fase Fill.
**App JS**::
Nome_da_Entidade.nome_do_campo.autoFill: mgr, crud
return 1000;
Nome_da_Entidade.nome_do_campo2.autoFill_: mgr, crud
mgr.resume(1000);
``condition``: Condição de preenchimento do campo. Se a condição retornar "false", passa ao proximo campo. Se não for um método com callback, o retorno padrao é "true", e o campo deve ser preenchido.
**App JS**::
Nome_da_Entidade.nome_do_campo.condition: mgr, crud
if (*condição de preenchimento*) {
return true;
} else {
return false;
}
Nome_da_Entidade.nome_do_campo.condition_: mgr, crud
if (*condição de preenchimento*) {
mgr.resume(true);
} else {
mgr.resume(false);
}
``defaultValue``: Pré-preenchimento do campo com o valor retornado. Se tiver defaultValue, o valor é apresentado, e pode ser editado.
**App JS**::
Nome_da_Entidade.nome_do_campo.defaultValue: mgr, crud
return 1000;
Nome_da_Entidade.nome_do_campo.defaultValue_: mgr, crud
mgr.resume(1000);
``validation``: Validação do valor preenchido para campo. Se a validação retornar "false", não continua, volta ao campo anterior. Se não for um método com callback, o retorno padrao é "true", a validação foi com sucesso.
**App JS**::
Nome_da_Entidade.nome_do_campo.validation: mgr, crud, value
if (entry) {
return false;
}
Nome_da_Entidade.nome_do_campo.validation_: mgr, crud, value
if (entry) {
mgr.resume(false);
}
``onLoadSrcHtml``: Preparação do Html a ser exibido.
**App JS**::
Nome_da_Entidade.nome_do_campo.onLoadSrcHtml: mgr, crud, entry
var html = '
';
model.UltimoApontamento.dao().last({delegate:this, callback:function(entry) {
if (entry) {
html += ' Último Apontamento |
';
html += ' OS: | ' + entry.os + ' |
';
html += ' Operação: | ' + entry.operacao + ' |
';
html += ' Data: | ' + entry.data + ' |
';
} else {
html += 'Não encontrou último apontamento! |
';
}
}});
html += '
';
Nome_da_Entidade.nome_do_campo.onLoadSrcHtml_: mgr, crud, entry
var html = ' ';
model.UltimoApontamento.dao().last({delegate:this, callback:function(entry) {
if (entry) {
html += ' Último Apontamento |
';
html += ' OS: | ' + entry.os + ' |
';
html += ' Operação: | ' + entry.operacao + ' |
';
html += ' Data: | ' + entry.data + ' |
';
} else {
html += 'Não encontrou último apontamento! |
';
}
}});
html += '
';
mgr.resume(html);
----------------
Eventos de Lista
----------------
``onEntityListQueryPrepare``: Preparação da lista filtrando por relacionamento entre entidades.
**App JS**::
Nome_da_Entidade.nome_do_campo.onEntityListQueryPrepare: mgr, crud, queryParams
queryParams.sql = 'SELECT t.* FROM Entidade1 AS e1 JOIN Entidade2 AS e2 on e1.id = e2.id_campo_entidade_1 WHERE e2.id_campo_entidade_2=' + this.id_campo_entidade_2.id;
``onFilterListEntry``: Preparação da lista filtrando registros por campo.
**App JS**::
Nome_da_Entidade.nome_do_campo.onFilterListEntry: mgr, crud, entry
if (entry.campo_a_ser_filtrado) {
return false;
}
``onListEntries``: Preparação de uma nova lista com os registros desejados.
**App JS**::
Nome_da_Entidade.nome_do_campo.onListEntries: mgr, crud, delegate, callback
model.Entidade2.dao().list({delegate:this, callback:function(list1) {
var list2 = [];
for (var i = 0; i < list1.length; i++) {
var entry = list1[i];
if (!entry.campo_a_ser_filtrado) {
list2.push(entry);
}
}
callback.call(delegate, list2);
}});
=========
ATRIBUTOS
=========
---------------------
Atributos de Entidade
---------------------
``confirmCreate``: Confirma criação da entidade. Se não houver o atributo confirmCreate, será mostrada a mensagem para confirmar a criação. Para retirar a mensagem, utilizar **confirmCreate:0**.
``confirmFinish``: Confirma finalização da entidade. Se não houver o atributo confirmFinish, será mostrada a mensagem para confirmar a finalização. Para retirar a mensagem, utilizar **confirmFinish:0**.
``descriptionFields``: Descrição do campo. Se não houver o atributo descriptionFields, a descrição é preparada com o primeiro campo INT que nao seja o ID se houver, mais o primeiro campo String se houver.
``extName``: Substitui o nome da entidade para enviar ao servidor.
``info``: Mostra informação no topo da tela. Utilizar **info:'Nome_da_Entidade'**, E na entidade adicionar o campo **info: {type:'text'}** que conterá a mensagem a ser exibida no topo da tela.
``label``: Texto que será exibido ao chamar o campo ou entidade.
``verifyRequired``: Verifica se tem registro no banco de dados. O atributo verifyRequired deve ser adicionado a entidade sync:out que será preenchida, para verificar se há alguma entidade do tipo sync:in que está sem dados. Nas entidades sync:in que devem ser verificadas, deve ser adicionado o atributo **required:1**. Caso alguma entidade obrigatoria esteja vazia, exibe uma mensagem ao usuario e impede o fluxo de prosseguir.
------------------
Atributos de Campo
------------------
Tipo de Campo
=============
Caso o tipo não seja definido, por default será considerado um campo númerico.
``type:'back'``: Utilizar com na tela **Main** junto com o evento para sair do aplicativo ``event:'exit()'``.
``type:'main'``: Utilizar com na tela para definir a entiade do tipo **Main**.
``type:'custom'``: HTML. Utilizar o evento **onLoadSrcHtml** para preparação o HTML a ser exibido.
``type:'lines'``: Campo de texto com multiplas linhas.
``type:'text'``: Campo de texto.
Atributos de Exibição
=====================
``position``: Posição do campo na tela **Main**. Pode ser definida como: 'Menu', 'Bar', 'Hidden'.
``addFixedOptions:1``: Usada para definir que as opções fixas do Crud menu devem ser adicionadas após esta opção.
Condição de Preenchimento do Campo
==================================
``fill:'no'``: Pula o preenchimento do campo.
``fill:'finish'``: Pede o preenchimento do campo no processo de finalização da entidade.
``fill:'manual'``:
Numeral
=======
**Campos com nome Padrão**
``id``: Não é pedido o preenchimento para o usuário. É um campo númerico com valor incremental para cada entidade.
``date``: Se o campo inicia com "date", não é pedido o preenchimento para o usuário. É um campo númerico cujo o valor será a data atual em milissegundos.
``onlineFlagInicial``: Se o campo inicia com "onlineFlag", não é pedido o preenchimento para o usuário. O campo númerico será preenchido no momento do sincronismo com os valores: 1 (online), 0 (offline).
``uuid``: Gera identificador único.
``decimal``: Defini o número de digitos da parte fracionária (à direita do separador).
``formatThousand``: Formatação de milhar no campo numérico. Para retirar a formatação, adicionar o atributo ``formatThousand:0``.
``maxLength``: Defini o tamanho máximo de casas decimais
Texto
=====
``upperCase``: Formatação do texto com letras maiusculas.
Lista
=====
``label``: Defini o texto que será apresentado ao mostrar o campo.
``list``: Defini o campo como um item de menu que deve ser listado no menu da entidade em questão, após a criação da mesma. O atributo ``list:1`` deve ser usado indicando a entidade a ser preenchida com ``fk:nome_da_entidade``.
``search``: Defini o campo que será usado para busca numa lista.
**Model JS**::
Nome_da_Entidade :{
sync:'out',
extName:'Apontamento',
info:'UltimoApontamento',
label:'Apontar',
confirmCreate:0,
confirmFinish:0,
verifyRequired:1,
fields:{
id: {},
date: {},
onlineFlag: {},
idSeq: {uuid:1},
campo_nao_pedido: {fill:'no'},
campo_texto: {type:'text', upperCase:1, label:'Texto simples'},
campo_texto_multilinha: {type:'lines', fill:'manual',defaultValue:'texto inicial'},
campo_validacao_online: {onlineValidate:{name:'Metodo_de_validacao', block:1}},
campo_inteiro_ou_long: {autoFill:10},
campo_fixed_point: {onlyConfirm:true, saveAppState:true, label:'Confirma chegada?'},
campo_decimal: {decimal:2, maxLength:9, formatThousand:0},
campo_assinatura: {fk:'Binary', signature:1, condition:'this.campo_inteiro_ou_long > 10'},
campo_foto: {fk:'Binary', picture:1},
campo_foto: {fk:'Binary', list:1},
campo_html: {type:'custom'},
campo_entidade: {fk:'Outra_Entidade', fill:'finish'}
},
crudMenuActions:{
campo: {}
}
},
Outra_Entidade:{
sync:'in',
label:'Outra Entidade',
required:1,
descriptionFields:['codigo','descricao'],
fields:{
id: {},
codigo: {search:1, label:'código'},
descricao: {type:'text'}
}
}
===============
FUNCIONALIDADES
===============
-----
Dates
-----
Formata a data(UTC) em milliseconds para String. Pode ser chamado direto pelo app e model.
``formatUTCTimeDate``: Retorno no padrao: HH:mm:ss DD/MM/YYYY
**App JS**::
var dataStr = Dates.formatUTCTimeDate(dateField);
``formatUTCDateTime``: Retorno no padrao: DD/MM/YYYY HH:mm:ss
**App JS**::
var dataStr = Dates.formatUTCDateTime(dateField);
``formatUTCDate``: Retorno no padrao: DD/MM/YYYY
**App JS**::
var dataStr = Dates.formatUTCDate(dateField);
``formatUTCTime``: Retorno no padrao: HH:mm
**App JS**::
var dataStr = Dates.formatUTCTime(dateField);
-----------
Fixed Point
-----------
**Model JS**::
Nome_da_Entidade:{
sync:'out',
fields:{
id: {},
fixedPoint: {onlyConfirm:true, saveAppState:true, label:'Confirma chegada?'}
}
}
----
Info
----
**Model JS**::
Nome_da_Entidade:{
sync:'out',
info:'UltimoApontamento',
fields:{
id: {},
campo_crud: {fk:'ApontamentoServico', list:1, label:'Serviço', info:'UltimoApontamento'}
}
}
--------
Location
--------
**Campos enviados**: *long*, *lat*, *alt*, *gpsTime*, *time*
**Model JS**::
Nome_da_Entidade:{
sync:'out',
fields:{
id: {},
location: {fk:'Location'}
}
}
-------
Picture
-------
**Model JS**::
Nome_da_Entidade:{
sync:'out',
fields:{
id: {},
binaryId: {fk:'Binary', picture:1}
}
}
---------
Signature
---------
**Model JS**::
Nome_da_Entidade:{
sync:'out',
fields:{
id: {},
binaryId: {fk:'Binary', signature:1}
}
}
-------------
Crud
-------------
``crud``: gera um novo registro da entidade passada como atributo
**App JS**::
crud(entity, delegate);
entity: entidade do modelo para criar o registro
delegate: quem irá executar o callback(onCrudFinish)
Exemplo:
Main.Boletim:
crud(model.Boletim);
``crudFields``: preenche apenas os campos da entidade que foram especificados em 'fieldsNames'
**App JS**::
crudFields(entity, entry, fieldsNames, delegate, callback);
entity: entidade do modelo para criar o registro
entry: registro a ser preenchido, ou null se quiser que seja criado um registro
fieldsNames: array de nomes que deseja que sejam preenchidos Exemplo: ['id', 'date']
delegate: quem irá executar o callback
callback: função que deverá ser chamada quando o crud finalizar o preenchimento, pode ser definido também no delegate com o listener de nome onCrudFinish
Exemplo:
Boletim.onOpenMenu_: crudController
this.onCrudFinish= function(entry, crud) {
crudController.showMenu();
};
var entry = {name: 'test'};
var c = crudFields(model.entity, entry, ['id', 'date', 'onlineFlag', 'location'], this);
-------------
Criação Dados
-------------
``installData``: Deve ser escrido alternando aspas duplas para os valores e aspas simples para o sql.
**Model JS**::
installData:[
'INSERT INTO Nome_da_Entidade VALUES(1,"descricao_do_campo")'
]
====
LANG
====
É possivel modificar os titulos, labels e mensagens padrão do fluxo, para isso é usado o atributo lang do sistema.
Exemplo de entidades:
**Model JS**::
Turno:{
sync:'out', extName:'Boletim',
fields:{
id: {},
idSeqBoletim: {uuid:1},
dateAbertura: {},
onlineFlagInicial: {},
location: {fk:'Location'},
apontamentoOS: {fk:'ApontamentoOS', list:1, label:'OS'},
apontamentoTG: {fk:'ApontamentoTG', list:1, label:'Tarefas Gerais'}
dateFechamento: {fill:'finish'},
onlineFlagFinal: {fill:'finish'},
}
},
ApontamentoDeslocamento:{
sync:'out',
fields:{
id: {},
apontamentoOS: {fk:'ApontamentoOS'},
idSeqBoletim: {type:'text', autoFill:'this.apontamentoOS.idSeqBoletim'},
idSeqOS: {type:'text', autoFill:'this.apontamentoOS.idSeqOS'},
idOS: {type:'text', autoFill:'this.apontamentoOS.idOS'},
idSeqApontamento: {uuid:1},
dateSaida: {},
onlineFlagSaida: {},
location: {fk:'Location'},
idModal: {fk:'Modal'},
idTipoTransporte: {fk:'TipoTransporte', label:'Tipo de Transporte'},
fornecedor: {fk:'Fornecedor', label:'Fornecedor', condition:'this.idTipoTransporte.fgFornecedor == 1'},
placa: {type:'text', upperCase:1, label:'Placa', condition:'this.idTipoTransporte.fgPlaca == 1', maxLength:250},
kmAnterior: {decimal:2, maxLength:9, label:'Km Anterior', formatThousand:0},
kmSaida: {decimal:2, maxLength:9, label:'Km Saída', formatThousand:0, condition:'this.idTipoTransporte.fgKM == 1', validation:'this.kmSaida > 0'},
idLocalSaida: {fk:'Local', label:'Local Saída'},
chegou: {onlyConfirm:true, saveAppState:true, label:'Confirma chegada?'},
idLocalChegada: {fk:'Local', label:'Local Chegada'},
kmChegada: {decimal:2, maxLength:9, label:'Km Chegada', formatThousand:0, condition:'this.idTipoTransporte.fgKM == 1'},
dateChegada: {condition:'this.chegou == 1'},
onlineFlagChegada: {condition:'this.chegou == 1'},
opcoesEscolhaOS: {fk:'OpcoesEscolhaOS', label:'Finalizar deslocamento e:'}
}
},
Exemplo de Lang:
**Model JS**::
lang:{
ApontamentoDeslocamento:'Deslocamento',
ApontamentoDeslocamento_idModal:'Modal',
ApontamentoDeslocamento_idTipoTransporte:'Tipo de transporte',
ApontamentoDeslocamento_chegou_input:'Confirma Chegada?',
ApontamentoDeslocamento_chegou_confirm:'Sim',
Turno_MsgCreateConfirm:'Confirma abertura de turno?',
Turno_MsgFinishConfirm:'Confirma fechamento de turno?',
Turno_LblFinish:'Finalizar/Pausar OS',
VerifyEmptyMessage:'O apontamento não poderá ser realizado pois o cadastro de está vazio.',
VerifyEmptyMessagePlural:'O apontamento não poderá ser realizado pois os cadastros de estão vazios.',
codigoTecnico_MsgOnlineValidateFail:'Matricula inválida para filial selecionada.'
}
``Titulo da Entidade``: Usado para alterar o titulo do menu da entidade, similar a colocar o atributo 'label' na entidade.
**Model JS**::
NomeDaEntidade:'Titulo da Entidade',
``Titulo do Campo``: Usado para alterar o titulo de um campo da entidade, exibido conforme este é preenchido. Similar a colocar o atributo 'label' no campo.
**Model JS**::
NomeDaEntidade_campo:'Campo da Entidade',
``Confirmação de criação``: Usado para alterar o texto na tela de confirmação de criação da entidade.
**Model JS**::
NomeDaEntidade_MsgCreateConfirm:'Confirma a criação da entidade?',
``Confirmação de finalização``: Usado para alterar o texto na tela de confirmação de finalização da entidade.
**Model JS**::
NomeDaEntidade_MsgCreateConfirm:'Confirma a finalização da entidade?',
``Label de finalização``: Altera o texto da opção de "Finalizar Entidade" do menu.
**Model JS**::
NomeDaEntidade_LblFinish:'Fechar menu de Entidade',
``Falha no sincronismo``: Altera o texto exibido quando ocorre algum erro no sincronismo de dados com o servidor. Usado junto com o atributo required das entidades.
**Model JS**::
VerifyEmptyMessage:'O apontamento não poderá ser realizado pois o cadastro de está vazio.',
VerifyEmptyMessagePlural:'O apontamento não poderá ser realizado pois os cadastros de estão vazios.',
``Falha na validação``: Altera o texto exibido num toast quando ocorre um erro na validação de um campo.
**Model JS**::
campoEntidade_MsgOnlineValidateFail:'Opção invalida selecionada.'
================
VALIDAÇÃO ONLINE
================
O xMova pode fazer validação online dos valores inseridos nos campos de uma entidade.
Basta adicionar ao campo o atributo ``onlineValidate``.
**Model JS**::
campo: {onlineValidate:{name:'Metodo_de_validacao', block:1}}
Retorno de Dados Validados
==========================
O sistema de terceiro deve retornar os seguites status:
* Sucesso: ``status=0``
* Erro: ``status=1``
* Falha: ``status>=2``
* Não autorizado: ``status=4``