Browse Source

Fix #2034 #2828 - Flexibilização de cronômetros (#2829)

* Fix #2828 - Adiciona tipo de cronômetro

* Corrige migrações

* Altera view do painel em Sessao

* Cronometros da tela de sessao funcionando

* Cronômetros na tela do painel funcionando

* Retira cronômetros do AppConfig

* Filtra apenas por cronometros ativos

* Adiciona requirements

* Melhoria no Form de Cronometro

* Adicionar link para o cronometro no Painel Eletronico e fix URL

* Muda nome do cronometro da ordem
pull/2761/head
Cesar Augusto de Carvalho 6 years ago
committed by Edward
parent
commit
ea4cd4623c
  1. 1
      requirements/requirements.txt
  2. 11
      sapl/base/forms.py
  3. 31
      sapl/base/migrations/0038_auto_20190604_1109.py
  4. 20
      sapl/base/models.py
  5. 5
      sapl/base/templatetags/common_tags.py
  6. 14
      sapl/painel/forms.py
  7. 48
      sapl/painel/migrations/0003_auto_20190603_1033.py
  8. 25
      sapl/painel/migrations/0004_auto_20190603_1033.py
  9. 26
      sapl/painel/models.py
  10. 6
      sapl/painel/urls.py
  11. 45
      sapl/painel/views.py
  12. 30
      sapl/sessao/views.py
  13. 4
      sapl/templates/base/layouts.yaml
  14. 6
      sapl/templates/menu_tabelas_auxiliares.yaml
  15. 465
      sapl/templates/painel/index.html
  16. 2
      sapl/templates/painel/layouts.yaml
  17. 444
      sapl/templates/sessao/painel.html

1
requirements/requirements.txt

@ -45,3 +45,4 @@ channels==2.1.7
git+git://github.com/interlegis/trml2pdf.git
git+git://github.com/interlegis/django-admin-bootstrapped
cryptography==2.7

11
sapl/base/forms.py

@ -1219,10 +1219,6 @@ class ConfiguracoesAppForm(ModelForm):
'texto_articulado_norma',
'proposicao_incorporacao_obrigatoria',
'protocolo_manual',
'cronometro_discurso',
'cronometro_aparte',
'cronometro_ordem',
'cronometro_consideracoes',
'mostrar_brasao_painel',
'receber_recibo_proposicao',
'assinatura_ata',
@ -1231,13 +1227,6 @@ class ConfiguracoesAppForm(ModelForm):
'tramitacao_materia',
'tramitacao_documento']
def __init__(self, *args, **kwargs):
super(ConfiguracoesAppForm, self).__init__(*args, **kwargs)
self.fields['cronometro_discurso'].widget.attrs['class'] = 'cronometro'
self.fields['cronometro_aparte'].widget.attrs['class'] = 'cronometro'
self.fields['cronometro_ordem'].widget.attrs['class'] = 'cronometro'
self.fields['cronometro_consideracoes'].widget.attrs['class'] = 'cronometro'
def clean_mostrar_brasao_painel(self):
mostrar_brasao_painel = self.cleaned_data.get(
'mostrar_brasao_painel', False)

31
sapl/base/migrations/0038_auto_20190604_1109.py

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-06-04 14:09
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('base', '0037_auto_20190527_0901'),
]
operations = [
migrations.RemoveField(
model_name='appconfig',
name='cronometro_aparte',
),
migrations.RemoveField(
model_name='appconfig',
name='cronometro_consideracoes',
),
migrations.RemoveField(
model_name='appconfig',
name='cronometro_discurso',
),
migrations.RemoveField(
model_name='appconfig',
name='cronometro_ordem',
),
]

20
sapl/base/models.py

@ -139,26 +139,6 @@ class AppConfig(models.Model):
verbose_name=_('Quem deve assina a ata'),
max_length=1, choices=ASSINATURA_ATA_CHOICES, default='T')
cronometro_discurso = models.DurationField(
verbose_name=_('Cronômetro do Discurso'),
blank=True,
null=True)
cronometro_aparte = models.DurationField(
verbose_name=_('Cronômetro do Aparte'),
blank=True,
null=True)
cronometro_ordem = models.DurationField(
verbose_name=_('Cronômetro da Ordem'),
blank=True,
null=True)
cronometro_consideracoes = models.DurationField(
verbose_name=_('Cronômetro de Considerações Finais'),
blank=True,
null=True)
mostrar_brasao_painel = models.BooleanField(
default=False,
verbose_name=_('Mostrar brasão da Casa no painel?'))

5
sapl/base/templatetags/common_tags.py

@ -241,6 +241,11 @@ def cronometro_to_seconds(value):
return AppConfig.attr('cronometro_' + value).seconds
@register.filter
def duration_to_seconds(cronometro_duration):
return cronometro_duration.seconds
@register.filter
def to_list_pk(object_list):
return [o.pk for o in object_list]

14
sapl/painel/forms.py

@ -0,0 +1,14 @@
from django import forms
from .models import Cronometro
class CronometroForm(forms.ModelForm):
class Meta:
model = Cronometro
fields = ['tipo', 'duracao_cronometro', 'ativo', 'ordenacao']
def __init__(self, *args, **kwargs):
super(CronometroForm, self).__init__(*args, **kwargs)
self.fields['duracao_cronometro'].widget.attrs['class'] = 'cronometro'
if not self.instance.ordenacao:
self.fields['ordenacao'].initial = Cronometro.objects.last().ordenacao + 1

48
sapl/painel/migrations/0003_auto_20190603_1033.py

@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-06-03 13:33
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('painel', '0002_auto_20180523_1430'),
]
operations = [
migrations.AlterModelOptions(
name='cronometro',
options={'ordering': ['ordenacao'], 'verbose_name': 'Cronômetro', 'verbose_name_plural': 'Cronômetros'},
),
migrations.RemoveField(
model_name='cronometro',
name='data_cronometro',
),
migrations.AddField(
model_name='cronometro',
name='ativo',
field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Ativo?'),
),
migrations.AddField(
model_name='cronometro',
name='duracao_cronometro',
field=models.DurationField(verbose_name='Duração do cronômetro'),
),
migrations.AddField(
model_name='cronometro',
name='ordenacao',
field=models.PositiveIntegerField(blank=True, null=True, verbose_name='Ordenação'),
),
migrations.AlterField(
model_name='cronometro',
name='status',
field=models.CharField(choices=[('I', 'Start'), ('R', 'Reset'), ('S', 'Stop'), ('C', 'Increment')], default='S', max_length=1, verbose_name='Status do cronômetro'),
),
migrations.AlterField(
model_name='cronometro',
name='tipo',
field=models.CharField(max_length=100, unique=True, verbose_name='Tipo Cronômetro'),
),
]

25
sapl/painel/migrations/0004_auto_20190603_1033.py

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-06-03 13:33
from __future__ import unicode_literals
from django.db import migrations
def create_default_cronometros(apps, schema_editor):
tipos_default = ['Cronômetro do Discurso', 'Cronômetro do Aparte',
'Cronômetro da Questão de Ordem', 'Cronômetro de Considerações Finais']
Cronometro = apps.get_model('painel', 'Cronometro')
for i,tipo in enumerate(tipos_default):
Cronometro.objects.get_or_create(tipo=tipo, duracao_cronometro='00:05:00', status='S', ativo=True, ordenacao=i+1)
class Migration(migrations.Migration):
dependencies = [
('painel', '0003_auto_20190603_1033'),
]
operations = [
migrations.RunPython(create_default_cronometros)
]

26
sapl/painel/models.py

@ -1,6 +1,7 @@
import reversion
from django.db import models
from django.utils.translation import ugettext_lazy as _
from sapl.utils import YES_NO_CHOICES
@reversion.register()
@ -34,6 +35,7 @@ class Cronometro(models.Model):
('I', 'Start'),
('R', 'Reset'),
('S', 'Stop'),
('C', 'Increment'),
)
status = models.CharField(
@ -41,7 +43,25 @@ class Cronometro(models.Model):
verbose_name=_('Status do cronômetro'),
choices=CRONOMETRO_STATUS,
default='S')
data_cronometro = models.DateField(verbose_name=_('Data do cronômetro'))
duracao_cronometro = models.DurationField(
verbose_name=_('Duração do cronômetro'))
tipo = models.CharField(
max_length=1, choices=CRONOMETRO_TYPES,
verbose_name=_('Tipo Cronômetro'))
max_length=100,
verbose_name=_('Tipo Cronômetro'),
unique=True)
ativo = models.BooleanField(
default=False,
choices=YES_NO_CHOICES,
verbose_name=_('Ativo?'))
ordenacao = models.PositiveIntegerField(
blank=True,
null=True,
verbose_name=_("Ordenação"))
class Meta:
verbose_name = _('Cronômetro')
verbose_name_plural = _('Cronômetros')
ordering = ['ordenacao']
def __str__(self):
return self.tipo

6
sapl/painel/urls.py

@ -1,9 +1,9 @@
from django.conf.urls import url
from django.conf.urls import url, include
from .apps import AppConfig
from .views import (cronometro_painel, get_dados_painel, painel_mensagem_view,
painel_parlamentar_view, painel_view, painel_votacao_view,
switch_painel, verifica_painel, votante_view)
switch_painel, verifica_painel, votante_view, CronometroPainelCrud)
app_name = AppConfig.name
@ -20,7 +20,7 @@ urlpatterns = [
url(r'^painel/verifica-painel$', verifica_painel,
name="verifica_painel"),
url(r'^painel/cronometro$', cronometro_painel, name='cronometro_painel'),
# url(r'^painel/cronometro$', include(CronometroPainelCrud.get_urls())),
url(r'^sistema/cronometro/', include(CronometroPainelCrud.get_urls())),
url(r'^voto-individual/$', votante_view,
name='voto_individual'),

45
sapl/painel/views.py

@ -15,7 +15,7 @@ from django.utils.translation import ugettext_lazy as _
from sapl.base.models import AppConfig as ConfiguracoesAplicacao
from sapl.base.models import CasaLegislativa
from sapl.crud.base import Crud
from sapl.crud.base import Crud, CrudAux
from sapl.painel.apps import AppConfig
from sapl.parlamentares.models import Legislatura, Parlamentar, Votante
from sapl.sessao.models import (ExpedienteMateria, OradorExpediente, OrdemDia,
@ -24,11 +24,17 @@ from sapl.sessao.models import (ExpedienteMateria, OradorExpediente, OrdemDia,
VotoParlamentar)
from sapl.utils import filiacao_data, get_client_ip, sort_lista_chave
from .forms import CronometroForm
from .models import Cronometro
VOTACAO_NOMINAL = 2
CronometroPainelCrud = Crud.build(Cronometro, '')
class CronometroPainelCrud(CrudAux):
model = Cronometro
class BaseMixin(CrudAux.BaseMixin):
form_class = CronometroForm
# FIXME mudar lógica
@ -290,7 +296,10 @@ def votante_view(request):
@user_passes_test(check_permission)
def painel_view(request, pk):
context = {'head_title': str(_('Painel Plenário')), 'sessao_id': pk}
context = {'head_title': str(_('Painel Plenário')),
'sessao_id': pk,
'cronometros': Cronometro.objects.filter(ativo=True).order_by('ordenacao')
}
return render(request, 'painel/index.html', context)
@ -331,9 +340,20 @@ def painel_votacao_view(request):
return render(request, 'painel/votacao.html')
CRONOMETRO_STATUS = {
'start': 'I',
'reset': 'R',
'stop': 'S',
'increment': 'C'
}
@user_passes_test(check_permission)
def cronometro_painel(request):
request.session[request.GET['tipo']] = request.GET['action']
acao = request.GET['action']
cronometro_id = request.GET['tipo'].split('cronometro_')[1]
cronometro = Cronometro.objects.get(id=cronometro_id)
cronometro.status = CRONOMETRO_STATUS[acao]
cronometro.save()
return HttpResponse({})
@ -523,15 +543,24 @@ def get_dados_painel(request, pk):
if casa and app_config and (bool(casa.logotipo)):
brasao = casa.logotipo.url \
if app_config.mostrar_brasao_painel else None
CRONOMETRO_STATUS = {
'I': 'start',
'R': 'reset',
'S': 'stop',
'C': 'increment'
}
dict_status_cronometros = dict(Cronometro.objects.filter(ativo=True).order_by('ordenacao').values_list('id', 'status'))
for key, value in dict_status_cronometros.items():
dict_status_cronometros[key] = CRONOMETRO_STATUS[dict_status_cronometros[key]]
response = {
'sessao_plenaria': str(sessao),
'sessao_plenaria_data': sessao.data_inicio.strftime('%d/%m/%Y'),
'sessao_plenaria_hora_inicio': sessao.hora_inicio,
'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'),
'cronometros': dict_status_cronometros,
'status_painel': sessao.painel_aberto,
'brasao': brasao
}

30
sapl/sessao/views.py

@ -31,6 +31,7 @@ from sapl.materia.forms import filtra_tramitacao_status
from sapl.materia.models import (Autoria, TipoMateriaLegislativa,
Tramitacao)
from sapl.materia.views import MateriaLegislativaPesquisaView
from sapl.painel.models import Cronometro
from sapl.parlamentares.models import (Filiacao, Legislatura, Mandato,
Parlamentar, SessaoLegislativa)
from sapl.sessao.apps import AppConfig
@ -890,22 +891,18 @@ class PainelView(PermissionRequiredForAppCrudMixin, TemplateView):
if request.user.is_anonymous():
self.template_name = 'painel/index.html'
request.session['discurso'] = 'stop'
request.session['aparte'] = 'stop'
request.session['ordem'] = 'stop'
request.session['consideracoes'] = 'stop'
cronometros = Cronometro.objects.filter(ativo=True).order_by('ordenacao')
for cronometro in cronometros:
cronometro.status = 'S' # Stop
cronometro.save()
return TemplateView.get(self, request, *args, **kwargs)
def get_context_data(self, **kwargs):
cronometro_discurso = AppsAppConfig.attr('cronometro_discurso')
cronometro_aparte = AppsAppConfig.attr('cronometro_aparte')
cronometro_ordem = AppsAppConfig.attr('cronometro_ordem')
cronometro_consideracoes = AppsAppConfig.attr(
'cronometro_consideracoes')
if (not cronometro_discurso or not cronometro_aparte
or not cronometro_ordem or not cronometro_consideracoes):
cronometros = Cronometro.objects.filter(ativo=True).order_by('ordenacao')
if not cronometros:
username = self.request.user.username
self.logger.error('user=' + username + '. Você precisa primeiro configurar os cronômetros'
@ -915,22 +912,13 @@ class PainelView(PermissionRequiredForAppCrudMixin, TemplateView):
nas Configurações da Aplicação')
messages.add_message(self.request, messages.ERROR, msg)
else:
cronometro_discurso = cronometro_discurso.seconds
cronometro_aparte = cronometro_aparte.seconds
cronometro_ordem = cronometro_ordem.seconds
cronometro_consideracoes = cronometro_consideracoes.seconds
context = TemplateView.get_context_data(self, **kwargs)
context.update({
'head_title': str(_('Painel Plenário')),
'sessao_id': kwargs['pk'],
'root_pk': kwargs['pk'],
'sessaoplenaria': SessaoPlenaria.objects.get(pk=kwargs['pk']),
'cronometro_discurso': cronometro_discurso,
'cronometro_aparte': cronometro_aparte,
'cronometro_ordem': cronometro_ordem,
'cronometro_consideracoes': cronometro_consideracoes})
'cronometros': cronometros})
return context

4
sapl/templates/base/layouts.yaml

@ -34,10 +34,6 @@ AppConfig:
{% trans 'Assinaturas' %}:
- assinatura_ata
{% trans 'Cronômetros do Painel' %}:
- cronometro_discurso cronometro_aparte
- cronometro_ordem cronometro_consideracoes
{% trans 'Configurações do Painel' %}:
- mostrar_brasao_painel

6
sapl/templates/menu_tabelas_auxiliares.yaml

@ -167,6 +167,12 @@
- title: {% trans 'Tipo de Justificativa' %}
url: sapl.sessao:tipojustificativa_list
css_class: btn btn-link
- title: {% trans 'Módulo Painel' %}
css_class: head_title
children:
- title: {% trans 'Cronômetro' %}
url: sapl.painel:cronometro_list
css_class: btn btn-link
- title: {% trans 'Módulo LexML' %}
css_class: head_title
children:

465
sapl/templates/painel/index.html

@ -21,7 +21,6 @@
{% render_bundle 'painel' 'css' %}
{% endblock webpack_loader_css %}
<style type="text/css">
html, body {
max-width: 100%;
@ -33,79 +32,75 @@
}
}
</style>
</head>
<body class="painel-principal">
<audio type="hidden" id="audio" src="{% webpack_static 'audio/ring.mp3' %}"></audio>
<div class="d-flex justify-content-center">
<h1 id="sessao_plenaria" class="title text-title"></h1>
</div>
<div class="row ">
<div class="col text-center">
<span id="sessao_plenaria_data" class="text-value"></span>
</div>
<div class="col text-center">
<span id="sessao_plenaria_hora_inicio" class="text-value"></span>
</div>
</div>
<div class="row justify-content-center">
<div class="col-1">
<img src="" id="logo-painel" class="logo-painel" alt=""/>
</div>
</div>
<div class="row justify-content-center">
<h2 class="text-danger"><span id="message"></span></h2>
<audio type="hidden" id="audio" src="{% webpack_static 'audio/ring.mp3' %}"></audio>
<div class="d-flex justify-content-center">
<h1 id="sessao_plenaria" class="title text-title"></h1>
</div>
<div class="row ">
<div class="col text-center">
<span id="sessao_plenaria_data" class="text-value"></span>
</div>
<div class="col text-center">
<span id="sessao_plenaria_hora_inicio" class="text-value"></span>
</div>
</div>
<div class="row">
<div class="col text-center"><span class="text-value data-hora" id="date"></span></div>
<div class="col text-center"><span class="text-value data-hora" id="relogio"></span></div>
<div class="row justify-content-center">
<div class="col-1">
<img src="" id="logo-painel" class="logo-painel" alt=""/>
</div>
<div class="">
<div class="d-flex justify-content-start">
<div class="col-md-4">
<div class="text-center painel">
<h2 class="text-subtitle">Parlamentares</h2>
<span id="parlamentares" class="text-value text-center"></span>
</div>
</div>
<div class="row justify-content-center">
<h2 class="text-danger"><span id="message"></span></h2>
</div>
<div class="row">
<div class="col text-center"><span class="text-value data-hora" id="date"></span></div>
<div class="col text-center"><span class="text-value data-hora" id="relogio"></span></div>
</div>
<div class="">
<div class="d-flex justify-content-start">
<div class="col-md-4">
<div class="text-center painel">
<h2 class="text-subtitle">Parlamentares</h2>
<span id="parlamentares" class="text-value text-center"></span>
</div>
</div>
<div class="d-flex col-md-8 painels">
<div class="col-md-6 text-center painel" id="aparecer_oradores">
<h2 class="text-subtitle">Oradores</h2>
<span id="orador" class="text-value" align="center"></span>
</div>
<div class="d-flex col-md-8 painels">
<div class="col-md-6 text-center painel" id="aparecer_oradores">
<h2 class="text-subtitle">Oradores</h2>
<span id="orador"></span>
</div>
<div class="col-md-6 text-center painel">
<h2 class="text-subtitle">Cronômetros</h2>
<div class="text-value">
Discurso: <span id="cronometro_discurso"></span><br>
Aparte: <span id="cronometro_aparte"></span><br>
Questão de Ordem: <span id="cronometro_ordem"></span><br>
Considerações Finais: <span id="cronometro_consideracoes"></span>
</div>
<div class="col-md-6 text-center painel">
<h2 class="text-subtitle">{% if cronometros|length == 1 %}Cronômetro{% elif cronometros|length > 1%}Cronômetros{% endif %}</h2>
<div class="text-value">
{% for cronometro in cronometros %}
{{cronometro}}: <span id="cronometro_{{cronometro.id}}"></span><br>
{% endfor %}
</div>
</div>
<div class="col-md-6 text-center painel">
<h2 class="text-subtitle">Resultado</h2>
<span id="votacao" class="text-value"></span>
<h2><span id="resultado_votacao" lass="text-title"></span>
</div>
<div class="col-md-6 text-center painel">
<h2 class="text-subtitle">Resultado</h2>
<span id="votacao" class="text-value"></span>
<h2><span id="resultado_votacao" lass="text-title"></span>
</div>
<div class="col-md-6 text-center painel">
<h2 class="text-subtitle">Matéria em Votação</h2>
<span id="materia_legislativa_texto" class="text-value"></span>
<span id="observacao_materia" class="text-value"></span>
</div>
<div class="col-md-6 text-center painel">
<h2 class="text-subtitle">Matéria em Votação</h2>
<span id="materia_legislativa_texto" class="text-value"></span>
<span id="observacao_materia" class="text-value"></span>
</div>
</div>
</div>
</div>
</div>
</body>
{% block webpack_loader_js %}
@ -122,89 +117,47 @@
var n = d.toLocaleDateString();
document.getElementById("date").innerHTML = n;
$(document).ready(function() {
//TODO: replace by a fancy jQuery clock
function checkTime(i) {
if (i<10) {i = "0" + i}; // add zero in front of numbers < 10
return i;
}
function startTime() {
var today=new Date();
var h=today.getHours();
var m=today.getMinutes();
var s=today.getSeconds();
m = checkTime(m);
s = checkTime(s);
$("#relogio").text(h+":"+m+":"+s)
var t = setTimeout(function(){
startTime()
}, 500);
}
startTime();
var audioAlertFinish = document.getElementById("audio");
$('#cronometro_discurso').runner({
autostart: false,
countdown: true,
startAt: {{ 'discurso'|cronometro_to_seconds }} * 1000,
stopAt: 0,
milliseconds: false,
format: function(value) {
let h = Math.floor((value/1000) / 3600);
h = checkTime(h);
let m = Math.floor((value/1000) % 3600 / 60);
m = checkTime(m);
let s = Math.floor((value/1000) % 3600 % 60);
s = checkTime(s);
return h.toString() + ":" + m.toString() + ":" + s.toString();
}
}).on('runnerFinish', function(eventObject, info){
audioAlertFinish.play();
});
function checkTime(i) {
if (i<10) {i = "0" + i}; // add zero in front of numbers < 10
return i;
}
function startTime() {
var today=new Date();
var h=today.getHours();
var m=today.getMinutes();
var s=today.getSeconds();
m = checkTime(m);
s = checkTime(s);
$("#relogio").text(h+":"+m+":"+s)
var t = setTimeout(function(){
startTime()
}, 500);
}
function show_voto(voto) {
if (voto == "Sim"){
return '<font color="green"> Sim </font>'
}
else if (voto == "Não"){
return '<font color="red"> Não </font>'
}
return voto
}
$('#cronometro_aparte').runner({
autostart: false,
countdown: true,
startAt: {{ 'aparte'|cronometro_to_seconds }} * 1000,
stopAt: 0,
milliseconds: false,
format: function(value) {
let h = Math.floor((value/1000) / 3600);
h = checkTime(h);
let m = Math.floor((value/1000) % 3600 / 60);
m = checkTime(m);
let s = Math.floor((value/1000) % 3600 % 60);
s = checkTime(s);
return h.toString() + ":" + m.toString() + ":" + s.toString();
}
}).on('runnerFinish', function(eventObject, info){
audioAlertFinish.play();
});
$(document).ready(function() {
//TODO: replace by a fancy jQuery clock
startTime();
$('#cronometro_ordem').runner({
autostart: false,
countdown: true,
startAt: {{ 'ordem'|cronometro_to_seconds }} * 1000,
stopAt: 0,
milliseconds: false,
format: function(value) {
let h = Math.floor((value/1000) / 3600);
h = checkTime(h);
let m = Math.floor((value/1000) % 3600 / 60);
m = checkTime(m);
let s = Math.floor((value/1000) % 3600 % 60);
s = checkTime(s);
return h.toString() + ":" + m.toString() + ":" + s.toString();
}
}).on('runnerFinish', function(eventObject, info){
audioAlertFinish.play();
});
var audioAlertFinish = document.getElementById("audio");
$('#cronometro_consideracoes').runner({
var cronometros_previous = [];
{% for cron in cronometros %}
cronometros_previous.push(0);
$('#cronometro_' + "{{cron.id}}").runner({
autostart: false,
countdown: true,
startAt: {{ 'consideracoes'|cronometro_to_seconds }} * 1000,
startAt: {{cron.duracao_cronometro|duration_to_seconds}} * 1000,
stopAt: 0,
milliseconds: false,
format: function(value) {
@ -218,15 +171,11 @@
}
}).on('runnerFinish', function(eventObject, info){
audioAlertFinish.play();
});
var discurso_previous;
var ordem_previous;
var aparte_previous;
var consideracoes_previous;
})
{% endfor %}
var counter = 1;
(function poll() {
var counter = 1;
(function poll() {
$.ajax({
url: "{% url 'sapl.painel:dados_painel' sessao_id %}",
type: "GET",
@ -236,8 +185,7 @@
$("#sessao_plenaria_hora_inicio").text("Hora Início: " + data["sessao_plenaria_hora_inicio"])
if (data["status_painel"] == false) {
$("#message").text("PAINEL ENCONTRA-SE FECHADO");
}
else {
} else {
$("#message").text("");
}
@ -256,56 +204,52 @@
var presentes_list = data["presentes"];
if (data["status_painel"] == true) {
presentes.append('<table id="parlamentares_list">');
$.each(presentes_list, function (index, parlamentar) {
if (parlamentar.voto == 'Voto Informado'){
$('#parlamentares_list').append('<tr><td style="padding-right:20px; color:yellow" >' +
parlamentar.nome +
'</td> <td style="padding-right:20px; color:yellow">' +
parlamentar.partido + '</td> <td style="padding-right:20px; color:yellow">'
+ '</td></tr>')
}
else{
$('#parlamentares_list').append('<tr> <td style="padding-right:20px">' +
parlamentar.nome +
'</td> <td style="padding-right:20px">' +
parlamentar.partido + '</td> <td style="padding-right:20px">'
+ show_voto(parlamentar.voto) + '</td></tr>')
}
presentes.append('<table id="parlamentares_list">');
$.each(presentes_list, function (index, parlamentar) {
if (parlamentar.voto == 'Voto Informado'){
$('#parlamentares_list').append('<tr><td style="padding-right:20px; color:yellow" >' +
parlamentar.nome +
'</td> <td style="padding-right:20px; color:yellow">' +
parlamentar.partido + '</td> <td style="padding-right:20px; color:yellow">'
+ '</td></tr>')
} else{
$('#parlamentares_list').append('<tr> <td style="padding-right:20px">' +
parlamentar.nome +
'</td> <td style="padding-right:20px">' +
parlamentar.partido + '</td> <td style="padding-right:20px">'
+ show_voto(parlamentar.voto) + '</td></tr>')
}
});
presentes.append('</table>')
if (data["oradores"].length > 0){
$('#aparecer_oradores').show();
oradores.append('<table id="oradores_list">');
$.each(oradores_list, function (index, orador) {
$('#oradores_list').append('<tr><td style="padding-right:20px; color:white" >' +
orador.numero + 'º &nbsp' +
orador.nome +'</td></tr>')
});
presentes.append('</table>')
if (data["oradores"].length > 0){
$('#aparecer_oradores').show();
oradores.append('<table id="oradores_list">');
$.each(oradores_list, function (index, orador) {
$('#oradores_list').append('<tr><td style="padding-right:20px; color:white" >' +
orador.numero + 'º &nbsp' +
orador.nome +'</td></tr>')
});
oradores.append('</table>');
}
else {
$('#aparecer_oradores').hide();
}
}
else{
presentes.append('<span id="parlamentares_list">');
$('#parlamentares_list').append(
'<center>A listagem de parlamentares só aparecerá quando o painel estiver aberto.</center>')
presentes.append('</span>');
oradores.append('<span id="oradores_list">');
$('#oradores_list').append(
'<center>A listagem de oradores só aparecerá quando o painel estiver aberto.</center>')
oradores.append('</span>');
votacao.append('<span id="votacao">');
$("#votacao").append('<center>A votação só aparecerá quando o painel estiver aberto</center>');
votacao.append('</span>');
oradores.append('</table>');
} else {
$('#aparecer_oradores').hide();
}
} else{
presentes.append('<span id="parlamentares_list">');
$('#parlamentares_list').append(
'<center>A listagem de parlamentares só aparecerá quando o painel estiver aberto.</center>')
presentes.append('</span>');
oradores.append('<span id="oradores_list">');
$('#oradores_list').append(
'<center>A listagem de oradores só aparecerá quando o painel estiver aberto.</center>')
oradores.append('</span>');
votacao.append('<span id="votacao">');
$("#votacao").append('<center>A votação só aparecerá quando o painel estiver aberto</center>');
votacao.append('</span>');
}
if (data['materia_legislativa_texto'] && data["status_painel"] == true){
@ -319,77 +263,39 @@
votacao.append("<li>Abstenções: " + data["numero_abstencoes"] + "</li>")
votacao.append("<li>Presentes: " + num_presentes + "</li>")
votacao.append("<li>Total votos: " + data["total_votos"] + "</li>")
}
else{
} else{
$("#votacao").append('<center>Não há votação, pois não há nenhuma matéria aberta ou já votada.</center>');
};
var ids = [];
var status_cronometros = []
for (var key in data['cronometros']) {
if (data['cronometros'].hasOwnProperty(key)) {
ids.push(key);
status_cronometros.push(data['cronometros'][key])
}
}
var discurso_current = data["cronometro_discurso"];
if (!discurso_previous){
discurso_previous = ''
}
if (discurso_current != discurso_previous) {
$('#cronometro_discurso').runner(discurso_current);
discurso_previous = discurso_current;
}
var aparte_current = data["cronometro_aparte"];
if (!aparte_previous){
aparte_previous = ''
}
if (aparte_current != aparte_previous) {
$('#cronometro_aparte').runner(aparte_current);
aparte_previous = aparte_current;
}
var ordem_current = data["cronometro_ordem"];
if (!ordem_previous){
ordem_previous = ''
}
if (ordem_current != ordem_previous) {
$('#cronometro_ordem').runner(ordem_current);
ordem_previous = ordem_current;
}
var consideracoes_current = data["cronometro_consideracoes"];
if (!consideracoes_previous){
consideracoes_previous = ''
}
if (consideracoes_current != consideracoes_previous) {
$('#cronometro_consideracoes').runner(consideracoes_current);
consideracoes_previous = consideracoes_current;
}
if($('#cronometro_discurso').runner('info').formattedTime == "00:00:30") {
audioAlertFinish.play();
}
if($('#cronometro_aparte').runner('info').formattedTime == "00:00:30") {
audioAlertFinish.play();
}
if($('#cronometro_ordem').runner('info').formattedTime == "00:00:30") {
audioAlertFinish.play();
}
for(let i=0; i<status_cronometros.length; i++){
if (!cronometros_previous[i])
cronometros_previous[i] = ''
if (status_cronometros[i] != cronometros_previous[i]) {
$('#cronometro_' + ids[i]).runner(status_cronometros[i]);
cronometros_previous[i] = status_cronometros[i];
}
if($('#cronometro_consideracoes').runner('info').formattedTime == "00:00:30") {
if($('#cronometro_' + ids[i]).runner('info').formattedTime == 30)
audioAlertFinish.play();
}
if (data['materia_legislativa_texto']){
if (data["status_painel"] == true){
$("#materia_legislativa_texto").text(data["materia_legislativa_texto"]);
}
else{
} else{
$("#materia_legislativa_texto").text('A Matéria em votação só aparecerá quando o painel estiver aberto');
}
}
else{
} else{
$("#materia_legislativa_texto").text('Não há nehuma matéria votada ou para votação');
}
@ -397,12 +303,10 @@
var texto = data['observacao_materia'];
if(texto.length > 151) {
$("#observacao_materia").text(texto.substr(0, 145).concat('(...)'));
}
else{
} else{
$("#observacao_materia").text(texto);
}
}
else{
} else{
$("#observacao_materia").text('');
}
@ -410,36 +314,25 @@
$("#resultado_votacao").text(data["tipo_resultado"]);
$("#resultado_votacao").css("color", "#45919D");
var resultado_votacao_upper = $("#resultado_votacao").text().toUpperCase();
if (resultado_votacao_upper.search("APROV") != -1){
$("#resultado_votacao").css("color", "green");
}
if (resultado_votacao_upper.search("REJEIT") != -1){
$("#resultado_votacao").css("color", "red");
}
}
else{
if (resultado_votacao_upper.search("APROV") != -1){
$("#resultado_votacao").css("color", "green");
}
if (resultado_votacao_upper.search("REJEIT") != -1){
$("#resultado_votacao").css("color", "red");
}
} else{
$("#resultado_votacao").text('');
}
},
error: function(err) {
console.error(err);
},
dataType: "json",
complete: setTimeout(function() {poll()}, 500),
timeout: 20000 // TODO: decrease
},
error: function(err) {
console.error(err);
},
dataType: "json",
complete: setTimeout(function() {poll()}, 500),
timeout: 20000 // TODO: decrease
})
})();
});
function show_voto(voto) {
if (voto == "Sim"){
return '<font color="green"> Sim </font>'
}
else if (voto == "Não"){
return '<font color="red"> Não </font>'
}
return voto
}
});
</script>
</html>

2
sapl/templates/painel/layouts.yaml

@ -1,4 +1,4 @@
{% load i18n %}
Cronometro:
{% trans 'Cronometro' %}:
- status:3 data_cronometro:6 tipo
- tipo:4 duracao_cronometro:4 ativo:2 ordenacao:2

444
sapl/templates/sessao/painel.html

@ -1,7 +1,11 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% load common_tags %}
{% load staticfiles %}
{% load webpack_static from webpack_loader %}
{% load render_bundle from webpack_loader %}
{% block actions %} {% endblock %}
{% block title %}
@ -25,361 +29,145 @@
<h1>Operação do Painel Eletrônico</h1>
<h2><span id="relogio"></span></h2>
<br />
<div class="row">
<div class="col-md-12 mb-2"><h3>Cronômetro do Discurso</h3></div>
</div>
<div class="row">
<div class="col-md-2"><input size="2" id="discurso" name="discurso" value="" readyonly="true" class="form-control"></div>
</div>
<br />
{% for cronometro in cronometros %}
<div class="row">
<div class="col-md-6"><button type="button" id="discursoStart" class="btn btn-success">Iniciar</button></div>
<div class="col-md-6"><button type="button" id="discursoReset" class="btn btn-success">Reiniciar</button></div>
</div>
<div class="row">
<div class="col-md-12 mb-2"><h3><a href="{% url 'sapl.painel:cronometro_detail' cronometro.id %}">{{cronometro}}</a></h3></div>
</div>
<br /><br >
<div class="row">
<div class="col-md-12 mb-2"><h3>Cronômetro do Aparte</h3></div>
</div>
<div class="row">
<div class="col-md-2"><input size="2" id="cronometro_{{cronometro.id}}" name="cronometro_{{cronometro.id}}" value="" readyonly="true" class="form-control"></div>
</div>
<br />
<div class="row">
<div class="col-md-2"><input size="2" id="aparte" name="aparte" value="" readyonly="true" class="form-control"></div>
</div>
<br />
<div class="row">
<div class="col-md-6"><button type="button" id="cronometro_{{cronometro.id}}_Start" class="btn btn-success">Iniciar</button></div>
<div class="col-md-6"><button type="button" id="cronometro_{{cronometro.id}}_Reset" class="btn btn-success">Reiniciar</button></div>
</div>
<div class="row">
<div class="col-md-6"><button type="button" id="aparteStart" class="btn btn-success">Iniciar</button></div>
<div class="col-md-6"><button type="button" id="aparteReset" class="btn btn-success" class="btn btn-success">Reiniciar</button></div>
</div>
<br /><br >
<div class="row">
<div class="col-md-12 mb-2"><h3>Cronômetro da Questão de Ordem </h3></div>
</div>
<div class="row">
<div class="col-md-2"><input size="2" id="ordem" name="ordem" value="" readyonly="true" class="form-control"></div>
</div>
<br />
<div class="row">
<div class="col-md-6"><button type="button" id="ordemStart" class="btn btn-success">Iniciar</button></div>
<div class="col-md-6"><button type="button" id="ordemReset" class="btn btn-success">Reiniciar</button></div>
</div>
<br/>
<br/>
<div class="row">
<div class="col-md-12 mb-2"><h3>Cronômetro de Considerações Finais</h3></div>
</div>
<div class="row">
<div class="col-md-4"><input size="2" id="consideracoes" name="consideracoes" value="" readyonly="true" class="form-control"></div>
</div>
<br />
<div class="row">
<div class="col-md-6"><button type="button" id="consideracoesStart" class="btn btn-success">Iniciar</button></div>
<div class="col-md-6"><button type="button" id="consideracoesReset" class="btn btn-success">Reiniciar</button></div>
</div>
<br /><br >
<br><br>
{% endfor %}
<div class="row">
<div class="col-md-6"><button type="button" id="sinalSonoro" class="btn btn-success" onclick="document.getElementById('audio').play();">Sinal Sonoro</button></div>
</div>
<br><br>
{% endblock detail_content %}
{% block extra_js %}
<script language="JavaScript">
$(function() {
function checkTime(i) {
if (i<10) {i = "0" + i};
return i;
}
function startTime() {
var today=new Date();
var h=today.getHours();
var m=today.getMinutes();
var s=today.getSeconds();
m = checkTime(m);
s = checkTime(s);
$("#relogio").text(h+":"+m+":"+s)
var t = setTimeout(function(){
startTime()
},500);
}
startTime();
var audioAlertFinish = document.getElementById("audio");
$('#discurso').prop('disabled', false);
$('#aparte').prop('disabled', false);
$('#ordem').prop('disabled', false);
$('#consideracoes').prop('disabled', false);
$('#discurso').runner({
autostart: false,
countdown: true,
startAt: {{cronometro_discurso}} * 1000,
stopAt: 0,
milliseconds: false,
format: function(value) {
let h = Math.floor((value/1000) / 3600);
h = checkTime(h);
let m = Math.floor((value/1000) % 3600 / 60);
m = checkTime(m);
let s = Math.floor((value/1000) % 3600 % 60);
s = checkTime(s);
return h.toString() + ":" + m.toString() + ":" + s.toString();
}
}).on('runnerFinish', function(eventObject, info){
$.get('/painel/cronometro', { tipo: 'discurso', action: 'stop' } );
audioAlertFinish.play();
$('#discursoReset').show();
$('#discurso').runner('stop');
$('#discursoStart').text('Iniciar');
});
$('#discursoStart').click(function() {
if ($('#discursoStart').text() == 'Iniciar'){
$.get('/painel/cronometro', { tipo: 'discurso', action: 'start' } );
$('#discursoReset').hide();
$('#discurso').runner('start');
$('#discursoStart').text('Parar');
} else {
$.get('/painel/cronometro', { tipo: 'discurso', action: 'stop' } );
$('#discursoReset').show();
$('#discurso').runner('stop');
$('#discursoStart').text('Iniciar');
}
});
$('#discursoReset').click(function() {
$.get('/painel/cronometro', { tipo: 'discurso', action: 'reset' } );
$('#discurso').runner('stop');
$('#discurso').runner('reset');
});
$('#aparte').runner({
autostart: false,
countdown: true,
startAt: {{cronometro_aparte}} * 1000,
stopAt: 0,
milliseconds: false,
format: function(value) {
let h = Math.floor((value/1000) / 3600);
h = checkTime(h);
let m = Math.floor((value/1000) % 3600 / 60);
m = checkTime(m);
let s = Math.floor((value/1000) % 3600 % 60);
s = checkTime(s);
return h.toString() + ":" + m.toString() + ":" + s.toString();
}
}).on('runnerFinish', function(eventObject, info){
$.get('/painel/cronometro', { tipo: 'aparte', action: 'stop' } );
audioAlertFinish.play();
$('#aparteReset').show();
$('#aparte').runner('stop');
$('#aparteStart').text('Iniciar');
});
$('#aparteStart').click(function(){
if ($('#aparteStart').text() == 'Iniciar') {
$.get('/painel/cronometro', { tipo: 'aparte', action: 'start' } );
$('#aparteReset').hide();
$('#aparte').runner('start');
$('#aparteStart').text('Parar');
} else {
$.get('/painel/cronometro', { tipo: 'aparte', action: 'stop' } );
$('#aparteReset').show();
$('#aparte').runner('stop');
$('#aparteStart').text('Iniciar');
}
});
$('#aparteReset').click(function() {
$.get('/painel/cronometro', { tipo: 'aparte', action: 'reset' } );
$('#aparte').runner('stop');
$('#aparte').runner('reset');
});
$('#ordem').runner({
autostart: false,
countdown: true,
startAt: {{cronometro_ordem}} * 1000,
stopAt: 0,
milliseconds: false,
format: function(value) {
let h = Math.floor((value/1000) / 3600);
h = checkTime(h);
let m = Math.floor((value/1000) % 3600 / 60);
m = checkTime(m);
let s = Math.floor((value/1000) % 3600 % 60);
s = checkTime(s);
return h.toString() + ":" + m.toString() + ":" + s.toString();
}
}).on('runnerFinish', function(eventObject, info){
$.get('/painel/cronometro', { tipo: 'ordem', action: 'stop' } );
audioAlertFinish.play();
$('#ordemReset').show();
$('#ordem').runner('stop');
$('#ordemStart').text('Iniciar');
});
$('#ordemStart').click(function() {
if ($('#ordemStart').text() == 'Iniciar') {
$.get('/painel/cronometro', { tipo: 'ordem', action: 'start' } );
$('#ordemReset').hide();
$('#ordem').runner('start');
$('#ordemStart').text('Parar');
} else {
$.get('/painel/cronometro', { tipo: 'ordem', action: 'stop' } );
$('#ordemReset').show();
$('#ordem').runner('stop');
$('#ordemStart').text('Iniciar');
}
});
$('#ordemReset').click(function() {
$.get('/painel/cronometro', { tipo: 'ordem', action: 'reset' } );
$('#ordem').runner('stop');
$('#ordem').runner('reset');
});
$('#consideracoes').runner({
autostart: false,
countdown: true,
startAt: {{cronometro_consideracoes}} * 1000,
stopAt: 0,
milliseconds: false,
format: function(value) {
let h = Math.floor((value/1000) / 3600);
h = checkTime(h);
let m = Math.floor((value/1000) % 3600 / 60);
m = checkTime(m);
let s = Math.floor((value/1000) % 3600 % 60);
s = checkTime(s);
return h.toString() + ":" + m.toString() + ":" + s.toString();
}
}).on('runnerFinish', function(eventObject, info){
$.get('/painel/cronometro', { tipo: 'consideracoes', action: 'stop' } );
audioAlertFinish.play();
$('#consideracoesReset').show();
$('#consideracoes').runner('stop');
$('#consideracoesStart').text('Iniciar');
});
$('#consideracoesStart').click(function(){
if ($('#consideracoesStart').text() == 'Iniciar') {
function switch_painel(aberto) {
let pk_sessao = {{root_pk}};
let botao_abrir = $('#id_abrir_painel');
let botao_fechar = $('#id_fechar_painel');
$.ajax({
data: {pk_sessao: pk_sessao, aberto: aberto},
type: 'POST',
url: "{% url 'sapl.painel:switch_painel' %}",
headers: {'X-CSRFToken': getCookie('csrftoken')},
});
if (aberto) {
botao_abrir.hide();
botao_fechar.show();
} else {
botao_abrir.show();
botao_fechar.hide();
}
}
$.get('/painel/cronometro', { tipo: 'consideracoes', action: 'start' } );
function checkTime(i) {
if (i<10) {
i = "0" + i
};
return i;
}
$('#consideracoesReset').hide();
$('#consideracoes').runner('start');
$('#consideracoesStart').text('Parar');
function startTime() {
let today=new Date();
let h=today.getHours();
let m=today.getMinutes();
let s=today.getSeconds();
m = checkTime(m);
s = checkTime(s);
$("#relogio").text(h+":"+m+":"+s)
let t = setTimeout(function(){
startTime()
},500);
}
$(document).ready(function(){
let pk_sessao = {{root_pk}};
let botao_abrir = $('#id_abrir_painel');
let botao_fechar = $('#id_fechar_painel');
$.ajax({
data: {pk_sessao: pk_sessao},
type: 'GET',
dataType: 'json',
url: "{% url 'sapl.painel:verifica_painel' %}",
error: function () {
alert("Erro ao verificar o Painel");
},
success: function (data) {
if (data['status']) {
botao_abrir.hide();
botao_fechar.show();
} else {
$.get('/painel/cronometro', { tipo: 'consideracoes', action: 'stop' } );
$('#consideracoesReset').show();
$('#consideracoes').runner('stop');
$('#consideracoesStart').text('Iniciar');
botao_abrir.show();
botao_fechar.hide();
}
});
$('#consideracoesReset').click(function() {
$.get('/painel/cronometro', { tipo: 'consideracoes', action: 'reset' } );
$('#consideracoes').runner('stop');
$('#consideracoes').runner('reset');
});
});
},
});
function switch_painel(aberto) {
var pk_sessao = {{root_pk}};
var botao_abrir = $('#id_abrir_painel');
var botao_fechar = $('#id_fechar_painel');
startTime();
let audioAlertFinish = document.getElementById("audio");
{% for cron in cronometros %}
$('#cronometro_' + "{{cron.id}}").prop('disabled', false);
$.ajax({
data: {pk_sessao: pk_sessao, aberto: aberto},
type: 'POST',
url: "{% url 'sapl.painel:switch_painel' %}",
headers: {'X-CSRFToken': getCookie('csrftoken')},
$('#cronometro_' + "{{cron.id}}").runner({
autostart: false,
countdown: true,
startAt: {{cron.duracao_cronometro|duration_to_seconds}} * 1000,
stopAt: 0,
milliseconds: false
}).on('runnerFinish', function(eventObject, info){
$.get('/painel/cronometro', { tipo: 'cronometro_' + "{{cron.id}}", action: 'stop' } );
audioAlertFinish.play();
$('#cronometro_' + "{{cron.id}}" + '_Reset').show();
$('#cronometro_' + "{{cron.id}}").runner('stop');
$('#cronometro_' + "{{cron.id}}" + '_Start').text('Iniciar');
})
$('#cronometro_' + "{{cron.id}}" + '_Start').click(function() {
if ($('#cronometro_' + "{{cron.id}}" + '_Start').text() == 'Iniciar'){
$.get('/painel/cronometro', { tipo: 'cronometro_' + "{{cron.id}}", action: 'start' } );
$('#cronometro_' + "{{cron.id}}" + '_Reset').hide();
$('#cronometro_' + "{{cron.id}}").runner('start');
$('#cronometro_' + "{{cron.id}}" + '_Start').text('Parar');
} else{
$.get('/painel/cronometro', { tipo: 'cronometro_' + "{{cron.id}}", action: 'stop' } );
$('#cronometro_' + "{{cron.id}}" + '_Reset').show();
$('#cronometro_' + "{{cron.id}}").runner('stop');
$('#cronometro_' + "{{cron.id}}" + '_Start').text('Iniciar');
}
});
if (aberto) {
botao_abrir.hide();
botao_fechar.show();
} else {
botao_abrir.show();
botao_fechar.hide();
}
}
$('#cronometro_' + "{{cron.id}}" + '_Reset').click(function() {
$(document).ready(function(){
var pk_sessao = {{root_pk}};
var botao_abrir = $('#id_abrir_painel');
var botao_fechar = $('#id_fechar_painel');
$.ajax({
data: {pk_sessao: pk_sessao},
type: 'GET',
dataType: 'json',
url: "{% url 'sapl.painel:verifica_painel' %}",
error: function () {
alert("Erro ao verificar o Painel");
},
success: function (data) {
if (data['status']) {
botao_abrir.hide();
botao_fechar.show();
} else {
botao_abrir.show();
botao_fechar.hide();
}
},
});
$.get('/painel/cronometro', { tipo: 'cronometro_' + "{{cron.id}}", action: 'reset' } );
$('#cronometro_' + "{{cron.id}}").runner('stop');
$('#cronometro_' + "{{cron.id}}").runner('reset');
});
{% endfor %}
});

Loading…
Cancel
Save