Histórico da Página
...
Este guia será divido basicamente em duas partes, como vamos trabalhar no Back-End Progress e acessar esses dados através do Front-End PO-UI.
CARLOS - Colocar aqui as imagens para o pessoal ter uma visao geral
02. Pré-Requisitos
Temos como pré-requisito para execução da técnica citada abaixo:
- API Rest desenvolvida no útlimo último padrão divulgado pelo Framework;API Rest fazer uso da include "utp/ut-api";, utilizando a técnica de construção de APIs; (CARLOS-Colocar o link da tecnica de construcao de APIs Rest)
- Utilização do Framework PO-UI na última versão disponível (v2.4.0);
- Utilização do Framework Tomcat Datasul;
- Conhecer a técnica de customização com EPC.
03. TÉCNICAS
Técnica Back-End Progress:
...
A técnica Back-End Progress se divide basicamente em três partesé formada pelos passos abaixo:
- Construção de API Rest para tela customizada;
- Uso da include "utp/ut-api";
- Cadastro de Programa / EPC;
- Cadastro da API Rest no Cadastro de Programas (men012aa) com a respectiva UPC;
- Utilizar a include "include/i-epcrest.i" Includes para chamada UPC na API Rest ;
- Desenvolvimento da UPC;.
Construção de API REST para tela customizada:
...
- Endpoint que retornará o metadados da tela;
- Endpoint para retornar os valores da tela;
Cadastro
...
da API Rest no Cadastro de Programas (men012aa) com a respectiva UPC:
Tendo criado a API REST que retorna os dados básicos para a tela, partimos para o segundo o passo, que é preparação da API para customização.
Esta API deverá ser cadastrada no cadastro de programas (MEN012AA), onde poderemos também especificar a UPC que será utilizada.
Devido a alteração que fizemos na Na técnica de construção de APIs REST informa que é necessario a utilização da include "utp/ut-api.i", a mesma identificará que a API em questão possuí pois além do que ela se propõem, ela também está identificando se a API possui uma UPC cadastrada ou não.
Informações | ||
---|---|---|
| ||
IMPORTANTE: A UPC para APIs REST possui um formato diferenciado das UPCs Padrões e de Ponto Estratégico, pois um dos parâmetros utilizados é um JsonObject. |
...
Utilizar a include "include/i-epcrest.i" para chamada UPC na API Rest :
Enfim para chamarmos um programa de customização, criamos uma include que fará esta chamada. Abaixo segue mais detalhes sobre esta include.
...
Bloco de código |
---|
{include/i-epcrest.i &endpoint=<nome_end_point> &event=<nome_do_evento> &jsonVar=<variavel<variável_jsonObject_com_conteudo>conteúdo>} |
Informações | ||
---|---|---|
| ||
IMPORTANTE: Não é permitido misturar tipos diferentes de UPCs no mesmo programa, pois as assinaturas são incompatíveis e poderão ocorrer erros de parâmetros. |
...
Para exemplificar a técnica citada acima, criamos uma API Rest que irá retornar os dados da tabela de idiomas, chamando uma UPC que acrescenta os dados algumas informações da tabela usuar_mestre.
Cadastro da UPC:
Primeiramente temos que cadastrar a API REST no cadastro de programas (MEN012AA) e também especificar a UPC a ser utilizada, conforme o exemplo abaixo:
Na aba Opções, teremos que especificar o Template como "API REST", conforme o exemplo abaixo:
API Rest com chamada de UPC:
...
Bloco de código | ||||
---|---|---|---|---|
| ||||
/************************************************************************** ** idiomas_upc.p - Exemplo de epc para Endpoints REST ***************************************************************************/ 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 jAList AS JsonArray NO-UNDO. DEFINE VARIABLE jObj AS JsonObject NO-UNDO. DEFINE VARIABLE hBuf AS HANDLE NO-UNDO. DEFINE VARIABLE ix AS INTEGER NO-UNDO. DEFINE VARIABLE iTot AS INTEGER NO-UNDO. DEFINE VARIABLE cType AS CHARACTER NO-UNDO. // carrega as definicoes dos campos da tabela IF pEndPoint = "getMetaData" AND pEvent = "getMetaData" THEN DO ON STOP UNDO, LEAVE: // obtem a lista de campos e valores ASSIGN jAList = jsonIO:getJsonArray('root'). // cria um buffer da tabela para obter os campos da tabela usuar_mestre CREATE BUFFER hBuf FOR TABLE 'usuar_mestre'. DO ix = 1 TO hBuf:NUM-FIELDS: // ignora os campos que nao estao nesta lista IF NOT CAN-DO("nom_usuario,cod_usuario,cod_dialet,dat_fim_valid,cod_e_mail_local", hBuf:BUFFER-FIELD(ix):NAME) THEN NEXT. // monta a formatacao do item ASSIGN jObj = NEW JsonObject(). jObj:add('property', JsonAPIUtils:convertToCamelCase(hBuf:BUFFER-FIELD(ix):NAME)). jObj:add('label', hBuf:BUFFER-FIELD(ix):Label). jObj:add('visible', TRUE). jObj:add('disabled', FALSE). // ajusta o tipo ASSIGN cType = JsonAPIUtils:convertAblTypeToHtmlType(hBuf:BUFFER-FIELD(ix):type). jObj:add('type', cType). // adiciona o objeto na lista jAList:add(jObj). END. hBuf:BUFFER-RELEASE(). DELETE OBJECT hBuf. // retorna a nova lista com os campos adicionados jsonIO:Set("root", jAList). END. // carrega os valores dos campos da tabela IF pEndPoint = "getAll" AND pEvent = "getAll" THEN DO ON STOP UNDO, LEAVE: // obtem a lista de campos e valores ASSIGN jAList = jsonIO:getJsonArray('root'). FIND FIRST usuar_mestre NO-LOCK NO-ERROR. // quardado o tamanho da lista em variavel para evitar LOOP devido a adicionar novos itens na lista ASSIGN iTot = jAList:length. DO ix = 1 TO iTot: ASSIGN jObj = jAList:GetJsonObject(ix). // alimenta os novos dados IF AVAILABLE usuar_mestre THEN DO: jObj:add('cod_usuariocodUsuario', usuar_mestre.cod_usuario) NO-ERROR. jObj:add('nom_usuarionomUsuario', usuar_mestre.nom_usuario) NO-ERROR. jObj:add('cod_dialetcodDialet', usuar_mestre.cod_dialet) NO-ERROR. END. jObj:add('dat_fim_valid', usuar_mestre.dat_fim_valid) NO-ERROR. // adiciona o jObj:add('cod_e_mail_local', usuar_mestre.cod_e_mail_local) NO-ERROR.objeto na lista ENDjAList:add(jObj). //FIND adicionaNEXT o objeto na lista jAList:add(jObj). FIND NEXT usuar_mestre NO-LOCK NOusuar_mestre NO-LOCK NO-ERROR. END. // devolve para o json ROOT a lista nova com novos objetos jsonIO:Set("root", jAList). END. IF pEndPoint = "getOne" AND pEvent = "getOne" THEN DO ON STOP UNDO, LEAVE: // nao implementado END. IF pEndPoint = "create" AND pEvent = "afterCreate" THEN DO ON STOP UNDO, LEAVE: // nao implementado END. /* fim */ |
...
Bloco de código | ||
---|---|---|
| ||
Busca do METADADOS onde foram adicionados os novos campos cod_usuariocodUsuario, nomUsuario e nom_usuariocodDialet: GET - http://localhost:8180/dts/datasul-rest/resources/prg/trn/v1/idiomas/metadados { "itemstotal": [9, "hasNext": false, { "items": [ { "visible": true, "property": "cod_idiomacodIdioma", "disabled": false, "label": "Idioma", "type": "string" }, { "visible": true, "property": "des_idiomadesIdioma", "disabled": false, "label": "Descrição", "type": "string" }, { "visible": true, "property": "cod_idiom_padrcodIdiomPadr", "disabled": false, "label": "Idioma Padrão", "type": "string" }, { "visible": true, "property": "cod_usuariocodUsuarUltAtualiz", "disabled": false, "label": "Usuário Ult Atualiz", "type": "string" }, { "visible": true, "property": "nom_usuariodatUltAtualiz", "disabled": false, "label": "NomeÚltima Atualização", "type": "string" }, ] Busca dos dados onde foram adiconados novos valores: GET - http://localhost:8180/dts/datasul-rest/resources/prg/trn/v1/idiomas { "itemsvisible": [ {true, "codIdiomaproperty": "12345678hraUltAtualiz", "desIdiomadisabled": "12345678901234567890"false, "cod_dialetlabel": "Pt", Hora "cod_usuario": "super"Última Atualiz", "nom_usuariotype": "Superstring" }, { "codIdiomavisible": "ale"true, "desIdiomaproperty": "AlemãocodUsuario", "cod_dialetdisabled": "PT"false, "cod_usuariolabel": "ManoelUsuário", "nom_usuariotype": "Manoel de Carvalhostring" }, { "codIdiomavisible": "EN"true, "desIdiomaproperty": "InglesnomUsuario", "cod_dialetdisabled": "PT"false, "cod_usuariolabel": "JoaoNome", "nom_usuariotype": "Joao da Silva""string" }, }{ ] |
Front-End PO-UI
Introdução:
Basicamente utilizamos o componente de Page-Dynamic-Detail para comunicar com o back-end através de duas APIS:
...
"visible": true,
"property": "codDialet",
"disabled": false,
"label": "Dialeto",
"type": "string"
}
]
}
Busca dos dados onde foram adicionados novos valores:
GET - http://localhost:8180/dts/datasul-rest/resources/prg/trn/v1/idiomas
{
"total": 3,
"hasNext": false,
"items": [
{
"codIdioma": "12345678",
"desIdioma": "12345678901234567890",
"hraUltAtualiz": "08:35:00",
"datUltAtualiz": "2010-02-15",
"codUsuario": "super",
"nomUsuario": "Super",
"codDialet": "Pt"
},
{
"codIdioma": "ale",
"desIdioma": "Alemão",
"hraUltAtualiz": "15:33:45",
"datUltAtualiz": "2018-10-23",
"codUsuario": "Joao",
"nomUsuario": "Joao da Silva",
"codDialet": "PT"
},
{
"codIdioma": "ESP",
"desIdioma": "Espanhol",
"hraUltAtualiz": "12:20:03",
"datUltAtualiz": "2004-12-08",
"codUsuario": "Manoel",
"nomUsuario": "Manoel da Silva",
"codDialet": "PT"
}
]
} |
Front-End PO-UI
Introdução:
Basicamente utilizamos o componente de Page-Dynamic-Detail para comunicar com o back-end através de duas APIS:
public readonly serviceMetadataApi: 'http://localhost:3000/v1/metadata'; // endpoint dos metadados
public readonly serviceMetadataApi: 'http://localhost:3000/v1/metadata'; // endpoint dos metadados (Carlos - esta duplicado )
Sendo que a primeira API é utilizada para fazer a montagem da tela, e a segunda API retorna os dados.
HTML:
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
<div class="po-wrapper">
<po-toolbar p-title="Datasul - Dynamic - Custom"></po-toolbar>
<po-menu [p-menus]="menus"></po-menu>
<po-page-default p-title="Idiomas">
<p> </p>
<po-dynamic-view [p-fields]="fields" [p-value]="employee"> </po-dynamic-view>
<po-page-dynamic-detail p-auto-router p-title="Detail" [p-actions]="actions" [p-breadcrumb]="breadcrumb"
[p-fields]="fields" [p-service-api]="serviceApi">
</po-page-dynamic-detail>
</po-page-default>
</div>
|
TypeScript:
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
import { Component } from '@angular/core'; import { PoMenuItem } from '@po-ui/ng-components'; import { PoDynamicViewField } from '@po-ui/ng-components'; import { PoBreadcrumb } from '@po-ui/ng-components'; import { PoPageDynamicDetailActions, PoPageDynamicDetailField } from '@po-ui/ng-templates'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { readonly menus: Array<PoMenuItem> = [ { label: 'Home', action: this.onClick.bind(this) } ]; private onClick() { alert('Clicked in menu item') } public readonly serviceApi = 'https://po-sample-api.herokuapp.com/v1/people'; public readonly serviceMetadataApi: 'http://localhost:3000/v1/metadata'; // endpoint dos |
...
metadados //public readonly serviceLoadApi: 'http://localhost:3000/ |
...
load-metadata' |
...
// endpoint de customizações dos |
...
Sendo que a primeira API é utilizada para fazer a montagem da tela, e a segunda API retorna os dados.
HTML:
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
<div class="po-wrapper">
<po-toolbar p-title="Datasul - Dynamic - Custom"></po-toolbar>
<po-menu [p-menus]="menus"></po-menu>
<po-page-default p-title="Idiomas">
<p> </p>
<po-dynamic-view [p-fields]="fields" [p-value]="employee"> </po-dynamic-view>
<po-page-dynamic-detail p-auto-router p-title="Detail" [p-actions]="actions" [p-breadcrumb]="breadcrumb"
[p-fields]="fields" [p-service-api]="serviceApi">
</po-page-dynamic-detail>
</po-page-default>
</div>
|
TypeScript:
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
import { Component } from '@angular/core'; import { PoMenuItem } from '@po-ui/ng-components'; import { PoDynamicViewField } from '@po-ui/ng-components'; import { PoBreadcrumb } from '@po-ui/ng-components'; import { PoPageDynamicDetailActions, PoPageDynamicDetailField } from '@po-ui/ng-templates'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { readonly menus: Array<PoMenuItem> = [ { label: 'Home', action: this.onClick.bind(this) } ]; private onClick() { alert('Clicked in menu item') } public readonly serviceApi = 'https://po-sample-api.herokuapp.com/v1/people'; public readonly serviceMetadataApi: 'http://localhost:3000/v1/metadata'; // endpoint dos metadados //public readonly serviceLoadApi: 'http://localhost:3000/load-metadata' // endpoint de customizações dos metadados public readonly actions: PoPageDynamicDetailActions = { back: '/documentation/po-page-dynamic-table' }; public readonly breadcrumb: PoBreadcrumb = { items: [ { label: 'Home', link: '/' }, { label: 'People', link: '/documentation/po-page-dynamic-table' }, { label: 'Detail' } ] }; public readonly fields: Array<PoPageDynamicDetailField> = [ { metadados public readonly actions: PoPageDynamicDetailActions = { back: '/documentation/po-page-dynamic-table' }; public readonly breadcrumb: PoBreadcrumb = { items: [ { label: 'Home', link: '/' }, { label: 'People', link: '/documentation/po-page-dynamic-table' }, { label: 'Detail' } ] }; public readonly fields: Array<PoPageDynamicDetailField> = [ { "visible": true, "property": "codIdioma", "label": "Idioma", "type": "string" }, { "visible": true, "property": "desIdioma", "label": "Descrição", "type": "string" }, { "visible": true, "property": "codIdiomPadr", "label": "Idioma Padrão", "type": "string" }, { "visible": true, "property": "codUsuarUltAtualiz", "label": "Usuário Ult Atualiz", "type": "string" }, { "visible": true, "property": "cod_idiomadatUltAtualiz", "label": "IdiomaÚltima Atualização", "type": "string" }, { "visible": true, "property": "des_idiomahraUltAtualiz", "label": "DescriçãoHora Última Atualiz", "type": "string" }, { "visible": true, "property": "cod_idiom_padrcodUsuario", "label": "Idioma PadrãoUsuário", "type": "string" " }, { "visible": true, "property": "cod_usuarionomUsuario", "label": "UsuárioNome", "type": "string" }, { "visible": true, "property": "nom_usuariocodDialet", "label": "NomeDialeto", "type": "string" } ]; employee = { cod_idiomacodIdioma: "EN", des_idiomadesIdioma: "Inglês", cod_dialetcodDialet: "Pt", cod_usuariocodUsuario: "super", nom_usuarionomUsuario: "Super" }; } |
05. Facilitadores Progress
...