diff --git a/sapl/compilacao/forms.py b/sapl/compilacao/forms.py index 29892b150..30ad5c63a 100644 --- a/sapl/compilacao/forms.py +++ b/sapl/compilacao/forms.py @@ -484,20 +484,31 @@ class DispositivoEdicaoBasicaForm(ModelForm): inst = kwargs['instance'] if 'instance' in kwargs else None + editor_type = kwargs['initial']['editor_type']\ + if'editor_type' in kwargs['initial'] else '' + if inst and inst.tipo_dispositivo.formato_variacao0 in [ TipoDispositivo.FNC8, TipoDispositivo.FNCN]: + # remove edição do rótulo se o tipo de disp. for não numerável + if 'rotulo' in DispositivoEdicaoBasicaForm.Meta.fields: + DispositivoEdicaoBasicaForm.Meta.fields.remove('rotulo') + for i in range(6): + DispositivoEdicaoBasicaForm.Meta.fields.remove( + 'dispositivo%s' % i) + elif editor_type == 'get_form_base': + # remove edição do rótulo se a req do form vier do editor dinamico if 'rotulo' in DispositivoEdicaoBasicaForm.Meta.fields: DispositivoEdicaoBasicaForm.Meta.fields.remove('rotulo') for i in range(6): DispositivoEdicaoBasicaForm.Meta.fields.remove( 'dispositivo%s' % i) else: + # adiciona campos de rótulo no formulário 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, @@ -552,6 +563,51 @@ class DispositivoEdicaoBasicaForm(ModelForm): row_texto, css_class="col-md-12")) + if editor_type == 'get_form_base' and inst.dispositivo_atualizador_id: + if inst and inst.tipo_dispositivo.dispositivo_de_articulacao: + if 'texto_atualizador' in\ + DispositivoEdicaoBasicaForm.Meta.fields: + DispositivoEdicaoBasicaForm.Meta.fields.remove( + 'texto_atualizador') + DispositivoEdicaoBasicaForm.Meta.fields.remove( + 'visibilidade') + else: + if 'texto_atualizador' not in\ + DispositivoEdicaoBasicaForm.Meta.fields: + DispositivoEdicaoBasicaForm.Meta.fields.append( + 'texto_atualizador') + DispositivoEdicaoBasicaForm.Meta.fields.append( + 'visibilidade') + + self.texto_atualizador = forms.CharField( + required=False, + label='', + widget=forms.Textarea(), + help_text=_('Não havendo diferenças gráficas entre o ' + 'conteúdo que deve estar no Texto Original e ' + 'no Texto Alterador, não há necessidade ' + 'de duplicar a informação. A validação dos ' + 'dados negará a igualdade.')) + self.visibilidade = forms.ChoiceField( + label=Dispositivo._meta.get_field( + 'visibilidade').verbose_name, + choices=utils.YES_NO_CHOICES, + widget=forms.RadioSelect()) + + layout.append( + Fieldset(Dispositivo._meta.get_field( + 'texto_atualizador').verbose_name, + to_row([(InlineRadios('visibilidade'), 12)]), + to_row([('texto_atualizador', 12)]), + css_class="col-md-12")) + else: + if 'texto_atualizador' in\ + DispositivoEdicaoBasicaForm.Meta.fields: + DispositivoEdicaoBasicaForm.Meta.fields.remove( + 'texto_atualizador') + DispositivoEdicaoBasicaForm.Meta.fields.remove( + 'visibilidade') + fields = DispositivoEdicaoBasicaForm.Meta.fields if fields: self.base_fields.clear() @@ -559,12 +615,66 @@ class DispositivoEdicaoBasicaForm(ModelForm): self.base_fields.update({f: getattr(self, f)}) self.helper = FormHelper() - self.helper.layout = SaplFormLayout( - *layout, - label_cancel=_('Ir para o Editor Sequencial')) + + if not editor_type: + label_cancel = _('Ir para o Editor Sequencial') + self.helper.layout = SaplFormLayout( + *layout, label_cancel=label_cancel) + + elif editor_type == "get_form_base": + getattr(self, "actions_" + editor_type)(layout, inst) super(DispositivoEdicaoBasicaForm, self).__init__(*args, **kwargs) + def actions_get_form_base(self, layout, inst): + label_cancel = _('Fechar') + + more = [ + HTML('%s' % + label_cancel), + ] + + btns_excluir = [] + + if not (inst.tipo_dispositivo.dispositivo_de_alteracao and + inst.tipo_dispositivo.dispositivo_de_articulacao): + btns_excluir = [ + HTML('%s' % (_('Excluir apenas este dispositivo.'), + inst.pk, + _('Excluir Dispositivo')))] + + if inst.dispositivos_filhos_set.filter( + auto_inserido=False).exists() or ( + inst.tipo_dispositivo.dispositivo_de_alteracao and + inst.tipo_dispositivo.dispositivo_de_articulacao): + btns_excluir.append( + HTML( + '%s' % (_('Excluir este dispositivo ' + 'e toda sua estrutura.'), + inst.pk, + _('Excluir Bloco de Dispositivo.')))) + + if btns_excluir and (not inst.auto_inserido or inst.ta_publicado): + css_class = 'btn-group pull-right btns-excluir' + more.append(Div(*btns_excluir, css_class=css_class)) + + if not inst.tipo_dispositivo.dispositivo_de_articulacao: + more.append(Submit('salvar', _('Salvar'), css_class='pull-right')) + + buttons = FormActions(*more, css_class='form-group') + + _fields = [Div(*layout, css_class="row-fluid")] + \ + [to_row([(buttons, 12)])] + self.helper.layout = Layout(*_fields) + class DispositivoSearchModalForm(Form): @@ -624,7 +734,7 @@ class DispositivoSearchModalForm(Form): placeholder=_('Digite palavras, letras, ' 'números ou algo' ' que estejam no texto.')), - StrictButton(_('Buscar'), css_class='btn-busca')), 7)) + StrictButton(_('Buscar'), css_class='btn-busca btn-primary')), 7)) ) ) @@ -750,7 +860,7 @@ class DispositivoEdicaoVigenciaForm(ModelForm): def clean_dispositivo_vigencia(self): dv = self.cleaned_data['dispositivo_vigencia'] - if dv and dv.is_relative_auto_insert(): + if dv and dv.auto_inserido: dv = dv.dispositivo_pai return dv @@ -765,7 +875,7 @@ class DispositivoEdicaoVigenciaForm(ModelForm): if extensao: dv = data['dispositivo_vigencia'] - if dv and dv.is_relative_auto_insert(): + if dv and dv.auto_inserido: dv = dv.dispositivo_pai dv_pk = dv.pk if dv else None @@ -1020,6 +1130,19 @@ class DispositivoEdicaoAlteracaoForm(ModelForm): 'Dispositivo sem haver um ' 'Dispositivo Alterador.')) + """if dst.inicio_vigencia > self.instance.inicio_vigencia: + raise ValidationError(_('Não é permitido substituir um ' + 'Dispositivo que sua data de início ' + 'de vigência é superior a do dispositivo ' + 'em edição.')) + + if dsq.inicio_vigencia <= self.instance.fim_vigencia: + raise ValidationError(_('Não é permitido possuir um Dispositivo ' + 'Subsequente que sua data de início ' + 'de vigência seja inferior a data de fim ' + 'de vigência do dispositivo em edição.')) + """ + def save(self): data = self.cleaned_data @@ -1030,17 +1153,23 @@ class DispositivoEdicaoAlteracaoForm(ModelForm): ndsq = data['dispositivo_subsequente'] nda = data['dispositivo_atualizador'] + # Se o dispositivo substituído foi trocado na edição if ndst != od.dispositivo_substituido: + # Se existia uma substituído, limpar seu subsequente e suas datas + # de fim de vigencia e eficacia if od.dispositivo_substituido: odst = od.dispositivo_substituido - odst.dispositivo_subsequente = None odst.fim_vigencia = None odst.fim_eficacia = None odst.save() + # se foi selecionado um dispositivo para ser substituído + # self.instance é seu subsequente if ndst: + # e se esse novo substituido possuia um outro sequente if ndst.dispositivo_subsequente: + # o substituido desse subsequente não é mais ndst ndst.dispositivo_subsequente.dispositivo_substituido = None ndst.dispositivo_subsequente.save() @@ -1082,7 +1211,7 @@ class TextNotificacoesForm(Form): type_notificacoes = forms.ChoiceField( label=_('Níveis de Notificações'), - choices=[('default', _('Mostrar Dispositivos sem Notificações!')), + choices=[('default', _('Dispositivos sem Notificações!')), ('success', _('Informações!')), ('info', _('Boas Práticas!')), ('warning', _('Alertas!')), @@ -1101,3 +1230,56 @@ class TextNotificacoesForm(Form): self.helper.layout = Layout(field_type_notificacoes) super(TextNotificacoesForm, self).__init__(*args, **kwargs) + + +class DispositivoRegistroAlteracaoForm(Form): + + dispositivo_alterado = forms.ModelChoiceField( + label=_('Dispositivo a ser alterado'), + required=False, + queryset=Dispositivo.objects.all()) + + dispositivo_search_form = forms.CharField(widget=forms.HiddenInput(), + required=False) + + def __init__(self, *args, **kwargs): + + layout = [] + kwargs.pop('instance') + kwargs['initial'].pop('editor_type') + + row_dispositivo = Field( + 'dispositivo_alterado', + data_sapl_ta='DispositivoSearch', + data_field='dispositivo_alterado', + data_type_selection='radio', + template="compilacao/layout/dispositivo_radio.html") + + layout.append(Fieldset(_('Registro de Alteração - ' + 'Seleção do Dispositivo a ser alterado'), + row_dispositivo, + css_class="col-md-12")) + layout.append(Field('dispositivo_search_form')) + + more = [ + HTML('%s' % + _('Cancelar')), + ] + more.append(Submit('salvar', _('Salvar'), css_class='pull-right')) + + buttons = FormActions(*more, css_class='form-group') + + _fields = [Div(*layout, css_class="row-fluid")] + \ + [to_row([(buttons, 12)])] + + self.helper = FormHelper() + self.helper.layout = Layout(*_fields) + + super(DispositivoRegistroAlteracaoForm, self).__init__(*args, **kwargs) + + self.fields['dispositivo_alterado'].choices = [] + + def save(self): + super(DispositivoRegistroAlteracaoForm, self).save() + + data = self.cleaned_data diff --git a/sapl/compilacao/migrations/0051_dispositivo_auto_inserido.py b/sapl/compilacao/migrations/0051_dispositivo_auto_inserido.py new file mode 100644 index 000000000..9b75fabf5 --- /dev/null +++ b/sapl/compilacao/migrations/0051_dispositivo_auto_inserido.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-12 16:24 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('compilacao', '0050_auto_20160503_0926'), + ] + + operations = [ + migrations.AddField( + model_name='dispositivo', + name='auto_inserido', + field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Auto Inserido'), + ), + ] diff --git a/sapl/compilacao/migrations/0052_auto_20160915_1327.py b/sapl/compilacao/migrations/0052_auto_20160915_1327.py new file mode 100644 index 000000000..5cab6191f --- /dev/null +++ b/sapl/compilacao/migrations/0052_auto_20160915_1327.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-15 16:27 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('compilacao', '0051_dispositivo_auto_inserido'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='dispositivo', + unique_together=set([('ta', 'dispositivo0', 'dispositivo1', 'dispositivo2', 'dispositivo3', 'dispositivo4', 'dispositivo5', 'tipo_dispositivo', 'dispositivo_pai', 'dispositivo_atualizador', 'ta_publicado', 'publicacao'), ('ta', 'ordem')]), + ), + ] diff --git a/sapl/compilacao/migrations/0053_auto_20160916_1420.py b/sapl/compilacao/migrations/0053_auto_20160916_1420.py new file mode 100644 index 000000000..15d1446ff --- /dev/null +++ b/sapl/compilacao/migrations/0053_auto_20160916_1420.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-16 17:20 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('compilacao', '0052_auto_20160915_1327'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='dispositivo', + unique_together=set([('ta', 'ordem'), ('ta', 'dispositivo0', 'dispositivo1', 'dispositivo2', 'dispositivo3', 'dispositivo4', 'dispositivo5', 'tipo_dispositivo', 'dispositivo_pai', 'ta_publicado', 'publicacao')]), + ), + ] diff --git a/sapl/compilacao/migrations/0054_auto_20160916_1424.py b/sapl/compilacao/migrations/0054_auto_20160916_1424.py new file mode 100644 index 000000000..3c9eb0df6 --- /dev/null +++ b/sapl/compilacao/migrations/0054_auto_20160916_1424.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-16 17:24 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('compilacao', '0053_auto_20160916_1420'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='dispositivo', + unique_together=set([('ta', 'ordem'), ('ta', 'dispositivo0', 'dispositivo1', 'dispositivo2', 'dispositivo3', 'dispositivo4', 'dispositivo5', 'tipo_dispositivo', 'dispositivo_pai', 'dispositivo_atualizador', 'ta_publicado', 'publicacao')]), + ), + ] diff --git a/sapl/compilacao/models.py b/sapl/compilacao/models.py index fbc282610..7bcc3ae39 100644 --- a/sapl/compilacao/models.py +++ b/sapl/compilacao/models.py @@ -578,7 +578,10 @@ class Dispositivo(BaseModel, TimestampedMixin): default=False, choices=YES_NO_CHOICES, verbose_name=_('Declarado Inconstitucional')) - # Relevant attribute only in altering norms + auto_inserido = models.BooleanField( + default=False, + choices=YES_NO_CHOICES, + verbose_name=_('Auto Inserido')) visibilidade = models.BooleanField( default=False, choices=YES_NO_CHOICES, @@ -647,6 +650,7 @@ class Dispositivo(BaseModel, TimestampedMixin): 'dispositivo5', 'tipo_dispositivo', 'dispositivo_pai', + 'dispositivo_atualizador', 'ta_publicado', 'publicacao',), ) @@ -924,12 +928,14 @@ class Dispositivo(BaseModel, TimestampedMixin): def criar_espaco(self, espaco_a_criar, local): - if local == 'add_next': + if local == 'json_add_next': proximo_bloco = Dispositivo.objects.filter( ordem__gt=self.ordem, nivel__lte=self.nivel, ta_id=self.ta_id)[:1] - elif local == 'add_in': + elif local == 'json_add_in': + # FIXME: o exclude não deve estar limitado a uma class_css caput e + # sim a qualquer filho de inserção automática proximo_bloco = Dispositivo.objects.filter( ordem__gt=self.ordem, nivel__lte=self.nivel + 1, @@ -951,7 +957,7 @@ class Dispositivo(BaseModel, TimestampedMixin): ordem=F('ordem') + ( Dispositivo.INTERVALO_ORDEM * espaco_a_criar - 1)) else: - # inserção no fim da ta + # inserção no fim do ta ordem_max = Dispositivo.objects.order_by( 'ordem').filter( ta_id=self.ta_id).aggregate( @@ -1112,7 +1118,14 @@ class Dispositivo(BaseModel, TimestampedMixin): ta_id=self.ta_id).last() return anterior_articulacao - def is_relative_auto_insert(self, perfil_pk=None): + def get_niveis_zero(self): + niveis_zero = Dispositivo.objects.order_by('ordem').filter( + nivel=0, + ta_id=self.ta_id) + return niveis_zero + + # metodo obsoleto, foi acrescentado o campo auto_inserido no modelo + def is_relative_auto_insert__obsoleto(self, perfil_pk=None): if self.dispositivo_pai is not None: # pp possiveis_pais @@ -1137,6 +1150,16 @@ class Dispositivo(BaseModel, TimestampedMixin): dp = dp.dispositivo_pai return dp + def history(self): + ultimo = self + while ultimo.dispositivo_subsequente: + ultimo = ultimo.dispositivo_subsequente + + yield ultimo + while ultimo.dispositivo_substituido: + ultimo = ultimo.dispositivo_substituido + yield ultimo + @staticmethod def new_instance_based_on(dispositivo_base, tipo_base): dp = Dispositivo() @@ -1148,6 +1171,7 @@ class Dispositivo(BaseModel, TimestampedMixin): dp.nivel = dispositivo_base.nivel dp.texto = '' dp.visibilidade = True + dp.auto_inserido = dispositivo_base.auto_inserido dp.ta = dispositivo_base.ta dp.dispositivo_pai = dispositivo_base.dispositivo_pai dp.publicacao = dispositivo_base.publicacao @@ -1161,7 +1185,7 @@ class Dispositivo(BaseModel, TimestampedMixin): else: dp.inicio_eficacia = dispositivo_base.inicio_eficacia dp.inicio_vigencia = dispositivo_base.inicio_vigencia - dp.fim_eficacia = dispositivo_base.inicio_eficacia + dp.fim_eficacia = dispositivo_base.fim_eficacia dp.fim_vigencia = dispositivo_base.fim_vigencia dp.ordem = dispositivo_base.ordem diff --git a/sapl/compilacao/templatetags/compilacao_filters.py b/sapl/compilacao/templatetags/compilacao_filters.py index 3fd024a77..4846e71be 100644 --- a/sapl/compilacao/templatetags/compilacao_filters.py +++ b/sapl/compilacao/templatetags/compilacao_filters.py @@ -7,9 +7,56 @@ from django.utils.translation import ugettext_lazy as _ from sapl.compilacao.models import Dispositivo + register = template.Library() +class DispositivoTreeNode(template.Node): + + def __init__(self, template_nodes, dispositivo_list_var): + self.template_nodes = template_nodes + self.dispositivo_list_var = dispositivo_list_var + + def _render_node(self, context, node): + bits_alts = [] + bits_filhos = [] + context.push() + for child in node['alts']: + bits_alts.append(self._render_node(context, child)) + for child in node['filhos']: + bits_filhos.append(self._render_node(context, child)) + context['node'] = node + context['alts'] = mark_safe(''.join(bits_alts)) + context['filhos'] = mark_safe(''.join(bits_filhos)) + rendered = self.template_nodes.render(context) + context.pop() + return rendered + + def render(self, context): + dispositivo_list_var = self.dispositivo_list_var.resolve(context) + bits = [self._render_node(context, node) + for node in dispositivo_list_var] + return ''.join(bits) + + +@register.tag +def dispositivotree(parser, token): + + bits = token.contents.split() + if len(bits) != 2: + raise template.TemplateSyntaxError( + _('%s tag requires a queryset') % bits[0]) + + dispositivo_list_var = template.Variable(bits[1]) + + template_nodes = parser.parse(('enddispositivotree',)) + parser.delete_first_token() + + return DispositivoTreeNode(template_nodes, dispositivo_list_var) + +# -------------------------------------------------------------- + + @register.filter def get_bloco_atualizador(pk_atualizador): return Dispositivo.objects.order_by('ordem_bloco_atualizador').filter( @@ -34,7 +81,7 @@ 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: + if dispositivo.ta_publicado: d = dispositivo.dispositivo_atualizador.dispositivo_pai ta_publicado = ta_pub_list[dispositivo.ta_publicado_id] if\ @@ -79,11 +126,6 @@ def select_provaveis_inserts(view, request): return view.select_provaveis_inserts(request) -@register.filter -def is_relative_auto_insert(dpt, request): - return dpt.is_relative_auto_insert(request.session['perfil_estrutural']) - - @register.filter def isinst(value, class_str): classe = value.__class__.__name__ @@ -168,7 +210,9 @@ def heranca(request, d, ignore_ultimo=0, ignore_primeiro=0): ta_dpts_parents = {} ta_id = str(d.ta_id) - if ta_id not in ta_dpts_parents: + d_pk = str(d.pk) + if ta_id not in ta_dpts_parents or d_pk not in ta_dpts_parents[ta_id]: + print('recarregando estrutura temporaria de heranças') dpts_parents = {} ta_dpts_parents[ta_id] = dpts_parents update_dispositivos_parents(dpts_parents, ta_id) @@ -185,7 +229,6 @@ def heranca(request, d, ignore_ultimo=0, ignore_primeiro=0): request.session['herancas_fila'] = herancas_fila request.session['herancas'] = ta_dpts_parents - d_pk = str(d.pk) h = ta_dpts_parents[ta_id][d_pk]['h'] if h: diff --git a/sapl/compilacao/urls.py b/sapl/compilacao/urls.py index f5466e747..1c6cc2e70 100644 --- a/sapl/compilacao/urls.py +++ b/sapl/compilacao/urls.py @@ -34,7 +34,8 @@ urlpatterns_compilacao = [ views.DispositivoView.as_view(), name='dispositivo'), url(r'^(?P[0-9]+)/text/(?P[0-9]+)/refresh', - views.DispositivoSimpleEditView.as_view(), name='dispositivo_refresh'), + views.DispositivoDinamicEditView.as_view(), + name='dispositivo_refresh'), url(r'^(?P[0-9]+)/text/(?P[0-9]+)/edit$', views.DispositivoEdicaoBasicaView.as_view(), name='dispositivo_edit'), @@ -51,8 +52,6 @@ urlpatterns_compilacao = [ 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$', @@ -126,3 +125,6 @@ urlpatterns = [ include(VeiculoPublicacaoCrud.get_urls())), ] + +"""url(r'^(?P[0-9]+)/text/(?P[0-9]+)/actions', + views.ActionsEditView.as_view(), name='dispositivo_actions'),""" \ No newline at end of file diff --git a/sapl/compilacao/utils.py b/sapl/compilacao/utils.py index 38c55239a..83f44e8f3 100644 --- a/sapl/compilacao/utils.py +++ b/sapl/compilacao/utils.py @@ -12,6 +12,18 @@ DISPOSITIVO_SELECT_RELATED = ( 'ta_publicado', 'ta',) +DISPOSITIVO_SELECT_RELATED_EDIT = ( + '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',) + def int_to_roman(int_value): # if isinstance(int_value, type(1)): diff --git a/sapl/compilacao/views.py b/sapl/compilacao/views.py index ff88d627d..4be220cde 100644 --- a/sapl/compilacao/views.py +++ b/sapl/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 @@ -15,6 +15,7 @@ from django.http.response import (HttpResponse, HttpResponseRedirect, from django.shortcuts import get_object_or_404, redirect from django.utils.dateparse import parse_date from django.utils.decorators import method_decorator +from django.utils.encoding import force_text from django.utils.translation import ugettext_lazy as _ from django.views.generic.base import TemplateView from django.views.generic.detail import DetailView @@ -22,26 +23,30 @@ from django.views.generic.edit import (CreateView, DeleteView, FormView, UpdateView) from django.views.generic.list import ListView -from sapl.compilacao.forms import (DispositivoDefinidorVigenciaForm, - DispositivoEdicaoAlteracaoForm, - DispositivoEdicaoBasicaForm, - DispositivoEdicaoVigenciaForm, - DispositivoSearchModalForm, NotaForm, - PublicacaoForm, TaForm, - TextNotificacoesForm, TipoTaForm, VideForm) -from sapl.compilacao.models import (Dispositivo, Nota, - PerfilEstruturalTextoArticulado, - Publicacao, TextoArticulado, - TipoDispositivo, TipoNota, TipoPublicacao, - TipoTextoArticulado, TipoVide, - VeiculoPublicacao, Vide) -from sapl.compilacao.utils import DISPOSITIVO_SELECT_RELATED +from sapl.compilacao.forms import ( + DispositivoDefinidorVigenciaForm, + DispositivoEdicaoAlteracaoForm, + DispositivoEdicaoBasicaForm, + DispositivoEdicaoVigenciaForm, + DispositivoSearchModalForm, NotaForm, + PublicacaoForm, TaForm, TextNotificacoesForm, + TipoTaForm, VideForm, DispositivoRegistroAlteracaoForm) +from sapl.compilacao.models import ( + Dispositivo, Nota, + PerfilEstruturalTextoArticulado, Publicacao, + TextoArticulado, TipoDispositivo, TipoNota, + TipoPublicacao, TipoTextoArticulado, TipoVide, + VeiculoPublicacao, Vide) +from sapl.compilacao.utils import DISPOSITIVO_SELECT_RELATED,\ + DISPOSITIVO_SELECT_RELATED_EDIT from sapl.crud.base import Crud, CrudListView, make_pagination + TipoNotaCrud = Crud.build(TipoNota, 'tipo_nota') TipoVideCrud = Crud.build(TipoVide, 'tipo_vide') TipoPublicacaoCrud = Crud.build(TipoPublicacao, 'tipo_publicacao') VeiculoPublicacaoCrud = Crud.build(VeiculoPublicacao, 'veiculo_publicacao') +#^class(.)+\((.)*^(CompMix)(.)* class IntegracaoTaView(TemplateView): @@ -133,15 +138,21 @@ def choice_models_in_extenal_views(): class CompMixin: - @property - def title(self): - try: - return self.get_object() - except: - return self.object + def get_context_data(self, **kwargs): + context = super(CompMixin, self).get_context_data(**kwargs) + + if hasattr(self, 'model') and not hasattr(self, 'object'): + context.update( + {'title': self.model._meta.verbose_name_plural + if isinstance(self, ListView) + else self.model._meta.verbose_name}) + + if isinstance(self, ListView): + context['NO_ENTRIES_MSG'] = CrudListView.no_entries_msg + return context -class TipoTaListView(ListView): +class TipoTaListView(CompMixin, ListView): model = TipoTextoArticulado paginate_by = 10 verbose_name = model._meta.verbose_name @@ -155,7 +166,7 @@ class TipoTaListView(ListView): return reverse_lazy('sapl.compilacao:tipo_ta_create') -class TipoTaCreateView(FormMessagesMixin, CreateView): +class TipoTaCreateView(CompMixin, FormMessagesMixin, CreateView): model = TipoTextoArticulado form_class = TipoTaForm template_name = "crud/form.html" @@ -220,7 +231,7 @@ class TipoTaDeleteView(CompMixin, DeleteView): return reverse_lazy('sapl.compilacao:tipo_ta_list') -class TaListView(ListView): +class TaListView(CompMixin, ListView): model = TextoArticulado paginate_by = 10 verbose_name = model._meta.verbose_name @@ -242,7 +253,7 @@ class TaListView(ListView): return context -class TaDetailView(DetailView): +class TaDetailView(CompMixin, DetailView): model = TextoArticulado @property @@ -257,7 +268,7 @@ class TaDetailView(DetailView): return self.get_object() -class TaCreateView(FormMessagesMixin, CreateView): +class TaCreateView(CompMixin, FormMessagesMixin, CreateView): model = TextoArticulado form_class = TaForm template_name = "crud/form.html" @@ -309,7 +320,7 @@ class TaDeleteView(CompMixin, DeleteView): return reverse_lazy('sapl.compilacao:ta_list') -class DispositivoSuccessUrlMixin: +class DispositivoSuccessUrlMixin(CompMixin): def get_success_url(self): return reverse_lazy( @@ -469,7 +480,7 @@ class VideDeleteView(VideMixin, TemplateView): return HttpResponseRedirect(self.get_success_url()) -class PublicacaoListView(ListView): +class PublicacaoListView(CompMixin, ListView): model = Publicacao verbose_name = model._meta.verbose_name @@ -500,7 +511,7 @@ class PublicacaoListView(ListView): return context -class PublicacaoCreateView(FormMessagesMixin, CreateView): +class PublicacaoCreateView(CompMixin, FormMessagesMixin, CreateView): model = Publicacao form_class = PublicacaoForm template_name = "crud/form.html" @@ -568,7 +579,7 @@ class PublicacaoDeleteView(CompMixin, DeleteView): kwargs={'ta_id': self.kwargs['ta_id']}) -class TextView(ListView, CompMixin): +class TextView(CompMixin, ListView): template_name = 'compilacao/text_list.html' flag_alteradora = -1 @@ -810,53 +821,189 @@ class DispositivoView(TextView): return itens -class TextEditView(ListView, CompMixin): +class TextEditView(TemplateView): template_name = 'compilacao/text_edit.html' - flag_alteradora = -1 + def get_context_data(self, **kwargs): + dispositivo_id = int(self.kwargs['dispositivo_id']) \ + if 'dispositivo_id' in self.kwargs else 0 - flag_nivel_ini = 0 - flag_nivel_old = -1 + if dispositivo_id: + self.object = Dispositivo.objects.get(pk=dispositivo_id) - pk_edit = 0 - pk_view = 0 + context = super(TextEditView, self).get_context_data(**kwargs) - def get(self, request, *args, **kwargs): + if not dispositivo_id: + ta = TextoArticulado.objects.get(pk=self.kwargs['ta_id']) + self.object = ta - return ListView.get(self, request, *args, **kwargs) + context['object'] = self.object + context['dispositivos_list'] = self.dispositivos_list() - def get_context_data(self, **kwargs): - context = super(TextEditView, self).get_context_data(**kwargs) + if 'action' in self.request.GET: + context['action'] = self.request.GET['action'] - ta = TextoArticulado.objects.get(pk=self.kwargs['ta_id']) - self.object = ta + return context - context['object'] = self.object + def dispositivos_list(self): + self.runBase() - tas_pub = [d.ta_publicado for d in self.object_list if d.ta_publicado] + tds = {td.pk: td for td in TipoDispositivo.objects.all()} + + dispositivo_id = int(self.kwargs['dispositivo_id']) \ + if 'dispositivo_id' in self.kwargs else 0 + ta_id = int(self.kwargs['ta_id']) \ + if 'ta_id' in self.kwargs else 0 + + q = Q(ta_id=ta_id) + + dispositivos_de_alteracao = [] + dispositivos = [] + if dispositivo_id: + bloco = Dispositivo.objects.get(pk=dispositivo_id) + + if (tds[bloco.tipo_dispositivo_id].dispositivo_de_alteracao and + not tds[bloco.tipo_dispositivo_id + ].dispositivo_de_articulacao) or ( + bloco.ta_id != ta_id and bloco.ta_publicado_id == ta_id): + dispositivos = [bloco, ] + else: + proximo_bloco = Dispositivo.objects.filter( + ordem__gt=bloco.ordem, + nivel__lte=bloco.nivel, + ta_id=ta_id)[:1] + + if not proximo_bloco.exists(): + q = q & Q(ordem__gte=bloco.ordem) + else: + q = q & Q(ordem__gte=bloco.ordem) & \ + Q(ordem__lt=proximo_bloco[0].ordem) + + dispositivos_de_alteracao = Dispositivo.objects.filter( + ta_id=ta_id, + tipo_dispositivo__dispositivo_de_alteracao=True, + tipo_dispositivo__dispositivo_de_articulacao=False + ).select_related(*DISPOSITIVO_SELECT_RELATED_EDIT) + + if not dispositivos: + dispositivos = Dispositivo.objects.filter( + q).select_related(*DISPOSITIVO_SELECT_RELATED_EDIT) + + dispositivos_alterados = Dispositivo.objects.filter( + ta_publicado_id=ta_id) + + dispositivos_alteradores = Dispositivo.objects.filter( + dispositivos_alterados_set__ta_id=ta_id) + + dpts = list(dispositivos) + \ + list(dispositivos_de_alteracao) + \ + list(dispositivos_alterados) + \ + list(dispositivos_alteradores) + + tas_pub = [d.ta_publicado for d in dispositivos if d.ta_publicado] tas_pub = set(tas_pub) - ta_pub_list = {} + lista_ta_publicado = {} for ta in tas_pub: - ta_pub_list[ta.pk] = str(ta) - context['ta_pub_list'] = ta_pub_list - - return context + lista_ta_publicado[ta.pk] = str(ta) + + dpts = {d.pk: { + 'dpt': d, + 'filhos': [], + 'alts': [], + 'pai': None, + 'st': None, # dispositivo substituido + 'sq': None, # dispositivo subsequente + 'da': None, # dispositivo atualizador + 'td': tds[d.tipo_dispositivo_id], # tipo do dispositivo + 'na': self.nota_alteracao(d, lista_ta_publicado)\ + if d.ta_id == ta_id else None + } for d in dpts} + + apagar = [] + for d in dispositivos: + try: + if d.dispositivo_substituido_id: + dpts[d.pk]['st'] = dpts[d.dispositivo_substituido_id] + except: + pass + try: + if d.dispositivo_subsequente_id: + dpts[d.pk]['sq'] = dpts[d.dispositivo_subsequente_id] + except: + pass + try: + if d.dispositivo_atualizador_id: + dpts[d.pk]['da'] = dpts[d.dispositivo_atualizador_id] + except: + pass + try: + if d.dispositivo_pai_id: + """ Pode não ser possível vincular a estrutura do pai + devido a busca de bloco não envolver o pai do bloco, + por isso os try's except's""" + dpts[d.pk]['pai'] = dpts[d.dispositivo_pai_id] + + if tds[d.tipo_dispositivo_id].\ + dispositivo_de_alteracao and not\ + tds[d.tipo_dispositivo_id].\ + dispositivo_de_articulacao: + apagar.append(d.pk) + else: + dpts[d.dispositivo_pai_id]['filhos'].append(dpts[d.pk]) + apagar.append(d.pk) + except: + pass + try: + if tds[d.tipo_dispositivo_id].dispositivo_de_alteracao and\ + tds[d.tipo_dispositivo_id].dispositivo_de_articulacao: + + alts = Dispositivo.objects.values_list( + 'pk', flat=True).order_by( + 'ordem_bloco_atualizador').filter( + Q(dispositivo_pai_id=d.pk) | + Q(dispositivo_atualizador_id=d.pk)) + + for dAlt in alts: + dpts[d.pk]['alts'].append(dpts[dAlt]) + dpts[dAlt]['da'] = dpts[d.pk] + except: + pass - def get_queryset(self): - self.pk_edit = 0 - self.pk_view = 0 + for pk in apagar: + del dpts[pk] + + r = [] + for dd in dispositivos: + if dd.pk in dpts: + r.append(dpts[dd.pk]) + return r + + def nota_alteracao(self, dispositivo, lista_ta_publicado): + if dispositivo.ta_publicado_id: + d = dispositivo.dispositivo_atualizador.dispositivo_pai + + ta_publicado = lista_ta_publicado[dispositivo.ta_publicado_id] if\ + lista_ta_publicado else dispositivo.ta_publicado + + if dispositivo.texto == \ + Dispositivo.TEXTO_PADRAO_DISPOSITIVO_REVOGADO: + return _('Revogado pelo %s - %s.') % ( + d, ta_publicado) + elif not dispositivo.dispositivo_substituido_id: + return _('Inclusão feita pelo %s - %s.') % ( + d, ta_publicado) + else: + return _('Alteração feita pelo %s - %s.') % ( + d, ta_publicado) - self.flag_alteradora = -1 - self.flag_nivel_ini = 0 - self.flag_nivel_old = -1 + return '' - result = Dispositivo.objects.filter( - ta_id=self.kwargs['ta_id'] - ).select_related(*DISPOSITIVO_SELECT_RELATED) + def runBase(self): + result = Dispositivo.objects.filter(ta_id=self.kwargs['ta_id']) if not result.exists(): - ta = TextoArticulado.objects.get(pk=self.kwargs['ta_id']) + ta = self.object td = TipoDispositivo.objects.filter(class_css='articulacao')[0] a = Dispositivo() @@ -891,485 +1038,175 @@ class TextEditView(ListView, CompMixin): a.set_numero_completo([2, 0, 0, 0, 0, 0, ]) a.save() - result = Dispositivo.objects.filter( - ta_id=self.kwargs['ta_id'] - ).select_related(*DISPOSITIVO_SELECT_RELATED) - return result +class ActionsCommonsMixin: - def set_perfil_in_session(self, request=None, perfil_id=0): - if not request: - return None + def set_message(self, data, _type, message, time=None, modal=False): + data['message'] = { + 'type': _type, + 'value': str(message)} + if time: + data['message']['time'] = time + data['message']['modal'] = modal + return - if perfil_id: - perfil = PerfilEstruturalTextoArticulado.objects.get( - pk=perfil_id) - request.session['perfil_estrutural'] = perfil.pk - else: - perfis = PerfilEstruturalTextoArticulado.objects.filter( - padrao=True)[:1] + def get_json_for_refresh(self, dp, dpauto=None): - if not perfis.exists(): - request.session.pop('perfil_estrutural') + if dp.tipo_dispositivo.contagem_continua: + pais = [] + if dp.dispositivo_pai is None: + data = {'pk': dp.pk, 'pai': [-1, ]} else: - request.session['perfil_estrutural'] = perfis[0].pk + pkfilho = dp.pk + dp = dp.dispositivo_pai + + proxima_articulacao = dp.get_proximo_nivel_zero() + if proxima_articulacao is not None: + parents = Dispositivo.objects.filter( + ta_id=dp.ta_id, + ordem__gte=dp.ordem, + ordem__lt=proxima_articulacao.ordem, + nivel__lte=dp.nivel) + else: + parents = Dispositivo.objects.filter( + ta_id=dp.ta_id, + ordem__gte=dp.ordem, + nivel__lte=dp.nivel) -class DispositivoSimpleEditView(TextEditView): - template_name = 'compilacao/text_edit_bloco.html' + nivel = sys.maxsize + for p in parents: + if p.nivel > nivel: + continue + pais.append(p.pk) + nivel = p.nivel + data = { + 'pk': pkfilho if not dpauto else dpauto.pk, 'pai': pais} + else: + data = {'pk': dp.pk if not dpauto else dpauto.pk, 'pai': [ + dp.dispositivo_pai.pk, ]} - def post(self, request, *args, **kwargs): + return data - d = Dispositivo.objects.get( - pk=self.kwargs['dispositivo_id']) - texto = request.POST['texto'] +class ActionDragAndMoveDispositivoAlteradoMixin(ActionsCommonsMixin): - if d.texto != '': - d.texto = texto - d.save() - return self.get(request, *args, **kwargs) - d.texto = texto.strip() - d.save() - - if texto != '': - dnext = Dispositivo.objects.filter( - ta_id=d.ta_id, - ordem__gt=d.ordem, - texto='', - tipo_dispositivo__dispositivo_de_articulacao=False)[:1] - - if not dnext.exists(): - dnext = [] - dnext.append(d) - pais = [d.dispositivo_pai_id, ] - else: + def json_drag_move_dpt_alterado(self, context): - if dnext[0].nivel > d.nivel: - pais = [d.pk, ] - else: - if dnext[0].dispositivo_pai_id == d.dispositivo_pai_id: - pais = [dnext[0].dispositivo_pai_id, ] - else: - pais = [ - dnext[0].dispositivo_pai_id, - d.dispositivo_pai_id] - data = {'pk': dnext[0].pk, 'pai': pais} + bloco = Dispositivo.objects.get(pk=self.request.GET['bloco_pk']) + dpt = Dispositivo.objects.get(pk=self.kwargs['dispositivo_id']) + + if dpt.tipo_dispositivo.dispositivo_de_alteracao: + dpt.dispositivo_pai = bloco else: - data = {'pk': d.pk, 'pai': [d.pk, ]} + dpt.dispositivo_atualizador = bloco - return JsonResponse(data, safe=False) + filhos = Dispositivo.objects.order_by( + 'ordem_bloco_atualizador').filter( + Q(dispositivo_pai_id=bloco.pk) | + Q(dispositivo_atualizador_id=bloco.pk)) - def get_queryset_perfil_estrutural(self): - perfis = PerfilEstruturalTextoArticulado.objects.all() - return perfis + if not filhos.exists(): + dpt.ordem_bloco_atualizador = Dispositivo.INTERVALO_ORDEM + else: + index = int(self.request.GET['index']) + fpks = filhos.values_list( + 'pk', flat=True).order_by('ordem_bloco_atualizador') - def get(self, request, *args, **kwargs): + index_dpt = 0 + try: + index_dpt = list(fpks).index(dpt.pk) + except: + pass - try: - if 'perfil_pk' in request.GET: - self.set_perfil_in_session( - request, request.GET['perfil_pk']) - elif 'perfil_estrutural' not in request.session: - self.set_perfil_in_session(request=request) + filho_index = filhos[ + index if index_dpt >= index + else index + 1] if ( + index if index_dpt >= index + else index + 1) < filhos.count() else filhos.last() + if filhos.last() == filho_index: + dpt.ordem_bloco_atualizador = \ + filho_index.ordem_bloco_atualizador + 1 + else: + dpt.ordem_bloco_atualizador = \ + filho_index.ordem_bloco_atualizador - 1 - self.object_list = self.get_queryset() + dpt.save() + bloco.ordenar_bloco_alteracao() - self.perfil_estrutural_list = self.get_queryset_perfil_estrutural() + data = {} - context = self.get_context_data( - object_list=self.object_list, - perfil_estrutural_list=self.perfil_estrutural_list - ) - except Exception as e: - print(e) - return self.render_to_response(context) +class ActionDeleteDispositivoMixin(ActionsCommonsMixin): - def get_queryset(self): - self.flag_alteradora = -1 - self.flag_nivel_ini = 0 - self.flag_nivel_old = -1 + def json_delete_item_dispositivo(self, context): + return self.json_delete_bloco_dispositivo(context, bloco=False) - try: - self.pk_edit = int(self.request.GET['edit']) - except: - self.pk_edit = 0 - self.pk_view = int(self.kwargs['dispositivo_id']) + def json_delete_bloco_dispositivo(self, context, bloco=True): + base = Dispositivo.objects.get(pk=self.kwargs['dispositivo_id']) + ta_base = base.ta - try: - if self.pk_edit == self.pk_view: - bloco = Dispositivo.objects.get( - pk=self.kwargs['dispositivo_id']) - else: - bloco = Dispositivo.objects.get( - pk=self.kwargs['dispositivo_id']) - except Dispositivo.DoesNotExist: - return [] + base_anterior = Dispositivo.objects.order_by('-ordem').filter( + ta_id=base.ta_id, + ordem__lt=base.ordem + ).first() - self.flag_nivel_old = bloco.nivel - 1 - self.flag_nivel_ini = bloco.nivel + data = {} + if base_anterior: + data = self.get_json_for_refresh(base_anterior) + else: + base_anterior = base.get_nivel_zero_anterior() + data = self.get_json_for_refresh(base_anterior) - if self.pk_edit == self.pk_view: - return [bloco, ] + bases_atualizacao = Dispositivo.objects.order_by('ordem').filter( + ta_id=base.ta_id, + ordem__gt=base.ordem, + nivel__lt=base.nivel) - proximo_bloco = Dispositivo.objects.filter( - ordem__gt=bloco.ordem, - nivel__lte=bloco.nivel, - ta_id=self.kwargs['ta_id'])[:1] + data['pai'] = [base.get_raiz().pk] - if proximo_bloco.count() == 0: - itens = Dispositivo.objects.filter( - ordem__gte=bloco.ordem, - ta_id=self.kwargs['ta_id'] - ).select_related(*DISPOSITIVO_SELECT_RELATED) - else: - itens = Dispositivo.objects.filter( - ordem__gte=bloco.ordem, - ordem__lt=proximo_bloco[0].ordem, - ta_id=self.kwargs['ta_id'] - ).select_related(*DISPOSITIVO_SELECT_RELATED) - return itens + if ta_base.id != int(self.kwargs['ta_id']): + data['pai'] = [base.dispositivo_atualizador.pk] + data['pk'] = base.dispositivo_atualizador.pk - def select_provaveis_inserts(self, request=None): try: - if request and 'perfil_estrutural' not in request.session: - self.set_perfil_in_session(request) - - perfil_pk = request.session['perfil_estrutural'] + with transaction.atomic(): + message = str(self.remover_dispositivo(base, bloco)) + if message: + self.set_message(data, 'warning', message, modal=True) + else: + self.set_message(data, 'success', _( + 'Exclusão efetuada com sucesso!'), modal=True) + ta_base.ordenar_dispositivos() + except Exception as e: + data['pk'] = self.kwargs['dispositivo_id'] + self.set_message(data, 'danger', str(e), modal=True) - # Não salvar d_base - if self.pk_edit == 0: - base = Dispositivo.objects.get(pk=self.pk_view) - else: - base = Dispositivo.objects.get(pk=self.pk_edit) + return data - prox_possivel = Dispositivo.objects.filter( - ordem__gt=base.ordem, - nivel__lte=base.nivel, - ta_id=base.ta_id)[:1] + def remover_dispositivo(self, base, bloco): + base_ordem = base.ordem + if base.dispositivo_subsequente or base.dispositivo_substituido: + p = base.dispositivo_substituido + n = base.dispositivo_subsequente - if prox_possivel.exists(): - prox_possivel = prox_possivel[0] - else: - prox_possivel = None - - result = [{'tipo_insert': _('Inserir Depois'), - 'icone': '↷ ', - 'action': 'add_next', - 'itens': []}, - {'tipo_insert': _('Inserir Dentro'), - 'icone': '⇲ ', - 'action': 'add_in', - 'itens': []}, - {'tipo_insert': _('Inserir Antes'), - 'icone': '↶ ', - 'action': 'add_prior', - 'itens': []} - ] - - # Possíveis inserções sequenciais já existentes - parents = base.get_parents() - parents.insert(0, base) - nivel = sys.maxsize - for dp in parents: - - if dp.nivel >= nivel: - continue - - if dp.is_relative_auto_insert(perfil_pk): - continue - - if prox_possivel and \ - dp.tipo_dispositivo != base.tipo_dispositivo and\ - dp.nivel < prox_possivel.nivel and\ - not prox_possivel.tipo_dispositivo.permitido_inserir_in( - dp.tipo_dispositivo, - perfil_pk=perfil_pk): - - if dp.tipo_dispositivo != prox_possivel.tipo_dispositivo: - continue - - nivel = dp.nivel - - # um do mesmo para inserção antes - if dp == base: - result[2]['itens'].append({ - 'class_css': dp.tipo_dispositivo.class_css, - 'tipo_pk': dp.tipo_dispositivo.pk, - 'variacao': 0, - 'provavel': '%s (%s)' % ( - dp.rotulo_padrao(local_insert=1), - dp.tipo_dispositivo.nome,), - 'dispositivo_base': base.pk}) - - if dp.dispositivo_pai: - flag_pv = dp.tipo_dispositivo.permitido_variacao( - dp.dispositivo_pai.tipo_dispositivo, - perfil_pk=perfil_pk) - else: - flag_pv = False - - r = [] - flag_direcao = 1 - flag_variacao = 0 - while True: - if dp.dispositivo0 == 0: - local_insert = 1 - else: - local_insert = 0 - - rt = dp.transform_in_next(flag_direcao) - if not rt[0]: - break - flag_variacao += rt[1] - r.append({'class_css': dp.tipo_dispositivo.class_css, - 'tipo_pk': dp.tipo_dispositivo.pk, - 'variacao': flag_variacao, - 'provavel': '%s (%s)' % ( - dp.rotulo_padrao(local_insert), - dp.tipo_dispositivo.nome,), - 'dispositivo_base': base.pk}) - - flag_direcao = -1 - - r.reverse() - - if not flag_pv: - r = [r[0], ] - - if len(r) > 0 and dp.tipo_dispositivo.formato_variacao0 == \ - TipoDispositivo.FNCN: - r = [r[0], ] - - if dp.tipo_dispositivo == base.tipo_dispositivo: - result[0]['itens'] += r - else: - result[0]['itens'] += r - result[2]['itens'] += r - - if nivel == 0: - break - - # tipo do dispositivo base - tipb = base.tipo_dispositivo - - for paradentro in [1, 0]: - if paradentro: - # Outros Tipos de Dispositivos PARA DENTRO - otds = TipoDispositivo.objects.order_by( - '-contagem_continua', 'id').all() - else: - # Outros Tipos de Dispositivos PARA FORA - classes_ja_inseridas = [] - for c in result[0]['itens']: - if c['class_css'] not in classes_ja_inseridas: - classes_ja_inseridas.append(c['class_css']) - for c in result[1]['itens']: - if c['class_css'] not in classes_ja_inseridas: - classes_ja_inseridas.append(c['class_css']) - otds = TipoDispositivo.objects.order_by( - '-contagem_continua', 'id').all().exclude( - class_css__in=classes_ja_inseridas) - - for td in otds: - - if paradentro and not td.permitido_inserir_in( - tipb, - include_relative_autos=False, - perfil_pk=perfil_pk): - continue - - base.tipo_dispositivo = td - - if not paradentro: - - flag_insercao = False - for possivelpai in parents: - if td.permitido_inserir_in( - possivelpai.tipo_dispositivo, - include_relative_autos=False, - perfil_pk=perfil_pk): - flag_insercao = True - break - - if not flag_insercao: - continue - - if possivelpai.is_relative_auto_insert(perfil_pk): - continue - - if prox_possivel: - if prox_possivel.nivel == base.nivel: - if prox_possivel.tipo_dispositivo != td and\ - not prox_possivel.tipo_dispositivo.\ - permitido_inserir_in( - td, perfil_pk=perfil_pk): - continue - else: - if possivelpai.tipo_dispositivo != \ - prox_possivel.tipo_dispositivo and\ - not prox_possivel.tipo_dispositivo.\ - permitido_inserir_in( - possivelpai.tipo_dispositivo, - perfil_pk=perfil_pk) and \ - possivelpai.nivel < \ - prox_possivel.nivel: - continue - base.dispositivo_pai = possivelpai - Dispositivo.set_numero_for_add_in( - possivelpai, base, td) - else: - Dispositivo.set_numero_for_add_in(base, base, td) - - r = [{'class_css': td.class_css, - 'tipo_pk': td.pk, - 'variacao': 0, - 'provavel': '%s (%s)' % ( - base.rotulo_padrao(1, paradentro), - td.nome,), - 'dispositivo_base': base.pk}] - - if paradentro == 1: - """if (tipb.class_css == 'caput' and - td.class_css == 'paragrafo'): - result[0]['itens'].insert(0, r[0]) - else:""" - result[1]['itens'] += r - else: - result[2]['itens'] += r - result[0]['itens'] += r - - # if len(result[0]['itens']) < len(result[1]['itens']): - # r = result[0] - # result.remove(result[0]) - # result.insert(1, r) - - # remover temporariamente a opção inserir antes - # confirmar necessidade - if len(result) > 2: - result.pop() - - # if tipb.dispositivo_de_articulacao and\ - # tipb.dispositivo_de_alteracao: - # result.pop() - - except Exception as e: - print(e) - - return result - - -class ActionsEditMixin: - - def render_to_json_response(self, context, **response_kwargs): - - action = getattr(self, context['action']) - 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(): - dvt = dvt.dispositivo_pai - - try: - Dispositivo.objects.filter( - (Q(ta=dvt.ta) & Q(ta_publicado__isnull=True)) | - Q(ta_publicado=dvt.ta) - ).update( - dispositivo_vigencia=dvt, - 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) - with transaction.atomic(): - 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) - d.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!!!'))} - except: - return {'message': str(_('Ocorreu um erro na atualização do ' - 'Dispositivo de Vigência'))} - - def delete_item_dispositivo(self, context): - return self.delete_bloco_dispositivo(context, bloco=False) - - def delete_bloco_dispositivo(self, context, bloco=True): - base = Dispositivo.objects.get(pk=context['dispositivo_id']) - - base_anterior = Dispositivo.objects.order_by('-ordem').filter( - ta_id=base.ta_id, - ordem__lt=base.ordem - ).first() - - data = {} - if base_anterior: - data = self.get_json_for_refresh(base_anterior) - else: - base_anterior = Dispositivo.objects.order_by('ordem').filter( - ta_id=base.ta_id, - ordem__lt=base.ordem - ).first() - if base_anterior: - data = self.get_json_for_refresh(base_anterior) - else: - data['pk'] = '' - - ta_base = base.ta - - # TODO: a linha abaixo causa atualização da tela inteira... - # retirar a linha abaixo e identificar atualizações pontuais - data['pai'] = [-1, ] - - try: - with transaction.atomic(): - data['message'] = str(self.remover_dispositivo(base, bloco)) - ta_base.ordenar_dispositivos() - except Exception as e: - print(e) - data['pk'] = context['dispositivo_id'] - data['message'] = str(_('Ocorreu um erro ao ' - 'excluir esse Dispositivo')) - - return data - - def remover_dispositivo(self, base, bloco): - base_ordem = base.ordem - if base.dispositivo_subsequente or base.dispositivo_substituido: - p = base.dispositivo_substituido - n = base.dispositivo_subsequente - - if n: - # print(n.id, n) - n.dispositivo_substituido = p - n.save() + if n: + # print(n.id, n) + n.dispositivo_substituido = p + n.save() if p: # print(p.id, p) p.dispositivo_subsequente = n if n: - p.fim_vigencia = n.ini_vigencia - timedelta(days=1) - p.fim_eficacia = n.ini_eficacia - timedelta(days=1) + p.fim_vigencia = n.inicio_vigencia - timedelta(days=1) + p.fim_eficacia = n.inicio_eficacia - timedelta(days=1) else: p.fim_vigencia = None p.fim_eficacia = None for d in base.dispositivos_filhos_set.all(): - if d.is_relative_auto_insert(): + if d.auto_inserido: self.remover_dispositivo(d, bloco) elif not bloco: p.dispositivos_filhos_set.add(d) @@ -1392,7 +1229,7 @@ class ActionsEditMixin: transferir para o caput imediatamente acima visto se tratar de uma exclusão de item?""" d_nivel_old = d.nivel - if d.is_relative_auto_insert(): + if d.auto_inserido: d.delete() continue @@ -1407,8 +1244,9 @@ class ActionsEditMixin: dispositivo_pai=base).first() if not anterior: - return _('Não é possível excluir este Dispositivo sem' - ' excluir toda a sua estrutura!!!') + raise Exception( + _('Não é possível excluir este Dispositivo sem' + ' excluir toda a sua estrutura!!!')) if anterior.tipo_dispositivo == d.tipo_dispositivo: d.dispositivo_pai = anterior.dispositivo_pai @@ -1425,9 +1263,10 @@ class ActionsEditMixin: for candidato in parents: if candidato == base: - return _('Não é possível excluir este ' - 'Dispositivo sem ' - 'excluir toda a sua estrutura!!!') + raise Exception( + _('Não é possível excluir este ' + 'Dispositivo sem ' + 'excluir toda a sua estrutura!!!')) if (candidato.tipo_dispositivo == d.tipo_dispositivo): d.dispositivo_pai = candidato.dispositivo_pai @@ -1458,6 +1297,12 @@ class ActionsEditMixin: d.nivel = candidato.nivel + 1 d.rotulo = d.rotulo_padrao() break + else: + + raise Exception( + _('Não é possível excluir este ' + 'Dispositivo sem ' + 'excluir toda a sua estrutura!!!')) if not parents: d.dispositivo_pai = anterior @@ -1485,150 +1330,427 @@ class ActionsEditMixin: ordem__gt=base_ordem, tipo_dispositivo_id=base.tipo_dispositivo_id) - if proxima_articulacao: - irmaos_posteriores = irmaos_posteriores.exclude( - ordem__gte=proxima_articulacao.ordem) + if proxima_articulacao: + irmaos_posteriores = irmaos_posteriores.exclude( + ordem__gte=proxima_articulacao.ordem) + + # excluir e renumerar irmaos + profundidade_base = base.get_profundidade() + base.delete() + + for irmao in irmaos_posteriores: + irmao.transform_in_prior( + profundidade=profundidade_base) + irmao.rotulo = irmao.rotulo_padrao() + irmao.save() + + irmaos = pai_base.dispositivos_filhos_set.\ + filter(tipo_dispositivo=base.tipo_dispositivo) + + if (irmaos.count() == 1 and + ';' in irmaos[0]. + tipo_dispositivo.rotulo_prefixo_texto): + i = irmaos[0] + i.set_numero_completo([0, 0, 0, 0, 0, 0, ]) + i.rotulo = i.rotulo_padrao(local_insert=1) + i.save() + else: + # Renumerar Dispostivos de Contagem Contínua + # de dentro da base se pai + dcc = Dispositivo.objects.order_by('ordem').filter( + ta_id=base.ta_id, + ordem__gt=base.ordem, + tipo_dispositivo__contagem_continua=True) + + if proxima_articulacao: + dcc = dcc.exclude( + ordem__gte=proxima_articulacao.ordem) + + base_adicao = {} + + nivel_zero_anterior = base.get_nivel_zero_anterior() + if nivel_zero_anterior: + nivel_zero_anterior = nivel_zero_anterior.ordem + else: + nivel_zero_anterior = 0 + + dcc = list(dcc) + for d in dcc: # ultimo DCC do tipo encontrado + + if d.tipo_dispositivo.class_css not in base_adicao: + ultimo_dcc = Dispositivo.objects.order_by( + 'ordem').filter( + ta_id=base.ta_id, + ordem__lt=base.ordem, + ordem__gt=nivel_zero_anterior, + tipo_dispositivo__contagem_continua=True, + tipo_dispositivo=d.tipo_dispositivo).last() + + if not ultimo_dcc: + break + + base_adicao[ + d.tipo_dispositivo.class_css] = ultimo_dcc.\ + dispositivo0 + + d.dispositivo0 += base_adicao[ + d.tipo_dispositivo.class_css] + + d.rotulo = d.rotulo_padrao() + dcc.reverse() + for d in dcc: + d.save() + + base.delete() + + # em Bloco + else: + + # Religar numeração de dispositivos de contagem contínua + # que serão excluidos + # pbi - proxima base independente + pbi = Dispositivo.objects.\ + order_by('ordem').filter( + ta_id=base.ta_id, + ordem__gt=base_ordem, + nivel__lte=base.nivel).first() + + if not pbi: + base.delete() + else: + dcc_a_excluir = Dispositivo.objects.order_by( + 'ordem').filter( + ta_id=base.ta_id, + ordem__gte=base_ordem, + ordem__lt=pbi.ordem, + tipo_dispositivo__contagem_continua=True) + + if proxima_articulacao: + dcc_a_excluir = dcc_a_excluir.exclude( + ordem__gte=proxima_articulacao.ordem) + + religado = {} + + for d in dcc_a_excluir: + if d.tipo_dispositivo.class_css in religado: + continue + religado[ + d.tipo_dispositivo.class_css] = d.dispositivo0 + + dcc_a_religar = Dispositivo.objects.filter( + ta_id=d.ta_id, + ordem__gte=pbi.ordem, + tipo_dispositivo=d.tipo_dispositivo) + + if proxima_articulacao: + dcc_a_religar = dcc_a_religar.exclude( + ordem__gte=proxima_articulacao.ordem) + + primeiro_a_religar = 0 + for dr in dcc_a_religar: + if not primeiro_a_religar: + primeiro_a_religar = dr.dispositivo0 + base.delete() + + dr.dispositivo0 = ( + dr.dispositivo0 - + primeiro_a_religar + d.dispositivo0) + dr.rotulo = dr.rotulo_padrao() + + dr.save(clean=base != dr) + if base.pk: + base.delete() + + return '' + + +class ActionDispositivoCreateMixin(ActionsCommonsMixin): + + def allowed_inserts(self): + request = self.request + try: + if request and 'perfil_estrutural' not in request.session: + self.set_perfil_in_session(request) + + perfil_pk = request.session['perfil_estrutural'] + + base = Dispositivo.objects.get(pk=self.kwargs['dispositivo_id']) + + prox_possivel = Dispositivo.objects.filter( + ordem__gt=base.ordem, + nivel__lte=base.nivel, + ta_id=base.ta_id)[:1] + + if prox_possivel.exists(): + prox_possivel = prox_possivel[0] + else: + prox_possivel = None + + result = [{'tipo_insert': force_text(_('Inserir Depois')), + 'icone': '↷ ', + 'action': 'json_add_next', + 'itens': []}, + {'tipo_insert': force_text(_('Inserir Dentro')), + 'icone': '⇲ ', + 'action': 'json_add_in', + 'itens': []}, + {'tipo_insert': force_text(_('Inserir Antes')), + 'icone': '↶ ', + 'action': 'json_add_prior', + 'itens': []} + ] + + # Possíveis inserções sequenciais já existentes + parents = base.get_parents() + parents.insert(0, base) + nivel = sys.maxsize + for dp in parents: + + if dp.nivel >= nivel: + continue + + if dp.auto_inserido: + continue + + if prox_possivel and \ + dp.tipo_dispositivo != base.tipo_dispositivo and\ + dp.nivel < prox_possivel.nivel and\ + not prox_possivel.tipo_dispositivo.permitido_inserir_in( + dp.tipo_dispositivo, + perfil_pk=perfil_pk): + + if dp.tipo_dispositivo != prox_possivel.tipo_dispositivo: + continue + + nivel = dp.nivel + + # um do mesmo para inserção antes + if dp == base: + result[2]['itens'].append({ + 'class_css': dp.tipo_dispositivo.class_css, + 'tipo_pk': dp.tipo_dispositivo.pk, + 'variacao': 0, + 'provavel': '%s (%s)' % ( + dp.rotulo_padrao(local_insert=1), + dp.tipo_dispositivo.nome,), + 'dispositivo_base': base.pk}) + + if dp.dispositivo_pai: + flag_pv = dp.tipo_dispositivo.permitido_variacao( + dp.dispositivo_pai.tipo_dispositivo, + perfil_pk=perfil_pk) + else: + flag_pv = False + + r = [] + flag_direcao = 1 + flag_variacao = 0 + while True: + if dp.dispositivo0 == 0: + local_insert = 1 + else: + local_insert = 0 + + rt = dp.transform_in_next(flag_direcao) + if not rt[0]: + break + flag_variacao += rt[1] + r.append({'class_css': dp.tipo_dispositivo.class_css, + 'tipo_pk': dp.tipo_dispositivo.pk, + 'variacao': flag_variacao, + 'provavel': '%s (%s)' % ( + dp.rotulo_padrao(local_insert), + dp.tipo_dispositivo.nome,), + 'dispositivo_base': base.pk}) + + flag_direcao = -1 + + r.reverse() + + if not flag_pv: + r = [r[0], ] + + if len(r) > 0 and dp.tipo_dispositivo.formato_variacao0 == \ + TipoDispositivo.FNCN: + r = [r[0], ] - # excluir e renumerar irmaos - profundidade_base = base.get_profundidade() - base.delete() + if dp.tipo_dispositivo == base.tipo_dispositivo: + result[0]['itens'] += r + else: + result[0]['itens'] += r + result[2]['itens'] += r - for irmao in irmaos_posteriores: - irmao.transform_in_prior( - profundidade=profundidade_base) - irmao.rotulo = irmao.rotulo_padrao() - irmao.save() + if nivel == 0: + break - irmaos = pai_base.dispositivos_filhos_set.\ - filter(tipo_dispositivo=base.tipo_dispositivo) + # tipo do dispositivo base + tipb = base.tipo_dispositivo - if (irmaos.count() == 1 and - ';' in irmaos[0]. - tipo_dispositivo.rotulo_prefixo_texto): - i = irmaos[0] - i.set_numero_completo([0, 0, 0, 0, 0, 0, ]) - i.rotulo = i.rotulo_padrao(local_insert=1) - i.save() + for paradentro in [1, 0]: + if paradentro: + # Outros Tipos de Dispositivos PARA DENTRO + otds = TipoDispositivo.objects.order_by( + '-contagem_continua', 'id').all() else: - # Renumerar Dispostivos de Contagem Contínua - # de dentro da base se pai - dcc = Dispositivo.objects.order_by('ordem').filter( - ta_id=base.ta_id, - ordem__gt=base.ordem, - tipo_dispositivo__contagem_continua=True) - - if proxima_articulacao: - dcc = dcc.exclude( - ordem__gte=proxima_articulacao.ordem) + # Outros Tipos de Dispositivos PARA FORA + classes_ja_inseridas = [] + for c in result[0]['itens']: + if c['class_css'] not in classes_ja_inseridas: + classes_ja_inseridas.append(c['class_css']) + for c in result[1]['itens']: + if c['class_css'] not in classes_ja_inseridas: + classes_ja_inseridas.append(c['class_css']) + otds = TipoDispositivo.objects.order_by( + '-contagem_continua', 'id').all().exclude( + class_css__in=classes_ja_inseridas) - base_adicao = {} + for td in otds: - nivel_zero_anterior = base.get_nivel_zero_anterior() - if nivel_zero_anterior: - nivel_zero_anterior = nivel_zero_anterior.ordem - else: - nivel_zero_anterior = 0 + if paradentro and not td.permitido_inserir_in( + tipb, + include_relative_autos=True, + perfil_pk=perfil_pk): + continue - dcc = list(dcc) - for d in dcc: # ultimo DCC do tipo encontrado + base.tipo_dispositivo = td - if d.tipo_dispositivo.class_css not in base_adicao: - ultimo_dcc = Dispositivo.objects.order_by( - 'ordem').filter( - ta_id=base.ta_id, - ordem__lt=base.ordem, - ordem__gt=nivel_zero_anterior, - tipo_dispositivo__contagem_continua=True, - tipo_dispositivo=d.tipo_dispositivo).last() + if not paradentro: - if not ultimo_dcc: + flag_insercao = False + for possivelpai in parents: + if td.permitido_inserir_in( + possivelpai.tipo_dispositivo, + include_relative_autos=True, + perfil_pk=perfil_pk): + flag_insercao = True break - base_adicao[ - d.tipo_dispositivo.class_css] = ultimo_dcc.\ - dispositivo0 + if not flag_insercao: + continue - d.dispositivo0 += base_adicao[ - d.tipo_dispositivo.class_css] + if possivelpai.auto_inserido: + continue - d.rotulo = d.rotulo_padrao() - dcc.reverse() - for d in dcc: - d.save() + if prox_possivel: + if prox_possivel.nivel == base.nivel: + if prox_possivel.tipo_dispositivo != td and\ + not prox_possivel.tipo_dispositivo.\ + permitido_inserir_in( + td, perfil_pk=perfil_pk): + continue + else: + if possivelpai.tipo_dispositivo != \ + prox_possivel.tipo_dispositivo and\ + not prox_possivel.tipo_dispositivo.\ + permitido_inserir_in( + possivelpai.tipo_dispositivo, + perfil_pk=perfil_pk) and \ + possivelpai.nivel < \ + prox_possivel.nivel: + continue + base.dispositivo_pai = possivelpai + Dispositivo.set_numero_for_add_in( + possivelpai, base, td) + else: + Dispositivo.set_numero_for_add_in(base, base, td) - base.delete() + r = [{'class_css': td.class_css, + 'tipo_pk': td.pk, + 'variacao': 0, + 'provavel': '%s (%s)' % ( + base.rotulo_padrao(1, paradentro), + td.nome,), + 'dispositivo_base': base.pk}] - # em Bloco - else: + if paradentro == 1: + """if (tipb.class_css == 'caput' and + td.class_css == 'paragrafo'): + result[0]['itens'].insert(0, r[0]) + else:""" + result[1]['itens'] += r + else: + result[2]['itens'] += r + result[0]['itens'] += r - # Religar numeração de dispositivos de contagem contínua - # que serão excluidos - # pbi - proxima base independente - pbi = Dispositivo.objects.\ - order_by('ordem').filter( - ta_id=base.ta_id, - ordem__gt=base_ordem, - nivel__lte=base.nivel).first() + # if len(result[0]['itens']) < len(result[1]['itens']): + # r = result[0] + # result.remove(result[0]) + # result.insert(1, r) - if not pbi: - base.delete() - else: - dcc_a_excluir = Dispositivo.objects.order_by( - 'ordem').filter( - ta_id=base.ta_id, - ordem__gte=base_ordem, - ordem__lt=pbi.ordem, - tipo_dispositivo__contagem_continua=True) + # remover temporariamente a opção inserir antes + # confirmar necessidade + if len(result) > 2: + result.pop() - if proxima_articulacao: - dcc_a_excluir = dcc_a_excluir.exclude( - ordem__gte=proxima_articulacao.ordem) + # if tipb.dispositivo_de_articulacao and\ + # tipb.dispositivo_de_alteracao: + # result.pop() - religado = {} + return result - for d in dcc_a_excluir: - if d.tipo_dispositivo.class_css in religado: - continue - religado[ - d.tipo_dispositivo.class_css] = d.dispositivo0 + except Exception as e: + print(e) - dcc_a_religar = Dispositivo.objects.filter( - ta_id=d.ta_id, - ordem__gte=pbi.ordem, - tipo_dispositivo=d.tipo_dispositivo) + return {} - if proxima_articulacao: - dcc_a_religar = dcc_a_religar.exclude( - ordem__gte=proxima_articulacao.ordem) + def json_set_dvt(self, context): + # Dispositivo de Vigência do Texto Original e de Dpts Alterados + dvt = Dispositivo.objects.get(pk=self.kwargs['dispositivo_id']) - primeiro_a_religar = 0 - for dr in dcc_a_religar: - if not primeiro_a_religar: - primeiro_a_religar = dr.dispositivo0 - base.delete() + if dvt.auto_inserido: + dvt = dvt.dispositivo_pai - dr.dispositivo0 = ( - dr.dispositivo0 - - primeiro_a_religar + d.dispositivo0) - dr.rotulo = dr.rotulo_padrao() + try: + Dispositivo.objects.filter( + (Q(ta=dvt.ta) & Q(ta_publicado__isnull=True)) | + Q(ta_publicado=dvt.ta) + ).update( + dispositivo_vigencia=dvt, + inicio_vigencia=dvt.inicio_vigencia, + inicio_eficacia=dvt.inicio_eficacia) - dr.save(clean=base != dr) - if base.pk: - base.delete() + dps = Dispositivo.objects.filter(dispositivo_vigencia_id=dvt.pk, + ta_publicado_id=dvt.ta_id) + with transaction.atomic(): + 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) + d.save() - return '' + 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() - def add_prior(self, context): + data = {'pk': dvt.pk, + 'pai': [dvt.pk, ]} + self.set_message(data, 'success', _('Dispositivo de Vigência atualizado ' + 'com sucesso!!!')) + + return data + except: + data = {} + self.set_message(data, + 'success', + _('Ocorreu um erro na atualização do ' + 'Dispositivo de Vigência')) + + return data + + def json_add_prior(self, context): return {} - def add_in(self, context): - return self.add_next(context, local_add='add_in') + def json_add_in(self, context): + return self.json_add_next(context, local_add='json_add_in') - def add_next(self, context, local_add='add_next'): + def json_add_next(self, context, local_add='json_add_next'): try: dp_auto_insert = None - base = Dispositivo.objects.get(pk=context['dispositivo_id']) + base = Dispositivo.objects.get(pk=self.kwargs['dispositivo_id']) tipo = TipoDispositivo.objects.get(pk=context['tipo_pk']) pub_last = Publicacao.objects.order_by( 'data', 'hora').filter(ta=base.ta).last() @@ -1644,23 +1766,6 @@ class ActionsEditMixin: else: raise Exception('Não existe perfil padrão!') - tipos_dp_auto_insert = tipo.filhos_permitidos.filter( - filho_de_insercao_automatica=True, - perfil_id=context['perfil_pk']) - - count_auto_insert = 0 - for tipoauto in tipos_dp_auto_insert: - qtdp = tipoauto.quantidade_permitida - if qtdp >= 0: - qtdp -= Dispositivo.objects.filter( - ta_id=base.ta_id, - tipo_dispositivo_id=tipoauto.filho_permitido.pk - ).count() - if qtdp > 0: - count_auto_insert += 1 - else: - count_auto_insert += 1 - dp_irmao = None dp_pai = None for dp in parents: @@ -1713,18 +1818,20 @@ class ActionsEditMixin: if pp.exists() and pp[0].quantidade_permitida >= 0: qtd_existente = Dispositivo.objects.filter( ta_id=dp.ta_id, - tipo_dispositivo_id=dp.tipo_dispositivo_id).count() + tipo_dispositivo_id=dp.tipo_dispositivo_id, + dispositivo_pai=dp.dispositivo_pai).count() if qtd_existente >= pp[0].quantidade_permitida: - return {'pk': base.pk, - 'pai': [base.dispositivo_pai.pk, ], - 'message': str(_('Limite de inserções de ' - 'dispositivos deste tipo ' - 'foi excedido.')) - } + data = {'pk': base.pk, + 'pai': [base.dispositivo_pai.pk, ]} + self.set_message(data, 'warning', + _('Limite de inserções de ' + 'dispositivos deste tipo ' + 'foi excedido.'), time=6000) + return data ordem = base.criar_espaco( - espaco_a_criar=1 + count_auto_insert, local=local_add) + espaco_a_criar=1, local=local_add) dp.rotulo = dp.rotulo_padrao() dp.ordem = ordem @@ -1733,9 +1840,32 @@ class ActionsEditMixin: dp.publicacao = pub_last dp.save() + tipos_dp_auto_insert = tipo.filhos_permitidos.filter( + filho_de_insercao_automatica=True, + perfil_id=context['perfil_pk']) + + count_auto_insert = 0 + for tipoauto in tipos_dp_auto_insert: + qtdp = tipoauto.quantidade_permitida + if qtdp >= 0: + qtdp -= Dispositivo.objects.filter( + ta_id=dp.ta_id, + dispositivo_pai_id=dp.id, + tipo_dispositivo_id=tipoauto.filho_permitido.pk + ).count() + if qtdp > 0: + count_auto_insert += 1 + else: + count_auto_insert += 1 + # Inserção automática if count_auto_insert: + + ordem = dp.criar_espaco( + espaco_a_criar=count_auto_insert, local=local_add) + dp_pk = dp.pk + dp.ordem = ordem dp.nivel += 1 for tipoauto in tipos_dp_auto_insert: dp.dispositivo_pai_id = dp_pk @@ -1747,11 +1877,13 @@ class ActionsEditMixin: dp.set_numero_completo([1, 0, 0, 0, 0, 0, ]) dp.rotulo = dp.rotulo_padrao() dp.texto = '' - dp.ordem = dp.ordem + Dispositivo.INTERVALO_ORDEM dp.publicacao = pub_last + dp.auto_inserido = True dp.save() dp_auto_insert = dp + + ordem += Dispositivo.INTERVALO_ORDEM dp = Dispositivo.objects.get(pk=dp_pk) ''' Reenquadrar todos os dispositivos que possuem pai @@ -1867,16 +1999,419 @@ class ActionsEditMixin: not dp.tipo_dispositivo.dispositivo_de_articulacao: dp.dispositivo_pai.ordenar_bloco_alteracao() + if dp_auto_insert is None: + data = self.get_json_for_refresh(dp) + else: + data = self.get_json_for_refresh(dp=dp, dpauto=dp_auto_insert) + + # data['action'] = 'get_form_base' + return data + except Exception as e: print(e) - if dp_auto_insert is None: - data = self.get_json_for_refresh(dp) + +class ActionsEditMixin(ActionDragAndMoveDispositivoAlteradoMixin, + ActionDeleteDispositivoMixin, + ActionDispositivoCreateMixin): + + def render_to_json_response(self, context, **response_kwargs): + + action = getattr(self, context['action']) + + if 'tipo_pk' in self.request.GET: + context['tipo_pk'] = self.request.GET['tipo_pk'] + + if 'variacao' in self.request.GET: + context['variacao'] = self.request.GET['variacao'] + + if 'perfil_estrutural' in self.request.session: + context['perfil_pk'] = self.request.session['perfil_estrutural'] + + data = action(context) + + if 'message' in context and 'message' not in data: + data['message'] = context['message'] + + return JsonResponse(data, safe=False) + + def get_queryset_perfil_estrutural(self): + perfis = PerfilEstruturalTextoArticulado.objects.all() + return perfis + + def json_get_perfis(self, context): + + if 'perfil_pk' in self.request.GET: + self.set_perfil_in_session( + self.request, self.request.GET['perfil_pk']) + elif 'perfil_estrutural' not in self.request.session: + self.set_perfil_in_session(request=self.request) + + data = {'pk': self.kwargs['dispositivo_id'], + 'pai': [self.kwargs['dispositivo_id'], ]} + + return data + + def set_perfil_in_session(self, request=None, perfil_id=0): + if not request: + return None + + if perfil_id: + perfil = PerfilEstruturalTextoArticulado.objects.get( + pk=perfil_id) + request.session['perfil_estrutural'] = perfil.pk + return perfil.pk + else: + perfis = PerfilEstruturalTextoArticulado.objects.filter( + padrao=True)[:1] + + if not perfis.exists(): + request.session.pop('perfil_estrutural') + else: + request.session['perfil_estrutural'] = perfis[0].pk + return perfis[0].pk + return None + + def registra_alteracao(self, bloco_alteracao, dispositivo_a_alterar): + """ + Caracteristicas: + 1 - Se é um dispositivo simples e sem subsequente + - filhos devem ser transferidos + + 2 - Se é um dispositivo simples com subsequente + - não deveria ter filhos locais + - substituidos e subsequentes devem ser religados + + 3 - Se é um dispositivo articulado e sem subsequente + - filhos locais devem ser transferidos + + 4 - Se é um dispositivo articulado com subsequente + - não deveria ter filhos locais + + 5 - Alterações em dispositivo articulado só são relevantes para + alteração de rótulo. O editor dinâmico não possibilita essa + mudança, porém, após registro de alteração, a mudança de rótulo + pode ser feita no editor avançado. + """ + + data = {} + data.update({'pk': bloco_alteracao.pk, + 'pai': [bloco_alteracao.pk, ]}) + + history = dispositivo_a_alterar.history() + + for d in history: + """FIXME: A comparação "<" deverá ser mudada para + "<=" caso um seja necessário permitir duas alterações + com mesmo inicio_vigencia no mesmo dispositivo. Neste Caso, + a sequencia correta ficará a cargo dos reposicionamentos entre + dispositivos de mesmo nível, + """ + if d.inicio_vigencia < bloco_alteracao.inicio_vigencia: + dispositivo_a_alterar = d + break + + if (dispositivo_a_alterar.inicio_vigencia > + bloco_alteracao.inicio_vigencia): + self.set_message( + data, 'danger', + _('Não é possível alterar um Dispositivo com início de ' + 'Vigência posterior a data de Vigência do Dispositivo ' + 'Alterador!'), time=10000) + return data + + ndp = Dispositivo.new_instance_based_on( + dispositivo_a_alterar, dispositivo_a_alterar.tipo_dispositivo) + + ndp.rotulo = dispositivo_a_alterar.rotulo + ndp.texto = dispositivo_a_alterar.texto + ndp.publicacao = bloco_alteracao.publicacao + + ndp.dispositivo_vigencia = bloco_alteracao.dispositivo_vigencia + if ndp.dispositivo_vigencia: + ndp.inicio_eficacia = ndp.dispositivo_vigencia.inicio_eficacia + ndp.inicio_vigencia = ndp.dispositivo_vigencia.inicio_vigencia else: - data = self.get_json_for_refresh(dp=dp, dpauto=dp_auto_insert) + ndp.inicio_eficacia = bloco_alteracao.inicio_eficacia + ndp.inicio_vigencia = bloco_alteracao.inicio_vigencia + + try: + ordem = dispositivo_a_alterar.criar_espaco( + espaco_a_criar=1, local='json_add_in') + + ndp.ordem = ordem + ndp.dispositivo_atualizador = bloco_alteracao + ndp.ta_publicado = bloco_alteracao.ta + + p = dispositivo_a_alterar + n = dispositivo_a_alterar.dispositivo_subsequente + + ndp.dispositivo_substituido = p + ndp.dispositivo_subsequente = n + + if n: + ndp.fim_eficacia = n.inicio_eficacia - \ + timedelta(days=1) + ndp.fim_vigencia = n.inicio_vigencia - \ + timedelta(days=1) + ndp.save() + + p.dispositivo_subsequente = ndp + p.fim_eficacia = ndp.inicio_eficacia - timedelta(days=1) + p.fim_vigencia = ndp.inicio_vigencia - timedelta(days=1) + p.save() + + if n: + # a ordem desse objeto foi alterada pela função criar_espaco + # deve ser recarregado para atualização + n.refresh_from_db() + n.dispositivo_substituido = ndp + n.save() + + filhos_diretos = dispositivo_a_alterar.dispositivos_filhos_set + for d in filhos_diretos.all(): + d.dispositivo_pai = ndp + d.save() + + self.set_message( + data, 'success', + _('Dispositivo de Alteração adicionado com sucesso.')) + + except Exception as e: + print(e) + + data.update({'pk': ndp.pk, + 'pai': [bloco_alteracao.pk, ]}) return data + +class DispositivoDinamicEditView( + CompMixin, ActionsEditMixin, TextEditView, UpdateView): + template_name = 'compilacao/text_edit_bloco.html' + model = Dispositivo + form_class = DispositivoEdicaoBasicaForm + contador = -1 + + def get_initial(self): + initial = UpdateView.get_initial(self) + + #perfil_pk = self.set_perfil_in_session(self.request) + + if 'action' in self.request.GET: + initial.update({'editor_type': self.request.GET['action']}) + + initial.update({'dispositivo_search_form': reverse_lazy( + 'sapl.compilacao:dispositivo_search_form')}) + return initial + + def get_form(self, form_class=None): + + if self.action and self.action.startswith('get_form_'): + if form_class is None: + form_class = self.get_form_class() + return form_class(**self.get_form_kwargs()) + else: + return None + + def get(self, request, *args, **kwargs): + + if 'action' not in request.GET: + self.action = None + self.template_name = 'compilacao/text_edit_bloco.html' + return TextEditView.get(self, request, *args, **kwargs) + + self.template_name = 'compilacao/ajax_form.html' + self.action = request.GET['action'] + + if self.action.startswith('get_form_'): + if self.action.endswith('_base'): + self.form_class = DispositivoEdicaoBasicaForm + elif self.action.endswith('_alteracao'): + self.form_class = DispositivoRegistroAlteracaoForm + context = self.get_context_data() + return self.render_to_response(context) + elif self.action.startswith('get_actions'): + self.form_class = None + self.template_name = 'compilacao/ajax_actions_dinamic_edit.html' + self.object = Dispositivo.objects.get( + pk=self.kwargs['dispositivo_id']) + + ta_id = self.kwargs['ta_id'] + + context = {} + context['object'] = self.object + + if ta_id == str(self.object.ta_id): + context['allowed_inserts'] = self.allowed_inserts() + + if 'perfil_pk' in request.GET: + self.set_perfil_in_session( + request, request.GET['perfil_pk']) + elif 'perfil_estrutural' not in request.session: + self.set_perfil_in_session(request=request) + + context['perfil_estrutural_list' + ] = PerfilEstruturalTextoArticulado.objects.all() + + return self.render_to_response(context) + + elif self.action.startswith('json_'): + context = self.get_context_data() + return self.render_to_json_response(context) + + return JsonResponse({}, safe=False) + + def post(self, request, *args, **kwargs): + + d = Dispositivo.objects.get( + pk=self.kwargs['dispositivo_id']) + + formtype = request.POST['formtype'] + if formtype == 'get_form_alteracao': + + dispositivo_a_alterar = Dispositivo.objects.get( + pk=request.POST['dispositivo_alterado']) + + data = self.registra_alteracao(d, dispositivo_a_alterar) + + elif formtype == 'get_form_base': + texto = request.POST['texto'].strip() + texto_atualizador = request.POST['texto_atualizador'].strip() + texto_atualizador = texto_atualizador \ + if texto != texto_atualizador else '' + visibilidade = request.POST['visibilidade'] + + # if d.texto != '': + # d.texto = texto + # d.save() + # return self.get(request, *args, **kwargs) + d_texto = d.texto + d.texto = texto.strip() + d.texto_atualizador = texto_atualizador.strip() + d.visibilidade = not visibilidade or visibilidade == 'True' + d.save() + + if texto != '' and d.ta_id == int(self.kwargs['ta_id']): + dnext = Dispositivo.objects.filter( + ta_id=d.ta_id, + ordem__gt=d.ordem, + texto='', + tipo_dispositivo__dispositivo_de_articulacao=False)[:1] + + if not dnext.exists(): + dnext = [] + dnext.append(d) + pais = [d.dispositivo_pai_id, ] + else: + + if dnext[0].nivel > d.nivel: + pais = [d.pk, ] + else: + if dnext[0].dispositivo_pai_id == d.dispositivo_pai_id: + pais = [dnext[0].dispositivo_pai_id, ] + else: + pais = [ + dnext[0].dispositivo_pai_id, + d.dispositivo_pai_id] + + data = {'pk': dnext[0].pk + if not d_texto else 0, 'pai': pais} + elif d.ta_id != int(self.kwargs['ta_id']): + data = {'pk': 0, + 'pai': [d.dispositivo_atualizador_id, ]} + else: + data = {'pk': d.pk + if not d_texto or not d.texto else 0, 'pai': [d.pk, ]} + + self.set_message(data, 'success', + _('Dispositivo alterado com sucesso.')) + + return JsonResponse(data, safe=False) + + +class DispositivoSimpleEditView__Old: + template_name = 'compilacao/text_edit_bloco.html' + + def get_queryset_perfil_estrutural(self): + perfis = PerfilEstruturalTextoArticulado.objects.all() + return perfis + + def get(self, request, *args, **kwargs): + + try: + if 'perfil_pk' in request.GET: + self.set_perfil_in_session( + request, request.GET['perfil_pk']) + elif 'perfil_estrutural' not in request.session: + self.set_perfil_in_session(request=request) + + self.object_list = self.get_queryset() + + self.perfil_estrutural_list = self.get_queryset_perfil_estrutural() + + context = self.get_context_data( + object_list=self.object_list, + perfil_estrutural_list=self.perfil_estrutural_list + ) + except Exception as e: + print(e) + + return self.render_to_response(context) + + def get_queryset(self): + self.flag_alteradora = -1 + self.flag_nivel_ini = 0 + self.flag_nivel_old = -1 + + try: + self.pk_edit = int(self.request.GET['edit']) + except: + self.pk_edit = 0 + self.pk_view = int(self.kwargs['dispositivo_id']) + + try: + if self.pk_edit == self.pk_view: + bloco = Dispositivo.objects.get( + pk=self.kwargs['dispositivo_id']) + else: + bloco = Dispositivo.objects.get( + pk=self.kwargs['dispositivo_id']) + except Dispositivo.DoesNotExist: + return [] + + self.flag_nivel_old = bloco.nivel - 1 + self.flag_nivel_ini = bloco.nivel + + if self.pk_edit == self.pk_view: + return [bloco, ] + + proximo_bloco = Dispositivo.objects.filter( + ordem__gt=bloco.ordem, + nivel__lte=bloco.nivel, + ta_id=self.kwargs['ta_id'])[:1] + + if proximo_bloco.count() == 0: + itens = Dispositivo.objects.filter( + ordem__gte=bloco.ordem, + ta_id=self.kwargs['ta_id'] + ).select_related(*DISPOSITIVO_SELECT_RELATED) + else: + itens = Dispositivo.objects.filter( + ordem__gte=bloco.ordem, + ordem__lt=proximo_bloco[0].ordem, + ta_id=self.kwargs['ta_id'] + ).select_related(*DISPOSITIVO_SELECT_RELATED) + return itens + + +class ActionsEditMixin_old: + + def render_to_json_response(self, context, **response_kwargs): + + action = getattr(self, context['action']) + return JsonResponse(action(context), safe=False) + def get_json_for_refresh(self, dp, dpauto=None): if dp.tipo_dispositivo.contagem_continua: @@ -1915,51 +2450,8 @@ class ActionsEditMixin: return data - def move_dpt_alterado(self, context): - - bloco = Dispositivo.objects.get(pk=context['bloco_pk']) - dpt = Dispositivo.objects.get(pk=context['dispositivo_id']) - - if dpt.tipo_dispositivo.dispositivo_de_alteracao: - dpt.dispositivo_pai = bloco - else: - dpt.dispositivo_atualizador = bloco - - filhos = Dispositivo.objects.order_by( - 'ordem_bloco_atualizador').filter( - Q(dispositivo_pai_id=bloco.pk) | - Q(dispositivo_atualizador_id=bloco.pk)) - - if not filhos.exists(): - dpt.ordem_bloco_atualizador = Dispositivo.INTERVALO_ORDEM - else: - index = int(context['index']) - fpks = filhos.values_list( - 'pk', flat=True).order_by('ordem_bloco_atualizador') - - index_dpt = 0 - try: - index_dpt = list(fpks).index(dpt.pk) - except: - pass - - filho_index = filhos[ - index if index_dpt >= index - else index + 1] if ( - index if index_dpt >= index - else index + 1) < filhos.count() else filhos.last() - if filhos.last() == filho_index: - dpt.ordem_bloco_atualizador = \ - filho_index.ordem_bloco_atualizador + 1 - else: - dpt.ordem_bloco_atualizador = \ - filho_index.ordem_bloco_atualizador - 1 - - dpt.save() - bloco.ordenar_bloco_alteracao() - -class ActionsEditView(ActionsEditMixin, TemplateView): +class ActionsEditView_Old(ActionsEditMixin, TemplateView): def render_to_response(self, context, **response_kwargs): context['action'] = self.request.GET['action'] @@ -1977,7 +2469,7 @@ class ActionsEditView(ActionsEditMixin, TemplateView): del self.request.session['herancas'] del self.request.session['herancas_fila'] - if context['action'] == 'move_dpt_alterado': + if context['action'] == 'drag_move_dpt_alterado': context['index'] = self.request.GET['index'] context['bloco_pk'] = self.request.GET['bloco_pk'] @@ -2153,7 +2645,10 @@ class DispositivoSearchFragmentFormView(ListView): q = q & Q(**{ 'ta__texto_articulado__' + column_field: tipo_model.pk }) - result = result.filter(q)[:n] + if n: + result = result.filter(q)[:n] + else: + result = result.filter(q) for d in result: if not d.ta.content_object or\ @@ -2177,7 +2672,7 @@ class DispositivoSearchModalView(FormView): form_class = DispositivoSearchModalForm -class DispositivoEdicaoBasicaView(FormMessagesMixin, UpdateView): +class DispositivoEdicaoBasicaView(CompMixin, FormMessagesMixin, UpdateView): model = Dispositivo template_name = 'compilacao/dispositivo_form_edicao_basica.html' form_class = DispositivoEdicaoBasicaForm @@ -2249,7 +2744,7 @@ class DispositivoEdicaoBasicaView(FormMessagesMixin, UpdateView): return UpdateView.get(self, request, *args, **kwargs) -class DispositivoEdicaoVigenciaView(FormMessagesMixin, UpdateView): +class DispositivoEdicaoVigenciaView(CompMixin, FormMessagesMixin, UpdateView): model = Dispositivo template_name = 'compilacao/dispositivo_form_vigencia.html' form_class = DispositivoEdicaoVigenciaForm @@ -2272,7 +2767,7 @@ class DispositivoEdicaoVigenciaView(FormMessagesMixin, UpdateView): kwargs={'ta_id': self.kwargs['ta_id'], 'pk': self.kwargs['pk']}) -class DispositivoDefinidorVigenciaView(FormMessagesMixin, FormView): +class DispositivoDefinidorVigenciaView(CompMixin, FormMessagesMixin, FormView): model = Dispositivo template_name = 'compilacao/dispositivo_form_definidor_vigencia.html' form_class = DispositivoDefinidorVigenciaForm @@ -2329,7 +2824,7 @@ class DispositivoDefinidorVigenciaView(FormMessagesMixin, FormView): return self.form_invalid(form) -class DispositivoEdicaoAlteracaoView(FormMessagesMixin, UpdateView): +class DispositivoEdicaoAlteracaoView(CompMixin, FormMessagesMixin, UpdateView): model = Dispositivo template_name = 'compilacao/dispositivo_form_alteracao.html' form_class = DispositivoEdicaoAlteracaoForm @@ -2359,13 +2854,13 @@ class DispositivoEdicaoAlteracaoView(FormMessagesMixin, UpdateView): try: with transaction.atomic(): return self.form_valid(form) - except: + except Exception as e: return self.form_invalid(form) else: return self.form_invalid(form) -class TextNotificacoesView(ListView, CompMixin, FormView): +class TextNotificacoesView(CompMixin, ListView, FormView): template_name = 'compilacao/text_notificacoes.html' form_class = TextNotificacoesForm @@ -2567,6 +3062,21 @@ class TextNotificacoesView(ListView, CompMixin, FormView): _('Dispositivo está substituindo um Dispositivo de outro ' 'Texto Articulado.')) + padd(r, type_notificacao, + 'sapl.compilacao:dispositivo_edit_alteracao', + r.dispositivo_substituido and + r.dispositivo_substituido.dispositivo_subsequente != r, + _('Dispositivo está substituindo um Dispositivo que não ' + 'possui este como seu Dispositivo Subsequente.')) + + padd(r, + type_notificacao, + 'sapl.compilacao:dispositivo_edit_alteracao', + r.dispositivo_subsequente and + r.dispositivo_subsequente.dispositivo_substituido != r, + _('Dispositivo foi substituído por outro que não ' + 'possui este como seu Dispositivo Substituído.')) + rr = [] for r in result: p = [] diff --git a/sapl/static/js/compilacao_edit.js b/sapl/static/js/compilacao_edit.js index 5b17f425e..94c279067 100644 --- a/sapl/static/js/compilacao_edit.js +++ b/sapl/static/js/compilacao_edit.js @@ -1,317 +1,448 @@ +function DispositivoEdit() { + // Função única - Singleton pattern - operador new sempre devolve o mesmo objeto + var instance; -var editortype = "textarea"; -var onSubmitEditForm = function(event) { + var editortype = "textarea"; - var texto = ''; - var editorTiny = tinymce.get('editdi_texto'); + if (!(this instanceof DispositivoEdit)) { + if (!instance) { + instance = new DispositivoEdit(); + } + return instance; + } + instance = this; + DispositivoEdit = function() { + return instance; + }; - if (editorTiny != null) - texto = editorTiny.getContent(); - else - texto = $('#editdi_texto').val(); + instance.bindActionsEditorType = function(event) { + editortype = this.getAttribute('editortype'); + SetCookie("editortype", editortype, 30); + var dpt = $(this).closest('.dpt'); - var formData = { - 'csrfmiddlewaretoken' : $('input[name=csrfmiddlewaretoken]').val(), - 'texto' : texto - }; + var pk = dpt.attr('pk'); + instance.clearEditSelected(); + instance.triggerBtnDptEdit(pk); + } - var url = $('.csform form').attr( "action_ajax" ); - $("#message_block").css("display", "block"); + instance.bindActionsClick = function(event) { + var pk = this.getAttribute('pk'); - $.post(url, formData) - .done(function(data) { + var form_data = { + 'action' : this.getAttribute('action'), + 'tipo_pk' : this.getAttribute('tipo_pk'), + 'perfil_pk' : this.getAttribute('perfil_pk'), + 'variacao' : this.getAttribute('variacao'), + }; - if (typeof data == "string") { - $('.dpt-selected').html(data); - clearEditSelected(); - reloadFunctionClicks(); - return; - } + var url = pk+'/refresh'; + instance.waitShow(); - clearEditSelected(); + $.get(url, form_data).done(function(data) { + instance.clearEditSelected(); + if (data.pk != null) { + if (data.message !== undefined) { + if (data.message.modal) { + instance.modalMessage(data.message.value, 'alert-'+data.message.type, function() { + instance.waitShow(); + instance.refreshScreenFocusPk(data); + }); + return; + } + else { + instance.message(data) + } + } + instance.refreshScreenFocusPk(data); + } + }).fail(instance.waitHide).always(instance.waitHide); + } - if (data.pk != null) - refreshScreenFocusPk(data); - else { - alert('Erro na inserção!'); - flag_refresh_all = false; - } + instance.clearEditSelected = function() { + $('.dpt-selected > .dpt-form').html(''); + $('.dpt-actions, .dpt-actions-bottom').html(''); + tinymce.remove(); + $('.dpt-selected').removeClass('dpt-selected'); + } - }).always(function() { - $("#message_block").css("display", "none"); - }); - if (event != null) - event.preventDefault(); -} + instance.editDispositivo = function(event) { + var obj_click = (event.target.classList.contains('dpt-link') + ? event.target + : (event.target.parentElement.classList.contains('dpt-link') + ? event.target.parentElement + : null)); + + if (obj_click && obj_click.getAttribute('href') && obj_click.getAttribute('href').length > 0) + return; + var dpt = $(this).closest('.dpt'); + if (dpt.hasClass('dpt-selected')) { + if (this.getAttribute('action') == 'editor-close') + instance.clearEditSelected(); + return; + } + instance.clearEditSelected(); + instance.loadActionsEdit(dpt); -var clickEditDispositivo = function(event) { - var _pk = event.currentTarget.getAttribute('pk'); - if ($('#dpt'+_pk).hasClass("dpt-selected")) { - clearEditSelected(); - return; + var formtype = dpt.attr('formtype'); + dpt.on(formtype, instance[formtype]); + instance.loadForm(dpt, formtype); } - clearEditSelected(); - clickUpdateDispositivo(event); -} -var clickUpdateDispositivo = function(event, __pk_refresh, __pk_edit, __action, flag_actions_vibible, flag_refresh_all) { - - var pk_refresh = __pk_refresh; - var pk_edit = __pk_edit; - var _action = __action; - var _variacao = ''; - var _tipo_pk = ''; - var _perfil_pk = ''; - - if (event != null) { - pk_refresh = event.currentTarget.getAttribute('pk'); - _action = $(this).attr('action'); - _variacao = $(this).attr('variacao'); - _tipo_pk = $(this).attr('tipo_pk'); - _perfil_pk = $(this).attr('perfil_pk'); + instance.gc = function() { + setTimeout(function() { + $('.dpt:not(.dpt-selected) > .dpt-form').html(''); + },500); } - if (pk_edit == null) - pk_edit = pk_refresh; + instance.get_form_base = function () { + var _this = $(this); + _this.addClass('dpt-selected'); - var url = ''; - if (_action == '') - return; - else if ( _action == null) { - url = pk_refresh+'/refresh?edit='+pk_edit; - } - else if (_action.startsWith('refresh')) { - var str = _action.split(':'); - if (str.length > 1) { - if(_action.endsWith('perfil')) { - url = '&perfil_pk='+_perfil_pk; - $("#message_block").css("display", "block"); - } - else { - editortype = str[1]; - SetCookie("editortype", editortype, 30) - } - } - url = pk_refresh+'/refresh?edit='+pk_edit+url; - } - else if (_action.startsWith('add_')) { + var dpt_form = _this.children().filter('.dpt-form'); + dpt_form.find('form').submit(instance.onSubmitEditFormBase); + + instance.scrollTo(_this); + _this.off('get_form_base') - url = pk_refresh+'/actions?action='+_action; - url += '&tipo_pk='+_tipo_pk; - url += '&variacao='+_variacao; + var btn_fechar = _this.find('.btn-fechar'); + btn_fechar.on('click', function() { + instance.clearEditSelected(); + }); - $("#message_block").css("display", "block"); + var btns_excluir = _this.find('.btns-excluir'); + _this.find('.dpt-actions-bottom').first().append(btns_excluir); + btns_excluir.find('.btn-excluir').on('click', instance.bindActionsClick); } - else if (_action.startsWith('set_')) { - url = pk_refresh+'/actions?action='+_action; - $("#message_block").css("display", "block"); + instance.get_form_alteracao = function () { + var _this = $(this); + _this.off('get_form_alteracao'); + $('.dpt-actions, .dpt-actions-bottom').html(''); + + var dpt_form = _this.children().filter('.dpt-form').children().first(); + var url_search = dpt_form[0]['id_dispositivo_search_form'].value; + DispostivoSearch({ + 'url_form': url_search, + 'text_button': 'Selecionar' + }); + + instance.scrollTo(_this); + dpt_form.submit(instance.onSubmitFormRegistraAlteracao); + + var btn_fechar = _this.find('.btn-fechar'); + btn_fechar.on('click', function() { + instance.clearEditSelected(); + instance.triggerBtnDptEdit(_this.attr('pk')); + }); + } + instance.loadActionsEdit = function(dpt) { + var pk = dpt.attr('pk'); + var url = pk+'/refresh?action=get_actions'; + $.get(url).done(function(data) { + dpt.find('.dpt-actions').first().html(data); + dpt.find('.btn-action').on('click', instance.bindActionsClick); + //dpt.find('.btn-perfis').on('click', instance.bindActionsClick); + dpt.find('.btn-compila').on('click', instance.loadFormsCompilacao); + dpt.find('.btn-editor-type').on('click', instance.bindActionsEditorType); + + if (editortype == 'construct') + dpt.find('.btn-group-inserts').first().addClass('open'); + + dpt.find('.btn-group-inserts button').mouseenter(function(event) { + dpt.find('.btn-group-inserts').removeClass('open'); + $(this.parentElement).addClass('open') + }); + + instance.gc(); + }); } - else if (_action.startsWith('delete_')) { - var r = confirm("Confirma Exclusão deste dispositivo?"); - if (!r) { - return + + instance.loadForm = function(dpt, trigger) { + var pk = dpt.attr('pk'); + var dpt_form = dpt.children().filter('.dpt-form'); + if (dpt_form.length == 1) { + var url = pk+'/refresh?action='+trigger; + $.get(url).done(function(data) { + if (editortype != "construct") { + dpt_form.html(data); + if (editortype == 'tinymce' ) { + initTinymce(); + } + } + dpt.trigger(trigger); + }).always(function() { + instance.waitHide(); + }); } - url = pk_refresh+'/actions?action='+_action; - $("#message_block").css("display", "block"); } - $.get(url).done(function( data ) { - if ( _action == null || _action.startsWith('refresh')) { + instance.loadFormsCompilacao = function(event) { + var dpt = $(this).closest('.dpt'); + var formtype = this.getAttribute('action'); + dpt.on(formtype, instance[formtype]); + instance.loadForm(dpt, formtype); + } - if (flag_refresh_all) { - if (flag_actions_vibible) - clearEditSelected(); + instance.modalMessage = function(message, alert, closeFunction) { + if (message != null && message != '') { + $('#modal-message #message').html(message); + $('#modal-message').modal('show'); + $('#modal-message, #modal-message .alert button').off(); + $('#modal-message .alert').removeClass('alert-success alert-info alert-warning alert-danger alert-danger'); + $('#modal-message .alert').addClass(alert); + + if (closeFunction != null) + $('#modal-message').on('hidden.bs.modal', closeFunction); + + $('#modal-message .alert button').on('click', function() { + $('#modal-message').modal('hide'); + }); + return true; + } + return false; + } - $( '#dpt' + pk_refresh ).html( data); - } - else { - //console.log(pk_refresh + ' - '+pk_edit) - if (flag_actions_vibible == null || flag_actions_vibible) - clearEditSelected(); + instance.message = function(data) { + if (!('message' in data)) + return; + var cp_notify = $(".cp-notify") + cp_notify.removeClass('hide') + var msg = cp_notify.find('.message'); + msg.text(data.message.value); + msg.removeClass('bg-primary bg-success bg-info bg-warning bg-danger').addClass('bg-'+data.message.type); + setTimeout(function() { + cp_notify.addClass('hide'); + }, (data.message.time?data.message.time: 3000)); + } + instance.offClicks = function() { + $('.btn-dpt-edit').off() + } + instance.onClicks = function(container) { + var objects; + if (container == null) + objects = $('.btn-dpt-edit'); + else + objects = $(container).find('.btn-dpt-edit'); + objects.on('click', instance.editDispositivo); + } - //$( '#dpt' + pk_refresh+' > .bloco' ).addClass('displaynone' ); - $( '#dpt' + pk_refresh ).prepend( data ); - } + instance.onSubmitFormRegistraAlteracao = function(event) { + var _this = this; - reloadFunctionClicks(); + var form_data = { + 'csrfmiddlewaretoken' : this['csrfmiddlewaretoken'].value, + 'dispositivo_alterado' : this['dispositivo_alterado'].value, + 'formtype': 'get_form_alteracao', + }; + var url = $(this).closest('.dpt').attr( "pk" )+'/refresh'; - var _editortype = editortype; - if ( $('.edt-'+_editortype).length == 0) { - _editortype = 'construct'; - } + instance.waitShow(); - if ( _editortype == 'tinymce' ) { - initTinymce(); - } - else if (_editortype == 'textarea') { - $('.csform form').submit(onSubmitEditForm); - } - else if (_editortype == 'construct') { - $('.csform .btn-salvar').parent().addClass("displaynone"); - $('.csform .btn-salvar, .csform .fields').addClass("displaynone"); - $('#dpt'+pk_refresh).css('min-height', $('.actions_right').height()*2); - $('.actions_inserts').removeClass('menu_flutuante'); + $.post(url, form_data) + .done(function(data) { + instance.clearEditSelected(); + + if (data.pk != null) { + instance.refreshScreenFocusPk(data); + instance.message(data); } - else if (_editortype == 'detail') { //TODO: código obsoleto - confirmar retirada desta condição - $('.csform .btn-salvar').parent().removeClass("displaynone"); - $('.csform .btn-salvar, .csform .fields').removeClass("displaynone"); - $('#dpt'+pk_refresh).css('min-height', $('.actions_right').height()*2); - $('.actions_inserts').addClass('menu_flutuante'); + else { + alert('Erro na resposta!'); } - $(".edt-"+_editortype).addClass('selected'); + }).always(function() { + instance.waitHide(); + }); + if (event != null) + event.preventDefault(); - if (flag_actions_vibible == null || flag_actions_vibible) { - $('#dpt'+pk_edit).addClass('dpt-selected'); - try { - $('html, body').animate({ - scrollTop: $('#dpt' + pk_edit ).offset().top - window.innerHeight / 9 - }, 100); - } - catch(err) { - } + } + instance.onSubmitEditFormBase = function(event) { + + var _this = this; + var texto = ''; + var texto_atualizador = ''; + var visibilidade = ''; + var editor_tiny_texto = tinymce.get('id_texto'); + var editor_tiny_texto_atualizador = tinymce.get('id_texto_atualizador'); + + if (editor_tiny_texto != null) + texto = editor_tiny_texto.getContent(); + else + texto = this['id_texto'].value; + + if (editor_tiny_texto_atualizador != null) + texto_atualizador = editor_tiny_texto_atualizador.getContent(); + else if ('id_texto_atualizador' in this) + texto_atualizador = this['id_texto_atualizador'].value; + + if ('visibilidade' in this) + visibilidade = this['visibilidade'].value; + + var form_data = { + 'csrfmiddlewaretoken' : this['csrfmiddlewaretoken'].value, + 'texto' : texto, + 'texto_atualizador' : texto_atualizador, + 'visibilidade' : visibilidade, + 'formtype': 'get_form_base', + }; + + var url = $(this).closest('.dpt').attr( "pk" )+'/refresh'; + + instance.waitShow(); + + $.post(url, form_data) + .done(function(data) { + if (typeof data == "string") { /* if obsoleto */ + var dpt = $(_this).closest('.dpt'); + dpt = $('#'+dpt.replaceWith(data).attr('id')); + instance.onClicks(dpt); + instance.waitHide(); + return; } - } + instance.clearEditSelected(); - else if (_action == 'add_next' || _action == 'add_in') { - clearEditSelected(); if (data.pk != null) { - refreshScreenFocusPk(data); + instance.refreshScreenFocusPk(data); + instance.message(data); } else { - alert('Erro na inserção!'); + alert('Erro na resposta!'); } - } - else if (_action.startsWith('delete_')) { - $("#message_block").css("display", "block"); - clearEditSelected(); - if (data.pk != null) { - if (!modalMessage(data.message, 'alert-danger', function() { - //refreshScreenFocusPk(data); - })) - refreshScreenFocusPk(data); - } - else { - alert('Erro exclusão de Dispositivo!'); - } - } - else { - clearEditSelected(); - reloadFunctionClicks(); - modalMessage(data.message, 'alert-success', null); - } - }).always(function() { - $("#message_block").css("display", "none"); - }); -} + }).always(function() { + instance.waitHide(); + }); + if (event != null) + event.preventDefault(); + } + instance.refreshContent = function(pais, trigger_edit_pk) { + if (pais.length == 0) { + instance.waitHide(); + return; + } + var pk = pais.shift(); + var url = pk+'/refresh'; -function modalMessage(message, alert, closeFunction) { - if (message != null && message != '') { - $('#modal-message #message').html(message); - $('#modal-message').modal('show'); - $('#modal-message, #modal-message .alert button').off(); - $('#modal-message .alert').removeClass('alert-success alert-info alert-warning alert-danger alert-danger'); - $('#modal-message .alert').addClass(alert); + $.get(url).done(function(data) { + var dpt = $('#id'+pk).closest('.dpt'); + dpt = $('#'+dpt.replaceWith(data).attr('id')); + instance.onClicks(dpt); + instance.reloadFunctionsDraggables(); - if (closeFunction != null) - $('#modal-message').on('hidden.bs.modal', closeFunction); + if (trigger_edit_pk > 0) + instance.triggerBtnDptEdit(trigger_edit_pk) - $('#modal-message .alert button').on('click', function() { - $('#modal-message').modal('hide'); + instance.refreshContent(pais); }); - return true; } - return false; -} - -function refreshScreenFocusPk(data) { + instance.refreshScreenFocusPk = function (data) { + instance.waitShow(); + if (data.pai[0] == -1) { + instance.waitShow() + href = location.href.split('#')[0] + location.href = href+'#'+data.pk; + location.reload(true) + } + else { + instance.refreshContent(data.pai, data.pk); - if (data.pai[0] == -1) { - $("#message_block").css("display", "block"); - href = location.href.split('#')[0] - location.href = href+'#'+data.pk; - location.reload(true) + /*setTimeout(function() { + for (var pai = 1; pai < data.pai.length; pai++) + instance.refreshContent(data.pai[pai]); + instance.waitHide(); + }, 1000);*/ } - else { - clickUpdateDispositivo(null, data.pai[0], data.pk, 'refresh', true, true); - setTimeout(function() { - for (var pai = 1; pai < data.pai.length; pai++) - clickUpdateDispositivo(null, data.pai[pai], data.pk, 'refresh', false, true); - }, 1000); } -} - -function clearEditSelected() { - $('.bloco' ).removeClass('displaynone' ); - $(".container").removeClass('class_color_container'); - tinymce.remove(); - $('.dpt-selected').removeClass('dpt-selected'); - $('.dpt').css('min-height', ''); - $('.csform').remove(); -} + instance.reloadFunctionsDraggables = function() { + $( ".dpt-alts" ).sortable({ + revert: true, + distance: 15, + start: function( event, ui ) { + } + , + stop: function( event, ui ) { + var pk = ui.item.attr('pk'); + var bloco_pk = ui.item.closest('.dpt-alts').closest('.dpt').attr('pk'); + + var url = pk+'/refresh?action=json_drag_move_dpt_alterado&index='+ui.item.index()+'&bloco_pk='+bloco_pk; + $.get(url).done(function( data ) { + console.log(pk+ ' - '+ bloco_pk); + //reloadFunctionsForObjectsOfCompilacao(); + }); + } + }); -function reloadFunctionClicks() { - $('.dpt .de, .btn-action, .btn-edit').off(); - - $('.dpt .de, .btn-edit').on('click', clickEditDispositivo); - - $('.btn-action').on('click', clickUpdateDispositivo); - - $('#editdi_texto').focus(); - $( ".bloco_alteracao" ).sortable({ - revert: true, - stop: function( event, ui ) { - var pk = ui.item.attr('pk'); - var bloco_pk = ui.item.closest('.bloco').closest('.dpt').attr('pk'); - - url = pk+'/actions?action=move_dpt_alterado&index='+ui.item.index()+'&bloco_pk='+bloco_pk; - $.get(url).done(function( data ) { - console.log(pk+ ' - '+ bloco_pk); - }); - } - }); - - $( ".bloco_alteracao .dpt" ).draggable({ - connectToSortable: ".bloco_alteracao", - revert: 'invalid', - zIndex: 1, - drag: function( event, ui ) { - $( ".bloco_alteracao" ).addClass('drag'); - }, - stop: function( event, ui ) { - $( ".bloco_alteracao" ).removeClass('drag'); - }, - }); - - $( ".bloco_alteracao" ).disableSelection(); -} + $( ".dpt-alts .dpt" ).draggable({ + connectToSortable: ".dpt-alts", + revert: 'invalid', + zIndex: 1, + distance: 15, + drag: function( event, ui ) { + //$('.dpt-comp-selected').removeClass('dpt-comp-selected'); + $(".dpt-alts").addClass('drag'); + }, + stop: function( event, ui ) { + $(".dpt-alts").removeClass('drag'); + }, + }); -$(document).ready(function() { + $(".dpt-alts").disableSelection(); + } + instance.scrollTo = function(dpt) { + try { + $('html, body').animate({ + scrollTop: dpt.offset().top - window.innerHeight / 9 + }, 100); + } + catch(err) { + } + } + instance.triggerBtnDptEdit =function(pk) { + var btn_dpt_edit = $('#id'+pk + ' > .dpt-text.btn-dpt-edit'); + if (btn_dpt_edit.length == 0) + btn_dpt_edit = $('#id'+pk + ' > .dpt-actions-fixed > .btn-dpt-edit'); + btn_dpt_edit.trigger( "click" ); + } + instance.waitHide = function() { + $("#wait_message").addClass("displaynone"); + } + instance.waitShow = function() { + $("#wait_message").removeClass("displaynone"); + } - editortype = ReadCookie("editortype") - if (editortype == null || editortype == "") { - editortype = "textarea" - SetCookie("editortype", editortype, 30) + instance.init = function() { + editortype = ReadCookie("editortype"); + if (editortype == null || editortype == '') { + editortype = "textarea" + SetCookie("editortype", editortype, 30) + } + //editortype = "textarea"; + instance.offClicks(); + instance.onClicks(); + instance.reloadFunctionsDraggables(); + + href = location.href.split('#') + if (href.length == 2 && href[1] != '') { + instance.triggerBtnDptEdit(href[1]) + } + $('main').click(function(event) { + if (event.target == this || event.target == this.firstElementChild) + instance.clearEditSelected(); + }); + instance.waitHide(); } + instance.init(); +} - reloadFunctionClicks(); - $("#message_block").css("display", "none"); - href = location.href.split('#') - if (href.length == 2 && href[1] != '') { - clickUpdateDispositivo(null, href[1], href[1], 'refresh', true); - } +$(document).ready(function() { - $('main').click(function(event) { - if (event.target == this || event.target == this.firstElementChild) - clearEditSelected(); - }); + DispositivoEdit(); }); diff --git a/sapl/static/js/compilacao_view.js b/sapl/static/js/compilacao_view.js index 0c15435dd..ffb96dd8b 100644 --- a/sapl/static/js/compilacao_view.js +++ b/sapl/static/js/compilacao_view.js @@ -36,7 +36,7 @@ function textoMultiVigente(item, diff) { $(".dptt.desativado").removeClass("displaynone"); $(".dtxt").removeClass("displaynone"); $(".dtxt.diff").remove(); - $(".link_alterador").removeClass("displaynone"); + $(".nota-alteracao").removeClass("displaynone"); if (diff) { $(".dtxt[id^='da'").each(function() { @@ -95,9 +95,14 @@ function textoMultiVigente(item, diff) { } if (elv) { - $('html, body').animate({ - scrollTop: $(elv).parent().offset().top - 60 - }, 0); + try { + $('html, body').animate({ + scrollTop: $(elv).parent().offset().top - 60 + }, 0); + } + catch(err) { + } + } } @@ -121,14 +126,18 @@ function textoVigente(item, link) { $(item).addClass("selected") $(".dptt.desativado").addClass("displaynone"); - $(".link_alterador").removeClass("displaynone"); + $(".nota-alteracao").removeClass("displaynone"); if (!link) - $(".link_alterador").addClass("displaynone"); + $(".nota-alteracao").addClass("displaynone"); if (elv) { - $('html, body').animate({ - scrollTop: $(elv).parent().offset().top - 60 - }, 0); + try { + $('html, body').animate({ + scrollTop: $(elv).parent().offset().top - 60 + }, 0); + } + catch(err) { + } } } diff --git a/sapl/static/styles/app.scss b/sapl/static/styles/app.scss index 1b2571e6f..27830c7e1 100644 --- a/sapl/static/styles/app.scss +++ b/sapl/static/styles/app.scss @@ -8,6 +8,12 @@ float: none; } +nav { + &.navbar { + border-radius: 0; + } +} + .masthead { padding: 10px; .nav { @@ -140,12 +146,6 @@ fieldset { } } -.btn-primary, .btn-danger{ - font-size: 16px; - height: 40px !important; - display: inline-block; -} - /* INDEX */ #conteudo { position: relative; diff --git a/sapl/static/styles/compilacao.scss b/sapl/static/styles/compilacao.scss index a35b694b8..148244c0b 100644 --- a/sapl/static/styles/compilacao.scss +++ b/sapl/static/styles/compilacao.scss @@ -61,6 +61,7 @@ a:link:after, a:visited:after { -webkit-transition-delay: 0.4s; /* Safari */ transition-delay: 0.4s; + li { a { border-right: 0px !important; @@ -84,7 +85,6 @@ a:link:after, a:visited:after { } } } - // This bridges the gap between the top bar and a dropdown. &::after { content: ""; position: absolute; @@ -93,27 +93,23 @@ a:link:after, a:visited:after { top: rem-calc(-25px); height: rem-calc(25px); width: 100%; - // This transition is for hover-on. transition: all 0.3s cubic-bezier(0.55,0,0.1,1); } } &:hover > ul { - transform: translateY(7px); - // This transition is actually for when we hover-out of the dropdown. transition: transform 0.4s linear, opacity 0.4s linear, clip 0s 0.2s; opacity: 1; clip: rect(-100px, 2000px, 2000px, -100px); - } } .test_import:nth-child(even) { background-color: #ccc; } -#message_block { +#wait_message { display: block; position: fixed; top: 0; @@ -137,12 +133,40 @@ a:link:after, a:visited:after { box-shadow: 0 1px 2px #999; } } - +.text-center { + text-align: center; +} +.cp-notify { + z-index: 9999; + position:fixed; + top: 2em; + left: 50%; + min-width: 600px; + transform: translate(-50%, 0); + transition: all 0.4s ease; + opacity: 0.97; + &.hide { + opacity: 0; + top: -1000px; + display: block !important; + transition: all 0.4s ease; + } + .message { + padding: 1em; + border: 2px solid rgba(0, 0, 0, 0.1); + border-radius: 4px; + color: rgba(0, 0, 0, 0.6); + line-height: 1em; + font-size: 1.3em; + text-align: center; + box-shadow: 0 0 100px rgba(0, 0, 0, 0.2); + } +} .cp { .desativado { - .dtxt, .dtxt * { + .dtxt, .dtxt *, .dpt-link, .dpt-link * { text-decoration: line-through; color: #999 !important; @@ -365,15 +389,14 @@ a:link:after, a:visited:after { } } } - } .dptt { & > a { color: #444444; - &.link_alterador { - color: #2980B9; + &.nota-alteracao { + color: #02baf2; font-size: 0.75em; &:hover { text-decoration: underline; @@ -418,7 +441,6 @@ a:link:after, a:visited:after { } } } - .dne-nota { position: relative; transform: scaleX(1); @@ -491,6 +513,261 @@ a:link:after, a:visited:after { } /* end cp */ .cp.cpe { + .desativado { + text-decoration: line-through; + color: #999 !important; + table, table td { + border: 1px dotted #ccc; + } + + a.nota-alteracao * { + color: #02baf2 !important; + } + } + .dpt { + display: block; + & > .dpt-actions-fixed { + position: absolute; + right: -0.8em; + top: -0.8em; + z-index: 3; + opacity: 0; + + .activate { + display:none; + } + .deactivate { + display:inline; + } + .btn-dpt-edit.btn-default { + color: #333; + &:hover { + color: #fff; + background-color: #02baf2; + } + } + } + & > .dpt-actions, & > .dpt-actions-bottom { + display: none; + } + & > .dpt-text { + cursor: text; + min-height: 30px; + border: 1px solid transparent; + &:hover, &.hover-fixed { + background-color: rgba(0, 0, 0, 0.01); + color: $color_buttons; + border: 1px solid #eee; + transition: color 0.3s ease; + } + &.artigo { + float: none; + } + a { + &.link-rotulo { + color: #000; + } + } + } + + &:hover { + & > .dpt-actions-fixed { + opacity: 1; + &:hover { + & ~ .dpt-text { + background-color: rgba(0, 0, 0, 0.01); + color: $color_buttons; + border: 1px solid #eee; + transition: color 0.3s ease; + } + } + } + } + + .semtexto { + font-weight: bold; + color: #9aaed6; + &:hover { + color: #5f76a4; + } + } + } /* fim .dpt */ + .dpt-alts { + margin: 0; + margin-bottom: 1em; + padding: 0; + background-color: transparent; + min-height: 100px; + border: 2px dashed #fff; + &:hover { + border-color: #d9ddde; + } + &:empty { + border-color: #ddd; + } + &.drag { + width: 100% !important; + border-color: #d9ddde; + .dpt { + transition-duration: 0s !important; + } + } + .dpt { + width: 100% !important; + box-shadow: 0 -1px 0 #e5e5e5, 0 0 2px rgba(0,0,0,.12),0 2px 4px rgba(0,0,0,.24); + padding: 0; + margin: 0; + background-color: #edf0f1; + height: auto !important; + min-height: 2em; + + z-index: 1; + &:not(:first-child) { + border-top: 1px solid white; + } + & > .dpt-text { + padding: 0.3em 1em; + margin-top: 0; + margin-bottom: 0; + a { + &.link-rotulo { + text-decoration: underline; + } + } + } + } + .dpt-selected { + &.dpt { + margin: 0em -0.5em; + } + } + } /* fim dpt-alts */ + + .dpt-selected { + &.dpt { + width: auto !important; + margin: 1em -0.5em; + border: 1px solid #ddd !important; + padding: 0; + background-color: #fafafa; + border-radius: 3px; + z-index: 4; + & > .dpt-text { + border: 1px solid transparent; + &:hover { + border: 1px solid transparent; + background-color: rgba(0, 0, 0, 0.0); + } + } + & > .dpt-form { + margin-bottom: 0em; + } + & > .dpt-actions, & > .dpt-actions-bottom { + display: table; + background-color: #e5e5e5; + padding: 1em; + margin-bottom: 0em; + width: 100%; + & > .btn-action { + display: table-cell; + float: none; + } + .btn-excluir { + display: inline-block; + opacity: 0.3; + &:hover { + opacity: 1; + } + } + } + & > .dpt-actions-bottom { + margin:0; + } + } + .dpt-block { + border-top: 1px solid #e5e5e5 !important; + opacity: 0.6; + transition: opacity 0.4s ease; + &:hover { + opacity: 1; + } + } + .dpt { + &:only-child { + /*border-bottom: 1px solid #e5e5e5 !important;*/ + } + &:not(:last-child) { + /*border-bottom: 1px solid #e5e5e5 !important;*/ + } + } + .dpt-text { + opacity: 0.7; + margin: 0; + padding: 0.7em; + &:hover { + opacity: 1; + background-color: #f5f5f5; + } + } + .dpt-alts { + margin: 1em; + .dpt { + box-shadow: 0 0 0; + } + } + & > .dpt-actions-fixed { + opacity: 1; + top: -12px; + right: 0.5em; + .activate { + display:inline; + } + .deactivate { + display:none; + } + .btn-dpt-edit { + padding-top: 2px; + padding-bottom: 1px; + &.btn-default { + background-color: #fad46b; + } + } + } + + .dropdown-menu { + &.dropdown-menu-left { + right: auto !important; + left: 0; + padding: 2px 0; + & > .top.arrow { + right: 88%; + left: auto; + } + } + li { + a { + padding-top: 2px; + padding-bottom: 2px; + + } + } + } + .btn-group { + .radius-right { + border-bottom-right-radius: 4px !important; + border-top-right-radius: 4px !important; + } + + } + &:hover { + & > .dpt-actions-fixed { + opacity: 1; + } + } + } +} + +.cp.cpe1 { margin-bottom: 15em; @@ -530,14 +807,19 @@ a:link:after, a:visited:after { position: absolute; opacity: 0; transition: all 0.4s ease-in-out; - z-index: 2000; + z-index: 1000; a { - &.btn-edit { + &.btn-bloco { background-color: #3498db; color: #ffffff !important; padding: 8px 18px 6px; display: inline-block; line-height: 1; + float: right; + &:hover{ + opacity: 1; + @include background-top-down(#1c81c4, #0b6dad); + } } } } @@ -570,13 +852,17 @@ a:link:after, a:visited:after { border-color: #d9ddde; } &.drag { + width: 100% !important; border-color: #d9ddde; + .dpt { + transition-duration: 0s !important; + } } .dpt { width: 100% !important; box-shadow: 0 -1px 0 #e5e5e5, 0 0 2px rgba(0,0,0,.12),0 2px 4px rgba(0,0,0,.24); padding: 0.3em 1em; - margin: 1px 0; + margin: 0; background-color: #edf0f1; z-index: 1; &:not(:first-child) { @@ -585,6 +871,12 @@ a:link:after, a:visited:after { &.ui-draggable div { cursor: pointer; } + &.dpt-comp-selected { + transition: all 0.3s ease; + width: auto !important; + margin: 2em -3.7em; + box-shadow: 0 0 6px rgba(0,0,0,.16),0 6px 12px rgba(0,0,0,.32); + } } } } /* fim dpt */ @@ -592,7 +884,7 @@ a:link:after, a:visited:after { .dpt-selected { font-size: 1em; border: 0px solid $color_actions_border; - margin: 1em -2em 1em -2.8em; + margin: 1em -1.8em 1em -1.8em; padding: 2.2em 2.2em 1.6em 2.2em; box-shadow: -4px 15px 15px rgba(0, 0, 0, 0.1), 0px 6px 6px rgba(0, 0, 0, 0.23); @@ -626,12 +918,26 @@ a:link:after, a:visited:after { .bloco_alteracao { margin: 0; padding: 1em; + border: 0 transparent; @include background-top-down(#eaeaee, #ddd); - &:not(:first-child) { - border-top: 0px solid white; + + &:hover { + border-color: transparent; + } + &.drag { + width: 100% !important; + .dpt { + transition-duration: 0s !important; + } } .dpt { + width: auto !important; + transition: all 0.3s ease; background-color: white; + &:not(:first-child) { + border-top: 0px solid white; + } + } } @@ -643,7 +949,11 @@ a:link:after, a:visited:after { } & > .actions_right { - display: none; + a { + &.btn-bloco { + display: none; + } + } } .csform { /* compilacao simple form */ @@ -910,6 +1220,7 @@ a:link:after, a:visited:after { .menu_flutuante, .menu_flutuante_fixo { + z-index: 2000; & > li { @include li_flutuante(); @@ -956,7 +1267,8 @@ a:link:after, a:visited:after { } } } /* fim csform*/ - } + } /* fim dpt-selected */ + .selected { background-color: rgba(255, 255, 255, 0.5); @@ -1092,8 +1404,10 @@ a:link:after, a:visited:after { clear:both; } -.mce-panel { - /*border: 0px solid #ccc !important;*/ +.mce-tinymce.mce-container { + border: 1px solid #ccc !important; + + margin-right: 2px; } .mce-btn button:hover { background-color: rgba(0,0,0,0.1) !important; @@ -1108,16 +1422,16 @@ a:link:after, a:visited:after { display: none !important; } -@media only screen and (max-width: 40.0625em) { +@media only screen and (max-width: 800px) { .cp .fixed{ z-index:98; position: relative; } - .cpe { + .cp.cpe1 { .dpt-selected { - margin:1em -1em 1em -1.8em; + margin: 1em 0; .csform { .actions_parents, .label_status { @@ -1126,6 +1440,9 @@ a:link:after, a:visited:after { display: block !important; padding: 0em; height: auto !important; + left: 0; + right: auto; + text-align: left; div, li { display: inline-block !important; } @@ -1179,7 +1496,7 @@ a:link:after, a:visited:after { margin-left: 0; margin-right: 0.5em; li:first-child::before { - right: 27%; + right: 0; left: auto; } } diff --git a/sapl/templates/compilacao/ajax_actions_dinamic_edit.html b/sapl/templates/compilacao/ajax_actions_dinamic_edit.html new file mode 100644 index 000000000..3231fdd1d --- /dev/null +++ b/sapl/templates/compilacao/ajax_actions_dinamic_edit.html @@ -0,0 +1,71 @@ +{% load i18n %} + + + + diff --git a/sapl/templates/compilacao/dispositivo_form.html b/sapl/templates/compilacao/dispositivo_form.html index 3bff729b3..d9882b53a 100644 --- a/sapl/templates/compilacao/dispositivo_form.html +++ b/sapl/templates/compilacao/dispositivo_form.html @@ -5,17 +5,16 @@ {% endblock %} {% block sections_nav %} - + {% endblock sections_nav %}{% trans '' %} {% block title %} @@ -23,16 +22,37 @@ {% endblock%} {% block base_content %}
+
+ + {% trans "Articulações" %} + + + +
{%for parent in object.get_parents_asc %} {%with node=parent active=False template_name='compilacao/dispositivo_form_parents.html' %} {%include template_name%} {%endwith%} {%endfor %} - {%with node=object active=True template_name='compilacao/dispositivo_form_parents.html' %} {%include template_name%} {%endwith%}
+
+ {%if object.ta_publicado_id %} + + {{ object.tipo_dispositivo.nota_automatica_prefixo_html|safe }} + {% nota_automatica object None %} + {{ object.tipo_dispositivo.nota_automatica_sufixo_html|safe }} + {%endif%}

{% crispy form %} {% endblock %} diff --git a/sapl/templates/compilacao/dispositivo_form_parents.html b/sapl/templates/compilacao/dispositivo_form_parents.html index c2f5f3e34..167671a4b 100644 --- a/sapl/templates/compilacao/dispositivo_form_parents.html +++ b/sapl/templates/compilacao/dispositivo_form_parents.html @@ -4,28 +4,25 @@ {{node|nomenclatura}} -{% else %} +{% else %} - {% endif %} diff --git a/sapl/templates/compilacao/dispositivo_form_search.html b/sapl/templates/compilacao/dispositivo_form_search.html index 4a7732446..9bcb1cba2 100644 --- a/sapl/templates/compilacao/dispositivo_form_search.html +++ b/sapl/templates/compilacao/dispositivo_form_search.html @@ -5,14 +5,14 @@ diff --git a/sapl/templates/compilacao/dispositivo_form_search_fragment.html b/sapl/templates/compilacao/dispositivo_form_search_fragment.html index 721fdddfa..a66b59245 100644 --- a/sapl/templates/compilacao/dispositivo_form_search_fragment.html +++ b/sapl/templates/compilacao/dispositivo_form_search_fragment.html @@ -24,7 +24,7 @@ {% endif %} {% endifchanged %} - {% if dpt.tipo_dispositivo.dispositivo_de_alteracao or dpt.dispositivo_pai.nivel > 0 and dpt.is_relative_auto_insert and dpt.dispositivo_pai not in object_list %} + {% if dpt.tipo_dispositivo.dispositivo_de_alteracao or dpt.dispositivo_pai.nivel > 0 and dpt.auto_inserido and dpt.dispositivo_pai not in object_list %}
  • @@ -40,7 +40,7 @@ {{ dpt.dispositivo_pai.tipo_dispositivo.rotulo_sufixo_html|safe }} {{ dpt.dispositivo_pai.tipo_dispositivo.texto_prefixo_html|safe }}{%if dpt.dispositivo_pai.texto %}{{ dpt.dispositivo_pai.texto|safe }}{%else%}{%if not dpt.dispositivo_pai.tipo_dispositivo.dispositivo_de_articulacao %} {% endif %}{% endif %} {% if dpt.dispositivo_pai.ta_publicado_id %} - + {{ dpt.dispositivo_pai.tipo_dispositivo.nota_automatica_prefixo_html|safe }} {% nota_automatica dpt.dispositivo_pai ta_pub_list %} {{ dpt.dispositivo_pai.tipo_dispositivo.nota_automatica_sufixo_html|safe }} @@ -72,7 +72,7 @@ pks="{{dpt.dispositivo_substituido_id|default:''}}" pk="{{dpt.pk}}">{{ 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 %} - + {{ dpt.tipo_dispositivo.nota_automatica_prefixo_html|safe }} {% nota_automatica dpt ta_pub_list %} {{ dpt.tipo_dispositivo.nota_automatica_sufixo_html|safe }} @@ -108,7 +108,7 @@ {{ 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 %} - + {{ df.tipo_dispositivo.nota_automatica_prefixo_html|safe }} {% nota_automatica df ta_pub_list %} {{ df.tipo_dispositivo.nota_automatica_sufixo_html|safe }} diff --git a/sapl/templates/compilacao/layout/dispositivo_checkbox.html b/sapl/templates/compilacao/layout/dispositivo_checkbox.html index dc08ddff9..3ae16e169 100644 --- a/sapl/templates/compilacao/layout/dispositivo_checkbox.html +++ b/sapl/templates/compilacao/layout/dispositivo_checkbox.html @@ -34,7 +34,7 @@ {{ 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 }} diff --git a/sapl/templates/compilacao/layout/dispositivo_radio.html b/sapl/templates/compilacao/layout/dispositivo_radio.html index e95e3a451..a189ca03a 100644 --- a/sapl/templates/compilacao/layout/dispositivo_radio.html +++ b/sapl/templates/compilacao/layout/dispositivo_radio.html @@ -18,7 +18,7 @@
    {% if dpt.nivel > 1 %} - {% trans "Herança:" %} {% heranca request dpt 1 0 %} + {% trans "Herança:" %} {% heranca request dpt 0 0 %} {% endif %}
    @@ -29,6 +29,18 @@ id="d{% if not dpt.dispositivo_subsequente_id and dpt.dispositivo_substituido_id %}a{% endif %}{{dpt.pk}}" pks="{{dpt.dispositivo_substituido_id|default:''}}" pk="{{dpt.pk}}">{{ 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 }} + + {% else %} + + + {% endif %}
    diff --git a/sapl/templates/compilacao/text_edit.html b/sapl/templates/compilacao/text_edit.html index f1793c6e0..013a7429d 100644 --- a/sapl/templates/compilacao/text_edit.html +++ b/sapl/templates/compilacao/text_edit.html @@ -11,7 +11,7 @@ {% endblock %} {% block title%} -

    Edição: {{ view.title }} - {% trans 'Texto Multivigente' %}

    +

    {{object }}. {% trans 'Texto Multivigente em Edição' %}

    {% endblock %} {% block actions %} @@ -19,20 +19,23 @@ {% endblock actions %} {% block base_content %}{{block.super}} -
    {% trans 'Aguarde... Atualizando informações!!!'%}
    +
    {% trans 'Aguarde... Atualizando informações!!!'%}
    + +
    +
    +
  •  Salvar
  • - +{% comment %} -
    - {% csrf_token %} +{% for item in dispositivos_list %} - {% if not dpt.tipo_dispositivo.dispositivo_de_articulacao %} - - {%endif%} -
    -
      -
    • 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 item.alts %} + {%with dispositivos_list=item.alts %} + {%include 'compilacao/text_edit_bloco.html'%} + {%endwith%} + {% endif %} +
      +<<<<<<< d5a8cdb5d563a8353942e0dc3c3b2484bd636ea6:templates/compilacao/text_edit_bloco.html +======= {% if dpt.dispositivo_vigencia %}
    • {% field_verbose_name dpt 'dispositivo_vigencia'%}: {{dpt.dispositivo_vigencia|nomenclatura}}
    • {% endif %} +>>>>>>> Fix #497 Encaps apps secundárias dentro app sapl:sapl/templates/compilacao/text_edit_bloco.html -
    • -
    • - ? - -
    • -
    + - - - - {% endif%} - - {% if view.pk_view == 0 and view.pk_edit == 0 or view.pk_edit != view.pk_view %} - {% if not dpt.rotulo and not dpt.texto and dpt.tipo_dispositivo.dispositivo_de_articulacao%} -
    - {% trans 'Editar'%} {{ dpt.tipo_dispositivo.nome }} {{ dpt.rotulo }} +{% endfor%} +{% for dpt in object_list %} +
    + {% spaceless %} + {% if not dpt.tipo_dispositivo.dispositivo_de_alteracao %} +
    + {{ dpt.tipo_dispositivo.rotulo_prefixo_html|safe }} + {{ dpt.rotulo }} + {{ dpt.tipo_dispositivo.rotulo_sufixo_html|safe }} + {{ dpt.tipo_dispositivo.texto_prefixo_html|safe }} + {% if dpt.texto == '' and not dpt.tipo_dispositivo.dispositivo_de_articulacao %} + ({{dpt.tipo_dispositivo}} sem texto) + {%else%} + {{ dpt.texto|safe }} + {%endif%}
    {% endif %} +<<<<<<< d5a8cdb5d563a8353942e0dc3c3b2484bd636ea6:templates/compilacao/text_edit_bloco.html + {% if dpt.ta_publicado_id != None 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 %} + {% endspaceless %} +=======
    {% spaceless %} {% if not dpt.tipo_dispositivo.dispositivo_de_alteracao %}
    {{ dpt.tipo_dispositivo.rotulo_prefixo_html|safe }}{{ dpt.rotulo }}{{ dpt.tipo_dispositivo.rotulo_sufixo_html|safe }}{{ dpt.tipo_dispositivo.texto_prefixo_html|safe }}{% if dpt.texto == '' and not dpt.tipo_dispositivo.dispositivo_de_articulacao %}({{dpt.tipo_dispositivo}} sem texto){%else%}{{ dpt.texto|safe }}{%endif%}
    {% endif %} {% if dpt.ta_publicado_id != None 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 }} @@ -150,13 +145,14 @@ {% endif%}
    {% endif%} +>>>>>>> Fix #497 Encaps apps secundárias dentro app sapl:sapl/templates/compilacao/text_edit_bloco.html - {% set_nivel_old view dpt.nivel %} - {% endif%} -{% endfor %} + {% if dpt.tipo_dispositivo.dispositivo_de_alteracao %} + {%with node=dpt template_name='compilacao/text_edit_blocoalteracao.html' %} + {%include template_name%} + {%endwith%} + {% endif%} -{% if view|isinst:'DispositivoSimpleEditView' %} - {% close_div view.flag_nivel_old view.flag_nivel_ini -1 %} -{% else %} - {% close_div view.flag_nivel_old view.flag_nivel_ini 0 %} -{% endif%} +
    +{% endfor %} +{% endcomment %} diff --git a/sapl/templates/compilacao/text_edit_blocoalteracao.html b/sapl/templates/compilacao/text_edit_blocoalteracao.html index 9eadfb1b3..d2d9f953f 100644 --- a/sapl/templates/compilacao/text_edit_blocoalteracao.html +++ b/sapl/templates/compilacao/text_edit_blocoalteracao.html @@ -2,9 +2,11 @@ {% load common_tags %} {% for ch in dpt.pk|get_bloco_atualizador %} {% spaceless %} -
    +
    - {{ ch.tipo_dispositivo.rotulo_prefixo_html|safe }}{{ ch.rotulo }}{{ ch.tipo_dispositivo.rotulo_sufixo_html|safe }}{{ ch.tipo_dispositivo.texto_prefixo_html|safe }}{{ ch.texto|safe }} +
    + {{ ch.tipo_dispositivo.rotulo_prefixo_html|safe }}{{ ch.rotulo }}{{ ch.tipo_dispositivo.rotulo_sufixo_html|safe }}{{ ch.tipo_dispositivo.texto_prefixo_html|safe }}{{ ch.texto|safe }} +
    {% endspaceless %} diff --git a/sapl/templates/compilacao/text_list.html b/sapl/templates/compilacao/text_list.html index 10c965459..933c2992e 100644 --- a/sapl/templates/compilacao/text_list.html +++ b/sapl/templates/compilacao/text_list.html @@ -72,6 +72,7 @@ {% else %}