Browse Source

Add cadastro de Proposições com encaps para Autor

As funcionalidades de inclusão, edição, exclusão, visualização, envio,
recibo e retorno refatoradas e encapsuladas no container de Autor
pull/752/head
LeandroRoberto 8 years ago
parent
commit
cca4dbfa8c
  1. 106
      sapl/base/views.py
  2. 6
      sapl/crud/base.py
  3. 12
      sapl/materia/forms.py
  4. 7
      sapl/materia/models.py
  5. 288
      sapl/materia/views.py
  6. 2
      sapl/settings.py
  7. 62
      sapl/static/js/app.js
  8. 13
      sapl/static/styles/app.scss
  9. 1
      sapl/templates/base/autor_form.html
  10. 23
      sapl/templates/crud/detail.html
  11. 1
      sapl/templates/materia/materialegislativa_form.html
  12. 27
      sapl/templates/materia/proposicao_detail.html
  13. 36
      sapl/templates/sessao/presenca_ordemdia.html

106
sapl/base/views.py

@ -77,36 +77,33 @@ class AutorCrud(CrudAux):
# FIXME try except - testar envio de emails # FIXME try except - testar envio de emails
pk_autor = self.object.id pk_autor = self.object.id
try: kwargs = {}
kwargs = {} user = self.object.user
user = self.object.user
"""if user.is_active:
if user.is_active: return reverse('sapl.base:autor_detail',
return reverse('sapl.base:autor_detail', kwargs={'pk': pk_autor})"""
kwargs={'pk': pk_autor})
kwargs['token'] = default_token_generator.make_token(user)
kwargs['token'] = default_token_generator.make_token(user) kwargs['uidb64'] = urlsafe_base64_encode(force_bytes(user.pk))
kwargs['uidb64'] = urlsafe_base64_encode(force_bytes(user.pk)) assunto = "SAPL - Confirmação de Conta"
assunto = "SAPL - Confirmação de Conta" full_url = self.request.get_raw_uri()
full_url = self.request.get_raw_uri() url_base = full_url[:full_url.find('sistema') - 1]
url_base = full_url[:full_url.find('sistema') - 1]
mensagem = (
mensagem = ( "Este e-mail foi utilizado para fazer cadastro no " +
"Este e-mail foi utilizado para fazer cadastro no " + "SAPL com o perfil de Autor. Agora você pode " +
"SAPL com o perfil de Autor. Agora você pode " + "criar/editar/enviar Proposições.\n" +
"criar/editar/enviar Proposições.\n" + "Seu nome de usuário é: " +
"Seu nome de usuário é: " + self.request.POST['username'] + "\n"
self.request.POST['username'] + "\n" "Caso você não tenha feito este cadastro, por favor " +
"Caso você não tenha feito este cadastro, por favor " + "ignore esta mensagem. Caso tenha, clique " +
"ignore esta mensagem. Caso tenha, clique " + "no link abaixo\n" + url_base +
"no link abaixo\n" + url_base + reverse('sapl.materia:confirmar_email', kwargs=kwargs))
reverse('sapl.materia:confirmar_email', kwargs=kwargs)) remetente = [settings.EMAIL_SEND_USER]
remetente = [settings.EMAIL_SEND_USER] destinatario = [user.email]
destinatario = [user.email] send_mail(assunto, mensagem, remetente, destinatario,
send_mail(assunto, mensagem, remetente, destinatario, fail_silently=False)
fail_silently=False)
except:
pass
return reverse('sapl.base:autor_detail', return reverse('sapl.base:autor_detail',
kwargs={'pk': pk_autor}) kwargs={'pk': pk_autor})
@ -121,32 +118,29 @@ class AutorCrud(CrudAux):
def get_success_url(self): def get_success_url(self):
pk_autor = self.object.id pk_autor = self.object.id
try: # FIXME try except - testar envio de emails
# FIXME try except - testar envio de emails kwargs = {}
kwargs = {} user = self.object.user
user = self.object.user kwargs['token'] = default_token_generator.make_token(user)
kwargs['token'] = default_token_generator.make_token(user) kwargs['uidb64'] = urlsafe_base64_encode(force_bytes(user.pk))
kwargs['uidb64'] = urlsafe_base64_encode(force_bytes(user.pk)) assunto = "SAPL - Confirmação de Conta"
assunto = "SAPL - Confirmação de Conta" full_url = self.request.get_raw_uri()
full_url = self.request.get_raw_uri() url_base = full_url[:full_url.find('sistema') - 1]
url_base = full_url[:full_url.find('sistema') - 1]
mensagem = (
mensagem = ( "Este e-mail foi utilizado para fazer cadastro no " +
"Este e-mail foi utilizado para fazer cadastro no " + "SAPL com o perfil de Autor. Agora você pode " +
"SAPL com o perfil de Autor. Agora você pode " + "criar/editar/enviar Proposições.\n" +
"criar/editar/enviar Proposições.\n" + "Seu nome de usuário é: " +
"Seu nome de usuário é: " + self.request.POST['username'] + "\n"
self.request.POST['username'] + "\n" "Caso você não tenha feito este cadastro, por favor " +
"Caso você não tenha feito este cadastro, por favor " + "ignore esta mensagem. Caso tenha, clique " +
"ignore esta mensagem. Caso tenha, clique " + "no link abaixo\n" + url_base +
"no link abaixo\n" + url_base + reverse('sapl.materia:confirmar_email', kwargs=kwargs))
reverse('sapl.materia:confirmar_email', kwargs=kwargs)) remetente = settings.EMAIL_SEND_USER
remetente = settings.EMAIL_SEND_USER destinatario = [user.email]
destinatario = [user.email] send_mail(assunto, mensagem, remetente, destinatario,
send_mail(assunto, mensagem, remetente, destinatario, fail_silently=False)
fail_silently=False)
except:
pass
return reverse('sapl.base:autor_detail', return reverse('sapl.base:autor_detail',
kwargs={'pk': pk_autor}) kwargs={'pk': pk_autor})

6
sapl/crud/base.py

@ -200,7 +200,6 @@ class PermissionRequiredContainerCrudMixin(PermissionRequiredMixin):
container = self.container_field.split('__') container = self.container_field.split('__')
if len(container) > 1: if len(container) > 1:
# TODO: implementar caso o user for o próprio o container
container_model = getattr( container_model = getattr(
self.model, container[0]).field.related_model self.model, container[0]).field.related_model
@ -211,9 +210,12 @@ class PermissionRequiredContainerCrudMixin(PermissionRequiredMixin):
if not container_model.objects.filter(**params).exists(): if not container_model.objects.filter(**params).exists():
messages.error( messages.error(
request, request,
'O Usuário (%s) não possui registro de %s.' % ( 'O Usuário (%s) não está registrado como (%s).' % (
request.user, container_model._meta.verbose_name)) request.user, container_model._meta.verbose_name))
return redirect('/') return redirect('/')
else:
# TODO: implementar caso o user for o próprio o container
pass
return super(PermissionRequiredMixin, self).dispatch( return super(PermissionRequiredMixin, self).dispatch(
request, *args, **kwargs) request, *args, **kwargs)

12
sapl/materia/forms.py

@ -858,7 +858,7 @@ class TipoProposicaoForm(ModelForm):
return tipo_proposicao return tipo_proposicao
class ProposicaoCreateForm(forms.ModelForm): class ProposicaoForm(forms.ModelForm):
TIPO_TEXTO_CHOICE = [ TIPO_TEXTO_CHOICE = [
('D', _('Arquivo Digital')), ('D', _('Arquivo Digital')),
@ -930,7 +930,15 @@ class ProposicaoCreateForm(forms.ModelForm):
self.helper = FormHelper() self.helper = FormHelper()
self.helper.layout = SaplFormLayout(*fields) self.helper.layout = SaplFormLayout(*fields)
super(ProposicaoCreateForm, self).__init__(*args, **kwargs) super(ProposicaoForm, self).__init__(*args, **kwargs)
if self.instance.pk:
if self.texto_articulado_proposicao:
self.fields['tipo_texto'].initial = []
if self.instance.texto_original:
self.fields['tipo_texto'].initial.append('D')
if self.instance.texto_articulado:
self.fields['tipo_texto'].initial.append('T')
def clean_texto_original(self): def clean_texto_original(self):
texto_original = self.cleaned_data.get('texto_original', False) texto_original = self.cleaned_data.get('texto_original', False)

7
sapl/materia/models.py

@ -1,5 +1,6 @@
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey,\
GenericRelation
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -7,6 +8,7 @@ from model_utils import Choices
from sapl.base.models import Autor from sapl.base.models import Autor
from sapl.comissoes.models import Comissao from sapl.comissoes.models import Comissao
from sapl.compilacao.models import TextoArticulado
from sapl.parlamentares.models import Parlamentar from sapl.parlamentares.models import Parlamentar
from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES,
get_settings_auth_user_model, get_settings_auth_user_model,
@ -495,6 +497,9 @@ class Proposicao(models.Model):
verbose_name=_('Texto Original'), verbose_name=_('Texto Original'),
validators=[restringe_tipos_de_arquivo_txt]) validators=[restringe_tipos_de_arquivo_txt])
texto_articulado = GenericRelation(
TextoArticulado, related_query_name='texto_articulado')
class Meta: class Meta:
verbose_name = _('Proposição') verbose_name = _('Proposição')
verbose_name_plural = _('Proposições') verbose_name_plural = _('Proposições')

288
sapl/materia/views.py

@ -7,14 +7,16 @@ from crispy_forms.layout import HTML
from django.contrib import messages from django.contrib import messages
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist,\
PermissionDenied
from django.core.mail import send_mail from django.core.mail import send_mail
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db.models import Q from django.db.models import Q
from django.http import JsonResponse from django.http import JsonResponse
from django.http.response import HttpResponseRedirect from django.http.response import HttpResponseRedirect, Http404
from django.shortcuts import redirect from django.shortcuts import redirect
from django.template import Context, loader from django.template import Context, loader
from django.utils import dateformat, formats
from django.utils.http import urlsafe_base64_decode from django.utils.http import urlsafe_base64_decode
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.views.generic import CreateView, ListView, TemplateView, UpdateView from django.views.generic import CreateView, ListView, TemplateView, UpdateView
@ -30,7 +32,7 @@ from sapl.crud.base import (ACTION_CREATE, ACTION_DELETE, ACTION_DETAIL,
make_pagination) make_pagination)
from sapl.materia import apps from sapl.materia import apps
from sapl.materia.forms import AnexadaForm, LegislacaoCitadaForm,\ from sapl.materia.forms import AnexadaForm, LegislacaoCitadaForm,\
TipoProposicaoForm, ProposicaoCreateForm TipoProposicaoForm, ProposicaoForm
from sapl.norma.models import LegislacaoCitada from sapl.norma.models import LegislacaoCitada
from sapl.utils import (TURNO_TRAMITACAO_CHOICES, YES_NO_CHOICES, autor_label, from sapl.utils import (TURNO_TRAMITACAO_CHOICES, YES_NO_CHOICES, autor_label,
autor_modal, gerar_hash_arquivo, get_base_url, autor_modal, gerar_hash_arquivo, get_base_url,
@ -38,7 +40,6 @@ from sapl.utils import (TURNO_TRAMITACAO_CHOICES, YES_NO_CHOICES, autor_label,
permissoes_protocoloadm, permission_required_for_app, permissoes_protocoloadm, permission_required_for_app,
montar_row_autor) montar_row_autor)
from .forms import (AcessorioEmLoteFilterSet, AcompanhamentoMateriaForm, from .forms import (AcessorioEmLoteFilterSet, AcompanhamentoMateriaForm,
ConfirmarProposicaoForm, DocumentoAcessorioForm, ConfirmarProposicaoForm, DocumentoAcessorioForm,
MateriaLegislativaFilterSet, MateriaLegislativaFilterSet,
@ -54,6 +55,7 @@ from .models import (AcompanhamentoMateria, Anexada, Autoria, DespachoInicial,
TipoMateriaLegislativa, TipoProposicao, Tramitacao, TipoMateriaLegislativa, TipoProposicao, Tramitacao,
UnidadeTramitacao) UnidadeTramitacao)
OrigemCrud = Crud.build(Origem, '') OrigemCrud = Crud.build(Origem, '')
TipoMateriaCrud = CrudAux.build( TipoMateriaCrud = CrudAux.build(
@ -326,145 +328,144 @@ class ConfirmarProposicao(PermissionRequiredMixin, CreateView):
class ProposicaoCrud(Crud): class ProposicaoCrud(Crud):
"""
TODO: Entre outros comportamento gerais, mesmo que um usuário tenha
Perfil de Autor o Crud de proposição não deverá permitir acesso a
proposições. O acesso deve ser permitido se existe um Autor registrado
e vinculado ao usuário. Essa tarefa deve ser realizada nas Tabelas Aux.
"""
model = Proposicao model = Proposicao
help_path = '' help_path = ''
container_field = 'autor__user' container_field = 'autor__user'
class BaseMixin(Crud.BaseMixin): class BaseMixin(Crud.BaseMixin):
list_field_names = ['data_envio', 'descricao', list_field_names = ['data_envio', 'data_recebimento', 'descricao',
'tipo', 'data_recebimento'] 'tipo']
class ListView(Crud.ListView):
ordering = ['-data_envio', 'descricao']
def get_rows(self, object_list): class BaseLocalMixin:
form_class = ProposicaoForm
for obj in object_list:
if obj.data_envio is None:
obj.data_envio = 'Em elaboração...'
else:
obj.data_envio = obj.data_envio.strftime("%d/%m/%Y %H:%M")
if obj.data_recebimento is None:
obj.data_recebimento = 'Não recebida'
else:
obj.data_recebimento = obj.data_recebimento.strftime(
"%d/%m/%Y %H:%M")
return [self._as_row(obj) for obj in object_list]
class CreateView(Crud.CreateView):
form_class = ProposicaoCreateForm
layout_key = None layout_key = None
def get_success_url(self): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
tipo_texto = self.request.POST.get('tipo_texto', '') context['subnav_template_name'] = ''
return context
if tipo_texto != 'T':
return Crud.CreateView.get_success_url(self)
else:
return reverse('sapl.materia:proposicao_ta',
kwargs={'pk': self.object.pk})
def get(self, request, *args, **kwargs):
"""if not Proposicao.objects.filter(
pk=kwargs.get('pk'), autor__user=self.autor.user).exists():
raise Http404()"""
class ProposicaoOldCrud(Crud): if not self._action_is_valid(request, *args, **kwargs):
""" return redirect(reverse('sapl.materia:proposicao_detail',
TODO: Entre outros comportamento gerais, mesmo que um usuário tenha kwargs={'pk': kwargs['pk']}))
Perfil de Autor o Crud de proposição não deverá permitir acesso a return super().get(self, request, *args, **kwargs)
proposições. O acesso deve ser permitido se existe um Autor registrado
e vinculado ao usuário. Essa tarefa deve ser realizada nas Tabelas Aux.
"""
model = Proposicao
help_path = ''
class BaseMixin(Crud.BaseMixin): def post(self, request, *args, **kwargs):
list_field_names = ['data_envio', 'descricao', """if not Proposicao.objects.filter(
'tipo', 'data_recebimento'] pk=kwargs.get('pk'), autor__user=self.autor.user).exists():
raise Http404()"""
class CreateView(Crud.CreateView): if not self._action_is_valid(request, *args, **kwargs):
form_class = ProposicaoOldForm return redirect(reverse('sapl.materia:proposicao_detail',
kwargs={'pk': kwargs['pk']}))
return super().post(self, request, *args, **kwargs)
@property class DetailView(BaseLocalMixin, Crud.DetailView):
def layout_key(self): layout_key = 'Proposicao'
return 'ProposicaoCreate'
def get_initial(self): def get(self, request, *args, **kwargs):
try: action = request.GET.get('action', '')
autor_id = Autor.objects.get(user=self.request.user).id
except MultipleObjectsReturned: if not action:
msg = _('Este usuário está relacionado a mais de um autor. ' + return Crud.DetailView.get(self, request, *args, **kwargs)
'Operação cancelada')
messages.add_message(self.request, messages.ERROR, msg) p = Proposicao.objects.get(id=kwargs['pk'])
return redirect(self.get_success_url())
except ObjectDoesNotExist: msg_error = ''
# FIXME: Pensar em uma melhor forma if p:
tipo = TipoAutor.objects.get(name='Externo') if action == 'send':
if p.data_envio and p.data_recebimento:
autor_id = Autor.objects.create( msg_error = _('Proposição já foi enviada e recebida.')
user=self.request.user, elif p.data_envio:
nome=str(self.request.user), msg_error = _('Proposição já foi enviada.')
tipo=tipo).id else:
return {'autor': autor_id} p.data_envio = datetime.now()
else: p.save()
return {'autor': autor_id} messages.success(request, _(
'Proposição enviada com sucesso.'))
elif action == 'return':
if not p.data_envio:
msg_error = _('Proposição ainda não foi enviada.')
elif p.data_recebimento:
msg_error = _('Proposição já foi recebida, não é '
'possível retorná-la.')
else:
p.data_envio = None
p.save()
messages.success(request, _(
'Proposição Retornada com sucesso.'))
if msg_error:
messages.error(request, msg_error)
return Crud.DetailView.get(self, request, *args, **kwargs)
class DeleteView(BaseLocalMixin, Crud.DeleteView):
def _action_is_valid(self, request, *args, **kwargs):
proposicao = Proposicao.objects.filter(
id=kwargs['pk']).values_list(
'data_envio', 'data_recebimento')
if proposicao:
if proposicao[0][0] and proposicao[0][1]:
msg = _('Proposição já foi enviada e recebida.'
'Não pode mais ser excluida.')
elif proposicao[0][0] and not proposicao[0][1]:
msg = _('Proposição já foi enviada mas ainda não recebida '
'pelo protocolo. Use a opção Recuperar Proposição '
'para depois excluí-la.')
if proposicao[0][0] or proposicao[0][1]:
messages.error(request, msg)
return False
return True
class UpdateView(Crud.UpdateView): class UpdateView(BaseLocalMixin, Crud.UpdateView):
form_class = ProposicaoOldForm
def get_initial(self): def _action_is_valid(self, request, *args, **kwargs):
initial = self.initial.copy()
if self.object.materia:
initial['tipo_materia'] = self.object.materia.tipo.id
initial['numero_materia'] = self.object.materia.numero
initial['ano_materia'] = self.object.materia.ano
return initial
@property proposicao = Proposicao.objects.filter(
def layout_key(self): id=kwargs['pk']).values_list(
return 'ProposicaoCreate' 'data_envio', 'data_recebimento')
def has_permission(self): if proposicao:
perms = self.get_permission_required() if proposicao[0][0] and proposicao[0][1]:
if not self.request.user.has_perms(perms): msg = _('Proposição já foi enviada e recebida.'
return False
if (Proposicao.objects.filter(
id=self.kwargs['pk'],
autor__user_id=self.request.user.id).exists()):
proposicao = Proposicao.objects.get(
id=self.kwargs['pk'],
autor__user_id=self.request.user.id)
if (not proposicao.data_recebimento or
proposicao.data_devolucao):
return True
else:
msg = _('Essa proposição já foi recebida. ' +
'Não pode mais ser editada') 'Não pode mais ser editada')
messages.add_message(self.request, messages.ERROR, msg) elif proposicao[0][0] and not proposicao[0][1]:
return False msg = _('Proposição já foi enviada mas ainda não recebida '
'pelo protocolo. Use a opção Recuperar Proposição '
class DetailView(Crud.DetailView): 'para voltar para edição.')
def has_permission(self): if proposicao[0][0] or proposicao[0][1]:
perms = self.get_permission_required() messages.error(request, msg)
if not self.request.user.has_perms(perms): return False
return False return True
return (Proposicao.objects.filter( class CreateView(Crud.CreateView):
id=self.kwargs['pk'],
autor__user_id=self.request.user.id).exists())
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = CrudDetailView.get_context_data(self, **kwargs) context = super().get_context_data(**kwargs)
context['subnav_template_name'] = '' context['subnav_template_name'] = ''
return context return context
def get_success_url(self):
tipo_texto = self.request.POST.get('tipo_texto', '')
if tipo_texto == 'T':
return reverse('sapl.materia:proposicao_ta',
kwargs={'pk': self.object.pk})
else:
return Crud.CreateView.get_success_url(self)
class ListView(Crud.ListView): class ListView(Crud.ListView):
ordering = ['-data_envio', 'descricao'] ordering = ['-data_envio', 'descricao']
@ -474,60 +475,17 @@ class ProposicaoOldCrud(Crud):
if obj.data_envio is None: if obj.data_envio is None:
obj.data_envio = 'Em elaboração...' obj.data_envio = 'Em elaboração...'
else: else:
obj.data_envio = obj.data_envio.strftime("%d/%m/%Y %H:%M") obj.data_envio = formats.date_format(
obj.data_envio, "DATE_FORMAT")
if obj.data_recebimento is None: if obj.data_recebimento is None:
obj.data_recebimento = 'Não recebida' obj.data_recebimento = 'Não recebida'
else: else:
obj.data_recebimento = obj.data_recebimento.strftime( obj.data_envio = formats.date_format(
"%d/%m/%Y %H:%M") obj.data_recebimento, "DATE_FORMAT")
return [self._as_row(obj) for obj in object_list] return [self._as_row(obj) for obj in object_list]
def get_queryset(self):
# Só tem acesso as Proposicoes criadas por ele que ainda nao foram
# recebidas ou foram devolvidas
lista = Proposicao.objects.filter(
autor__user_id=self.request.user.id)
lista = lista.filter(
Q(data_recebimento__isnull=True) |
Q(data_devolucao__isnull=False))
return lista
class DeleteView(Crud.DeleteView):
def has_permission(self):
perms = self.get_permission_required()
if not self.request.user.has_perms(perms):
return False
return (Proposicao.objects.filter(
id=self.kwargs['pk'],
autor__user_id=self.request.user.id).exists())
def delete(self, request, *args, **kwargs):
proposicao = Proposicao.objects.get(id=self.kwargs['pk'])
if not proposicao.data_envio or proposicao.data_devolucao:
proposicao.delete()
return HttpResponseRedirect(
reverse('sapl.materia:proposicao_list'))
elif not proposicao.data_recebimento:
proposicao.data_envio = None
proposicao.save()
return HttpResponseRedirect(
reverse('sapl.materia:proposicao_detail',
kwargs={'pk': proposicao.pk}))
else:
msg = _('Essa proposição já foi recebida. ' +
'Não pode mais ser excluída/recuperada')
messages.add_message(self.request, messages.ERROR, msg)
return HttpResponseRedirect(
reverse('sapl.materia:proposicao_detail',
kwargs={'pk': proposicao.pk}))
class ReciboProposicaoView(TemplateView): class ReciboProposicaoView(TemplateView):
template_name = "materia/recibo_proposicao.html" template_name = "materia/recibo_proposicao.html"

2
sapl/settings.py

@ -179,7 +179,7 @@ USE_I18N = True
USE_L10N = False USE_L10N = False
USE_TZ = True USE_TZ = True
# DATE_FORMAT = 'N j, Y' # DATE_FORMAT = 'N j, Y'
DATE_FORMAT = 'd/m/Y' DATE_FORMAT = 'd/m/Y H:i'
SHORT_DATE_FORMAT = 'd/m/Y' SHORT_DATE_FORMAT = 'd/m/Y'
DATE_INPUT_FORMATS = ('%d/%m/%Y', '%m-%d-%Y', '%Y-%m-%d') DATE_INPUT_FORMATS = ('%d/%m/%Y', '%m-%d-%Y', '%Y-%m-%d')

62
sapl/static/js/app.js

@ -150,13 +150,62 @@ function autorModal() {
get_nome_autor("#id_autoria__autor");*/ get_nome_autor("#id_autoria__autor");*/
} }
function OptionalCustomFrontEnd() {
// Adaptações opcionais de layout com a presença de JS.
// Não implementar customizações que a funcionalidade que fique dependente.
var instance;
if (!(this instanceof OptionalCustomFrontEnd)) {
if (!instance) {
instance = new OptionalCustomFrontEnd();
}
return instance;
}
instance = this;
OptionalCustomFrontEnd = function() {
return instance;
}
instance.customCheckBoxAndRadio = function() {
$('[type=radio], [type=checkbox]').each(function() {
var _this = $(this)
var _controls = _this.closest('.controls');
_controls && _controls.find(':file').length == 0 && !_controls.hasClass('controls-radio-checkbox') && _controls.addClass('controls-radio-checkbox');
_controls.find(':file').length > 0 && _controls.addClass('controls-file');
});
}
instance.customCheckBoxAndRadioWithoutLabel = function() {
var customsFront = function() { $('[type=radio], [type=checkbox]').each(function() {
$('[type=radio], [type=checkbox]').each(function() { var _this = $(this);
var $controls = $(this).closest('.controls') var _label = _this.closest('label');
$controls && !$controls.hasClass('controls-radio-checkbox') && $controls.addClass('controls-radio-checkbox')
}); if (_label.length)
return;
if (this.id)
_label = $('label[for='+this.id+']');
else {
_label = $('<label/>').insertBefore(this)
}
if (_label.length) {
/*var _controls = _label.closest('.controls');
if (!_controls.length) {
_controls = $('<div class="controls"/>').insertBefore(_label)
_controls.append(_label)
}*/
_label.addClass('checkbox-inline');
_label.prepend(_this);
_this.checkbox();
}
});
}
instance.init = function() {
this.customCheckBoxAndRadio();
this.customCheckBoxAndRadioWithoutLabel();
}
instance.init();
} }
$(document).ready(function(){ $(document).ready(function(){
@ -164,5 +213,6 @@ $(document).ready(function(){
refreshMask(); refreshMask();
autorModal(); autorModal();
initTinymce("texto-rico"); initTinymce("texto-rico");
customsFront();
OptionalCustomFrontEnd();
}); });

13
sapl/static/styles/app.scss

@ -113,6 +113,16 @@ h6, .h6 {
} }
} }
.controls-file {
padding: 10px;
border: 1px solid #d6e1e5;
border-radius: 4px;
label.checkbox-inline {
margin: 0px;
display: block;
}
}
.controls-radio-checkbox { .controls-radio-checkbox {
padding: 0px; padding: 0px;
border: 1px solid #d6e1e5; border: 1px solid #d6e1e5;
@ -142,7 +152,7 @@ h6, .h6 {
.checkbox, .radio, .checkbox-inline, .radio-inline { .checkbox, .radio, .checkbox-inline, .radio-inline {
margin: 0; margin: 0;
&:hover { &:hover {
background-color: #d6e1e5;; background-color: #d6e1e5;
} }
} }
} }
@ -168,6 +178,7 @@ p.control-label {
color: $legend-color; color: $legend-color;
border: 0; border: 0;
border-bottom: 1px solid $legend-border-color; border-bottom: 1px solid $legend-border-color;
clear: both;
} }
// #### footer ########################################### // #### footer ###########################################

1
sapl/templates/base/autor_form.html

@ -67,7 +67,6 @@ $(document).ready(function(){
$('input[name=autor_related]').prop('checked', 'checked'); $('input[name=autor_related]').prop('checked', 'checked');
$('input[name=autor_related]').closest('.radio').addClass('checked'); $('input[name=autor_related]').closest('.radio').addClass('checked');
} }
} }
}).fail(function(data) { }).fail(function(data) {
active('nome', atualizar); active('nome', atualizar);

23
sapl/templates/crud/detail.html

@ -18,16 +18,19 @@
</a> </a>
{% endif %} {% endif %}
</div> </div>
{% if view.update_url or view.delete_url %} {% block editions %}
<div class="actions btn-group pull-right" role="group"> {% if view.update_url or view.delete_url %}
{% if view.update_url %} <div class="actions btn-group pull-right" role="group">
<a href="{{ view.update_url }}" class="btn btn-default">{% trans 'Editar' %}</a> {% if view.update_url %}
{% endif %} <a href="{{ view.update_url }}" class="btn btn-default">{% trans 'Editar' %}</a>
{% if view.delete_url %} {% endif %}
<a href="{{ view.delete_url }}" class="btn btn-default btn-excluir">{% trans 'Excluir' %}</a> {% if view.delete_url %}
{% endif %} <a href="{{ view.delete_url }}" class="btn btn-default btn-excluir">{% trans 'Excluir' %}</a>
</div> {% endif %}
{% endif %} </div>
{% endif %}
{% endblock %}
{% endblock actions %} {% endblock actions %}
</div> </div>

1
sapl/templates/materia/materialegislativa_form.html

@ -1,3 +1,4 @@
{% extends "crud/form.html" %} {% extends "crud/form.html" %}
{% load i18n %} {% load i18n %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}

27
sapl/templates/materia/proposicao_detail.html

@ -2,30 +2,29 @@
{% load i18n %} {% load i18n %}
{% load common_tags %} {% load common_tags %}
{% block actions %} {% block editions %}
<div class="actions btn-group pull-right" role="group"> <div class="actions btn-group pull-right" role="group">
{% if proposicao.data_envio %} {% if proposicao.data_envio %}
{% if perms|get_change_perm:view and not object.data_recebimento %}
<a href="{{ view.update_url }}" class="btn btn-default">{% trans 'Editar Proposição' %}</a>
{% endif %}
{% if perms|get_delete_perm:view and not object.data_recebimento %} {% if not object.data_recebimento %}
<a href="{{ view.delete_url }}" class="btn btn-default">{% trans 'Retornar Proposição Enviada' %}</a> <a class="btn btn-default" onclick="window.open('{% url 'sapl.materia:recibo-proposicao' object.pk %}','Recibo','width=1100, height=600, scrollbars=yes')">{% trans "Recibo de Envio" %}</a>
<a href="{{ view.detail_url }}?action=return" class="btn btn-default btn-excluir">{% trans 'Retornar Proposição Enviada' %}</a>
{% else %}
<a class="btn btn-default" onclick="window.open('{% url 'sapl.materia:recibo-proposicao' object.pk %}','Recibo','width=1100, height=600, scrollbars=yes')">{% trans "Homologação do Protocolo" %}</a>
{% endif %} {% endif %}
{% else %} {% else %}
{% if perms|get_change_perm:view and not object.data_recebimento %} <a href="{{ view.detail_url }}?action=send" class="btn btn-default">{% trans 'Enviar' %}</a>
<a href="{{ view.update_url }}" class="btn btn-default">{% trans 'Enviar/Editar Proposição' %}</a> <a href="{{ view.update_url }}" class="btn btn-default">{% trans 'Editar' %}</a>
{% endif %} <a href="{{ view.delete_url }}" class="btn btn-default btn-excluir">{% trans 'Excluir' %}</a>
{% if perms|get_delete_perm:view and not object.data_recebimento %}
<a href="{{ view.delete_url }}" class="btn btn-default">{% trans 'Excluir Proposição' %}</a>
{% endif %}
{% endif %} {% endif %}
</div> </div>
{% endblock actions %} {% endblock editions %}
{% block extra_msg %} {% block extra_msg %}
{% if proposicao.data_envio and not proposicao.data_recebimento %} {% if proposicao.data_envio and not proposicao.data_recebimento %}
<b><p align="center"><a href="" onclick="window.open('{% url 'sapl.materia:recibo-proposicao' object.pk %}','Recibo','width=1100, height=600, scrollbars=yes')">[Imprimir Recibo]</a></p></b> <b><p align="center"></p></b>
{% endif %} {% endif %}
{% endblock extra_msg %} {% endblock extra_msg %}

36
sapl/templates/sessao/presenca_ordemdia.html

@ -10,21 +10,25 @@
<form method="POST"> <form method="POST">
{% csrf_token %} {% csrf_token %}
<div class="row"> <div class="controls">
<div class="col-md-6">Presença</div> <div class="checkbox">
<div class="col-md-6">Parlamentar</div> <label for="id_check_all">
</div> <input type="checkbox" id="id_check_all" onchange="checkAll(event)" /> Marcar/Desmarcar Todos
</label>
<div class="row"> </div>
<div class="col-md-12"><input type="checkbox" onClick="checkAll(this)" /> Marcar/Desmarcar Todos</div>
</div> </div>
<br>
<div class="controls">
{% for parlamentar, check in view.get_presencas_ordem %} {% for parlamentar, check in view.get_presencas_ordem %}
<div class="row"> <div class="checkbox">
<div class="col-md-6"><input type="checkbox" name="presenca" value="{{ parlamentar.id }}" {% if check %} checked {% endif %}/></div> <label for="id_presenca_{{forloop.counter}}">
<div class="col-md-6"><label for="parlamentar">{{ parlamentar }}</label></div> <input type="checkbox" id="id_presenca_{{forloop.counter}}" name="presenca" value="{{ parlamentar.id }}" {% if check %} checked {% endif %}/>
</div> {{ parlamentar }}
</label>
</div>
{% endfor %} {% endfor %}
</div>
<br /> <br />
<input type="submit" value="Salvar" class="btn btn-primary" /> <input type="submit" value="Salvar" class="btn btn-primary" />
@ -51,11 +55,11 @@
{% block extra_js %} {% block extra_js %}
<script language="JavaScript"> <script language="JavaScript">
function checkAll(source) { function checkAll(event) {
checkboxes = document.getElementsByName('presenca'); $('[name=presenca]').each(function() {
for(var i=0, n=checkboxes.length;i<n;i++) { $(this).prop('checked', event.target.checked ? 'checked': null);
checkboxes[i].checked = source.checked; $(this).trigger('click');
} });
} }
</script> </script>
{% endblock %} {% endblock %}

Loading…
Cancel
Save