Browse Source

Conclusão da Issue #77

pull/98/head
LeandroRoberto 9 years ago
parent
commit
7403bbbbba
  1. 2
      compilacao/models.py
  2. 7
      compilacao/templatetags/compilacao_filters.py
  3. 20
      compilacao/urls.py
  4. 805
      compilacao/views.py
  5. 1043
      compilacao/views2.py
  6. 41
      materia/views.py
  7. 2
      norma/models.py
  8. 39
      norma/views.py
  9. 2
      static/js/compilacao_edit.js
  10. 32
      static/styles/app.scss
  11. 5
      static/styles/compilacao.scss
  12. 9
      templates/base.html
  13. 5
      templates/compilacao/text_edit.html
  14. 4
      templates/compilacao/text_edit_bloco.html
  15. 2
      templates/compilacao/text_edit_blocoalteracao.html
  16. 11
      templates/compilacao/text_list.html
  17. 44
      templates/compilacao/textoarticulado_detail.html
  18. 7
      templates/materia/materialegislativa_detail.html
  19. 15
      templates/norma/normajuridica_detail.html
  20. 10
      templates/sistema.html

2
compilacao/models.py

@ -122,7 +122,7 @@ class TextoArticulado(TimestampedMixin):
if self.content_object:
return str(self.content_object)
else:
return _('Texto Articulado%(numero)s de %(data)s') % {
return _('%(tipo)s%(numero)s de %(data)s') % {
'tipo': self.tipo_ta,
'numero': self.numero,
'data': defaultfilters.date(self.data, "d \d\e F \d\e Y")}

7
compilacao/templatetags/compilacao_filters.py

@ -156,4 +156,9 @@ def nomenclatura_heranca(d, ignore_ultimo=0, ignore_primeiro=0):
@register.simple_tag
def verbose_name(instance, field_name):
return instance._meta.get_field(field_name).verbose_name.title()
return instance._meta.get_field(field_name).verbose_name
@register.filter
def urldetail_content_type(obj):
return '%s:detail' % obj.content_type.model

20
compilacao/urls.py

@ -11,7 +11,6 @@ urlpatterns_compilacao = [
url(r'^(?P<pk>[0-9]+)/delete$',
views.TaDeleteView.as_view(), name='ta_delete'),
url(r'^(?P<ta_id>[0-9]+)/text$',
views.TextView.as_view(), name='ta_text'),
url(r'^(?P<ta_id>[0-9]+)/text/vigencia/(?P<sign>.+)/$',
@ -20,10 +19,17 @@ urlpatterns_compilacao = [
url(r'^(?P<ta_id>[0-9]+)/text/edit',
views.TextEditView.as_view(), name='ta_text_edit'),
url(r'^(?P<ta_id>[0-9]+)/text/(?P<dispositivo_id>[0-9]+)/$',
views.DispositivoView.as_view(), name='dispositivo'),
url(r'^(?P<ta_id>[0-9]+)/text/(?P<dispositivo_id>[0-9]+)/refresh',
views.DispositivoEditView.as_view(), name='dispositivo_edit'),
url(r'^(?P<ta_id>[0-9]+)/text/(?P<dispositivo_id>[0-9]+)/actions',
views.ActionsEditView.as_view(), name='dispositivo_actions'),
url(r'^(?P<ta_id>[0-9]+)/text/'
'(?P<dispositivo_id>[0-9]+)/nota/create$',
views.NotasCreateView.as_view(), name='nota_create'),
@ -56,13 +62,3 @@ urlpatterns_compilacao = [
urlpatterns = [
url(r'^ta/', include(urlpatterns_compilacao)),
]
"""
url(r'^(?P<ta_id>[0-9]+)/compilacao/(?P<dispositivo_id>[0-9]+)/refresh',
views.DispositivoEditView.as_view(), name='dispositivo_edit'),
url(r'^(?P<ta_id>[0-9]+)/compilacao/(?P<dispositivo_id>[0-9]+)/actions',
views.ActionsEditView.as_view(), name='dispositivo_actions'),
"""

805
compilacao/views.py

@ -1,13 +1,16 @@
import sys
from collections import OrderedDict
from datetime import datetime, timedelta
from braces.views import FormMessagesMixin
from django.contrib.auth.decorators import login_required
from django.contrib.contenttypes.models import ContentType
from django.core.signing import Signer
from django.core.urlresolvers import reverse, reverse_lazy
from django.db.models import Q
from django.http.response import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.http.response import (HttpResponse, HttpResponseRedirect,
JsonResponse)
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.translation import ugettext_lazy as _
@ -20,7 +23,7 @@ from compilacao import forms, utils
from compilacao.models import (Dispositivo, Nota,
PerfilEstruturalTextoArticulado,
TextoArticulado, TipoDispositivo, TipoNota,
Vide)
TipoTextoArticulado, Vide)
DISPOSITIVO_SELECT_RELATED = (
'tipo_dispositivo',
@ -55,7 +58,13 @@ class TaDetailView(DetailView):
@property
def title(self):
return self.get_object()
if self.object.content_object:
return _(
'Metadados para o Texto Articulado da %s - %s') % (
self.get_object().content_object._meta.verbose_name_plural,
self.get_object().content_object)
else:
return self.get_object()
class TaCreateView(FormMessagesMixin, CreateView):
@ -81,6 +90,10 @@ class TaUpdateView(UpdateView):
def get_success_url(self):
return reverse_lazy('ta_detail', kwargs={'pk': self.kwargs['pk']})
@property
def cancel_url(self):
return reverse_lazy('ta_detail', kwargs={'pk': self.kwargs['pk']})
class TaDeleteView(DeleteView):
model = TextoArticulado
@ -97,6 +110,64 @@ class TaDeleteView(DeleteView):
return reverse_lazy('ta_list')
class IntegracaoTaView(TemplateView):
def get(self, *args, **kwargs):
item = get_object_or_404(self.model, pk=kwargs['pk'])
related_object_type = ContentType.objects.get_for_model(item)
ta = TextoArticulado.objects.filter(
object_id=item.pk,
content_type=related_object_type)
if not ta.exists():
ta = TextoArticulado()
tipo_ta = TipoTextoArticulado.objects.filter(
model=item.__class__.__name__.lower())[:1]
if tipo_ta.exists():
ta.tipo_ta = tipo_ta[0]
ta.content_object = item
else:
ta = ta[0]
if hasattr(item, 'ementa') and item.ementa:
ta.ementa = item.ementa
else:
ta.ementa = 'Integração com %s sem ementa.' % item
if hasattr(item, 'observacao') and item.observacao:
ta.observacao = item.observacao
else:
ta.observacao = 'Integração com %s sem observacao.' % item
if hasattr(item, 'numero') and item.numero:
ta.numero = item.numero
else:
ta.numero = int('%s%s%s' % (
int(datetime.now().year),
int(datetime.now().month),
int(datetime.now().day)))
if hasattr(item, 'ano') and item.ano:
ta.ano = item.ano
else:
ta.ano = datetime.now().year
if hasattr(item, 'data_apresentacao'):
ta.data = item.data_apresentacao
elif hasattr(item, 'data'):
ta.data = item.data
else:
ta.data = datetime.now()
ta.save()
return redirect(to=reverse_lazy('ta_text', kwargs={'ta_id': ta.pk}))
class Meta:
abstract = True
class TextView(ListView):
template_name = 'compilacao/text_list.html'
@ -110,6 +181,45 @@ class TextView(ListView):
inicio_vigencia = None
fim_vigencia = None
def get(self, request, *args, **kwargs):
ta = TextoArticulado.objects.get(pk=self.kwargs['ta_id'])
self.title = ta
if ta.content_object:
item = ta.content_object
self.title = item
if hasattr(item, 'ementa') and item.ementa:
ta.ementa = item.ementa
else:
ta.ementa = 'Integração com %s sem ementa.' % item
if hasattr(item, 'observacao') and item.observacao:
ta.observacao = item.observacao
else:
ta.observacao = 'Integração com %s sem observacao.' % item
if hasattr(item, 'numero') and item.numero:
ta.numero = item.numero
else:
ta.numero = int('%s%s%s' % (
int(datetime.now().year),
int(datetime.now().month),
int(datetime.now().day)))
if hasattr(item, 'ano') and item.ano:
ta.ano = item.ano
else:
ta.ano = datetime.now().year
if hasattr(item, 'data_apresentacao'):
ta.data = item.data_apresentacao
elif hasattr(item, 'data'):
ta.data = item.data
else:
ta.data = datetime.now()
ta.save()
return super(TextView, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(TextView, self).get_context_data(**kwargs)
@ -288,7 +398,6 @@ class DispositivoView(TextView):
class TextEditView(TextView):
template_name = 'compilacao/text_edit.html'
flag_alteradora = -1
@ -383,6 +492,692 @@ class TextEditView(TextView):
request.session['perfil_estrutural'] = perfis[0].pk
class DispositivoEditView(TextEditView):
template_name = 'compilacao/text_edit_bloco.html'
def post(self, request, *args, **kwargs):
d = Dispositivo.objects.get(
pk=self.kwargs['dispositivo_id'])
texto = request.POST['texto']
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[0] = d
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, 'pai': pais}
else:
data = {'pk': d.pk, 'pai': [d.pk, ]}
return JsonResponse(data, safe=False)
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
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']
# 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)
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': 'Inserir Depois',
'icone': '&#8631;&nbsp;',
'action': 'add_next',
'itens': []},
{'tipo_insert': 'Inserir Dentro',
'icone': '&#8690;&nbsp;',
'action': 'add_in',
'itens': []},
{'tipo_insert': 'Inserir Antes',
'icone': '&#8630;&nbsp;',
'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 falta de necessidade
if len(result) > 2:
result.pop()
except Exception as e:
print(e)
return result
class ActionsEditMixin(object):
def render_to_json_response(self, context, **response_kwargs):
action = getattr(self, context['action'])
return JsonResponse(action(context), safe=False)
def delete_item_dispositivo(self, context):
return self.delete_bloco_dispositivo(context)
def delete_bloco_dispositivo(self, context):
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
)[:1]
base.delete()
if base_anterior.exists():
if base_anterior[0].dispositivo_pai_id:
data = {'pk': base_anterior[0].pk, 'pai': [
base_anterior[0].dispositivo_pai_id, ]}
else:
data = {'pk': base_anterior[0].pk, 'pai': [-1, ]}
return data
else:
return {}
def add_prior(self, context):
return {}
def add_in(self, context):
return self.add_next(context, local_add='add_in')
def add_next(self, context, local_add='add_next'):
try:
base = Dispositivo.objects.get(pk=context['dispositivo_id'])
tipo = TipoDispositivo.objects.get(pk=context['tipo_pk'])
variacao = int(context['variacao'])
parents = [base, ] + base.get_parents()
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:
if dp.tipo_dispositivo == tipo:
dp_irmao = dp
break
if tipo.permitido_inserir_in(
dp.tipo_dispositivo,
perfil_pk=context['perfil_pk']):
dp_pai = dp
break
dp_pai = dp
if dp_irmao is not None:
dp = Dispositivo.new_instance_based_on(dp_irmao, tipo)
dp.transform_in_next(variacao)
else:
# Inserção sem precedente
dp = Dispositivo.new_instance_based_on(dp_pai, tipo)
dp.dispositivo_pai = dp_pai
dp.nivel += 1
if tipo.contagem_continua:
ultimo_irmao = Dispositivo.objects.order_by(
'-ordem').filter(
ordem__lte=base.ordem,
tipo_dispositivo_id=tipo.pk,
ta_id=base.ta_id)[:1]
if not ultimo_irmao.exists():
dp.set_numero_completo([1, 0, 0, 0, 0, 0, ])
else:
ultimo_irmao = ultimo_irmao[0]
dp.set_numero_completo(
ultimo_irmao.get_numero_completo())
dp.transform_in_next()
else:
if ';' in tipo.rotulo_prefixo_texto:
dp.set_numero_completo([0, 0, 0, 0, 0, 0, ])
else:
dp.set_numero_completo([1, 0, 0, 0, 0, 0, ])
# verificar se existe restrição de quantidade de itens
if dp.dispositivo_pai:
pp = dp.tipo_dispositivo.possiveis_pais.filter(
pai_id=dp.dispositivo_pai.tipo_dispositivo_id,
perfil_id=context['perfil_pk'])
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()
if qtd_existente >= pp[0].quantidade_permitida:
return {'pk': base.pk,
'pai': [base.dispositivo_pai.pk, ],
'alert': str(_('Limite de inserções de '
'dispositivos deste tipo '
'foi excedido.'))
}
ordem = base.criar_espaco(
espaco_a_criar=1 + count_auto_insert, local=local_add)
dp.rotulo = dp.rotulo_padrao()
dp.ordem = ordem
dp.incrementar_irmaos(variacao, [local_add, ])
dp.clean()
dp.save()
dp_auto_insert = None
# Inserção automática
if count_auto_insert:
dp_pk = dp.pk
dp.nivel += 1
for tipoauto in tipos_dp_auto_insert:
dp.dispositivo_pai_id = dp_pk
dp.pk = None
dp.tipo_dispositivo = tipoauto.filho_permitido
if ';' in dp.tipo_dispositivo.rotulo_prefixo_texto:
dp.set_numero_completo([0, 0, 0, 0, 0, 0, ])
else:
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.clean()
dp.save()
dp_auto_insert = dp
dp = Dispositivo.objects.get(pk=dp_pk)
''' Reenquadrar todos os dispositivos que possuem pai
antes da inserção atual e que são inferiores a dp,
redirecionando para o novo pai'''
nivel = sys.maxsize
flag_niveis = False
if not dp.tipo_dispositivo.dispositivo_de_alteracao:
possiveis_filhos = Dispositivo.objects.filter(
ordem__gt=dp.ordem,
ta_id=dp.ta_id)
for filho in possiveis_filhos:
if filho.nivel > nivel:
continue
if filho.dispositivo_pai.ordem >= dp.ordem:
continue
nivel = filho.nivel
if not filho.tipo_dispositivo.permitido_inserir_in(
dp.tipo_dispositivo,
perfil_pk=context['perfil_pk']):
continue
filho.dispositivo_pai = dp
filho.clean()
filho.save()
flag_niveis = True
if flag_niveis:
dp.organizar_niveis()
numtipos = {}
''' Renumerar filhos imediatos que
não possuam contagem continua'''
if flag_niveis:
filhos = Dispositivo.objects.filter(
dispositivo_pai_id=dp.pk)
for filho in filhos:
if filho.tipo_dispositivo.contagem_continua:
continue
if filho.tipo_dispositivo.class_css in numtipos:
if filho.dispositivo_substituido is None:
numtipos[filho.tipo_dispositivo.class_css] += 1
else:
t = filho.tipo_dispositivo
prefixo = t.rotulo_prefixo_texto.split(';')
if len(prefixo) > 1:
count_irmaos_m_tipo = Dispositivo.objects.filter(
~Q(pk=filho.pk),
tipo_dispositivo=t,
dispositivo_pai=filho.dispositivo_pai)[:1]
if count_irmaos_m_tipo.exists():
numtipos[filho.tipo_dispositivo.class_css] = 1
else:
numtipos[filho.tipo_dispositivo.class_css] = 0
else:
numtipos[filho.tipo_dispositivo.class_css] = 1
filho.dispositivo0 = numtipos[
filho.tipo_dispositivo.class_css]
filho.rotulo = filho.rotulo_padrao()
filho.clean()
filho.save()
''' Renumerar dispositivos de
contagem continua, caso a inserção seja uma articulação'''
numtipos = {}
if dp.nivel == 0:
proxima_articulacao = Dispositivo.objects.filter(
ordem__gt=dp.ordem,
nivel=0,
ta_id=dp.ta_id)[:1]
if not proxima_articulacao.exists():
filhos_continuos = list(Dispositivo.objects.filter(
ordem__gt=dp.ordem,
ta_id=dp.ta_id,
tipo_dispositivo__contagem_continua=True))
else:
filhos_continuos = list(Dispositivo.objects.filter(
Q(ordem__gt=dp.ordem) &
Q(ordem__lt=proxima_articulacao[0].ordem),
ta_id=dp.ta_id,
tipo_dispositivo__contagem_continua=True))
for filho in filhos_continuos:
if filho.tipo_dispositivo.class_css in numtipos:
if filho.dispositivo_substituido is None:
numtipos[filho.tipo_dispositivo.class_css] += 1
else:
t = filho.tipo_dispositivo
prefixo = t.rotulo_prefixo_texto.split(';')
if len(prefixo) > 1:
count_irmaos_m_tipo = Dispositivo.objects.filter(
~Q(pk=filho.pk),
tipo_dispositivo=t,
dispositivo_pai=filho.dispositivo_pai)[:1]
if count_irmaos_m_tipo.exists():
numtipos[filho.tipo_dispositivo.class_css] = 1
else:
numtipos[filho.tipo_dispositivo.class_css] = 0
else:
numtipos[filho.tipo_dispositivo.class_css] = 1
filho.dispositivo0 = numtipos[
filho.tipo_dispositivo.class_css]
filho.rotulo = filho.rotulo_padrao()
filho.clean()
filho.save()
except Exception as e:
print(e)
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)
return data
def get_json_for_refresh(self, dp, dpauto=None):
if dp.tipo_dispositivo.contagem_continua:
pais = []
if dp.dispositivo_pai is None:
data = {'pk': dp.pk, 'pai': [-1, ]}
else:
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)
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, ]}
return data
class ActionsEditView(ActionsEditMixin, TemplateView):
def render_to_response(self, context, **response_kwargs):
context['action'] = self.request.GET['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']
return self.render_to_json_response(context, **response_kwargs)
class DispositivoSuccessUrlMixin(object):
def get_success_url(self):

1043
compilacao/views2.py

File diff suppressed because it is too large

41
materia/views.py

@ -4,21 +4,20 @@ from re import sub
from crispy_forms.helper import FormHelper
from crispy_forms.layout import ButtonHolder, Column, Fieldset, Layout, Submit
from django import forms
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse, reverse_lazy
from django.core.urlresolvers import reverse
from django.forms import ModelForm
from django.shortcuts import get_object_or_404, redirect
from django.shortcuts import redirect
from django.utils.html import strip_tags
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.views.generic import ListView
from django.views.generic.edit import FormMixin
from vanilla import GenericView
from vanilla.views import GenericView
import sapl
from comissoes.models import Comissao, Composicao
from compilacao.models import TextoArticulado, TipoTextoArticulado
from compilacao.views import IntegracaoTaView
from norma.models import LegislacaoCitada, NormaJuridica, TipoNormaJuridica
from parlamentares.models import Parlamentar
from sapl.crud import build_crud
@ -2022,33 +2021,5 @@ class PesquisaMateriaListView(FormMixin, ListView):
return context
class MateriaTaView(GenericView):
def get(self, *args, **kwargs):
materia = get_object_or_404(MateriaLegislativa, pk=kwargs['pk'])
related_object_type = ContentType.objects.get_for_model(materia)
ta = TextoArticulado.objects.filter(
object_id=materia.pk,
content_type=related_object_type)
if not ta.exists():
tipo_ta = TipoTextoArticulado.objects.filter(
model=materia.__class__.__name__.lower())[:1]
ta = TextoArticulado()
if tipo_ta.exists():
ta.tipo_ta = tipo_ta[0]
ta.ementa = materia.ementa
ta.numero = materia.numero
ta.ano = materia.ano
ta.data = materia.data_apresentacao
ta.content_object = materia
ta.save()
else:
ta = ta[0]
return redirect(to=reverse_lazy('ta_text', kwargs={'ta_id': ta.pk}))
class MateriaTaView(IntegracaoTaView):
model = MateriaLegislativa

2
norma/models.py

@ -72,7 +72,7 @@ class NormaJuridica(models.Model):
null=True,
upload_to=texto_upload_path,
verbose_name=_('Texto Integral'))
tipo = models.ForeignKey(TipoNormaJuridica, verbose_name=_('Tipo'))
tipo = models.ForeignKey(TipoNormaJuridica, verbose_name=_('Tipo da Norma Juridica'))
materia = models.ForeignKey(MateriaLegislativa, blank=True, null=True)
numero = models.PositiveIntegerField(verbose_name=_('Número'))
ano = models.PositiveSmallIntegerField(verbose_name=_('Ano'))

39
norma/views.py

@ -4,19 +4,16 @@ from re import sub
from crispy_forms.helper import FormHelper
from crispy_forms.layout import ButtonHolder, Fieldset, Layout, Submit
from django import forms
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse_lazy
from django.forms import ModelForm
from django.shortcuts import get_object_or_404, redirect
from django.utils.html import strip_tags
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.views.generic.edit import FormMixin
from vanilla import GenericView
from vanilla.views import GenericView
import sapl
from compilacao.models import TextoArticulado, TipoTextoArticulado
from compilacao.views import IntegracaoTaView
from materia.models import MateriaLegislativa, TipoMateriaLegislativa
from sapl.crud import build_crud
@ -224,33 +221,5 @@ class NormaIncluirView(FormMixin, GenericView):
return self.form_invalid(form)
class NormaTaView(GenericView):
def get(self, *args, **kwargs):
norma = get_object_or_404(NormaJuridica, pk=kwargs['pk'])
related_object_type = ContentType.objects.get_for_model(norma)
ta = TextoArticulado.objects.filter(
object_id=norma.pk,
content_type=related_object_type)
if not ta.exists():
tipo_ta = TipoTextoArticulado.objects.filter(
model=norma.__class__.__name__.lower())[:1]
ta = TextoArticulado()
if tipo_ta.exists():
ta.tipo_ta = tipo_ta[0]
ta.ementa = norma.ementa
ta.numero = norma.numero
ta.ano = norma.ano
ta.data = norma.data
ta.content_object = norma
ta.save()
else:
ta = ta[0]
return redirect(to=reverse_lazy('ta_text', kwargs={'ta_id': ta.pk}))
class NormaTaView(IntegracaoTaView):
model = NormaJuridica

2
static/js/compilacao_edit.js

@ -167,7 +167,7 @@ var clickUpdateDispositivo = function(event, __pk_refresh, __pk_edit, __action,
if (flag_actions_vibible == null || flag_actions_vibible) {
$('#dpt'+pk_edit).addClass('dpt-selected');
$('html, body').animate({
scrollTop: $('#dpt' + pk_edit ).offset().top - window.innerHeight / 10
scrollTop: $('#dpt' + pk_edit ).offset().top - window.innerHeight / 9
}, 0);
}
}

32
static/styles/app.scss

@ -25,8 +25,8 @@ $top-bar-dropdown-radius: $global-radius;
}
}
// Restyles to foundation top bar menu, in order to behave aesthetically different
/*
// Restyles to foundation top bar menu, in order to behave aesthetically different
/*
XXX
Is there a better way to implement these styles using best practices without the
need to override this much of foundation? Or at least avoid too much nesting and
@ -38,7 +38,7 @@ $top-bar-dropdown-radius: $global-radius;
.has-dropdown {
// Default values for dropdowns, while also being hidden.
.dropdown {
// Border-radius for the first and last dropdown items. We don't style the parent dropdown, as the items overflows it.
// Border-radius for the first and last dropdown items. We don't style the parent dropdown, as the items overflows it.
@include radius(rem-calc($top-bar-dropdown-radius));
// Second child here actually targets the first item, since Foundation JS injects a hidden li before it for a mobile back button.
> li:nth-child(2), > li:nth-child(2) > a {
@ -50,8 +50,8 @@ $top-bar-dropdown-radius: $global-radius;
box-shadow: 0 10px 18px rgba(0, 0, 0, 0.19),
0 2px 6px rgba(0, 0, 0, 0.23);
// For the transition effect.
opacity: 0;
// Show the dropdown accurately while it animates.
opacity: 0;
// Show the dropdown accurately while it animates.
width: auto;
// This will allow the triangle pip to be visible above the dropdown.
overflow: visible;
@ -68,14 +68,14 @@ $top-bar-dropdown-radius: $global-radius;
position: absolute;
top: rem-calc(-12px);
left: rem-calc(15px);
}
// This bridges the gap between the top bar and a dropdown.
}
// This bridges the gap between the top bar and a dropdown.
&::after {
content: "";
position: absolute;
z-index: -1;
left: 0;
top: rem-calc(-25px);
top: rem-calc(-25px);
height: rem-calc(25px);
width: 100%;
// This transition is for hover-on.
@ -94,7 +94,7 @@ $top-bar-dropdown-radius: $global-radius;
pointer-events: auto;
// Animating with a beautiful cubic-bezier curve, or Google's "Swift out" easing :)
transition: transform 0.3s cubic-bezier(0.55,0,0.1,1),
opacity 0.3s cubic-bezier(0.55,0,0.1,1),
opacity 0.3s cubic-bezier(0.55,0,0.1,1),
// Here we make sure the clipping is set before any other transition.
clip 0s 0s;
// Don't forget to properly animate our bridge, so it keeps only between our gap.
@ -107,6 +107,8 @@ $top-bar-dropdown-radius: $global-radius;
}
}
// Our app
// - - - - - - - - - - - - - - - - - - - - - - - - -
@ -158,7 +160,7 @@ color: $primary-color;
.fadein {
-webkit-animation: fadeIn 0.25s ease-in-out;
-moz-animation: fadeIn 0.25s ease-in-out;
-o-animation: fadeIn 0.25s ease-in-out;
-o-animation: fadeIn 0.25s ease-in-out;
}
.container {
@ -181,7 +183,7 @@ color: #444444;
display: table-row;
box-sizing: content-box;
}
/* XXX find a better way to fix main layout box-sizing */
.page__row > .container > *{
box-sizing: border-box;
@ -196,6 +198,12 @@ box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 1px 4px rgba(0, 0, 0, 0.23);
max-width: 960px;
}
.sub-nav {
dt a, dd a, li a {
color: white !important;
}
}
.icon-bar {
vertical-align: top;
@ -301,7 +309,7 @@ text-align: center;
.footer__block--about {
padding-left: 0;
max-width: 195px;
max-width: 195px;
}
.footer__block--license {

5
static/styles/compilacao.scss

@ -79,7 +79,7 @@ a:link:after, a:visited:after {
width: 0px;
border-color: transparent transparent #3385CA;
position: absolute;
top: -0.75rem;
top: -0.71rem;
left: 0.9375rem;
}
&:hover::before {
@ -597,6 +597,7 @@ a:link:after, a:visited:after {
.dne {
height: 0.1667rem;
transform: scaleX(1);
transition-delay: 1s;
ul.btns-action {
clip: rect(-100px, 2000px, 2000px, -100px);
@ -610,7 +611,7 @@ a:link:after, a:visited:after {
}
.dne-nota {
height: auto;
transition-delay: 0s;
}
}

9
templates/base.html

@ -117,12 +117,12 @@
{% block main_header %}
<header id="masthead" class="masthead page__row">
<div class="container">
<a class="masthead__logo" href="#">
<a class="masthead__logo" href="#">
{% if logotipo %}
<img src="{{ MEDIA_URL }}{{ logotipo }}" alt="Logo">
{% else %}
<img src="{% static 'img/logo.png' %}" alt="Logo">
{% endif %}
{% endif %}
</a>
<div class="masthead__heading">
{# XXX Make better use of translation tags in html blocks ie. actually use the proper blocktrans tag efficiently #}
@ -158,7 +158,7 @@
{% block title %}
{% if view.title %}
<h1>{{ view.title }}</h1>
<h1>{{ view.title|linebreaksbr }}</h1>
{% endif %}
{% endblock %}
@ -214,9 +214,10 @@
<script>tinymce.init({selector:'textarea'});</script>
<script>$(document).foundation();</script>
<script type="text/javascript">
$(function () {
$('.dateinput').fdatepicker({
// TODO localize
format: 'dd/mm/yyyy',

5
templates/compilacao/text_edit.html

@ -18,12 +18,11 @@
{% endblock %}
{% block sections_nav %}
{% block sections_nav %}{{block.super}}
<dd><a href="{% url 'ta_text' object.pk %}" class="button secondary">{% trans 'Texto' %}</a></dd>
{% endblock %}
{% block base_content %}{{block.super}}
{% block actions %}{% endblock %}
{% block detail_content %}{% endblock %}
<div id="message_block"><div id="msg">{% trans 'Aguarde... Atualizando informações!!!'%}</div></div>

4
templates/compilacao/text_edit_bloco.html

@ -35,7 +35,7 @@
</ul>
<ul class="btns-action actions_left">
<li><a class="btn-left btn-action" pk="{{dpt.pk}}" title="TODO: Vides...">Vd</a></li>
<li><a class="btn-left btn-action" pk="{{dpt.pk}}" title="">.</a></li>
</ul>
<ul class="btns-action actions_bottom">
{% for perfil in perfil_estrutural_list%}
@ -108,7 +108,7 @@
{% spaceless %}
<div class="de" id="id{{dpt.id}}" pk="{{dpt.pk}}" ordem="{{dpt.ordem}}" name="{{dpt.pk}}" title="{{dpt.pk}}">{{ 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 %}<span class="semtexto">({{dpt.tipo_dispositivo}} sem texto)</span>{%else%}{{ dpt.texto|safe }}{%endif%}</div>
{% if dpt.ta_publicado_id != None and not dpt.tipo_dispositivo.dispositivo_de_articulacao %}
<a class="link_alterador" href="{%url 'comp_edit' dpt.ta_publicado.pk %}#{{dpt.dispositivo_atualizador_id}}">
<a class="link_alterador" href="{%url 'ta_text_edit' dpt.ta_publicado.pk %}#{{dpt.dispositivo_atualizador_id}}">
{{ dpt.tipo_dispositivo.nota_automatica_prefixo_html|safe }}
{% nota_automatica dpt %}
{{ dpt.tipo_dispositivo.nota_automatica_sufixo_html|safe }}

2
templates/compilacao/text_edit_blocoalteracao.html

@ -3,7 +3,7 @@
{% spaceless %}
<div class="dpt" id="d{{ch.id}}">
<div class="{{ ch.tipo_dispositivo.class_css }}" id="id{{ch.id}}" nivel="{{ch.nivel}}">
{{ ch.tipo_dispositivo.rotulo_prefixo_html|safe }}<a name="{{ch.pk}}" href="{%url 'comp_edit' ch.ta.pk %}#{{ch.pk}}">{{ ch.rotulo }}</a>{{ ch.tipo_dispositivo.rotulo_sufixo_html|safe }}{{ ch.tipo_dispositivo.texto_prefixo_html|safe }}{{ ch.texto|safe }}
{{ ch.tipo_dispositivo.rotulo_prefixo_html|safe }}<a name="{{ch.pk}}" href="{%url 'ta_text_edit' ch.ta.pk %}#{{ch.pk}}">{{ ch.rotulo }}</a>{{ ch.tipo_dispositivo.rotulo_sufixo_html|safe }}{{ ch.tipo_dispositivo.texto_prefixo_html|safe }}{{ ch.texto|safe }}
</div>
</div>
{% endspaceless %}

11
templates/compilacao/text_list.html

@ -16,23 +16,14 @@
{% endif %}
{% endblock %}
{% block title%}
<h1>{{ view.get_ta }}</h1>
{% endblock %}
{% block sections_nav %}{{block.super}}
<dd><a href="{% url 'ta_text_edit' object.pk %}" class="button secondary">{% trans 'Edição do Texto' %}</a></dd>
<dd><a href="{% url 'ta_text_edit' object.pk %}" class="button secondary">{% trans 'Edição' %}</a></dd>
{% endblock %}
{% block base_content %}{{block.super}}
{% block actions %}{% endblock %}
{% block detail_content %}{% endblock %}
<div class="cp">
{% if object_list %}
<div style="float: right; clear:right;">
<a id="btn_font_menos" title="Diminuir tamanho da letra">a</a>

44
templates/compilacao/textoarticulado_detail.html

@ -1,29 +1,25 @@
{% extends "base.html" %} {% load i18n %} {% load compilacao_filters %}
{% extends "base.html" %} {% load i18n %} {% load compilacao_filters %}
{% block base_content %} {# FIXME is this the best markup to use? #}
<div class="clearfix">
{% block actions %}
<dl class="sub-nav right">
<dd><a href="{% url 'ta_edit' object.pk %}" class="button">{% trans 'Editar' %}</a></dd>
<dd><a href="{% url 'ta_edit' object.pk %}" class="button">{% trans 'Edição dos Metadados do Texto Articulado' %}</a></dd>
<dd><a href="{% url 'ta_delete' object.pk %}" class="button alert">{% trans 'Excluir' %}</a></dd>
</dl>
{% endblock actions %}
<dl class="sub-nav left">
{% block sections_nav %}
<dd><a href="{% url 'ta_detail' object.pk %}" class="button secondary">{% trans 'Início' %}</a></dd>
<dd><a href="{% url 'ta_text' object.pk %}" class="button secondary">{% trans 'Texto' %}</a></dd>
{% endblock %}
</dl>
{% block sections_nav %}
{% if object.content_object%}
<dd><a href="{% url object|urldetail_content_type object.content_object.pk %}" class="button secondary" title="{% trans 'Ir para '%}{{object.content_object}}">Início</a></dd>
{%else%}
<dd><a href="{% url 'ta_detail' object.pk %}" class="button secondary">{% trans 'Início' %}</a></dd>
{%endif%}
{% endblock %}
</dl>
</div>
{% block detail_content %} {# TODO replace fieldset for something semantically correct, but with similar visual grouping style #}
<fieldset>
<legend>{%trans 'Identificação Básica'%}</legend>
@ -36,14 +32,14 @@
</div>
</div>
{% if object.content_object %}
<div class="columns large-3">
<div id="div_id_tipo" class="holder">
<label>{% verbose_name object.content_object 'tipo' %}</label>
<p>{{ object.content_object.tipo}}</p>
</div>
</div>
{%endif%}
{% if object.content_object and object.content_object.tipo%}
<div class="columns large-3">
<div id="div_id_tipo" class="holder">
<label>{% verbose_name object.content_object 'tipo' %}</label>
<p>{{ object.content_object.tipo}}</p>
</div>
</div>
{%endif%}
<div class="columns large-2">
<div id="div_id_numero" class="holder">
@ -74,8 +70,6 @@
<p>{{ object.ementa|safe}}</p>
</div>
</div>
</div>
</fieldset>
</fieldset>
{% endblock detail_content %} {% endblock base_content %}

7
templates/materia/materialegislativa_detail.html

@ -12,6 +12,13 @@
<dd><a href="{% url 'numeracao' materialegislativa.id %}" class="button secondary">{% trans 'Numeração' %}</a></dd>
<dd><a href="{% url 'tramitacao_materia' materialegislativa.id %}" class="button secondary">{% trans 'Tramitação' %}</a></dd>
<dd><a href="{% url 'relatoria' materialegislativa.id %}" class="button secondary">{% trans 'Relatoria' %}</a></dd>
{% comment %}
Opção adicionada para chamar o TextoArticulado da matéria.
para integração foram necessárias apenas criar a url materia_ta em urls.py
e a view MateriaTaView(IntegracaoTaView) em views.py
Em nada mais a integração interfere em MateriaLegislativa
{% endcomment %}
<dd><a href="{% url 'materia_ta' materialegislativa.id %}" class="button secondary">{% trans 'Texto' %}</a></dd>
</dl>
{% endblock sections_nav %}

15
templates/norma/normajuridica_detail.html

@ -1,15 +1,16 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% block actions %}
<dl class="sub-nav right">
<dd><a href="{% url 'ta_edit' object.pk %}" class="button">{% trans 'Editar' %}</a></dd>
<dd><a href="{% url 'ta_delete' object.pk %}" class="button alert">{% trans 'Excluir' %}</a></dd>
</dl>
{% endblock actions %}
{% block sections_nav %}
<dl class="sub-nav left">
<dd><a href="{% url 'normajuridica:detail' object.pk %}" class="button secondary">{% trans 'Início' %}</a></dd>
{% comment %}
Opção adicionada para chamar o TextoArticulado da norma.
para integração foram necessárias apenas criar a url norma_ta em urls.py
e a view NormaTa(IntegracaoTaView) em views.py
Em nada mais a integração interfere em Norma Jurídica
{% endcomment %}
<dd><a href="{% url 'norma_ta' object.pk %}" class="button secondary">{% trans 'Texto' %}</a></dd>
</dl>
{% endblock sections_nav %}

10
templates/sistema.html

@ -77,16 +77,6 @@
<li><a href="">Assunto de Norma Jurídica</a></li>
</ul>
<h5>Módulo Compilação</h5>
<ul class="small-block-grid-1 medium-block-grid-2 large-block-grid-2">
<li><a href="{% url 'tipodispositivo:list' %}">Tipo de Dispositivo</a></li>
<li><a href="{% url 'tiponota:list' %}">Tipo de Nota</a></li>
<li><a href="{% url 'tipovide:list' %}">Tipo de Vide</a></li>
<li><a href="{% url 'tipopublicacao:list' %}">Tipo de Publicação</a></li>
<li><a href="{% url 'veiculopublicacao:list' %}">Veículo de Públicação</a></li>
<li><a href="{% url 'perfilestruturaltextosnormativos:list' %}">Perfil Estrutural de Textos Normativos</a></li>
</ul>
<h5>Módulo Sessão Plenária</h5>
<ul class="small-block-grid-1 medium-block-grid-2 large-block-grid-2">
<li><a href="{% url 'tiposessaoplenaria:list' %}">Tipo de Sessão Plenária</a></li>

Loading…
Cancel
Save