Browse Source

Fix #2877 - Possibilidade de um Autor possuir múltiplos usuários (#2962)

* Fix #2877 - Possibilidade de múltiplos usuários por autor

* Permite adição e remoção da relação autor-user na tela de Autor

* Remove campo user do model Autor e retira referências a este campo

* Fix testes em matéria

* Corrige formulário antigo de Autor

* Reduz migrations e corrige bugs

* Remove comentários

* Fix migrations

* Remove Crud desnecessário

* Update sapl/base/models.py

Co-Authored-By: Edward <9326037+edwardoliveira@users.noreply.github.com>
pull/3009/head
Cesar Augusto de Carvalho 5 years ago
committed by Edward
parent
commit
6a139b79c7
  1. 2
      sapl/api/views.py
  2. 255
      sapl/base/forms.py
  3. 56
      sapl/base/migrations/0039_auto_20190913_1228.py
  4. 30
      sapl/base/models.py
  5. 9
      sapl/base/urls.py
  6. 52
      sapl/base/views.py
  7. 14
      sapl/materia/tests/test_materia.py
  8. 16
      sapl/materia/views.py
  9. 1
      sapl/rules/map_rules.py
  10. 2
      sapl/templates/base.html
  11. 62
      sapl/templates/base/autor_detail.html
  12. 2
      sapl/templates/base/autoruser_form.html
  13. 7
      sapl/templates/base/layouts.yaml

2
sapl/api/views.py

@ -383,7 +383,7 @@ class _ProposicaoViewSet():
q = Q(data_recebimento__isnull=False, object_id__isnull=False)
if not self.request.user.is_anonymous():
q |= Q(autor__user=self.request.user)
q |= Q(autor__autoruser__user=self.request.user)
qs = qs.filter(q)
return qs

255
sapl/base/forms.py

@ -10,10 +10,10 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.forms import (AuthenticationForm, PasswordResetForm,
SetPasswordForm)
from django.contrib.auth.models import Group, User
from django.core.exceptions import ValidationError
from django.core.exceptions import ValidationError, ObjectDoesNotExist
from django.db import models, transaction
from django.db.models import Q
from django.forms import Form, ModelForm
from django.forms import Form, ModelForm, widgets
from django.utils import timezone
from django.utils.translation import string_concat
from django.utils.translation import ugettext_lazy as _
@ -38,7 +38,7 @@ from sapl.utils import (autor_label, autor_modal, ChoiceWithoutValidationField,
ImageThumbnailFileInput, models_with_gr_for_model,
qs_override_django_filter, RangeWidgetOverride,
RANGE_ANOS, YES_NO_CHOICES, AnoNumeroOrderingFilter)
from .models import AppConfig, CasaLegislativa
from .models import AppConfig, CasaLegislativa, AutorUser
from operator import xor
@ -411,11 +411,6 @@ class AutorForm(ModelForm):
required=False,
label=_('Confirmar Email'))
username = forms.CharField(label=get_user_model()._meta.get_field(
get_user_model().USERNAME_FIELD).verbose_name.capitalize(),
required=False,
max_length=50)
q = forms.CharField(
max_length=50, required=False,
label='Pesquise o nome do Autor com o '
@ -425,11 +420,6 @@ class AutorForm(ModelForm):
required=False,
widget=forms.RadioSelect())
action_user = forms.ChoiceField(
label=_('Usuário com acesso ao Sistema para este Autor'),
choices=ACTION_CREATE_USERS_AUTOR_CHOICE,
widget=forms.RadioSelect())
class Meta:
model = Autor
fields = ['tipo',
@ -437,8 +427,7 @@ class AutorForm(ModelForm):
'cargo',
'autor_related',
'q',
'action_user',
'username']
]
def __init__(self, *args, **kwargs):
@ -465,33 +454,10 @@ class AutorForm(ModelForm):
css_class='radiogroup-autor-related hidden'),
12)))
row2 = Row(to_column((InlineRadios('action_user'), 8)),
to_column((Div('username'), 4)))
row3 = Row(to_column(('senha', 3)),
to_column(('senha_confirma', 3)),
to_column(('email', 3)),
to_column(('confirma_email', 3)),
css_class='new_user_fields hidden')
row4 = Row(to_column((
Div(InlineRadios('status_user'),
css_class='radiogroup-status hidden'),
12))) if 'status_user' in self.Meta.fields else None
controle_acesso = [row2, row3]
if row4:
controle_acesso.append(row4)
controle_acesso = Fieldset(_('Controle de Acesso do Autor'),
*controle_acesso)
self.helper = SaplFormHelper()
self.helper.layout = SaplFormLayout(autor_select, controle_acesso)
super(AutorForm, self).__init__(*args, **kwargs)
self.helper.layout = SaplFormLayout(autor_select)
self.fields['action_user'].initial = 'N'
super().__init__(*args, **kwargs)
if self.instance.pk:
if self.instance.autor_related:
@ -502,39 +468,7 @@ class AutorForm(ModelForm):
self.fields['q'].initial = ''
self.fields['autor_related'].initial = self.instance.autor_related
if self.instance.user:
self.fields['username'].initial = getattr(
self.instance.user,
get_user_model().USERNAME_FIELD)
self.fields['action_user'].initial = 'A'
self.fields['username'].label = string_concat(
self.fields['username'].label,
' (', getattr(
self.instance.user,
get_user_model().USERNAME_FIELD), ')')
if 'status_user' in self.Meta.fields:
self.fields['status_user'].initial = 'R'
self.fields['status_user'].label = string_concat(
self.fields['status_user'].label,
' (', getattr(
self.instance.user,
get_user_model().USERNAME_FIELD), ')')
self.fields['username'].widget.attrs.update({
'data': getattr(
self.instance.user,
get_user_model().USERNAME_FIELD)
if self.instance.user else ''})
if 'status_user' in self.Meta.fields:
self.fields['status_user'].widget.attrs.update({
'data': getattr(
self.instance.user,
get_user_model().USERNAME_FIELD)
if self.instance.user else ''})
def valida_igualdade(self, texto1, texto2, msg):
if texto1 != texto2:
@ -544,66 +478,17 @@ class AutorForm(ModelForm):
return True
def clean(self):
super(AutorForm, self).clean()
super().clean()
if not self.is_valid():
return self.cleaned_data
User = get_user_model()
cd = self.cleaned_data
if 'action_user' not in cd or not cd['action_user']:
self.logger.error('Não Informado se o Autor terá usuário '
'vinculado para acesso ao Sistema.')
raise ValidationError(_('Informe se o Autor terá usuário '
'vinculado para acesso ao Sistema.'))
if 'status_user' in self.Meta.fields:
if self.instance.pk and self.instance.user_id:
if getattr(
self.instance.user,
get_user_model().USERNAME_FIELD) != cd['username']:
if 'status_user' not in cd or not cd['status_user']:
self.logger.error('Foi trocado ou removido o usuário deste Autor ({}), '
'mas não foi informado como se deve proceder '
'com o usuário que está sendo desvinculado? ({})'
.format(cd['username'], get_user_model().USERNAME_FIELD))
raise ValidationError(
_('Foi trocado ou removido o usuário deste Autor, '
'mas não foi informado como se deve proceder '
'com o usuário que está sendo desvinculado?'))
qs_user = User.objects.all()
qs_autor = Autor.objects.all()
if self.instance.pk:
qs_autor = qs_autor.exclude(pk=self.instance.pk)
if self.instance.user:
qs_user = qs_user.exclude(pk=self.instance.user.pk)
if cd['action_user'] == 'A':
param_username = {get_user_model().USERNAME_FIELD: cd['username']}
if not User.objects.filter(**param_username).exists():
self.logger.error(
'Não existe usuário com username "%s". ' % cd['username'])
raise ValidationError(
_('Não existe usuário com username "%s". '
'Para utilizar esse username você deve selecionar '
'"Criar novo Usuário".') % cd['username'])
if cd['action_user'] != 'N':
if 'username' not in cd or not cd['username']:
self.logger.error('Username não informado.')
raise ValidationError(_('O username deve ser informado.'))
param_username = {
'user__' + get_user_model().USERNAME_FIELD: cd['username']}
if qs_autor.filter(**param_username).exists():
self.logger.error(
'Já existe um Autor para este usuário ({}).'.format(cd['username']))
raise ValidationError(
_('Já existe um usuário vinculado a esse autor'))
"""
'if' não é necessário por ser campo obrigatório e o framework
@ -657,20 +542,7 @@ class AutorForm(ModelForm):
@transaction.atomic
def save(self, commit=False):
autor = super(AutorForm, self).save(commit)
user_old = autor.user if autor.user_id else None
u = None
param_username = {
get_user_model().USERNAME_FIELD: self.cleaned_data['username']}
if self.cleaned_data['action_user'] == 'A':
u = get_user_model().objects.get(**param_username)
if not u.is_active:
u.is_active = settings.DEBUG
u.save()
autor.user = u
autor = super().save(commit)
if not autor.tipo.content_type:
autor.content_type = None
@ -683,32 +555,6 @@ class AutorForm(ModelForm):
autor.save()
# FIXME melhorar captura de grupo de Autor, levando em conta,
# no mínimo, a tradução.
grupo = Group.objects.filter(name='Autor')[0]
if self.cleaned_data['action_user'] != 'N':
autor.user.groups.add(grupo)
if user_old and user_old != autor.user:
user_old.groups.remove(grupo)
else:
if 'status_user' in self.Meta.fields:
if 'status_user' in self.cleaned_data and user_old:
if self.cleaned_data['status_user'] == 'X':
user_old.delete()
elif self.cleaned_data['status_user'] == 'D':
user_old.groups.remove(grupo)
user_old.is_active = False
user_old.save()
elif self.cleaned_data['status_user'] == 'R':
user_old.groups.remove(grupo)
elif user_old:
user_old.groups.remove(grupo)
elif user_old:
user_old.groups.remove(grupo)
return autor
@ -729,9 +575,7 @@ class AutorFormForAdmin(AutorForm):
'cargo',
'autor_related',
'q',
'action_user',
'username',
'status_user']
]
class RelatorioDocumentosAcessoriosFilterSet(django_filters.FilterSet):
@ -747,9 +591,7 @@ class RelatorioDocumentosAcessoriosFilterSet(django_filters.FilterSet):
def __init__(self, *args, **kwargs):
super(
RelatorioDocumentosAcessoriosFilterSet, self
).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self.filters['tipo'].label = 'Tipo de Documento'
self.filters['materia__tipo'].label = 'Tipo de Matéria do Documento'
@ -1883,3 +1725,74 @@ class RelatorioNormasPorAutorFilterSet(django_filters.FilterSet):
row3,
form_actions(label='Pesquisar'))
)
class AutorUserForm(ModelForm):
username = forms.CharField(label=get_user_model()._meta.get_field(
get_user_model().USERNAME_FIELD).verbose_name.capitalize(),
required=True,
max_length=50)
nome_autor = forms.CharField(
label='Autor',
widget=widgets.TextInput(attrs={'readonly': 'readonly'})
)
class Meta:
model = AutorUser
exclude = ['user']
widgets = {
'autor': forms.HiddenInput(),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
row1 = to_row(
[('nome_autor', 6),('username', 6),])
row2 = to_row(
[('autor', 6)]
)
actions = [HTML('<a href="{{ view.cancel_url }}"'
' class="btn btn-dark">Cancelar</a>')]
self.helper = SaplFormHelper()
self.helper.layout = Layout(
Fieldset(_('Vincular Usuário ao Autor'),
row1, row2,
HTML("&nbsp;"),
form_actions(more=actions)
)
)
def clean(self):
cd = super().clean()
if not self.is_valid():
return cd
username = cd['username']
try:
user = User.objects.get(username=username)
except ObjectDoesNotExist as e:
raise ValidationError("Este usuário não existe.")
if AutorUser.objects.filter(user=user).exists():
raise ValidationError("Este usuário ({}) já está vinculado a um Autor ({}).".format(
username, AutorUser.objects.get(user=user).autor))
def save(self):
cd = self.cleaned_data
user = User.objects.get(username=cd['username'])
autor = cd['autor']
autor_user = AutorUser.objects.create(autor=autor, user=user)
# FIXME melhorar captura de grupo de Autor, levando em conta,
# no mínimo, a tradução.
grupo = Group.objects.filter(name='Autor')[0]
user.groups.add(grupo)
return autor_user

56
sapl/base/migrations/0039_auto_20190913_1228.py

@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-09-13 15:28
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
def migra_autores_usuarios(apps, schema_editor):
Autor = apps.get_model('base', 'Autor')
AutorUser = apps.get_model('base', 'AutorUser')
for a in Autor.objects.filter(user__isnull=False):
AutorUser.objects.create(autor=a, user=a.user)
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('base', '0038_auto_20190604_1109'),
]
operations = [
migrations.CreateModel(
name='AutorUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
],
options={
'verbose_name': 'Autor - Usuário',
'verbose_name_plural': 'Autores - Usuários',
'ordering': ('autor__nome',),
},
),
migrations.AlterField(
model_name='autor',
name='cargo',
field=models.CharField(blank=True, max_length=50, verbose_name='Cargo'),
),
migrations.AddField(
model_name='autoruser',
name='autor',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='base.Autor', verbose_name='Autor'),
),
migrations.AddField(
model_name='autoruser',
name='user',
field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='Usuário'),
),
migrations.RunPython(migra_autores_usuarios),
migrations.RemoveField(
model_name='autor',
name='user',
)
]

30
sapl/base/models.py

@ -212,10 +212,6 @@ class TipoAutor(models.Model):
@reversion.register()
class Autor(models.Model):
user = models.OneToOneField(get_settings_auth_user_model(),
on_delete=models.SET_NULL,
null=True)
tipo = models.ForeignKey(TipoAutor, verbose_name=_('Tipo do Autor'),
on_delete=models.PROTECT)
@ -229,7 +225,7 @@ class Autor(models.Model):
nome = models.CharField(
max_length=120, blank=True, verbose_name=_('Nome do Autor'))
cargo = models.CharField(max_length=50, blank=True)
cargo = models.CharField(max_length=50, blank=True, verbose_name=_('Cargo'))
class Meta:
verbose_name = _('Autor')
@ -246,6 +242,26 @@ class Autor(models.Model):
return '{} - {}'.format(self.nome, self.cargo)
else:
return str(self.nome)
if self.user:
return str(self.user.username)
return '?'
@reversion.register()
class AutorUser(models.Model):
autor = models.ForeignKey(
Autor,
verbose_name=_('Autor'),
on_delete=models.PROTECT
)
user = models.OneToOneField(
get_settings_auth_user_model(),
verbose_name=_('Usuário'),
on_delete=models.PROTECT,
)
class Meta:
verbose_name = _('Autor - Usuário')
verbose_name_plural = _('Autores - Usuários')
ordering = ('autor__nome',)
def __str__(self):
return "%s - %s" % (self.autor, self.user)

9
sapl/base/urls.py

@ -39,7 +39,8 @@ from .views import (AlterarSenha, AppConfigCrud, CasaLegislativaCrud,
ListarLegislaturaInfindavelView, ListarAnexadasCiclicasView,
ListarAnexadosCiclicosView, pesquisa_textual,
RelatorioHistoricoTramitacaoAdmView, RelatorioDocumentosAcessoriosView,
RelatorioNormasPorAutorView)
RelatorioNormasPorAutorView, AutorUserFormView,
deleta_autoruser)
app_name = AppConfig.name
@ -233,5 +234,11 @@ urlpatterns = [
url(r'^(sapl/)?sapl_documentos/props_sapl/logo_casa',
LogotipoView.as_view(), name='logotipo'),
url(r'^sistema/autor/(?P<autor_pk>\d+)/vincular-usuario/create$',
AutorUserFormView.as_view(), name='vincular-usuario-autor'),
url(r'^sistema/deleta-autoruser/$',
deleta_autoruser, name='deleta_autorser'),
] + recuperar_senha + alterar_senha + admin_user + channels_url

52
sapl/base/views.py

@ -76,8 +76,8 @@ from .forms import (AlterarSenhaForm, CasaLegislativaForm,
EstatisticasAcessoNormasForm, UsuarioFilterSet,
RelatorioHistoricoTramitacaoAdmFilterSet,
RelatorioDocumentosAcessoriosFilterSet,
RelatorioNormasPorAutorFilterSet)
from .models import AppConfig, CasaLegislativa
RelatorioNormasPorAutorFilterSet, AutorUserForm)
from .models import AppConfig, CasaLegislativa, AutorUser
def chanel_index(request):
@ -181,7 +181,7 @@ class AutorCrud(CrudAux):
help_topic = 'autor'
class BaseMixin(CrudAux.BaseMixin):
list_field_names = ['tipo', 'nome', 'user']
list_field_names = ['tipo', 'nome']
class DeleteView(CrudAux.DeleteView):
@ -326,6 +326,13 @@ class AutorCrud(CrudAux):
return url_reverse
class DetailView(CrudAux.DetailView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['autor_user'] = AutorUser.objects.filter(autor=context['object'])
return context
class RelatoriosListView(TemplateView):
template_name = 'base/relatorios_list.html'
@ -2266,3 +2273,42 @@ class RelatorioNormasPorAutorView(RelatorioMixin, FilterView):
' - ' + self.request.GET['data_1'])
return context
def deleta_autoruser(request):
pk = int(request.GET['pk'])
autor_user = AutorUser.objects.get(pk=pk)
# FIXME melhorar captura de grupo de Autor, levando em conta,
# no mínimo, a tradução.
grupo = Group.objects.filter(name='Autor')[0]
autor_user.user.groups.remove(grupo)
autor_user.delete()
return JsonResponse({})
class AutorUserFormView(FormView):
form_class = AutorUserForm
template_name = 'base/autoruser_form.html'
def get_initial(self):
initial = super().get_initial()
autor_pk = self.kwargs['autor_pk']
autor = Autor.objects.get(id=autor_pk)
initial['nome_autor'] = autor.nome
initial['autor'] = autor
return initial
def form_valid(self, form):
form.save()
return super().form_valid(form)
@property
def cancel_url(self):
return reverse('sapl.base:autor_detail',
kwargs={'pk': self.kwargs['autor_pk']})
def get_success_url(self):
return reverse('sapl.base:autor_detail',
kwargs={'pk': self.kwargs['autor_pk']})

14
sapl/materia/tests/test_materia.py

@ -7,7 +7,7 @@ from django.db.models import Max
from model_mommy import mommy
import pytest
from sapl.base.models import Autor, TipoAutor, AppConfig
from sapl.base.models import Autor, TipoAutor, AppConfig, AutorUser
from sapl.comissoes.models import Comissao, TipoComissao
from sapl.materia.models import (Anexada, Autoria, DespachoInicial,
DocumentoAcessorio, MateriaLegislativa,
@ -548,10 +548,14 @@ def test_proposicao_submit(admin_client):
autor = mommy.make(
Autor,
user=user,
tipo=tipo_autor,
nome='Autor Teste')
autor_user = mommy.make(
AutorUser,
user=user,
autor=autor)
file_content = 'file_content'
texto = SimpleUploadedFile("file.txt", file_content.encode('UTF-8'))
@ -594,10 +598,14 @@ def test_form_errors_proposicao(admin_client):
autor = mommy.make(
Autor,
user=user,
tipo=tipo_autor,
nome='Autor Teste')
autor_user = mommy.make(
AutorUser,
user=user,
autor=autor)
file_content = 'file_content'
texto = SimpleUploadedFile("file.txt", file_content.encode('UTF-8'))

16
sapl/materia/views.py

@ -112,7 +112,7 @@ def proposicao_texto(request, pk):
if proposicao.texto_original:
if (not proposicao.data_recebimento and
proposicao.autor.user_id != request.user.id):
not proposicao.autor.autoruser_set.filter(user=request.user).exists()):
logger.error("user=" + username + ". Usuário ({}) não tem permissão para acessar o texto original."
.format(request.user.id))
messages.error(request, _(
@ -318,7 +318,7 @@ class ProposicaoTaView(IntegracaoTaView):
proposicao = get_object_or_404(self.model, pk=kwargs['pk'])
if not proposicao.data_envio and\
request.user != proposicao.autor.user:
proposicao.autor.autoruser_set.filter(user=request.user).exists():
raise Http404()
return IntegracaoTaView.get(self, request, *args, **kwargs)
@ -590,7 +590,7 @@ class RetornarProposicao(UpdateView):
"user=" + username + ". Objeto Proposicao com id={} não encontrado.".format(kwargs['pk']))
raise Http404()
if p.autor.user != request.user:
if not p.autor.autoruser_set.filter(user=request.user).exists():
self.logger.error(
"user=" + username + ". Usuário ({}) sem acesso a esta opção.".format(request.user))
messages.error(
@ -732,7 +732,7 @@ class UnidadeTramitacaoCrud(CrudAux):
class ProposicaoCrud(Crud):
model = Proposicao
help_topic = 'proposicao'
container_field = 'autor__user'
container_field = 'autor__autoruser__user'
class BaseMixin(Crud.BaseMixin):
list_field_names = ['data_envio', 'data_recebimento', 'descricao',
@ -896,7 +896,7 @@ class ProposicaoCrud(Crud):
if not self.has_permission():
return self.handle_no_permission()
if p.autor.user != request.user:
if not p.autor.autoruser_set.filter(user=request.user).exists():
if not p.data_envio and not p.data_devolucao:
raise Http404()
@ -1111,9 +1111,9 @@ class ReciboProposicaoView(TemplateView):
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())
prop = Proposicao.objects.get(
id=self.kwargs['pk'])
return prop.autor.autoruser_set.filter(user=self.request.user).exists()
def get_context_data(self, **kwargs):
context = super(ReciboProposicaoView, self).get_context_data(

1
sapl/rules/map_rules.py

@ -234,6 +234,7 @@ rules_group_geral = {
[RP_ADD], __perms_publicas__),
(base.TipoAutor, __base__, __perms_publicas__),
(base.Autor, __base__, __perms_publicas__),
(base.AutorUser, __base__, __perms_publicas__),
(protocoloadm.StatusTramitacaoAdministrativo, __base__, set()),
(protocoloadm.TipoDocumentoAdministrativo, __base__, set()),

2
sapl/templates/base.html

@ -63,7 +63,7 @@
<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><img height="30" width="30" src="{% webpack_static 'img/authenticated.png' %}"><span class="caret"></span></a>
</a>
<ul class="dropdown-menu">
<li class="dropdown-item"><a>{{user.username}}</a></li>
<li class="dropdown-item"><a>{{user.username}} {% if user.autoruser.autor %} ({{user.autoruser.autor}}) {% endif %}</a></li>
{% if 'parlamentares.can_vote' in request.user.get_all_permissions %}
<li class="dropdown-item"><a href="" onclick="window.open('{% url 'sapl.painel:voto_individual' %}','Voto Individual','width=1000, height=800, scrollbars=yes')";>
Votar Matéria

62
sapl/templates/base/autor_detail.html

@ -0,0 +1,62 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% block sub_actions %}
{{block.super}}
<div class="actions btn-group btn-group-sm" role="group">
<a href="{% url 'sapl.base:vincular-usuario-autor' object.pk %}" class="btn btn-outline-primary">Vincular Usuário</a>
</div>
{% endblock sub_actions %}
{% block detail_content %}
{{block.super}}
{% if autor_user %}
<h2 class="legend">Usuários vinculados</h2>
<table class="table table-striped table-hover table-link-ordering">
<thead>
<tr>
<th>Usuário</th>
</tr>
</thead>
<tbody>
{% for au in autor_user %}
<tr>
<td><a href="{% url 'sapl.base:user_edit' au.user.pk %}">{{au.user}}</a></td>
<td>
<button type="button" class="btn btn-danger float-right" onclick='desvincular("{{au.pk}}")'>
Desvincular
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endblock %}
{% block extra_js %}
<script type="text/javascript">
function desvincular(pk){
$.get("{% url 'sapl.base:deleta_autorser' %}",
{
pk: pk
}, function(data, status) {
if(status == "success")
console.log("Usuário desvinculado.");
});
location.reload();
}
$(document).ready(function(){
// Esconde cargo se o mesmo for vazio
if(!$('.form-control-static').last().text())
$('#div_id_cargo').hide();
else
$('#div_id_cargo').show();
})
</script>
{% endblock %}

2
sapl/templates/base/autoruser_form.html

@ -0,0 +1,2 @@
{% extends "crud/form.html" %}
{% load i18n %}

7
sapl/templates/base/layouts.yaml

@ -43,9 +43,12 @@ TipoAutor:
Autor:
{% trans 'Autor' %}:
- tipo:3 nome
- cargo
- tipo:4 nome:4 cargo:4
AutorCreate:
{% trans 'Cadastro de Usuários Autores' %}:
- tipo:3 search_autor
AutorUser:
{% trans 'Autor - Usuário' %}:
- autor:6 user:6
Loading…
Cancel
Save