diff --git a/frontend/src/__apps/painel/main.js b/frontend/src/__apps/painel/main.js
index fdf4e5dbd..2328573fa 100644
--- a/frontend/src/__apps/painel/main.js
+++ b/frontend/src/__apps/painel/main.js
@@ -1 +1,267 @@
import './scss/painel.scss'
+import Vue from 'vue'
+import axios from 'axios'
+
+axios.defaults.xsrfCookieName = 'csrftoken'
+axios.defaults.xsrfHeaderName = 'X-CSRFToken'
+
+// Variaveis dos cronometros
+var crono = 0
+var time = null
+var timeEnd = null
+var audioAlertFinish = document.getElementById('audio')
+var cronometroStart = []
+
+const v = new Vue({ // eslint-disable-line
+ delimiters: ['[[', ']]'],
+ el: '#app-painel',
+ data () {
+ return {
+ message: 'Hello VueJUS', // TODO: remove when porting to VueJS is done
+ polling: null,
+ painel_aberto: true,
+ sessao_plenaria: '',
+ sessao_plenaria_data: '',
+ sessao_plenaria_hora_inicio: '',
+ brasao: '',
+ cronometro_discurso: '',
+ cronometro_aparte: '',
+ cronometro_ordem: '',
+ cronometro_consideracoes: '',
+ sessao_solene: false,
+ sessao_solene_tema: '',
+ presentes: [],
+ oradores: [],
+ numero_votos_sim: 0,
+ numero_votos_nao: 0,
+ numero_abstencoes: 0,
+ num_presentes: 0,
+ total_votos: 0,
+ sessao_finalizada: true,
+ materia_legislativa_texto: '',
+ materia_legislativa_ementa: '',
+ observacao_materia: '',
+ mat_em_votacao: '',
+ resultado_votacao_css: '',
+ tipo_resultado: '',
+ tipo_votacao: '',
+ running: 0
+ }
+ },
+ methods: {
+ msgMateria () {
+ if (this.tipo_resultado && this.painel_aberto) {
+ if (this.tipo_votacao !== 'Leitura' && !this.sessao_finalizada && !this.sessao_solene) {
+ this.resultado_votacao_css = 'color: #45919D'
+ this.mat_em_votacao = 'Matéria em Votação'
+ } else {
+ this.resultado_votacao_css = 'color: #45919D'
+ this.mat_em_votacao = 'Matéria em Leitura'
+ }
+
+ this.resultado_votacao = this.tipo_resultado
+
+ var resultado_votacao_upper = this.resultado_votacao.toUpperCase()
+
+ if (resultado_votacao_upper.search('APROV') !== -1) {
+ this.resultado_votacao_css = 'color: #7CFC00'
+ this.mat_em_votacao = 'Matéria Votada'
+ } else if (resultado_votacao_upper.search('REJEIT') !== -1) {
+ this.resultado_votacao_css = 'color: red'
+ this.mat_em_votacao = 'Matéria Votada'
+ } else if (resultado_votacao_upper.search('LIDA') !== -1) {
+ this.mat_em_votacao = 'Matéria Lida'
+ }
+ } else {
+ this.resultado_votacao = ''
+ if (this.tipo_votacao !== 'Leitura') {
+ this.mat_em_votacao = 'Matéria em Votação'
+ } else {
+ this.mat_em_votacao = 'Matéria em Leitura'
+ }
+ }
+ },
+ atribuiColor (parlamentar) {
+ var color = 'white'
+ if (parlamentar.voto === 'Voto Informado' || parlamentar.voto === '') {
+ color = 'yellow'
+ } else {
+ if (parlamentar.voto === 'Sim') {
+ color = 'green'
+ } else if (parlamentar.voto === 'Não') {
+ color = 'red'
+ }
+ }
+ parlamentar.color = color
+ },
+ capObservacao (texto) {
+ if (texto && texto.length > 151) {
+ return texto.substr(0, 145).concat('(...)')
+ }
+ return texto
+ },
+ converterUrl (url) {
+ url = url.slice(-(url.length - url.lastIndexOf('/')))
+ url = '/painel' + url + '/dados'
+ return url
+ },
+ fetchData () {
+ // TODO: how to get no hardcoded URL?
+ $.get(this.converterUrl(window.location.pathname), function (response) {
+ this.brasao = response.brasao
+ this.painel_aberto = response.status_painel
+ this.sessao_finalizada = response.sessao_finalizada
+ this.sessao_plenaria = response.sessao_plenaria
+ this.sessao_plenaria_data = 'Data Início: ' + response.sessao_plenaria_data
+ this.sessao_plenaria_hora_inicio = 'Hora Início: ' + response.sessao_plenaria_hora_inicio
+ this.sessao_solene = response.sessao_solene
+ this.sessao_solene_tema = response.sessao_solene_tema
+
+ this.presentes = response.presentes
+ this.presentes.forEach(parlamentar => {
+ this.atribuiColor(parlamentar)
+ })
+
+ this.oradores = response.oradores
+
+ this.materia_legislativa_texto = response.materia_legislativa_texto
+ this.numero_votos_sim = response.numero_votos_sim
+ this.numero_votos_nao = response.numero_votos_nao
+ this.numero_abstencoes = response.numero_abstencoes
+ this.num_presentes = response.num_presentes
+ this.total_votos = response.total_votos
+
+ this.materia_legislativa_texto = response.materia_legislativa_texto
+ this.materia_legislativa_ementa = response.materia_legislativa_ementa
+ this.observacao_materia = this.capObservacao(response.observacao_materia)
+
+ this.tipo_resultado = response.tipo_resultado
+ this.tipo_votacao = response.tipo_votacao
+ this.mat_em_votacao = this.msgMateria()
+
+ // Cronometros
+ cronometroStart[0] = response.cronometro_discurso
+ cronometroStart[1] = response.cronometro_aparte
+ cronometroStart[2] = response.cronometro_ordem
+ cronometroStart[3] = response.cronometro_consideracoes
+
+ if (time === null) {
+ // Pegar data atual
+ this.cronometro_discurso = new Date()
+ this.cronometro_aparte = this.cronometro_discurso
+ this.cronometro_ordem = this.cronometro_discurso
+ this.cronometro_consideracoes = this.cronometro_discurso
+
+ // Setar cada Cronometro
+ var temp = new Date()
+ temp.setSeconds(this.cronometro_discurso.getSeconds() + cronometroStart[0])
+ var res = new Date(temp - this.cronometro_discurso)
+ this.cronometro_discurso = this.formatTime(res)
+
+ temp = new Date()
+ temp.setSeconds(this.cronometro_aparte.getSeconds() + cronometroStart[1])
+ res = new Date(temp - this.cronometro_aparte)
+ this.cronometro_aparte = this.formatTime(res)
+
+ temp = new Date()
+ temp.setSeconds(this.cronometro_ordem.getSeconds() + cronometroStart[2])
+ res = new Date(temp - this.cronometro_ordem)
+ this.cronometro_ordem = this.formatTime(res)
+
+ temp = new Date()
+ temp.setSeconds(this.cronometro_consideracoes.getSeconds() + cronometroStart[3])
+ res = new Date(temp - this.cronometro_consideracoes)
+ this.cronometro_consideracoes = this.formatTime(res)
+ }
+ }.bind(this))
+ },
+ formatTime (time) {
+ var tempo = '00:' + time.getMinutes().toLocaleString('en-US', {
+ minimumIntegerDigits: 2,
+ useGrouping: false
+ }) + ':' + time.getSeconds().toLocaleString('en-US', {
+ minimumIntegerDigits: 2,
+ useGrouping: false
+ })
+ return tempo
+ },
+ stop: function stop (crono) {
+ if (crono === 5) {
+ audioAlertFinish.play()
+ }
+
+ this.running = 0
+ clearInterval(this.started)
+ this.stopped = setInterval(() => {
+ this.timeStopped()
+ }, 100)
+ },
+ timeStopped () {
+ timeEnd.setMilliseconds(timeEnd.getMilliseconds() + 100)
+ },
+ reset: function reset () {
+ this.running = 0
+ time = null
+ clearInterval(this.started)
+ clearInterval(this.stopped)
+ },
+ clockRunning (crono) {
+ var now = new Date()
+ time = new Date(timeEnd - now)
+
+ // Definir propriamento o tempo
+ time.setHours(timeEnd.getHours() - now.getHours())
+
+ if (timeEnd > now) {
+ if (crono === 1) {
+ this.cronometro_discurso = this.formatTime(time)
+ } else if (crono === 2) {
+ this.cronometro_aparte = this.formatTime(time)
+ } else if (crono === 3) {
+ this.cronometro_ordem = this.formatTime(time)
+ } else {
+ this.cronometro_consideracoes = this.formatTime(time)
+ }
+ } else {
+ audioAlertFinish.play()
+ this.alert = setTimeout(() => {
+ this.reset()
+ }, 5000)
+ }
+ },
+ start: function startStopWatch (temp_crono) {
+ if (this.running !== 0) return
+
+ crono = temp_crono
+ if (time === null) {
+ time = cronometroStart[crono - 1]
+ console.log(time)
+ timeEnd = new Date()
+ timeEnd.setSeconds(timeEnd.getSeconds() + time)
+ } else {
+ clearInterval(this.stopped)
+ }
+ this.running = crono
+
+ this.started = setInterval(() => {
+ this.clockRunning(crono)
+ }, 100)
+ },
+ pollData () {
+ this.fetchData()
+
+ this.polling = setInterval(() => {
+ console.info('Fetching data from backend')
+ this.fetchData()
+ }, 100)
+ }
+ },
+ beforeDestroy () {
+ console.info('Destroying polling.')
+ clearInterval(this.polling)
+ },
+ created () {
+ console.info('Start polling data...')
+ this.pollData()
+ }
+})
diff --git a/sapl/painel/views.py b/sapl/painel/views.py
index 75f5a1b97..6718683cd 100644
--- a/sapl/painel/views.py
+++ b/sapl/painel/views.py
@@ -352,6 +352,18 @@ def get_cronometro_status(request, name):
cronometro = ''
return cronometro
+def get_cronometro_value(request, name):
+ if name == 'discurso':
+ result = ConfiguracoesAplicacao.objects.first().cronometro_discurso
+ if name == 'aparte':
+ result = ConfiguracoesAplicacao.objects.first().cronometro_aparte
+ if name == 'ordem':
+ result = ConfiguracoesAplicacao.objects.first().cronometro_ordem
+ if name == 'consideracoes':
+ result = ConfiguracoesAplicacao.objects.first().cronometro_consideracoes
+
+ return result.total_seconds()
+
def get_materia_aberta(pk):
return OrdemDia.objects.filter(
@@ -558,10 +570,10 @@ def get_dados_painel(request, pk):
'sessao_solene': sessao.tipo.nome == "Solene",
'sessao_finalizada': sessao.finalizada,
'tema_solene': sessao.tema_solene,
- 'cronometro_aparte': get_cronometro_status(request, 'aparte'),
- 'cronometro_discurso': get_cronometro_status(request, 'discurso'),
- 'cronometro_ordem': get_cronometro_status(request, 'ordem'),
- 'cronometro_consideracoes': get_cronometro_status(request, 'consideracoes'),
+ 'cronometro_aparte': get_cronometro_value(request, 'aparte'),
+ 'cronometro_discurso': get_cronometro_value(request, 'discurso'),
+ 'cronometro_ordem': get_cronometro_value(request, 'ordem'),
+ 'cronometro_consideracoes': get_cronometro_value(request, 'consideracoes'),
'status_painel': sessao.painel_aberto,
'brasao': brasao
}
diff --git a/sapl/templates/painel/index.html b/sapl/templates/painel/index.html
index 1cb2e2c83..35f8f3430 100644
--- a/sapl/templates/painel/index.html
+++ b/sapl/templates/painel/index.html
@@ -1,495 +1,231 @@
{% load i18n %}
{% load common_tags %}
+{% load staticfiles %}
{% load render_bundle from webpack_loader %}
{% load webpack_static from webpack_loader %}
-
-
-
-
-
-
-
- {% block head_title %}{% trans 'SAPL - Sistema de Apoio ao Processo Legislativo' %}{% endblock %}
-
- {% block webpack_loader_css %}
- {% render_chunk_vendors 'css' %}
- {% render_bundle 'global' 'css' %}
- {% render_bundle 'painel' 'css' %}
- {% endblock webpack_loader_css %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
{% block head_title %}{% trans 'SAPL - Sistema de Apoio ao Processo Legislativo' %}{% endblock %}
+
+ {% block webpack_loader_css %}
+ {% render_chunk_vendors 'css' %}
+ {% render_bundle 'global' 'css' %}
+ {% render_bundle 'painel' 'css' %}
+ {% endblock webpack_loader_css %}
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
[[ sessao_plenaria ]]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Parlamentares
-
-
+
+
+
+ [[ sessao_plenaria_data ]]
+
+
+ [[ sessao_plenaria_hora_inicio ]]
-
+
+
+
PAINEL ENCONTRA-SE FECHADO
+
+
+
-
-
Cronômetros
-
- Discurso:
- Aparte:
- Questão de Ordem:
- Considerações Finais:
+
+
+
+
+
+
Parlamentares
+
+
+
+
+
+ [[p.nome]]
+
+
+ [[p.partido]]
+
+
+ [[p.voto]]
+
+
+
+
+
+
+
+ A listagem de parlamentares só aparecerá quando o painel estiver aberto.
+
+
+
+
+
+
+
Oradores
+
+
+
+
+
+ [[ o.numero]]º  [[o.nome]]
+
+
+
+
+
+
+
+ A listagem de oradores só aparecerá quando o painel estiver aberto.
+
+
-
-
-
Resultado
-
-
-
-
-
-
Matéria em Votação
-
-
-
-
-
+
+
+
+
+
+
Cronômetros
+
+ Discurso:[[ cronometro_discurso ]]
+ Iniciar Reiniciar
+ Parar
+
+
+ Aparte:[[ cronometro_aparte ]]
+ Iniciar Reiniciar
+ Parar
+
+
+ Questão de Ordem: [[ cronometro_ordem ]]
+ Iniciar Reiniciar
+ Parar
+
+
+ Considerações Finais: [[ cronometro_consideracoes ]]
+ Iniciar Reiniciar
+ Parar
+
-
-
-
Tema da Sessão Solene
-
+
+
+
+
Tema da Sessão Solene
+ [[ sessao_solene_tema ]]
+
+
+
+
Resultado
+
+
+ Sim: [[ numero_votos_sim ]]
+ Não: [[ numero_votos_nao ]]
+ Abstenções: [[ numero_abstencoes ]]
+ Presentes: [[ num_presentes ]]
+ Total votos: [[ total_votos ]]
+
+
[[ tipo_resultado ]]
+
+
+
Não há votação, pois não há nenhuma matéria aberta ou já votada.
+
+
+
+
+
[[ mat_em_votacao ]]
+
+ [[ materia_legislativa_texto ]]
+
+ [[ materia_legislativa_ementa ]]
+
+ [[ observacao_materia ]]
+
+
+ Não há nenhuma matéria votada ou para votação.
+
+
+
+
+ A Matéria em votação só aparecerá quando o painel estiver aberto
+
+
+
+
+
Resultado
+
+ A votação só aparecerá quando o painel estiver aberto
+
+
+
-
-
-
-
- {% block webpack_loader_js %}
- {% render_chunk_vendors 'js' %}
- {% render_bundle 'global' 'js' %}
- {% render_bundle 'painel' 'js' %}
- {% endblock webpack_loader_js %}
+
+
+
- {% block webpack_loader_chunks_js %}
- {% endblock webpack_loader_chunks_js %}
+ {% block webpack_loader_js %}
+ {% render_chunk_vendors 'js' %}
+ {% render_bundle 'global' 'js' %}
+ {% render_bundle 'painel' 'js' %}
+ {% endblock webpack_loader_js %}
-
-
-
+ // As constantes decisões sobre a existência ou não do horário de verão,
+ // assim como que data de início e termino do mesmo, fizeram com que fosse necessário
+ // substituir a chamada a Date() por um esquema mais elaborado, onde se
+ // recupera o offset do UTC (-3 GMT, no caso de Brasília) e seta-se
+ // manualmente. Esta informação vem do servidor, desta forma não ficamos
+ // na dependência da atualização de browser, pois tanto o Date() em JS
+ // quanto as libs python (django.utils.timezone, datetime, pytz, etc)
+ // lêem do tzdata, que precisa ser atualizado toda vez que o governo
+ // brasileiro modifica alguma coisa relacionada ao horário de verão.
+ // Recuperando essa informação do servidor só teremos que atualizar as
+ // libs tzdata (Linux) e pytz (Python) uma vez. Além disso, o uso da
+ // biblioteca moment.js é recomendada, pois ela trata data e hora
+ // melhor que o Date() do JS.
+
+ $("#date").append(moment().format("DD/MM/YY"));
+
+ })
+
+