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

6
sapl/crud/base.py

@ -200,7 +200,6 @@ class PermissionRequiredContainerCrudMixin(PermissionRequiredMixin):
container = self.container_field.split('__')
if len(container) > 1:
# TODO: implementar caso o user for o próprio o container
container_model = getattr(
self.model, container[0]).field.related_model
@ -211,9 +210,12 @@ class PermissionRequiredContainerCrudMixin(PermissionRequiredMixin):
if not container_model.objects.filter(**params).exists():
messages.error(
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))
return redirect('/')
else:
# TODO: implementar caso o user for o próprio o container
pass
return super(PermissionRequiredMixin, self).dispatch(
request, *args, **kwargs)

12
sapl/materia/forms.py

@ -858,7 +858,7 @@ class TipoProposicaoForm(ModelForm):
return tipo_proposicao
class ProposicaoCreateForm(forms.ModelForm):
class ProposicaoForm(forms.ModelForm):
TIPO_TEXTO_CHOICE = [
('D', _('Arquivo Digital')),
@ -930,7 +930,15 @@ class ProposicaoCreateForm(forms.ModelForm):
self.helper = FormHelper()
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):
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.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.fields import GenericForeignKey,\
GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models
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.comissoes.models import Comissao
from sapl.compilacao.models import TextoArticulado
from sapl.parlamentares.models import Parlamentar
from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES,
get_settings_auth_user_model,
@ -495,6 +497,9 @@ class Proposicao(models.Model):
verbose_name=_('Texto Original'),
validators=[restringe_tipos_de_arquivo_txt])
texto_articulado = GenericRelation(
TextoArticulado, related_query_name='texto_articulado')
class Meta:
verbose_name = _('Proposição')
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.auth import get_user_model
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.urlresolvers import reverse
from django.db.models import Q
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.template import Context, loader
from django.utils import dateformat, formats
from django.utils.http import urlsafe_base64_decode
from django.utils.translation import ugettext_lazy as _
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)
from sapl.materia import apps
from sapl.materia.forms import AnexadaForm, LegislacaoCitadaForm,\
TipoProposicaoForm, ProposicaoCreateForm
TipoProposicaoForm, ProposicaoForm
from sapl.norma.models import LegislacaoCitada
from sapl.utils import (TURNO_TRAMITACAO_CHOICES, YES_NO_CHOICES, autor_label,
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,
montar_row_autor)
from .forms import (AcessorioEmLoteFilterSet, AcompanhamentoMateriaForm,
ConfirmarProposicaoForm, DocumentoAcessorioForm,
MateriaLegislativaFilterSet,
@ -54,6 +55,7 @@ from .models import (AcompanhamentoMateria, Anexada, Autoria, DespachoInicial,
TipoMateriaLegislativa, TipoProposicao, Tramitacao,
UnidadeTramitacao)
OrigemCrud = Crud.build(Origem, '')
TipoMateriaCrud = CrudAux.build(
@ -326,145 +328,144 @@ class ConfirmarProposicao(PermissionRequiredMixin, CreateView):
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
help_path = ''
container_field = 'autor__user'
class BaseMixin(Crud.BaseMixin):
list_field_names = ['data_envio', 'descricao',
'tipo', 'data_recebimento']
class ListView(Crud.ListView):
ordering = ['-data_envio', 'descricao']
list_field_names = ['data_envio', 'data_recebimento', 'descricao',
'tipo']
def get_rows(self, object_list):
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
class BaseLocalMixin:
form_class = ProposicaoForm
layout_key = None
def get_success_url(self):
tipo_texto = self.request.POST.get('tipo_texto', '')
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_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['subnav_template_name'] = ''
return context
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):
"""
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
help_path = ''
if not self._action_is_valid(request, *args, **kwargs):
return redirect(reverse('sapl.materia:proposicao_detail',
kwargs={'pk': kwargs['pk']}))
return super().get(self, request, *args, **kwargs)
class BaseMixin(Crud.BaseMixin):
list_field_names = ['data_envio', 'descricao',
'tipo', 'data_recebimento']
def post(self, request, *args, **kwargs):
"""if not Proposicao.objects.filter(
pk=kwargs.get('pk'), autor__user=self.autor.user).exists():
raise Http404()"""
class CreateView(Crud.CreateView):
form_class = ProposicaoOldForm
if not self._action_is_valid(request, *args, **kwargs):
return redirect(reverse('sapl.materia:proposicao_detail',
kwargs={'pk': kwargs['pk']}))
return super().post(self, request, *args, **kwargs)
@property
def layout_key(self):
return 'ProposicaoCreate'
class DetailView(BaseLocalMixin, Crud.DetailView):
layout_key = 'Proposicao'
def get_initial(self):
try:
autor_id = Autor.objects.get(user=self.request.user).id
except MultipleObjectsReturned:
msg = _('Este usuário está relacionado a mais de um autor. ' +
'Operação cancelada')
messages.add_message(self.request, messages.ERROR, msg)
return redirect(self.get_success_url())
except ObjectDoesNotExist:
# FIXME: Pensar em uma melhor forma
tipo = TipoAutor.objects.get(name='Externo')
autor_id = Autor.objects.create(
user=self.request.user,
nome=str(self.request.user),
tipo=tipo).id
return {'autor': autor_id}
else:
return {'autor': autor_id}
def get(self, request, *args, **kwargs):
action = request.GET.get('action', '')
if not action:
return Crud.DetailView.get(self, request, *args, **kwargs)
p = Proposicao.objects.get(id=kwargs['pk'])
msg_error = ''
if p:
if action == 'send':
if p.data_envio and p.data_recebimento:
msg_error = _('Proposição já foi enviada e recebida.')
elif p.data_envio:
msg_error = _('Proposição já foi enviada.')
else:
p.data_envio = datetime.now()
p.save()
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):
form_class = ProposicaoOldForm
class UpdateView(BaseLocalMixin, Crud.UpdateView):
def get_initial(self):
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
def _action_is_valid(self, request, *args, **kwargs):
@property
def layout_key(self):
return 'ProposicaoCreate'
proposicao = Proposicao.objects.filter(
id=kwargs['pk']).values_list(
'data_envio', 'data_recebimento')
def has_permission(self):
perms = self.get_permission_required()
if not self.request.user.has_perms(perms):
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. ' +
if proposicao:
if proposicao[0][0] and proposicao[0][1]:
msg = _('Proposição já foi enviada e recebida.'
'Não pode mais ser editada')
messages.add_message(self.request, messages.ERROR, msg)
return False
class DetailView(Crud.DetailView):
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 voltar para edição.')
def has_permission(self):
perms = self.get_permission_required()
if not self.request.user.has_perms(perms):
return False
if proposicao[0][0] or proposicao[0][1]:
messages.error(request, msg)
return False
return True
return (Proposicao.objects.filter(
id=self.kwargs['pk'],
autor__user_id=self.request.user.id).exists())
class CreateView(Crud.CreateView):
def get_context_data(self, **kwargs):
context = CrudDetailView.get_context_data(self, **kwargs)
context = super().get_context_data(**kwargs)
context['subnav_template_name'] = ''
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):
ordering = ['-data_envio', 'descricao']
@ -474,60 +475,17 @@ class ProposicaoOldCrud(Crud):
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")
obj.data_envio = formats.date_format(
obj.data_envio, "DATE_FORMAT")
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")
obj.data_envio = formats.date_format(
obj.data_recebimento, "DATE_FORMAT")
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):
template_name = "materia/recibo_proposicao.html"

2
sapl/settings.py

@ -179,7 +179,7 @@ USE_I18N = True
USE_L10N = False
USE_TZ = True
# DATE_FORMAT = 'N j, Y'
DATE_FORMAT = 'd/m/Y'
DATE_FORMAT = 'd/m/Y H:i'
SHORT_DATE_FORMAT = 'd/m/Y'
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");*/
}
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() {
var $controls = $(this).closest('.controls')
$controls && !$controls.hasClass('controls-radio-checkbox') && $controls.addClass('controls-radio-checkbox')
});
$('[type=radio], [type=checkbox]').each(function() {
var _this = $(this);
var _label = _this.closest('label');
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(){
@ -164,5 +213,6 @@ $(document).ready(function(){
refreshMask();
autorModal();
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 {
padding: 0px;
border: 1px solid #d6e1e5;
@ -142,7 +152,7 @@ h6, .h6 {
.checkbox, .radio, .checkbox-inline, .radio-inline {
margin: 0;
&:hover {
background-color: #d6e1e5;;
background-color: #d6e1e5;
}
}
}
@ -168,6 +178,7 @@ p.control-label {
color: $legend-color;
border: 0;
border-bottom: 1px solid $legend-border-color;
clear: both;
}
// #### 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]').closest('.radio').addClass('checked');
}
}
}).fail(function(data) {
active('nome', atualizar);

23
sapl/templates/crud/detail.html

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

1
sapl/templates/materia/materialegislativa_form.html

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

27
sapl/templates/materia/proposicao_detail.html

@ -2,30 +2,29 @@
{% load i18n %}
{% load common_tags %}
{% block actions %}
{% block editions %}
<div class="actions btn-group pull-right" role="group">
{% 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 %}
<a href="{{ view.delete_url }}" class="btn btn-default">{% trans 'Retornar Proposição Enviada' %}</a>
{% if not object.data_recebimento %}
<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 %}
{% else %}
{% if perms|get_change_perm:view and not object.data_recebimento %}
<a href="{{ view.update_url }}" class="btn btn-default">{% trans 'Enviar/Editar Proposição' %}</a>
{% endif %}
<a href="{{ view.detail_url }}?action=send" class="btn btn-default">{% trans 'Enviar' %}</a>
<a href="{{ view.update_url }}" class="btn btn-default">{% trans 'Editar' %}</a>
<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 %}
</div>
{% endblock actions %}
{% endblock editions %}
{% block extra_msg %}
{% 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 %}
{% endblock extra_msg %}

36
sapl/templates/sessao/presenca_ordemdia.html

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

Loading…
Cancel
Save