[Gastosabertos-dev] ao

Luiz Armesto luiz.armesto em gmail.com
Segunda Março 2 22:27:31 UTC 2015


2015-03-02 17:30 GMT-03:00 Edgar Zanella Alvarenga <e em vaz.io>:

> Oi Luiz, ótimo! Dei uma olhada rápida no seu código e fiz alguns testes.
> Está legal, mas ocorreu mais de uma vez ao visitar o
> http://site.gastosabertos.org/receita
> que o gráfico drilldown carregou, mas a tabela não. Uma vez consegui
> identificar
> o erro, que foi não conseguir importar o Datatables, talvez o servidor
> deles
> estava fora do ar.
>

Vou verificar isso. Além de problema no servidor deles pode ter sido
timeout do requirejs ou talvez tentou carregar o datatables antes do jquery
(atualmente o jquery está sendo carregado direto no html, com tag script,
mas o datatables via requirejs. Isso porque o jquery já estava sendo usado
direto sem o requirejs e o datatables identifica se tem alguma lib de AMD,
no caso o requirejs, e se registra direto nela, não deixando carregar
colocando direto uma tag script com ele, então tive que carregar usando o
requirejs. Precisamos arrumar isso, ou usar requirejs ou não usar, misturar
é pedir problemas).



> Mas olhando seu código, fiquei encafifado com a quantidade de código
> que escreveu pra registrar os eventos e não ficou claro pra mim o quão
> fácil será fazer isso sincronizado com o gráfico de barras. Se tivermos
> uma forma fácil de utilizar o modelo pusub que está usando legal sem muito
> biolerplate code, ótimo. Mas fico em dúvida se utilizarmos uma solução
> como o Riot js não seja melhor, pra não termos que resolver novamente
> certos problemas.


> O que você acha? Por mim sem problemas em utilizar a solução mais simples
> possível, só acho legal que exista um howto pra saber como usar o esquema
> que está utilizando nos outros gráficos em uma mesma página. O quanto
> de código precisará ser replicado? Se conseguir fazer um resumo bem breve
> do que tem em mente pra anotar os eventos e criar as funções pra
> respondê-los
> seria legal.
>


Pelo que olhei no riotjs não enxerguei uma solução mais simples usando ele
do que a que pensei. Nós temos que integrar componentes que são feitos com
libs de terceiros, então para sincronizar temos que escutar os eventos que
essas libs emitem quando o usuário interage com elas e chamar métodos que
elas definem na API para alterar seus valores na hora de sincronizar. Não
vejo como as funcionalidades do riotjs de virtual DOM com interpolação (o
DOM que exibem os gráficos e as tabelas são criadas pelas próprias libs
externas, não temos controle sobre isso) podem ajudar.

O que poderiamos usar do riotjs é a API de Observer deles, mas o jQuery já
implementa isso (é o que estou usando) e já o temos como dependência.

Vocês chegaram a pensar em como sincronizar os vários componentes usando o
riotjs e viram usos dele que eu não enxerguei?


Sobre a implementação do Sub/Pub, na verdade é apenas uma facade para a
implementação de eventos do jQuery, são 7 linhas [0] que definem um objeto
e redirecionam 3 métodos para o jQuery:

 subscribe --> on
 unsubscribe --> off
 publish -- trigger

Para usar é simplesmente criar uma instância e se registrar com o
"subscribe" para receber as notificações de uma determinada mensagem e
mandar notificações com o "publish":

// Cria o objeto
var pubSub = new PubSub();

// Registra para receber notificações
pubSub.subscribe('nome_da_mensagem', function(evt, content) {
  console.log('Mensagem recebida com o seguinte conteúdo: ', content);
});

// Publica notificação
pubSub.publish('nome_da_mensagem', 'este é o conteúdo');

// Neste ponto foi exibido "Mensagem recebida com o seguinte conteúdo: este
é o conteúdo"

Então para usar o pub/sub é bem fácil e com muito pouco código, só precisa
que todos os envolvidos na sincronização tenham acesso ao mesmo objeto de
pub/sub e compartilhem de uma padronização nos nomes e formatos das
mensagens enviadas, sem ter conhecimento de quem são os demais
participantes (desacoplados). Então se, por exemplo, a tabela registrou
para receber uma mensagem quando o código é alterado, ela tera o mesmo
comportamento independente se a alteração é proveniente de uma mudança na
url, um clique no gráfico ou uma seleção num menu, só precisa que a
mensagem seja publicada no objeto pub/sub seguindo o padrão definido.

O que acontece, em relação a quantidade de código que escrevi, para ter
mais linhas [1] do que 3 simples "pubSub.subscribe(...)" (que seria um para
"page", um para "per_page_num" e um para "years", que são as três coisas
que atualmente importam para a tabela) é porque eu fiz de um modo que o
mesmo objeto pode ser reutilizado para tabelas diferentes, que buscam os
dados em outros endpoints que tenham parâmetros diferentes (ou mesmo para
estender o funcionamento da tabela atual quando os outros parâmetros forem
implementados, como o "codes", sem precisar alterar o código).

Eu defino na criação do objeto quais são os parâmetros do endpoint que
importam para a tabela, ou que poderão ser alterados externamente por outro
componente, podendo definir um valor inicial [2], então eu itero sobre os
parâmetros registrando automaticamente [3].

Assim, se eu criar um objeto DataTable passando nas opções "params: {
years: 2014, page: 0, per_page_num: 10  }" ele vai se registrar para as
mensagens "years:changed", "page:changed" e "per_page_num:changed" e quando
qualquer um publicar uma dessas mensagens ele vai se atualizar. Quando
tivermos implementado o parâmetro "codes" na endpoint "List revenues" basta
alterar na criação do objetos incluindo esse parâmetro nas opções (passando
a ser "params: { years: 2014, page: 0, per_page_num: 10 , codes: null }")
que a tabela passará a responder também a mensagem "codes:changed",
armazenando internamente o valor (método "setParam" chamado pelo callback
do "pubSub.subscribe"), que será enviado na requisição AJAX (no método
"_ajaxRequest", que é usado pela lib DataTables, e é responsável por enviar
todos os parâmetros registrados).


Então para criar tabelas com dados diferentes, endpoint diferente e
parâmetros diferentes, mas também facilmente sincronizável e com paginação
via ajax, basta criar um objeto DataTable informando qual a url do
endpoint, quais são os parametros e quais são os campos do json de cada
coluna e pronto. Fazer o que está entre as linhas 199 e 222 [4] com as
devidas alterações, em especial em "columns" e "params", sem precisar nem
criar mais funções nem definir outros tipos de objetos.


TL; DR;

Para sincronizar, o componente com o qual o usuário está interagindo, por
exemplo no caso do ano ser alterado, só terá que chamar
"pubSub.publish(years:changed, {value: [anoMin, anoMax]})" e os demais
terem se registrado com "pubSub.subscribe(years:changed, callback)", e
implementado a logica necessária no callback, para serem notificados e se
manterem sincronizados.

O DataTable é mais complicado do que isso pois foi feito de modo genérico
para ser reutilizado em outras páginas, pecisando apenas configurar algumas
coisas na criação do objeto.



[0]
https://github.com/okfn-brasil/gastos_abertos_website/blob/cd83cc446e6953b2281c7cebbdabc8f7d5e79772/frontend/src/javascripts/receitas/main.js#L188
[1]
https://github.com/okfn-brasil/gastos_abertos_website/blob/cd83cc446e6953b2281c7cebbdabc8f7d5e79772/frontend/src/javascripts/receitas/main.js#L71
[2]
https://github.com/okfn-brasil/gastos_abertos_website/blob/cd83cc446e6953b2281c7cebbdabc8f7d5e79772/frontend/src/javascripts/receitas/main.js#L211
[3]
https://github.com/okfn-brasil/gastos_abertos_website/blob/cd83cc446e6953b2281c7cebbdabc8f7d5e79772/frontend/src/javascripts/receitas/main.js#L86
[4]
https://github.com/okfn-brasil/gastos_abertos_website/blob/cd83cc446e6953b2281c7cebbdabc8f7d5e79772/frontend/src/javascripts/receitas/main.js#L199


[]'s



>
> Abs,
> E.
>
> On 02/03/2015 14:07, Luiz Armesto wrote:
>
>> Para sincronização na tabela eu implementei um padrão pub/sub, daí
>> mandando uma mensagem como "pubSub.publish(years:changed, {value:
>> [2012, 2014]})" usando a instancia do PubSub que eu incluo na tabela
>> ela se atualiza para usar o ano (ou período entre dois anos) passado.
>> Quando navega pelas páginas da tabela ou muda o número de itens por
>> página ela publica pelo pubSub mensagens "page:changed" e
>> "per_page_num:changed" (se algum outro objeto mandar o pubSub emitir
>> essas mensagens a tabela identifica e altera, respectivamente, a
>> página sendo exibida ou o número de items), que podem ser escutadas
>> por qualquer um que tenha acesso a instância do pubSub, sem criar
>> acoplamento com o objeto da tabela.
>>
>> Eu já comecei a escrever uma código para colocar e pegar os
>> parametros da URL, ainda hoje mando algo.
>>
>> Se quiserem testar, o pubSub está temporariamente acessivel via
>> console, então dá para mandar um "pubSub.publish(years:changed,
>> {value: [2012, 2014]})" para ver mudando o ano e um
>> "pubSub.publish(page:changed, {value: 3})" para ver ela indo pra
>> página "4" (no código começa com indice 0 mas na interface é com
>> indice 1)
>>
>> []s
>>
>> 2015-03-02 13:54 GMT-03:00 Edgar Zanella Alvarenga <e em vaz.io [18]>:
>>
>>  Acho que tá legal, só senti falta da animação que existia antes
>>> na transição
>>> com drilldown. Será que não dá de forma simples de termos isso?
>>> Agora
>>> o que precisamos são as outras tarefas:
>>>
>>>  * Breadcrumb navegável pelos níveis
>>>  + Seleção do ano
>>>  * Sincronização com tabela abaixo
>>>
>>> E o mais importante, que acho que seria legal discutirmos os três:
>>> colocar os
>>> parâmetros da visualização no URL na medida que se navega tanto
>>> pelo drilldown
>>> quanto pela tabel, para assim termos urls que possam ser
>>> compartilhadas.
>>>
>>> E
>>>
>>> On 02/03/2015 12:25, Andres MRM wrote:
>>>
>>>  Acho que agora foi.
>>>> Você tinha habilitado CORS para a API Restfull, mas não para os
>>>> statics.
>>>>
>>>> Como os statics estavam sendo configurados via Blueprint, eu não
>>>> estava
>>>> conseguindo descobrir onde colocar o decorador cors.
>>>> Perguntei no #pocoo e um cara me orientou a usar o
>>>> "after_request".
>>>> https://github.com/okfn-brasil/gastos_abertos/pull/134 [12]
>>>> Pelo que testei está funcionando, mas não sei se a API não
>>>> está sendo
>>>> decorada
>>>> duas vezes desse jeito.
>>>>
>>>> Veja se está tudo certo para fechar o:
>>>> https://github.com/okfn-brasil/gastos_abertos/issues/121 [13]
>>>>
>>>>
>>>> Quoting Andres MRM (2015-03-02 08:56:21)
>>>>
>>>>  Concordo completamente que servir arquivos estáticos daquela
>>>>> maneira não era
>>>>> bom. Eu inclusive deixei um TODO na própria função dizendo
>>>>> que aquilo estava
>>>>> feio.
>>>>> Mas no momento da implementação não estava achando outro
>>>>> jeito simples (não
>>>>> sabia que a API tinha uma pasta static dentro da receita),
>>>>> então fui naquele
>>>>> mesmo temporariamente.
>>>>>
>>>>> Edgar, eu acho que você manja muito e gosto muito de você
>>>>> como pessoa, mas só
>>>>> peço para maneirar um pouco nos tons dos comentários. Aqui na
>>>>> lista ainda está
>>>>> mais de boa, mas no issue está agressivo.
>>>>> Estou me esforçando ao máximo para tentar implementar as
>>>>> coisas do seu jeito
>>>>> (que concordo que geralmente é melhor), mas nem tudo que está
>>>>> na sua cabeça é
>>>>> trivial e transparente. Trivial no sentido de só ter uma
>>>>> implementação óbvia,
>>>>> e transparente de ser fácil saber o que você está pensando.
>>>>> Tenho perguntado o
>>>>> máximo que posso para você justamente para evitar fazer as
>>>>> coisas de outra
>>>>> forma, mas nem sempre você responde e também não dá para
>>>>> perguntar linha a
>>>>> linha...
>>>>>
>>>>> Arrumei o que você falou. Aparentemente o erro de COR persiste
>>>>> mesmo com o
>>>>> link funcionando:
>>>>>
>>>>>
>>>>>
>>>>
>>>
>> http://demo.gastosabertos.org/receita/static/total_by_year_
>> by_code/2014.json
>>
>>> [1]
>>>>>
>>>>> Abs
>>>>>
>>>>> Quoting Edgar Zanella Alvarenga (2015-03-02 07:51:12)
>>>>> > Andres, você nao debugou o problema. Se d erro num request
>>>>> pra API,
>>>>> > o Firefox indica erro de CORS. Mas pra saber se foi CORS,
>>>>> melhor ver
>>>>> > a resposta ao request da API. Fazendo isso vi que o código
>>>>> estava
>>>>> > dando um exception na linha 281 dum endpoint que você
>>>>> adicionou, que
>>>>> > nunca deveia ter sido adicionado:
>>>>> >
>>>>> > https://github.com/okfn-brasil/gastos_abertos/issues/132 [2]
>>>>>
>>>>> >
>>>>> > Nunca faça um endpoint para servir arquivos estáticos! A
>>>>> não ser
>>>>> > que tenha uma lógica extremamente complexa pra buscar os
>>>>> arquivos
>>>>> > baseado
>>>>> > no request. No nosso caso precisamos apenas de arquivos
>>>>> estáticos
>>>>> > nomeados pelo ano, nada mais do que isso.
>>>>> >
>>>>> > Coloque os arquivos em data/total_by_year_by_code/ em algum
>>>>> local do
>>>>> > static
>>>>> > do gastos_abertos no momento, e a requisição no view
>>>>> deverá ser
>>>>> > alterada de
>>>>> > acordo. Só estou falando pra colocar lá para ser gerado
>>>>> novamente a
>>>>> > cada novo deploy
>>>>> > da api pelo fab. Esqueça o que comentei no issue pra colocar
>>>>> no repo
>>>>> > gastos_abertos_website.
>>>>> >
>>>>> > Abs,
>>>>> > Edgar
>>>>> >
>>>>> > On 02/03/2015 07:38, Andres MRM wrote:
>>>>> > > Você diz a que fica em settings/local_settings.py?
>>>>> > > Não mexi nisso no servidor, mas imagino que esteja, já
>>>>> que o
>>>>> > > DataTables está
>>>>> > > conseguindo fazer o request normal...
>>>>> > >
>>>>> > >
>>>>> > > Quoting Edgar Zanella Alvarenga (2015-03-02 07:26:06)
>>>>> > >> Você está utilizando a configuração correta pro
>>>>> API_URL?
>>>>> > >>
>>>>> > >> On 02/03/2015 06:39, Andres MRM wrote:
>>>>> > >> > Estou tentando fazer o drilldown funcionar no servidor,
>>>>> mas estou
>>>>> > >> > tendo aquele
>>>>> > >> > erro de COR:
>>>>> > >> >
>>>>> > >> >       Cross-Origin Request Blocked: The Same Origin
>>>>> Policy
>>>>> > >> disallows
>>>>> > >> > reading the
>>>>> > >> >       remote resource at
>>>>> > >> >
>>>>> > >> >
>>>>> > >>
>>>>>
>>>>>
>>>>
>>>  http://demo.gastosabertos.org/api/v1/receita/totaldrilldown?year=2014
>>
>>> [3].
>>>>> > >> > This
>>>>> > >> >       can be fixed by moving the resource to the
>>>>> same domain or
>>>>> > >> enabling
>>>>> > >> > CORS.
>>>>> > >> >
>>>>> > >> > Pelo visto o request do DataTables para a API está
>>>>> funcionando sem
>>>>> > >> > problema,
>>>>> > >> > só o meu que não. =(
>>>>> > >> > Alguma ideia do porque?
>>>>> > >> >
>>>>> > >> > _______________________________________________
>>>>> > >> > Gastosabertos-dev mailing list
>>>>> > >> > Gastosabertos-dev em lists.okfn.org [4]
>>>>> > >> >
>>>>> https://lists.okfn.org/mailman/listinfo/gastosabertos-dev [5]
>>>>> > >>
>>>>> > >> _______________________________________________
>>>>> > >> Gastosabertos-dev mailing list
>>>>> > >> Gastosabertos-dev em lists.okfn.org [6]
>>>>> > >> https://lists.okfn.org/mailman/listinfo/gastosabertos-dev
>>>>> [7]
>>>>> > > _______________________________________________
>>>>> > > Gastosabertos-dev mailing list
>>>>> > > Gastosabertos-dev em lists.okfn.org [8]
>>>>> > > https://lists.okfn.org/mailman/listinfo/gastosabertos-dev
>>>>> [9]
>>>>> >
>>>>> > _______________________________________________
>>>>> > Gastosabertos-dev mailing list
>>>>> > Gastosabertos-dev em lists.okfn.org [10]
>>>>> > https://lists.okfn.org/mailman/listinfo/gastosabertos-dev
>>>>> [11]
>>>>>
>>>> _______________________________________________
>>>> Gastosabertos-dev mailing list
>>>> Gastosabertos-dev em lists.okfn.org [14]
>>>> https://lists.okfn.org/mailman/listinfo/gastosabertos-dev [15]
>>>>
>>>
>>> _______________________________________________
>>> Gastosabertos-dev mailing list
>>> Gastosabertos-dev em lists.okfn.org [16]
>>> https://lists.okfn.org/mailman/listinfo/gastosabertos-dev [17]
>>>
>>
>> --
>>
>> Luiz Armesto
>>
>>
>> Links:
>> ------
>> [1]
>>
>> http://demo.gastosabertos.org/receita/static/total_by_year_
>> by_code/2014.json
>> [2] https://github.com/okfn-brasil/gastos_abertos/issues/132
>> [3] http://demo.gastosabertos.org/api/v1/receita/totaldrilldown?year=2014
>> [4] mailto:Gastosabertos-dev em lists.okfn.org
>> [5] https://lists.okfn.org/mailman/listinfo/gastosabertos-dev
>> [6] mailto:Gastosabertos-dev em lists.okfn.org
>> [7] https://lists.okfn.org/mailman/listinfo/gastosabertos-dev
>> [8] mailto:Gastosabertos-dev em lists.okfn.org
>> [9] https://lists.okfn.org/mailman/listinfo/gastosabertos-dev
>> [10] mailto:Gastosabertos-dev em lists.okfn.org
>> [11] https://lists.okfn.org/mailman/listinfo/gastosabertos-dev
>> [12] https://github.com/okfn-brasil/gastos_abertos/pull/134
>> [13] https://github.com/okfn-brasil/gastos_abertos/issues/121
>> [14] mailto:Gastosabertos-dev em lists.okfn.org
>> [15] https://lists.okfn.org/mailman/listinfo/gastosabertos-dev
>> [16] mailto:Gastosabertos-dev em lists.okfn.org
>> [17] https://lists.okfn.org/mailman/listinfo/gastosabertos-dev
>> [18] mailto:e em vaz.io
>>
>
> _______________________________________________
> Gastosabertos-dev mailing list
> Gastosabertos-dev em lists.okfn.org
> https://lists.okfn.org/mailman/listinfo/gastosabertos-dev
>



-- 
Luiz Armesto
-------------- Próxima Parte ----------
Um anexo em HTML foi limpo...
URL: <http://lists.okfn.org/pipermail/gastosabertos-dev/attachments/20150302/ad2c3aa8/attachment-0003.html>


Mais detalhes sobre a lista de discussão Gastosabertos-dev