From a891a40280154c4488f8ae9617783fba04ba3955 Mon Sep 17 00:00:00 2001 From: Cesar Augusto de Carvalho Date: Wed, 3 Jul 2019 13:41:29 -0300 Subject: [PATCH] =?UTF-8?q?Fix=20#1782=20-=20Cron=C3=B4metro=20da=20Quest?= =?UTF-8?q?=C3=A3o=20de=20Ordem=20trava=20os=20demais=20(#2861)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix #2828 - Adiciona tipo de cronômetro * Corrige migrações * Altera view do painel em Sessao * Cronômetros na tela do painel funcionando * Filtra apenas por cronometros ativos * Melhoria no Form de Cronometro * Muda nome do cronometro da ordem * Cria PainelConfig * Cronometro da ordem parando os demais * Adiciona map rule * Mensagem de aviso do funcionamento do travamento do cronometro --- sapl/painel/forms.py | 11 ++- .../0003_auto_20190603_1033.py~HEAD | 48 +++++++++++ .../0004_auto_20190603_1033.py~HEAD | 25 ++++++ sapl/painel/migrations/0005_painelconfig.py | 27 +++++++ sapl/painel/models.py | 28 ++++++- sapl/painel/urls.py | 5 +- sapl/painel/views.py | 47 ++++++++++- sapl/rules/map_rules.py | 2 + sapl/sessao/views.py | 5 +- sapl/templates/menu_tabelas_auxiliares.yaml | 3 + sapl/templates/painel/layouts.yaml | 6 +- sapl/templates/painel/painelconfig_form.html | 15 ++++ sapl/templates/sessao/painel.html | 81 ++++++++++++------- 13 files changed, 263 insertions(+), 40 deletions(-) create mode 100644 sapl/painel/migrations/0003_auto_20190603_1033.py~HEAD create mode 100644 sapl/painel/migrations/0004_auto_20190603_1033.py~HEAD create mode 100644 sapl/painel/migrations/0005_painelconfig.py create mode 100644 sapl/templates/painel/painelconfig_form.html diff --git a/sapl/painel/forms.py b/sapl/painel/forms.py index 619a120d3..e2314c407 100644 --- a/sapl/painel/forms.py +++ b/sapl/painel/forms.py @@ -1,5 +1,5 @@ from django import forms -from .models import Cronometro +from .models import Cronometro, PainelConfig class CronometroForm(forms.ModelForm): @@ -11,4 +11,11 @@ class CronometroForm(forms.ModelForm): 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 \ No newline at end of file + self.fields['ordenacao'].initial = Cronometro.objects.last().ordenacao + 1 + + +class ConfiguracoesPainelForm(forms.ModelForm): + + class Meta: + model = PainelConfig + fields = ['cronometro_ordem'] \ No newline at end of file diff --git a/sapl/painel/migrations/0003_auto_20190603_1033.py~HEAD b/sapl/painel/migrations/0003_auto_20190603_1033.py~HEAD new file mode 100644 index 000000000..7df9c2b83 --- /dev/null +++ b/sapl/painel/migrations/0003_auto_20190603_1033.py~HEAD @@ -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'), + ), + ] diff --git a/sapl/painel/migrations/0004_auto_20190603_1033.py~HEAD b/sapl/painel/migrations/0004_auto_20190603_1033.py~HEAD new file mode 100644 index 000000000..f3256ae61 --- /dev/null +++ b/sapl/painel/migrations/0004_auto_20190603_1033.py~HEAD @@ -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) + ] diff --git a/sapl/painel/migrations/0005_painelconfig.py b/sapl/painel/migrations/0005_painelconfig.py new file mode 100644 index 000000000..5daa6156c --- /dev/null +++ b/sapl/painel/migrations/0005_painelconfig.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-06-10 11:46 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('painel', '0004_auto_20190603_1033'), + ] + + operations = [ + migrations.CreateModel( + name='PainelConfig', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('cronometro_ordem', models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=True, verbose_name='Cronômetro da Questão de Ordem deve travar os demais?')), + ], + options={ + 'verbose_name': 'Configurações do Painel', + 'verbose_name_plural': 'Configurações do Painel', + 'ordering': ('-id',), + }, + ), + ] diff --git a/sapl/painel/models.py b/sapl/painel/models.py index 702fb00fe..555899884 100644 --- a/sapl/painel/models.py +++ b/sapl/painel/models.py @@ -64,4 +64,30 @@ class Cronometro(models.Model): ordering = ['ordenacao'] def __str__(self): - return self.tipo \ No newline at end of file + return self.tipo + + +@reversion.register() +class PainelConfig(models.Model): + + cronometro_ordem = models.BooleanField( + verbose_name=_('Cronômetro da Questão de Ordem deve travar os demais?'), + choices=YES_NO_CHOICES, default=True) + + class Meta: + verbose_name = _('Configurações do Painel') + verbose_name_plural = _('Configurações do Painel') + ordering = ('-id',) + + @classmethod + def attr(cls, attr): + config = PainelConfig.objects.first() + + if not config: + config = PainelConfig() + config.save() + + return getattr(config, attr) + + def __str__(self): + return 'Configurações do Painel' diff --git a/sapl/painel/urls.py b/sapl/painel/urls.py index d3921f2e2..c0d6800e5 100644 --- a/sapl/painel/urls.py +++ b/sapl/painel/urls.py @@ -3,7 +3,8 @@ 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, CronometroPainelCrud) + switch_painel, verifica_painel, votante_view, CronometroPainelCrud, + PainelConfigCrud) app_name = AppConfig.name @@ -20,7 +21,9 @@ urlpatterns = [ url(r'^painel/verifica-painel$', verifica_painel, name="verifica_painel"), url(r'^painel/cronometro$', cronometro_painel, name='cronometro_painel'), + url(r'^sistema/cronometro/', include(CronometroPainelCrud.get_urls())), + url(r'^sistema/painel-config/', include(PainelConfigCrud.get_urls())), url(r'^voto-individual/$', votante_view, name='voto_individual'), diff --git a/sapl/painel/views.py b/sapl/painel/views.py index 2421f527b..e939e71bc 100644 --- a/sapl/painel/views.py +++ b/sapl/painel/views.py @@ -24,8 +24,8 @@ 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 +from .forms import CronometroForm, ConfiguracoesPainelForm +from .models import Cronometro, PainelConfig VOTACAO_NOMINAL = 2 @@ -36,6 +36,46 @@ class CronometroPainelCrud(CrudAux): form_class = CronometroForm +class PainelConfigCrud(CrudAux): + model = PainelConfig + + class BaseMixin(CrudAux.BaseMixin): + form_class = ConfiguracoesPainelForm + list_url = '' + create_url = '' + + class CreateView(CrudAux.CreateView): + + def get(self, request, *args, **kwargs): + painel_config = PainelConfig.objects.first() + + if not painel_config: + painel_config = PainelConfig() + painel_config.save() + + return HttpResponseRedirect( + reverse('sapl.painel:painelconfig_update', + kwargs={'pk': painel_config.pk})) + + def post(self, request, *args, **kwargs): + return self.get(request, *args, **kwargs) + + class ListView(CrudAux.ListView): + + def get(self, request, *args, **kwargs): + return HttpResponseRedirect(reverse('sapl.painel:painelconfig_create')) + + class DetailView(CrudAux.DetailView): + + def get(self, request, *args, **kwargs): + return HttpResponseRedirect(reverse('sapl.painel:painelconfig_create')) + + class DeleteView(CrudAux.DeleteView): + + def get(self, request, *args, **kwargs): + return HttpResponseRedirect(reverse('sapl.painel:painelconfig_create')) + + # FIXME mudar lógica @@ -298,7 +338,8 @@ def votante_view(request): def painel_view(request, pk): context = {'head_title': str(_('Painel Plenário')), 'sessao_id': pk, - 'cronometros': Cronometro.objects.filter(ativo=True).order_by('ordenacao') + 'cronometros': Cronometro.objects.filter(ativo=True).order_by('ordenacao'), + 'painel_config': PainelConfig.objects.first() } return render(request, 'painel/index.html', context) diff --git a/sapl/rules/map_rules.py b/sapl/rules/map_rules.py index 41d2e965c..88637ddf2 100644 --- a/sapl/rules/map_rules.py +++ b/sapl/rules/map_rules.py @@ -227,6 +227,8 @@ rules_group_geral = { 'view_tabelas_auxiliares' ], set()), + (painel.PainelConfig, __base__, set()), + (base.CasaLegislativa, __listdetailchange__ + [RP_ADD], __perms_publicas__), (base.TipoAutor, __base__, __perms_publicas__), diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index 56f787fab..91a2bf6cc 100755 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -33,7 +33,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.painel.models import Cronometro, PainelConfig from sapl.parlamentares.models import (Filiacao, Legislatura, Mandato, Parlamentar, SessaoLegislativa) from sapl.sessao.apps import AppConfig @@ -1097,7 +1097,8 @@ class PainelView(PermissionRequiredForAppCrudMixin, TemplateView): 'sessao_id': kwargs['pk'], 'root_pk': kwargs['pk'], 'sessaoplenaria': SessaoPlenaria.objects.get(pk=kwargs['pk']), - 'cronometros': cronometros}) + 'cronometros': cronometros, + 'painel_config': PainelConfig.objects.first()}) tipo_sessao = sessao.tipo if tipo_sessao.nome == "Solene": diff --git a/sapl/templates/menu_tabelas_auxiliares.yaml b/sapl/templates/menu_tabelas_auxiliares.yaml index 9b02fb73a..45d3638a9 100644 --- a/sapl/templates/menu_tabelas_auxiliares.yaml +++ b/sapl/templates/menu_tabelas_auxiliares.yaml @@ -173,6 +173,9 @@ - title: {% trans 'Cronômetro' %} url: sapl.painel:cronometro_list css_class: btn btn-link + - title: {% trans 'Configurações do Painel' %} + url: sapl.painel:painelconfig_list + css_class: btn btn-link - title: {% trans 'Módulo LexML' %} css_class: head_title children: diff --git a/sapl/templates/painel/layouts.yaml b/sapl/templates/painel/layouts.yaml index 0238e74db..47957549e 100644 --- a/sapl/templates/painel/layouts.yaml +++ b/sapl/templates/painel/layouts.yaml @@ -1,4 +1,8 @@ {% load i18n %} Cronometro: {% trans 'Cronometro' %}: - - tipo:4 duracao_cronometro:4 ativo:2 ordenacao:2 \ No newline at end of file + - tipo:4 duracao_cronometro:4 ativo:2 ordenacao:2 + +PainelConfig: + {% trans 'Configurações do Painel' %}: + - cronometro_ordem diff --git a/sapl/templates/painel/painelconfig_form.html b/sapl/templates/painel/painelconfig_form.html new file mode 100644 index 000000000..990d81b7b --- /dev/null +++ b/sapl/templates/painel/painelconfig_form.html @@ -0,0 +1,15 @@ +{% extends "crud/form.html" %} +{% load i18n %} +{% load crispy_forms_tags %} + +{% block extra_js %} + + + +{% endblock extra_js%} \ No newline at end of file diff --git a/sapl/templates/sessao/painel.html b/sapl/templates/sessao/painel.html index e6b52dd2f..a9039b4e6 100644 --- a/sapl/templates/sessao/painel.html +++ b/sapl/templates/sessao/painel.html @@ -82,8 +82,8 @@ function switch_painel(aberto) { function checkTime(i) { if (i<10) { - i = "0" + i - }; + i = "0" + i; + } return i; } @@ -96,12 +96,12 @@ function startTime() { s = checkTime(s); $("#relogio").text(h+":"+m+":"+s) let t = setTimeout(function(){ - startTime() + startTime(); },500); } $(document).ready(function(){ - let pk_sessao = {{root_pk}}; + let pk_sessao = parseInt("{{root_pk}}"); let botao_abrir = $('#id_abrir_painel'); let botao_fechar = $('#id_fechar_painel'); @@ -111,16 +111,16 @@ $(document).ready(function(){ dataType: 'json', url: "{% url 'sapl.painel:verifica_painel' %}", error: function () { - alert("Erro ao verificar o Painel"); + 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(); - } + if (data['status']) { + botao_abrir.hide(); + botao_fechar.show(); + } else { + botao_abrir.show(); + botao_fechar.hide(); + } }, }); @@ -133,7 +133,7 @@ $(document).ready(function(){ $('#cronometro_' + "{{cron.id}}").runner({ autostart: false, countdown: true, - startAt: {{cron.duracao_cronometro|duration_to_seconds}} * 1000, + startAt: parseInt("{{cron.duracao_cronometro|duration_to_seconds}}") * 1000, stopAt: 0, milliseconds: false }).on('runnerFinish', function(eventObject, info){ @@ -144,26 +144,47 @@ $(document).ready(function(){ $('#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 painel_config.cronometro_ordem and cron.tipo == "Cronômetro da Questão de Ordem" %} + $('#cronometro_' + "{{cron.id}}" + '_Start').click(function() { + if ($('#cronometro_' + "{{cron.id}}" + '_Start').text() == 'Iniciar'){ + {% for c in cronometros %} + {% if c.tipo == "Cronômetro da Questão de Ordem" %} + $.get('/painel/cronometro', { tipo: 'cronometro_' + "{{c.id}}", action: 'start' } ); + $('#cronometro_' + "{{c.id}}" + '_Reset').hide(); + $('#cronometro_' + "{{c.id}}").runner('start'); + $('#cronometro_' + "{{c.id}}" + '_Start').text('Parar'); + {% else %} + $.get('/painel/cronometro', { tipo: 'cronometro_' + "{{c.id}}", action: 'stop' } ); + $('#cronometro_' + "{{c.id}}" + '_Reset').show(); + $('#cronometro_' + "{{c.id}}").runner('stop'); + $('#cronometro_' + "{{c.id}}" + '_Start').text('Iniciar'); + {% endif %} + {% endfor %} + } 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'); + } + }); + {% else %} + $('#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'); + } + }); + {% endif %} $('#cronometro_' + "{{cron.id}}" + '_Reset').click(function() { - $.get('/painel/cronometro', { tipo: 'cronometro_' + "{{cron.id}}", action: 'reset' } ); - $('#cronometro_' + "{{cron.id}}").runner('stop'); $('#cronometro_' + "{{cron.id}}").runner('reset'); });