Árvore de páginas

Versões comparadas

Chave

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

...

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 (piscar o olho)


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) (piscar o olho)
  • 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
titleIMPORTANTE

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
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.

...

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:

Image Modified


Na aba Opções, teremos que especificar o Template como "API REST", conforme o exemplo abaixo:

Image Modified


API Rest com chamada de UPC:

...

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', 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
linenumberstrue
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 (piscar o olho) )

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

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>

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

...

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

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>

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> = [

    {
 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

...