diff --git a/compilacao/forms.py b/compilacao/forms.py index eed197ca4..cb854f9af 100644 --- a/compilacao/forms.py +++ b/compilacao/forms.py @@ -1,20 +1,24 @@ -from crispy_forms.bootstrap import FieldWithButtons, FormActions, StrictButton +from crispy_forms.bootstrap import FieldWithButtons, FormActions, StrictButton,\ + InlineRadios, Alert from crispy_forms.helper import FormHelper from crispy_forms.layout import (HTML, Button, Column, Div, Field, Fieldset, Layout, Row) from django import forms from django.core.exceptions import NON_FIELD_ERRORS from django.forms.models import ModelForm +from django.template import defaultfilters from django.utils.translation import ugettext_lazy as _ from compilacao.models import (NOTAS_PUBLICIDADE_CHOICES, PARTICIPACAO_SOCIAL_CHOICES, Dispositivo, Nota, Publicacao, TextoArticulado, TipoNota, TipoPublicacao, TipoTextoArticulado, TipoVide, - VeiculoPublicacao, Vide) + VeiculoPublicacao, Vide, TipoDispositivo) from crispy_layout_mixin import SaplFormLayout, to_column, to_row +from sapl import utils from sapl.utils import YES_NO_CHOICES + error_messages = { 'required': _('Este campo é obrigatório'), 'invalid': _('URL inválida.') @@ -257,6 +261,10 @@ class NotaForm(ModelForm): super(NotaForm, self).__init__(*args, **kwargs) +class DispositivoSearchFragmentForm(ModelForm): + pass + + class VideForm(ModelForm): dispositivo_base = forms.ModelChoiceField( queryset=Dispositivo.objects.all(), @@ -343,7 +351,7 @@ class VideForm(ModelForm): 'números ou algo' ' que estejam ' 'no rótulo ou no texto.')), - StrictButton("Buscar", css_class='btn-busca')), 12))), + StrictButton(_('Buscar'), css_class='btn-busca')), 12))), Row(to_column( (Div(css_class='container-busca'), 12))) ) @@ -482,82 +490,156 @@ class DispositivoIntegerField(forms.IntegerField): class DispositivoEdicaoBasicaForm(ModelForm): - texto = forms.CharField( - widget=forms.Textarea, - required=False) + class Meta: + model = Dispositivo + fields = [] + + def __init__(self, *args, **kwargs): + + layout = [] + + inst = kwargs['instance'] if 'instance' in kwargs else None + + if inst and inst.tipo_dispositivo.formato_variacao0 in [ + TipoDispositivo.FNC8, TipoDispositivo.FNCN]: + if 'rotulo' in DispositivoEdicaoBasicaForm.Meta.fields: + DispositivoEdicaoBasicaForm.Meta.fields.remove('rotulo') + for i in range(6): + DispositivoEdicaoBasicaForm.Meta.fields.remove( + 'dispositivo%s' % i) + else: + if 'rotulo' not in DispositivoEdicaoBasicaForm.Meta.fields: + DispositivoEdicaoBasicaForm.Meta.fields.append('rotulo') + for i in range(6): + DispositivoEdicaoBasicaForm.Meta.fields.append( + 'dispositivo%s' % i) + # adiciona campos de rótulo no formulário + self.dispositivo0 = forms.IntegerField( + min_value=0, + label=Dispositivo._meta.get_field('dispositivo0').verbose_name, + widget=forms.NumberInput( + attrs={'title': _('Valor 0(zero) é permitido apenas para ' + 'Dispositivos com tipos variáveis.'), + 'onchange': 'atualizaRotulo()'})) + self.dispositivo1 = DispositivoIntegerField( + label=('1ª %s' % _('Variação')), + field_name='dispositivo1') + self.dispositivo2 = DispositivoIntegerField( + label=('2ª'), + field_name='dispositivo2') + self.dispositivo3 = DispositivoIntegerField( + label=('3ª'), + field_name='dispositivo3') + self.dispositivo4 = DispositivoIntegerField( + label=('4ª'), + field_name='dispositivo4') + self.dispositivo5 = DispositivoIntegerField( + label=('5ª'), + field_name='dispositivo5') + + self.rotulo = forms.CharField( + required=False, label=_('Rótulo Resultante')) + + rotulo_fieldset = to_row([ + ('dispositivo0', 3), + ('dispositivo1', 2), + ('dispositivo2', 1), + ('dispositivo3', 1), + ('dispositivo4', 1), + ('dispositivo5', 1), + ('rotulo', 3)]) + + layout.append(Fieldset(_('Construção do Rótulo'), rotulo_fieldset, + css_class="col-md-12")) + + if inst and inst.tipo_dispositivo.dispositivo_de_articulacao: + if 'texto' in DispositivoEdicaoBasicaForm.Meta.fields: + DispositivoEdicaoBasicaForm.Meta.fields.remove('texto') + else: + if 'texto' not in DispositivoEdicaoBasicaForm.Meta.fields: + DispositivoEdicaoBasicaForm.Meta.fields.append('texto') + + self.texto = forms.CharField(required=False, + label='', + widget=forms.Textarea()) + row_texto = to_row([('texto', 12)]) + layout.append( + Fieldset(Dispositivo._meta.get_field('texto').verbose_name, + row_texto, + css_class="col-md-12")) + + fields = DispositivoEdicaoBasicaForm.Meta.fields + if fields: + self.base_fields.clear() + for f in fields: + self.base_fields.update({f: getattr(self, f)}) - dispositivo1 = DispositivoIntegerField( - label=('1ª %s' % _('Variação')), - field_name='dispositivo1') - dispositivo2 = DispositivoIntegerField( - label=('2ª'), - field_name='dispositivo2') - dispositivo3 = DispositivoIntegerField( - label=('3ª'), - field_name='dispositivo3') - dispositivo4 = DispositivoIntegerField( - label=('4ª'), - field_name='dispositivo4') - dispositivo5 = DispositivoIntegerField( - label=('5ª'), - field_name='dispositivo5') - - rotulo = forms.CharField(label=_('Rótulo Resultante')) + self.helper = FormHelper() + self.helper.layout = SaplFormLayout( + *layout, + label_cancel=_('Retornar para o Editor Sequencial')) + + super(DispositivoEdicaoBasicaForm, self).__init__(*args, **kwargs) + + +class DispositivoEdicaoVigenciaForm(ModelForm): + + inconstitucionalidade = forms.ChoiceField( + label=Dispositivo._meta.get_field( + 'inconstitucionalidade').verbose_name, + choices=utils.YES_NO_CHOICES, + widget=forms.RadioSelect()) class Meta: model = Dispositivo - fields = ( - 'dispositivo0', - 'dispositivo1', - 'dispositivo2', - 'dispositivo3', - 'dispositivo4', - 'dispositivo5', - 'rotulo', - 'texto') - - widgets = { - 'dispositivo0': forms.NumberInput( - attrs={'title': _('Valor 0(zero) é permitido apenas ' - 'para Dispositivos com tipos variáveis.'), - 'onchange': 'atualizaRotulo()'})} + fields = ['inicio_vigencia', + 'fim_vigencia', + 'inicio_eficacia', + 'fim_eficacia', + 'publicacao', + 'inconstitucionalidade' + ] def __init__(self, *args, **kwargs): layout = [] - rotulo_fieldset = to_row([ - ('dispositivo0', 3), - ('dispositivo1', 2), - ('dispositivo2', 1), - ('dispositivo3', 1), - ('dispositivo4', 1), - ('dispositivo5', 1), - ('rotulo', 3) - ]) + row_publicacao = to_row([ + ('publicacao', 6), + (InlineRadios('inconstitucionalidade'), 3), ]) + row_publicacao.fields.append( + Alert( + css_class='alert-info col-md-3', + content='%s%s' % ( + _('Dica!'), _('Inclua uma Nota de Dispositivo informando ' + 'sobre a Inconstitucionalidade.')))) layout.append( - Fieldset( - _('Montagem do Rótulo'), - rotulo_fieldset, - css_class="col-md-12")) - - # Campo Texto - row_texto = to_row([('texto', 12)]) - css_class_texto = "col-md-12" - if 'instance' in kwargs and\ - kwargs['instance'].tipo_dispositivo.dispositivo_de_articulacao: - css_class_texto = "col-md-12 hidden" + Fieldset(_('Registro de Publicação e Validade'), + row_publicacao, + css_class="col-md-12")) + + row_datas = to_row([ + ('inicio_vigencia', 3), + ('fim_vigencia', 3), + ('inicio_eficacia', 3), + ('fim_eficacia', 3), ]) layout.append( - Fieldset( - Dispositivo._meta.get_field('texto').verbose_name, - row_texto, - css_class=css_class_texto)) + Fieldset(_('Datas de Controle de Vigência'), + row_datas, + css_class="col-md-12")) self.helper = FormHelper() - if layout: - self.helper.layout = SaplFormLayout(*layout) - else: - self.helper.layout = SaplFormLayout() - - super(DispositivoEdicaoBasicaForm, self).__init__(*args, **kwargs) + self.helper.layout = SaplFormLayout( + *layout, + label_cancel=_('Retornar para o Editor Sequencial')) + + super(DispositivoEdicaoVigenciaForm, self).__init__(*args, **kwargs) + + pubs = Publicacao.objects.order_by( + '-data', '-hora').filter(ta=self.instance.ta) + self.fields['publicacao'].choices = [("", "---------")] + [( + p.pk, _('%s realizada em %s') % ( + p.tipo_publicacao, + defaultfilters.date( + p.data, "d \d\e F \d\e Y"))) for p in pubs] diff --git a/compilacao/models.py b/compilacao/models.py index 026b4496e..f9bfb61ff 100644 --- a/compilacao/models.py +++ b/compilacao/models.py @@ -556,7 +556,7 @@ class Dispositivo(BaseModel, TimestampedMixin): texto = models.TextField( blank=True, default='', - verbose_name=_('Texto na Norma Original')) + verbose_name=_('Texto Original')) texto_atualizador = models.TextField( blank=True, default='', @@ -575,7 +575,7 @@ class Dispositivo(BaseModel, TimestampedMixin): inconstitucionalidade = models.BooleanField( default=False, choices=utils.YES_NO_CHOICES, - verbose_name=_('Declaração de Inconstitucionalidade')) + verbose_name=_('Declarado Inconstitucional')) # Relevant attribute only in altering norms visibilidade = models.BooleanField( default=False, diff --git a/compilacao/urls.py b/compilacao/urls.py index d70445d2a..0d48376b1 100644 --- a/compilacao/urls.py +++ b/compilacao/urls.py @@ -33,9 +33,13 @@ urlpatterns_compilacao = [ url(r'^(?P[0-9]+)/text/(?P[0-9]+)/refresh', views.DispositivoSimpleEditView.as_view(), name='dispositivo_refresh'), - url(r'^(?P[0-9]+)/text/(?P[0-9]+)/edit', + url(r'^(?P[0-9]+)/text/(?P[0-9]+)/edit$', views.DispositivoEdicaoBasicaView.as_view(), name='dispositivo_edit'), + url(r'^(?P[0-9]+)/text/(?P[0-9]+)/edit/vigencia', + views.DispositivoEdicaoVigenciaView.as_view(), + name='dispositivo_edit_vigencia'), + url(r'^(?P[0-9]+)/text/(?P[0-9]+)/actions', diff --git a/compilacao/views.py b/compilacao/views.py index f631d48bc..62bdd32f4 100644 --- a/compilacao/views.py +++ b/compilacao/views.py @@ -1,6 +1,6 @@ -import sys from collections import OrderedDict from datetime import datetime, timedelta +import sys from braces.views import FormMessagesMixin from django import forms @@ -21,7 +21,8 @@ from django.views.generic.edit import CreateView, DeleteView, UpdateView from django.views.generic.list import ListView from compilacao.forms import (DispositivoEdicaoBasicaForm, NotaForm, - PublicacaoForm, TaForm, TipoTaForm, VideForm) + PublicacaoForm, TaForm, TipoTaForm, VideForm, + DispositivoEdicaoVigenciaForm) from compilacao.models import (Dispositivo, Nota, PerfilEstruturalTextoArticulado, Publicacao, TextoArticulado, TipoDispositivo, TipoNota, @@ -29,6 +30,7 @@ from compilacao.models import (Dispositivo, Nota, VeiculoPublicacao, Vide) from crud.base import Crud, CrudListView, make_pagination + DISPOSITIVO_SELECT_RELATED = ( 'tipo_dispositivo', 'ta_publicado', @@ -1772,12 +1774,6 @@ class VideDeleteView(VideMixin, TemplateView): class DispositivoSearchFragmentFormView(ListView): template_name = 'compilacao/dispositivo_search_fragment_form.html' - @method_decorator(login_required) - def dispatch(self, *args, **kwargs): - return super( - DispositivoSearchFragmentFormView, - self).dispatch(*args, **kwargs) - def get_queryset(self): try: busca = '' @@ -2003,8 +1999,8 @@ class DispositivoEdicaoBasicaView(UpdateView): 'compilacao:dispositivo_edit', kwargs={'ta_id': self.kwargs['ta_id'], 'pk': self.kwargs['pk']}) - def get_context_data(self, **kwargs): - return UpdateView.get_context_data(self, **kwargs) + def get_url_this_view(self): + return 'compilacao:dispositivo_edit' def run_actions(self, request): if 'action' in request.GET and\ @@ -2018,10 +2014,32 @@ class DispositivoEdicaoBasicaView(UpdateView): d.dispositivo4 = int(request.GET['dispositivo4']) d.dispositivo5 = int(request.GET['dispositivo5']) d.rotulo = d.rotulo_padrao() + + numero = d.get_numero_completo()[1:] + + zerar = False + for i in range(len(numero)): + if not numero[i]: + zerar = True + + if zerar: + numero[i] = 0 + + if zerar: + d.set_numero_completo([d.dispositivo0, ] + numero) + d.rotulo = d.rotulo_padrao() + except: return True, JsonResponse({'message': str( _('Ocorreu erro na atualização do rótulo'))}, safe=False) - return True, JsonResponse({'rotulo': d.rotulo}, safe=False) + return True, JsonResponse({ + 'rotulo': d.rotulo, + 'dispositivo0': d.dispositivo0, + 'dispositivo1': d.dispositivo1, + 'dispositivo2': d.dispositivo2, + 'dispositivo3': d.dispositivo3, + 'dispositivo4': d.dispositivo4, + 'dispositivo5': d.dispositivo5}, safe=False) return False, '' @@ -2032,3 +2050,27 @@ class DispositivoEdicaoBasicaView(UpdateView): return render_json_response return UpdateView.get(self, request, *args, **kwargs) + + +class DispositivoEdicaoVigenciaView(DispositivoEdicaoBasicaView): + model = Dispositivo + form_class = DispositivoEdicaoVigenciaForm + + def get_url_this_view(self): + return 'compilacao:dispositivo_edit_vigencia' + + def get_success_url(self): + return reverse_lazy( + 'compilacao:dispositivo_edit_vigencia', + kwargs={'ta_id': self.kwargs['ta_id'], 'pk': self.kwargs['pk']}) + + def run_actions(self, request): + if 'action' in request.GET and\ + request.GET['action'] == 'atualiza_rotulo': + try: + pass + except: + return True, JsonResponse({'message': str( + _('Ocorreu erro na atualização do rótulo'))}, safe=False) + return True, JsonResponse({}, safe=False) + return False, '' diff --git a/crispy_layout_mixin.py b/crispy_layout_mixin.py index 46dadf7a7..c812b4315 100644 --- a/crispy_layout_mixin.py +++ b/crispy_layout_mixin.py @@ -1,11 +1,11 @@ from math import ceil from os.path import dirname, join -import rtyaml from crispy_forms.bootstrap import FormActions from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Div, Fieldset, Layout, Submit from django.utils.translation import ugettext as _ +import rtyaml def heads_and_tails(list_of_lists): @@ -39,10 +39,10 @@ def form_actions(more=[], save_label=_('Salvar')): class SaplFormLayout(Layout): - def __init__(self, *fields): + def __init__(self, *fields, label_cancel=_('Cancelar')): buttons = form_actions(more=[ HTML('%s' % _('Cancelar'))]) + ' class="btn btn-inverse">%s' % label_cancel)]) _fields = list(to_fieldsets(fields)) + [to_row([(buttons, 12)])] super(SaplFormLayout, self).__init__(*_fields) diff --git a/templates/compilacao/dispositivo_form.html b/templates/compilacao/dispositivo_form.html index cb17c9cfa..1c5350be9 100644 --- a/templates/compilacao/dispositivo_form.html +++ b/templates/compilacao/dispositivo_form.html @@ -7,6 +7,16 @@ {% block head_content %}{{block.super}} {% endblock %} +{% block sections_nav %} + +{% endblock sections_nav %} {% block title %}

{{object.ta}}
{% trans 'Edição de Dispositivo' %}

@@ -52,6 +62,12 @@ $.get(url, formData).done(function(data) { if (data.rotulo != undefined) { $('[name="rotulo"]').val(data.rotulo); + $('[name="dispositivo0"]').val(data.dispositivo0); + $('[name="dispositivo1"]').val(data.dispositivo1); + $('[name="dispositivo2"]').val(data.dispositivo2); + $('[name="dispositivo3"]').val(data.dispositivo3); + $('[name="dispositivo4"]').val(data.dispositivo4); + $('[name="dispositivo5"]').val(data.dispositivo5); return; } }); diff --git a/templates/compilacao/dispositivo_form_parents.html b/templates/compilacao/dispositivo_form_parents.html index 7006d2581..09d1c2cf1 100644 --- a/templates/compilacao/dispositivo_form_parents.html +++ b/templates/compilacao/dispositivo_form_parents.html @@ -2,13 +2,13 @@ {% load compilacao_filters %} {% if not node.dispositivos_filhos_set.exists %} - + {{node|nomenclatura}} {% else %}
- + {{node|nomenclatura}} @@ -16,7 +16,7 @@