Browse Source

Conclusão da Edição Avançada - Issue #14

pull/299/head
LeandroRoberto 9 years ago
parent
commit
1e88b25216
  1. 291
      compilacao/forms.py
  2. 21
      compilacao/migrations/0048_auto_20160404_2309.py
  3. 16
      compilacao/migrations/0049_merge.py
  4. 4
      compilacao/models.py
  5. 92
      compilacao/templatetags/compilacao_filters.py
  6. 6
      compilacao/urls.py
  7. 312
      compilacao/views.py
  8. 2
      crispy_layout_mixin.py
  9. 2
      norma/urls.py
  10. 19
      static/js/app.js
  11. 4
      static/js/compilacao.js
  12. 11
      templates/compilacao/dispositivo_form.html
  13. 12
      templates/compilacao/dispositivo_form_alteracao.html
  14. 2
      templates/compilacao/dispositivo_form_definidor_vigencia.html
  15. 8
      templates/compilacao/dispositivo_form_edicao_basica.html
  16. 33
      templates/compilacao/dispositivo_form_search_fragment.html
  17. 1
      templates/compilacao/dispositivo_form_vigencia.html
  18. 3
      templates/compilacao/layout/dispositivo_checkbox.html
  19. 41
      templates/compilacao/layout/dispositivo_radio.html
  20. 8
      templates/compilacao/text_edit.html
  21. 2
      templates/compilacao/text_list_bloco.html
  22. 8
      templates/compilacao/textoarticulado_menu_config.html

291
compilacao/forms.py

@ -1,7 +1,7 @@
from datetime import datetime from datetime import timedelta
from crispy_forms.bootstrap import FieldWithButtons, FormActions, StrictButton,\ from crispy_forms.bootstrap import (Alert, FieldWithButtons, FormActions,
InlineRadios, Alert InlineRadios, StrictButton)
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.layout import (HTML, Button, Column, Div, Field, Fieldset, from crispy_forms.layout import (HTML, Button, Column, Div, Field, Fieldset,
Layout, Row) Layout, Row)
@ -10,20 +10,18 @@ from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
from django.forms.forms import Form from django.forms.forms import Form
from django.forms.models import ModelForm from django.forms.models import ModelForm
from django.template import defaultfilters from django.template import defaultfilters
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from compilacao.models import (NOTAS_PUBLICIDADE_CHOICES, from compilacao.models import (NOTAS_PUBLICIDADE_CHOICES,
PARTICIPACAO_SOCIAL_CHOICES, Dispositivo, Nota, PARTICIPACAO_SOCIAL_CHOICES, Dispositivo, Nota,
Publicacao, TextoArticulado, TipoNota, Publicacao, TextoArticulado, TipoDispositivo,
TipoPublicacao, TipoTextoArticulado, TipoVide, TipoNota, TipoPublicacao, TipoTextoArticulado,
VeiculoPublicacao, Vide, TipoDispositivo) TipoVide, VeiculoPublicacao, Vide)
from compilacao.utils import DISPOSITIVO_SELECT_RELATED from compilacao.utils import DISPOSITIVO_SELECT_RELATED
from crispy_layout_mixin import SaplFormLayout, to_column, to_row from crispy_layout_mixin import SaplFormLayout, to_column, to_row
from sapl import utils from sapl import utils
from sapl.utils import YES_NO_CHOICES from sapl.utils import YES_NO_CHOICES
error_messages = { error_messages = {
'required': _('Este campo é obrigatório'), 'required': _('Este campo é obrigatório'),
'invalid': _('URL inválida.') 'invalid': _('URL inválida.')
@ -516,6 +514,13 @@ class DispositivoEdicaoBasicaForm(ModelForm):
model = Dispositivo model = Dispositivo
fields = [] fields = []
error_messages = {
NON_FIELD_ERRORS: {
'unique_together':
_("Já existe um Dispositivo com características idênticas."),
}
}
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
layout = [] layout = []
@ -598,10 +603,9 @@ class DispositivoEdicaoBasicaForm(ModelForm):
self.helper = FormHelper() self.helper = FormHelper()
self.helper.layout = SaplFormLayout( self.helper.layout = SaplFormLayout(
*layout,
label_cancel=_('Retornar para o Editor Sequencial')) label_cancel=_('Retornar para o Editor Sequencial'))
self.helper.layout.fields += layout
super(DispositivoEdicaoBasicaForm, self).__init__(*args, **kwargs) super(DispositivoEdicaoBasicaForm, self).__init__(*args, **kwargs)
@ -622,11 +626,20 @@ class DispositivoSearchModalForm(Form):
label=_('Ano do Documento'), required=False) label=_('Ano do Documento'), required=False)
dispositivos_internos = forms.ChoiceField( dispositivos_internos = forms.ChoiceField(
label=_('Incluir Dispositivos Internos Imediatos?'), label=_('Dispositivos Internos?'),
choices=utils.YES_NO_CHOICES, choices=utils.YES_NO_CHOICES,
widget=forms.RadioSelect(), widget=forms.RadioSelect(),
required=False) required=False)
max_results = forms.ChoiceField(
label=_('Limite de Listagem'),
choices=[(10, _('Dez Dispositivos')),
(30, _('Trinta Dispositivos')),
(50, _('Cinquenta Dispositivos')),
(0, _('Tudo que atender aos Critérios da Busca'))],
widget=forms.Select(),
required=False)
rotulo_dispositivo = forms.CharField( rotulo_dispositivo = forms.CharField(
label=_('Rótulo'), label=_('Rótulo'),
required=False) required=False)
@ -640,20 +653,22 @@ class DispositivoSearchModalForm(Form):
fields_search = Fieldset( fields_search = Fieldset(
_('Busca por um Dispositivo'), _('Busca por um Dispositivo'),
Row( Row(
to_column(('num_ta', 3)), to_column(('num_ta', 4)),
to_column(('ano_ta', 3)), to_column(('ano_ta', 4)),
to_column((InlineRadios('dispositivos_internos'), 6))), to_column(('max_results', 4))),
Row( Row(
to_column(('tipo_ta', 6)), to_column(('tipo_ta', 6)),
to_column(('tipo_model', 6))), to_column(('tipo_model', 6))),
Row(to_column(('rotulo_dispositivo', 3)), Row(to_column((InlineRadios('dispositivos_internos'), 3)),
to_column(('rotulo_dispositivo', 2)),
to_column((FieldWithButtons( to_column((FieldWithButtons(
Field( Field(
'texto_dispositivo', 'texto_dispositivo',
placeholder=_('Digite palavras, letras, ' placeholder=_('Digite palavras, letras, '
'números ou algo' 'números ou algo'
' que estejam no texto.')), ' que estejam no texto.')),
StrictButton(_('Buscar'), css_class='btn-busca')), 9))) StrictButton(_('Buscar'), css_class='btn-busca')), 7))
)
) )
self.helper = FormHelper() self.helper = FormHelper()
@ -707,6 +722,13 @@ class DispositivoEdicaoVigenciaForm(ModelForm):
'dispositivo_vigencia' 'dispositivo_vigencia'
] ]
error_messages = {
NON_FIELD_ERRORS: {
'unique_together':
_("Já existe um Dispositivo com características idênticas."),
}
}
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
layout = [] layout = []
@ -849,8 +871,11 @@ class DispositivoDefinidorVigenciaForm(Form):
*DISPOSITIVO_SELECT_RELATED) *DISPOSITIVO_SELECT_RELATED)
self.initial['dispositivo_vigencia'] = [d.pk for d in dvs] self.initial['dispositivo_vigencia'] = [d.pk for d in dvs]
tas = Dispositivo.objects.filter( TA_TA_PUB = 'ta_id', 'ta_publicado_id'
dispositivo_vigencia_id=pk).values_list('ta', 'ta_publicado') tas = Dispositivo.objects.order_by(
*TA_TA_PUB).filter(dispositivo_vigencia_id=pk).distinct(
*TA_TA_PUB).values_list(
*TA_TA_PUB)
tas = list(set().union(*list(map(list, zip(*tas))))) tas = list(set().union(*list(map(list, zip(*tas)))))
@ -864,3 +889,233 @@ class DispositivoDefinidorVigenciaForm(Form):
(d.pk, d) (d.pk, d)
for d in dvs for d in dvs
if d.pk in self.initial['dispositivo_vigencia']] if d.pk in self.initial['dispositivo_vigencia']]
class DispositivoEdicaoAlteracaoForm(ModelForm):
class Meta:
model = Dispositivo
fields = [
'dispositivo_atualizador',
'dispositivo_substituido',
'dispositivo_subsequente',
]
error_messages = {
NON_FIELD_ERRORS: {
'unique_together':
_("Já existe um Dispositivo com características idênticas."),
}
}
def __init__(self, *args, **kwargs):
layout = []
self.dispositivo_substituido = forms.ModelChoiceField(
label=Dispositivo._meta.get_field(
'dispositivo_substituido').verbose_name,
required=False,
queryset=Dispositivo.objects.all())
self.dispositivo_subsequente = forms.ModelChoiceField(
label=Dispositivo._meta.get_field(
'dispositivo_subsequente').verbose_name,
required=False,
queryset=Dispositivo.objects.all())
self.dispositivo_atualizador = forms.ModelChoiceField(
label=Dispositivo._meta.get_field(
'dispositivo_atualizador').verbose_name,
required=False,
queryset=Dispositivo.objects.all())
substituido = Field(
'dispositivo_substituido',
data_sapl_ta='DispositivoSearch',
data_field='dispositivo_substituido',
data_type_selection='radio',
template="compilacao/layout/dispositivo_radio.html")
subsequente = Field(
'dispositivo_subsequente',
data_sapl_ta='DispositivoSearch',
data_field='dispositivo_subsequente',
data_type_selection='radio',
template="compilacao/layout/dispositivo_radio.html")
alterador = Field(
'dispositivo_atualizador',
data_sapl_ta='DispositivoSearch',
data_field='dispositivo_atualizador',
data_type_selection='radio',
data_function='alterador',
template="compilacao/layout/dispositivo_radio.html")
layout.append(
to_row([
(Fieldset(_('Dispositivo Subsitituido'), substituido), 6),
(Fieldset(_('Dispositivo Subsequente'), subsequente), 6)]))
layout.append(
Fieldset(
_('Dispositivo Alterador'),
Div(alterador),
css_class="col-md-12"))
inst = kwargs['instance'] if 'instance' in kwargs else None
if inst and inst.tipo_dispositivo.dispositivo_de_articulacao:
if 'texto_atualizador' in\
DispositivoEdicaoAlteracaoForm.Meta.fields:
DispositivoEdicaoAlteracaoForm.Meta.fields.remove(
'texto_atualizador')
DispositivoEdicaoAlteracaoForm.Meta.fields.remove(
'visibilidade')
else:
if 'texto_atualizador' not in\
DispositivoEdicaoAlteracaoForm.Meta.fields:
DispositivoEdicaoAlteracaoForm.Meta.fields.append(
'texto_atualizador')
DispositivoEdicaoAlteracaoForm.Meta.fields.append(
'visibilidade')
self.texto_atualizador = forms.CharField(required=False,
label='',
widget=forms.Textarea())
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"))
fields = DispositivoEdicaoAlteracaoForm.Meta.fields
if fields:
self.base_fields.clear()
for f in fields:
if hasattr(self, f):
self.base_fields.update({f: getattr(self, f)})
self.helper = FormHelper()
self.helper.layout = SaplFormLayout(
*layout,
label_cancel=_('Retornar para o Editor Sequencial'))
super(DispositivoEdicaoAlteracaoForm, self).__init__(*args, **kwargs)
self.fields['dispositivo_substituido'].choices = []
self.fields['dispositivo_subsequente'].choices = []
self.fields['dispositivo_atualizador'].choices = []
if inst.dispositivo_substituido:
self.fields['dispositivo_substituido'].choices = [
(inst.dispositivo_substituido.pk,
inst.dispositivo_substituido)]
if inst.dispositivo_subsequente:
self.fields['dispositivo_subsequente'].choices = [
(inst.dispositivo_subsequente.pk,
inst.dispositivo_subsequente)]
if inst.dispositivo_atualizador:
self.fields['dispositivo_atualizador'].choices = [
(inst.dispositivo_atualizador.pk,
inst.dispositivo_atualizador)]
def clean_dispositivo_substituido(self):
dst = self.cleaned_data['dispositivo_substituido']
if dst and dst.ta != self.instance.ta:
raise ValidationError(_('Não é permitido selecionar um '
'Dispositivo de outro Texto Articulado.'))
if dst and dst.tipo_dispositivo != self.instance.tipo_dispositivo:
raise ValidationError(_('Não é permitido selecionar um '
'Dispositivo de outro Tipo.'))
return dst
def clean_dispositivo_subsequente(self):
dsq = self.cleaned_data['dispositivo_subsequente']
if dsq and dsq.ta != self.instance.ta:
raise ValidationError(_('Não é permitido selecionar um '
'Dispositivo de outro Texto Articulado.'))
if dsq and dsq.tipo_dispositivo != self.instance.tipo_dispositivo:
raise ValidationError(_('Não é permitido selecionar um '
'Dispositivo de outro Tipo.'))
return dsq
def clean_dispositivo_atualizador(self):
da = self.cleaned_data['dispositivo_atualizador']
if da and not da.tipo_dispositivo.dispositivo_de_alteracao and\
not da.tipo_dispositivo.dispositivo_de_articulacao:
raise ValidationError(_('O Dispositivo de Atualização selecionado '
'não é um Bloco de Alteração.'))
return da
def clean(self):
data = self.cleaned_data
ndst = data['dispositivo_substituido']
nda = data['dispositivo_atualizador']
if not nda and ndst:
raise ValidationError(_('Não é permitido substituir um '
'Dispositivo sem haver um '
'Dispositivo Alterador.'))
def save(self):
data = self.cleaned_data
od = Dispositivo.objects.get(pk=self.instance.pk)
nd = self.instance
ndst = data['dispositivo_substituido']
ndsq = data['dispositivo_subsequente']
nda = data['dispositivo_atualizador']
if ndst != od.dispositivo_substituido:
if od.dispositivo_substituido:
odst = od.dispositivo_substituido
odst.dispositivo_subsequente = None
odst.fim_vigencia = None
odst.fim_eficacia = None
odst.save()
if ndst:
if ndst.dispositivo_subsequente:
ndst.dispositivo_subsequente.dispositivo_substituido = None
ndst.dispositivo_subsequente.save()
ndst.dispositivo_subsequente = nd
ndst.fim_vigencia = nd.inicio_vigencia - timedelta(days=1)
ndst.fim_eficacia = nd.inicio_eficacia - timedelta(days=1)
ndst.save()
if ndsq != od.dispositivo_subsequente:
if od.dispositivo_subsequente:
odsq = od.dispositivo_subsequente
odsq.dispositivo_substituido = None
odsq.save()
if ndsq:
if ndsq.dispositivo_substituido:
ndsq.dispositivo_substituido.dispositivo_subsequente = None
ndsq.dispositivo_substituido.fim_vigencia = None
ndsq.dispositivo_substituido.fim_eficacia = None
ndsq.dispositivo_substituido.save()
ndsq.dispositivo_substituido = nd
ndsq.save()
nd.ta_publicado = nda.ta if nda else None
super(DispositivoEdicaoAlteracaoForm, self).save()
if nd.dispositivo_subsequente:
nd.fim_vigencia = nd.dispositivo_subsequente.inicio_vigencia - \
timedelta(days=1)
nd.fim_eficacia = nd.dispositivo_subsequente.inicio_eficacia - \
timedelta(days=1)
nd.save()

21
compilacao/migrations/0048_auto_20160404_2309.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-04-05 02:09
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('compilacao', '0047_auto_20160330_0027'),
]
operations = [
migrations.AlterField(
model_name='dispositivo',
name='dispositivo_vigencia',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='dispositivos_vigencias_set', to='compilacao.Dispositivo', verbose_name='Dispositivo de Vigência'),
),
]

16
compilacao/migrations/0049_merge.py

@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-04-06 17:43
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('compilacao', '0045_auto_20160404_1411'),
('compilacao', '0048_auto_20160404_2309'),
]
operations = [
]

4
compilacao/models.py

@ -1,5 +1,3 @@
from builtins import zip
from datetime import datetime
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
@ -983,7 +981,7 @@ class Dispositivo(BaseModel, TimestampedMixin):
def get_parents(self, ordem='desc'): def get_parents(self, ordem='desc'):
dp = self dp = self
p = [] p = []
while dp.dispositivo_pai is not None: while dp.dispositivo_pai:
dp = dp.dispositivo_pai dp = dp.dispositivo_pai
if ordem == 'desc': if ordem == 'desc':
p.append(dp) p.append(dp)

92
compilacao/templatetags/compilacao_filters.py

@ -1,10 +1,11 @@
from django import template from django import template
from django.core.signing import Signer from django.core.signing import Signer
from django.db.models import Q from django.db.models import Q
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from compilacao.models import Dispositivo, TipoDispositivo from compilacao.models import Dispositivo
register = template.Library() register = template.Library()
@ -131,6 +132,92 @@ def nomenclatura(d):
return result return result
def update_dispositivos_parents(dpts_parents, ta_id):
dpts = Dispositivo.objects.order_by('ordem').filter(
ta_id=ta_id).values_list(
'pk', 'dispositivo_pai_id', 'rotulo', 'tipo_dispositivo__nome',
'tipo_dispositivo__rotulo_prefixo_texto')
for d in dpts:
dpts_parents[str(d[0])] = {
'd': d, 'p': [], 'h': None}
def parents(k):
pai = dpts_parents[str(k)]['d'][1]
p = dpts_parents[str(k)]['p']
if not p:
if pai:
parent_k = [pai, ] + parents(pai)
else:
parent_k = []
else:
parent_k = p
return parent_k
for k in dpts_parents:
dpts_parents[str(k)]['p'] = parents(k)
@register.simple_tag
def heranca(request, d, ignore_ultimo=0, ignore_primeiro=0):
ta_dpts_parents = request.session.get('herancas')
if not ta_dpts_parents:
ta_dpts_parents = {}
ta_id = str(d.ta_id)
if ta_id not in ta_dpts_parents:
dpts_parents = {}
ta_dpts_parents[ta_id] = dpts_parents
update_dispositivos_parents(dpts_parents, ta_id)
herancas_fila = request.session.get('herancas_fila')
if not herancas_fila:
herancas_fila = []
herancas_fila.append(ta_id)
if len(herancas_fila) > 100:
ta_remove = herancas_fila.pop(0)
del ta_dpts_parents[str(ta_remove)]
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:
return h
dpts_parents = ta_dpts_parents[ta_id]
parents = dpts_parents[d_pk]['p']
result = ''
if parents:
pk_last = parents[-1]
for pk in parents:
if ignore_ultimo and pk == pk_last:
break
if ignore_primeiro:
ignore_primeiro = 0
continue
p = dpts_parents[str(pk)]['d']
if p[4] != '':
result = p[2] + ' ' + result
else:
result = '(' + p[3] + ' ' + \
p[2] + ')' + ' ' + result
dpts_parents[d_pk]['h'] = result
return result
@register.simple_tag @register.simple_tag
def nomenclatura_heranca(d, ignore_ultimo=0, ignore_primeiro=0): def nomenclatura_heranca(d, ignore_ultimo=0, ignore_primeiro=0):
result = '' result = ''
@ -159,7 +246,8 @@ def nomenclatura_heranca(d, ignore_ultimo=0, ignore_primeiro=0):
@register.filter @register.filter
def urldetail_content_type(obj): def urldetail_content_type(obj):
return '%s:detail' % obj.content_type.model return '%s:%s_detail' % (
obj.content_type.app_label, obj.content_type.model)
@register.filter @register.filter

6
compilacao/urls.py

@ -40,6 +40,10 @@ urlpatterns_compilacao = [
views.DispositivoEdicaoVigenciaView.as_view(), views.DispositivoEdicaoVigenciaView.as_view(),
name='dispositivo_edit_vigencia'), name='dispositivo_edit_vigencia'),
url(r'^(?P<ta_id>[0-9]+)/text/(?P<pk>[0-9]+)/edit/alteracao',
views.DispositivoEdicaoAlteracaoView.as_view(),
name='dispositivo_edit_alteracao'),
url(r'^(?P<ta_id>[0-9]+)/text/(?P<pk>[0-9]+)/edit/definidor_vigencia', url(r'^(?P<ta_id>[0-9]+)/text/(?P<pk>[0-9]+)/edit/definidor_vigencia',
views.DispositivoDefinidorVigenciaView.as_view(), views.DispositivoDefinidorVigenciaView.as_view(),
name='dispositivo_edit_definidor_vigencia'), name='dispositivo_edit_definidor_vigencia'),
@ -107,7 +111,7 @@ urlpatterns_compilacao = [
] ]
urlpatterns = [ urlpatterns = [
url(r'^ta/', include(urlpatterns_compilacao, 'compilacao', 'compilacao')), url(r'^ta/', include(urlpatterns_compilacao)),
url(r'^ta/config/tipo-nota/', url(r'^ta/config/tipo-nota/',
include(TipoNotaCrud.get_urls())), include(TipoNotaCrud.get_urls())),

312
compilacao/views.py

@ -1,6 +1,6 @@
import sys
from collections import OrderedDict from collections import OrderedDict
from datetime import datetime, timedelta from datetime import datetime, timedelta
import sys
from braces.views import FormMessagesMixin from braces.views import FormMessagesMixin
from django import forms from django import forms
@ -10,7 +10,6 @@ from django.core.signing import Signer
from django.core.urlresolvers import reverse_lazy from django.core.urlresolvers import reverse_lazy
from django.db import transaction from django.db import transaction
from django.db.models import Q from django.db.models import Q
from django.forms.models import model_to_dict
from django.http.response import (HttpResponse, HttpResponseRedirect, from django.http.response import (HttpResponse, HttpResponseRedirect,
JsonResponse) JsonResponse)
from django.shortcuts import get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
@ -19,15 +18,16 @@ from django.utils.decorators import method_decorator
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
from django.views.generic.detail import DetailView from django.views.generic.detail import DetailView
from django.views.generic.edit import CreateView, DeleteView, UpdateView,\ from django.views.generic.edit import (CreateView, DeleteView, FormView,
FormView UpdateView)
from django.views.generic.list import ListView from django.views.generic.list import ListView
from compilacao.forms import (DispositivoEdicaoBasicaForm, NotaForm, from compilacao.forms import (DispositivoDefinidorVigenciaForm,
PublicacaoForm, TaForm, TipoTaForm, VideForm, DispositivoEdicaoAlteracaoForm,
DispositivoEdicaoBasicaForm,
DispositivoEdicaoVigenciaForm, DispositivoEdicaoVigenciaForm,
DispositivoSearchModalForm, DispositivoSearchModalForm, NotaForm,
DispositivoDefinidorVigenciaForm) PublicacaoForm, TaForm, TipoTaForm, VideForm)
from compilacao.models import (Dispositivo, Nota, from compilacao.models import (Dispositivo, Nota,
PerfilEstruturalTextoArticulado, Publicacao, PerfilEstruturalTextoArticulado, Publicacao,
TextoArticulado, TipoDispositivo, TipoNota, TextoArticulado, TipoDispositivo, TipoNota,
@ -36,7 +36,6 @@ from compilacao.models import (Dispositivo, Nota,
from compilacao.utils import DISPOSITIVO_SELECT_RELATED from compilacao.utils import DISPOSITIVO_SELECT_RELATED
from crud.base import Crud, CrudListView, make_pagination from crud.base import Crud, CrudListView, make_pagination
TipoNotaCrud = Crud.build(TipoNota, 'tipo_nota') TipoNotaCrud = Crud.build(TipoNota, 'tipo_nota')
TipoVideCrud = Crud.build(TipoVide, 'tipo_vide') TipoVideCrud = Crud.build(TipoVide, 'tipo_vide')
TipoPublicacaoCrud = Crud.build(TipoPublicacao, 'tipo_publicacao') TipoPublicacaoCrud = Crud.build(TipoPublicacao, 'tipo_publicacao')
@ -1283,13 +1282,13 @@ class ActionsEditMixin:
dps = Dispositivo.objects.filter(dispositivo_vigencia_id=dvt.pk, dps = Dispositivo.objects.filter(dispositivo_vigencia_id=dvt.pk,
ta_publicado_id=dvt.ta_id) ta_publicado_id=dvt.ta_id)
with transaction.atomic():
for d in dps: for d in dps:
if d.dispositivo_substituido: if d.dispositivo_substituido:
ds = d.dispositivo_substituido ds = d.dispositivo_substituido
ds.fim_vigencia = d.inicio_vigencia - timedelta(days=1) ds.fim_vigencia = d.inicio_vigencia - timedelta(days=1)
ds.fim_eficacia = d.inicio_eficacia - timedelta(days=1) ds.fim_eficacia = d.inicio_eficacia - timedelta(days=1)
ds.save() d.save()
if d.dispositivo_subsequente: if d.dispositivo_subsequente:
ds = d.dispositivo_subsequente ds = d.dispositivo_subsequente
@ -1616,72 +1615,6 @@ class ActionsEditMixin:
return '' return ''
"""
if proxima_articulacao:
irmaos_posteriores = Dispositivo.objects.filter(
ta_id=base.ta_id,
ordem__gt=base.ordem,
tipo_dispositivo=base.tipo_dispositivo,
ordem__lt=proxima_articulacao.ordem)
else:
irmaos_posteriores = Dispositivo.objects.filter(
ta_id=base.ta_id,
ordem__gt=base.ordem,
tipo_dispositivo=base.tipo_dispositivo)
proxima_articulacao = base.get_proximo_nivel_zero()
# Renumerar Dispostivos de Contagem Contínua de dentro da base
if not proxima_articulacao:
dcc = Dispositivo.objects.order_by('ordem').filter(
ta_id=base.ta_id,
ordem__gt=base.ordem,
tipo_dispositivo__contagem_continua=True)
else:
dcc = Dispositivo.objects.order_by('ordem').filter(
ta_id=base.ta_id,
ordem__gt=base.ordem,
ordem__lt=proxima_articulacao.ordem,
tipo_dispositivo__contagem_continua=True)
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()
return ''
"""
def add_prior(self, context): def add_prior(self, context):
return {} return {}
@ -1694,6 +1627,9 @@ class ActionsEditMixin:
dp_auto_insert = None dp_auto_insert = None
base = Dispositivo.objects.get(pk=context['dispositivo_id']) base = Dispositivo.objects.get(pk=context['dispositivo_id'])
tipo = TipoDispositivo.objects.get(pk=context['tipo_pk']) tipo = TipoDispositivo.objects.get(pk=context['tipo_pk'])
pub_last = Publicacao.objects.order_by(
'data', 'hora').filter(ta=base.ta).last()
variacao = int(context['variacao']) variacao = int(context['variacao'])
parents = [base, ] + base.get_parents() parents = [base, ] + base.get_parents()
@ -1791,6 +1727,7 @@ class ActionsEditMixin:
dp.ordem = ordem dp.ordem = ordem
dp.incrementar_irmaos(variacao, [local_add, ], force=False) dp.incrementar_irmaos(variacao, [local_add, ], force=False)
dp.publicacao = pub_last
dp.save() dp.save()
# Inserção automática # Inserção automática
@ -1808,6 +1745,8 @@ class ActionsEditMixin:
dp.rotulo = dp.rotulo_padrao() dp.rotulo = dp.rotulo_padrao()
dp.texto = '' dp.texto = ''
dp.ordem = dp.ordem + Dispositivo.INTERVALO_ORDEM dp.ordem = dp.ordem + Dispositivo.INTERVALO_ORDEM
dp.publicacao = pub_last
dp.save() dp.save()
dp_auto_insert = dp dp_auto_insert = dp
dp = Dispositivo.objects.get(pk=dp_pk) dp = Dispositivo.objects.get(pk=dp_pk)
@ -1841,7 +1780,6 @@ class ActionsEditMixin:
continue continue
filho.dispositivo_pai = dp filho.dispositivo_pai = dp
filho.clean()
filho.save() filho.save()
flag_niveis = True flag_niveis = True
@ -1982,79 +1920,11 @@ class ActionsEditView(ActionsEditMixin, TemplateView):
if 'perfil_estrutural' in self.request.session: if 'perfil_estrutural' in self.request.session:
context['perfil_pk'] = self.request.session['perfil_estrutural'] context['perfil_pk'] = self.request.session['perfil_estrutural']
return self.render_to_json_response(context, **response_kwargs) if 'herancas' in self.request.session:
del self.request.session['herancas']
del self.request.session['herancas_fila']
class DispositivoEdicaoBasicaView(FormMessagesMixin, UpdateView):
model = Dispositivo
template_name = 'compilacao/dispositivo_form_edicao_basica.html'
form_class = DispositivoEdicaoBasicaForm
form_valid_message = _('Alterações no Dispositivo realizadas com sucesso!')
form_invalid_message = _('Houve erro em registrar '
'as alterações no Dispositivo')
@property
def cancel_url(self):
return reverse_lazy(
'compilacao:ta_text_edit',
kwargs={'ta_id': self.kwargs['ta_id']}) + '#' + str(self.object.pk)
def get_success_url(self):
return reverse_lazy(
'compilacao:dispositivo_edit',
kwargs={'ta_id': self.kwargs['ta_id'], 'pk': self.kwargs['pk']})
def get_url_this_view(self):
return 'compilacao:dispositivo_edit'
def run_actions(self, request):
if 'action' in request.GET and\
request.GET['action'] == 'atualiza_rotulo':
try:
d = Dispositivo.objects.get(pk=self.kwargs['pk'])
d.dispositivo0 = int(request.GET['dispositivo0'])
d.dispositivo1 = int(request.GET['dispositivo1'])
d.dispositivo2 = int(request.GET['dispositivo2'])
d.dispositivo3 = int(request.GET['dispositivo3'])
d.dispositivo4 = int(request.GET['dispositivo4'])
d.dispositivo5 = int(request.GET['dispositivo5'])
d.rotulo = d.rotulo_padrao()
numero = d.get_numero_completo()[1:]
zerar = False
for i in range(len(numero)):
if not numero[i]:
zerar = True
if zerar:
numero[i] = 0
if zerar:
d.set_numero_completo([d.dispositivo0, ] + numero)
d.rotulo = d.rotulo_padrao()
except:
return True, JsonResponse({'message': str(
_('Ocorreu erro na atualização do rótulo'))}, safe=False)
return True, JsonResponse({
'rotulo': d.rotulo,
'dispositivo0': d.dispositivo0,
'dispositivo1': d.dispositivo1,
'dispositivo2': d.dispositivo2,
'dispositivo3': d.dispositivo3,
'dispositivo4': d.dispositivo4,
'dispositivo5': d.dispositivo5}, safe=False)
return False, '' return self.render_to_json_response(context, **response_kwargs)
def get(self, request, *args, **kwargs):
flag_action, render_json_response = self.run_actions(request)
if flag_action:
return render_json_response
return UpdateView.get(self, request, *args, **kwargs)
class DispositivoSearchFragmentFormView(ListView): class DispositivoSearchFragmentFormView(ListView):
@ -2078,7 +1948,10 @@ class DispositivoSearchFragmentFormView(ListView):
def get_queryset(self): def get_queryset(self):
try: try:
n = 50 n = 10
if 'max_results' in self.request.GET:
n = int(self.request.GET['max_results'])
q = Q() q = Q()
if 'initial_ref' in self.request.GET: if 'initial_ref' in self.request.GET:
initial_ref = self.request.GET['initial_ref'] initial_ref = self.request.GET['initial_ref']
@ -2132,7 +2005,7 @@ class DispositivoSearchFragmentFormView(ListView):
if ano_ta: if ano_ta:
q = q & Q(ta__ano=ano_ta) q = q & Q(ta__ano=ano_ta)
if not q.children: if not q.children and not n:
n = 10 n = 10
q = q & Q(nivel__gt=0) q = q & Q(nivel__gt=0)
@ -2141,16 +2014,35 @@ class DispositivoSearchFragmentFormView(ListView):
'-ta__ano', '-ta__ano',
'-ta__numero', '-ta__numero',
'ta', 'ta',
'ordem').filter(q).select_related('ta').exclude( 'ordem').filter(q).select_related('ta')
if 'data_type_selection' in self.request.GET and\
self.request.GET['data_type_selection'] == 'checkbox':
result = result.exclude(
tipo_dispositivo__dispositivo_de_alteracao=True) tipo_dispositivo__dispositivo_de_alteracao=True)
else:
if 'data_function' in self.request.GET and\
self.request.GET['data_function'] == 'alterador':
result = result.exclude(
tipo_dispositivo__dispositivo_de_alteracao=False,
)
result = result.exclude(
tipo_dispositivo__dispositivo_de_articulacao=False,
)
print(str(result.query))
def resultados(r): def resultados(r):
if num_ta and ano_ta and not rotulo and not str_texto and\ if n:
return r[:n]
else:
return r
"""if num_ta and ano_ta and not rotulo and not str_texto and\
'data_type_selection' in self.request.GET and\ 'data_type_selection' in self.request.GET and\
self.request.GET['data_type_selection'] == 'checkbox': self.request.GET['data_type_selection'] == 'checkbox':
return r return r
else: else:
return r[:n] return r[:n]"""
if 'tipo_model' not in self.request.GET: if 'tipo_model' not in self.request.GET:
return resultados(result) return resultados(result)
@ -2214,6 +2106,78 @@ class DispositivoSearchModalView(FormView):
form_class = DispositivoSearchModalForm form_class = DispositivoSearchModalForm
class DispositivoEdicaoBasicaView(FormMessagesMixin, UpdateView):
model = Dispositivo
template_name = 'compilacao/dispositivo_form_edicao_basica.html'
form_class = DispositivoEdicaoBasicaForm
form_valid_message = _('Alterações no Dispositivo realizadas com sucesso!')
form_invalid_message = _('Houve erro em registrar '
'as alterações no Dispositivo')
@property
def cancel_url(self):
return reverse_lazy(
'compilacao:ta_text_edit',
kwargs={'ta_id': self.kwargs['ta_id']}) + '#' + str(self.object.pk)
def get_success_url(self):
return reverse_lazy(
'compilacao:dispositivo_edit',
kwargs={'ta_id': self.kwargs['ta_id'], 'pk': self.kwargs['pk']})
def get_url_this_view(self):
return 'compilacao:dispositivo_edit'
def run_actions(self, request):
if 'action' in request.GET and\
request.GET['action'] == 'atualiza_rotulo':
try:
d = Dispositivo.objects.get(pk=self.kwargs['pk'])
d.dispositivo0 = int(request.GET['dispositivo0'])
d.dispositivo1 = int(request.GET['dispositivo1'])
d.dispositivo2 = int(request.GET['dispositivo2'])
d.dispositivo3 = int(request.GET['dispositivo3'])
d.dispositivo4 = int(request.GET['dispositivo4'])
d.dispositivo5 = int(request.GET['dispositivo5'])
d.rotulo = d.rotulo_padrao()
numero = d.get_numero_completo()[1:]
zerar = False
for i in range(len(numero)):
if not numero[i]:
zerar = True
if zerar:
numero[i] = 0
if zerar:
d.set_numero_completo([d.dispositivo0, ] + numero)
d.rotulo = d.rotulo_padrao()
except:
return True, JsonResponse({'message': str(
_('Ocorreu erro na atualização do rótulo'))}, safe=False)
return True, JsonResponse({
'rotulo': d.rotulo,
'dispositivo0': d.dispositivo0,
'dispositivo1': d.dispositivo1,
'dispositivo2': d.dispositivo2,
'dispositivo3': d.dispositivo3,
'dispositivo4': d.dispositivo4,
'dispositivo5': d.dispositivo5}, safe=False)
return False, ''
def get(self, request, *args, **kwargs):
flag_action, render_json_response = self.run_actions(request)
if flag_action:
return render_json_response
return UpdateView.get(self, request, *args, **kwargs)
class DispositivoEdicaoVigenciaView(FormMessagesMixin, UpdateView): class DispositivoEdicaoVigenciaView(FormMessagesMixin, UpdateView):
model = Dispositivo model = Dispositivo
template_name = 'compilacao/dispositivo_form_vigencia.html' template_name = 'compilacao/dispositivo_form_vigencia.html'
@ -2281,12 +2245,50 @@ class DispositivoDefinidorVigenciaView(FormMessagesMixin, FormView):
form = self.get_form() form = self.get_form()
if form.is_valid(): if form.is_valid():
dvs = form.cleaned_data['dispositivo_vigencia'] dvs = form.cleaned_data['dispositivo_vigencia']
try:
with transaction.atomic(): with transaction.atomic():
self.object.dispositivos_vigencias_set.clear() self.object.dispositivos_vigencias_set.clear()
for item in dvs: for item in dvs:
d = Dispositivo.objects.get(pk=item) d = Dispositivo.objects.get(pk=item)
self.object.dispositivos_vigencias_set.add(d) self.object.dispositivos_vigencias_set.add(d)
return self.form_valid(form)
except:
return self.form_invalid(form)
else:
return self.form_invalid(form)
class DispositivoEdicaoAlteracaoView(FormMessagesMixin, UpdateView):
model = Dispositivo
template_name = 'compilacao/dispositivo_form_alteracao.html'
form_class = DispositivoEdicaoAlteracaoForm
form_valid_message = _('Alterações no Dispositivo realizadas com sucesso!')
form_invalid_message = _('Houve erro em registrar '
'as alterações no Dispositivo')
@property
def cancel_url(self):
return reverse_lazy(
'compilacao:ta_text_edit',
kwargs={'ta_id': self.kwargs['ta_id']}) + '#' + str(self.object.pk)
def get_url_this_view(self):
return 'compilacao:dispositivo_edit_alteracao'
def get_success_url(self):
return reverse_lazy(
'compilacao:dispositivo_edit_alteracao',
kwargs={'ta_id': self.kwargs['ta_id'], 'pk': self.kwargs['pk']})
def post(self, request, *args, **kwargs):
self.object = get_object_or_404(Dispositivo, pk=kwargs['pk'])
form = self.get_form()
if form.is_valid():
try:
with transaction.atomic():
return self.form_valid(form) return self.form_valid(form)
except:
return self.form_invalid(form)
else: else:
return self.form_invalid(form) return self.form_invalid(form)

2
crispy_layout_mixin.py

@ -1,11 +1,11 @@
from math import ceil from math import ceil
from os.path import dirname, join from os.path import dirname, join
import rtyaml
from crispy_forms.bootstrap import FormActions from crispy_forms.bootstrap import FormActions
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Div, Fieldset, Layout, Submit from crispy_forms.layout import HTML, Div, Fieldset, Layout, Submit
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
import rtyaml
def heads_and_tails(list_of_lists): def heads_and_tails(list_of_lists):

2
norma/urls.py

@ -19,7 +19,7 @@ app_name = AppConfig.name
# url(r'^norma/(?P<pk>[0-9]+)/ta$', NormaTaView.as_view(), name='ta') # url(r'^norma/(?P<pk>[0-9]+)/ta$', NormaTaView.as_view(), name='ta')
# bem como a classe NormaTaView que está em norma.views # bem como a classe NormaTaView que está em norma.views
norma_url_patterns = NormaTemporarioCrud.get_urls() + [ norma_url_patterns = NormaTemporarioCrud.get_urls() + [
url(r'^norma/(?P<pk>[0-9]+)/ta$', url(r'^(?P<pk>[0-9]+)/ta$',
NormaTaView.as_view(), name='ta') NormaTaView.as_view(), name='ta')
] ]

19
static/js/app.js

@ -1,7 +1,6 @@
function initTinymce() { function initTinymce(elements) {
removeTinymce(); removeTinymce();
tinymce.init({ var config_tinymce = {
mode : "textareas",
force_br_newlines : false, force_br_newlines : false,
force_p_newlines : false, force_p_newlines : false,
forced_root_block : '', forced_root_block : '',
@ -10,8 +9,16 @@ function initTinymce() {
toolbar: "undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent", toolbar: "undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent",
tools: "inserttable", tools: "inserttable",
border_css: "/static/styles/style_tinymce.css", border_css: "/static/styles/style_tinymce.css",
content_css: "/static/styles/style_tinymce.css" content_css: "/static/styles/style_tinymce.css",
}); }
if (elements != null) {
config_tinymce['elements'] = elements;
config_tinymce['mode'] = "exact";
}
else
config_tinymce['mode'] = "textareas";
tinymce.init(config_tinymce);
} }
function removeTinymce() { function removeTinymce() {
@ -112,5 +119,5 @@ $(document).ready(function(){
refreshDatePicker(); refreshDatePicker();
refreshMask(); refreshMask();
autorModal(); autorModal();
initTinymce(); initTinymce("biografia-parlamentar,casa-informacoes");
}); });

4
static/js/compilacao.js

@ -39,6 +39,7 @@ function DispostivoSearch(opts) {
var field = $(this); var field = $(this);
var data_type_selection = field.attr('data-type-selection'); var data_type_selection = field.attr('data-type-selection');
var data_field = field.attr('data-field'); var data_field = field.attr('data-field');
var data_function = field.attr('data-function');
var onChangeFieldSelects = function(event) { var onChangeFieldSelects = function(event) {
if (data_type_selection == 'checkbox') { if (data_type_selection == 'checkbox') {
@ -77,6 +78,7 @@ function DispostivoSearch(opts) {
var dispositivos_internos = $("input[name='dispositivos_internos']:checked").val(); var dispositivos_internos = $("input[name='dispositivos_internos']:checked").val();
var rotulo_dispositivo = $("input[name='rotulo_dispositivo']").val(); var rotulo_dispositivo = $("input[name='rotulo_dispositivo']").val();
var texto_dispositivo = $("input[name='texto_dispositivo']").val(); var texto_dispositivo = $("input[name='texto_dispositivo']").val();
var max_results = $("select[name='max_results']").val();
var url = ''; var url = '';
if (rotulo_dispositivo.length > 0 || texto_dispositivo.length > 0) { if (rotulo_dispositivo.length > 0 || texto_dispositivo.length > 0) {
@ -97,8 +99,10 @@ function DispostivoSearch(opts) {
'texto' : texto_dispositivo, 'texto' : texto_dispositivo,
'rotulo' : rotulo_dispositivo, 'rotulo' : rotulo_dispositivo,
'dispositivos_internos' : dispositivos_internos, 'dispositivos_internos' : dispositivos_internos,
'max_results' : max_results,
'data_type_selection' : data_type_selection, 'data_type_selection' : data_type_selection,
'data_field' : data_field, 'data_field' : data_field,
'data_function' : data_function,
}; };
url = '/ta/search_fragment_form'; url = '/ta/search_fragment_form';

11
templates/compilacao/dispositivo_form.html

@ -8,12 +8,13 @@
<ul class="nav nav-pills navbar-right"> <ul class="nav nav-pills navbar-right">
{% url 'compilacao:dispositivo_edit' object.ta_id object.pk as edit_url%} {% url 'compilacao:dispositivo_edit' object.ta_id object.pk as edit_url%}
{% url 'compilacao:dispositivo_edit_vigencia' object.ta_id object.pk as edit_vigencia_url %} {% url 'compilacao:dispositivo_edit_vigencia' object.ta_id object.pk as edit_vigencia_url %}
{% url 'compilacao:dispositivo_edit_alteracao' object.ta_id object.pk as edit_alteracao_url %}
{% url 'compilacao:dispositivo_edit_definidor_vigencia' object.ta_id object.pk as edit_definidor_vigencia_url %} {% url 'compilacao:dispositivo_edit_definidor_vigencia' object.ta_id object.pk as edit_definidor_vigencia_url %}
<li {% if request.get_full_path == edit_url %}class="active"{%endif%}><a href="{{ edit_url }}">{% trans 'Dados Básicos' %}</a></li> <li {% if request.get_full_path == edit_url %}class="active"{%endif%}><a class="btn-warning" href="{{ edit_url }}">{% trans 'Dados Básicos' %}</a></li>
<li {% if request.get_full_path == edit_vigencia_url %}class="active"{%endif%}><a href="{{ edit_vigencia_url }}" >{% trans 'Vigência' %}</a></li> <li {% if request.get_full_path == edit_vigencia_url %}class="active"{%endif%}><a class="btn-warning" href="{{ edit_vigencia_url }}" >{% trans 'Vigência' %}</a></li>
<li><a href="#">{% trans 'Alteração' %}</a></li> <li {% if request.get_full_path == edit_definidor_vigencia_url %}class="active"{%endif%}><a class="btn-danger" href="{{ edit_definidor_vigencia_url }}" >{% trans 'Definidor de Vigência' %}</a></li>
<li><a href="#">{% trans 'Alterador' %}</a></li> <li {% if request.get_full_path == edit_alteracao_url %}class="active"{%endif%}><a class="btn-danger" href="{{ edit_alteracao_url }}" >{% trans 'Alteração' %}</a></li>
<li {% if request.get_full_path == edit_definidor_vigencia_url %}class="active"{%endif%}><a href="{{ edit_definidor_vigencia_url }}" >{% trans 'Definidor de Vigência' %}</a></li> <li><a href="#" class="btn-danger">{% trans 'Alterador' %}</a></li>
</ul> </ul>
{% endblock sections_nav %}{% trans '' %} {% endblock sections_nav %}{% trans '' %}

12
templates/compilacao/dispositivo_form_alteracao.html

@ -0,0 +1,12 @@
{% extends "compilacao/dispositivo_form.html" %}
{% load i18n %}
{% block extra_js %}{{block.super}}
<script type="text/javascript">
DispostivoSearch({
'url_form': '{% url 'compilacao:dispositivo_search_form'%}',
'text_button': '{% trans 'Definir Dispositivo'%}'
});
initTinymce();
</script>
{% endblock %}

2
templates/compilacao/dispositivo_form_definidor_vigencia.html

@ -5,7 +5,7 @@
<script type="text/javascript"> <script type="text/javascript">
DispostivoSearch({ DispostivoSearch({
'url_form': '{% url 'compilacao:dispositivo_search_form'%}', 'url_form': '{% url 'compilacao:dispositivo_search_form'%}',
'text_button': '{% trans 'Adicionar Novos Dispositivos que não apareceram previamente na lista'%}' 'text_button': '{% trans 'Adicionar Dispositivos'%}'
}); });
</script> </script>
{% endblock %} {% endblock %}

8
templates/compilacao/dispositivo_form_edicao_basica.html

@ -31,12 +31,6 @@
}); });
} }
$(document).ready(function() { initTinymce();
{% if object.tipo_dispositivo.dispositivo_de_articulacao %}
setTimeout(removeTinymce, 100);
{% endif %}
});
</script> </script>
{% endblock %} {% endblock %}

33
templates/compilacao/dispositivo_form_search_fragment.html

@ -24,22 +24,22 @@
{% endif %} {% endif %}
{% endifchanged %} {% endifchanged %}
{% if 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.is_relative_auto_insert and dpt.dispositivo_pai not in object_list %}
<li> <li>
<div class="iteminput"> <div class="iteminput">
<input type="{{request.GET.data_type_selection}}" name="{{request.GET.data_field}}" id="dpt{{dpt.pk}}" value="{{dpt.pk}}"/> <input type="{{request.GET.data_type_selection}}" name="{{request.GET.data_field}}" id="dpt{{dpt.pk}}" value="{{dpt.pk}}"/>
</div> </div>
<div class="itemlabel dpt"> <div class="itemlabel dpt">
{% if dpt.dispositivo_pai.nivel > 1 %} {% if dpt.dispositivo_pai.nivel > 1 %}
<a target="_blank" href="{% url 'compilacao:ta_text' dpt.dispositivo_pai.ta.pk%}#{{dpt.dispositivo_pai.pk}}" class="nomenclatura_heranca">{% trans "Herança:" %} {% nomenclatura_heranca dpt 1 1 %}</a> <a class="clearfix" target="_blank" href="{% url 'compilacao:ta_text' dpt.dispositivo_pai.ta.pk%}#{{dpt.dispositivo_pai.pk}}" class="nomenclatura_heranca">{% trans "Herança:" %} {% heranca request dpt 1 0 %}</a>
{% endif %} {% endif %}
<div class="{{ dpt.dispositivo_pai.tipo_dispositivo.class_css }}"> <div class="{{ dpt.dispositivo_pai.tipo_dispositivo.class_css }}">
<div class="dptt {% dispositivo_desativado dpt.dispositivo_pai view.inicio_vigencia view.fim_vigencia %}" id="dptt{{dpt.dispositivo_pai.pk}}" > <div class="dptt {% dispositivo_desativado dpt.dispositivo_pai None None %}" id="dptt{{dpt.dispositivo_pai.pk}}" >
{{ dpt.dispositivo_pai.tipo_dispositivo.rotulo_prefixo_html|safe }} {{ dpt.dispositivo_pai.tipo_dispositivo.rotulo_prefixo_html|safe }}
{{ dpt.dispositivo_pai.rotulo }} {{ dpt.dispositivo_pai.rotulo }}
{{ dpt.dispositivo_pai.tipo_dispositivo.rotulo_sufixo_html|safe }} {{ dpt.dispositivo_pai.tipo_dispositivo.rotulo_sufixo_html|safe }}
<span class="dtxt" id="d{% if not dpt.dispositivo_pai.dispositivo_subsequente_id and dpt.dispositivo_pai.dispositivo_substituido_id %}a{% endif %}{{dpt.dispositivo_pai.pk}}" pks="{{dpt.dispositivo_pai.dispositivo_substituido_id|default:''}}" pk="{{dpt.dispositivo_pai.pk}}">{{ 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 %}&nbsp;{% endif %}{% endif %}</span> <span class="dtxt" id="d{% if not dpt.dispositivo_pai.dispositivo_subsequente_id and dpt.dispositivo_pai.dispositivo_substituido_id %}a{% endif %}{{dpt.dispositivo_pai.pk}}" pks="{{dpt.dispositivo_pai.dispositivo_substituido_id|default:''}}" pk="{{dpt.dispositivo_pai.pk}}">{{ 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 %}&nbsp;{% endif %}{% endif %}</span>
{% if dpt.dispositivo_pai.ta_publicado_id and not dpt.dispositivo_pai.tipo_dispositivo.dispositivo_de_articulacao %} {% if dpt.dispositivo_pai.ta_publicado_id %}
<a class="link_alterador" href="{%url 'compilacao:ta_text' dpt.dispositivo_pai.ta_publicado.pk %}#{{dpt.dispositivo_pai.dispositivo_atualizador_id}}"> <a class="link_alterador" href="{%url 'compilacao:ta_text' dpt.dispositivo_pai.ta_publicado.pk %}#{{dpt.dispositivo_pai.dispositivo_atualizador_id}}">
{{ dpt.dispositivo_pai.tipo_dispositivo.nota_automatica_prefixo_html|safe }} {{ dpt.dispositivo_pai.tipo_dispositivo.nota_automatica_prefixo_html|safe }}
{% nota_automatica dpt.dispositivo_pai ta_pub_list %} {% nota_automatica dpt.dispositivo_pai ta_pub_list %}
@ -48,6 +48,7 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div> </div>
</li> </li>
{% endif %} {% endif %}
@ -58,22 +59,32 @@
</div> </div>
<div class="itemlabel dpt"> <div class="itemlabel dpt">
{% if dpt.nivel > 1 %} {% if dpt.nivel > 1 %}
<a target="_blank" href="{% url 'compilacao:ta_text' dpt.ta.pk%}#{{dpt.pk}}" class="nomenclatura_heranca">{% trans "Herança:" %} {% nomenclatura_heranca dpt 1 1 %}</a> <a class="clearfix" target="_blank" href="{% url 'compilacao:ta_text' dpt.ta.pk%}#{{dpt.pk}}" class="nomenclatura_heranca">{% trans "Herança:" %} {% heranca request dpt 1 0 %}</a>
{% endif %} {% endif %}
<div class="{{ dpt.tipo_dispositivo.class_css }}"> <div class="{{ dpt.tipo_dispositivo.class_css }}">
<div class="dptt {% dispositivo_desativado dpt view.inicio_vigencia view.fim_vigencia %}" id="dptt{{dpt.pk}}" > <div class="dptt {% dispositivo_desativado dpt None None %}" id="dptt{{dpt.pk}}" >
{{ dpt.tipo_dispositivo.rotulo_prefixo_html|safe }} {{ dpt.tipo_dispositivo.rotulo_prefixo_html|safe }}
{% if dpt.rotulo or dpt.nivel = 1 %}{{ dpt.rotulo }}{%else%}[{{ dpt|nomenclatura}} {% trans "de" %} {{ dpt.dispositivo_pai.rotulo }}] - {% endif %} {% if dpt.rotulo or dpt.nivel = 1 %}{{ dpt.rotulo }}{%else%}[{{ dpt|nomenclatura}} {% trans "de" %} {{ dpt.dispositivo_pai.rotulo }}] - {% endif %}
{{ dpt.tipo_dispositivo.rotulo_sufixo_html|safe }} {{ dpt.tipo_dispositivo.rotulo_sufixo_html|safe }}
<span class="dtxt" 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 %}&nbsp;{% endif %}{% endif %}</span>
{% if dpt.ta_publicado_id and not dpt.tipo_dispositivo.dispositivo_de_articulacao %} <span class="dtxt"
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 %}&nbsp;{% endif %}{% endif %}</span>
{% if dpt.ta_publicado_id %}
<a class="link_alterador" href="{%url 'compilacao:ta_text' dpt.ta_publicado.pk %}#{{dpt.dispositivo_atualizador_id}}"> <a class="link_alterador" href="{%url 'compilacao:ta_text' dpt.ta_publicado.pk %}#{{dpt.dispositivo_atualizador_id}}">
{{ dpt.tipo_dispositivo.nota_automatica_prefixo_html|safe }} {{ dpt.tipo_dispositivo.nota_automatica_prefixo_html|safe }}
{% nota_automatica dpt ta_pub_list %} {% nota_automatica dpt ta_pub_list %}
{{ dpt.tipo_dispositivo.nota_automatica_sufixo_html|safe }} {{ dpt.tipo_dispositivo.nota_automatica_sufixo_html|safe }}
</a> </a>
{% endif %} {% endif %}
</div> </div>
{% if dpt.tipo_dispositivo.dispositivo_de_alteracao%}
{%with node=dpt template_name='compilacao/text_list_blocoalteracao.html' %}
{%include template_name%}
{%endwith%}
{% endif%}
</div> </div>
</div> </div>
</li> </li>
@ -87,16 +98,16 @@
</div> </div>
<div class="itemlabel dpt"> <div class="itemlabel dpt">
{% if df.nivel > 1 %} {% if df.nivel > 1 %}
<a target="_blank" href="{% url 'compilacao:ta_text' df.ta.pk%}#{{df.pk}}" class="nomenclatura_heranca">{% trans "Herança:" %} {% nomenclatura_heranca df 1 1 %}</a> <a class="clearfix" target="_blank" href="{% url 'compilacao:ta_text' df.ta.pk%}#{{df.pk}}" class="nomenclatura_heranca">{% trans "Herança:" %} {% heranca request df 1 0 %}</a>
{% endif %} {% endif %}
<div class="{{ df.tipo_dispositivo.class_css }}"> <div class="{{ df.tipo_dispositivo.class_css }}">
<div class="dptt {% dispositivo_desativado dpt view.inicio_vigencia view.fim_vigencia %}" id="dptt{{df.pk}}" > <div class="dptt {% dispositivo_desativado dpt None None %}" id="dptt{{df.pk}}" >
{{ df.tipo_dispositivo.rotulo_prefixo_html|safe }} {{ df.tipo_dispositivo.rotulo_prefixo_html|safe }}
<a name="{{df.pk}}" title="{{df.pk}}">{% if df.rotulo or df.nivel = 1%}{{ df.rotulo }}{%else%}[{{ df|nomenclatura}} {% trans "de" %} {{ df.dispositivo_pai.rotulo }}] - {% endif %}</a> <a name="{{df.pk}}" title="{{df.pk}}">{% if df.rotulo or df.nivel = 1%}{{ df.rotulo }}{%else%}[{{ df|nomenclatura}} {% trans "de" %} {{ df.dispositivo_pai.rotulo }}] - {% endif %}</a>
{{ df.tipo_dispositivo.rotulo_sufixo_html|safe }} {{ df.tipo_dispositivo.rotulo_sufixo_html|safe }}
<span class="dtxt" id="d{% if not df.dispositivo_subsequente_id and df.dispositivo_substituido_id %}a{% endif %}{{df.pk}}" pks="{{df.dispositivo_substituido_id|default:''}}" pk="{{df.pk}}">{{ df.tipo_dispositivo.texto_prefixo_html|safe }}{%if df.texto %}{{ df.texto|safe }}{%else%}{%if not df.tipo_dispositivo.dispositivo_de_articulacao %}&nbsp;{% endif %}{% endif %}</span> <span class="dtxt" id="d{% if not df.dispositivo_subsequente_id and df.dispositivo_substituido_id %}a{% endif %}{{df.pk}}" pks="{{df.dispositivo_substituido_id|default:''}}" pk="{{df.pk}}">{{ df.tipo_dispositivo.texto_prefixo_html|safe }}{%if df.texto %}{{ df.texto|safe }}{%else%}{%if not df.tipo_dispositivo.dispositivo_de_articulacao %}&nbsp;{% endif %}{% endif %}</span>
{% if df.ta_publicado_id and not df.tipo_dispositivo.dispositivo_de_articulacao %} {% if df.ta_publicado_id %}
<a class="link_alterador" href="{%url 'compilacao:ta_text' df.ta_publicado.pk %}#{{df.dispositivo_atualizador_id}}"> <a class="link_alterador" href="{%url 'compilacao:ta_text' df.ta_publicado.pk %}#{{df.dispositivo_atualizador_id}}">
{{ df.tipo_dispositivo.nota_automatica_prefixo_html|safe }} {{ df.tipo_dispositivo.nota_automatica_prefixo_html|safe }}
{% nota_automatica df ta_pub_list %} {% nota_automatica df ta_pub_list %}

1
templates/compilacao/dispositivo_form_vigencia.html

@ -23,5 +23,6 @@
'url_form': '{% url 'compilacao:dispositivo_search_form'%}', 'url_form': '{% url 'compilacao:dispositivo_search_form'%}',
'text_button': '{% trans 'Selecionar Dispositivo'%}' 'text_button': '{% trans 'Selecionar Dispositivo'%}'
}); });
</script> </script>
{% endblock %} {% endblock %}

3
templates/compilacao/layout/dispositivo_checkbox.html

@ -19,7 +19,6 @@
</li> </li>
{% endifchanged %} {% endifchanged %}
<li> <li>
<div class="iteminput"> <div class="iteminput">
<input type="{{field.field.widget.attrs|lookup:"data-type-selection"}}" name="{{ field.html_name }}" id="dpt{{choice.1.pk}}" value="{{choice.1.pk}}" {% if choice.0 in field.value or choice.0|stringformat:"s" in field.value or choice.0|stringformat:"s" == field.value|stringformat:"s" %} checked="checked"{% endif %} /> <input type="{{field.field.widget.attrs|lookup:"data-type-selection"}}" name="{{ field.html_name }}" id="dpt{{choice.1.pk}}" value="{{choice.1.pk}}" {% if choice.0 in field.value or choice.0|stringformat:"s" in field.value or choice.0|stringformat:"s" == field.value|stringformat:"s" %} checked="checked"{% endif %} />
@ -43,11 +42,9 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div> </div>
</li> </li>
{% if forloop.last %}</ul>{% endif %} {% if forloop.last %}</ul>{% endif %}
{% endfor %} {% endfor %}

41
templates/compilacao/layout/dispositivo_radio.html

@ -5,46 +5,35 @@
<div class="controls lista-dispositvo"{% if flat_attrs %} {{ flat_attrs|safe }}{% endif %}> <div class="controls lista-dispositvo"{% if flat_attrs %} {{ flat_attrs|safe }}{% endif %}>
{% include 'bootstrap/layout/field_errors_block.html' %} {% include 'bootstrap/layout/field_errors_block.html' %}
{% for choice, dpt in field.field.choices %} {% for choice, dpt in field.field.choices %}
{% ifchanged dpt.ta%} {% ifchanged dpt.ta%}
{% if not forloop.first %}</ul>{% endif %} {% if not forloop.first %}</ul>{% endif %}
<ul id="ta{{dpt.ta.pk}}"> <ul id="ta{{dpt.ta.pk}}">
<li class="ta_title"><span>{{dpt.ta}}</span></li> <li class="ta_title"><span>{{dpt.ta}}</span></li>
{% endifchanged %} {% endifchanged %}
{% if dpt.is_relative_auto_insert %}
<li>
<div class="iteminput">
<input type="{{field.field.widget.attrs|lookup:"data-type-selection"}}" name="{{ field.html_name }}" id="dpt{{dpt.pk}}" value="{{dpt.pk}}" {% if choice|stringformat:"s" == field.value|stringformat:"s" %} checked="checked"{% endif %} />
</div>
<div class="itemlabel">
<label for="r{{dpt.dispositivo_pai.pk}}">{{dpt.dispositivo_pai.rotulo|safe}} - {{dpt.texto|safe}}</label>
<a target="_blank" href="{% url 'compilacao:ta_text' dpt.ta.pk%}#{{dpt.pk}}" class="nomenclatura_heranca" title="{% trans 'Abrir Texto deste Dispositivo'%}">{% nomenclatura_heranca dpt 1 1 %}</a>
</div>
</li>
{% elif not dpt.tipo_dispositivo.dispositivo_de_articulacao and not dpt.is_relative_auto_insert %}
<li> <li>
<div class="iteminput"> <div class="iteminput">
<input type="{{field.field.widget.attrs|lookup:"data-type-selection"}}" name="{{ field.html_name }}" id="dpt{{dpt.pk}}" value="{{dpt.pk}}" {% if choice|stringformat:"s" == field.value|stringformat:"s" %} checked="checked"{% endif %} /> <input type="{{field.field.widget.attrs|lookup:"data-type-selection"}}" name="{{ field.html_name }}" id="dpt{{dpt.pk}}" value="{{dpt.pk}}" {% if choice|stringformat:"s" == field.value|stringformat:"s" %} checked="checked"{% endif %} />
</div> </div>
<div class="itemlabel"> <div class="itemlabel dpt">
<label for="r{{dpt.pk}}">{{dpt.rotulo|safe}} - {{dpt.texto|safe}}</label> {% if dpt.nivel > 1 %}
<a target="_blank" href="{% url 'compilacao:ta_text' dpt.ta.pk%}#{{dpt.pk}}" class="nomenclatura_heranca" title="{% trans 'Abrir Texto deste Dispositivo'%}">{% nomenclatura_heranca dpt 1 1 %}</a> <a class="clearfix" target="_blank" href="{% url 'compilacao:ta_text' dpt.ta.pk%}#{{dpt.pk}}" class="nomenclatura_heranca">{% trans "Herança:" %} {% heranca request dpt 1 0 %}</a>
{% endif %}
<div class="{{ dpt.tipo_dispositivo.class_css }}">
<div class="dptt {% dispositivo_desativado dpt None None %}" id="dptt{{dpt.pk}}" >
{{ dpt.tipo_dispositivo.rotulo_prefixo_html|safe }}
{% if dpt.rotulo or dpt.nivel = 1 %}{{ dpt.rotulo }}{%else%}[{{ dpt|nomenclatura}} {% trans "de" %} {{ dpt.dispositivo_pai.rotulo }}] - {% endif %}
{{ dpt.tipo_dispositivo.rotulo_sufixo_html|safe }}
<span class="dtxt"
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 %}&nbsp;{% endif %}{% endif %}</span>
</div> </div>
</li>
{% elif dpt.tipo_dispositivo.dispositivo_de_articulacao%}
<li>
<div class="iteminput">
<input type="{{field.field.widget.attrs|lookup:"data-type-selection"}}" name="{{ field.html_name }}" id="dpt{{dpt.pk}}" value="{{dpt.pk}}" {% if choice|stringformat:"s" == field.value|stringformat:"s" %} checked="checked"{% endif %} />
</div> </div>
<div class="itemlabel">
<label for="r{{dpt.pk}}">{{dpt.rotulo|safe}} - {% if dpt.tipo_dispositivo.dispositivo_de_articulacao %}{{dpt.dispositivos_filhos_set.all.first.texto|safe}}{% else %}{{dpt.texto|safe}}{% endif %}</label>
<a target="_blank" href="{% url 'compilacao:ta_text' dpt.ta.pk%}#{{dpt.pk}}" class="nomenclatura_heranca" title="{% trans 'Abrir Texto deste Dispositivo'%}">{% nomenclatura_heranca dpt 1 1 %}</a>
</div> </div>
</li> </li>
{% endif%}
{% if forloop.last %}</ul>{% endif %} {% if forloop.last %}</ul>{% endif %}
{% endfor %} {% endfor %}

8
templates/compilacao/text_edit.html

@ -66,7 +66,7 @@
<li><strong>(C) Construtor Estrutural:</strong> Neste modo, o editor foca na inserção de Dispositivos e busca deixar mais acessíveis estas ações.</li> <li><strong>(C) Construtor Estrutural:</strong> Neste modo, o editor foca na inserção de Dispositivos e busca deixar mais acessíveis estas ações.</li>
</ol></li> </ol></li>
<li>A Edição Avançada é complexa e sensível a erros de edição. É recomendável o uso cuidadoso e consciente das funcionalidades.</li> <li>A Edição Avançada é complexa e sensível a erros de edição. É recomendável o uso cuidadoso e consciente das funcionalidades. Ela será tratada num tópico aparte.</li>
<li>Gere toda a estrutura básica sem adicionar texto, isso evitará erros estruturais e otimizará seu trabalho por: <li>Gere toda a estrutura básica sem adicionar texto, isso evitará erros estruturais e otimizará seu trabalho por:
<ol> <ol>
<li>Facilitar o trabalho local aí, de seu navegador.</li> <li>Facilitar o trabalho local aí, de seu navegador.</li>
@ -105,6 +105,12 @@
</ol> </ol>
</li> </li>
</ol> </ol>
<hr>
<h4>Edição Avançada</h4>
<ol>
<li>...
</li>
</ol>
{% endblocktrans %} {% endblocktrans %}

2
templates/compilacao/text_list_bloco.html

@ -163,7 +163,7 @@
{% endif%} {% endif%}
</div> </div>
{% endspaceless %} {% endspaceless %}
{% if dpt.tipo_dispositivo.class_css == 'bloco_alteracao'%} {% if dpt.tipo_dispositivo.dispositivo_de_alteracao%}
{%with node=dpt template_name='compilacao/text_list_blocoalteracao.html' %} {%with node=dpt template_name='compilacao/text_list_blocoalteracao.html' %}
{%include template_name%} {%include template_name%}
{%endwith%} {%endwith%}

8
templates/compilacao/textoarticulado_menu_config.html

@ -6,10 +6,10 @@
</button> </button>
<ul class="dropdown-menu" role="menu"> <ul class="dropdown-menu" role="menu">
<li><a href="{% url 'compilacao:tipo_ta_list' %}">{%model_verbose_name_plural 'compilacao.models.TipoTextoArticulado'%}</a></li> <li><a href="{% url 'compilacao:tipo_ta_list' %}">{%model_verbose_name_plural 'compilacao.models.TipoTextoArticulado'%}</a></li>
<li><a href="{% url 'tipopublicacao:list' %}">{%model_verbose_name_plural 'compilacao.models.TipoPublicacao'%}</a></li> <li><a href="{% url 'compilacao:tipopublicacao_list' %}">{%model_verbose_name_plural 'compilacao.models.TipoPublicacao'%}</a></li>
<li><a href="{% url 'veiculopublicacao:list' %}">{%model_verbose_name_plural 'compilacao.models.VeiculoPublicacao'%}</a></li> <li><a href="{% url 'compilacao:veiculopublicacao_list' %}">{%model_verbose_name_plural 'compilacao.models.VeiculoPublicacao'%}</a></li>
<li><a href="{% url 'tiponota:list' %}">{%model_verbose_name_plural 'compilacao.models.TipoNota'%}</a></li> <li><a href="{% url 'compilacao:tiponota_list' %}">{%model_verbose_name_plural 'compilacao.models.TipoNota'%}</a></li>
<li><a href="{% url 'tipovide:list' %}">{%model_verbose_name_plural 'compilacao.models.TipoVide'%}</a></li> <li><a href="{% url 'compilacao:tipovide_list' %}">{%model_verbose_name_plural 'compilacao.models.TipoVide'%}</a></li>
<li><a href="#">TODO: Tipo de Dispositivo</a></li> <li><a href="#">TODO: Tipo de Dispositivo</a></li>
<li><a href="#">TODO: Perfil Estrutural de Textos Articulados</a></li> <li><a href="#">TODO: Perfil Estrutural de Textos Articulados</a></li>
</ul> </ul>

Loading…
Cancel
Save