Histórico da Página
...
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
{utp/ut-api.i} {utp/ut-api-action.i pFindById GET /byid/~* } {utp/ut-api-action.i pIdiomas GET /translations/~* } {utp/ut-api-action.i pFindAll GET /~* } {utp/ut-api-action.i pUpdateById PUT /~* } {utp/ut-api-action.i pGetMetadata POST /metadata/~* } {utp/ut-api-action.i pValidateForm POST /validateForm/~* } {utp/ut-api-action.i pValidateField POST /validateField/~* } {utp/ut-api-action.i pCreate POST /~* } {utp/ut-api-action.i pDeleteById DELETE /~* } {utp/ut-api-notfound.i} DEFINE TEMP-TABLE ttIdiomas NO-UNDO FIELD cod_idioma LIKE idioma.cod_idioma SERIALIZE-NAME "codIdioma" FIELD des_idioma LIKE idioma.des_idioma SERIALIZE-NAME "desIdioma" FIELD cod_idiom_padr LIKE idioma.cod_idiom_padr SERIALIZE-NAME "codIdiomPadr" FIELD dat_ult_atualiz LIKE idioma.dat_ult_atualiz SERIALIZE-NAME "datUltAtualiz" FIELD hra_ult_atualiz LIKE idioma.hra_ult_atualiz SERIALIZE-NAME "hraUltAtualiz" FIELD id AS RECID. /** Procedure que retorna a metadata **/ PROCEDURE pGetMetadata: DEFINE INPUT PARAMETER oJsonInput AS JsonObject NO-UNDO. DEFINE OUTPUT PARAMETER oJsonOutput AS JsonObject NO-UNDO. DEFINE VARIABLE oResponse AS JsonAPIResponse NO-UNDO. DEFINE VARIABLE oIdiomas AS JsonArray NO-UNDO. DEFINE VARIABLE oOpts AS JsonArray NO-UNDO. DEFINE VARIABLE oObj AS JsonObject NO-UNDO. DEFINE VARIABLE oOpt AS JsonObject NO-UNDO. ASSIGN oIdiomas = NEW JsonArray(). /* Define a lista de campos a serem apresentados no HTML */ ASSIGN oObj = NEW JsonObject(). oObj:add('property', 'codIdioma'). oObj:add('label', 'Idioma'"~{~{language~}~}"). oObj:add('visible', TRUE). oObj:add('disable', TRUE). oObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('character')). oObj:add('gridColumns', 6). oIdiomas:add(oObj). ASSIGN oObj = NEW JsonObject(). oObj:add('property', 'desIdioma'). oObj:add('label', 'Descrição~{~{description~}~}'). oObj:add('visible', TRUE). oObj:add('required', TRUE). oObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('character')). oObj:add('gridColumns', 6). oIdiomas:add(oObj). ASSIGN oObj = NEW JsonObject(). oObj:add('property', 'codIdiomPadr'). oObj:add('label', 'Idioma Padrão~{~{defaultLanguage~}~}'). oObj:add('visible', TRUE). oObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('character')). oObj:add('gridColumns', 6). oIdiomas:add(oObj). ASSIGN oObj = NEW JsonObject(). oObj:add('property', 'datUltAtualiz'). oObj:add('label', 'Última Atualização~{~{lastUpdate~}~}'). oObj:add('visible', TRUE). oObj:add('format', 'dd/MM/yyyy'). oObj:add('disable', TRUE). oObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('date')). oObj:add('gridColumns', 6). oIdiomas:add(oObj). ASSIGN oObj = NEW JsonObject(). oObj:add('property', 'hraUltAtualiz'). oObj:add('label', 'Hora Última Atualização~{~{hourLastUpdate~}~}'). oObj:add('visible', TRUE). oObj:add('disable', TRUE). oObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('character')). oObj:add('gridColumns', 6). oIdiomas:add(oObj). // osacoes camposde abaixotela foram adicionados para testes de validacao do formulario ASSIGN oOpts = NEW JsonArray(). ASSIGN oOpt = NEW JsonObject(). oOpt:add('label', 'Foco CodIdiomaPadrao~{~{languageDefaultFocus~}~}'). oOpt:add('value', 'focoCodIdiomPadr'). oOpts:add(oOpt). ASSIGN oOpt = NEW JsonObject(). oOpt:add('label', 'Foco DesIdioma~{~{descriptionFocus~}~}'). oOpt:add('value', 'FocoDesIdioma'). oOpts:add(oOpt). ASSIGN oOpt = NEW JsonObject(). oOpt:add('label', 'Desabilita CodIdiomaPadrao~{~{languageDefaultDisable~}~}'). oOpt:add('value', 'DesabilitaCodIdiomaPadrao'). oOpts:add(oOpt). ASSIGN oOpt = NEW JsonObject(). oOpt:add('label', 'Habilita CodIdiomaPadrao~{~{languageDefaultEnable~}~}'). oOpt:add('value', 'HabilitaCodIdiomaPadrao'). oOpts:add(oOpt). ASSIGN oOpt = NEW JsonObject(). oOpt:add('label', 'Mascara CPF~{~{cpfMask~}~}'). oOpt:add('value', 'MascaraCPF'). oOpts:add(oOpt). ASSIGN oOpt = NEW JsonObject(). oOpt:add('label', 'Mascara CNPJ~{~{cnpjMask~}~}'). oOpt:add('value', 'MascaraCNPJ'). oOpts:add(oOpt). ASSIGN oOpt = NEW JsonObject(). oOpt:add('label', 'TrocaValor DesIdioma~{~{changeValueLanguage~}~}'). oOpt:add('value', 'TrocaValorDesIdioma'). oOpts:add(oOpt). ASSIGN oOpt = NEW JsonObject(). oOpt:add('label', 'Esconder DesIdioma~{~{languageHide~}~}'). oOpt:add('value', 'EsconderDesIdioma'). oOpts:add(oOpt). ASSIGN oOpt = NEW JsonObject(). oOpt:add('label', 'Aparecer DesIdioma~{~{languageShow~}~}'). oOpt:add('value', 'AparecerDesIdioma'). oOpts:add(oOpt). ASSIGN oOpt = NEW JsonObject(). oOpt:add('label', 'Mostra Mensagem de Erro~{~{errorMessageShow~}~}'). oOpt:add('value', 'showErrorMessage'). oOpts:add(oOpt). ASSIGN oOpt = NEW JsonObject(). oOpt:add('label', 'Muda Label DesIdioma~{~{languageLabelChange~}~}'). oOpt:add('value', 'mudaLabelDesIdioma'). oOpts:add(oOpt). ASSIGN oObj = NEW JsonObject(). oObj:add('property', 'codAcoes'). oObj:add('label', 'Acoes de Tela~{~{screenActions~}~}'). oObj:add('visible', TRUE). oObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('character')). oObj:add('options', oOpts). oObj:add('gridColumns', 12). oObj:add('validate', '/api/trn/v1/idiomas/validateField'). oIdiomas:add(oObj). // Informacoes de Tipo de Pessoa ASSIGN oOpts = NEW JsonArray(). ASSIGN oOpt = NEW JsonObject(). oOpt:add('label', 'Pessoa Fisica~{~{PF~}~}'). oOpt:add('value', 'f'). oOpts:add(oOpt). ASSIGN oOpt = NEW JsonObject(). oOpt:add('label', 'Pessoa Juridica~{~{PJ~}~}'). oOpt:add('value', 'j'). oOpts:add(oOpt). ASSIGN oObj = NEW JsonObject(). oObj:add('property', 'tipUsuario'). oObj:add('label', 'Tipo do usuario~{~{userType~}~}'). oObj:add('visible', TRUE). oObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('character')). oObj:add('options', oOpts). oObj:add('gridColumns', 6). oObj:add('validate', '/api/trn/v1/idiomas/validateField'). oObj:add('gridColumns', 6). oIdiomas:add(oObj). ASSIGN oObj = NEW JsonObject(). oObj:add('property', 'codCpfCnpj'). oObj:add('label', 'CPF/CNPJ~{~{documentOptions~}~}'). oObj:add('visible', TRUE). oObj:add('mask', '999.999.999-99'). oObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('character')). oObj:add('gridColumns', 6). oIdiomas:add(oObj). // Adiciona o campo ID na lista de campos para a interface HTML // Isso facilitara o gerenciamento do registro na interface HTML oIdiomas:add(JsonAPIUtils:getIdField()). // Adiciona o JsonArray em um JsonObject para enviar para a UPC oObj = NEW JsonObject(). oObj:add('root', oIdiomas). // Realiza a chamada da UPC Progress {include/i-epcrest.i &endpoint=getMetaData &event=getMetaData &jsonVar=oObj} // Recupera o JsonArray de dentro do JsonObject retornado pela UPC oIdiomas = oObj:getJsonArray('root'). // Retorna a colecao de campos customizados ou nao para a interface HTML oResponse = NEW JsonAPIResponse(oIdiomas). oJsonOutput = oResponse:createJsonResponse(). END PROCEDURE. /** Procedure que retorna os valores **/ PROCEDURE pFindAll: DEFINE INPUT PARAMETER oJsonInput AS JsonObject NO-UNDO. DEFINE OUTPUT PARAMETER oJsonOutput AS JsonObject NO-UNDO. DEFINE VARIABLE oResponse AS JsonAPIResponse NO-UNDO. DEFINE VARIABLE oIdiomas AS JsonArray NO-UNDO. DEFINE VARIABLE oObj AS JsonObject NO-UNDO. DEFINE VARIABLE oId AS JsonObject NO-UNDO. EMPTY TEMP-TABLE ttIdiomas. // Monta a lista de valores dos campos FOR EACH idioma NO-LOCK BY idioma.cod_idioma: CREATE ttIdiomas. BUFFER-COPY idioma TO ttIdiomas. // Alimenta o campo ID utilizado pela interface HTML como chave primaria ASSIGN ttIdiomas.id = RECID(idioma). END. // Obtem um jsonArray com base no conteudo da temp-table oIdiomas = JsonAPIUtils:convertTempTableToJsonArray(TEMP-TABLE ttIdiomas:HANDLE). // Adiciona o JsonArray em um JsonObject para enviar para a UPC oObj = NEW JsonObject(). oObj:add('root', oIdiomas). // Realiza a chamada da UPC Progress {include/i-epcrest.i &endpoint=findAll &event=findAll &jsonVar=oObj} // Recupera o JsonArray de dentro do JsonObject retornado pela UPC oIdiomas = oObj:getJsonArray('root'). // Retorna a colecao de dados customizados ou nao para a interface HTML oResponse = NEW JsonAPIResponse(oIdiomas). oJsonOutput = oResponse:createJsonResponse(). END PROCEDURE. /** Procedure que retorna 1 registro pelo ID **/ PROCEDURE pFindById: DEFINE INPUT PARAMETER oJsonInput AS JsonObject NO-UNDO. DEFINE OUTPUT PARAMETER oJsonOutput AS JsonObject NO-UNDO. DEFINE VARIABLE oRequest AS JsonAPIRequestParser NO-UNDO. DEFINE VARIABLE oResponse AS JsonAPIResponse NO-UNDO. DEFINE VARIABLE oIdioma AS JsonObject NO-UNDO. DEFINE VARIABLE oId AS JsonObject NO-UNDO. DEFINE VARIABLE cId AS CHARACTER NO-UNDO. DEFINE VARIABLE iId AS INTEGER NO-UNDO. EMPTY TEMP-TABLE ttIdiomas. // Le os parametros enviados pela interface HTML oRequest = NEW JsonAPIRequestParser(oJsonInput). // Obtem o ID cId = oRequest:getPathParams():getCharacter(2). // Localiza o registro na tabela IDIOMA pelo ID (recid) FIND FIRST idioma WHERE RECID(idioma) = INT(cId) NO-LOCK NO-ERROR. IF AVAILABLE idioma THEN DO: BUFFER-COPY idioma TO ttIdiomas. ASSIGN ttIdiomas.id = RECID(idioma). END. // Obtem um jsonArray com base no conteudo da temp-table oIdioma = JsonAPIUtils:convertTempTableFirstItemToJsonObject(TEMP-TABLE ttIdiomas:HANDLE). // Realiza a chamada da UPC Progress {include/i-epcrest.i &endpoint=findById &event=findById &jsonVar=oIdioma} // Retorna o registro customizado ou nao para a interface HTML oResponse = NEW JsonAPIResponse(oIdioma). oJsonOutput = oResponse:createJsonResponse(). END PROCEDURE. /** Procedure que cria um novo registro na tabela **/ PROCEDURE pCreate: DEFINE INPUT PARAMETER oJsonInput AS JsonObject NO-UNDO. DEFINE OUTPUT PARAMETER oJsonOutput AS JsonObject NO-UNDO. DEFINE VARIABLE oBody AS JsonObject NO-UNDO. DEFINE VARIABLE oRequest AS JsonAPIRequestParser NO-UNDO. DEFINE VARIABLE oResponse AS JsonAPIResponse NO-UNDO. DEFINE VARIABLE cCodIdioma AS CHARACTER NO-UNDO. DEFINE VARIABLE cDesIdioma AS CHARACTER NO-UNDO. DEFINE VARIABLE cCodIdiomPadr AS CHARACTER NO-UNDO. DEFINE VARIABLE rIdioma AS RECID NO-UNDO. DEFINE VARIABLE lCreated AS LOGICAL NO-UNDO INITIAL FALSE. // Le os parametros e os dados enviados pela interface HTML oRequest = NEW JsonAPIRequestParser(oJsonInput). oBody = oRequest:getPayload(). // Obtem os demais dados cCodIdioma = oBody:getCharacter("codIdioma") NO-ERROR. cDesIdioma = oBody:getCharacter("desIdioma") NO-ERROR. cCodIdiomPadr = oBody:getCharacter("codIdiomPadr") NO-ERROR. // Cria o registro na tabela IDIOMA DO TRANSACTION ON ERROR UNDO, LEAVE: FIND FIRST idioma WHERE idioma.cod_idioma = cCodIdioma NO-LOCK NO-ERROR. IF NOT AVAILABLE idioma THEN DO: CREATE idioma. ASSIGN idioma.cod_idioma = cCodIdioma idioma.des_idioma = cDesIdioma idioma.cod_idiom_padr = cCodIdiomPadr idioma.dat_ult_atualiz = TODAY idioma.hra_ult_atualiz = STRING(TIME,"HH:MM:SS") rIdioma = RECID(idioma) lCreated = TRUE. // Realiza a chamada da UPC Progress para a criacao do // registro customizado. Nao utilizaremos o retorno da UPC // neste caso. {include/i-epcrest.i &endpoint=create &event=afterCreate &jsonVar=oBody} RELEASE idioma. END. END. // Retorna o ID e se foi criado com sucesso oBody = NEW JsonObject(). oBody:add('id', rIdioma). oBody:add('created', (IF lCreated THEN 'OK' ELSE 'NOK')). // Retorna o oBody montado para a interface HTML oResponse = NEW JsonAPIResponse(oBody). oJsonOutput = oResponse:createJsonResponse(). END PROCEDURE. /** Procedure que atualiza o conteudo do registro pelo ID **/ PROCEDURE pUpdateById: DEFINE INPUT PARAMETER oJsonInput AS JsonObject NO-UNDO. DEFINE OUTPUT PARAMETER oJsonOutput AS JsonObject NO-UNDO. DEFINE VARIABLE oBody AS JsonObject NO-UNDO. DEFINE VARIABLE oRequest AS JsonAPIRequestParser NO-UNDO. DEFINE VARIABLE oResponse AS JsonAPIResponse NO-UNDO. DEFINE VARIABLE oIdioma AS JsonObject NO-UNDO. DEFINE VARIABLE oId AS JsonObject NO-UNDO. DEFINE VARIABLE cId AS CHARACTER NO-UNDO. DEFINE VARIABLE cCodIdioma AS CHARACTER NO-UNDO. DEFINE VARIABLE cDesIdioma AS CHARACTER NO-UNDO. DEFINE VARIABLE cCodIdiomPadr AS CHARACTER NO-UNDO. DEFINE VARIABLE datUltAtualiz AS DATE NO-UNDO. DEFINE VARIABLE hraUltAtualiz AS CHARACTER NO-UNDO. DEFINE VARIABLE lUpdated AS LOGICAL NO-UNDO INITIAL FALSE. // Le os parametros e os dados enviados pela interface HTML oRequest = NEW JsonAPIRequestParser(oJsonInput). oBody = oRequest:getPayload(). // Obtem o ID cId = oRequest:getPathParams():getCharacter(1). // Obtem os demais dados cCodIdioma = oBody:getCharacter("codIdioma") NO-ERROR. cDesIdioma = oBody:getCharacter("desIdioma") NO-ERROR. cCodIdiomPadr = oBody:getCharacter("codIdiomPadr") NO-ERROR. // Atualiza o registro na tabela IDIOMA pelo ID (recid) DO TRANSACTION ON ERROR UNDO, LEAVE: FIND FIRST idioma WHERE RECID(idioma) = INT(cId) EXCLUSIVE-LOCK NO-ERROR. IF AVAILABLE idioma THEN DO: ASSIGN idioma.des_idioma = cDesIdioma idioma.cod_idiom_padr = cCodIdiomPadr idioma.dat_ult_atualiz = TODAY idioma.hra_ult_atualiz = STRING(TIME,"HH:MM:SS") lUpdated = TRUE. // Realiza a chamada da UPC Progress para atualizar o registro // na tabela cutomizada ou nao. Nao utilizaremos o retorno da UPC // neste caso. {include/i-epcrest.i &endpoint=update &event=afterUpdate &jsonVar=oBody} END. END. // Retorna o ID e se foi atualizado com sucesso oBody = NEW JsonObject(). oBody:add('id', cId). oBody:add('updated', (IF lUpdated THEN 'OK' ELSE 'NOK')). // Retorna o oBody montado para a interface HTML oResponse = NEW JsonAPIResponse(oBody). oJsonOutput = oResponse:createJsonResponse(). END PROCEDURE. /** Procedure que atualiza o conteudo do registro pelo ID **/ PROCEDURE pDeleteById: DEFINE INPUT PARAMETER oJsonInput AS JsonObject NO-UNDO. DEFINE OUTPUT PARAMETER oJsonOutput AS JsonObject NO-UNDO. DEFINE VARIABLE oObj AS JsonObject NO-UNDO. DEFINE VARIABLE oRequest AS JsonAPIRequestParser NO-UNDO. DEFINE VARIABLE oResponse AS JsonAPIResponse NO-UNDO. DEFINE VARIABLE oArray AS JsonArray NO-UNDO. DEFINE VARIABLE oIdioma AS JsonObject NO-UNDO. DEFINE VARIABLE oId AS JsonObject NO-UNDO. DEFINE VARIABLE cId AS CHARACTER NO-UNDO. DEFINE VARIABLE lDeleted AS LOGICAL NO-UNDO INITIAL FALSE. DEFINE VARIABLE ix AS INTEGER NO-UNDO. // Le os parametros enviados pela interface HTML oRequest = NEW JsonAPIRequestParser(oJsonInput). // Eliminacao de registro individual IF oRequest:getPathParams():length > 0 THEN DO: // Obtem o ID cId = oRequest:getPathParams():getCharacter(1). RUN piDeleteRecord (cId). ASSIGN lDeleted = (RETURN-VALUE = "OK"). END. ELSE DO: // Eliminacao de registros em lote // Obtem a lista de IDs diretamente do oJsonInput onde vem um JsonArray // oArray = oJsonInput:getJsonArray('payload'). oArray = oRequest:getPayloadArray(). DO ix = 1 TO oArray:length: oObj = oArray:getJsonObject(ix). cId = STRING(oObj:getInteger('id')). RUN piDeleteRecord (cId). IF lDeleted = FALSE THEN ASSIGN lDeleted = (RETURN-VALUE = "OK"). END. END. // Retorna o ID e se foi criado com sucesso oObj = NEW JsonObject(). IF oRequest:getPathParams():length > 0 THEN DO: oObj:add('id', cId). END. oObj:add('deleted', (IF lDeleted THEN 'OK' ELSE 'NOK')). // Retorna o oBody montado para a interface HTML oResponse = NEW JsonAPIResponse(oObj). oJsonOutput = oResponse:createJsonResponse(). END PROCEDURE. PROCEDURE piDeleteRecord: DEFINE INPUT PARAMETER cId AS CHARACTER NO-UNDO. DEFINE VARIABLE oObj AS JsonObject NO-UNDO. DEFINE VARIABLE lDeleted AS LOGICAL NO-UNDO INITIAL FALSE. LOG-MANAGER:WRITE-MESSAGE("Eliminando registro -> " + cId, ">>>>>"). // Elimina o registro na tabela IDIOMA pelo ID (recid) DO TRANSACTION ON ERROR UNDO, LEAVE: FIND FIRST idioma WHERE RECID(idioma) = INT(cId) EXCLUSIVE-LOCK NO-ERROR. IF AVAILABLE idioma THEN DO: // Monta a chave estrangeira para enviar para UPC // poder elominar o registro da tabela customizada oObj = NEW JsonObject(). oObj:add('codIdioma', idioma.cod_idioma). // Realiza a chamada da UPC Progress para a eliminacao do // registro customizado. Nao utilizaremos o retorno da UPC // neste caso. {include/i-epcrest.i &endpoint=delete &event=beforeDelete &jsonVar=oObj} DELETE idioma. ASSIGN lDeleted = TRUE. END. END. RETURN (IF lDeleted THEN "OK" ELSE "NOK"). END PROCEDURE. PROCEDURE pValidateForm: DEFINE INPUT PARAMETER oJsonInput AS JsonObject NO-UNDO. DEFINE OUTPUT PARAMETER oJsonOutput AS JsonObject NO-UNDO. DEFINE VARIABLE oRequest AS JsonAPIRequestParser NO-UNDO. DEFINE VARIABLE oResponse AS JsonAPIResponse NO-UNDO. DEFINE VARIABLE oBody AS JsonObject NO-UNDO. DEFINE VARIABLE cProp AS CHARACTER NO-UNDO. DEFINE VARIABLE oValue AS JsonObject NO-UNDO. DEFINE VARIABLE cValue AS CHARACTER NO-UNDO. DEFINE VARIABLE cId AS CHARACTER NO-UNDO. DEFINE VARIABLE oNewValue AS JsonObject NO-UNDO. DEFINE VARIABLE oNewFields AS JsonArray NO-UNDO. DEFINE VARIABLE cFocus AS CHARACTER NO-UNDO. DEFINE VARIABLE oRet AS JsonObject NO-UNDO. DEFINE VARIABLE oObj AS JsonObject NO-UNDO. DEFINE VARIABLE oMessages AS JsonArray NO-UNDO. oRequest = NEW JsonAPIRequestParser(oJsonInput). oBody = oRequest:getPayload(). // obtem o nome da propriedade que ocorreu o LEAVE para validacao cProp = oBody:getCharacter("property") NO-ERROR. oValue = oBody:getJsonObject("value") NO-ERROR. cValue = STRING(oValue:GetCharacter(cProp)) NO-ERROR. cId = oValue:getCharacter("id") NO-ERROR. /* Recebemos do HTML o JSON abaixo { "property": "codAcoes", "value": { "codIdiomPadr": "01 PortuguêsPortuguˆs", "codIdioma": "12345678", "desIdioma": "12345678901234567890", "hraUltAtualiz": "", "datUltAtualiz": null, "id": 6, "codAcoes": "FocoDesIdioma" } } */ // Novas Acoes sobre os campos da tela // oNewValue guarda os valores a serem especificados para os campos ASSIGN oNewValue = NEW JsonObject(). // oNewFields guarda a lista de campos que serao alterados/modificados ASSIGN oNewFields = NEW JsonArray(). // cFocus especifica em qual campo sera feito o focus ASSIGN cFocus = cProp. // oMessages guarda as mensagens de retorno formato // { code: '00', message: 'texto', detailedMessage: 'detalhes da mensagem' } ASSIGN oMessages = NEW JsonArray(). CASE cProp: WHEN "codAcoes" THEN DO: CASE cValue: WHEN 'focoCodIdiomPadr' THEN DO: // setamos o focus para o campo desejado ASSIGN cFocus = 'codIdiomPadr'. END. WHEN 'FocoDesIdioma' THEN DO: // setamos o focus para o campo desejado ASSIGN cFocus = 'desIdioma'. END. WHEN 'DesabilitaCodIdiomaPadrao' THEN DO: // criamos um novo field para desabilitar ASSIGN oObj = NEW JsonObject(). oObj:add('property', 'codIdiomPadr'). oObj:add('disabled', TRUE). oNewFields:add(oObj). END. WHEN 'HabilitaCodIdiomaPadrao' THEN DO: // criamos um novo field para habilitar ASSIGN oObj = NEW JsonObject(). oObj:add('property', 'codIdiomPadr'). oObj:add('disabled', FALSE). oNewFields:add(oObj). END. WHEN 'MascaraCPF' THEN DO: // IMPORTANTE: // Quando alteramos o valor do radio-set tipUsuario por aqui, // O value-changed dele que especifica qual a mascara // seráser utilizada NAO sera disparado, pois ele é‚ dinamico e // estamos validando o campo codAcoes, sendo necessario // fazermos a formatacao da mascara aqui tambem. // A mesma regra é‚ valida para o CNPJ // mudamos os valores dos campos desejados oNewValue:add('tipUsuario', 'f'). oNewValue:add('codCpfCnpj', FILL('0',11)). // criamos um novo field para mudar a mascara ASSIGN oObj = NEW JsonObject(). oObj:add('property', 'codCpfCnpj'). oObj:add('mask', '999.999.999-99'). oNewFields:add(oObj). END. WHEN 'MascaraCNPJ' THEN DO: // IMPORTANTE: // Quando alteramos o valor do radio-set tipUsuario por aqui, // O value-changed dele que especifica qual a mascara // seráser utilizada NAO sera disparado, pois ele é‚ dinamico e // estamos validando o campo codAcoes, sendo necessario // fazermos a formatacao da mascara aqui tambem. // A mesma regra é‚ valida para o CPF // alteramos os valores dos campos desejados oNewValue:add('tipUsuario', 'j'). oNewValue:add('codCpfCnpj', FILL('0',15)). // criamos um novo field para mudar a mascara ASSIGN oObj = NEW JsonObject(). oObj:add('property', 'codCpfCnpj'). oObj:add('mask', '99.999.999/9999-99'). oNewFields:add(oObj). END. WHEN 'TrocaValorDesIdioma' THEN DO: // alteramos o conteudo de um campo qualquer oNewValue:add('desIdioma', "Valor retornado do backend de validacao"). END. WHEN 'EsconderDesIdioma' THEN DO: // criamos um novo field para tornar invisivel o campo ASSIGN oObj = NEW JsonObject(). oObj:add('property', 'desIdioma'). oObj:add('visible', FALSE). oNewFields:add(oObj). END. WHEN 'AparecerDesIdioma' THEN DO: // criamos um novo field para tornar visivel o campo ASSIGN oObj = NEW JsonObject(). oObj:add('property', 'desIdioma'). oObj:add('visible', TRUE). oNewFields:add(oObj). END. WHEN 'mudaLabelDesIdioma' THEN DO: // criamos um novo field para mudar o label ASSIGN oObj = NEW JsonObject(). oObj:add('property', 'desIdioma'). oObj:add('label', 'Label alterado da descricao'). oNewFields:add(oObj). END. WHEN 'showErrorMessage' THEN DO: // criamos uma mensagem de erro ASSIGN oObj = NEW JsonObject(). oObj:add('code', '33'). oObj:add('message', 'A Descricao do idioma nao foi preenchida corretamente'). oObj:add('detailedMessage', 'Detalhe da mensagem de erro'). oMessages:add(oObj). END. END CASE. END. WHEN "tipUsuario" THEN DO: // setamos o focus para o campo desejado ASSIGN cFocus = 'codCpfCnpj'. // criamos um field para mudar o informar o campo e a nova mascara ASSIGN oObj = NEW JsonObject(). oObj:add('property', "codCpfCnpj"). IF cValue = "j" THEN DO: // é‚ definido um novo valor para o CNPJ oNewValue:add('codCpfCnpj', FILL('0',15)). // é‚ alterado o formato da mascara de edicao oObj:add('mask', '99.999.999/9999-99'). END. IF cValue = "f" THEN DO: // é‚ definido um novo valor para o CPF oNewValue:add('codCpfCnpj', FILL('0',11)). // é‚ alterado o formato da mascara de edicao oObj:add('mask', '999.999.999-99'). END. oNewFields:add(oObj). END. END CASE. ASSIGN oRet = NEW JsonObject(). // value -> contem todos os valores dos campos de tela oRet:add('value', oNewValue). // fields -> contem a lista de campos com suas novas propriedades oRet:add('fields', oNewFields). // focus -> especifica em qual campo o cursor vai ficar posicionado oRet:add('focus', cFocus). // _messages -> contem uma lista de mensagens que vao aparecer como notificacoes oRet:add('_messages', oMessages). // encapsulamos o retorno para enviar para a UPC oObj = NEW JsonObject(). oObj:add("property", cProp). oObj:add("originalValues", oValue). oObj:add("root", oRet). // Realiza a chamada da UPC Progress {include/i-epcrest.i &endpoint=validateForm &event=validateForm &jsonVar=oObj} // obtem o retorno customizado, onde o mesmo foi alterado e retornado somentena tag // o conteudo da tag returnroot oRet = oObj:getJsonObject("root"). /* JSON de retorno para o HTML value: { desIdioma: 'teste de escrita', hraUltAtualiz: '17:18:19' }, fields: [ { property: 'codCpfCnpj', mask: '99.999.999/9999-99' } ], focus: 'hraUltAtualiz', _messages: [ { code: '01', message: 'Mensagem do erro que aconteceu', detailedMessage: 'detalhes do erro acontecido' } ] */ // Retorna a colecao de campos customizados ou nao para a interface HTML oResponse = NEW JsonAPIResponse(oRet). oJsonOutput = oResponse:createJsonResponse(). END PROCEDURE. PROCEDURE pValidateField: DEFINE INPUT PARAMETER oJsonInput AS JsonObject NO-UNDO. DEFINE OUTPUT PARAMETER oJsonOutput AS JsonObject NO-UNDO. DEFINE VARIABLE oRequest AS JsonAPIRequestParser NO-UNDO. DEFINE VARIABLE oResponse AS JsonAPIResponse NO-UNDO. DEFINE VARIABLE oBody AS JsonObject NO-UNDO. DEFINE VARIABLE cProp AS CHARACTER NO-UNDO. DEFINE VARIABLE oValue AS JsonObject NO-UNDO. DEFINE VARIABLE cValue AS CHARACTER NO-UNDO. DEFINE VARIABLE cId AS CHARACTER NO-UNDO. DEFINE VARIABLE oNewValue AS JsonObject NO-UNDO. DEFINE VARIABLE oNewField AS JsonObject NO-UNDO. DEFINE VARIABLE lFocus AS LOGICAL NO-UNDO INITIAL FALSE. DEFINE VARIABLE oRet AS JsonObject NO-UNDO. DEFINE VARIABLE oObj AS JsonObject NO-UNDO. DEFINE VARIABLE oMessages AS JsonArray NO-UNDO. oRequest = NEW JsonAPIRequestParser(oJsonInput). oBody = oRequest:getPayload(). // obtem o nome da propriedade que ocorreu o LEAVE para validacao cProp = oBody:getCharacter("property") NO-ERROR. cValue = oBody:getCharacter("value") NO-ERROR. /* Recebemos do HTML o JSON abaixo { "property": "codAcoes", "value": "FocoDesIdioma" } */ // Novas Acoes sobre os campos da tela // oNewField guarda o objeto que sera alterado/modificado ASSIGN oNewField = NEW JsonObject(). // oMessages guarda as mensagens de retorno formato // { code: '00', message: 'texto', detailedMessage: 'detalhes da mensagem' } ASSIGN oMessages = NEW JsonArray(). IF cProp = "tipUsuario" THEN DO: ASSIGN lFocus = TRUE. oNewField:add('property', "codCpfCnpj"). IF cValue = "j" THEN DO: // é‚ alterado o formato da mascara de edicao oNewField:add('mask', '99.999.999/9999-99'). END. IF cValue = "f" THEN DO: // é‚ alterado o formato da mascara de edicao oNewField:add('mask', '999.999.999-99'). END. ASSIGN oObj = NEW JsonObject(). oObj:add('code', '33'). oObj:add('message', 'A mascara do CPF/CNPJ foi ajustada'). oObj:add('detailedMessage', 'Ocorreu um ajusta na mascara do CPF/CNPJ, favor verificar se os dados estao corretos'). oMessages:add(oObj). END. ASSIGN oRet = NEW JsonObject(). // value -> contem todos os valores dos campos de tela oRet:add('value', cValue). // field -> contem os novos atributos do campo atual oRet:add('field', oNewField). // focus -> especifica se o campo recebe o focu oRet:add('focus', lFocus). // _messages -> contem uma lista de mensagens que vao aparecer como notificacoes oRet:add('_messages', oMessages). // encapsulamos o retorno para enviar para a UPC oObj = NEW JsonObject(). oObj:add("property", cProp). oObj:add("root", oRet). // Realiza a chamada da UPC Progress {include/i-epcrest.i &endpoint=validateField &event=validateField &jsonVar=oObj} // obtem o retorno customizado, onde o mesmo foi alterado e retornado somente // o conteudo da tag return oRet = oObj:getJsonObject("root"). /* JSON de retorno para o HTML value: 'teste de escrita', field: { mask: '99.999.999/9999-99', required: true }, focus: true, _messages: [ { code: '01', message: 'Mensagem do erro que aconteceu', detailedMessage: 'detalhes do erro acontecido' } ] */ // Retorna a colecao de campos customizados ou nao para a interface HTML oResponse = NEW JsonAPIResponse(oRet). oJsonOutput = oResponse:createJsonResponse(). END PROCEDURE. /** Recupera as literais */ PROCEDURE pIdiomas: DEFINE INPUT PARAMETER oJsonInput AS JsonObject NO-UNDO. DEFINE OUTPUT PARAMETER oJsonOutput AS JsonObject NO-UNDO. // Realiza a chamada da UPC Progress {include/i-epcrest.i &endpoint=i18n &event=i18n &jsonVar=oJsonInput} ASSIGN oJsonOutput = oJsonInput. END PROCEDURE. /* fim */ |
Programa UPC:
Abaixo temos um exemplo de uma UPC criada para a API REST:
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
/************************************************************************** ** idiomas_upc.p - Exemplo de epc para Endpoints REST ** 18/05/2020 - Menna - Criado exemplo ***************************************************************************/ USING PROGRESS.json.*. USING PROGRESS.json.ObjectModel.*. USING com.totvs.framework.api.*. DEFINE INPUT PARAMETER pEndPoint AS CHARACTER NO-UNDO. DEFINE INPUT PARAMETER pEvent AS CHARACTER NO-UNDO. DEFINE INPUT PARAMETER pAPI AS CHARACTER NO-UNDO. DEFINE INPUT-OUTPUT PARAMETER jsonIO AS JSONObject NO-UNDO. DEFINE VARIABLE jObj AS JsonObject NO-UNDO. DEFINE VARIABLE oOriginalValues AS JSonObject NO-UNDO. DEFINE VARIABLE oReturn AS JSonObject NO-UNDO. DEFINE VARIABLE oValues AS JSonObject NO-UNDO. DEFINE VARIABLE oFieldObj AS JSonObject NO-UNDO. DEFINE VARIABLE oFields AS JSonArray NO-UNDO. DEFINE VARIABLE oMessages AS JSonArray NO-UNDO. DEFINE VARIABLE ix AS INTEGER NO-UNDO. DEFINE VARIABLE iTot AS INTEGER NO-UNDO. DEFINE VARIABLE cCodIdioma AS CHARACTER NO-UNDO. DEFINE VARIABLE cCodUsuario AS CHARACTER NO-UNDO. DEFINE VARIABLE cNomUsuario AS CHARACTER NO-UNDO. DEFINE VARIABLE cCodDialet AS CHARACTER NO-UNDO. DEFINE VARIABLE cProp AS CHARACTER NO-UNDO. DEFINE VARIABLE cFocus AS CHARACTER NO-UNDO. DEFINE VARIABLE cOriginalValue AS CHARACTER NO-UNDO. DEFINE VARIABLE cValue AS CHARACTER NO-UNDO. DEFINE VARIABLE lFocus AS LOGICAL NO-UNDO INITIAL FALSE. /* *************************** Main Block *************************** */ LOG-MANAGER:WRITE-MESSAGE("UPC EndPoint = " + pEndPoint, ">>>>"). LOG-MANAGER:WRITE-MESSAGE("UPC Event = " + pEvent, ">>>>"). // Carrega as definicoes dos campos customizados da tabela IF pEndPoint = "getMetaData" AND pEvent = "getMetaData" THEN DO ON STOP UNDO, LEAVE: RUN piGetMetaData. END. // Carrega os valores dos campos customizados das tabelas IF pEndPoint = "findAll" AND pEvent = "findAll" THEN DO ON STOP UNDO, LEAVE: RUN piFindAll. END. IF pEndPoint = "findById" AND pEvent = "findById" THEN DO ON STOP UNDO, LEAVE: RUN piFindById. END. IF pEndPoint = "create" AND pEvent = "afterCreate" THEN DO ON STOP UNDO, LEAVE: RUN piCreate. END. IF pEndPoint = "update" AND pEvent = "afterUpdate" THEN DO ON STOP UNDO, LEAVE: RUN piUpdate. END. IF pEndPoint = "delete" AND pEvent = "beforeDelete" THEN DO ON STOP UNDO, LEAVE: RUN piDelete. END. IF pEndPoint = "validateForm" AND pEvent = "validateForm" THEN DO ON STOP UNDO, LEAVE: RUN piValidateForm. END. IF pEndPoint = "validateField" AND pEvent = "validateField" THEN DO ON STOP UNDO, LEAVE: RUN piValidateField. END. RETURNIF pEndPoint = "OKi18n". AND pEvent = "i18n" THEN DO ON STOP UNDO, LEAVE: RUN piI18N. END. RETURN "OK". PROCEDURE piGetMetaData: // Obtem a lista de campos e valores ASSIGN oFields = jsonIO:getJsonArray('root'). // Cria os novos campos na lista ASSIGN jObj = NEW JsonObject(). jObj:add('divider', "Itens da UPC"). jObj:add('property', 'codUsuario'). jObj:add('label', 'Usuário~{~{user~}~}'). jObj:add('visible', TRUE). jObj:add('required', TRUE). jObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('character')). jObj:add('gridColumns', 6). oFields:add(jObj). ASSIGN jObj = NEW JsonObject(). jObj:add('property', 'nomUsuario'). jObj:add('label', 'Nome~{~{name~}~}'). jObj:add('visible', TRUE). jObj:add('required', TRUE). jObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('character')). jObj:add('gridColumns', 6). oFields:add(jObj). ASSIGN jObj = NEW JsonObject(). jObj:add('property', 'codDialet'). jObj:add('label', 'Dialeto~{~{dialect~}~}'). jObj:add('visible', FALSE). // <- Remove o item da tela de todos seus correspondentes (Form, View, Table) jObj:add('required', TRUE). jObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('character')). jObj:add('gridColumns', 6). oFields:add(jObj). ASSIGN jObj = NEW JsonObject(). jObj:add('property', 'testeValidacaoRegEx'). jObj:add('label', 'Teste Validação RegEx~{~{regexTestValidation~}~}'). jObj:add('gridColumns', 6). jObj:add('pattern', "[0-9]~{2~}"). // <- Validacao RegEx jObj:add('errorMessage', 'ObrigatórioObrigat¢rio mínimom¡nimo 2 númerosn£meros consecutivos.'). oFields:add(jObj). ASSIGN jObj = NEW JsonObject(). jObj:add('property', 'numberRangeValidate'). jObj:add('label', 'Aplicação de máscara CPF~{~{cpfMaskApply~}~}'). jObj:add('mask', '999.999.999-99'). // <-- Mascara CPF jObj:add('visible', TRUE). jObj:add('required', FALSE). jObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('character')). jObj:add('gridColumns', 6). oFields:add(jObj). ASSIGN jObj = NEW JsonObject(). jObj:add('property', 'numberValidate'). jObj:add('label', 'Somente números~{~{onlyNumbers~}~}'). jObj:add('visible', TRUE). jObj:add('required', FALSE). jObj:add('minValue', 1). jObj:add('maxValue', 9). jObj:add('errorMessage', 'Somente númerosn£meros de 1 a 9'). // <- Mensagem de erro 1-9 jObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('integer')). // <- Restringe a digitacao somente numeros jObj:add('gridColumns', 6). oFields:add(jObj). // Retorna a nova lista com os campos customizados jsonIO:Set("root", oFields). END PROCEDURE. PROCEDURE piFindAll: // Obtem a lista de campos e valores ASSIGN oFields = jsonIO:getJsonArray('root'). LOG-MANAGER:WRITE-MESSAGE("UPC FINDALL", ">>>>"). FIND FIRST usuar_mestre NO-LOCK NO-ERROR. // Armazena o tamanho da lista em variavel para evitar LOOP devido a adicionar novos itens na lista ASSIGN iTot = oFields:length. DO ix = 1 TO iTot: ASSIGN jObj = oFields:GetJsonObject(ix). // Alimenta os novos dados IF AVAILABLE usuar_mestre THEN DO: jObj:add('codUsuario', usuar_mestre.cod_usuario) NO-ERROR. jObj:add('nomUsuario', usuar_mestre.nom_usuario) NO-ERROR. jObj:add('codDialet', usuar_mestre.cod_dialet) NO-ERROR. END. // Atualiza o objeto na lista oFields:set(ix, jObj). FIND NEXT usuar_mestre NO-LOCK NO-ERROR. END. // Retorna o json ROOT a lista nova com novos dados customizados jsonIO:Set("root", oFields). END PROCEDURE. PROCEDURE piFindById: // Obtem as informacoes necessarias da API para retornar dados cCodIdioma = jsonIO:getCharacter("codIdioma"). // chave estrangeira LOG-MANAGER:WRITE-MESSAGE("UPC FINDBYID cod_idioma= " + cCodIdioma, ">>>>"). // Adiciona os valores da tabela customizada no retorno FIND FIRST usuar_mestre NO-LOCK NO-ERROR. IF AVAILABLE usuar_mestre THEN DO: jsonIO:add('codUsuario', usuar_mestre.cod_usuario) NO-ERROR. jsonIO:add('nomUsuario', usuar_mestre.nom_usuario) NO-ERROR. jsonIO:add('codDialet', usuar_mestre.cod_dialet) NO-ERROR. END. END PROCEDURE. PROCEDURE piCreate: // Obtem as informacoes necessarias da API para criacao do registro cCodIdioma = jsonIO:getCharacter("codIdioma") NO-ERROR. // chave estrangeira cCodUsuario = jsonIO:getCharacter("codUsuario") NO-ERROR. cNomUsuario = jsonIO:getCharacter("nomUsuario") NO-ERROR. cCodDialet = jsonIO:getCharacter("codDialet") NO-ERROR. LOG-MANAGER:WRITE-MESSAGE("UPC CREATE cod_idioma= " + cCodIdioma, ">>>>"). LOG-MANAGER:WRITE-MESSAGE("UPC CREATE cod_usuario= " + cCodUsuario, ">>>>"). // logica de CREATE /* Em comentario a logica para nao criar registros desnecessariamente FIND FIRST usuar_mestre WHERE usuar_mestre.cod_usuario = cCodUsuario EXCLUSIVE-LOCK NO-ERROR. IF NOT AVAILABLE usuar_mestre THEN DO: ASSIGN usuar_mestre.nom_usuario = cNomUsuario usuar_mestre.cod_dialet = cCodDialet. END. */ END PROCEDURE. PROCEDURE piUpdate: // Obtem as informacoes necessarias da API para atualizacao cCodIdioma = jsonIO:getCharacter("codIdioma") NO-ERROR. // chave estrangeira cCodUsuario = jsonIO:getCharacter("codUsuario") NO-ERROR. cNomUsuario = jsonIO:getCharacter("nomUsuario") NO-ERROR. cCodDialet = jsonIO:getCharacter("codDialet") NO-ERROR. LOG-MANAGER:WRITE-MESSAGE("UPC UPDATE cod_idioma= " + cCodIdioma, ">>>>"). LOG-MANAGER:WRITE-MESSAGE("UPC UPDATE cod_usuario= " + cCodUsuario, ">>>>"). // logica de UPDATE /* Em comentario a logica para nao alterar tabelas desnecessariamente FIND FIRST usuar_mestre WHERE usuar_mestre.cod_usuario = cCodUsuario EXCLUSIVE-LOCK NO-ERROR. IF AVAILABLE usuar_mestre THEN DO: ASSIGN usuar_mestre.nom_usuario = cNomUsuario usuar_mestre.cod_dialet = cCodDialet. END. */ END PROCEDURE. PROCEDURE piDelete: // obtem as informacoes necessarias da API para eliminacao cCodIdioma = jsonIO:getCharacter("codIdioma"). // chave estrangeira LOG-MANAGER:WRITE-MESSAGE("UPC DELETE cod_idioma= " + cCodIdioma, ">>>>"). // logica de DELETE /* Em comentario a logica para nao eliminar o registro desnecessariamente FIND FIRST usuar_mestre WHERE usuar_mestre.cod_usuario = cCodUsuario EXCLUSIVE-LOCK NO-ERROR. IF AVAILABLE usuar_mestre THEN DO: delete usuar_mestre. END. */ END PROCEDURE. PROCEDURE piValidateForm: cProp = jsonIO:getCharacter("property") NO-ERROR. // o cProp contem o nome da propriedade que esta sendo validada oOriginalValues = jsonIO:getJsonObject("originalValues") NO-ERROR. // obtem os valores dos campos que vieram da tela html LOG-MANAGER:WRITE-MESSAGE("UPC ValidateForm property= " + cProp, ">>>>"). oReturn = jsonIO:getJsonObject("root") NO-ERROR. // obtem o retorno que sera enviado para a tela html oValues = oReturn:getJsonObject("value") NO-ERROR. // obtem os valores dos campos ja ajustados oFields = oReturn:getJsonArray("fields") NO-ERROR. // obtem as propriedades dos campos a serem alteradas cFocus = oReturn:getCharacter("focus") NO-ERROR. // obtem o campo de focus a ser retornado para a tela html oMessages = oReturn:getJsonArray("_messages") NO-ERROR. // obtem as mensagens a serem retornados para a tela html /* Exemplo de JSON que veio para a UPC { property: 'codAcao', originalValues: { "codIdiomPadr": "01 PortuguêsPortuguˆs", "codIdioma": "12345678", "desIdioma": "12345678901234567890", "hraUltAtualiz": "", "datUltAtualiz": null, "id": 6, "codAcoes": "FocoDesIdioma" }, returnroot: { value: { desIdioma: 'teste de escrita', hraUltAtualiz: '17:18:19' }, fields: [ { property: 'codCpfCnpj', mask: '99.999.999/9999-99' } ], focus: 'hraUltAtualiz', _messages: [ { code: '01', message: 'Mensagem do erro que aconteceu', detailedMessage: 'detalhes do erro acontecido' } ] } } */ IF cProp = "desIdioma" THEN DO: cCodIdioma = oOriginalValues:getCharacter("codIdioma"). // chave estrangeira IF cCodIdioma = "12345678" THEN DO: oValues:add("desIdioma", "Valor customizado na UPC"). oValues:add("hraUltAtualiz", "17:18:19"). // criamos um novo field para desabilitar ASSIGN jObj = NEW JsonObject(). jObj:add('property', 'codIdiomPadr'). jObj:add('disabled', TRUE). oFields:add(jObj). ASSIGN cFocus = "desIdioma". ASSIGN jObj = NEW JsonObject(). jObj:add('code', '44'). jObj:add('message', 'A UPC alterou algumas caracteristica da tela.'). jObj:add('detailedMessage', 'Na execuçãoexecu‡Æo da UPC, houveram alteraçõesaltera‡äes nos campos de tela.'). oMessages:add(jObj). END. END. /* Exemplo de JSON de retorno para o HTML value: { desIdioma: 'Valor customizado na UPC' hraUltAtualiz: '17:18:19' }, fields: [ { property: 'codCpfCnpj', mask: '99.999.999/9999-99' } ], focus: 'hraUltAtualiz', _messages: [ { code: '01', message: 'Mensagem do erro que aconteceu', detailedMessage: 'detalhes do erro acontecido' } ] */ // atribui os valores de volta para a tela HTML jsonIO = NEW JSonObject(). oReturn = NEW JSonObject(). oReturn:add("value", oValues). // seta os valores dos campos ja ajustados oReturn:add("fields", oFields). // seta as propriedades dos campos a serem alteradas oReturn:add("focus", cFocus). // seta o campo de focus a ser retornado para a tela html oReturn:add("_messages", oMessages). // seta as mensagens a serem retornadas para a tela html jsonIO:add("root", oReturn). END PROCEDURE. PROCEDURE piValidateField: cProp = jsonIO:getCharacter("property") NO-ERROR. // o cProp contem o nome da propriedade que esta sendo validada LOG-MANAGER:WRITE-MESSAGE("UPC ValidateField property= " + cProp, ">>>>"). oReturn = jsonIO:getJsonObject("root") NO-ERROR. // obtem o retorno que sera enviado para a tela html cValue = oReturn:getCharacter("value") NO-ERROR. // pega o novo valor do campo atual oFieldObj = oReturn:getJsonObject("field") NO-ERROR. // obtem as propriedades dos campos a serem alteradas lFocus = oReturn:getLogical("focus") NO-ERROR. // obtem se o focus ficara sobre o mesmo campo ao retornar para a tela html oMessages = oReturn:getJsonArray("_messages") NO-ERROR. // obtem as mensagens a serem retornados para a tela html /* Exemplo de JSON que veio para a UPC { property: 'codAcao', returnroot: { value: '', field: { mask: '99.999.999/9999-99' }, focus: false, _messages: [ { code: '01', message: 'Mensagem do erro que aconteceu', detailedMessage: 'detalhes do erro acontecido' } ] } } */ IF cProp = "codAcoes" THEN DO: oFieldObj = NEW JsonObject(). oFieldObj:add('label', 'Novo label'). oFieldObj:add('required', TRUE). ASSIGN lFocus = TRUE cValue = "FocoDesIdioma". ASSIGN jObj = NEW JsonObject(). jObj:add('code', '44'). jObj:add('message', 'A UPC alterou algumas caracteristica da tela.'). jObj:add('detailedMessage', 'Na execuçãoexecu‡Æo da UPC, houveram alteraçõesaltera‡äes nos campos de tela.'). oMessages:add(jObj). END. /* Exemplo de JSON de retorno para o HTML value: 'FocoDesIdioma', field: { label: 'Novo Label', required: true }, focus: true, _messages: [ { code: '44', message: 'A UPC alterou algumas caracteristica da tela.', detailedMessage: 'Na execuçãoexecu‡Æo da UPC, houveram alteraçõesaltera‡äes nos campos de tela.' } ] */ // atribui os valores de volta para a tela HTML jsonIO = NEW JSonObject(). oReturn = NEW JSonObject(). oReturn:add("value", cValue). // mantem o valor seta os valores dos campos ja ajustados oReturn:add("field", oFieldObj). // seta as propriedades dos campos a serem alteradas oReturn:add("focus", lFocus). // seta o focus a ser retornado para a tela html oReturn:add("_messages", oMessages). // seta as mensagens a serem retornadas para a tela html jsonIO:add("root", oReturn). END PROCEDURE. /* fim */ |
Resultado ao chamar ao API tendo uma UPC cadastrada:
Ao fazer as requisições, virão os seguintes resultados na UPC.
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
Busca do METADADOS onde foram adicionados os novos campos codUsuario, nomUsuario e codDialet: POST - http://localhost:8180/dts/datasul-rest/resources/prg/trn/v1/idiomas/metadata {PROCEDURE piI18N: DEFINE VARIABLE oParser AS JsonAPIRequestParser NO-UNDO. "total": 9, "hasNext": false, "items": [ DEFINE VARIABLE oQueryParams AS JsonObject {NO-UNDO. DEFINE VARIABLE pIdioma "visible": true, AS CHARACTER "gridColumns": 6,NO-UNDO. ASSIGN "disable": true, oParser = "property": "codIdioma",NEW JsonAPIRequestParser(jsonIO) oQueryParams = oParser:GetQueryParams() "label": "Idioma", pIdioma = oQueryParams:GetJsonArray("typelanguage": "string"):GetCharacter(1). }, IF (pIdioma = "pt-BR") {THEN DO: jsonIO = "visible": true,NEW JsonObject(). "gridColumns": 6,jsonIO:Add("user", "Usu rio"). "property": "desIdioma",jsonIO:Add("name", "Nome"). "label": "DescriçãojsonIO:Add("regexTestValidation", "Teste Valida‡Æo REGEX"). "type": "stringjsonIO:Add("cpfMaskApply", "Aplica‡Æo M scara CPF"). jsonIO:Add("onlyNumbers", "required": true,Somente N£meros"). END. ELSE IF (pIdioma = "validate": "/api/trn/v1/idiomas/validateField"en-US") THEN DO: }, jsonIO = NEW JsonObject(). { jsonIO:Add("user", "User"). jsonIO:Add("visiblename": true,, "Name"). "gridColumns": 6, jsonIO:Add("regexTestValidation", "REGEX Test Validation"). "property": "codIdiomPadrjsonIO:Add("cpfMaskApply", "CPF Apply Mask"). "label":jsonIO:Add("onlyNumbers", "IdiomaOnly PadrãoNumbers",). END. END PROCEDURE. /* fim */ |
Resultado ao chamar ao API tendo uma UPC cadastrada:
Ao fazer as requisições, virão os seguintes resultados na UPC.
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
Busca do METADADOS onde foram "type": "string" },adicionados os novos campos codUsuario, nomUsuario e codDialet: POST - http://localhost:8180/dts/datasul-rest/resources/prg/trn/v1/idiomas/metadata { "total": 9, {"hasNext": false, "items": [ "visible": true, { "gridColumnsvisible": 6true, "disablegridColumns": true6, "propertydisable": "datUltAtualiz"true, "formatproperty": "dd/MM/yyyycodIdioma", "label": "Última AtualizaçãoIdioma", "type": "datestring" }, { "visible": true, "gridColumns": 6, "disableproperty": true"desIdioma", "propertylabel": "hraUltAtualizDescrição", "labeltype": "Hora Última Atualização""string", "required": true, "typevalidate": "string/api/trn/v1/idiomas/validateField" }, { "visible": true, "gridColumns": false6, "property": "idcodIdiomPadr", "typelabel": "numberIdioma Padrão", "keytype": true"string" }, { "visible": true, "gridColumns": 6, "disable": true, "property": "codUsuariodatUltAtualiz", "labelformat": "Usuáriodd/MM/yyyy", "typelabel": "stringÚltima Atualização", "requiredtype": true"date" }, { "visible": true, "gridColumns": 6, "propertydisable": "nomUsuario"true, "labelproperty": "NomehraUltAtualiz", "typelabel": "stringHora Última Atualização", "requiredtype": true"string" }, { "visible": truefalse, "gridColumnsproperty": 6"id", "propertytype": "codDialetnumber", "labelkey": "Dialeto", true }, "type": "string", { "requiredvisible": true, } ] } Busca dos dados onde foram adicionados novos valores: GET - http://localhost:8180/dts/datasul-rest/resources/prg/trn/v1/idiomas { "gridColumns": 6, "totalproperty": 3, "hasNextcodUsuario": false, "items": [ {"label": "Usuário", "codIdiomPadrtype": "99 Outrosstring", "codDialetrequired": "Pt",true }, "codIdioma": "ale", { "codUsuariovisible": "super"true, "desIdiomagridColumns": "Alemão"6, "hraUltAtualizproperty": "nomUsuario", "datUltAtualizlabel": null"Nome", "nomUsuariotype": "Superstring", "idrequired": 4580144true }, { "codIdiomPadrvisible": "99 Outros"true, "codDialetgridColumns": "PT"6, "codIdiomaproperty": "ENcodDialet", "codUsuariolabel": "joaoDialeto", "desIdiomatype": "Inglesstring", "hraUltAtualizrequired": "",true } "datUltAtualiz": null, "nomUsuario": "Joao da Silva", ] } Busca dos dados onde foram adicionados novos valores: GET - http://localhost:8180/dts/datasul-rest/resources/prg/trn/v1/idiomas { "total": 3, "idhasNext": 194736false, },"items": [ { "codIdiomPadr": "0399 EspanholOutros", "codDialet": "PTPt", "codIdioma": "ESale", "codUsuario": "Manoelsuper", "desIdioma": "EspanholAlemão", "hraUltAtualiz": "", "datUltAtualiz": null, "nomUsuario": "Manoel da SilvaSuper", "id": 29688984580144 }, ] } |
Front-End PO-UI
Introdução:
Para este exemplo vamos criar um CRUD com template dinâmico, onde serão mostrados os dados de acordo com o que o back-end retornar.
O desenvolvimento do frontend utilizando este campo componente se divide basicamente em três partes:
- Routes:
- Na definição da rota é onde vamos definir todos os caminhos dos componentes;
- HTML
- No HTML basta colocarmos os componentes, pois o metadados irá retornar o que precisamos para renderizar o componente;
- TypeScript
- No Typescript do componente vamos realizar uma pequena lógica para o tratamento dos dados de acordo com metadado;
Abaixo vamos mostrar como ficaram a parte de Listagem, Edição e Detalhe do nosso CRUD dinâmico.
Routes:
Abaixo segue exemplo de como ficará o arquivo de rotas de nossa aplicação CRUD.
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { IdiomaDetailComponent } from './idioma/detail/idioma-detail.component';
import { IdiomaEditComponent } from './idioma/edit/idioma-edit.component';
import { IdiomaListComponent } from './idioma/list/idioma-list.component';
const routes: Routes = [
{ path: 'idiomas/create', component: IdiomaEditComponent },
{ path: 'idiomas/edit/:id', component: IdiomaEditComponent },
{ path: 'idiomas/detail/:id', component: IdiomaDetailComponent },
{ path: 'idiomas', component: IdiomaListComponent },
{ path: '', redirectTo: '/idiomas', pathMatch: 'full' },
{ path: '**', component: IdiomaListComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
|
Listagem:
É a tela inicial da nossa aplicação e mostra a lista de dados da tabela Idioma, onde foram adicionados através de customização três campos da tabela usuar_mestre. Esta tela dará acesso às outras funcionalidades como edição e detalhamento.
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<po-loading-overlay
[hidden]="!showLoading">
</po-loading-overlay>
<po-page-dynamic-table
p-auto-router
[p-title]="cTitle"
[p-actions]="actions"
[p-breadcrumb]="breadcrumb"
[p-fields]="fields"
[p-service-api]="serviceApi">
</po-page-dynamic-table>
|
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { PoBreadcrumb } from '@po-ui/ng-components';
import { PoPageDynamicTableActions } from '@po-ui/ng-templates';
import { IdiomaService } from './../resources/idioma.service';
@Component({
selector: 'app-idioma-list',
templateUrl: './idioma-list.component.html',
styleUrls: ['./idioma-list.component.css']
})
export class IdiomaListComponent implements OnInit {
// Definicao das variaveis utilizadas
public cTitle = 'Manutenção de Idiomas';
public serviceApi: string;
public fields: Array<any> = [];
public showLoading = false;
public readonly actions: PoPageDynamicTableActions = {
new: '/idiomas/create',
detail: '/idiomas/detail/:id',
edit: '/idiomas/edit/:id',
remove: true,
removeAll: true
};
public readonly breadcrumb: PoBreadcrumb = {
items: [
{ label: 'Home', link: '/' },
{ label: 'Idiomas'}
]
};
// Construtor da classe
constructor(
private service: IdiomaService,
private route: Router
) { }
// Load do componente
public ngOnInit(): void {
this.fields = [];
this.serviceApi = this.service.getUrl();
this.showLoading = true;
this.service.getMetadata().subscribe(resp => {
this.fields = resp['items'];
this.service.setFieldList(this.fields);
this.showLoading = false;
});
}
} |
Edição:
{
"codIdiomPadr": "99 Outros",
"codDialet": "PT",
"codIdioma": "EN",
"codUsuario": "joao",
"desIdioma": "Ingles",
"hraUltAtualiz": "",
"datUltAtualiz": null,
"nomUsuario": "Joao da Silva",
"id": 194736
},
{
"codIdiomPadr": "03 Espanhol",
"codDialet": "PT",
"codIdioma": "ES",
"codUsuario": "Manoel",
"desIdioma": "Espanhol",
"hraUltAtualiz": "",
"datUltAtualiz": null,
"nomUsuario": "Manoel da Silva",
"id": 2968898
}
]
} |
Front-End PO-UI
Introdução:
Para este exemplo vamos criar um CRUD com template dinâmico, onde serão mostrados os dados de acordo com o que o back-end retornar.
O desenvolvimento do frontend utilizando este campo componente se divide basicamente em três partes:
- Routes:
- Na definição da rota é onde vamos definir todos os caminhos dos componentes;
- HTML
- No HTML basta colocarmos os componentes, pois o metadados irá retornar o que precisamos para renderizar o componente;
- TypeScript
- No Typescript do componente vamos realizar uma pequena lógica para o tratamento dos dados de acordo com metadado;
Abaixo vamos mostrar como ficaram a parte de Listagem, Edição e Detalhe do nosso CRUD dinâmico.
Routes:
Abaixo segue exemplo de como ficará o arquivo de rotas de nossa aplicação CRUD.
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { IdiomaDetailComponent } from './idioma/detail/idioma-detail.component';
import { IdiomaEditComponent } from './idioma/edit/idioma-edit.component';
import { IdiomaListComponent } from './idioma/list/idioma-list.component';
const routes: Routes = [
{ path: 'idiomas/create', component: IdiomaEditComponent },
{ path: 'idiomas/edit/:id', component: IdiomaEditComponent },
{ path: 'idiomas/detail/:id', component: IdiomaDetailComponent },
{ path: 'idiomas', component: IdiomaListComponent },
{ path: '', redirectTo: '/idiomas', pathMatch: 'full' },
{ path: '**', component: IdiomaListComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
|
Listagem:
É a tela inicial da nossa aplicação e mostra a lista de dados da tabela Idioma, onde foram adicionados através de customização três campos da tabela usuar_mestre. Esta tela dará acesso às outras funcionalidades como edição e detalhamentoEsta tela permite a inclusão de um novo registro na tabela Idioma e também a alteração de registros já existentes.
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<po-loading-overlay [hidden]="!showLoading"> </po-loading-overlay> <po-page-editdynamic-table p-auto-router [p-title]="cTitle" [p-breadcrumbactions]="breadcrumbactions" [p-disable-submitbreadcrumb]="formEdit.form.invalidbreadcrumb" ([p-cancel)fields]="cancelClick()fields" ([p-service-save)api]="saveClick()serviceApi"> <po</po-page-dynamic-form #formEdit p-auto-focus="string" [p-fields]="fields" p-validate="/api/trn/v1/idiomas/validateForm" [p-value]="record"> </po-dynamic-form> </po-page-edit> table> |
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
Bloco de código | ||||||||
| ||||||||
import { Component, OnInit, ViewChild } from '@angular/core'; import { NgFormRouter } from '@angular/formsrouter'; import { ActivatedRoute,PoBreadcrumb Router } from '@angular/router@po-ui/ng-components'; import { PoBreadcrumb, PoDialogService, PoNotificationServicePoPageDynamicTableActions } from '@po-ui/ng-componentstemplates'; import { IdiomaService } from './../resources/idioma.service'; @Component({ selector: 'app-idioma-editlist', templateUrl: './idioma-editlist.component.html', styleUrls: ['./idioma-editlist.component.css'] }) export class IdiomaEditComponentIdiomaListComponent implements OnInit { // DefineDefinicao asdas variaveis a serem utilizadas public cTitle: string; = 'Manutenção public currentId: stringde Idiomas'; public record = {}serviceApi: string; public fields: Array<any> = []; public isUpdateshowLoading = false; public readonly actions: showLoadingPoPageDynamicTableActions = false;{ public breadcrumbnew: PoBreadcrumb; // Obtem a referencia do componente HTML @ViewChild('formEdit', { static: true }) formEdit: NgForm; // Construtor da classe com os servicos necessarios constructor( private service: IdiomaService, private activatedRoute: ActivatedRoute, private route: Router,'/idiomas/create', detail: '/idiomas/detail/:id', edit: '/idiomas/edit/:id', remove: true, removeAll: true }; public readonly breadcrumb: PoBreadcrumb = { items: [ { label: 'Home', link: '/' }, { label: 'Idiomas'} ] }; // Construtor da classe constructor( private poDialogservice: PoDialogServiceIdiomaService, private poNotificationroute: PoNotificationServiceRouter ) { } // Load do componente public ngOnInit(): void { this.isUpdatefields = false[]; this.showLoadingserviceApi = true; this.service.getUrl(); // Carrega o registro pelo IDthis.showLoading = true; this.activatedRouteservice.paramsgetMetadata().subscribe(parsresp => { this.currentIdfields = parsresp['iditems']; // Se nao tiver o ID definido sera um CREATEthis.service.setFieldList(this.fields); this.showLoading = false; }); } } |
Edição:
Esta tela permite a inclusão de um novo registro na tabela Idioma e também a alteração de registros já existentes.
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<po-loading-overlay
[hidden]="!showLoading">
</po-loading-overlay>
<po-page-edit
[p-title]="cTitle"
[p-breadcrumb]="breadcrumb"
[p-disable-submit]="formEdit.form.invalid"
(p-cancel)="cancelClick()"
(p-save)="saveClick()">
<po-dynamic-form
#formEdit
p-auto-focus="string"
[p-fields]="fields"
p-validate="/api/trn/v1/idiomas/validateForm"
[p-value]="record">
</po-dynamic-form>
</po-page-edit>
|
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
import { Component, OnInit, ViewChild } from '@angular/core'; import { NgForm } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { PoBreadcrumb, PoDialogService, PoNotificationService } from '@po-ui/ng-components'; import { IdiomaService } from './../resources/idioma.service'; @Component({ selector: 'app-idioma-edit', templateUrl: './idioma-edit.component.html', styleUrls: ['./idioma-edit.component.css'] }) export class IdiomaEditComponent implements OnInit { // Define as variaveis a serem utilizadas public cTitle: string; public currentId: string; public record = {}; public fields: Array<any> = []; public isUpdate = false; public showLoading = false; public breadcrumb: PoBreadcrumb; // Obtem a referencia do componente HTML @ViewChild('formEdit', { static: true }) formEdit: NgForm; // Construtor da classe com os servicos necessarios constructor( private service: IdiomaService, private activatedRoute: ActivatedRoute, private route: Router, private poDialog: PoDialogService, private poNotification: PoNotificationService ) { } // Load do componente public ngOnInit(): void { this.isUpdate = false; this.showLoading = true; // Carrega o registro pelo ID this.activatedRoute.params.subscribe(pars => { this.currentId = pars['id']; // Se nao tiver o ID definido sera um CREATE if (this.currentId === undefined) if (this.currentId === undefined) { this.isUpdate = false; this.cTitle = 'Inclusão de Idioma'; } else { this.isUpdate = true; this.cTitle = 'Alteração de Idioma'; } // Atualiza o breadcrumb de acordo com o tipo de edicao this.breadcrumb = { items: [ { label: 'Home', action: this.beforeRedirect.bind(this) }, { label: 'Idiomas', action: this.beforeRedirect.bind(this) }, { label: this.cTitle } ] }; // Se for uma alteracao, busca o registro a ser alterado if (this.isUpdate) { this.service.getById(this.currentId).subscribe(resp => { Object.keys(resp).forEach((key) => this.record[key] = resp[key]); // Em alteracao temos que receber o registro para depois buscar a lista de campos this.getMetadata(); }); } else { // Se for create, pega a lista de camposthis.isUpdate = false; this.cTitle = 'Inclusão de Idioma'; } else { this.getMetadata()isUpdate = true; } this.cTitle = })'Alteração de Idioma'; } // RetornaAtualiza ao listabreadcrumb de campos acordo com o privatetipo getMetadata()de {edicao let fieldList: Array<any>this.breadcrumb = [];{ // Carrega a lista de campos, trabalhando com um cache da lista de campos fieldList = this.service.getFieldList(this.isUpdate);items: [ { label: 'Home', action: this.beforeRedirect.bind(this) }, if (fieldList === null || fieldList.length === 0) { label: 'Idiomas', action: this.servicebeforeRedirect.getMetadatabind().subscribe(resp => { this) }, { label: this.service.setFieldList(resp['items']); cTitle } ] this.fields = this.service.getFieldList(this.isUpdate); }; // Se this.showLoadingfor = false; }); uma alteracao, busca o registro a ser alterado } elseif (this.isUpdate) { this.service.getById(this.fieldscurrentId).subscribe(resp => fieldList;{ this.showLoading Object.keys(resp).forEach((key) => this.record[key] = falseresp[key]); } } // Em Redirecionaalteracao viatemos breadcrumb que receber private beforeRedirect(itemBreadcrumbLabel) { if (this.formEdit.valid) {o registro para depois buscar a lista de campos this.route.navigate(['/']getMetadata(); }); else { } else this.poDialog.confirm({ title:// `Confirma o redirecionamento para ${itemBreadcrumbLabel}`, Se for create, pega a lista de campos message: `Existem dados que não foram salvos ainda. Você tem certeza que quer sair ?`, confirm: () => this.route.navigate(['/']) }); } } // Grava o registro quando clicado no botao Salvar public saveClick(): void { this.showLoading = true; if (this.isUpdate) { // Altera um registro ja existente this.getMetadata(); } }); } // Retorna a lista de campos private getMetadata() { let fieldList: Array<any> = []; // Carrega a lista de campos, trabalhando com um cache da lista de campos fieldList = this.service.getFieldList(this.isUpdate); if (fieldList === null || fieldList.length === 0) { this.service.update(this.currentId, this.recordgetMetadata().subscribe(resp => { this.poNotificationservice.successsetFieldList('Idioma alterado com sucesso'resp['items']); this.showLoadingfields = falsethis.service.getFieldList(this.isUpdate); this.route.navigate(['/idiomas'])showLoading = false; }); } else { // Cria um registro novothis.fields = fieldList; this.service.create(this.record).subscribe(respshowLoading => {false; } } this.poNotification.success('Idioma criado com sucesso'); // Redireciona via breadcrumb private beforeRedirect(itemBreadcrumbLabel) { if (this.formEdit.showLoading = false;valid) { this.route.navigate(['/idiomas']); }); } } else { // Cancela a edicao e redireciona ao clicar no botao Cancelar public cancelClick(): void { this.poDialog.confirm({ title: 'Confirma cancelamento', `Confirma o redirecionamento para ${itemBreadcrumbLabel}`, message: 'Existem`Existem dados que não foram salvos ainda. Você tem certeza que quer cancelarsair ?'`, confirm: () => this.route.navigate(['/']) }); } } |
Detalhe:
Esta tela apresenta os detalhes de um registro de Idioma, com suas customizações.
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<po-loading-overlay
[hidden]="!showLoading">
</po-loading-overlay>
<po-page-detail
[p-title]="cTitle"
[p-breadcrumb]="breadcrumb"
(p-edit)="editClick()"
(p-back)="goBackClick()">
<po-dynamic-view
[p-fields]="fields"
[p-value]="record">
</po-dynamic-view>
</po-page-detail>
|
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { PoBreadcrumb } from '@po-ui/ng-components'; import { IdiomaService } from './../resources/idioma.service'; @Component({ selector: 'app-idioma-detail', templateUrl: './idioma-detail.component.html', styleUrls: ['./idioma-detail.component.css'] }) export class IdiomaDetailComponent implements OnInit { // definicao das variaveis utilizadas public cTitle = 'Detalhe do Idioma'; public currentId: string; public fields: Array<any> = []; public record = {}; public } // Grava o registro quando clicado no botao Salvar public saveClick(): void { this.showLoading = true; if (this.isUpdate) { // Altera um registro ja existente this.service.update(this.currentId, this.record).subscribe(resp => { this.poNotification.success('Idioma alterado com sucesso'); this.showLoading = false; this.route.navigate(['/idiomas']); }); } else { // Cria um registro novo this.service.create(this.record).subscribe(resp => { this.poNotification.success('Idioma criado com sucesso'); this.showLoading = false; public readonly breadcrumb: PoBreadcrumb = { items: [ this.route.navigate(['/idiomas']); }); } } // Cancela a edicao e redireciona ao clicar no botao Cancelar public cancelClick(): void { this.poDialog.confirm({ title: 'Confirma cancelamento', message: 'Existem dados que não foram salvos ainda. Você tem certeza que quer cancelar ?', confirm: () => this.route.navigate(['/']) }); } } |
Detalhe:
Esta tela apresenta os detalhes de um registro de Idioma, com suas customizações.
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<po-loading-overlay
[hidden]="!showLoading">
</po-loading-overlay>
<po-page-detail
[p-title]="cTitle"
[p-breadcrumb]="breadcrumb"
(p-edit)="editClick()"
(p-back)="goBackClick()">
<po-dynamic-view
[p-fields]="fields"
[p-value]="record">
</po-dynamic-view>
</po-page-detail>
|
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { PoBreadcrumb } from '@po-ui/ng-components'; import { IdiomaService } from './../resources/idioma.service'; @Component({ selector: 'app-idioma-detail', templateUrl: './idioma-detail.component.html', styleUrls: ['./idioma-detail.component.css'] }) export class IdiomaDetailComponent implements OnInit { // definicao das variaveis utilizadas public cTitle = 'Detalhe do Idioma'; public currentId: string; public fields: Array<any> = []; public record = {}; public showLoading = false; public readonly breadcrumb: PoBreadcrumb = { items: [ { label: 'Home', link: '/' }, { label: 'Idiomas', link: '/idiomas' }, { label: 'Detail' } ] }; // construtor com os servicos necessarios constructor( private service: IdiomaService, private activatedRoute: ActivatedRoute, private route: Router ) {{ label: 'Home', link: '/' }, { label: 'Idiomas', link: '/idiomas' }, { label: 'Detail' } ] }; // construtor com os servicos necessarios constructor( private service: IdiomaService, private activatedRoute: ActivatedRoute, private route: Router ) { } // load do componente public ngOnInit(): void { this.activatedRoute.params.subscribe(pars => { this.showLoading = true; // carrega o registro pelo ID this.currentId = pars['id']; this.service.getById(this.currentId).subscribe(resp => { Object.keys(resp).forEach((key) => this.record[key] = resp[key]); // carrega a lista de campos somente apos receber o registro a ser apresentado this.fields = this.service.getFieldList(false); if (this.fields === null || this.fields.length === 0) { this.service.getMetadata().subscribe(data => { this.fields = data['items']; this.service.setFieldList(this.fields); this.showLoading = false; }); } this.showLoading = false; }); }); } // Redireciona quando clicar no botao Edit public editClick(): void { this.route.navigate(['/idiomas', 'edit', this.currentId]); } // Redirecionaload quando clicar no botao Voltardo componente public goBackClickngOnInit(): void { this.activatedRoute.routeparams.navigate(['/idiomas']); } } |
06. VALIDAÇÃO DE COMPONENTES
Para os itens a seguir, são apresentados algumas formas de interação com os componentes presentes na interface, bem como possíveis validações sobre os mesmos.
Esconder ou visualizar os campos
Como a geração da tela dinâmica é automática, para esconder determinados campos basta setar o atributo visible para FALSE na montagem do JsonObject de retorno do metadados.
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
...
ASSIGN jObj = NEW JsonObject().
jObj:add('property', 'codDialet').
jObj:add('label', 'Dialeto').
jObj:add('visible', FALSE). // <- Remove o item da tela de todos seus correspondentes (Form, View, Table)
jObj:add('required', TRUE).
jObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('character')).
jObj:add('gridColumns', 6).
jObj:add('validate', '/api/trn/v1/idiomas/validateField').
jAList:add(jObj).
... |
Validação de componentes na interface
Uma boa prática em desenvolvimento de telas é a validação de alguns campos na própria interface, cujo intuito é reduzir requisições desnecessárias ao 'Back-End'. As funcionalidades apresentadas a seguir podem ser utilizadas conjunto com a validação do próprio Form ([p-disable-submit]="formEdit.form.invalid"), no qual pode desabilitar o botão de confirmação enquanto houver campos inválidos.
Utilização do pattern (RegEx)
Para a validação de campos textos, pode ser utilizado o atributo pattern qualquer expressão regular, caso não atenda ao RegEx, uma mensagem de erro definida em errorMessage é apresentada em tela.
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
...
ASSIGN jObj = NEW JsonObject().
jObj:add('property', 'testeValidacaoRegEx').
jObj:add('label', 'Teste Validação RegEx').
jObj:add('gridColumns', 6).
jObj:add('pattern', "[0-9]~{2~}"). // <- Validacao RegEx
jObj:add('errorMessage', 'Obrigatório mínimo 2 números consecutivos.').
jAList:add(jObj).
...
|
Utilização de limites em numeração
subscribe(pars => {
this.showLoading = true;
// carrega o registro pelo ID
this.currentId = pars['id'];
this.service.getById(this.currentId).subscribe(resp => {
Object.keys(resp).forEach((key) => this.record[key] = resp[key]);
// carrega a lista de campos somente apos receber o registro a ser apresentado
this.fields = this.service.getFieldList(false);
if (this.fields === null || this.fields.length === 0) {
this.service.getMetadata().subscribe(data => {
this.fields = data['items'];
this.service.setFieldList(this.fields);
this.showLoading = false;
});
}
this.showLoading = false;
});
});
}
// Redireciona quando clicar no botao Edit
public editClick(): void {
this.route.navigate(['/idiomas', 'edit', this.currentId]);
}
// Redireciona quando clicar no botao Voltar
public goBackClick(): void {
this.route.navigate(['/idiomas']);
}
} |
06. VALIDAÇÃO DE COMPONENTES
Para os itens a seguir, são apresentados algumas formas de interação com os componentes presentes na interface, bem como possíveis validações sobre os mesmos.
Esconder ou visualizar os campos
Como a geração da tela dinâmica é automática, para esconder determinados campos basta setar o atributo visible para FALSE na montagem do JsonObject de retorno do metadados. Com a utilização dos atributos minValue e maxValue, é possível efetuar a restrição de períodos da numeração que pode ser utilizado em conjunto com o type para restringir a digitação em somente números. Caso houver números inválidos, a mensagem definida em errorMessage é apresentada na tela.
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
... ASSIGN jObj = NEW JsonObject(). jObj:add('property', 'numberValidatecodDialet'). jObj:add('label', 'Somente númerosDialeto'). jObj:add('visible', TRUEFALSE). // <- jObj:add('required', FALSE). jObj:add('minValue', 1). jObj:add('maxValue', 9).Remove o item da tela de todos seus correspondentes (Form, View, Table) jObj:add('errorMessagerequired', 'Somente números de 1 a 9'). // <- Mensagem de erro 1-9TRUE). jObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('integercharacter')). // <- Restringe a digitacao somente numeros jObj:add('gridColumns', 6). jAListjObj:add(jObj'validate', '/api/trn/v1/idiomas/validateField'). jAList:add(jObj). ... |
Utilização de máscaras para os campos
Validação de componentes na interface
Uma boa prática em desenvolvimento de telas é a validação de alguns campos na própria interface, cujo intuito é reduzir requisições desnecessárias ao 'Back-End'. As funcionalidades apresentadas a seguir podem ser utilizadas conjunto com a validação do próprio Form ([p-disable-submit]="formEdit.form.invalid"), no qual pode desabilitar o botão de confirmação enquanto houver campos inválidos.
Utilização do pattern (RegEx)
Para a validação de campos textos, pode ser utilizado o atributo pattern qualquer expressão regular, caso não atenda ao RegEx, uma mensagem de erro definida em errorMessage é apresentada em tela. Quando é definida uma máscara mask, ocorre a restrição de digitação no próprio campo. Para o exemplo abaixo, é permitido digitar somente números e ao efetuar a digitação, a máscara será aplicada automaticamente.
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
... ASSIGN jObj = NEW JsonObject(). jObj:add('property', 'numberRangeValidatetesteValidacaoRegEx'). jObj:add('label', 'AplicaçãoTeste deValidação máscara CPFRegEx'). jObj:add('maskgridColumns', '999.999.999-99'6). jObj:add('pattern', "[0-9]~{2~}"). // <-- MascaraValidacao CPFRegEx jObj:add('visibleerrorMessage', TRUE 'Obrigatório mínimo 2 números consecutivos.'). jAList:add(jObj). ... |
Utilização de limites em numeração
Com a utilização dos atributos minValue e maxValue, é possível efetuar a restrição de períodos da numeração que pode ser utilizado em conjunto com o type para restringir a digitação em somente números. Caso houver números inválidos, a mensagem definida em errorMessage é apresentada na tela.
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
... ASSIGN jObj = NEW JsonObject(). jObj:add('requiredproperty', FALSE'numberValidate'). jObj:add('typelabel', JsonAPIUtils:convertAblTypeToHtmlType('character'Somente números')). jObj:add('gridColumnsvisible', 6TRUE). jAListjObj:add(jObj). ... |
Validações no back-end
O po-dynamic-form permite dois tipos de validações, a validação do formulário completo ou por campo.
A validação do formulário completo vamos detalhar mais a frente.
A validação por campo é feito através da validação campo-a-campo, onde você conseguirá alterar algumas características do campo que esta sendo validado.
Aviso |
---|
Nas validações de campos é possível somente alterar as características do próprio campo validado, onde não é permitido alterar nas características de outros campos. |
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
... ASSIGN jObj = NEW JsonObject('required', FALSE). jObj:add('minValue', 1). jObj:add('propertymaxValue', 'nomCampo'9). jObj:add('labelerrorMessage', 'Label do campoSomente números de 1 a 9'). // <- Mensagem jObj:add('visible', TRUE).de erro 1-9 jObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('characterinteger')). // <- jObj:add('validate', '/api/trn/v1/idiomas/validateField'Restringe a digitacao somente numeros jObj:add('gridColumns', 6). jAList:add(jObj). ... |
A adição da tag validate na definição do campo, onde deverá ser especificado a URL de validação, fará com que sempre que o campo for alterado pelo usuário, será enviado uma requisição para o back-end para realizar a validação desse campo.
JSon que recebemos da tela HTML
O componente PO-DYNAMIC-FORM, quando ocorre alguma alteração em seus campos, no LEAVE do campo, ele enviará um JSon com o seguinte formato para o back-end:
...
Utilização de máscaras para os campos
Quando é definida uma máscara mask, ocorre a restrição de digitação no próprio campo. Para o exemplo abaixo, é permitido digitar somente números e ao efetuar a digitação, a máscara será aplicada automaticamente.
Onde o back-end receberá o seguinte JSon:
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
{ ... "property": "campoValidado",ASSIGN jObj = NEW JsonObject(). "value": "valorAtualDoCampoValidado" } |
JSon que retornamos para a tela HTML
A validação do campo, aguarda o seguinte formato de JSon:
...
jObj:add('property', 'numberRangeValidate').
jObj:add('label', 'Aplicação de máscara CPF').
jObj:add('mask', '999.999.999-99'). // <-- Mascara CPF
jObj:add('visible', TRUE).
jObj:add('required', FALSE).
jObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('character')).
jObj:add('gridColumns', 6).
jAList:add(jObj).
... |
Validações no back-end
O po-dynamic-form permite dois tipos de validações, a validação do formulário completo ou por campo.
A validação do formulário completo vamos detalhar mais a frente.
A validação por campo é feito através da validação campo-a-campo, onde você conseguirá alterar algumas características do campo que esta sendo validado.
Aviso |
---|
Nas validações de campos é possível somente alterar as características do próprio campo validado, onde não é permitido alterar nas características de outros campos. |
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
...
ASSIGN jObj = NEW JsonObject().
jObj:add('property', 'nomCampo').
jObj:add('label', 'Label do campo').
jObj:add('visible', TRUE).
jObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('character')).
jObj:add('validate', '/api/trn/v1/idiomas/validateField'
jObj:add('gridColumns', 6).
jAList:add(jObj).
... |
A adição da tag validate na definição do campo, onde deverá ser especificado a URL de validação, fará com que sempre que o campo for alterado pelo usuário, será enviado uma requisição para o back-end para realizar a validação desse campo.
JSon que recebemos da tela HTML
O componente PO-DYNAMIC-FORM, quando ocorre alguma alteração em seus campos, no LEAVE do campo, ele enviará um JSon com o seguinte formato para o back-end
O back-end, após processar e realizar a validação necessária, retornará para o front-end o seguinte JSon:
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
{
value: 'novoValorDoCampoValidado',
field: {
mask: '99.999.999/9999-99',
required: true
},
focus: true,
_messages: [
{
code: '01',
message: 'Mensagem do erro que aconteceu',
detailedMessage: 'detalhes do erro acontecido'
}
]
} |
Para utilizarmos a UPC de customização, tivemos que encapsular o JSon recebido no back-end, dentro da procedure pValidateField, e tambem o JSon a ser enviado para a tela HTML, conforme o exemplo abaixo:
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
// encapsulamos o retorno para enviar para a UPC
oObj = NEW JsonObject().
oObj:add("property", cProp).
oObj:add("root", oRet).
// Realiza a chamada da UPC Progress
{include/i-epcrest.i &endpoint=validateField &event=validateField &jsonVar=oObj}
// obtem o retorno customizado, onde o mesmo foi alterado e retornado na tag root
oRet = oObj:getJsonObject("root"). |
Neste nosso exemplo, nós dividimos o JSon a ser enviado para UPC em três partes, que são:
Tag | Tipo | Descrição |
---|---|---|
property | Character | Comtêm Contêm o nome do campo que esta sendo houve a alteração para ser validado. |
rootvalue | JSonObjectCharacter | Contêm um JSonObject com que será retornado para o HTML e que poderá ser customizado na UPC. Tudo que for customizado deverá estar dentro desta tag. |
Exemplo de JSon recebido pela UPC:
o valor atual do campo para ser validado. |
Onde o back-end receberá o seguinte JSon:
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
Bloco de código | ||||||
| ||||||
{ "property": 'nomeDoCampoValidado'"campoValidado", "value": "valorAtualDoCampoValidado" } |
JSon que retornamos para a tela HTML
A validação do campo, aguarda o seguinte formato de JSon:
Tag | Tipo | Descrição |
---|---|---|
value | Character | Contêm o novo valor para o campo. |
field | JSonObject | Contêm uma lista de propriedades que serão alteradas. OBS: Estas propriedades tem efeito somente sobre o campo que está sendo validado. |
focus | Logical | Informa se o campo validado deverá ou não receber o focus. |
_messages | JSonArray | Contêm uma lista de mensagens "de erro" que podem ser apresentadas ao voltar para o HTML. |
O back-end, após processar e realizar a validação necessária, retornará para o front-end o seguinte JSon:
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
{ value: 'novoValorDoCampoValidadoroot: { value: '', field: { mask: '99.999.999/9999-99', required: },true }, focus: falsetrue, _messages: [ { code: '01', message: 'Mensagem do erro que aconteceu', detailedMessage: 'detalhes do erro acontecido' } ] } } |
Após Para utilizarmos a customização pela UPC, sera devolvido para a API Rest apenas a tag root, com as customizações necessárias, conforme o exemplo abaixo onde temos o resultado de uma customização:UPC de customização, tivemos que encapsular o JSon recebido no back-end, dentro da procedure pValidateField, e tambem o JSon a ser enviado para a tela HTML, conforme o exemplo abaixo:
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
Bloco de código | ||||||
| ||||||
{ // encapsulamos o retorno para enviar para a UPC oObj = NEW JsonObject(). oObj:add("property", cProp). oObj:add("root", oRet). // Realiza a chamada da UPC Progress {include/i-epcrest.i &endpoint=validateField &event=validateField &jsonVar=oObj} // obtem o retorno customizado, onde o mesmo foi alterado e retornado na tag root oRet = oObj:getJsonObject("root"). |
Neste nosso exemplo, nós dividimos o JSon a ser enviado para UPC em três partes, que são:
Tag | Tipo | Descrição |
---|---|---|
property | Character | Comtêm o nome do campo que esta sendo validado. |
root | JSonObject | Contêm um JSonObject com que será retornado para o HTML e que poderá ser customizado na UPC. Tudo que for customizado deverá estar dentro desta tag. |
Exemplo de JSon recebido pela UPC:
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
{ property: 'nomeDoCampoValidado', root: { value: '', field: { mask: '99.999.999/9999-99', label: 'Novo Label' }, focus: false, _messages: [ { codevalue: '01', field: { mask: '99.999.999/9999-99' }, focus: false, _messages: [ { code: '01', message: 'Mensagem do erro que aconteceu', detailedMessage: 'detalhes do erro acontecido' } ] } |
07. VALIDAÇÃO DE FORMULÁRIOS
O quê deve ser alterado no componente PO-DYNAMIC-FORM
Para validarmos um formulário, temos que configurar primeiro o nosso componente po-dynamic-form para ficar apto a enviar as ocorrências de validações. Para isso temos que especificar no componente po-dynamic-form a tag p-validate, onde informamos a URL que fará a validação do form, neste exemplo será "/api/trn/v1/idiomas/validateForm".
} |
Após a customização pela UPC, sera devolvido para a API Rest apenas a tag root, com as customizações necessárias, conforme o exemplo abaixo onde temos o resultado de uma customização:
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
Bloco de código | ||||||||
| ||||||||
{ <po-dynamic-form value: '', field: #formEdit{ p-auto-focus="string" mask: '99.999.999/9999-99', label: 'Novo Label' [p-fields]="fields" }, p-validate="/api/trn/v1/idiomas/validateForm"focus: false, [p-value]="record"> </po-dynamic-form> |
Aviso |
---|
As validações de formulário validam somente os campos já existentes, onde não é permitido adicionar novos campos. Para adicionar novos campos deve-se utilizar a tag p-load, que é executada logo após a inicialização do componente. |
JSon que recebemos da tela HTML
_messages: [
{
code: '01',
message: 'Mensagem do erro que aconteceu',
detailedMessage: 'detalhes do erro acontecido'
}
]
} |
07. VALIDAÇÃO DE FORMULÁRIOS
O quê deve ser alterado no componente PO-DYNAMIC-FORM
Para validarmos um formulário, temos que configurar primeiro o nosso componente po-dynamic-form para ficar apto a enviar as ocorrências de validações. Para isso temos que especificar no componente po-dynamic-form a tag p-validate, onde informamos a URL que fará a validação do form, neste exemplo será "/api/trn/v1/idiomas/validateForm".
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<po-dynamic-form
#formEdit
p-auto-focus="string"
[p-fields]="fields"
p-validate="/api/trn/v1/idiomas/validateForm"
[p-value]="record">
</po-dynamic-form> |
Aviso |
---|
As validações de formulário validam somente os campos já existentes, onde não é permitido adicionar novos campos. Para adicionar novos campos deve-se utilizar a tag p-load, que é executada logo após a inicialização do componente. |
JSon que recebemos da tela HTML
O componente PO-O componente PO-DYNAMIC-FORM, quando ocorre alguma alteração em seus campos, no LEAVE do campo, ele enviará um JSon com o seguinte formato para o back-end:
...
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
{ value: value: { desIdioma: 'teste de escrita', hraUltAtualiz: '17:18:19' }, fields: [ { property: 'codCpfCnpj', mask: '99.999.999/9999-99' } ], focus: 'hraUltAtualiz', _messages: [ { code: '01', message: 'Mensagem do erro que aconteceu', detailedMessage: 'detalhes do erro acontecido' } ] } |
Para utilizarmos a UPC de customização, tivemos que encapsular o JSon recebido no back-end, dentro da procedure pValidateForm, e tambem o JSon a ser enviado para a tela HTML, conforme o exemplo abaixo:
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
// encapsulamos o retorno para enviar para a UPC
oObj = NEW JsonObject().
oObj:add("property", cProp).
oObj:add("originalValues", oValue).
oObj:add("root", oRet).
// Realiza a chamada da UPC Progress
{include/i-epcrest.i &endpoint=validateForm &event=validateForm &jsonVar=oObj}
// obtem o retorno customizado, onde o mesmo foi alterado e retornado na tag root
oRet = oObj:getJsonObject("root"). |
Neste nosso exemplo, nós dividimos o JSon a ser enviado para UPC em três partes, que são:
Tag | Tipo | Descrição |
---|---|---|
property | Character | Comtêm o nome do campo que esta sendo validado. |
originalValues | JsonObject | Contêm um JSonObject com propriedades contendo os nomes dos campos e os seus respectivos valores. |
root | JSonObject | Contêm um JSonObject com que será retornado para o HTML e que poderá ser customizado na UPC. Tudo que for customizado deverá estar dentro desta tag. |
Exemplo de JSon recebido pela UPC:
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
{
property: 'codAcao',
originalValues: {
"codIdiomPadr": "01 Português",
"codIdioma": "12345678",
"desIdioma": "12345678901234567890",
"hraUltAtualiz": "",
"datUltAtualiz": null,
"id": 6,
"codAcoes": "FocoDesIdioma"
},
root: {
value: {
desIdioma: 'teste de escrita',
hraUltAtualiz: '17:18:19'
},
fields: [
{
property: 'codCpfCnpj',
mask: '99.999.999/9999-99'
}
],
focus: 'hraUltAtualiz',
_messages: [
{
code: '01',
message: 'Mensagem do erro que aconteceu',
detailedMessage: 'detalhes do erro acontecido'
}
]
}
} |
Após a customização pela UPC, sera devolvido para a API Rest apenas a tag root, com as customizações necessárias, conforme o exemplo abaixo onde temos o resultado de uma customização:
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
{
"_messages": [
{
"detailedMessage": "Na execução da UPC, houveram alterações nos campos de tela.",
"code": "44",
"message": "A UPC alterou algumas caracteristica da tela."
}
],
"focus": "desIdioma",
"fields": [
{
"property": "codIdiomPadr",
"disabled": true
}
],
"value": {
"desIdioma": "Valor customizado na UPC"
}
} |
08. FACILITADORES PROGRESS
Criamos facilitadores para auxiliar no desenvolvimento das API's, ficam localizados na classe Progress "com.totvs.framework.api.JsonAPIUtils":
Método | Descrição | Assinatura/Exemplo |
---|---|---|
convertAblTypeToHtmlType | Converte os tipos nativos do Progress para os tipos esperados pelo PO-UI | Assinatura: convertAblTypeToHtmlType (INPUT cType AS CHARACTER) Exemplo: ASSIGN cType = JsonAPIUtils:convertAblTypeToHtmlType ("integer"). O retorno no cType será "number", que é um formato reconhecido pelo PO-UI. |
convertToCamelCase | Converter os nomes dos campos lidos da tabela, normalmente com "_", para "camel case", que é o mais comum utilizado em Json's. | Assinatura: convertToCamelCase (INPUT cKey AS CHARACTER) Exemplo: ASSIGN cField= JsonAPIUtils:convertToCamelCase ("cod_e_mail_usuar"). O retorno no cField será "codEMailUsuar", que é o campo em Camel Case. |
getIdField | Retorna um campo do tipo ID para ser adicionado na lista de campos do Metadata. Este campo serve como chave do registro nos tratamentos de CRUD na parte HTML. | Assinatura: getIdField() Exemplo: oIdiomas:add( JsonAPIUtils:getIdField() ). |
09. TÉCNICAS PARA TRADUÇÃO
breve descricao
Bloco de código |
---|
...
ASSIGN oObj = NEW JsonObject().
oObj:add('property', 'codIdioma').
oObj:add('label', "~{~{language~}~}").
oObj:add('visible', TRUE).
oObj:add('disable', TRUE).
oObj:add('type', JsonAPIUtils:convertAblTypeToHtmlType('character')).
oObj:add('gridColumns', 6).
oIdiomas:add(oObj).
... |
No Front-end, deve-se efetuar a substitução para que as literais
Bloco de código |
---|
... public getFieldList(update, literals) { // ajusta alista de campos para habilitar ou nao a chave primaria se for CREATE let fields: Array<any> = []; if (this.fieldList.length > 0) { this.fieldList.forEach((data) => { desIdioma: 'teste de escrita', if (data['label'] !== undefined) { hraUltAtualiz: '17:18:19' }, const key fields:= data['label'].replace('{{', '').replace('}}', ''); { if (literals[key] !== property: 'codCpfCnpj', undefined) { mask: '99.999.999/9999-99' data['label'] = literals[key]; } ],} focus: 'hraUltAtualiz', } _messages: [ if (data['options'] !== undefined) { let options code:= data['01options', ]; message: 'Mensagem do erro que aconteceu', options.forEach((option) => { detailedMessage:const 'detalheskey do erro acontecido' = option['label'].replace('{{', '').replace('}}', ''); } if (literals[key] !== undefined) { } |
Para utilizarmos a UPC de customização, tivemos que encapsular o JSon recebido no back-end, dentro da procedure pValidateForm, e tambem o JSon a ser enviado para a tela HTML, conforme o exemplo abaixo:
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
// encapsulamos o retorno para enviar para a UPC
oObj = NEW JsonObject().
oObj:add("property", cProp).
oObj:add("originalValues", oValue).
oObj:add("root", oRet).
// Realiza a chamada da UPC Progress
{include/i-epcrest.i &endpoint=validateForm &event=validateForm &jsonVar=oObj}
// obtem o retorno customizado, onde o mesmo foi alterado e retornado na tag root
oRet = oObj:getJsonObject("root"). |
Neste nosso exemplo, nós dividimos o JSon a ser enviado para UPC em três partes, que são:
...
option['label'] = literals[key];
}
});
}
fields.push(data);
});
}
return fields;
}
... |
Exemplo de chamadas
Bloco de código |
---|
...
// carrega a lista de campos somente apos receber o registro a ser apresentado
this.fields = this.service.getFieldList(false, this.literals);
if (this.fields === null || this.fields.length === 0) {
this.service.getMetadata().subscribe(data => { |
Exemplo de JSon recebido pela UPC:
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
{ property: 'codAcao', originalValues: { "codIdiomPadr": "01 Português", "codIdioma": "12345678", "desIdioma": "12345678901234567890", "hraUltAtualiz": "", "datUltAtualiz": null, "id": 6,this.fields = data['items']; "codAcoes": "FocoDesIdioma" this.service.setFieldList(this.fields); }, this.showLoading root:= {false; }); value: { } ... |
Avaisjdioasjdi aisodjsiad
Bloco de código |
---|
... const i18nConfig: PoI18nConfig = { default: { desIdiomalanguage: 'teste de escritapt-BR', hraUltAtualizcontext: '17:18:19general', cache: false }, contexts: { fieldsgeneral: [{ {'pt-BR': generalPt, 'en-US': generalEn, propertyurl: 'codCpfCnpj', api/trn/v1/idiomas/translations' mask: '99.999.999/9999-99' } } }; ... |
Definição das literais no back-end
Bloco de código |
---|
/** Recupera as literais */ PROCEDURE pIdiomas: DEFINE } INPUT PARAMETER oJsonInput AS JsonObject ], NO-UNDO. DEFINE OUTPUT focus: 'hraUltAtualiz', PARAMETER oJsonOutput AS JsonObject NO-UNDO. _messages: [ // Realiza a chamada da UPC Progress { {include/i-epcrest.i &endpoint=i18n &event=i18n &jsonVar=oJsonInput} ASSIGN oJsonOutput = oJsonInput. END PROCEDURE. |
Bloco de código |
---|
... IF pEndPoint = "i18n" AND pEventcode: '01', = "i18n" THEN DO ON STOP UNDO, messageLEAVE: 'Mensagem do erro que aconteceu', RUN piI18N. END. ... PROCEDURE piI18N: DEFINE VARIABLE oParser AS JsonAPIRequestParser detailedMessage: 'detalhes do erro acontecido' NO-UNDO. DEFINE VARIABLE oQueryParams AS JsonObject } NO-UNDO. DEFINE VARIABLE pIdioma ] } } |
Após a customização pela UPC, sera devolvido para a API Rest apenas a tag root, com as customizações necessárias, conforme o exemplo abaixo onde temos o resultado de uma customização:
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
{ AS CHARACTER "_messages": [ NO-UNDO. {ASSIGN oParser "detailedMessage": "Na execução da UPC, houveram alterações nos campos de tela.", = NEW JsonAPIRequestParser(jsonIO) oQueryParams = oParser:GetQueryParams() pIdioma = oQueryParams:GetJsonArray("codelanguage": "44",):GetCharacter(1). IF (pIdioma = "message": "A UPC alterou algumas caracteristica da tela."pt-BR") THEN DO: jsonIO = NEW JsonObject(). }jsonIO:Add("user", "Usu rio"). ], jsonIO:Add("focusname":, "desIdiomaNome",). "fields": [ jsonIO:Add("regexTestValidation", "Teste Valida‡Æo REGEX"). { jsonIO:Add("cpfMaskApply", "Aplica‡Æo M scara CPF"). jsonIO:Add("propertyonlyNumbers":, "codIdiomPadr",Somente N£meros"). END. ELSE IF (pIdioma = "disabled": trueen-US") THEN DO: } jsonIO = ], "value": {NEW JsonObject(). jsonIO:Add("desIdiomauser":, "Valor customizado na UPC" } } |
07. FACILITADORES PROGRESS
Criamos facilitadores para auxiliar no desenvolvimento das API's, ficam localizados na classe Progress "com.totvs.framework.api.JsonAPIUtils":
...
Assinatura:
convertAblTypeToHtmlType (INPUT cType AS CHARACTER)
Exemplo:
ASSIGN cType = JsonAPIUtils:convertAblTypeToHtmlType ("integer").
O retorno no cType será "number", que é um formato reconhecido pelo PO-UI.
...
Assinatura:
convertToCamelCase (INPUT cKey AS CHARACTER)
Exemplo:
ASSIGN cField= JsonAPIUtils:convertToCamelCase ("cod_e_mail_usuar").
O retorno no cField será "codEMailUsuar", que é o campo em Camel Case.
...
Assinatura:
getIdField()
Exemplo:
oIdiomas:add( JsonAPIUtils:getIdField() ).
"User").
jsonIO:Add("name", "Name").
jsonIO:Add("regexTestValidation", "REGEX Test Validation").
jsonIO:Add("cpfMaskApply", "CPF Apply Mask").
jsonIO:Add("onlyNumbers", "Only Numbers").
END.
END PROCEDURE. |
10
...
. LINKS ÚTEIS
Documentação API Datasul:
...
fwk-tools-jille/DATASUL/customization-poui/ ( https://github.com/totvs/fwk-tools-jille )
...
11. CONCLUSÃO
A ideia era apresentar uma técnica para que possibilita-se as áreas de negócio, de forma segura e simples, disponibilizarem pontos de customização em suas API’s REST.
...