diff --git a/compilacao/forms.py b/compilacao/forms.py index 3d81a1622..8b52a4d81 100644 --- a/compilacao/forms.py +++ b/compilacao/forms.py @@ -1,12 +1,16 @@ +from datetime import datetime + 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.core.exceptions import NON_FIELD_ERRORS, ValidationError +from django.forms.forms import Form from django.forms.models import ModelForm from django.template import defaultfilters +from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ from compilacao.models import (NOTAS_PUBLICIDADE_CHOICES, @@ -599,13 +603,78 @@ class DispositivoEdicaoBasicaForm(ModelForm): super(DispositivoEdicaoBasicaForm, self).__init__(*args, **kwargs) -FIELD_NAME_MAPPING = { - 'dispositivo_vigencia': 'dispositivo_ref', -} +class DispositivoSearchModalForm(Form): + + tipo_ta = forms.ModelChoiceField( + label=_('Tipo do Texto Articulado'), + queryset=TipoTextoArticulado.objects.all(), + required=False) + + tipo_model = forms.ChoiceField( + choices=[], + label=_('Tipos de...'), required=False) + + num_ta = forms.IntegerField( + label=_('Número do Documento'), required=False) + ano_ta = forms.IntegerField( + label=_('Ano do Documento'), required=False) + + dispositivos_internos = forms.ChoiceField( + label=_('Incluir Dispositivos Internos?'), + choices=utils.YES_NO_CHOICES, + widget=forms.RadioSelect(), + required=False) + + rotulo_dispositivo = forms.CharField( + label=_('Rótulo'), + required=False) + + texto_dispositivo = forms.CharField( + label=_('Pesquisa Textual'), + required=False) + + def __init__(self, *args, **kwargs): + + fields_search = Fieldset( + _('Busca por um Dispositivo'), + Row( + to_column(('num_ta', 4)), + to_column(('ano_ta', 4)), + to_column((InlineRadios('dispositivos_internos'), 4))), + Row( + to_column(('tipo_ta', 6)), + to_column(('tipo_model', 6))), + Row(to_column(('rotulo_dispositivo', 3)), + to_column((FieldWithButtons( + Field( + 'texto_dispositivo', + placeholder=_('Digite palavras, letras, ' + 'números ou algo' + ' que estejam no texto.')), + StrictButton(_('Buscar'), css_class='btn-busca')), 9))) + ) -class DispositivoEdicaoVigenciaForm(DispositivoSearchFragmentForm): + self.helper = FormHelper() + self.helper.layout = Layout( + fields_search, + Row(to_column((Div(css_class='result-busca-dispositivo'), 12)))) + if 'choice_model_type_foreignkey_in_extenal_views' in kwargs: + ch = kwargs.pop('choice_model_type_foreignkey_in_extenal_views') + if 'data' in kwargs: + choice = ch(kwargs['data']['tipo_ta']) + self.base_fields['tipo_model'].choices = choice + elif 'instance' in kwargs and\ + isinstance(kwargs['instance'], Dispositivo): + choice = ch(kwargs['instance'].ta.tipo_ta_id) + self.base_fields['tipo_model'].choices = choice + + kwargs['initial'].update({'dispositivos_internos': False}) + super(DispositivoSearchModalForm, self).__init__(*args, **kwargs) + + +class DispositivoEdicaoVigenciaForm(ModelForm): inconstitucionalidade = forms.ChoiceField( label=Dispositivo._meta.get_field( 'inconstitucionalidade').verbose_name, @@ -613,9 +682,18 @@ class DispositivoEdicaoVigenciaForm(DispositivoSearchFragmentForm): widget=forms.RadioSelect()) dispositivo_vigencia = forms.ModelChoiceField( + label=Dispositivo._meta.get_field( + 'dispositivo_vigencia').verbose_name, required=False, - queryset=Dispositivo.objects.all(), - widget=forms.HiddenInput()) + queryset=Dispositivo.objects.all()) + + extensao = forms.ChoiceField( + label=_('Extender a seleção abaixo como Dispositivo de Vigência ' + 'para todos dependentes originais ' + 'deste Dispositivo em edição?'), + choices=utils.YES_NO_CHOICES, + widget=forms.RadioSelect(), + required=False) class Meta: model = Dispositivo @@ -628,11 +706,6 @@ class DispositivoEdicaoVigenciaForm(DispositivoSearchFragmentForm): 'dispositivo_vigencia' ] - def add_prefix(self, field_name): - # look up field name; return original if not found - field_name = FIELD_NAME_MAPPING.get(field_name, field_name) - return super(DispositivoEdicaoVigenciaForm, self).add_prefix(field_name) - def __init__(self, *args, **kwargs): layout = [] @@ -646,7 +719,6 @@ class DispositivoEdicaoVigenciaForm(DispositivoSearchFragmentForm): content='%s %s' % ( _('Dica!'), _('Inclua uma Nota de Dispositivo informando ' 'sobre a Inconstitucionalidade.')))) - layout.append( Fieldset(_('Registro de Publicação e Validade'), row_publicacao, @@ -657,24 +729,28 @@ class DispositivoEdicaoVigenciaForm(DispositivoSearchFragmentForm): ('fim_vigencia', 3), ('inicio_eficacia', 3), ('fim_eficacia', 3), ]) - layout.append( Fieldset(_('Datas de Controle de Vigência'), row_datas, css_class="col-md-12")) + row_vigencia = Field( + 'dispositivo_vigencia', + data_sapl_ta='DispositivoSearch', + data_field='dispositivo_vigencia', + data_type_selection='radio', + template="compilacao/layout/dispositivo_radio.html") + layout.append( + Fieldset(_('Dispositivo de Vigência'), + to_row([(InlineRadios('extensao'), 12)]), + row_vigencia, + css_class="col-md-12")) + self.helper = FormHelper() self.helper.layout = SaplFormLayout( + *layout, label_cancel=_('Retornar para o Editor Sequencial')) - self.helper.layout.fields += layout - - kwargs['fields_search'] = fields_search = Div() - self.helper.layout.fields.append( - Fieldset(_('Dispositivo de Vigência'), - fields_search, - css_class="col-md-12 dispositivo_vigencia_busca")) - super(DispositivoEdicaoVigenciaForm, self).__init__(*args, **kwargs) pubs = Publicacao.objects.order_by( @@ -684,3 +760,112 @@ class DispositivoEdicaoVigenciaForm(DispositivoSearchFragmentForm): p.tipo_publicacao, defaultfilters.date( p.data, "d \d\e F \d\e Y"))) for p in pubs] + + dvs = Dispositivo.objects.order_by('ordem').filter( + pk=self.instance.dispositivo_vigencia_id) + self.fields['dispositivo_vigencia'].choices = [(d.pk, d) for d in dvs] + + def save(self): + super(DispositivoEdicaoVigenciaForm, self).save() + + data = self.cleaned_data + + extensao = 'extensao' in data and data['extensao'] == 'True' + + if extensao: + dv = data['dispositivo_vigencia'] + dv_pk = dv.pk if dv else None + instance = self.instance + + def extenderPara(dpt_pk): + + Dispositivo.objects.filter( + dispositivo_pai_id=dpt_pk, + ta_publicado__isnull=True).update( + dispositivo_vigencia_id=dv_pk) + + filhos = Dispositivo.objects.filter( + dispositivo_pai_id=dpt_pk).values_list('pk', flat=True) + + for d in filhos: + extenderPara(d) + + extenderPara(instance.pk) + + +class MultipleChoiceWithoutValidationField(forms.MultipleChoiceField): + + def validate(self, value): + if self.required and not value: + raise ValidationError( + self.error_messages['required'], code='required') + + +class DispositivoDefinidorVigenciaForm(Form): + + dispositivo_vigencia = MultipleChoiceWithoutValidationField( + label=Dispositivo._meta.get_field( + 'dispositivo_vigencia').verbose_name, + required=False) + + def __init__(self, *args, **kwargs): + + layout = [] + + row_vigencia = Field( + 'dispositivo_vigencia', + data_sapl_ta='DispositivoSearch', + data_field='dispositivo_vigencia', + data_type_selection='checkbox', + template="compilacao/layout/dispositivo_checkbox.html") + layout.append( + Fieldset(_('Definidor de Vigência dos Dispositívos abaixo'), + row_vigencia, + css_class="col-md-12")) + + self.helper = FormHelper() + self.helper.layout = SaplFormLayout( + *layout, + label_cancel=_('Retornar para o Editor Sequencial')) + + pk = kwargs.pop('pk') + super(DispositivoDefinidorVigenciaForm, self).__init__(*args, **kwargs) + + dvs = Dispositivo.objects.order_by('ta', 'ordem').filter( + dispositivo_vigencia_id=pk).select_related( + 'tipo_dispositivo', + 'ta_publicado', + 'ta', + 'dispositivo_atualizador', + 'dispositivo_atualizador__dispositivo_pai', + 'dispositivo_atualizador__dispositivo_pai__ta', + 'dispositivo_atualizador__dispositivo_pai__ta__tipo_ta', + 'dispositivo_pai', + 'dispositivo_pai__tipo_dispositivo', + 'ta_publicado', + 'ta',) + self.initial['dispositivo_vigencia'] = [d.pk for d in dvs] + + tas = Dispositivo.objects.filter( + dispositivo_vigencia_id=pk).values_list('ta', 'ta_publicado') + + tas = list(set().union(*list(map(list, zip(*tas))))) + + if not tas: + tas = Dispositivo.objects.filter(pk=pk).values_list('ta_id') + + dvs = Dispositivo.objects.order_by('-ta__data', '-ta__ano', '-ta__numero', 'ta', 'ordem').filter( + ta__in=tas).select_related( + 'tipo_dispositivo', + 'ta_publicado', + 'ta', + 'dispositivo_atualizador', + 'dispositivo_atualizador__dispositivo_pai', + 'dispositivo_atualizador__dispositivo_pai__ta', + 'dispositivo_atualizador__dispositivo_pai__ta__tipo_ta', + 'dispositivo_pai', + 'dispositivo_pai__tipo_dispositivo', + 'ta_publicado', + 'ta',) + self.fields['dispositivo_vigencia'].choices = [ + (d.pk, d) for d in dvs] diff --git a/compilacao/models.py b/compilacao/models.py index 847e2f7ff..96961f673 100644 --- a/compilacao/models.py +++ b/compilacao/models.py @@ -627,7 +627,7 @@ class Dispositivo(BaseModel, TimestampedMixin): dispositivo_vigencia = models.ForeignKey( 'self', blank=True, null=True, default=None, - related_name='+', + related_name='dispositivos_vigencias_set', verbose_name=_('Dispositivo de Vigência')) dispositivo_atualizador = models.ForeignKey( 'self', @@ -752,6 +752,8 @@ class Dispositivo(BaseModel, TimestampedMixin): r += prefixo[0] r += self.get_nomenclatura_completa() else: + if self.dispositivo0 == 0: + self.dispositivo0 = 1 r += prefixo[0] r += self.get_nomenclatura_completa() @@ -1150,10 +1152,20 @@ class Dispositivo(BaseModel, TimestampedMixin): dp.texto = '' dp.ta = dispositivo_base.ta dp.dispositivo_pai = dispositivo_base.dispositivo_pai - dp.inicio_eficacia = dispositivo_base.inicio_eficacia - dp.inicio_vigencia = dispositivo_base.inicio_vigencia dp.publicacao = dispositivo_base.publicacao - dp.timestamp = datetime.now() + + dp.dispositivo_vigencia = dispositivo_base.dispositivo_vigencia + if dp.dispositivo_vigencia: + dp.inicio_eficacia = dp.dispositivo_vigencia.inicio_eficacia + dp.inicio_vigencia = dp.dispositivo_vigencia.inicio_vigencia + dp.fim_eficacia = dp.dispositivo_vigencia.fim_eficacia + dp.fim_vigencia = dp.dispositivo_vigencia.fim_vigencia + else: + dp.inicio_eficacia = dispositivo_base.inicio_eficacia + dp.inicio_vigencia = dispositivo_base.inicio_vigencia + dp.fim_eficacia = dispositivo_base.inicio_eficacia + dp.fim_vigencia = dispositivo_base.fim_vigencia + dp.ordem = dispositivo_base.ordem return dp diff --git a/compilacao/templatetags/compilacao_filters.py b/compilacao/templatetags/compilacao_filters.py index 6aab329a5..2ee09593b 100644 --- a/compilacao/templatetags/compilacao_filters.py +++ b/compilacao/templatetags/compilacao_filters.py @@ -16,13 +16,6 @@ def get_bloco_atualizador(pk_atualizador): Q(dispositivo_atualizador_id=pk_atualizador)).select_related() -@register.filter -def get_tipos_dispositivo(pk_atual): - - return TipoDispositivo.objects.filter( - id__gte=pk_atual) - - @register.simple_tag def dispositivo_desativado(dispositivo, inicio_vigencia, fim_vigencia): if inicio_vigencia and fim_vigencia: @@ -39,17 +32,23 @@ def dispositivo_desativado(dispositivo, inicio_vigencia, fim_vigencia): @register.simple_tag def nota_automatica(dispositivo, ta_pub_list): + if dispositivo.ta_publicado is not None: d = dispositivo.dispositivo_atualizador.dispositivo_pai + + ta_publicado = ta_pub_list[dispositivo.ta_publicado_id] if\ + ta_pub_list else dispositivo.ta_publicado + if dispositivo.texto == Dispositivo.TEXTO_PADRAO_DISPOSITIVO_REVOGADO: return _('Revogado pelo %s - %s.') % ( - d, ta_pub_list[dispositivo.ta_publicado_id]) + d, ta_publicado) elif not dispositivo.dispositivo_substituido_id: return _('Inclusão feita pelo %s - %s.') % ( - d, ta_pub_list[dispositivo.ta_publicado_id]) + d, ta_publicado) else: return _('Alteração feita pelo %s - %s.') % ( - d, ta_pub_list[dispositivo.ta_publicado_id]) + d, ta_publicado) + return '' @@ -125,8 +124,10 @@ def nomenclatura(d): result = '(' + d.tipo_dispositivo.nome + ' ' + \ d.rotulo + ')' else: - result = '(' + d.tipo_dispositivo.nome + ' ' + \ - d.rotulo_padrao() + ')' + r = d.rotulo_padrao() + if r: + r += ' ' + result = '(' + d.tipo_dispositivo.nome + r + ')' return result @@ -159,3 +160,8 @@ def nomenclatura_heranca(d, ignore_ultimo=0, ignore_primeiro=0): @register.filter def urldetail_content_type(obj): return '%s:detail' % obj.content_type.model + + +@register.filter +def list(obj): + return [obj, ] diff --git a/compilacao/urls.py b/compilacao/urls.py index bc5d22754..1a2262c02 100644 --- a/compilacao/urls.py +++ b/compilacao/urls.py @@ -40,13 +40,13 @@ urlpatterns_compilacao = [ views.DispositivoEdicaoVigenciaView.as_view(), name='dispositivo_edit_vigencia'), - + url(r'^(?P[0-9]+)/text/(?P[0-9]+)/edit/definidor_vigencia', + views.DispositivoDefinidorVigenciaView.as_view(), + name='dispositivo_edit_definidor_vigencia'), url(r'^(?P[0-9]+)/text/(?P[0-9]+)/actions', views.ActionsEditView.as_view(), name='dispositivo_actions'), - - url(r'^(?P[0-9]+)/text/' '(?P[0-9]+)/nota/create$', views.NotasCreateView.as_view(), name='nota_create'), @@ -75,6 +75,10 @@ urlpatterns_compilacao = [ views.DispositivoSearchFragmentFormView.as_view(), name='dispositivo_fragment_form'), + url(r'^search_form$', + views.DispositivoSearchModalView.as_view(), + name='dispositivo_search_form'), + url(r'^(?P[0-9]+)/publicacao$', views.PublicacaoListView.as_view(), name='ta_pub_list'), diff --git a/compilacao/views.py b/compilacao/views.py index 82dceebbf..1e6c901f4 100644 --- a/compilacao/views.py +++ b/compilacao/views.py @@ -19,12 +19,15 @@ from django.utils.decorators import method_decorator from django.utils.translation import ugettext_lazy as _ from django.views.generic.base import TemplateView from django.views.generic.detail import DetailView -from django.views.generic.edit import CreateView, DeleteView, UpdateView +from django.views.generic.edit import CreateView, DeleteView, UpdateView,\ + FormView from django.views.generic.list import ListView from compilacao.forms import (DispositivoEdicaoBasicaForm, NotaForm, PublicacaoForm, TaForm, TipoTaForm, VideForm, - DispositivoEdicaoVigenciaForm) + DispositivoEdicaoVigenciaForm, + DispositivoSearchModalForm, + DispositivoDefinidorVigenciaForm) from compilacao.models import (Dispositivo, Nota, PerfilEstruturalTextoArticulado, Publicacao, TextoArticulado, TipoDispositivo, TipoNota, @@ -317,6 +320,266 @@ class TaDeleteView(CompMixin, DeleteView): return reverse_lazy('compilacao:ta_list') +class DispositivoSuccessUrlMixin: + + def get_success_url(self): + return reverse_lazy( + 'compilacao:dispositivo', kwargs={ + 'ta_id': self.kwargs[ + 'ta_id'], + 'dispositivo_id': self.kwargs[ + 'dispositivo_id']}) + + +class NotaMixin(DispositivoSuccessUrlMixin): + + def get_modelo_nota(self, request): + if 'action' in request.GET and request.GET['action'] == 'modelo_nota': + tn = TipoNota.objects.get(pk=request.GET['id_tipo']) + return True, tn.modelo + return False, '' + + def get_initial(self): + dispositivo = get_object_or_404( + Dispositivo, pk=self.kwargs.get('dispositivo_id')) + initial = {'dispositivo': dispositivo} + + if 'pk' in self.kwargs: + initial['pk'] = self.kwargs.get('pk') + + return initial + + @method_decorator(login_required) + def dispatch(self, *args, **kwargs): + return super(NotaMixin, self).dispatch(*args, **kwargs) + + +class NotasCreateView(NotaMixin, CreateView): + template_name = 'compilacao/ajax_form.html' + form_class = NotaForm + + def get(self, request, *args, **kwargs): + flag_action, modelo_nota = self.get_modelo_nota(request) + if flag_action: + return HttpResponse(modelo_nota) + + return super(NotasCreateView, self).get(request, *args, **kwargs) + + def post(self, request, *args, **kwargs): + self.object = None + try: + ta_id = kwargs.pop('ta_id') + dispositivo_id = kwargs.pop('dispositivo_id') + form = NotaForm(request.POST, request.FILES, **kwargs) + kwargs['ta_id'] = ta_id + kwargs['dispositivo_id'] = dispositivo_id + + if form.is_valid(): + nt = form.save(commit=False) + nt.owner_id = request.user.pk + nt.save() + self.kwargs['pk'] = nt.pk + return self.form_valid(form) + else: + return self.form_invalid(form) + except Exception as e: + print(e) + return HttpResponse("error post") + + +class NotasEditView(NotaMixin, UpdateView): + model = Nota + template_name = 'compilacao/ajax_form.html' + form_class = NotaForm + + def get(self, request, *args, **kwargs): + flag_action, modelo_nota = self.get_modelo_nota(request) + if flag_action: + return HttpResponse(modelo_nota) + + return super(NotasEditView, self).get(request, *args, **kwargs) + + +class NotasDeleteView(NotaMixin, TemplateView): + + def get(self, request, *args, **kwargs): + nt = Nota.objects.get(pk=self.kwargs['pk']) + nt.delete() + return HttpResponseRedirect(self.get_success_url()) + + +class VideMixin(DispositivoSuccessUrlMixin): + + def get_initial(self): + dispositivo_base = get_object_or_404( + Dispositivo, pk=self.kwargs.get('dispositivo_id')) + + initial = {'dispositivo_base': dispositivo_base} + + if 'pk' in self.kwargs: + initial['pk'] = self.kwargs.get('pk') + + return initial + + @method_decorator(login_required) + def dispatch(self, *args, **kwargs): + return super(VideMixin, self).dispatch(*args, **kwargs) + + +def choice_model_type_foreignkey_in_extenal_views(id_tipo_ta=None): + yield None, '-------------' + + if not id_tipo_ta: + return + + tipo_ta = TipoTextoArticulado.objects.get(pk=id_tipo_ta) + + integrations_view_names = get_integrations_view_names() + for item in integrations_view_names: + if hasattr(item, 'model_type_foreignkey'): + if (tipo_ta.content_type.model == item.model.__name__.lower() and + tipo_ta.content_type.app_label == + item.model._meta.app_label): + for i in item.model_type_foreignkey.objects.all(): + yield i.pk, i + + +class VideCreateView(VideMixin, CreateView): + model = Vide + template_name = 'compilacao/ajax_form.html' + form_class = VideForm + + def get(self, request, *args, **kwargs): + self.object = None + form = self.get_form() + return self.render_to_response(self.get_context_data(form=form)) + + def get_form_kwargs(self): + + kwargs = super(VideCreateView, self).get_form_kwargs() + + if 'choice_model_type_foreignkey_in_extenal_views' not in kwargs: + kwargs.update({ + 'choice_model_type_foreignkey_in_extenal_views': + choice_model_type_foreignkey_in_extenal_views + }) + + return kwargs + + +class VideEditView(VideMixin, UpdateView): + model = Vide + template_name = 'compilacao/ajax_form.html' + form_class = VideForm + + +class VideDeleteView(VideMixin, TemplateView): + + def get(self, request, *args, **kwargs): + vd = Vide.objects.get(pk=self.kwargs['pk']) + vd.delete() + return HttpResponseRedirect(self.get_success_url()) + + +class PublicacaoListView(ListView): + model = Publicacao + verbose_name = model._meta.verbose_name + + @property + def title(self): + return _('%s de %s' % ( + self.model._meta.verbose_name_plural, + self.ta)) + + @property + def ta(self): + ta = TextoArticulado.objects.get(pk=self.kwargs['ta_id']) + return ta + + @property + def create_url(self): + return reverse_lazy( + 'compilacao:ta_pub_create', + kwargs={'ta_id': self.kwargs['ta_id']}) + + def get_queryset(self): + pubs = Publicacao.objects.filter(ta_id=self.kwargs['ta_id']) + return pubs + + def get_context_data(self, **kwargs): + context = super(PublicacaoListView, self).get_context_data(**kwargs) + context['NO_ENTRIES_MSG'] = CrudListView.no_entries_msg + return context + + +class PublicacaoCreateView(FormMessagesMixin, CreateView): + model = Publicacao + form_class = PublicacaoForm + template_name = "crud/form.html" + form_valid_message = _('Registro criado com sucesso!') + form_invalid_message = _('O registro não foi criado.') + + def get_success_url(self): + return reverse_lazy( + 'compilacao:ta_pub_detail', + kwargs={ + 'pk': self.object.id, + 'ta_id': self.kwargs['ta_id']}) + + @property + def cancel_url(self): + return reverse_lazy( + 'compilacao:ta_pub_list', + kwargs={'ta_id': self.kwargs['ta_id']}) + + def get_initial(self): + return {'ta': self.kwargs['ta_id']} + + +class PublicacaoDetailView(CompMixin, DetailView): + model = Publicacao + + +class PublicacaoUpdateView(CompMixin, UpdateView): + model = Publicacao + form_class = PublicacaoForm + template_name = "crud/form.html" + + def get(self, request, *args, **kwargs): + self.object = self.get_object() + form = self.get_form() + # if self.object and self.object.content_object: + # form.fields['tipo_ta'].required = False + # form.fields['tipo_ta'].widget.attrs['disabled'] = 'disabled' + return self.render_to_response(self.get_context_data(form=form)) + + def get_success_url(self): + return reverse_lazy('compilacao:ta_pub_detail', + kwargs={ + 'pk': self.object.id, + 'ta_id': self.kwargs['ta_id']}) + + @property + def cancel_url(self): + return self.get_success_url() + + +class PublicacaoDeleteView(CompMixin, DeleteView): + model = Publicacao + template_name = "crud/confirm_delete.html" + + @property + def detail_url(self): + return reverse_lazy('compilacao:ta_pub_detail', + kwargs={ + 'pk': self.object.id, + 'ta_id': self.kwargs['ta_id']}) + + def get_success_url(self): + return reverse_lazy('compilacao:ta_pub_list', + kwargs={'ta_id': self.kwargs['ta_id']}) + + class TextView(ListView, CompMixin): template_name = 'compilacao/text_list.html' @@ -617,7 +880,6 @@ class TextEditView(ListView, CompMixin): a.tipo_dispositivo = td a.inicio_vigencia = ta.data a.inicio_eficacia = ta.data - a.timestamp = datetime.now() a.save() td = TipoDispositivo.objects.filter(class_css='ementa')[0] @@ -630,7 +892,6 @@ class TextEditView(ListView, CompMixin): e.tipo_dispositivo = td e.inicio_vigencia = ta.data e.inicio_eficacia = ta.data - e.timestamp = datetime.now() e.texto = ta.ementa e.dispositivo_pai = a e.save() @@ -640,7 +901,6 @@ class TextEditView(ListView, CompMixin): a.ordem = e.ordem + Dispositivo.INTERVALO_ORDEM a.ordem_bloco_atualizador = 0 a.set_numero_completo([2, 0, 0, 0, 0, 0, ]) - a.timestamp = datetime.now() a.save() result = Dispositivo.objects.filter( @@ -1018,6 +1278,7 @@ class ActionsEditMixin: return JsonResponse(action(context), safe=False) def set_dvt(self, context): + # Dispositivo de Vigência do Texto Original e de Dpts Alterados dvt = Dispositivo.objects.get(pk=context['dispositivo_id']) if dvt.is_relative_auto_insert(): @@ -1025,15 +1286,28 @@ class ActionsEditMixin: try: Dispositivo.objects.filter( - ta=dvt.ta, - ta_publicado__isnull=True).update( - dispositivo_vigencia=dvt, - inicio_vigencia=dvt.inicio_vigencia) - - Dispositivo.objects.filter( - ta_publicado=dvt.ta).update( + (Q(ta=dvt.ta) & Q(ta_publicado__isnull=True)) | + Q(ta_publicado=dvt.ta) + ).update( dispositivo_vigencia=dvt, - inicio_vigencia=dvt.inicio_vigencia) + inicio_vigencia=dvt.inicio_vigencia, + inicio_eficacia=dvt.inicio_eficacia) + + dps = Dispositivo.objects.filter(dispositivo_vigencia_id=dvt.pk, + ta_publicado_id=dvt.ta_id) + + for d in dps: + if d.dispositivo_substituido: + ds = d.dispositivo_substituido + ds.fim_vigencia = d.inicio_vigencia - timedelta(days=1) + ds.fim_eficacia = d.inicio_eficacia - timedelta(days=1) + ds.save() + + if d.dispositivo_subsequente: + ds = d.dispositivo_subsequente + d.fim_vigencia = ds.inicio_vigencia - timedelta(days=1) + d.fim_eficacia = ds.inicio_eficacia - timedelta(days=1) + d.save() return {'message': str(_('Dispositivo de Vigência atualizado ' 'com sucesso!!!'))} @@ -1723,172 +1997,80 @@ class ActionsEditView(ActionsEditMixin, TemplateView): return self.render_to_json_response(context, **response_kwargs) -class DispositivoSuccessUrlMixin: +class DispositivoEdicaoBasicaView(FormMessagesMixin, UpdateView): + model = Dispositivo + template_name = 'compilacao/dispositivo_form_edicao_basica.html' + form_class = DispositivoEdicaoBasicaForm + form_valid_message = _('Alterações no Dispositivo realizadas com sucesso!') + form_invalid_message = _('Houve erro em registrar ' + 'as alterações no Dispositivo') - def get_success_url(self): + @property + def cancel_url(self): return reverse_lazy( - 'compilacao:dispositivo', kwargs={ - 'ta_id': self.kwargs[ - 'ta_id'], - 'dispositivo_id': self.kwargs[ - 'dispositivo_id']}) - - -class NotaMixin(DispositivoSuccessUrlMixin): - - def get_modelo_nota(self, request): - if 'action' in request.GET and request.GET['action'] == 'modelo_nota': - tn = TipoNota.objects.get(pk=request.GET['id_tipo']) - return True, tn.modelo - return False, '' - - def get_initial(self): - dispositivo = get_object_or_404( - Dispositivo, pk=self.kwargs.get('dispositivo_id')) - initial = {'dispositivo': dispositivo} - - if 'pk' in self.kwargs: - initial['pk'] = self.kwargs.get('pk') - - return initial - - @method_decorator(login_required) - def dispatch(self, *args, **kwargs): - return super(NotaMixin, self).dispatch(*args, **kwargs) - - -class NotasCreateView(NotaMixin, CreateView): - template_name = 'compilacao/ajax_form.html' - form_class = NotaForm - - def get(self, request, *args, **kwargs): - flag_action, modelo_nota = self.get_modelo_nota(request) - if flag_action: - return HttpResponse(modelo_nota) - - return super(NotasCreateView, self).get(request, *args, **kwargs) - - def post(self, request, *args, **kwargs): - self.object = None - try: - ta_id = kwargs.pop('ta_id') - dispositivo_id = kwargs.pop('dispositivo_id') - form = NotaForm(request.POST, request.FILES, **kwargs) - kwargs['ta_id'] = ta_id - kwargs['dispositivo_id'] = dispositivo_id - - if form.is_valid(): - nt = form.save(commit=False) - nt.owner_id = request.user.pk - nt.save() - self.kwargs['pk'] = nt.pk - return self.form_valid(form) - else: - return self.form_invalid(form) - except Exception as e: - print(e) - return HttpResponse("error post") - - -class NotasEditView(NotaMixin, UpdateView): - model = Nota - template_name = 'compilacao/ajax_form.html' - form_class = NotaForm - - def get(self, request, *args, **kwargs): - flag_action, modelo_nota = self.get_modelo_nota(request) - if flag_action: - return HttpResponse(modelo_nota) - - return super(NotasEditView, self).get(request, *args, **kwargs) - - -class NotasDeleteView(NotaMixin, TemplateView): - - def get(self, request, *args, **kwargs): - nt = Nota.objects.get(pk=self.kwargs['pk']) - nt.delete() - return HttpResponseRedirect(self.get_success_url()) - - -class VideMixin(DispositivoSuccessUrlMixin): - - def get_initial(self): - dispositivo_base = get_object_or_404( - Dispositivo, pk=self.kwargs.get('dispositivo_id')) - - initial = {'dispositivo_base': dispositivo_base} - - if 'pk' in self.kwargs: - initial['pk'] = self.kwargs.get('pk') - - return initial - - @method_decorator(login_required) - def dispatch(self, *args, **kwargs): - return super(VideMixin, self).dispatch(*args, **kwargs) - - -def choice_model_type_foreignkey_in_extenal_views(id_tipo_ta=None): - yield None, '-------------' - - if not id_tipo_ta: - return - - tipo_ta = TipoTextoArticulado.objects.get(pk=id_tipo_ta) - - integrations_view_names = get_integrations_view_names() - for item in integrations_view_names: - if hasattr(item, 'model_type_foreignkey'): - if (tipo_ta.content_type.model == item.model.__name__.lower() and - tipo_ta.content_type.app_label == - item.model._meta.app_label): - for i in item.model_type_foreignkey.objects.all(): - yield i.pk, i - - -class DispositivoSearchMixin: + 'compilacao:ta_text_edit', + kwargs={'ta_id': self.kwargs['ta_id']}) + '#' + str(self.object.pk) - def get_form_kwargs(self): + def get_success_url(self): + return reverse_lazy( + 'compilacao:dispositivo_edit', + kwargs={'ta_id': self.kwargs['ta_id'], 'pk': self.kwargs['pk']}) - kwargs = super(DispositivoSearchMixin, self).get_form_kwargs() + def get_url_this_view(self): + return 'compilacao:dispositivo_edit' - if 'choice_model_type_foreignkey_in_extenal_views' not in kwargs: - kwargs.update({ - 'choice_model_type_foreignkey_in_extenal_views': - choice_model_type_foreignkey_in_extenal_views - }) + def run_actions(self, request): + if 'action' in request.GET and\ + request.GET['action'] == 'atualiza_rotulo': + try: + d = Dispositivo.objects.get(pk=self.kwargs['pk']) + d.dispositivo0 = int(request.GET['dispositivo0']) + d.dispositivo1 = int(request.GET['dispositivo1']) + d.dispositivo2 = int(request.GET['dispositivo2']) + d.dispositivo3 = int(request.GET['dispositivo3']) + d.dispositivo4 = int(request.GET['dispositivo4']) + d.dispositivo5 = int(request.GET['dispositivo5']) + d.rotulo = d.rotulo_padrao() - return kwargs + numero = d.get_numero_completo()[1:] + zerar = False + for i in range(len(numero)): + if not numero[i]: + zerar = True -class VideCreateView(VideMixin, DispositivoSearchMixin, CreateView): - model = Vide - template_name = 'compilacao/ajax_form.html' - form_class = VideForm + if zerar: + numero[i] = 0 - def get(self, request, *args, **kwargs): - self.object = None - form = self.get_form() - return self.render_to_response(self.get_context_data(form=form)) + 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, + 'dispositivo0': d.dispositivo0, + 'dispositivo1': d.dispositivo1, + 'dispositivo2': d.dispositivo2, + 'dispositivo3': d.dispositivo3, + 'dispositivo4': d.dispositivo4, + 'dispositivo5': d.dispositivo5}, safe=False) -class VideEditView(VideMixin, UpdateView): - model = Vide - template_name = 'compilacao/ajax_form.html' - form_class = VideForm + return False, '' + def get(self, request, *args, **kwargs): -class VideDeleteView(VideMixin, TemplateView): + flag_action, render_json_response = self.run_actions(request) + if flag_action: + return render_json_response - def get(self, request, *args, **kwargs): - vd = Vide.objects.get(pk=self.kwargs['pk']) - vd.delete() - return HttpResponseRedirect(self.get_success_url()) + return UpdateView.get(self, request, *args, **kwargs) class DispositivoSearchFragmentFormView(ListView): - template_name = 'compilacao/dispositivo_search_fragment_form.html' + template_name = 'compilacao/dispositivo_form_search_fragment.html' def get(self, request, *args, **kwargs): @@ -1908,16 +2090,18 @@ class DispositivoSearchFragmentFormView(ListView): def get_queryset(self): try: + n = 10 + q = Q(nivel__gt=0) if 'initial_ref' in self.request.GET: initial_ref = self.request.GET['initial_ref'] if initial_ref: - q = Q(pk=initial_ref) + q = q & Q(pk=initial_ref) result = Dispositivo.objects.filter(q).select_related( 'ta').exclude( tipo_dispositivo__dispositivo_de_alteracao=True) - return result + return result[:n] texto = '' rotulo = '' @@ -1925,9 +2109,7 @@ class DispositivoSearchFragmentFormView(ListView): if 'texto' in self.request.GET: texto = self.request.GET['texto'] - q = Q(nivel__gt=0) texto = texto.split(' ') - n = 10 if 'rotulo' in self.request.GET: rotulo = self.request.GET['rotulo'] @@ -2023,220 +2205,84 @@ class DispositivoSearchFragmentFormView(ListView): print(e) -class PublicacaoListView(ListView): - model = Publicacao - verbose_name = model._meta.verbose_name - - @property - def title(self): - return _('%s de %s' % ( - self.model._meta.verbose_name_plural, - self.ta)) - - @property - def ta(self): - ta = TextoArticulado.objects.get(pk=self.kwargs['ta_id']) - return ta - - @property - def create_url(self): - return reverse_lazy( - 'compilacao:ta_pub_create', - kwargs={'ta_id': self.kwargs['ta_id']}) - - def get_queryset(self): - pubs = Publicacao.objects.filter(ta_id=self.kwargs['ta_id']) - return pubs - - def get_context_data(self, **kwargs): - context = super(PublicacaoListView, self).get_context_data(**kwargs) - context['NO_ENTRIES_MSG'] = CrudListView.no_entries_msg - return context - +class DispositivoSearchModalView(FormView): + template_name = 'compilacao/dispositivo_form_search.html' + form_class = DispositivoSearchModalForm -class PublicacaoCreateView(FormMessagesMixin, CreateView): - model = Publicacao - form_class = PublicacaoForm - template_name = "crud/form.html" - form_valid_message = _('Registro criado com sucesso!') - form_invalid_message = _('O registro não foi criado.') - def get_success_url(self): - return reverse_lazy( - 'compilacao:ta_pub_detail', - kwargs={ - 'pk': self.object.id, - 'ta_id': self.kwargs['ta_id']}) +class DispositivoEdicaoVigenciaView(FormMessagesMixin, UpdateView): + model = Dispositivo + template_name = 'compilacao/dispositivo_form_vigencia.html' + form_class = DispositivoEdicaoVigenciaForm + form_valid_message = _('Alterações no Dispositivo realizadas com sucesso!') + form_invalid_message = _('Houve erro em registrar ' + 'as alterações no Dispositivo') @property def cancel_url(self): return reverse_lazy( - 'compilacao:ta_pub_list', - kwargs={'ta_id': self.kwargs['ta_id']}) - - def get_initial(self): - return {'ta': self.kwargs['ta_id']} - - -class PublicacaoDetailView(CompMixin, DetailView): - model = Publicacao - - -class PublicacaoUpdateView(CompMixin, UpdateView): - model = Publicacao - form_class = PublicacaoForm - template_name = "crud/form.html" - - def get(self, request, *args, **kwargs): - self.object = self.get_object() - form = self.get_form() - # if self.object and self.object.content_object: - # form.fields['tipo_ta'].required = False - # form.fields['tipo_ta'].widget.attrs['disabled'] = 'disabled' - return self.render_to_response(self.get_context_data(form=form)) - - def get_success_url(self): - return reverse_lazy('compilacao:ta_pub_detail', - kwargs={ - 'pk': self.object.id, - 'ta_id': self.kwargs['ta_id']}) - - @property - def cancel_url(self): - return self.get_success_url() - - -class PublicacaoDeleteView(CompMixin, DeleteView): - model = Publicacao - template_name = "crud/confirm_delete.html" + 'compilacao:ta_text_edit', + kwargs={'ta_id': self.kwargs['ta_id']}) + '#' + str(self.object.pk) - @property - def detail_url(self): - return reverse_lazy('compilacao:ta_pub_detail', - kwargs={ - 'pk': self.object.id, - 'ta_id': self.kwargs['ta_id']}) + def get_url_this_view(self): + return 'compilacao:dispositivo_edit_vigencia' def get_success_url(self): - return reverse_lazy('compilacao:ta_pub_list', - kwargs={'ta_id': self.kwargs['ta_id']}) + return reverse_lazy( + 'compilacao:dispositivo_edit_vigencia', + kwargs={'ta_id': self.kwargs['ta_id'], 'pk': self.kwargs['pk']}) -class DispositivoEdicaoBasicaView(FormMessagesMixin, UpdateView): +class DispositivoDefinidorVigenciaView(FormMessagesMixin, FormView): model = Dispositivo - form_class = DispositivoEdicaoBasicaForm + template_name = 'compilacao/dispositivo_form_definidor_vigencia.html' + form_class = DispositivoDefinidorVigenciaForm form_valid_message = _('Alterações no Dispositivo realizadas com sucesso!') form_invalid_message = _('Houve erro em registrar ' 'as alterações no Dispositivo') + def get_form_kwargs(self): + kwargs = FormView.get_form_kwargs(self) + kwargs.update({ + 'pk': self.kwargs['pk'], + }) + return kwargs + @property def cancel_url(self): return reverse_lazy( 'compilacao:ta_text_edit', kwargs={'ta_id': self.kwargs['ta_id']}) + '#' + str(self.object.pk) - def get_success_url(self): - return reverse_lazy( - 'compilacao:dispositivo_edit', - kwargs={'ta_id': self.kwargs['ta_id'], 'pk': self.kwargs['pk']}) - - def get_url_this_view(self): - return 'compilacao:dispositivo_edit' - - def run_actions(self, request): - if 'action' in request.GET and\ - request.GET['action'] == 'atualiza_rotulo': - try: - d = Dispositivo.objects.get(pk=self.kwargs['pk']) - d.dispositivo0 = int(request.GET['dispositivo0']) - d.dispositivo1 = int(request.GET['dispositivo1']) - d.dispositivo2 = int(request.GET['dispositivo2']) - d.dispositivo3 = int(request.GET['dispositivo3']) - 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, - 'dispositivo0': d.dispositivo0, - 'dispositivo1': d.dispositivo1, - 'dispositivo2': d.dispositivo2, - 'dispositivo3': d.dispositivo3, - 'dispositivo4': d.dispositivo4, - 'dispositivo5': d.dispositivo5}, safe=False) - - return False, '' - - def get(self, request, *args, **kwargs): - - flag_action, render_json_response = self.run_actions(request) - if flag_action: - return render_json_response - - return UpdateView.get(self, request, *args, **kwargs) - - -class DispositivoEdicaoVigenciaView( - DispositivoSearchMixin, DispositivoEdicaoBasicaView): - model = Dispositivo - form_class = DispositivoEdicaoVigenciaForm - def get_url_this_view(self): - return 'compilacao:dispositivo_edit_vigencia' + return 'compilacao:dispositivo_edit_definidor_vigencia' def get_success_url(self): return reverse_lazy( - 'compilacao:dispositivo_edit_vigencia', + 'compilacao:dispositivo_edit_definidor_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, '' - - def get_initial(self): - - ta = self.object.ta_publicado if self.object.ta_publicado else\ - self.object.ta + def get(self, request, *args, **kwargs): + self.object = get_object_or_404(Dispositivo, pk=kwargs['pk']) + return FormView.get(self, request, *args, **kwargs) - initial = { - 'ano_ta': ta.ano, - 'num_ta': ta.numero, - 'tipo_ta': ta.tipo_ta, - } - if hasattr(ta, 'content_object') and\ - ta.content_object: - lista_tipos = list(choice_model_type_foreignkey_in_extenal_views( - id_tipo_ta=ta.tipo_ta_id)) + def get_context_data(self, **kwargs): + context = FormView.get_context_data(self, **kwargs) + context.update({'object': self.object}) + return context - content_object = model_to_dict(ta.content_object) + def post(self, request, *args, **kwargs): + self.object = get_object_or_404(Dispositivo, pk=kwargs['pk']) - for key, value in content_object.items(): - for item in lista_tipos: - if getattr(ta.content_object, key) == item[1]: - initial['tipo_model'] = item[0] + form = self.get_form() + if form.is_valid(): + dvs = form.cleaned_data['dispositivo_vigencia'] + with transaction.atomic(): + self.object.dispositivos_vigencias_set.clear() + for item in dvs: + d = Dispositivo.objects.get(pk=item) + self.object.dispositivos_vigencias_set.add(d) - return initial + return self.form_valid(form) + else: + return self.form_invalid(form) diff --git a/static/js/compilacao.js b/static/js/compilacao.js index b6d2242f4..0a7f2aa3a 100644 --- a/static/js/compilacao.js +++ b/static/js/compilacao.js @@ -34,18 +34,14 @@ var configFormSearchTA = function(container, _tipo_form, _tipo_select) { $(container+" select[name='tipo_ta']").change(function(event) { var url = ''; url = '/ta/search_fragment_form?action=get_tipos&tipo_ta='+this.value; - $(container+" label[for='id_tipo_model']").html('Tipos de ' + this.children[this.selectedIndex].innerHTML); - var select = $(container+" select[name='tipo_model']"); select.empty(); $('Carregando...').appendTo(select); $.get(url).done(function( data ) { select.empty(); - - for(var item in data) { for (var i in data[item]) select.append($("").attr('value',i).text(data[item][i])); @@ -57,6 +53,7 @@ var configFormSearchTA = function(container, _tipo_form, _tipo_select) { $(container+" input[name='num_ta'], " + container+" input[name='ano_ta'], " + container+" select[name='tipo_model'], " + + container+" input[name='dispositivos_internos'], " + container+" input[name='texto_dispositivo'], " + container+" input[name='rotulo_dispositivo']" ).change(onChangeParamTA); @@ -64,42 +61,166 @@ var configFormSearchTA = function(container, _tipo_form, _tipo_select) { $(container+" .btn-busca").click(onChangeParamTA); } -var onChangeParamTA = function(event) { - var tipo_ta = $("select[name='tipo_ta']").val(); - var tipo_model = $("select[name='tipo_model']").val(); - var num_ta = $("input[name='num_ta']").val(); - var ano_ta = $("input[name='ano_ta']").val(); - var rotulo_dispositivo = $("input[name='rotulo_dispositivo']").val(); - var texto_dispositivo = $("input[name='texto_dispositivo']").val(); - var dispositivo_ref = $("#id_dispositivo_ref").val(); - var dispositivo_select_ref = null; - $('#id_dispositivo_ref').remove(); - - if (dispositivo_ref == null) - dispositivo_select_ref = $("input[name='dispositivo_ref']:checked").val() - - var url = ''; - - var formData = { - 'tipo_ta' : tipo_ta, - 'tipo_model' : tipo_model, - 'num_ta' : num_ta, - 'ano_ta' : ano_ta, - 'texto' : texto_dispositivo, - 'rotulo' : rotulo_dispositivo, - 'tipo_form' : tipo_form, - 'tipo_select' : tipo_select, - 'initial_ref' : dispositivo_ref - }; - - url = '/ta/search_fragment_form'; - $('.result-busca-dispositivo').html(''); - insertWaitAjax('.result-busca-dispositivo') - $.get(url, formData).done(function( data ) { - $('.result-busca-dispositivo').html(data); - if (dispositivo_ref != null) - $("input[name='dispositivo_ref']").filter('[value="'+dispositivo_ref+'"]').prop('checked', true); - else if (dispositivo_select_ref != null) - $("input[name='dispositivo_ref']").filter('[value="'+dispositivo_select_ref+'"]').prop('checked', true); + + +function DispostivoSearch(opts) { + + $(function() { + + var container_ds = $('body').children("#container_ds"); + if (container_ds.length > 0) + $(container_ds).remove(); + container_ds = $(''); + $('body').prepend(container_ds); + + var fields = $("[data-sapl-ta='DispositivoSearch']"); + fields.each(function() { + var field = $(this); + var data_type_selection = field.attr('data-type-selection'); + var data_field = field.attr('data-field'); + + var onChangeFieldSelects = function(event) { + var selecionados = field.find('input'); + selecionados.off() + + if (data_type_selection == 'checkbox') { + selecionados.on('change', function(event) { + if (!this.checked) { + if ($(this).closest('ul').find('li').length == 2) + $(this).closest('ul').remove(); + else + $(this).closest('li').remove(); + } + }); + } + else { + selecionados.attr('type', 'hidden'); + $('') + .insertBefore(selecionados) + .append($('')) + .on('click', function() { + if ($(this).closest('ul').find('li').length == 2) + $(this).closest('ul').remove(); + else + $(this).closest('li').remove(); + }); + } + } + onChangeFieldSelects(); + + var onChangeParamTA = function(event) { + var tipo_ta = $("select[name='tipo_ta']").val(); + var tipo_model = $("select[name='tipo_model']").val(); + var num_ta = $("input[name='num_ta']").val(); + var ano_ta = $("input[name='ano_ta']").val(); + var dispositivos_internos = $("input[name='dispositivos_internos']:checked").val(); + var rotulo_dispositivo = $("input[name='rotulo_dispositivo']").val(); + var texto_dispositivo = $("input[name='texto_dispositivo']").val(); + var url = ''; + var formData = { + 'tipo_ta' : tipo_ta, + 'tipo_model' : tipo_model, + 'num_ta' : num_ta, + 'ano_ta' : ano_ta, + 'texto' : texto_dispositivo, + 'rotulo' : rotulo_dispositivo, + 'dispositivos_internos' : dispositivos_internos, + 'data_type_selection' : data_type_selection, + 'data_field' : data_field, + }; + + url = '/ta/search_fragment_form'; + $('.result-busca-dispositivo').html(''); + insertWaitAjax('.result-busca-dispositivo') + $.get(url, formData).done(function( data ) { + $('.result-busca-dispositivo').html(data); + }); + } + + var button_ds = field.children("#button_ds"); + if (button_ds.length > 0) + $(button_ds).remove(); + button_ds = $(''); + field.prepend(button_ds); + + var btn_open_search = $('') + .text(opts['text_button']) + .attr('type','button') + .attr('class','btn btn-sm btn-modal-open'); + button_ds.append(btn_open_search); + btn_open_search.on('click', function() { + $.get(opts['url_form'], function(data) { + container_ds.html(data); + var modal_ds = $('#modal-ds'); + + modal_ds.find("select[name='tipo_ta']").change(function(event) { + var url = ''; + url = '/ta/search_fragment_form?action=get_tipos&tipo_ta='+this.value; + modal_ds.find("label[for='id_tipo_model']").html('Tipos de ' + this.children[this.selectedIndex].innerHTML); + + var select = modal_ds.find("select[name='tipo_model']"); + select.empty(); + $('Carregando...').appendTo(select); + + $.get(url).done(function( data ) { + select.empty(); + for(var item in data) { + for (var i in data[item]) + select.append($("").attr('value',i).text(data[item][i])); + } + select.change(onChangeParamTA) + }); + }); + + modal_ds.find("input[name='num_ta'], " + +"input[name='ano_ta'], " + +"select[name='tipo_model'], " + +"input[name='texto_dispositivo'], " + +"input[name='dispositivos_internos'], " + +"input[name='rotulo_dispositivo']" + ).change(onChangeParamTA); + + modal_ds.find(".btn-busca").click(onChangeParamTA); + + modal_ds.find("#btn-modal-select").click(function() { + // limpar selecionados se o tipo é radio + var listas = field.find('ul'); + if (data_type_selection == 'radio') + listas.remove(); + + // adicionar itens selecionados na caixa modal + var selecionados = modal_ds.find('[name="'+data_field+'"]:checked'); + + // com base nos selecionados, limpa seus ta's removendo os não selecionados + selecionados.closest('ul').find('input:not(:checked)').closest('li').remove(); + + selecionados.closest('ul').each(function() { + //insere na lista de selecionados os ta's não presentes + var ul_lista = field.find('#'+this.id); + if (ul_lista.length == 0) { + field.append(this); + return; + } + + //insere os dispositivos não presentes + var inputs_for_this = $(this).find('input'); + + inputs_for_this.each(function() { + if (ul_lista.find("#"+this.id).length > 0) + return; + ul_lista.append($(this).closest('li')); + }); + }); + + onChangeFieldSelects(); + + modal_ds.modal('hide'); + }); + + modal_ds.modal('show'); + onChangeParamTA(); + }) + }); + }); }); } diff --git a/static/js/compilacao_edit.js b/static/js/compilacao_edit.js index 51b7b8cee..8d842c0b2 100644 --- a/static/js/compilacao_edit.js +++ b/static/js/compilacao_edit.js @@ -1,19 +1,3 @@ -function initTinymceForEdit() { - - tinymce.init({ - mode : "textareas", - force_br_newlines : false, - force_p_newlines : false, - forced_root_block : '', - plugins: ["table save code"], - menubar: "edit format table tools", - toolbar: "save | undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent", - tools: "inserttable", - save_onsavecallback: onSubmitEditForm, - border_css: "/static/styles/compilacao_tinymce.css", - content_css: "/static/styles/compilacao_tinymce.css" - }); -} var editortype = "textarea"; var gets = 0; @@ -162,7 +146,7 @@ var clickUpdateDispositivo = function(event, __pk_refresh, __pk_edit, __action, } if ( _editortype == 'tinymce' ) { - initTinymceForEdit(); + initTinymce(); } else if (_editortype == 'textarea') { $('.csform form').submit(onSubmitEditForm); diff --git a/static/styles/compilacao.scss b/static/styles/compilacao.scss index d907e9828..78eb35b54 100644 --- a/static/styles/compilacao.scss +++ b/static/styles/compilacao.scss @@ -175,9 +175,8 @@ a:link:after, a:visited:after { transition: all 0.2s ease-in-out; position: relative; - .ementa { - padding: 4em 0em 3em 35%; + padding: 2em 0em 2em 35%; font-weight: bold; } @@ -976,28 +975,40 @@ a:link:after, a:visited:after { } } -.result-busca-dispositivo { - ul{ +.result-busca-dispositivo, .lista-dispositvo { + + padding: 0 0 1em; + min-height: 3em; + ul { list-style: none; - display: table; - margin-left: 0; - border-collapse:separate; - border-spacing:1px; - padding: 0px; + margin: 0; + padding: 1em 0 0; + transition: all 2s linear; + clear: both; li { - display: table-row; + display: table; - &:nth-child(even) { - background-color: rgba(0, 0, 0, 0.05); + border-collapse:separate; + border-bottom: 1px solid white; + &.ta_title { + padding: 0.15em 0.7em; + background-color: rgba(0, 0, 0, 0.15); + display:block; + border-radius: 4px 4px 0 0; + } + &:last-child .itemlabel { + border-radius: 0 0 4px 0px; } - &:nth-child(odd) { - background-color: rgba(0, 0, 0, 0.08); + &:last-child .iteminput { + border-radius: 0 0 0px 4px; } .iteminput { + background-color: rgba(0, 0, 0, 0.1); + border-right: 1px solid white; display: table-cell; padding: 0.5em; vertical-align: middle; @@ -1009,6 +1020,7 @@ a:link:after, a:visited:after { } .itemlabel { + background-color: rgba(0, 0, 0, 0.1); display: table-cell; padding: 0.5em; vertical-align: middle; @@ -1016,19 +1028,15 @@ a:link:after, a:visited:after { label { line-height: 1; font-family: "SourceSansPro", Helvetica, Arial, sans-serif; + display: block; } } } } - .ta_title { - padding: 0.15em 0.7em; - background-color: rgba(0, 0, 0, 0.15); - margin: 0.1em 0.08em 0 1px; - } .nomenclatura_heranca { font-size: 90%; color: #057dba; - display: block; + display: inline; } } .cp-nav-parents { @@ -1050,6 +1058,9 @@ a:link:after, a:visited:after { } } +.btn-modal-open { + float: right; +} .class_color_container { diff --git a/templates/compilacao/dispositivo_form.html b/templates/compilacao/dispositivo_form.html index 0d585ac59..9cbe7f2e1 100644 --- a/templates/compilacao/dispositivo_form.html +++ b/templates/compilacao/dispositivo_form.html @@ -1,8 +1,5 @@ {% extends "base.html" %} -{% load i18n crispy_forms_tags %} -{% load compilacao_filters %} -{% load staticfiles %} -{% load sass_tags %} +{% load i18n crispy_forms_tags compilacao_filters staticfiles sass_tags %} {% block head_content %}{{block.super}} @@ -11,13 +8,14 @@ {% url 'compilacao:dispositivo_edit' object.ta_id object.pk as edit_url%} {% url 'compilacao:dispositivo_edit_vigencia' object.ta_id object.pk as edit_vigencia_url %} + {% url 'compilacao:dispositivo_edit_definidor_vigencia' object.ta_id object.pk as edit_definidor_vigencia_url %} {% trans 'Dados Básicos' %} {% trans 'Vigência' %} - {% trans 'Dispositivo Alterado' %} - {% trans 'Dispositivo Alterador' %} - {% trans 'Dispositivo de Vigência' %} + {% trans 'Alteração' %} + {% trans 'Alterador' %} + {% trans 'Definidor de Vigência' %} -{% endblock sections_nav %} +{% endblock sections_nav %}{% trans '' %} {% block title %} {{object.ta}}{% trans 'Edição de Dispositivo' %} @@ -40,68 +38,4 @@ {% block extra_js %} - {% endblock %} diff --git a/templates/compilacao/dispositivo_form_definidor_vigencia.html b/templates/compilacao/dispositivo_form_definidor_vigencia.html new file mode 100644 index 000000000..c45bc8387 --- /dev/null +++ b/templates/compilacao/dispositivo_form_definidor_vigencia.html @@ -0,0 +1,11 @@ +{% extends "compilacao/dispositivo_form.html" %} +{% load i18n %} + +{% block extra_js %}{{block.super}} + +{% endblock %} diff --git a/templates/compilacao/dispositivo_form_edicao_basica.html b/templates/compilacao/dispositivo_form_edicao_basica.html new file mode 100644 index 000000000..73f376d4e --- /dev/null +++ b/templates/compilacao/dispositivo_form_edicao_basica.html @@ -0,0 +1,42 @@ +{% extends "compilacao/dispositivo_form.html" %} +{% load i18n %} + +{% block extra_js %}{{block.super}} + + +{% endblock %} diff --git a/templates/compilacao/dispositivo_form_parents.html b/templates/compilacao/dispositivo_form_parents.html index 09d1c2cf1..c2f5f3e34 100644 --- a/templates/compilacao/dispositivo_form_parents.html +++ b/templates/compilacao/dispositivo_form_parents.html @@ -1,5 +1,4 @@ -{% load i18n %} -{% load compilacao_filters %} +{% load i18n compilacao_filters %} {% if not node.dispositivos_filhos_set.exists %} @@ -17,9 +16,13 @@ {%for parent in node.dispositivos_filhos_set.all %} - {{parent|nomenclatura}} + {{parent|nomenclatura}} {% if parent.dispositivo_subsequente_id %}({% trans "Alterado" %}){% endif %} + {%endfor %} + + + diff --git a/templates/compilacao/dispositivo_form_search.html b/templates/compilacao/dispositivo_form_search.html new file mode 100644 index 000000000..4a7732446 --- /dev/null +++ b/templates/compilacao/dispositivo_form_search.html @@ -0,0 +1,19 @@ +{% load i18n crispy_forms_tags %} + + + + + + × + {% trans "Selecionar Dispositivo(s)" %} + + + {% crispy form form.helper%} + + + + + diff --git a/templates/compilacao/dispositivo_form_search_fragment.html b/templates/compilacao/dispositivo_form_search_fragment.html new file mode 100644 index 000000000..f32a89482 --- /dev/null +++ b/templates/compilacao/dispositivo_form_search_fragment.html @@ -0,0 +1,75 @@ +{% load i18n compilacao_filters %} + +{% if object_list.count >= 100 %} + + {% trans 'Use argumentos para simplificar listagem...' %} + +{% endif %} + +{% for dpt in object_list %} + {% ifchanged dpt.ta%} + {% if not forloop.first %}{% endif %} + + {{dpt.ta}} + {% endifchanged %} + + + + + + + {% if dpt.nivel > 1 %} + {% trans "Herança:" %} {% nomenclatura_heranca dpt 1 1 %} + {% endif %} + + + {{ dpt.tipo_dispositivo.rotulo_prefixo_html|safe }} + {% if dpt.rotulo or dpt.nivel = 1 %}{{ dpt.rotulo }}{%else%}[{{ dpt|nomenclatura}} {% trans "de" %} {{ dpt.dispositivo_pai.rotulo }}] - {% endif %} + {{ dpt.tipo_dispositivo.rotulo_sufixo_html|safe }} + {{ dpt.tipo_dispositivo.texto_prefixo_html|safe }}{%if dpt.texto %}{{ dpt.texto|safe }}{%else%}{%if not dpt.tipo_dispositivo.dispositivo_de_articulacao %} {% endif %}{% endif %} + {% if dpt.ta_publicado_id and not dpt.tipo_dispositivo.dispositivo_de_articulacao %} + + {{ dpt.tipo_dispositivo.nota_automatica_prefixo_html|safe }} + {% nota_automatica dpt ta_pub_list %} + {{ dpt.tipo_dispositivo.nota_automatica_sufixo_html|safe }} + + {% endif %} + + + + + + {% if request.GET.dispositivos_internos == 'True' %} + {% for df in dpt.dispositivos_filhos_set.all %} + {% if df not in object_list %} + + + + + + {% if df.nivel > 1 %} + {% trans "Herança:" %} {% nomenclatura_heranca df 1 1 %} + {% endif %} + + + + {{ df.tipo_dispositivo.rotulo_prefixo_html|safe }} + {% if df.rotulo or df.nivel = 1%}{{ df.rotulo }}{%else%}[{{ df|nomenclatura}} {% trans "de" %} {{ df.dispositivo_pai.rotulo }}] - {% endif %} + {{ df.tipo_dispositivo.rotulo_sufixo_html|safe }} + {{ df.tipo_dispositivo.texto_prefixo_html|safe }}{%if df.texto %}{{ df.texto|safe }}{%else%}{%if not df.tipo_dispositivo.dispositivo_de_articulacao %} {% endif %}{% endif %} + {% if df.ta_publicado_id and not df.tipo_dispositivo.dispositivo_de_articulacao %} + + {{ df.tipo_dispositivo.nota_automatica_prefixo_html|safe }} + {% nota_automatica df ta_pub_list %} + {{ df.tipo_dispositivo.nota_automatica_sufixo_html|safe }} + + {% endif %} + + + + + {% endif %} + {% endfor %} + {% endif %} + {% if forloop.last %}{% endif %} +{% endfor %} diff --git a/templates/compilacao/dispositivo_form_vigencia.html b/templates/compilacao/dispositivo_form_vigencia.html new file mode 100644 index 000000000..73ac5d95d --- /dev/null +++ b/templates/compilacao/dispositivo_form_vigencia.html @@ -0,0 +1,27 @@ +{% extends "compilacao/dispositivo_form.html" %} +{% load i18n %} +{% block extra_js %}{{block.super}} + +{% endblock %} diff --git a/templates/compilacao/dispositivo_search_fragment_form.html b/templates/compilacao/dispositivo_search_fragment_form.html deleted file mode 100644 index 501233d09..000000000 --- a/templates/compilacao/dispositivo_search_fragment_form.html +++ /dev/null @@ -1,48 +0,0 @@ -{% load i18n %} -{% load compilacao_filters %} - -{% if object_list.count >= 100 %} - - {% trans 'Use argumentos para simplificar listagem...' %} - -{% endif %} - -{% for dpt in object_list %} - {% ifchanged dpt.ta%} - {% if not forloop.first %}{% endif %} - {{dpt.ta}} - - {% endifchanged %} - {% if dpt.is_relative_auto_insert and dpt.dispositivo_pai.nivel != 0 %} - - - - - - {{dpt.dispositivo_pai.rotulo|safe}} - {{dpt.texto|safe}} - {% nomenclatura_heranca dpt 1 1 %} - - - {% elif not dpt.tipo_dispositivo.dispositivo_de_articulacao %} - - - - - - {{dpt.rotulo|safe}} - {{dpt.texto|safe}} - {% nomenclatura_heranca dpt 1 1 %} - - - {% elif dpt.tipo_dispositivo.dispositivo_de_articulacao%} - - - - - - {{dpt.rotulo|safe}} - {% if dpt.tipo_dispositivo.dispositivo_de_articulacao %}{{dpt.dispositivos_filhos_set.all.first.texto|safe}}{% else %}{{dpt.texto|safe}}{% endif %} - {% nomenclatura_heranca dpt 1 1 %} - - - {% endif%} - {% if forloop.last %}{% endif %} -{% endfor %} diff --git a/templates/compilacao/layout/dispositivo_checkbox.html b/templates/compilacao/layout/dispositivo_checkbox.html new file mode 100644 index 000000000..815c9fd2d --- /dev/null +++ b/templates/compilacao/layout/dispositivo_checkbox.html @@ -0,0 +1,49 @@ +{% load crispy_forms_filters %} +{% load i18n compilacao_filters common_tags%} + + + + {% include 'bootstrap/layout/field_errors_block.html' %} + + {% for choice in field.field.choices %} + + {% ifchanged choice.1.ta%} + {% if not forloop.first %}{% endif %} + + {{choice.1.ta}} + {% endifchanged %} + + + + + + + + + + + {{ choice.1.tipo_dispositivo.rotulo_prefixo_html|safe }} + {% if choice.1.rotulo %}{{ choice.1.rotulo }}{%else%}[{{ choice.1|nomenclatura}}{% if choice.1.dispositivo_pai %} {% trans "de" %} {{ choice.1.dispositivo_pai.rotulo }}{% endif %}] - {% endif %} + {{ choice.1.tipo_dispositivo.rotulo_sufixo_html|safe }} + {{ choice.1.tipo_dispositivo.texto_prefixo_html|safe }}{%if choice.1.texto %}{{ choice.1.texto|safe }}{%else%}{%if not choice.1.tipo_dispositivo.dispositivo_de_articulacao %} {% endif %}{% endif %} + {% if choice.1.ta_publicado_id and not choice.1.tipo_dispositivo.dispositivo_de_articulacao %} + + {{ choice.1.tipo_dispositivo.nota_automatica_prefixo_html|safe }} + {% nota_automatica choice.1 ta_pub_list %} + {{ choice.1.tipo_dispositivo.nota_automatica_sufixo_html|safe }} + + {% endif %} + + + + + + + + {% if forloop.last %}{% endif %} + {% endfor %} + + + + {% include 'bootstrap/layout/help_text.html' %} + diff --git a/templates/compilacao/layout/dispositivo_checkbox_old.html b/templates/compilacao/layout/dispositivo_checkbox_old.html new file mode 100644 index 000000000..ec994877d --- /dev/null +++ b/templates/compilacao/layout/dispositivo_checkbox_old.html @@ -0,0 +1,54 @@ +{% load crispy_forms_filters %} +{% load i18n compilacao_filters common_tags%} + + + + {% include 'bootstrap/layout/field_errors_block.html' %} + + + + + {% for choice, dpt in field.field.choices %} + {% ifchanged dpt.ta%} + {% if not forloop.first %}{% endif %} + + {{dpt.ta}} + {% endifchanged %} + {% if dpt.is_relative_auto_insert %} + + + + + + {{dpt.dispositivo_pai.rotulo|safe}} - {{dpt.texto|safe}} + {% nomenclatura_heranca dpt 1 1 %} + + + {% elif not dpt.tipo_dispositivo.dispositivo_de_articulacao and not dpt.is_relative_auto_insert %} + + + + + + {{dpt.rotulo|safe}} - {{dpt.texto|safe}} + {% nomenclatura_heranca dpt 1 1 %} + + + {% elif dpt.tipo_dispositivo.dispositivo_de_articulacao%} + + + + + + {{dpt.rotulo|safe}} - {% if dpt.tipo_dispositivo.dispositivo_de_articulacao %}{{dpt.dispositivos_filhos_set.all.first.texto|safe}}{% else %}{{dpt.texto|safe}}{% endif %} + {% nomenclatura_heranca dpt 1 1 %} + + + {% endif%} + {% if forloop.last %}{% endif %} + {% endfor %} + + + + {% include 'bootstrap/layout/help_text.html' %} + diff --git a/templates/compilacao/layout/dispositivo_radio.html b/templates/compilacao/layout/dispositivo_radio.html new file mode 100644 index 000000000..1192e86aa --- /dev/null +++ b/templates/compilacao/layout/dispositivo_radio.html @@ -0,0 +1,54 @@ +{% load crispy_forms_filters %} +{% load i18n compilacao_filters common_tags%} + + + + {% include 'bootstrap/layout/field_errors_block.html' %} + + + + + {% for choice, dpt in field.field.choices %} + {% ifchanged dpt.ta%} + {% if not forloop.first %}{% endif %} + + {{dpt.ta}} + {% endifchanged %} + {% if dpt.is_relative_auto_insert %} + + + + + + {{dpt.dispositivo_pai.rotulo|safe}} - {{dpt.texto|safe}} + {% nomenclatura_heranca dpt 1 1 %} + + + {% elif not dpt.tipo_dispositivo.dispositivo_de_articulacao and not dpt.is_relative_auto_insert %} + + + + + + {{dpt.rotulo|safe}} - {{dpt.texto|safe}} + {% nomenclatura_heranca dpt 1 1 %} + + + {% elif dpt.tipo_dispositivo.dispositivo_de_articulacao%} + + + + + + {{dpt.rotulo|safe}} - {% if dpt.tipo_dispositivo.dispositivo_de_articulacao %}{{dpt.dispositivos_filhos_set.all.first.texto|safe}}{% else %}{{dpt.texto|safe}}{% endif %} + {% nomenclatura_heranca dpt 1 1 %} + + + {% endif%} + {% if forloop.last %}{% endif %} + {% endfor %} + + + + {% include 'bootstrap/layout/help_text.html' %} + diff --git a/templates/compilacao/text_edit.html b/templates/compilacao/text_edit.html index e72b41eba..e61c89f53 100644 --- a/templates/compilacao/text_edit.html +++ b/templates/compilacao/text_edit.html @@ -49,7 +49,7 @@ - × + × Orientações Gerais Dicas e Boas Práticas @@ -75,10 +75,12 @@ Inserir os Dispositivos na sequência natural é mais produtivo para você, além de ser também mais simples para o algorítmo que controla este processo. Quanto maior a mudança estutural, mais lento será o procedimento. - A Opção DVt (Dispositivo de Vigência do Texto) redefine o dispositivo em seleção, como o dispositivo de vigência de todos os outros, desde que estes sejam os dispositivos originais do texto. + A Opção DVt (Dispositivo de Vigência do Texto) redefine o dispositivo em seleção, como o dispositivo de vigência de todos os outros, inclusive os dispositivos alterados, caso se trate de um Texto Alterador. - O Dispositivo de Vigência de Dispositivos Alterados são controlados pelos seus Dispositivos Alteradores + O Dispositivo de Vigência de Dispositivos Alterados é, quase sempre, o Dispositivo do Texto Alterador, e não do Texto Alterado. Ao usar a opção DVt, todas as datas de início de vigência serão reenquadradas para a data de vigência do dispositivo de vigência. Posteriormente, alterações manuais poderão ser feitas. + Ao fazer alterações de dispositivos, a opção DVt manipula automáticamente as datas de fim de vigência dos Dispositivos substituidos, ou seja, ao definir um Dispositivo de Vigência de um Dispositivo Alterado, automaticamente será encerrado a vigência de seu antecessor. O mesmo ocorre para dispositivos que possuem sucessores. + Após usar a opção DVt, alterações manuais poderão ser feitas no Editor Avançado e, não sendo usado novamente a opção Dvt, essas alterações manuais serão mantidas. A criação de Tipos de Dispositivos é dinâmica e deverão estar amarrados por perfis estuturais configuráveis. Por serem tarefas técnicas e complicadas, criar/editar tipos de dispositivos e perfis estuturais estão disponíveis apenas na área de edição técnica do SAPL (admin). @@ -108,7 +110,7 @@ {% endblocktrans %} diff --git a/templates/compilacao/text_edit_bloco.html b/templates/compilacao/text_edit_bloco.html index 1cd33507e..34e078de9 100644 --- a/templates/compilacao/text_edit_bloco.html +++ b/templates/compilacao/text_edit_bloco.html @@ -27,7 +27,7 @@ - DVt + DVt {% comment %} ❬ @@ -87,17 +87,26 @@ - p: {{dpt.dispositivo_substituido_id|default:''}}, n: {{dpt.dispositivo_subsequente_id|default:''}}, Ordem: {{dpt.ordem}}, Nivel: {{dpt.nivel}}, Número: {{dpt.get_numero_completo}} + p: {{dpt.dispositivo_substituido_id|default:''}} + • + n: {{dpt.dispositivo_subsequente_id|default:''}} + • + Ordem: {{dpt.ordem}} + • + Nivel: {{dpt.nivel}} + • + Número: {{dpt.get_numero_completo}} {% if dpt.dispositivo_vigencia %} - {% field_verbose_name dpt 'dispositivo_vigencia'%}: {{dpt.dispositivo_vigencia|nomenclatura}} + • + {% field_verbose_name dpt 'dispositivo_vigencia'%}: {{dpt.dispositivo_vigencia|nomenclatura}} {% endif %} - - + • + ? - - + + diff --git a/templates/compilacao/text_list_bloco.html b/templates/compilacao/text_list_bloco.html index fd467cc25..c9e81d223 100644 --- a/templates/compilacao/text_list_bloco.html +++ b/templates/compilacao/text_list_bloco.html @@ -9,7 +9,7 @@ {% close_div view.flag_nivel_old dpt.nivel 0 %} {% endif%} - {% if forloop.first and view|isinst:'DispositivoView' %} + {% if forloop.first and not view|isinst:'TextView' %} {% else %} {% endif%} @@ -171,7 +171,7 @@ {% set_nivel_old view dpt.nivel %} {% endfor %} -{% if view|isinst:'DispositivoView' %} +{% if not view|isinst:'TextView' %} {% close_div view.flag_nivel_old view.flag_nivel_ini -1 %} {% else %} {% close_div view.flag_nivel_old view.flag_nivel_ini 0 %}