Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

CONTEÚDO

  1. Visão Geral
  2. Pré-Requisitos
  3. Técnicas 
    1. Back-End Progress
    2. Front-End PO-UI
  4. Exemplo de utilização
    1. Back-End Progress
    2. Front-End PO-UI
  5. Facilitadores Progress
  6. Links Úteis


01. VISÃO GERAL

O Objetivo desta técnica é apresentar uma forma de customizar as telas HTML que foram construídas utilizando o Form Dinâmica do PO-UI.

No PO-UI, a Form Dinâmica trabalha recebendo uma lista de campos que serão apresentados em tela, bem como uma outra lista contendo os dados que serão apresentados nestes campos.

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.


02. Pré-Requisitos

Para execução da técnica abaixo é necessário as seguintes situações:

  • API Rest desenvolvida no útlimo padrão divulgado pelo Framework;
  • Utilização do Framework PO-UI na última versão disponível (v2.4.0);
  • Utilização do Framework Tomcat Datasul;


03. TÉCNICAS

Back-End Progress

A técnica Back-End Progress se divide basicamente em três partes:

  • Cadastro de Programa / EPC;
  • Includes para chamada UPC na API Rest;
  • Desenvolvimento da UPC;


Cadastro de Programa:

Para que possamos customizar uma tela, teremos que ter uma API REST que possa receber as informações do HTML, e esta API deverá permitir a utilização da técnica de EPC.A API REST para ser customizada, deverá ser cadastrada no cadastro de programas (MEN012AA), onde poderemos também especificar a UPC que será utilizada.


Includes para chamada UPC na API Rest:

Para que possamos customizar uma tela, teremos que ter uma API REST que possa receber as informações do HTML, e esta API deverá permitir a utilização da técnica de EPC.A API REST para ser customizada, deverá ser cadastrada no cadastro de programas (MEN012AA), onde poderemos também especificar a UPC que será utilizada.

A UPC para APIs REST possui um formato diferenciado das UPCs Padrões e de Ponto Estratégico, pois ela passa como um dos parâmetros um JsonObject. Ela encontra-se na pasta include e possui o nome i-epcrest.i, conforme o exemplo abaixo:

Bloco de código
{include/i-epcrest.i &endpoint=<nome_end_point> &event=<nome_do_evento> &jsonVar=<variavel_jsonObject_com_conteudo>}
Informações
titleIMPORTANTE

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.

Preprocessadores da include i-epcrest.i

Abaixo temos a lista de preprocessadores que devem ser passados para a include i-epcrest.i:

PreprocessadorDescrição
endpointEspecifica o endpoint que esta sendo chamado pelo HTML. Uma API REST deve possuir 1 ou mais endpoints.
eventÉ o nome do evento que esta ocorrendo antes de chamar a UPC. Exemplo: beforeCreate, getAll, getMetaData, etc.
jsonVarÉ a variável do tipo JsonObject que será passada como INPUT-OUTPUT para a UPC.
Informações
titleIMPORTANTE

IMPORTANTE: Todas as UPCs de API REST deverão importar os seguintes pacotes:

                       USING PROGRESS.json.*.

                       USING PROGRESS.json.ObjectModel.*.

                       USING com.totvs.framework.api.*.

Parâmetros recebidos na UPC da API REST

ParametroTipoTipo de DadosDescrição
pEndPointINPUTCHARACTERContem o nome do endpoint que está sendo executado.
pEventINPUTCHARACTERContem o nome do evento que está sendo executado.
pAPIINPUTCHARACTERContem o nome da API que está sendo executada.
jsonIOINPUT-OUTPUTJSONObjectContem o JSON com os dados (campos ou valores) que poderão ser customizados.

Front-End PO-UI


Introdução:

Para termos uma tela dinâmica do de acordo com o que o Back-End retorna precisamos utilizar os componentes dinâmicos do PO-UI sendo eles:

Componentes:

Templates:

Migrando THF2 para PO-UI

Para facilitar a migração do seu projeto com o THF para o PO UI, disponibilizamos um pacote para fazer esta conversão.

Este pacote, irá passar pelos arquivos do seu projeto alterando as palavras-chaves do THF para a nova nomenclatura do PO UI.

Basta seguir o guia disponibilizado pela equipe do PO-UI:

https://po-ui.io/guides/migration-thf-to-po-ui

Comunicando com o Back-End Progress

  • Tendo o projeto iniciado conforme documentação acima e adicionado os componentes desejados do PO-UI vamos ao desenvolvimento.
  • Todo componente dinâmico é divido basicamente em duas partes:


  • Metadado



04. EXEMPLO DE UTILIZAÇÃO

Back-End Progress

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:


Abaixo temos um exemplo de partes de uma API REST que possui 2 procedures, a procedure pGetAll para tratar as chamadas GET dos dados a serem apresentados e a procedure pGetMetaData que trata os GETs para a criação de novos campos.

Bloco de código
titleAPI REST
linenumberstrue
PROCEDURE pGetAll:
    DEFINE INPUT  PARAMETER oJsonInput  AS JsonObject NO-UNDO.
    DEFINE OUTPUT PARAMETER oJsonOutput AS JsonObject NO-UNDO.

    ...
    
    oIdiomas    = JsonAPIUtils:convertTempTableToJsonArray(TEMP-TABLE ttIdiomas:HANDLE).
    oObj        = new JsonObject().
    oObj:add('root', oIdiomas).
    
    /* realiza a chamada da UPC Progress */
    {include/i-epcrest.i &endpoint=getAll &event=getAll &jsonVar=oObj}
    oIdiomas = oObj:getJsonArray('root').    

    oResponse   = NEW JsonAPIResponse(oIdiomas).
    oJsonOutput = oResponse:createJsonResponse().
    
    ...
    
END PROCEDURE.

PROCEDURE pGetMetaData:
    DEFINE INPUT  PARAMETER oJsonInput  AS JsonObject NO-UNDO.
    DEFINE OUTPUT PARAMETER oJsonOutput AS JsonObject NO-UNDO.

    ...
    
    // monsta-se a lista de campos que aparecerão em tela
    oObj        = new JsonObject().
    oObj:add('root', jAList).
    
    /* realiza a chamada da UPC Progress */
    {include/i-epcrest.i &endpoint=getMetaData &event=getMetaData &jsonVar=oObj}    
    oIdiomas = oObj:getJsonArray('root').    
    
    oResponse   = NEW JsonAPIResponse(oIdiomas).
    oJsonOutput = oResponse:createJsonResponse().
    
    ...
    
END PROCEDURE.


Abaixo temos um exemplo de uma UPC criada para a API REST:

Bloco de código
titleUPC da API REST
linenumberstrue
/**************************************************************************
** 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', 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_usuario', usuar_mestre.cod_usuario) NO-ERROR.
            jObj:add('nom_usuario', usuar_mestre.nom_usuario) NO-ERROR.
            jObj:add('cod_dialet', usuar_mestre.cod_dialet) NO-ERROR.
            jObj:add('dat_fim_valid', usuar_mestre.dat_fim_valid) NO-ERROR.
            jObj:add('cod_e_mail_local', usuar_mestre.cod_e_mail_local) NO-ERROR.
        END.
        
        // adiciona o objeto na lista
        jAList:add(jObj).
        
        FIND NEXT usuar_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 */


Ao fazer as requisições, virão os seguintes resultados na UPC.

Bloco de código
linenumberstrue
Busca do METADADOS onde foram adicionados os novos campos cod_usuario e nom_usuario:

GET - http://localhost:8180/dts/datasul-rest/resources/prg/trn/v1/idiomas/metadados

   "items": [
        {
            "visible": true,
            "property": "cod_idioma",
            "disabled": false,
            "label": "Idioma",
            "type": "string"
        },
        {
            "visible": true,
            "property": "des_idioma",
            "disabled": false,
            "label": "Descrição",
            "type": "string"
        },
        {
            "visible": true,
            "property": "cod_idiom_padr",
            "disabled": false,
            "label": "Idioma Padrão",
            "type": "string"
        },
        {
            "visible": true,
            "property": "cod_usuario",
            "disabled": false,
            "label": "Usuário",
            "type": "string"
        },
        {
            "visible": true,
            "property": "nom_usuario",
            "disabled": false,
            "label": "Nome",
            "type": "string"
        }
     ]

Busca dos dados onde foram adiconados novos valores:

GET - http://localhost:8180/dts/datasul-rest/resources/prg/trn/v1/idiomas

   "items": [
        {
            "codIdioma": "12345678",
            "desIdioma": "12345678901234567890",
            "cod_dialet": "Pt",
            "cod_usuario": "super",
            "nom_usuario": "Super"
        },
        {
            "codIdioma": "ale",
            "desIdioma": "Alemão",
            "cod_dialet": "PT",
            "cod_usuario": "Manoel",
            "nom_usuario": "Manoel de Carvalho"
        },
        {
            "codIdioma": "EN",
            "desIdioma": "Ingles",
            "cod_dialet": "PT",
            "cod_usuario": "Joao",
            "nom_usuario": "Joao da Silva"
        }
    ]


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

Sendo que a primeira API é utilizada para fazer a montagem da tela, e a segunda API retorna os dados.

Código Fonte HTML: 

Bloco de código
languagexml
titleidioma-dynamic.component.html
linenumberstrue
<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>

Código Fonte TypeScript: 

Bloco de código
languagejs
titleidioma.component.ts
linenumberstrue
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> = [

    {
      "visible": true,
      "property": "cod_idioma",
      "label": "Idioma",
      "type": "string"
  },
  {
      "visible": true,
      "property": "des_idioma",      
      "label": "Descrição",
      "type": "string"
  },
  {
      "visible": true,
      "property": "cod_idiom_padr",
      "label": "Idioma Padrão",
      "type": "string"
  },
  {
      "visible": true,
      "property": "cod_usuario",
      "label": "Usuário",
      "type": "string"
  },
  {
      "visible": true,
      "property": "nom_usuario",
      "label": "Nome",
      "type": "string"
  }


  ];


  employee = {
    cod_idioma: "EN",
    des_idioma: "Inglês",
    cod_dialet: "Pt",
    cod_usuario: "super",
    nom_usuario: "Super"

  }; 

}

Tela:




05. Facilitadores Progress




07. Links Úteis




HTML
<!-- esconder o menu --> 


<style>
div.theme-default .ia-splitter #main {
    margin-left: 0px;
}
.ia-fixed-sidebar, .ia-splitter-left {
    display: none;
}
#main {
    padding-left: 10px;
    padding-right: 10px;
    overflow-x: hidden;
}

.aui-header-primary .aui-nav,  .aui-page-panel {
    margin-left: 0px !important;
}
.aui-header-primary .aui-nav {
    margin-left: 0px !important;
}
</style>