BPM

Formulários WEB - API

1568 views 25/01/2018 07/10/2021 rodrigo-rossi 6

O cockpit do Workflow é capaz de apresentar dentro de um iframe formulários ECM e interfaces customizadas hospedadas em outros domínios. A comunicação entre as duas partes é realizada por Window.postMessage() e abstraída por este componente, que deve ser incluído na página e configurado pelo desenvolvedor.

Para o correto funcionamento da interface customizada dentro do cockpit, o desenvolvedor deve definir como a página salva os dados do processo e como reage a erros ocorridos na criação do processo e tratamento da pendência.

Passos para integração

Adicionar na página um componente que auxilia o cockpit a exibir o iframe no tamanho correto e o componente Javascript do Workflow:

<script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/3.5.14/iframeResizer.contentWindow.min.js"></script>

Caso você não tiver babel-polyfill instalado como dependência de seu projeto é necessário adicionar o seguinte arquivo:

<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.26.0/polyfill.js"></script>

Referenciar também o componente Javascript do Workflow:

<script type="text/javascript" src="https://cdn.senior.com.br/bpm/1.10.0/workflow-cockpit.min.js"></script>

Utilizando a tarefa com modo de abertura “Abrir Formulário no Cockpit do Workflow”, é preciso definir as funções que tratarão cada evento originado pelo cockpit. Exemplo:

this.workflowCockpit = workflowCockpit({
    init: _loadData,
    onSubmit: _saveData,
    onError: _rollback
});

Basicamente a integração com o BPM ocorre com essas 3 funções, são elas:

init: essa função é executada sempre que a página é carregada. Ela fornece dados para o formulário, como usuário logado por exemplo ou os dados do processo e variável do processo caso for um processo já em andamento.
onSubmit: o formulário deve implementar essa função para gravar os dados no BPM, para isso eles devem ser retornados na função. Importante que existam no BPM as variáveis do processo cadastradas para cada dado que se deseja gravar.
onError: função que é executada se em qualquer momento do processamento do formulário ocorrer algum erro para comunicar ao usuário. Exemplo um erro no processamento do método save.

O BPM envia por parâmetro para as funções, informações referente ao processo e plataforma:
data: Informações do processo, por exemplo, Id do processo e ação selecionado pelo usuário.
info: Informações diversas através das funções getUserData(), getPlatformData(), isRequestNew() e getInfoFromProcessVariables().

Em cada método as informações disponíveis nos parâmetros podem variar.

Funções da instância retornada

O objeto retornado pela função workflowCockpit possui funções que irão disponibilizar informações que auxiliarão no desenvolvimento do formulário. Abaixo está a descrição de cada uma.

isRequestNew(): Indica se a tela foi aberta porque o usuário está criando uma solicitação. Se for false, indica que o usuário está respondendo a uma solicitação.

getUserData(): Obtém um objeto contendo informações sobre o usuário logado no Workflow. É retornada uma promise.

info.getUserData().then(function(data) {
  /*{
      description: ...,
      email: ...,
      fullname: ...,
      id: ...,
      locale: ...,
      subject: ...,
      tenantName: ...,
      username: ...
    }*/
});

getPlatformData(): Obtém um objeto contendo dados para acessar recursos da plataforma G7. É retornada uma promise.

info.getPlatformData().then(function(data) {
  /*{
      serviceUrl: ...,
      odataUrl: ...,
      token: {
          token_type: ...,
          access_token: ...
    }*/
});

getInfoFromProcessVariables(): Obtém um array com os dados da instancia do processo. É retornada uma promise.

info.getInfoFromProcessVariables().then(function(data) {
  /*[{
       key: "first_name",//nome do campo na base
       value: "João", // valor da variavel
       type: "String"// tipo da variavel
     },
     {
       key: "last_name",
       value: "Silva",
       type: "String"
    }]*/
});

getTaskData: Disponibiliza dados relacionados a tarefa em execução.

info.getTaskData().then(function(data) {
  /*{
      processName: ...
      taskName: ...
    }*/
});

Handlers de eventos

O Desenvolvedor pode configurar determinadas funções que responderão mensagens do Workflow. As funções retornadas por WorkflowCockpit estão disponíveis em um segundo parâmetro ‘info’:

init(data, info)

/*info: ({
    isRequestNew: function
    getUserData: function
    getPlatformData: function
  })*/
/*data: ({
    processInstanceId: int? (ocasional)
    loadContext: {
    initialVariables?: {
      campo_1: "valor"
      campo_2: "valor"
      [...]
    } (ocasional)
  }
})*/

Esta função é executada quando ocorre a criação do WorkflowCockpit, ou seja, não é executada por mensagem. Quando for uma nova requisição não existe um processInstanceId pelo simples fato do fluxo ainda não ter sido criado.
Exemplo:

function _loadData(data, info) {
   info.getPlatformData().then(function(platformData) {
       this.tokenG7 = platformData.token;
       this.serviceUrl = platformData.serviceUrl;
       this.odataUrl = platformData.odataUrl;

       if (info.isRequestNew()) {
           this.fields = this.loadData(data.processInstanceId);
       }
   });
}

Quando um serviço externo for configurado antes da execução de uma tarefa inicial, o valor initialVariables conterá os dados retornados pelo serviço, podendo ser utilizados para, por exemplo, alimentar os campos do formulário.

onSubmit(data, info)

  /*data: ({
       processInstanceId: int
       nextAction: {
         connectsWithAutomaticGateway: boolean // Se a ação está associada a algum elemento de decisão automática.
         finish: boolean, // Se a ação finaliza a execução do processo.
         name: string // Nome da ação a ser realizada.
       },
       nextSubject?: {
        name: string // Nome do usuário.
        subjectKind: string // O tipo do usuário escolhido, podendo ser: User|Group|Role.
        userCode: int // Código do usuário, podendo ser útil para comunicação com a API do Workflow.
       } (ocasional)
   })*/

Esta função é executada no momento que o usuário finaliza sua interação com a tela e tenta prosseguir ou iniciar um processo pelo Cockpit. Neste momento, a tela pode realizar a persistência dos dados do formulário e retornar os valores que deseja adicionar às variáveis do fluxo. Pode ser retornada uma Promise ou o próprio objeto contendo os dados.
Toda exceção lançada por essa função não permitirá a continuação do processo por parte do Workflow. Exemplo:

function _saveData(data, info) {
  if (!isValid()) {
      throw Error('Os dados informados são inválidos.');
  }
  return persistData(data.processInstanceId, info.isRequestNew()).then(function(result) {
    return {
        formData: this.data // objeto contendo os dados dos campos
    };
  });
}

Quando o usuário não estiver disponível no cockpit, isto é, quando é definido durante a execução do processo sem termos um meio de saber previamente, não haverá a propriedade nextResponsible no objeto data, por isso está marcada como ocasional.
Importante lembrar que, como a execução dessa função não está associada a um contexto de renderização do Angular, é preciso invocar $scope.$apply() caso a função isValid() modifique alguma variável que afeta a apresentação.

onError(data, info)

/*data: ({
       error: obj
       processInstanceId: int
   })*/

Esta função é chamada quando o ocorre algum erro ao iniciar ou responder o fluxo. Após a execução do save, se ocorrer algum erro quando o Workflow tentar prosseguir com o processo, este é o momento onde pode ser realizado algum tipo de consistência com o erro ocorrido, por exemplo:

function _rollback(data, info) {
  console.log(data.error);
  if (info.isRequestNew()) {
     return removeData(data.processInstanceId);
  }
  return rollbackData(data.processInstanceId);
}

Formulário de Exemplo

Temos em nosso GitHub um exemplo de formulário web que foi construído de forma simples, usando apenas HTML, JavaScript e o Bootstrap como framework visual. No readme do projeto você encontra o passo-a-passo para implantação.

Este artigo foi útil para você?