Árvore de páginas

Versões comparadas

Chave

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

Índice

Índice

 

Vamos desenvolver uma widget que mostre notícias cadastradas no Fluig. Não deixe de conferir o projeto completo.

Criar projeto Fluig

Em primeiro lugar devemos ter disponível um projeto Fluig onde desenvolveremos nossa widget utilizando o Fluig Studio. Para isso podemos seguir os passos para criação de um projeto Fluig.

Criar Widget

Em seguida criaremos uma widget. Para isso podemos seguir os passos para criação de uma widget.

Desenvolvendo a widget

Agora que temos a estrutura básica, podemos começar a desenvolver o código customizado e inserir as propriedades que desejamos para essa widget.

Para isso podemos começar com o arquivo de configurações application.info. É nele que ficam registrados informações como título, descrição, arquivos de visualização, componentes a serem utilizados e etc.

Arquivo application.info

Abaixo o arquivo application.info detalhado:

Bloco de código
themeEclipse
languagetext
titleapplication.info
linenumberstrue
application.type=widget
application.code=news
application.title=Not\u00EDcias da Semana
application.description=Exibe uma lista com as \u00FAltimas not\u00EDcias da semana
application.category=KitIntranet	
application.renderer=freemarker
application.icon=icon.png
developer.code=developer
developer.name=TOTVS S.A.
developer.url=http://www.fluig.com
view.file=view.ftl
edit.file=edit.ftl
application.uiwidget=true
application.resource.js.1=/resources/js/news.js
application.resource.css.2=/resources/css/news.css
simple.deploy=false
Informações

Para saber mais, acesse a documentação Arquivo application.info.

 

Uso do Conceito Super Widget

Iremos utilizar o conceito de Super Widget na construção de nossa widget. Para saber mais sobre, acesse o guia da Super Widget.

Precisamos adicionar a classe css super widget na div que instancia a widget, tanto no arquivo de edição (edit.ftl) como no arquivo de visualização (view.ftl). 

Bloco de código
themeEclipse
languagexml
<div id="KitIntranetNews_${instanceId}" class="wcm-widget-class super-widget fluig-style-guide"
	data-params="KitIntranetNews.instance(${parameters})">
	<!--
		código
	 -->
</div>

 

No arquivo javascript devemos contruir o código fonte com a seguinte estrutura.

Bloco de código
languagejs
var KitIntranetNews = SuperWidget.extend({
	// código
});

 

Informações
titleImportante

Note que é essencial referenciar corretamente o nome da variavel javascript no "data-params" do arquivo .ftl, ou seja:

Esse código:

Bloco de código
languagexml
KitIntranetNews.instance(${parameters})

Faz referência a essa variável:

Bloco de código
languagejs
var KitIntranetNews

Interface aplicada com Fluig Style Guide

Para construir a interface de nossa widget, vamos utilizar o Fluig Style Guide, que nos facilita a construção dos componentes visuais. O guia pode ser acessado em Fluig Style Guide.

Para essa widget de notícias por exemplo, precisamos utilizar um form para cadastro de alguns dados, para utiliza o padrão visual do Fluig Style Guide, basta adicionar a classe .form-group. Assim todos os elementos textuais como <input>, <textarea>, e <select> terão seus tamanhos ajustados para 100%.

Bloco de código
languagexml
<form role="form">
	<div id="newsSource_${instanceId}" class="form-group">
		<!-- código -->
    </div>
</form>

Para criar um botão no padrão, basta adicionar as classes 'btn btn-default'.

Bloco de código
languagexml
<button type="submit" class="btn btn-default" data-save-preferences> Salvar </button>

Preferências da Widget

Abaixo é explicado como salvar as preferências de sua widget da forma como idealizada pela equipe do Fluig. É a forma padrão e é desejável que todas as widgets utilizem apenas essa técnica quando for necessário guardar algum tipo de informação para cada instância. Apesar de existirem outras formas de se guardar as preferências de uma widget, recomendamos fortemente que utilize a forma disponibilizada pelo Fluig pelos seguintes motivos:

  • Não existe preocupação de "quem é propriedade de quem", uma vez que o Fluig guarda de forma independente as preferências para cada instância de widget;
  • Cada página possui controle de versão e as instâncias das widgets contidas nela não são diferentes. Utilizar as preferências padrão minimiza o risco de se perder alguma informação, já que tudo estará sob o controle de versão do Fluig;
  • A busca das informações é feita automaticamente pelo renderizador de página, tornando a consulta aos dados das preferências ágil e simples;
Informações
titleSobre Tipos de Dados

Na base do Fluig, as preferências das widget sãos salvas em uma tabela padrão do sistema em um campo do tipo texto. Apesar de ser usado um tipo de dado com grande capacidade de armazenamento, não se deve usá-lo para outra coisa que não seja armazenar tipos de dados primitivos:

  • Character / String;
  • Números de todos os tipos;
  • Datas;
  • Booleanos;

Sendo todos os dados salvos como string, caberá ao desenvolvedor fazer os tratamentos e conversões necessárias conforme a sua necessidade.

 

Armazenamento

Para salvar as preferências da widget, utilizamos o método WCMSpaceAPI.PageService.UPDATEPREFERENCES passando um método para callback (tratamento de retorno), o id da instância da widget e as preferências a serem salvas.

Bloco de código
themeEclipse
languagejs
var preferences = {
    newsSource: "fonte",
    url: "/news/feed/url",
    numberOfArticles: 10
};
 
WCMSpaceAPI.PageService.UPDATEPREFERENCES({
    async: true,
    success: function (data) {
			// código
    },
    fail: function (xhr, message, errorData) {
		// código
    }
}, this.instanceId, preferences
);

Utilização

No código abaixo, podemos observar que a widget tem algumas variáveis chamadas news, newsSource, ulr e numberOfArticles.

Bloco de código
themeEclipse
languagejs
var KitIntranetNews = SuperWidget.extend({
    news: null,
    newsSource: null,
    url: null,
    numberOfArticles: null,
    DATASET: "dataset",
    FEED: "rssfeed",
    KIT_NEWS: "kit_news",
	// código
});

As preferências da widget são recuperadas automaticamente. Basta salvar as preferências com os nomes das variáveis da widget, como no tópico Como salvar as preferências da widget.

Integrando sua widget com armazenamento de dados.

Interno (Formulários)

Armazenamento

Frequentemente é necessário armazenar dados além daqueles que a plataforma Fluig já guarda nativamente e não faz sentido esperar que toda pessoa que precisar de tal recurso tenha de saber ou contratar alguém que saiba configurar novas tabelas no banco de dados. Pensando nisso, o Fluig disponibiliza uma forma de guardar seus dados de forma simples e ágil. Estamos falando da customização de formulários.

É um recurso valioso do Fluig e preparado para realizar soluções completas e complexas. Entretanto pode ser usado de forma bastante descomplicada para atender a demandas mais simples. Utilizando datasets, o processo de armazenamentos de seus dados torna-se rápido. Imagine que você deseja guardar o nome, dia e mês do aniversário do colaboradores de sua empresa. Considere os passos abaixo:

Bloco de código
languagexml
<form name="form" role="form">
	...
	<input name="newTitle" id="newTitle">
	...
	<input name="newDescription" id="newDescription">
	...
	<input name="newsSourceURL" id="newsSourceURL">
	...
</form>

Feito isso, basta agora seguir os passos de exportação de um artefato Fluig para um Servidor Fluig e seu formulário já estará pronto para armazenamento. Por padrão, os formulário localizam-se em Documentos / Formulários Fluig. Seu formulário se encotrará lá exibindo o nome escolhido no momento da criação.

Utilização

Com seu formulário pronto e alimentado com os dados desejados, basta buscar a identificação do seu formulário no início do arquivo javascript. Em posse da identidade do registro, é simples buscar os dados desse. Em seu arquivo .js execute uma chamada ao DatasetFactory. Abaixo um exemplo simples:

Bloco de código
languagejs
var datasetReturned = DatasetFactory.getDataset({codigo-do-seu-formulario}, null, null, null);

Onde:

ElementoDescrição
datasetReturnedObjeto contendo os registros do formulário retornados
{codigo-do-seu-formulario}
Código escolhido para o seu formulário (definido aqui )

O consumo desses registros pode ser efetuado da seguinte forma:

Bloco de código
languagejs
if(datasetReturned != null && datasetReturned.values != null && datasetReturned.values.length > 0){
	var records = datasetReturned.values;
	for (var index in records) {
		var record = records[index];
		// ... restanto do código omitido
	}
}

Onde:

ElementoDescrição
datasetReturned
Objeto contendo os registros do formulário retornados
records
Um array de objetos ( Object[ ] ) contendo os registros
index
Índice do registro corrente conforme o laço (for) avança pelo array
record

É o registro, ou seja, o Objeto contendo as propriedades de um registro de formulário.

Considerando o exemplo do formulário de notícias, podemos assumir para esse caso que as propriedades desse objeto serão as seguintes:

  • record.newTitle

  • record.newDescription

  • record.newsSourceURL

Externo (REST)

Para obter dados de uma fonte externa ao seu sistema, a forma mais aconselhável é via chamada REST. Vamos criar um rest dentro da própria widget, para isso devemos seguir alguns passos.

Primeiro devemos criar uma classe chamada ApplicationConfig que extende a classe Application.

Bloco de código
languagejava
package com.fluig.kitintranet.news.proxy.rest.config;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("api/rest")
public class ApplicationConfig extends Application{
	//não é necessário código, precisamos apenas para o @ApplicationPath
}

 

Em seguida devemos criar a classe REST que desejamos acessar.

Bloco de código
languagejava
package com.fluig.kitintranet.news.proxy.rest;

import com.totvs.technology.wcm.sdk.rest.WCMRest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
 
@Path("/news")
public class NewsRest extends WCMRest {

    @POST
    @Path("feed")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public Response getRSSFeedTest(String requestParams) {
		//código
	}
}

 

Em seguida temos de alterar os arquivos jboss-web.xml

Bloco de código
languagexml
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
    <context-root>/news</context-root>
    <disable-cross-context>false</disable-cross-context>
    <security-domain>TOTVSTech</security-domain>
    <security-role>
        <role-name>user</role-name>
        <principal-name>totvstech</principal-name>
    </security-role>
    <security-role>
        <role-name>totvstech</role-name>
        <principal-name>totvstech</principal-name>
    </security-role>
    <security-role>
        <role-name>sysadmin</role-name>
        <principal-name>wcmadmin</principal-name>
    </security-role>
    <security-role>
        <role-name>admin</role-name>
        <principal-name>wcmadmin</principal-name>
    </security-role>
    <valve>
        <class-name>com.totvs.technology.auth.saml.TOTVSAuthenticatorValve</class-name>
    </valve>
</jboss-web>

 

Também temos de alterar o arquivo web.xml para que possamos acessar esse REST.

maxLevel4
outlinetrue
exclude.*ndice
stylenone

Objetivo

O objetivo deste guia é apresentar todo o processo de desenvolvimento de um widget integrado a vários possíveis tipos de fonte de dados. Cada sessão contém apenas o código necessário para o entendimento de cada assunto específico abordado. Para ver o resultado final do desenvolvimento, baixe os projetos abaixo:

Projeto 01: Widget de Notícias (integra-se com formulário):

Deck of Cards
idnoticias
Card
labelImagem 1

Image Added

Card
labelImagem 2

Image Added


Projeto 02: Widget de Aniversariantes (integra-se com formulário ou serviço soap do RM):

Deck of Cards
idaniversario
Card
labelImagem 1

Image Added

Card
labelImagem 2

Image Added

Vamos desenvolver um widget que mostre notícias cadastradas no Fluig Plataforma. Não deixe de conferir o projeto completo.


Criar projeto Fluig

Em primeiro lugar, devemos ter disponível um projeto Fluig onde desenvolveremos nosso widget utilizando o Fluig Studio. Para isso podemos seguir os passos para criação de um projeto Fluig.


Criar widget

Em seguida, criaremos um widget. Para isso podemos seguir os passos para criação de um widget.

Informações

Veja o exemplo em nosso repositório aqui.


Desenvolvendo o widget

Agora que temos a estrutura básica, podemos começar a desenvolver o código personalizado e inserir as propriedades que desejamos para esse widget.

Para isso, podemos começar com o arquivo de configurações application.info. É nele que ficam registradas informações como título, descrição, arquivos de visualização, componentes a serem utilizados etc.


Arquivo application.info

Abaixo o arquivo application.info detalhado:

Bloco de código
languagetext
themeEclipse
titleapplication.info
linenumberstrue
application.type=widget
application.code=news
application.title=Not\u00EDcias da Semana
application.description=Exibe uma lista com as \u00FAltimas not\u00EDcias da semana
application.category=KitIntranet	
application.renderer=freemarker
application.icon=icon.png
developer.code=developer
developer.name=TOTVS S.A.
developer.url=http://www.fluig.com
view.file=view.ftl
edit.file=edit.ftl
application.uiwidget=true
application.resource.js.1=/resources/js/news.js
application.resource.css.2=/resources/css/news.css
simple.deploy=false
Informações
titleNota

Para saber mais, acesse a documentação Arquivo application.info.


Uso do conceito Super widget

Iremos utilizar o conceito de Super widget na construção de nosso widget. Para mais detalhes acesse o guia Super widget.

Precisamos adicionar a classe css super widget na div que instancia o widget, tanto no arquivo de edição (edit.ftl) como no arquivo de visualização (view.ftl).

Bloco de código
languagexml
themeEclipse
<div id="KitIntranetNews_${instanceId}" class="wcm-widget-class super-widget fluig-style-guide"
	data-params="KitIntranetNews.instance(${parameters})">
	<!--
		código
	 -->
</div>

No arquivo javascript devemos construir o código fonte com a seguinte estrutura.

Bloco de código
languagejs
var KitIntranetNews = SuperWidget.extend({
	// código
});
Nota
titleImportante

Note que é essencial referenciar corretamente o nome da variável javascript no "data-params" do arquivo .ftl, ou seja:

Esse código:

Bloco de código
languagexml
KitIntranetNews.instance(${parameters})

Faz referência a essa variável:

Bloco de código
languagejs
var KitIntranetNews
Dica
titleDica

Dispense alguns momentos para entender as diferenças entre o modo de visualização e o modo de edição dos widgets.


Interface aplicada com Fluig Style Guide

Para construir a interface do widget, vamos utilizar o Fluig Style Guide, que facilita a construção dos componentes visuais. O guia pode ser acessado em Fluig Style Guide.

Para esse widget de notícias por exemplo, precisamos utilizar um form para cadastro de alguns dados. Para utilizar o padrão visual do Fluig Style Guide, basta adicionar a classe .form-group. Assim todos os elementos textuais como <input>, <textarea>, e <select> terão seus tamanhos ajustados para 100%.

Bloco de código
languagexml
<form role="form">
	<div id="newsSource_${instanceId}" class="form-group">
		<!-- código -->
    </div>
</form>

Para criar um botão no padrão, basta adicionar as classes 'btn btn-default'.

Bloco de código
languagexml
<button type="submit" class="btn btn-default" data-save-preferences> Salvar </button>


Preferências do widget

A seguir é explicado como salvar as preferências do widget da forma como idealizada pela equipe do Fluig Plataforma. É a forma padrão e é desejável que todos os widgets utilizem apenas essa técnica quando for necessário guardar algum tipo de informação para cada instância. Apesar de existirem outras formas de se guardar as preferências de um widget, recomendamos fortemente que utilize a forma disponibilizada pelo Fluig Plataforma pelos seguintes motivos:

  • não existe preocupação de "quem é propriedade de quem", uma vez que o Fluig guarda de forma independente as preferências para cada instância de widget;
  • cada página possui controle de versão e as instâncias dos widgets contidos nela não são diferentes. Utilizar as preferências padrão minimiza o risco de se perder alguma informação, já que tudo estará sob o controle de versão da plataforma Fluig;
  • a busca das informações é feita automaticamente pelo renderizador de página, tornando a consulta dos dados das preferências ágil e simples.
Informações
titleSobre tipos de dados

Na base da plataforma Fluig as preferências dos widget são salvas em uma tabela padrão da plataforma dentro de um campo do tipo texto. Apesar de ser usado um tipo de dado com grande capacidade de armazenamento, não se deve usá-lo para outra fim que não seja armazenar tipos de dados primitivos:

  • Character / String;
  • números de todos os tipos;
  • datas;
  • booleanos;

Sendo todos os dados salvos como string, caberá ao desenvolvedor fazer os tratamentos e conversões necessárias conforme a sua necessidade.

Armazenamento

Para salvar as preferências do widget, utilizamos o método WCMSpaceAPI.PageService.UPDATEPREFERENCES passando um método para callback (tratamento de retorno), o id da instância do widget e as preferências a serem salvas.

Bloco de código
languagejs
themeEclipse
var preferences = {
    newsSource: "fonte",
    url: "/news/feed/url",
    numberOfArticles: 10
};
 
WCMSpaceAPI.PageService.UPDATEPREFERENCES({
    async: true,
    success: function (data) {
			// código
    },
    fail: function (xhr, message, errorData) {
		// código
    }
}, this.instanceId, preferences
);

Utilização

No código abaixo podemos observar que o widget tem algumas variáveis chamadas news, newsSource, url e numberOfArticles.

Bloco de código
languagejs
themeEclipse
var KitIntranetNews = SuperWidget.extend({
    news: null,
    newsSource: null,
    url: null,
    numberOfArticles: null,
    DATASET: "dataset",
    FEED: "rssfeed",
    KIT_NEWS: "kit_news",
	// código
});

As preferências do widget são recuperadas automaticamente. Basta salvar as preferências com os nomes das variáveis do widget, como no tópico Como salvar as preferências do widget.


Integrando o widget com dados

Interno (formulários)

Externo utilizando serviços REST

Externo utilizando serviços JSON de terceiros (JSONP)

Externo utilizando serviços SOAP

Para fazer a integração com serviços SOAP, acesse este guia.


Exportar widget no servidor Fluig

Para exportar o widget para o servidor Fluig, basta seguir o guia Realizando o deploy do componente.


Evitar conflito de dependências com o Fluig

Para saber como evitar conflito de dependência entre widgets desenvolvidos sobre a plataforma e o Fluig, acesse este guia.


Zoom / Filter de Dataset

Para implementar o zoom de datasets em seu widget, pode-se usar como referência a forma indicada pelo Fluig Style Guide para fazer o filter/zoom de um serviço externo. Porém, é necessário atentar-se para alguns detalhes específicos do desenvolvimento de datasets.

Vide abaixo um exemplo que utiliza o dataset colleague como base:

Bloco de código
languagejs
titleDataset Filter
var settings = {
        source: {
            url: '/api/public/ecm/dataset/search?datasetId=colleague&searchField=colleagueName&',
Bloco de código
languagexml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	 version="3.0">
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <!-- REST -->
    <security-constraint>
        <display-name>REST</display-name>
        <web-resource-collection>
            <web-resource-name>REST</web-resource-name>
            <description>REST</description>
* Também poderia ser informada a URL      <url-pattern>completa: 
			'http://{host}:{port}/api/rest/*</url-pattern>public/ecm/dataset/search?datasetId=colleague&searchField=colleagueName&'
        </web-resource-collection>
    É importante manter  <auth-constraint>
            <description>REST</description>
            <role-name>user</role-name>
o "&" no final da URL, pois os outros parâmetros são montados 
         </auth-constraint>
    </security-constraint>
    <login-config>
        <auth-method>FORM</auth-method>
sem levar em consideração que já possa haver algo parametrizado no próprio link */
           <realm-name>TOTVSTech</realm-name>
  contentType: 'application/json',
             <form-login-config>root: 'content',
            <form-login-page>/login.jsp</form-login-page>pattern: '',
            <form-error-page>/loginfail.jsp</form-error-page>
  limit: 10,
      </form-login-config>
    </login-config>
    <security-role>offset: 0,
        <role-name>totvstech</role-name>
    </security-role>
    <security-role>patternKey: 'searchValue',
        <role-name>user</role-name>
    </security-role>
    <security-role>
        <role-name>sysadmin</role-name>
    </security-role>
    <welcome-file-list>
/*Para que a consulta funcione, é importante que o valor do 'patternKey' 
            seja  <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

Após isso estamos capazes de utilizar o REST que se encontra dentro da widget utilizando um método chamado WCMAPI.Read que iremos utilizá-lo para fazer chamadas REST.

Bloco de código
languagejs
var that = this;
 
WCMAPI.Read({
    type: "POST",
    url: WCMAPI.getServerURL() + '/news/api/rest/news/feed',
    async: true,
    data: feed,
    success: function funcao(data) {
        that.appendNews(data.content.channel.items);
    },
    error: function () {
        that.showLoadingError();
    }
});

O método WCMAPI.getServerURL()  traz a url do server que utilizaremos para montar a url da chamada rest. Em seguida concatenamos o caminho do REST que pretendemos chamar, neste caso utilizamos o seguinte caminho '/news/api/rest/news/feed'. Sendo:

'/news' o código da widget.

'/api/rest' é o @Path da classe ApplicationConfig.java.

'/news' é o @Path da classe NewsRest.java.

'/feed' é o @Path do método que desejamos chamar da classe NewsRest.java.

Exportar a widget no servidor Fluig

Para exportar a widget para o servidor Fluig, basta seguir o guia Realizando o deploy do componente.

 

...

sempre 'searchValue' para o caso de zoom de dataset */
            limitkey: 'limit',
            offsetKey: 'offset'
        },
        displayKey: 'colleagueName', 
        /* Para o dataset de colleague optamos por mostrar o nome completo.
        É aconselhável escolher o campo que, sozinho, represente melhor o registro*/
        multiSelect: true,
        style: {
            autocompleteTagClass: 'tag-gray',
            tableSelectedLineClass: 'info'
        }
    };
Nota
titleAtenção

Desde que obedecidos os demais itens do tutorial sobre filterdo Fluig Style Guide, basta copiar e colar o código acima diretamente em seu widget para observar o seu funcionamento.