From 18c54c14013789df14cb3ae81cdd643a2e10bee9 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Silva Date: Tue, 2 Mar 2021 13:28:17 -0300 Subject: [PATCH] Impl feature flag (#3357) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add load para variável de ambiente * altera url de primeira página se SAPL_AS_SAPN = True * add context_processor para sapl as sapn * ajuste de identação * refatora base.html para sapl as sapn * remove menus do sapl em sapn * ajusta tabelas auxiliares * refatora norma e compilação para sapl as sapn * impl feature flag superficial * ajusta menu Acessar em sapl as sapn * add orgao como fk para normas * add órgão no cadastro de normas * ajuste de teste redirecionamento sapl index * ajuste de teste de url --- sapl/base/forms.py | 3 +- .../migrations/0044_appconfig_sapl_as_sapn.py | 18 ++ .../migrations/0045_auto_20210301_1537.py | 18 ++ sapl/base/models.py | 5 + sapl/base/templatetags/common_tags.py | 15 +- sapl/base/urls.py | 36 ++-- sapl/base/views.py | 9 +- .../migrations/0018_auto_20210227_2152.py | 19 ++ sapl/compilacao/models.py | 3 +- sapl/context_processors.py | 13 +- sapl/norma/forms.py | 46 ++--- .../migrations/0038_normajuridica_orgao.py | 20 +++ sapl/norma/models.py | 8 +- sapl/norma/urls.py | 4 +- sapl/norma/views.py | 19 +- sapl/redireciona_urls/tests.py | 5 +- sapl/redireciona_urls/views.py | 113 +++++++----- sapl/settings.py | 1 + sapl/templates/base.html | 163 ++++++++++-------- sapl/templates/base/layouts.yaml | 3 +- sapl/templates/compilacao/subnav.html | 4 +- .../compilacao/text_list__embedded.html | 3 + .../compilacao/textoarticulado_detail.html | 6 +- sapl/templates/menu_tabelas_auxiliares.yaml | 74 ++++---- sapl/templates/navbar.yaml | 4 +- sapl/templates/norma/layouts.yaml | 4 +- .../templates/norma/normajuridica_detail.html | 6 +- sapl/templates/norma/normajuridica_form.html | 7 +- sapl/templates/search/search.html | 29 ++-- sapl/test_urls.py | 14 +- sapl/urls.py | 18 +- sapl/utils.py | 7 + 32 files changed, 462 insertions(+), 235 deletions(-) create mode 100644 sapl/base/migrations/0044_appconfig_sapl_as_sapn.py create mode 100644 sapl/base/migrations/0045_auto_20210301_1537.py create mode 100644 sapl/compilacao/migrations/0018_auto_20210227_2152.py create mode 100644 sapl/norma/migrations/0038_normajuridica_orgao.py diff --git a/sapl/base/forms.py b/sapl/base/forms.py index 30f4f47e5..f8667a5c4 100644 --- a/sapl/base/forms.py +++ b/sapl/base/forms.py @@ -1611,7 +1611,8 @@ class ConfiguracoesAppForm(ModelForm): 'tramitacao_materia', 'tramitacao_documento', 'google_recaptcha_site_key', - 'google_recaptcha_secret_key'] + 'google_recaptcha_secret_key', + 'sapl_as_sapn'] def __init__(self, *args, **kwargs): super(ConfiguracoesAppForm, self).__init__(*args, **kwargs) diff --git a/sapl/base/migrations/0044_appconfig_sapl_as_sapn.py b/sapl/base/migrations/0044_appconfig_sapl_as_sapn.py new file mode 100644 index 000000000..3fcb96d5a --- /dev/null +++ b/sapl/base/migrations/0044_appconfig_sapl_as_sapn.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.13 on 2021-02-28 00:45 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('base', '0043_auto_20210203_1442'), + ] + + operations = [ + migrations.AddField( + model_name='appconfig', + name='sapl_as_sapn', + field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Utilizar SAPL com SAPN?'), + ), + ] diff --git a/sapl/base/migrations/0045_auto_20210301_1537.py b/sapl/base/migrations/0045_auto_20210301_1537.py new file mode 100644 index 000000000..d10898b4f --- /dev/null +++ b/sapl/base/migrations/0045_auto_20210301_1537.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.13 on 2021-03-01 18:37 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('base', '0044_appconfig_sapl_as_sapn'), + ] + + operations = [ + migrations.AlterField( + model_name='appconfig', + name='sapl_as_sapn', + field=models.BooleanField(choices=[(True, 'Sim'), (False, 'Não')], default=False, verbose_name='Utilizar SAPL como SAPN?'), + ), + ] diff --git a/sapl/base/models.py b/sapl/base/models.py index aabdd88f3..ae5db11a8 100644 --- a/sapl/base/models.py +++ b/sapl/base/models.py @@ -200,6 +200,11 @@ class AppConfig(models.Model): verbose_name=_('Chave privada gerada pelo Google Recaptcha'), max_length=256, default='') + sapl_as_sapn = models.BooleanField( + verbose_name=_( + 'Utilizar SAPL como SAPN?'), + choices=YES_NO_CHOICES, default=False) + class Meta: verbose_name = _('Configurações da Aplicação') verbose_name_plural = _('Configurações da Aplicação') diff --git a/sapl/base/templatetags/common_tags.py b/sapl/base/templatetags/common_tags.py index 048778d8d..56d7d356e 100644 --- a/sapl/base/templatetags/common_tags.py +++ b/sapl/base/templatetags/common_tags.py @@ -51,6 +51,13 @@ def model_verbose_name_plural(class_name): model = get_class(class_name) return model._meta.verbose_name_plural +@register.filter +def meta_model_value(instance, attr): + try: + return getattr(instance._meta, attr) + except: + return '' + @register.filter def split(value, arg): @@ -324,12 +331,12 @@ def render_chunk_vendors(extension=None): return mark_safe('\n'.join(tags)) except: return '' - - + + @register.filter(is_safe=True) -@stringfilter +@stringfilter def dont_break_out(value): _safe = '
{}
'.format(value) _safe = mark_safe(_safe) - return _safe + return _safe diff --git a/sapl/base/urls.py b/sapl/base/urls.py index fbb1e483d..d311acbb5 100644 --- a/sapl/base/urls.py +++ b/sapl/base/urls.py @@ -11,7 +11,8 @@ from django.views.generic.base import RedirectView, TemplateView from sapl.base.views import (AutorCrud, ConfirmarEmailView, TipoAutorCrud, get_estatistica, DetailUsuarioView, PesquisarAutorView, RecuperarSenhaEmailView, RecuperarSenhaFinalizadoView, - RecuperarSenhaConfirmaView, RecuperarSenhaCompletoView, RelatorioMateriaAnoAssuntoView) + RecuperarSenhaConfirmaView, RecuperarSenhaCompletoView, RelatorioMateriaAnoAssuntoView, + IndexView) from sapl.settings import EMAIL_SEND_USER, MEDIA_URL, LOGOUT_REDIRECT_URL from .apps import AppConfig @@ -35,10 +36,14 @@ app_name = AppConfig.name admin_user = [ url(r'^sistema/usuario/$', PesquisarUsuarioView.as_view(), name='usuario'), - url(r'^sistema/usuario/create$', CreateUsuarioView.as_view(), name='user_create'), - url(r'^sistema/usuario/(?P\d+)$', DetailUsuarioView.as_view(), name='user_detail'), - url(r'^sistema/usuario/(?P\d+)/edit$', EditUsuarioView.as_view(), name='user_edit'), - url(r'^sistema/usuario/(?P\d+)/delete$', DeleteUsuarioView.as_view(), name='user_delete') + url(r'^sistema/usuario/create$', + CreateUsuarioView.as_view(), name='user_create'), + url(r'^sistema/usuario/(?P\d+)$', + DetailUsuarioView.as_view(), name='user_detail'), + url(r'^sistema/usuario/(?P\d+)/edit$', + EditUsuarioView.as_view(), name='user_edit'), + url(r'^sistema/usuario/(?P\d+)/delete$', + DeleteUsuarioView.as_view(), name='user_delete') ] alterar_senha = [ @@ -49,17 +54,23 @@ alterar_senha = [ ] recuperar_senha = [ - url(r'^recuperar-senha/email/$', RecuperarSenhaEmailView.as_view(), name='recuperar_senha_email'), - url(r'^recuperar-senha/finalizado/$', RecuperarSenhaFinalizadoView.as_view(), name='recuperar_senha_finalizado'), + url(r'^recuperar-senha/email/$', RecuperarSenhaEmailView.as_view(), + name='recuperar_senha_email'), + url(r'^recuperar-senha/finalizado/$', + RecuperarSenhaFinalizadoView.as_view(), name='recuperar_senha_finalizado'), url(r'^recuperar-senha/(?P[0-9A-Za-z_\-]+)/(?P.+)/$', RecuperarSenhaConfirmaView.as_view(), name='recuperar_senha_confirma'), - url(r'^recuperar-senha/completo/$', RecuperarSenhaCompletoView.as_view(), name='recuperar_senha_completo'), + url(r'^recuperar-senha/completo/$', + RecuperarSenhaCompletoView.as_view(), name='recuperar_senha_completo'), ] urlpatterns = [ + url(r'^$', IndexView.as_view(template_name='index.html'), name='sapl_index'), + url(r'^sistema/autor/tipo/', include(TipoAutorCrud.get_urls())), url(r'^sistema/autor/', include(AutorCrud.get_urls())), - url(r'^sistema/autor/pesquisar-autor/', PesquisarAutorView.as_view(), name='pesquisar_autor'), + url(r'^sistema/autor/pesquisar-autor/', + PesquisarAutorView.as_view(), name='pesquisar_autor'), url(r'^sistema/ajuda/(?P\w+)$', HelpTopicView.as_view(), name='help_topic'), @@ -70,7 +81,7 @@ urlpatterns = [ url(r'^sistema/app-config/', include(AppConfigCrud.get_urls())), # TODO mover estas telas para a app 'relatorios' - url(r'^sistema/relatorios/$', + url(r'^sistema/relatorios/$', RelatoriosListView.as_view(), name='relatorios_list'), url(r'^sistema/relatorios/materia-por-autor$', RelatorioMateriasPorAutorView.as_view(), name='materia_por_autor'), @@ -174,9 +185,10 @@ urlpatterns = [ (TemplateView.as_view(template_name='sistema.html')), name='sistema'), - url(r'^login/$', views.LoginView.as_view(template_name= 'base/login.html', authentication_form= LoginForm), + url(r'^login/$', views.LoginView.as_view(template_name='base/login.html', authentication_form=LoginForm), name='login'), - url(r'^logout/$', views.LogoutView.as_view(), {'next_page': LOGOUT_REDIRECT_URL}, name='logout'), + url(r'^logout/$', views.LogoutView.as_view(), + {'next_page': LOGOUT_REDIRECT_URL}, name='logout'), url(r'^sistema/search/', SaplSearchView(), name='haystack_search'), diff --git a/sapl/base/views.py b/sapl/base/views.py index b38bee7bf..0d4da76d7 100644 --- a/sapl/base/views.py +++ b/sapl/base/views.py @@ -60,7 +60,7 @@ from sapl.sessao.models import ( from sapl.settings import EMAIL_SEND_USER from sapl.utils import (gerar_hash_arquivo, intervalos_tem_intersecao, mail_service_configured, parlamentares_ativos, SEPARADOR_HASH_PROPOSICAO, show_results_filter_set, num_materias_por_tipo, - google_recaptcha_configured) + google_recaptcha_configured, sapl_as_sapn) from .forms import (AlterarSenhaForm, CasaLegislativaForm, ConfiguracoesAppForm, RelatorioAtasFilterSet, RelatorioAudienciaFilterSet, RelatorioDataFimPrazoTramitacaoFilterSet, @@ -77,6 +77,13 @@ def get_casalegislativa(): return CasaLegislativa.objects.first() +class IndexView(TemplateView): + def get(self, request, *args, **kwargs): + if sapl_as_sapn(): + return redirect('/norma/pesquisar') + return TemplateView.get(self, request, *args, **kwargs) + + class ConfirmarEmailView(TemplateView): template_name = "email/confirma.html" diff --git a/sapl/compilacao/migrations/0018_auto_20210227_2152.py b/sapl/compilacao/migrations/0018_auto_20210227_2152.py new file mode 100644 index 000000000..2630b5bca --- /dev/null +++ b/sapl/compilacao/migrations/0018_auto_20210227_2152.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.13 on 2021-02-28 00:52 + +from django.db import migrations +import image_cropping.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('compilacao', '0017_auto_20210225_1127'), + ] + + operations = [ + migrations.AlterField( + model_name='dispositivo', + name='imagem_cropping', + field=image_cropping.fields.ImageRatioField('imagem', '100x100', adapt_rotation=False, allow_fullsize=False, free_crop=True, help_text='O recorte de imagem é possível após a atualização.', hide_image_field=False, size_warning=True, verbose_name='Recorte de Imagem'), + ), + ] diff --git a/sapl/compilacao/models.py b/sapl/compilacao/models.py index 3c6fee330..452d2a494 100644 --- a/sapl/compilacao/models.py +++ b/sapl/compilacao/models.py @@ -1192,8 +1192,7 @@ class Dispositivo(BaseModel, TimestampedMixin): imagem = ImageCropField( verbose_name=_('Imagem'), - upload_to=imagem_upload_path, - validators=[restringe_tipos_de_arquivo_img], null=True, blank=True) + upload_to=imagem_upload_path, null=True, blank=True) imagem_cropping = ImageRatioField( 'imagem', '100x100', verbose_name=_('Recorte de Imagem'), diff --git a/sapl/context_processors.py b/sapl/context_processors.py index a84d77e3d..046cd8ab0 100644 --- a/sapl/context_processors.py +++ b/sapl/context_processors.py @@ -1,8 +1,10 @@ import logging +from django.conf import settings from django.utils.translation import ugettext_lazy as _ -from sapl.utils import google_recaptcha_configured as google_recaptcha_configured_utils +from sapl.utils import google_recaptcha_configured as google_recaptcha_configured_utils,\ + sapl_as_sapn as sapl_as_sapn_utils from sapl.utils import mail_service_configured as mail_service_configured_utils @@ -32,3 +34,12 @@ def google_recaptcha_configured(request): logger.warning(_('Google Recaptcha não configurado.')) return {'google_recaptcha_configured': False} return {'google_recaptcha_configured': True} + + +def sapl_as_sapn(request): + return { + 'sapl_as_sapn': sapl_as_sapn_utils(), + 'nome_sistema': _('Sistema de Apoio ao Processo Legislativo') + if not sapl_as_sapn_utils() + else _('Sistema de Apoio a Publicação de Normas') + } diff --git a/sapl/norma/forms.py b/sapl/norma/forms.py index 85153b846..e0a5a0d7d 100644 --- a/sapl/norma/forms.py +++ b/sapl/norma/forms.py @@ -1,8 +1,6 @@ -import django_filters import logging from crispy_forms.layout import Fieldset, Layout - from django import forms from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.db import models @@ -10,6 +8,7 @@ from django.db.models import Q from django.forms import ModelChoiceField, ModelForm, widgets from django.utils import timezone from django.utils.translation import ugettext_lazy as _ +import django_filters from sapl.base.models import Autor, TipoAutor from sapl.crispy_layout_mixin import form_actions, SaplFormHelper, to_row @@ -85,7 +84,7 @@ class NormaFilterSet(django_filters.FilterSet): class Meta(FilterOverridesMetaMixin): model = NormaJuridica - fields = ['tipo', 'numero', 'ano', 'data', 'data_vigencia', + fields = ['orgao', 'tipo', 'numero', 'ano', 'data', 'data_vigencia', 'data_publicacao', 'ementa', 'assuntos'] def __init__(self, *args, **kwargs): @@ -94,7 +93,7 @@ class NormaFilterSet(django_filters.FilterSet): row1 = to_row([('tipo', 4), ('numero', 4), ('ano', 4)]) row2 = to_row([('data', 6), ('data_publicacao', 6)]) row3 = to_row([('ementa', 6), ('assuntos', 6)]) - row4 = to_row([('data_vigencia', 12)]) + row4 = to_row([('data_vigencia', 6), ('orgao', 6), ]) row5 = to_row([('o', 6), ('indexacao', 6)]) self.form.helper = SaplFormHelper() @@ -143,6 +142,7 @@ class NormaJuridicaForm(FileFieldCheckMixin, ModelForm): fields = ['tipo', 'numero', 'ano', + 'orgao', 'data', 'esfera_federacao', 'complemento', @@ -159,14 +159,14 @@ class NormaJuridicaForm(FileFieldCheckMixin, ModelForm): 'observacao', 'texto_integral', 'assuntos', - 'user', + 'user', 'ip', 'ultima_edicao'] widgets = {'assuntos': widgets.CheckboxSelectMultiple, - 'user': forms.HiddenInput(), - 'ip': forms.HiddenInput(), - 'ultima_edicao': forms.HiddenInput()} + 'user': forms.HiddenInput(), + 'ip': forms.HiddenInput(), + 'ultima_edicao': forms.HiddenInput()} def clean(self): @@ -184,14 +184,18 @@ class NormaJuridicaForm(FileFieldCheckMixin, ModelForm): 'Número de norma não pode conter somente letras') if self.instance.numero != cleaned_data['numero']: - norma = NormaJuridica.objects.filter(ano=cleaned_data['ano'], - numero=cleaned_data['numero'], - tipo=cleaned_data['tipo']).exists() + params = { + 'ano': cleaned_data['ano'], + 'numero': cleaned_data['numero'], + 'tipo': cleaned_data['tipo'], + } + params['orgao'] = cleaned_data['orgao'] + norma = NormaJuridica.objects.filter(**params).exists() if norma: self.logger.warning("Já existe uma norma de mesmo Tipo ({}), Ano ({}) " - "e Número ({}) no sistema." - .format(cleaned_data['tipo'], cleaned_data['ano'], cleaned_data['numero'])) - raise ValidationError("Já existe uma norma de mesmo Tipo, Ano " + "e Número ({}) no sistema." + .format(cleaned_data['tipo'], cleaned_data['ano'], cleaned_data['numero'])) + raise ValidationError("Já existe uma norma de mesmo Tipo, Ano, Órgão " "e Número no sistema") if (cleaned_data['tipo_materia'] and cleaned_data['numero_materia'] and @@ -294,9 +298,9 @@ class AutoriaNormaForm(ModelForm): class AnexoNormaJuridicaForm(FileFieldCheckMixin, ModelForm): - + logger = logging.getLogger(__name__) - + anexo_arquivo = forms.FileField( required=True, label="Arquivo Anexo" @@ -311,10 +315,10 @@ class AnexoNormaJuridicaForm(FileFieldCheckMixin, ModelForm): def clean(self): cleaned_data = super(AnexoNormaJuridicaForm, self).clean() - + if not self.is_valid(): return cleaned_data - + anexo_arquivo = self.cleaned_data.get('anexo_arquivo', False) if anexo_arquivo: @@ -454,7 +458,9 @@ class NormaPesquisaSimplesForm(forms.Form): raise ValidationError(_('Caso pesquise por data, os campos de Data Inicial e ' 'Data Final devem ser preenchidos obrigatoriamente')) elif data_inicial > data_final: - self.logger.error("Data Final ({}) menor que a Data Inicial ({}).".format(data_final, data_inicial)) - raise ValidationError(_('A Data Final não pode ser menor que a Data Inicial')) + self.logger.error("Data Final ({}) menor que a Data Inicial ({}).".format( + data_final, data_inicial)) + raise ValidationError( + _('A Data Final não pode ser menor que a Data Inicial')) return cleaned_data diff --git a/sapl/norma/migrations/0038_normajuridica_orgao.py b/sapl/norma/migrations/0038_normajuridica_orgao.py new file mode 100644 index 000000000..5149ceb09 --- /dev/null +++ b/sapl/norma/migrations/0038_normajuridica_orgao.py @@ -0,0 +1,20 @@ +# Generated by Django 2.2.13 on 2021-03-01 18:37 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0077_auto_20210209_1047'), + ('norma', '0037_auto_20210107_1408'), + ] + + operations = [ + migrations.AddField( + model_name='normajuridica', + name='orgao', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='materia.Orgao', verbose_name='Órgão'), + ), + ] diff --git a/sapl/norma/models.py b/sapl/norma/models.py index ac93f5ae0..85358ed75 100644 --- a/sapl/norma/models.py +++ b/sapl/norma/models.py @@ -8,7 +8,7 @@ import reversion from sapl.base.models import Autor from sapl.compilacao.models import TextoArticulado -from sapl.materia.models import MateriaLegislativa +from sapl.materia.models import MateriaLegislativa, Orgao from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, restringe_tipos_de_arquivo_txt, texto_upload_path, @@ -151,6 +151,9 @@ class NormaJuridica(models.Model): materia = models.ForeignKey( MateriaLegislativa, blank=True, null=True, on_delete=models.PROTECT, verbose_name=_('Matéria')) + orgao = models.ForeignKey( + Orgao, blank=True, null=True, + on_delete=models.PROTECT, verbose_name=_('Órgão')) numero = models.CharField( max_length=8, verbose_name=_('Número')) @@ -247,8 +250,9 @@ class NormaJuridica(models.Model): if numero_norma.isnumeric(): numero_norma = '{0:,}'.format(int(self.numero)).replace(',', '.') - return _('%(tipo)s nº %(numero)s, de %(data)s') % { + return _('%(tipo)s%(orgao_sigla)s nº %(numero)s, de %(data)s') % { 'tipo': self.tipo, + 'orgao_sigla': f'-{self.orgao.sigla}' if self.orgao else '', 'numero': numero_norma, 'data': defaultfilters.date(self.data, "d \d\e F \d\e Y").lower()} diff --git a/sapl/norma/urls.py b/sapl/norma/urls.py index 3a941e0b3..951479ea4 100644 --- a/sapl/norma/urls.py +++ b/sapl/norma/urls.py @@ -1,3 +1,4 @@ +from django.conf import settings from django.conf.urls import include, url from sapl.norma.views import (AnexoNormaJuridicaCrud, AssuntoNormaCrud, @@ -7,8 +8,10 @@ from sapl.norma.views import (AnexoNormaJuridicaCrud, AssuntoNormaCrud, recuperar_numero_norma, AutoriaNormaCrud, PesquisarAssuntoNormaView) + from .apps import AppConfig + app_name = AppConfig.name @@ -37,5 +40,4 @@ urlpatterns = [ url(r'^norma/recuperar-norma$', recuperar_norma, name="recuperar_norma"), url(r'^norma/recuperar-numero-norma$', recuperar_numero_norma, name="recuperar_numero_norma"), - ] diff --git a/sapl/norma/views.py b/sapl/norma/views.py index 1281f9d76..3c7abc870 100644 --- a/sapl/norma/views.py +++ b/sapl/norma/views.py @@ -7,6 +7,7 @@ from django.core.exceptions import ObjectDoesNotExist from django.db.models import Q from django.http import HttpResponse, JsonResponse from django.http.response import HttpResponseRedirect +from django.shortcuts import redirect from django.template import RequestContext, loader from django.urls import reverse from django.urls.base import reverse_lazy @@ -25,7 +26,9 @@ from sapl.base.models import AppConfig from sapl.compilacao.views import IntegracaoTaView from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux, MasterDetailCrud, make_pagination) -from sapl.utils import show_results_filter_set, get_client_ip +from sapl.materia.models import Orgao +from sapl.utils import show_results_filter_set, get_client_ip,\ + sapl_as_sapn from .forms import (AnexoNormaJuridicaForm, NormaFilterSet, NormaJuridicaForm, NormaPesquisaSimplesForm, NormaRelacionadaForm, @@ -35,8 +38,6 @@ from .models import (AnexoNormaJuridica, AssuntoNorma, NormaJuridica, NormaRelac # LegislacaoCitadaCrud = Crud.build(LegislacaoCitada, '') - - TipoNormaCrud = CrudAux.build( TipoNormaJuridica, 'tipo_norma_juridica', list_field_names=['sigla', 'descricao', 'equivalente_lexml']) @@ -273,6 +274,11 @@ class NormaCrud(Crud): norma_id=kwargs['pk'], ano=timezone.now().year, horario_acesso=timezone.now()) + + if not 'display' in request.GET and not request.user.has_perm('norma.change_normajuridica') and \ + self.get_object().texto_articulado.exists(): + return redirect(reverse('sapl.norma:norma_ta', + kwargs={'pk': self.kwargs['pk']})) return super().get(request, *args, **kwargs) class DeleteView(Crud.DeleteView): @@ -450,9 +456,14 @@ def recuperar_norma(request): def recuperar_numero_norma(request): tipo = TipoNormaJuridica.objects.get(pk=request.GET['tipo']) ano = request.GET.get('ano', '') + orgao = request.GET.get('orgao', '') + param = {'tipo': tipo, - 'ano': ano if ano else timezone.now().year + 'ano': ano if ano else timezone.now().year, } + if orgao: + param['orgao'] = Orgao.objects.get(pk=orgao) + norma = NormaJuridica.objects.filter(**param).order_by( 'tipo', 'ano', 'numero').values_list('numero', flat=True) if norma: diff --git a/sapl/redireciona_urls/tests.py b/sapl/redireciona_urls/tests.py index d641afc6c..5a0e8b98f 100644 --- a/sapl/redireciona_urls/tests.py +++ b/sapl/redireciona_urls/tests.py @@ -1,5 +1,6 @@ -from django.urls import reverse from django.test import TestCase +from django.urls import reverse + MovedPermanentlyHTTPStatusCode = 301 EMPTY_STRING = '' @@ -11,7 +12,7 @@ class RedirecionaURLsTests(TestCase): response = self.client.get(reverse( 'sapl.redireciona_urls:redireciona_sapl_index') ) - url_e = reverse('sapl_index') + url_e = reverse('sapl.base:sapl_index') self.assertEqual(response.status_code, MovedPermanentlyHTTPStatusCode) self.assertEqual(response.url, url_e) diff --git a/sapl/redireciona_urls/views.py b/sapl/redireciona_urls/views.py index ad3cae93c..435280b3b 100644 --- a/sapl/redireciona_urls/views.py +++ b/sapl/redireciona_urls/views.py @@ -76,13 +76,14 @@ class RedirecionaSAPLIndex(RedirectView): logger = logging.getLogger(__name__) def get_redirect_url(self): - url_pattern = 'sapl_index' + url_pattern = 'sapl.base:sapl_index' username = self.request.user.username try: self.logger.info("user=" + username + ". Tentando obter url.") url = reverse(url_pattern) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(url_pattern) url = has_iframe(url, self.request) @@ -95,7 +96,7 @@ class RedirecionaParlamentar(RedirectView): logger = logging.getLogger(__name__) def get_redirect_url(self): - + url = EMPTY_STRING pk_parlamentar = self.request.GET.get( 'cod_parlamentar', @@ -105,17 +106,20 @@ class RedirecionaParlamentar(RedirectView): if pk_parlamentar: try: kwargs = {'pk': pk_parlamentar} - self.logger.debug("user=" + username + ". Tentando obter url correspondente.") + self.logger.debug("user=" + username + + ". Tentando obter url correspondente.") url = reverse(parlamentar_detail, kwargs=kwargs) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(parlamentar_detail, kwargs=kwargs) else: try: self.logger.debug("user=" + username + ". Tentando obter url.") url = reverse(parlamentar_list) except NoReverseMatch: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(parlamentar_list) numero_legislatura = self.request.GET.get( @@ -143,17 +147,20 @@ class RedirecionaComissao(RedirectView): kwargs = {'pk': pk_comissao} try: - self.logger.debug("user=" + username + ". Tentando obter url correspondente.") + self.logger.debug("user=" + username + + ". Tentando obter url correspondente.") url = reverse(comissao_detail, kwargs=kwargs) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(comissao_detail) else: try: self.logger.debug("user=" + username + ". Tentando obter url.") url = reverse(comissao_list) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(comissao_list) url = has_iframe(url, self.request) @@ -176,17 +183,20 @@ class RedirecionaComposicaoComissao(RedirectView): kwargs = {'pk': pk_comissao} try: - self.logger.debug("user=" + username + ". Tentando obter url correspondente.") + self.logger.debug("user=" + username + + ". Tentando obter url correspondente.") url = reverse(comissao_detail, kwargs=kwargs) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(comissao_detail) else: try: self.logger.debug("user=" + username + ". Tentando obter url.") url = reverse(comissao_list) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(comissao_list) url = has_iframe(url, self.request) @@ -199,7 +209,7 @@ class RedirecionaPautaSessao(RedirectView): logger = logging.getLogger(__name__) def get_redirect_url(self): - + pk_sessao_plenaria = self.request.GET.get( 'cod_sessao_plen', EMPTY_STRING) @@ -208,17 +218,20 @@ class RedirecionaPautaSessao(RedirectView): if pk_sessao_plenaria: kwargs = {'pk': pk_sessao_plenaria} try: - self.logger.debug("user=" + username + ". Tentando obter url correspondente.") + self.logger.debug("user=" + username + + ". Tentando obter url correspondente.") url = reverse(pauta_sessao_detail, kwargs=kwargs) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(pauta_sessao_detail) else: try: self.logger.debug("user=" + username + ". Tentando obter url.") url = reverse(pauta_sessao_list) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(pauta_sessao_list) data_sessao_plenaria = self.request.GET.get( @@ -255,10 +268,12 @@ class RedirecionaSessaoPlenaria(RedirectView): if pk_sessao_plenaria: kwargs = {'pk': pk_sessao_plenaria} try: - self.logger.debug("user=" + username + ". Tentando obter url correspondente.") + self.logger.debug("user=" + username + + ". Tentando obter url correspondente.") url = reverse(sessao_plenaria_detail, kwargs=kwargs) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(sessao_plenaria_detail) else: @@ -266,7 +281,8 @@ class RedirecionaSessaoPlenaria(RedirectView): self.logger.debug("user=" + username + ". Tentando obter url.") url = reverse(sessao_plenaria_list) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(sessao_plenaria_list) year = self.request.GET.get( @@ -302,14 +318,15 @@ class RedirecionaRelatoriosList(RedirectView): logger = logging.getLogger(__name__) def get_redirect_url(self): - + url = EMPTY_STRING username = self.request.user.username try: self.logger.debug("user=" + username + ". Tentando obter url.") url = reverse(relatorios_list) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(relatorios_list) url = has_iframe(url, self.request) @@ -328,7 +345,8 @@ class RedirecionaRelatoriosMateriasEmTramitacaoList(RedirectView): self.logger.debug("user=" + username + ". Tentando obter url.") url = reverse(relatorio_materia_por_tramitacao) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(relatorio_materia_por_tramitacao) year = self.request.GET.get( @@ -396,7 +414,8 @@ class RedirecionaMateriaLegislativaList(RedirectView): self.logger.debug("user=" + username + ". Tentando obter url.") url = reverse(materialegislativa_list) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(materialegislativa_list) tipo_materia = self.request.GET.get( @@ -468,14 +487,15 @@ class RedirecionaMesaDiretoraView(RedirectView): logger = logging.getLogger(__name__) def get_redirect_url(self): - + url = EMPTY_STRING username = self.request.user.username try: self.logger.debug("user=" + username + ". Tentando obter url.") url = reverse(parlamentar_mesa_diretora) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(parlamentar_mesa_diretora) url = has_iframe(url, self.request) @@ -509,12 +529,14 @@ class RedirecionaNormasJuridicasTextoIntegral(RedirectView): url = EMPTY_STRING username = self.request.user.username try: - self.logger.debug("user=" + username + ". Tentando obter NormaJuridica com pk={}.".format(kwargs['norma_id'])) + self.logger.debug( + "user=" + username + ". Tentando obter NormaJuridica com pk={}.".format(kwargs['norma_id'])) norma = NormaJuridica.objects.get(pk=kwargs['norma_id']) if norma: url = norma.texto_integral.url except Exception as e: - self.logger.error("user=" + username + ". Erro ao obter NormaJuridica com pk={}. ".format(kwargs['norma_id']) + str(e)) + self.logger.error( + "user=" + username + ". Erro ao obter NormaJuridica com pk={}. ".format(kwargs['norma_id']) + str(e)) raise e url = has_iframe(url, self.request) @@ -535,7 +557,8 @@ class RedirecionaNormasJuridicasList(RedirectView): self.logger.debug("user=" + username + ". Tentando obter url.") url = reverse(norma_juridica_pesquisa) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(norma_juridica_pesquisa) tipo_norma = self.request.GET.get( @@ -590,7 +613,7 @@ class RedirecionaHistoricoTramitacoesList(RedirectView): logger = logging.getLogger(__name__) def get_redirect_url(self): - + url = EMPTY_STRING args = EMPTY_STRING username = self.request.user.username @@ -598,7 +621,8 @@ class RedirecionaHistoricoTramitacoesList(RedirectView): self.logger.debug("user=" + username + ". Tentando obter url.") url = reverse(historico_tramitacoes) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(historico_tramitacoes) inicio_intervalo_data_tramitacao = self.request.GET.get( @@ -652,7 +676,7 @@ class RedirecionaAtasList(RedirectView): logger = logging.getLogger(__name__) def get_redirect_url(self): - + url = EMPTY_STRING args = EMPTY_STRING username = self.request.user.username @@ -660,7 +684,8 @@ class RedirecionaAtasList(RedirectView): self.logger.debug("user=" + username + ". Tentando obter url.") url = reverse(pesquisar_atas) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(pesquisar_atas) inicio_intervalo_data_ata = self.request.GET.get( @@ -691,7 +716,7 @@ class RedirecionaPresencaParlamentares(RedirectView): logger = logging.getLogger(__name__) def get_redirect_url(self): - + url = EMPTY_STRING args = EMPTY_STRING username = self.request.user.username @@ -699,7 +724,8 @@ class RedirecionaPresencaParlamentares(RedirectView): self.logger.debug("user=" + username + ". Tentando obter url.") url = reverse(presenca_sessao) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(presenca_sessao) inicio_intervalo_data_presenca_parlamentar = self.request.GET.get( @@ -736,7 +762,8 @@ class RedirecionaMateriasPorAutor(RedirectView): self.logger.debug("user=" + username + ". Tentando obter url.") url = reverse(relatorio_materia_por_autor) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(relatorio_materia_por_autor) url = has_iframe(url, self.request) @@ -750,7 +777,7 @@ class RedirecionaMateriasPorAnoAutorTipo(RedirectView): logger = logging.getLogger(__name__) def get_redirect_url(self): - + url = EMPTY_STRING ano = self.request.GET.get('ano', '') username = self.request.user.username @@ -758,7 +785,8 @@ class RedirecionaMateriasPorAnoAutorTipo(RedirectView): self.logger.debug("user=" + username + ". Tentando obter url.") url = reverse(relatorio_materia_por_ano_autor_tipo) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(relatorio_materia_por_ano_autor_tipo) if ano: @@ -776,7 +804,7 @@ class RedirecionaReuniao(RedirectView): logger = logging.getLogger(__name__) def get_redirect_url(self): - + pk_reuniao = self.request.GET.get( 'cod_comissao', EMPTY_STRING) @@ -785,10 +813,12 @@ class RedirecionaReuniao(RedirectView): if pk_reuniao: kwargs = {'pk': pk_reuniao} try: - self.logger.debug("user=" + username + ". Tentando obter url correspondente (pk={}).".format(kwargs['pk'])) + self.logger.debug( + "user=" + username + ". Tentando obter url correspondente (pk={}).".format(kwargs['pk'])) url = reverse(reuniao_detail, kwargs=kwargs) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(reuniao_detail) else: @@ -796,7 +826,8 @@ class RedirecionaReuniao(RedirectView): self.logger.debug("user=" + username + ". Tentando obter url.") url = reverse(reuniao_list) except NoReverseMatch as e: - self.logger.error("user=" + username + ". Erro ao obter url. " + str(e)) + self.logger.error("user=" + username + + ". Erro ao obter url. " + str(e)) raise UnknownUrlNameError(reuniao_list) year = self.request.GET.get( diff --git a/sapl/settings.py b/sapl/settings.py index 7fdc64adc..004a9d104 100644 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -196,6 +196,7 @@ TEMPLATES = [ 'sapl.context_processors.parliament_info', 'sapl.context_processors.mail_service_configured', 'sapl.context_processors.google_recaptcha_configured', + 'sapl.context_processors.sapl_as_sapn', ], 'debug': DEBUG diff --git a/sapl/templates/base.html b/sapl/templates/base.html index bfc59498c..db7f79f3a 100644 --- a/sapl/templates/base.html +++ b/sapl/templates/base.html @@ -34,83 +34,96 @@
- {% if not request|has_iframe %} - {% block navigation %} - - {% endblock navigation %} + {% endif %} + - {# Header #} - {% block main_header %} -
+
+ + + {% endblock navigation %} + {% else %} +
+ +
+
+
+
+ {% subnav %} +
+
+
+ {% endif %} + {% else %}
- -
- {% block sections_nav %} {% subnav %} {% endblock sections_nav %} +
+ + {% if sapl_as_sapn and not user.is_authenticated%} + Acessar + {% endif %}
- - {% endblock main_header %} - {% else %} -
- -
-
-
-
- {% subnav %} -
-
-
+ {% endif %} + {% if not request|has_iframe %} + {# Header #} + {% block main_header %} +
+ +
+ {% endblock main_header %} {% endif %} {# Main content #} @@ -205,6 +218,7 @@
{% trans 'Site' %} | + {% else %} @@ -214,6 +228,9 @@ Favor configurar clicando aqui {% endif %} {% endif %} + + +
@@ -226,7 +243,7 @@ {% block webpack_loader_js %} {% render_chunk_vendors 'js' %} - {% render_bundle 'global' 'js' %} + {% render_bundle 'global' 'js' %} {% endblock webpack_loader_js %} {% block webpack_loader_chunks_js %} diff --git a/sapl/templates/base/layouts.yaml b/sapl/templates/base/layouts.yaml index d3e0a943b..143e351e0 100644 --- a/sapl/templates/base/layouts.yaml +++ b/sapl/templates/base/layouts.yaml @@ -13,8 +13,7 @@ CasaLegislativa: AppConfig: {% trans 'Configurações Gerais' %}: - - esfera_federacao - - documentos_administrativos + - esfera_federacao documentos_administrativos sapl_as_sapn #{% trans 'Módulo Parlamentares' %}: diff --git a/sapl/templates/compilacao/subnav.html b/sapl/templates/compilacao/subnav.html index 72c90749c..611e71199 100644 --- a/sapl/templates/compilacao/subnav.html +++ b/sapl/templates/compilacao/subnav.html @@ -4,7 +4,9 @@