[Gastosabertos-dev] ao
Andres MRM
andres em inventati.org
Sábado Março 7 02:51:14 UTC 2015
Agora está funcionando a paginação e aumentar o número de páginas.
Não sei se eu que fiz confusão ou se mexi em algo que arrumou isso sem
querer...
Quoting Andres MRM (2015-03-06 18:29:47)
> Quoting Luiz Armesto (2015-03-06 18:09:47)
> > Eu troquei a implementação antiga do pubsub pelo PubSubJS[1], daí mudou o
> > formato das mensagens. No lugar de dois pontos agora é um ponto, ficando "
> > pubsub.publish('years.changed', {value: [2012]})"
>
> Ah, deu certo! Que legal! =P
> Consigo alterar o ano dos dados na tabela usando esse comando no console.
>
> > A implementação da manipulação da url só trabalha com o fragmento do hash, o
> > que vem depois do #. Então ele simula uma string de query colocando "?param=
> > value" depois do #. Isso por que manipular o conteúdo do hash não faz com que a
> > página seja recarregada, já manipular o a string real de query, o "?param=
> > value" logo após o endereço, antes do #, faz com que o navegador faça uma nova
> > requisição.
> >
> >
> > Quando navega nas páginas ou altera a quantidade de itens não está alterando a
> > parte da URL depois do #? Qual navegador está usando para eu testar aqui? Não
> > está usando alguma versão antiga do js salva no cache?
>
> Agora vi que muda a URL sim. Mas não altera a tabela...
> Uso FF. Testei agora no Chromium e deu na mesma...
>
> >
> > Vou instalar localmente com o mysql e dar uma pesquisada para ver o erro da
> > conexão, mas acho que não tem tantos registros para dar pau numa contagem...
> > sei lá.
>
> Concordo...
> >
> >
> >
> > [1] https://github.com/mroderick/PubSubJS
> >
> > 2015-03-06 16:16 GMT-03:00 Andres MRM <andres em inventati.org>:
> >
> >
> > Tive o mesmo tipo de erro (a tabela não abriu).
> > Pelo que vi nos logs está dando: 'Lost connection to MySQL server during
> > query'
> > https://gist.github.com/andresmrm/3e2ac724d5c491607f09
> > Tem vários parecidos com esses lá.
> > Aparentemente o pau é na hora de 'X-Total-Count': revenue_data.count()
> > Será que é dado demais para ele contar? =P
> >
> > Outra coisa, Luiz, o pubsub é para estar funcionado?
> > Estou abrindo, por exemplo:
> > http://site.gastosabertos.org/receitas/?year=2014&level=2.3#2014/1?page=3&
> > year=2012&level=2.3
> > Indo no console e dando:
> > pubsub.publish('years:changed', {value: [2012]})
> > Mas ele está retornando 'false'
> > Apertar os botões da tabela, apesar de fazer duas requisições que retornam
> > 200
> > OK, não está tendo efeito...
> > Aumentar o número de páginas da tabela também faz as requisições, mas não
> > altera nada na página...
> >
> >
> > Quoting Luiz Armesto (2015-03-04 13:43:11)
> > > Aconteceu aqui o problema de não carregar a tabela direito mas com uma
> > causa
> > > diferente das possibilidades levantadas. No caso o servidor da api deu
> > erro
> > > 500.
> > >
> > > Não consegui reproduzir o erro nem localmente nem no próprio servidor
> > (dando
> > > reload ou abrindo em outra aba o mesmo endereço da api, com os mesmos
> > > parâmetros. funcionou).
> > > Precisaria ter acesso ao log do servidor para ver o que houve.
> > >
> > >
> > > []'s
> > >
> > > 2015-03-02 23:05 GMT-03:00 Luiz Armesto <luiz.armesto em gmail.com>:
> > >
> > > 2015-03-02 22:04 GMT-03:00 Edgar Zanella Alvarenga <e em vaz.io>:
> > >
> > > Ok, vi com mais calma o código agora e seu email esclareceu
> > melhor
> > > alguns pontos. Estava confuso com os eventos 'page.dt' e
> > 'length.dt',
> > > não sabia que eram eventos do próprio DataTables e pensei que os
> > > tinha criado também.
> > >
> > >
> > > É, isso não estava claro mesmo.
> > >
> > >
> > >
> > > Gostei de como fez, só acho que da linha 85 a 114 ficou um pouco
> > > obfuscated, apesar de entender a razão de querer ter feito um
> > código
> > > genéricopra lista de parâmetros em 'param'. Acho que seria melhor
> > > ter um subscribe explícito por parâmetro e separar em funções
> > distintas
> > > cada uma das cláusulas condicionais entre 103 e 107, entende, ao
> > > invése de um setParam genérico.
> > >
> > >
> > > Sobre as clausulas no setParam eu cheguei a fazer separado, mas
> > acabei
> > > juntando justamente para aprovitar o código de "subscribe" genérico
> > (linhas
> > > 85-114).
> > >
> > > Acho que separar os "subscribe" em dois explícitos para "page" e
> > > "per_page_num" e um genérico (o atual) não teria problema, apesar de
> > > introduzir código parcialmente repetido, mas se melhora a leitura e
> > > compreensão vale a pena.
> > > O que não dá é para remover completamente o código genérico que itera
> > nas
> > > chaves dos parâmetros definidos na inicialização do objeto senão ele
> > deixa
> > > de ser reaproveitável. Ficou um tanto obscuro mesmo, mas posso
> > melhorar com
> > > um comentário explicando o que o trecho faz e o porquê.
> > >
> > >
> > > Isso deixaria mais claro o código e mais separado a lógica a ser
> > > realizada a cada mudança de parâmetro.
> > >
> > > Tirando isso, maravilha, acho legal irmos por esse direção, me
> > parece
> > > uma solução simples e elegante.
> > >
> > > Quanto a dependência com o jquery, sim, devemos colocar isso via
> > > require,
> > > a idéia é que todo gerenciamento de dependência deja feito por
> > ele,
> > > então considere esses imports via script como algo que vamos ter
> > > que resolver.
> > >
> > >
> > > blz
> > >
> > >
> > >
> > > Ah sim, o parâmetro code pro endpoint listrevenue já está
> > funcionando:
> > >
> > > http://demo.gastosabertos.org/api/v1/receita/list?code=1.1.2&page
> > =0&
> > > per_page_num=10&years=2014
> > >
> > > Basta adicionar o code com parte do nível superior cujo subníveis
> > quer
> > > consultar.
> > >
> > >
> > > Boa, já inclui na tabela.
> > >
> > >
> > >
> > > E pra finalizar, sobre o Riot, eu só tinha visto o observer dele,
> > mas
> > > nunca usei e não faço idéia se na prática ele iria nos ajudar ou
> > > complicar
> > > mais no nosso caso de uso, pelo menos no problema de
> > sincronização de
> > > eventos. Eu só fiquei pensando se não era algo já resolvido por
> > um
> > > desses frameworks da modinha ou libs simples como:
> > >
> > > https://github.com/mroderick/PubSubJS
> > > https://github.com/uxder/Radio
> > >
> > > Que talvez evitem que tenhamos muito trabalho em resolver
> > problemas que
> > > não são nossa prioridade no momento. Novamente, não conheço a
> > fundo
> > > nenhuma dessa libs que citei e a única vantagem que vejo nelas é
> > > estarem
> > > desacopladas do JQuery, caso fossemos pra uma solução JQuery
> > free.
> > >
> > >
> > > Vou ver essas libs, mas de qualquer modo estou usando o jQuery para
> > pub/sub
> > > com facade, entre outras coisas, para usar uma interface com nomes de
> > > métodos comuns a implementações de pub/sub, então se quisermos chutar
> > o
> > > jQuery e usar uma lib dedicada será bem tranquilo. Ou adaptamos a
> > facade
> > > para a nova lib ou, se a interface for a mesma que fiz, tiramos a
> > facade e
> > > usamos direto a lib.
> > >
> > >
> > >
> > > Mas entendo o ponto de que estamos tentando sincronizar
> > componentes de
> > > libs diferentes, com arquiteturas diferentes e no final se
> > fossemos pra
> > > uma solução "mágica" acabaríamos tendo que fazer vários códigos
> > ao
> > > redor
> > > dessas bibliotecas pra conversarem entre si. E fiquei pensando na
> > parte
> > > pra sincronizar as mudanças nas variáveis com alterações no URL,
> > > leitura
> > > do URL pros parâmetros nas diferentes visualizações e me
> > perguntei se
> > > não tinha uma solução onde ganharíamos tudo isso pronto de
> > lambuja (a
> > > man
> > > can dream!).
> > >
> > >
> > > Já enviei o código que estava fazendo em relação a URL usando hash e
> > o pub/
> > > sub. Se tudo deu certo ao acessar http://site.gastosabertos.org/
> > receitas/#
> > > 2014/1.1.1?page=7 (e não estiver usando o js velho salvo no cache do
> > > navegador) verá a lista exibindo a página 8 dos impostos de 2014. Se
> > > navegar pelas páginas da tabela a URL deve ser atualizada e se usar
> > os
> > > botões de back/forward do navegador a tabela deve se atualizar junto
> > com a
> > > URL. Editar manualmente o ano (para periodo use hifen para separar o
> > ano de
> > > inicio e de fim) e o código na URL também funciona.
> > >
> > >
> > >
> > > Enfim, acho uma boa irmos pela direção que tomou, só talvez
> > tornar isso
> > > mais independente para que seja replicado nas outras páginas,
> > > provavelmente
> > > fazendo uma biblioteca, RSpubsub (Really Simple PubSub), mas esse
> > não
> > > precisa
> > > ser nossa prioridade agora.
> > >
> > > Abs,
> > > E.
> > >
> > >
> > > []'s
> > >
> > >
> > >
> > > On 02/03/2015 19:27, Luiz Armesto wrote:
> > >
> > > 2015-03-02 17:30 GMT-03:00 Edgar Zanella Alvarenga <e em vaz.io
> > [39]>:
> > >
> > >
> > > 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 [1]
> > >
> > > 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
> > >
> > >
> > > s 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 lib
> > >
> > > s, 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
> > > [40]
> > >
> > > [1] https://github.com/okfn-brasil/gastos_abertos_website/
> > blob/
> > > cd83cc446e6953b2281c7cebbdabc8f7d5e79772/frontend/src/
> > javascripts/
> > > receitas/main.js#L71
> > > [41]
> > >
> > > [2] https://github.com/okfn-brasil/gastos_abertos_website/
> > blob/
> > > cd83cc446e6953b2281c7cebbdabc8f7d5e79772/frontend/src/
> > javascripts/
> > > receitas/main.js#L211
> > > [42]
> > >
> > > [3] https://github.com/okfn-brasil/gastos_abertos_website/
> > blob/
> > > cd83cc446e6953b2281c7cebbdabc8f7d5e79772/frontend/src/
> > javascripts/
> > > receitas/main.js#L86
> > > [43]
> > >
> > > [4] https://github.com/okfn-brasil/gastos_abertos_website/
> > blob/
> > > cd83cc446e6953b2281c7cebbdabc8f7d5e79772/frontend/src/
> > javascripts/
> > > receitas/main.js#L199
> > > [44]
> > >
> > > []s
> > >
> > >
> > > Abs,
> > > E.
> > >
> > > On 02/03/2015 14:07, Luiz Armesto wrote:
> > >
> > >
> > > Links:
> > > ------
> > > [1] http://site.gastosabertos.org/receita
> > > [2] https://github.com/okfn-brasil/gastos_abertos/pull/134
> > > [3] https://github.com/okfn-brasil/gastos_abertos/issues/121
> > > [4] https://github.com/okfn-brasil/gastos_abertos/issues/132
> > > [5] mailto:Gastosabertos-dev em lists.okfn.org
> > > [6] https://lists.okfn.org/mailman/listinfo/gastosabertos-dev
> > > [7] mailto:Gastosabertos-dev em lists.okfn.org
> > > [8] https://lists.okfn.org/mailman/listinfo/gastosabertos-dev
> > > [9] mailto:Gastosabertos-dev em lists.okfn.org
> > > [10] https://lists.okfn.org/mailman/listinfo/
> > gastosabertos-dev
> > > [11] mailto:Gastosabertos-dev em lists.okfn.org
> > > [12] https://lists.okfn.org/mailman/listinfo/
> > gastosabertos-dev
> > > [13] mailto:Gastosabertos-dev em lists.okfn.org
> > > [14] https://lists.okfn.org/mailman/listinfo/
> > gastosabertos-dev
> > > [15] mailto:Gastosabertos-dev em lists.okfn.org
> > > [16] https://lists.okfn.org/mailman/listinfo/
> > gastosabertos-dev
> > > [17]
> > >
> > > http://demo.gastosabertos.org/receita/static/
> > total_by_year_by_code/
> > > 2014.json
> > > [18] mailto:e em vaz.io
> > > [19]
> > >
> > > http://demo.gastosabertos.org/receita/static/
> > total_by_year_by_code/
> > > 2014.json
> > > [20] http://demo.gastosabertos.org/api/v1/receita/
> > totaldrilldown?
> > > year=2014
> > > [21] http://demo.gastosabertos.org/api/v1/receita/
> > totaldrilldown?
> > > year=2014
> > > [22] mailto:Gastosabertos-dev em lists.okfn.org
> > > [23] https://lists.okfn.org/mailman/listinfo/
> > gastosabertos-dev
> > > [24] mailto:Gastosabertos-dev em lists.okfn.org
> > > [25] https://lists.okfn.org/mailman/listinfo/
> > gastosabertos-dev
> > > [26] mailto:Gastosabertos-dev em lists.okfn.org
> > > [27] https://lists.okfn.org/mailman/listinfo/
> > gastosabertos-dev
> > > [28] mailto:Gastosabertos-dev em lists.okfn.org
> > > [29] https://lists.okfn.org/mailman/listinfo/
> > gastosabertos-dev
> > > [30] https://github.com/okfn-brasil/gastos_abertos/pull/134
> > > [31] https://github.com/okfn-brasil/gastos_abertos/issues/121
> > > [32] mailto:Gastosabertos-dev em lists.okfn.org
> > > [33] https://lists.okfn.org/mailman/listinfo/
> > gastosabertos-dev
> > > [34] mailto:Gastosabertos-dev em lists.okfn.org
> > > [35] https://lists.okfn.org/mailman/listinfo/
> > gastosabertos-dev
> > > [36] mailto:e em vaz.io
> > > [37] mailto:Gastosabertos-dev em lists.okfn.org
> > > [38] https://lists.okfn.org/mailman/listinfo/
> > gastosabertos-dev
> > > [39] mailto:e em vaz.io
> > > [40]
> > >
> > > https://github.com/okfn-brasil/gastos_abertos_website/blob/
> > > cd83cc446e6953b2281c7cebbdabc8f7d5e79772/frontend/src/
> > javascripts/
> > > receitas/main.js#L188
> > > [41]
> > >
> > > https://github.com/okfn-brasil/gastos_abertos_website/blob/
> > > cd83cc446e6953b2281c7cebbdabc8f7d5e79772/frontend/src/
> > javascripts/
> > > receitas/main.js#L71
> > > [42]
> > >
> > > https://github.com/okfn-brasil/gastos_abertos_website/blob/
> > > cd83cc446e6953b2281c7cebbdabc8f7d5e79772/frontend/src/
> > javascripts/
> > > receitas/main.js#L211
> > > [43]
> > >
> > > https://github.com/okfn-brasil/gastos_abertos_website/blob/
> > > cd83cc446e6953b2281c7cebbdabc8f7d5e79772/frontend/src/
> > javascripts/
> > > receitas/main.js#L86
> > > [44]
> > >
> > > https://github.com/okfn-brasil/gastos_abertos_website/blob/
> > > cd83cc446e6953b2281c7cebbdabc8f7d5e79772/frontend/src/
> > javascripts/
> > > receitas/main.js#L199
> > >
> > >
> > > _______________________________________________
> > > Gastosabertos-dev mailing list
> > > Gastosabertos-dev em lists.okfn.org
> > > https://lists.okfn.org/mailman/listinfo/gastosabertos-dev
> > >
> > >
> > >
> > >
> > > --
> > > Luiz Armesto
> > >
> > >
> > >
> > >
> > > --
> > > Luiz Armesto
> > _______________________________________________
> > Gastosabertos-dev mailing list
> > Gastosabertos-dev em lists.okfn.org
> > https://lists.okfn.org/mailman/listinfo/gastosabertos-dev
> >
> >
> >
> >
> > --
> > Luiz Armesto
Mais detalhes sobre a lista de discussão Gastosabertos-dev