Browse Source

Refatora manutenção de usuário

- elimina view class independentes
- elimina form class independentes
- impl UserCrud e UserAdminForm
pull/3372/head
Leandro Roberto 4 years ago
parent
commit
acd43abf46
  1. 304
      sapl/base/forms.py
  2. 26
      sapl/base/urls.py
  3. 279
      sapl/base/views.py
  4. 2
      sapl/crud/base.py
  5. 51
      sapl/templates/auth/user_filter.html
  6. 35
      sapl/templates/auth/user_form.html
  7. 7
      sapl/templates/base/layouts.yaml
  8. 57
      sapl/templates/base/usuario_detail.html
  9. 20
      sapl/templates/base/usuario_edit.html
  10. 14
      sapl/templates/crud/detail.html
  11. 8
      sapl/templates/crud/list.html
  12. 2
      sapl/templates/materia/materialegislativa_detail.html
  13. 6
      sapl/templates/materia/materialegislativa_filter.html
  14. 2
      sapl/templates/materia/proposicao_detail.html
  15. 6
      sapl/templates/materia/tramitacao_detail.html
  16. 2
      sapl/templates/navbar.yaml
  17. 2
      sapl/templates/norma/normajuridica_detail.html
  18. 2
      sapl/templates/protocoloadm/documentoadministrativo_detail.html
  19. 6
      sapl/templates/protocoloadm/tramitacaoadministrativo_detail.html

304
sapl/base/forms.py

@ -6,10 +6,10 @@ from crispy_forms.bootstrap import FieldWithButtons, InlineRadios, StrictButton,
from crispy_forms.layout import HTML, Button, Div, Field, Fieldset, Layout, Row, Submit
from django import forms
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth import get_user_model, password_validation
from django.contrib.auth.forms import (AuthenticationForm, PasswordResetForm,
SetPasswordForm)
from django.contrib.auth.models import Group, User
from django.contrib.auth.models import Group, User, Permission
from django.core.exceptions import ValidationError
from django.db import models, transaction
from django.db.models import Q
@ -57,206 +57,160 @@ STATUS_USER_CHOICE = [
]
def get_roles():
roles = [(g.id, g.name) for g in Group.objects.all().order_by('name')
if g.name != 'Votante']
return roles
class UserAdminForm(ModelForm):
is_active = forms.TypedChoiceField(label=_('Usuário Ativo'),
choices=YES_NO_CHOICES,
coerce=lambda x: x == 'True')
class UsuarioCreateForm(ModelForm):
logger = logging.getLogger(__name__)
firstname = forms.CharField(
required=True,
label="Nome",
max_length=30
)
lastname = forms.CharField(
required=True,
label="Sobrenome",
max_length=30
)
password1 = forms.CharField(
required=True,
widget=forms.PasswordInput,
label='Senha',
min_length=6,
max_length=128
)
password2 = forms.CharField(
required=True,
widget=forms.PasswordInput,
label='Confirmar senha',
min_length=6,
max_length=128
)
user_active = forms.ChoiceField(
required=True,
choices=YES_NO_CHOICES,
label="Usuário ativo?",
initial='True'
)
roles = forms.MultipleChoiceField(
required=True,
widget=forms.CheckboxSelectMultiple(),
choices=get_roles
)
class Meta:
model = get_user_model()
fields = [
get_user_model().USERNAME_FIELD, 'firstname', 'lastname',
'password1', 'password2', 'user_active', 'roles'
] + (['email']
if get_user_model().USERNAME_FIELD != 'email' else [])
def clean(self):
super().clean()
if not self.is_valid():
return self.cleaned_data
data = self.cleaned_data
if data['password1'] != data['password2']:
self.logger.warning(
'Erro de validação. Senhas informadas são diferentes.')
raise ValidationError('Senhas informadas são diferentes')
return data
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
row0 = to_row([('username', 12)])
row1 = to_row([('firstname', 6),
('lastname', 6)])
row2 = to_row([('email', 6),
('user_active', 6)])
row3 = to_row(
[('password1', 6),
('password2', 6)])
self.helper = SaplFormHelper()
self.helper.layout = Layout(
row0,
row1,
row3,
row2,
'roles',
form_actions(label='Confirmar'))
class UsuarioFilterSet(django_filters.FilterSet):
username = django_filters.CharFilter(
label=_('Nome de Usuário'),
lookup_expr='icontains')
class Meta:
model = User
fields = ['username']
def __init__(self, *args, **kwargs):
super(UsuarioFilterSet, self).__init__(*args, **kwargs)
row0 = to_row([('username', 12)])
self.form.helper = SaplFormHelper()
self.form.helper.form_method = 'GET'
self.form.helper.layout = Layout(
Fieldset(_('Pesquisa de Usuário'),
row0,
form_actions(label='Pesquisar'))
)
new_password1 = forms.CharField(
label='Nova senha',
max_length=50,
strip=False,
required=False,
widget=forms.PasswordInput(),
help_text='Deixe os campos em branco para não fazer alteração de senha')
new_password2 = forms.CharField(
label='Confirmar senha',
max_length=50,
strip=False,
required=False,
widget=forms.PasswordInput(),
help_text='Deixe os campos em branco para não fazer alteração de senha')
class UsuarioEditForm(ModelForm):
logger = logging.getLogger(__name__)
# ROLES = [(g.id, g.name) for g in Group.objects.all().order_by('name')]
ROLES = []
autor = forms.ModelChoiceField(
label=_('Operador de Autor'),
queryset=Autor.objects.all(),
required=False)
token = forms.CharField(
required=False,
label="Token",
max_length=40,
widget=forms.TextInput(attrs={'readonly': 'readonly'}))
first_name = forms.CharField(
required=False,
label="Nome",
max_length=30)
last_name = forms.CharField(
required=False,
label="Sobrenome",
max_length=30)
password1 = forms.CharField(
required=False,
widget=forms.PasswordInput,
label='Senha')
password2 = forms.CharField(
required=False, widget=forms.PasswordInput,
label='Confirmar senha')
user_active = forms.ChoiceField(
choices=YES_NO_CHOICES,
required=True,
label="Usuário ativo?",
initial='True')
roles = forms.MultipleChoiceField(
required=True,
widget=forms.CheckboxSelectMultiple(),
choices=get_roles)
class Meta:
model = get_user_model()
fields = [
get_user_model().USERNAME_FIELD,
"token",
"first_name",
"last_name",
'password1',
'password2',
'user_active',
'roles']
'first_name',
'last_name',
'is_active',
'token',
'new_password1',
'new_password2',
'groups',
'user_permissions'
]
if get_user_model().USERNAME_FIELD != 'email':
fields.extend(['email'])
def __init__(self, *args, **kwargs):
super(UsuarioEditForm, self).__init__(*args, **kwargs)
rows = to_row((
('first_name', 6),
('last_name', 6),
('email', 6),
('user_active', 6),
('password1', 6),
('password2', 6),
('roles', 12)))
self.user_session = kwargs.pop('user_session', None)
self.granular = kwargs.pop('granular', None)
row_pwd = to_row(
[
('username', 4),
('email', 6),
('is_active', 2),
('first_name', 6),
('last_name', 6),
('new_password1', 3),
('new_password2', 3),
(
FieldWithButtons(
'token',
StrictButton(
'Renovar',
id="renovar-token",
css_class="btn-outline-primary")
),
6
),
('groups', 12),
] + ([('user_permissions', 12)] if not self.granular is None else [])
)
self.helper = SaplFormHelper()
self.helper.layout = Layout(
'username',
FieldWithButtons('token', StrictButton(
'Renovar', id="renovar-token", css_class="btn-outline-primary")),
rows,
form_actions(
more=[
HTML("<a href='{% url 'sapl.base:user_detail' object.pk %}' "
"class='btn btn-dark'>Cancelar</a>")],
label='Salvar Alterações'))
self.helper.layout = SaplFormLayout(row_pwd)
super(UserAdminForm, self).__init__(*args, **kwargs)
if self.instance.pk:
self.fields['token'].initial = self.instance.auth_token.key
self.fields[
'groups'].widget = forms.CheckboxSelectMultiple()
self.fields['groups'].choices = [
(g.id, g) for g in self.instance.groups.exclude(name='Votante').order_by('name')
] + [
(g.id, g) for g in Group.objects.exclude(
user=self.instance).exclude(name='Votante').order_by('name')
]
self.fields[
'user_permissions'].widget = forms.CheckboxSelectMultiple()
if not self.granular is None:
self.fields['user_permissions'].choices = [
(p.id, p) for p in self.instance.user_permissions.all(
).order_by('content_type__app_label',
'content_type__model',
'codename')
] + [
(p.id, p) for p in Permission.objects.filter(
content_type__app_label__in=list(
map(lambda x: x.split('.')[-1], settings.SAPL_APPS))
).exclude(
user=self.instance
).order_by('content_type__app_label',
'content_type__model',
'codename')
]
# self.fields['user_permissions'].queryset = self.fields[
# 'user_permissions'].queryset.all().order_by('name')
def save(self, commit=True):
if self.cleaned_data['new_password1']:
self.instance.set_password(self.cleaned_data['new_password1'])
votante = None
if self.instance.id:
inst_old = get_user_model().objects.get(pk=self.instance.pk)
votante = inst_old.groups.filter(name='Votante').first()
inst_new = super().save(commit)
if votante:
inst_new.groups.add(votante)
return inst_new
def clean(self):
super().clean()
if not self.is_valid():
return self.cleaned_data
data = super().clean()
data = self.cleaned_data
if data['password1'] and data['password1'] != data['password2']:
self.logger.warning(
"Erro de validação. Senhas informadas são diferentes.")
raise ValidationError('Senhas informadas são diferentes')
if self.errors:
return data
new_password1 = data.get('new_password1', '')
new_password2 = data.get('new_password2', '')
if new_password1 != new_password2:
raise forms.ValidationError(
_("As senhas informadas são diferentes"),
)
else:
if new_password1 and new_password2:
password_validation.validate_password(
new_password2, self.instance)
return data

26
sapl/base/urls.py

@ -3,22 +3,19 @@ import os
from django.conf.urls import include, url
from django.contrib.auth import views
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.views import (PasswordResetView, PasswordResetCompleteView, PasswordResetConfirmView,
PasswordResetDoneView)
from django.urls.base import reverse_lazy
from django.views.generic.base import RedirectView, TemplateView
from sapl.base.views import (AutorCrud, ConfirmarEmailView, TipoAutorCrud, get_estatistica, DetailUsuarioView,
from sapl.base.views import (AutorCrud, ConfirmarEmailView, TipoAutorCrud, get_estatistica,
PesquisarAutorView, RecuperarSenhaEmailView, RecuperarSenhaFinalizadoView,
RecuperarSenhaConfirmaView, RecuperarSenhaCompletoView, RelatorioMateriaAnoAssuntoView,
IndexView)
from sapl.settings import EMAIL_SEND_USER, MEDIA_URL, LOGOUT_REDIRECT_URL
IndexView, UserCrud)
from sapl.settings import MEDIA_URL, LOGOUT_REDIRECT_URL
from .apps import AppConfig
from .forms import LoginForm, NovaSenhaForm, RecuperarSenhaForm
from .views import (AlterarSenha, AppConfigCrud, CasaLegislativaCrud, CreateUsuarioView, DeleteUsuarioView,
EditUsuarioView, HelpTopicView, PesquisarUsuarioView, LogotipoView, RelatorioAtasView,
from .forms import LoginForm
from .views import (AlterarSenha, AppConfigCrud, CasaLegislativaCrud,
HelpTopicView, LogotipoView, RelatorioAtasView,
RelatorioAudienciaView, RelatorioDataFimPrazoTramitacaoView, RelatorioHistoricoTramitacaoView,
RelatorioMateriasPorAnoAutorTipoView, RelatorioMateriasPorAutorView,
RelatorioMateriasTramitacaoView, RelatorioPresencaSessaoView, RelatorioReuniaoView, SaplSearchView,
@ -35,15 +32,8 @@ from .views import (AlterarSenha, AppConfigCrud, CasaLegislativaCrud, CreateUsua
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<pk>\d+)$',
DetailUsuarioView.as_view(), name='user_detail'),
url(r'^sistema/usuario/(?P<pk>\d+)/edit$',
EditUsuarioView.as_view(), name='user_edit'),
url(r'^sistema/usuario/(?P<pk>\d+)/delete$',
DeleteUsuarioView.as_view(), name='user_delete')
url(r'^sistema/usuario/', include(UserCrud.get_urls())),
]
alterar_senha = [

279
sapl/base/views.py

@ -36,13 +36,14 @@ from rest_framework.authtoken.models import Token
from sapl import settings
from sapl.audiencia.models import AudienciaPublica, TipoAudienciaPublica
from sapl.base.forms import (AutorForm, AutorFormForAdmin, TipoAutorForm, AutorFilterSet, RecuperarSenhaForm,
NovaSenhaForm)
NovaSenhaForm, UserAdminForm)
from sapl.base.models import Autor, TipoAutor
from sapl.comissoes.models import Comissao, Reuniao
from sapl.crud.base import CrudAux, make_pagination
from sapl.crud.base import CrudAux, make_pagination, Crud,\
ListWithSearchForm
from sapl.materia.models import (Anexada, Autoria, DocumentoAcessorio, MateriaEmTramitacao, MateriaLegislativa,
Proposicao, StatusTramitacao, TipoDocumento, TipoMateriaLegislativa, UnidadeTramitacao,
MateriaAssunto, Tramitacao)
MateriaAssunto)
from sapl.norma.models import NormaJuridica, TipoNormaJuridica
from sapl.parlamentares.models import (
Filiacao, Legislatura, Mandato, Parlamentar, SessaoLegislativa)
@ -66,9 +67,9 @@ from .forms import (AlterarSenhaForm, CasaLegislativaForm, ConfiguracoesAppForm,
RelatorioAudienciaFilterSet, RelatorioDataFimPrazoTramitacaoFilterSet,
RelatorioHistoricoTramitacaoFilterSet, RelatorioMateriasPorAnoAutorTipoFilterSet,
RelatorioMateriasPorAutorFilterSet, RelatorioMateriasTramitacaoFilterSet,
RelatorioPresencaSessaoFilterSet, RelatorioReuniaoFilterSet, UsuarioCreateForm, UsuarioEditForm,
RelatorioPresencaSessaoFilterSet, RelatorioReuniaoFilterSet,
RelatorioNormasMesFilterSet, RelatorioNormasVigenciaFilterSet, EstatisticasAcessoNormasForm,
UsuarioFilterSet, RelatorioHistoricoTramitacaoAdmFilterSet, RelatorioDocumentosAcessoriosFilterSet,
RelatorioHistoricoTramitacaoAdmFilterSet, RelatorioDocumentosAcessoriosFilterSet,
RelatorioNormasPorAutorFilterSet)
from .models import AppConfig, CasaLegislativa
@ -1936,208 +1937,118 @@ class ListarProtocolosDuplicadosView(PermissionRequiredMixin, ListView):
return context
class PesquisarUsuarioView(PermissionRequiredMixin, FilterView):
class UserCrud(Crud):
model = get_user_model()
filterset_class = UsuarioFilterSet
permission_required = ('base.list_appconfig',)
paginate_by = 10
def get_filterset_kwargs(self, filterset_class):
super(PesquisarUsuarioView,
self).get_filterset_kwargs(filterset_class)
kwargs = {'data': self.request.GET or None}
qs = self.get_queryset().order_by('username').distinct()
kwargs.update({
'queryset': qs,
})
return kwargs
def get_context_data(self, **kwargs):
context = super(PesquisarUsuarioView, self).get_context_data(**kwargs)
paginator = context['paginator']
page_obj = context['page_obj']
context.update({
"page_range": make_pagination(page_obj.number, paginator.num_pages),
"NO_ENTRIES_MSG": "Nenhum usuário encontrado!",
"title": _("Usuários")
})
return context
def get(self, request, *args, **kwargs):
super(PesquisarUsuarioView, self).get(request)
data = self.filterset.data
url = ''
if data:
url = "&" + str(self.request.META['QUERY_STRING'])
if url.startswith("&page"):
ponto_comeco = url.find('username=') - 1
url = url[ponto_comeco:]
context = self.get_context_data(filter=self.filterset,
object_list=self.object_list,
filter_url=url,
numero_res=len(self.object_list)
)
context['show_results'] = show_results_filter_set(
self.request.GET.copy())
return self.render_to_response(context)
class BaseMixin(Crud.BaseMixin):
list_field_names = [
'usuario', 'groups', 'is_active'
]
class DetailUsuarioView(PermissionRequiredMixin, DetailView):
model = get_user_model()
template_name = "base/usuario_detail.html"
permission_required = ('base.detail_appconfig',)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
user = get_user_model().objects.get(id=self.kwargs['pk'])
context.update({
"user": user,
"token": Token.objects.filter(user=user)[0],
"roles": [
{
"checked": "checked" if g in user.groups.all() else "unchecked",
"group": g.name
} for g in Group.objects.all().order_by("name") if g.name != 'Votante']
})
def resolve_url(self, suffix, args=None):
return reverse('sapl.base:%s' % self.url_name(suffix),
args=args)
return context
class CreateUsuarioView(PermissionRequiredMixin, CreateView):
model = get_user_model()
form_class = UsuarioCreateForm
success_message = 'Usuário criado com sucesso!'
fail_message = 'Usuário não criado!'
permission_required = ('base.add_appconfig',)
def get_layout(self):
return super().get_layout(
'base/layouts.yaml'
)
def get_success_url(self, pk):
return reverse('sapl.base:user_detail', kwargs={"pk": pk})
def get_context_object_name(self, *args, **kwargs):
return None
def form_valid(self, form):
data = form.cleaned_data
new_user = get_user_model().objects.create(
username=data['username'],
email=data['email'],
first_name=data['firstname'],
last_name=data['lastname'],
is_superuser=False,
is_staff=False
)
new_user.set_password(data['password1'])
new_user.save()
class CreateView(Crud.CreateView):
form_class = UserAdminForm
groups = Group.objects.filter(id__in=data['roles'])
for g in groups:
g.user_set.add(new_user)
class UpdateView(Crud.UpdateView):
form_class = UserAdminForm
layout_key = None
messages.success(self.request, self.success_message)
return HttpResponseRedirect(self.get_success_url(new_user.pk))
def get_form_kwargs(self):
kwargs = Crud.UpdateView.get_form_kwargs(self)
kwargs['user_session'] = self.request.user
granular = self.request.GET.get('granular', None)
if not granular is None:
kwargs['granular'] = granular
return kwargs
class DetailView(Crud.DetailView):
layout_key = 'UserDetail'
def hook_usuario(self, obj):
return 'Usuário', '{}<br><small>{}</small>'.format(
obj.get_full_name() or '...',
obj.email
)
def form_invalid(self, form):
messages.error(self.request, self.fail_message)
return super().form_invalid(form)
def hook_auth_token(self, obj):
return 'Token', str(obj.auth_token)
def hook_username(self, obj):
return 'username', obj.username
class DeleteUsuarioView(PermissionRequiredMixin, DeleteView):
model = get_user_model()
template_name = "crud/confirm_delete.html"
permission_required = ('base.delete_appconfig',)
success_url = reverse_lazy('sapl.base:usuario')
success_message = "Usuário removido com sucesso!"
def get_context_data(self, **kwargs):
context = Crud.DetailView.get_context_data(self, **kwargs)
context['title'] = '{} <i>({})</i><br><small>{}</small>'.format(
self.object.get_full_name() or '...',
self.object.username,
self.object.email
)
return context
def delete(self, request, *args, **kwargs):
try:
super(DeleteUsuarioView, self).delete(request, *args, **kwargs)
except ProtectedError as exception:
error_url = reverse_lazy('sapl.base:user_delete', kwargs={
'pk': self.kwargs['pk']})
error_message = "O usuário não pode ser removido, pois é referenciado por:<br><ul>"
for e in exception.protected_objects:
error_message += '<li>{} - {}</li>'.format(
e._meta.verbose_name, e
@property
def extras_url(self):
btns = [
(
'{}?granular'.format(reverse('sapl.base:user_update',
kwargs={'pk': self.object.pk})),
'btn-outline-primary',
_('Edição granular')
)
error_message += '</ul>'
messages.error(self.request, error_message)
return HttpResponseRedirect(error_url)
]
messages.success(self.request, self.success_message)
return HttpResponseRedirect(self.success_url)
return btns
@property
def cancel_url(self):
return reverse('sapl.base:user_edit',
kwargs={'pk': self.kwargs['pk']})
class ListView(Crud.ListView):
form_search_class = ListWithSearchForm
ordered_list = None
paginate_by = 300
def get_context_data(self, **kwargs):
context = Crud.ListView.get_context_data(self, **kwargs)
context['subnav_template_name'] = None
return context
class EditUsuarioView(PermissionRequiredMixin, UpdateView):
model = get_user_model()
form_class = UsuarioEditForm
template_name = "base/usuario_edit.html"
success_message = 'Usuário editado com sucesso!'
permission_required = ('base.change_appconfig',)
def get_success_url(self):
return reverse('sapl.base:user_detail', kwargs={"pk": self.kwargs['pk']})
def get_initial(self):
initial = super().get_initial()
user = get_user_model().objects.get(id=self.kwargs['pk'])
roles = [str(g.id) for g in user.groups.all()]
initial.update({
"token": Token.objects.filter(user=user)[0],
"first_name": user.first_name,
"last_name": user.last_name,
"roles": roles,
"user_active": user.is_active
})
return initial
def form_valid(self, form):
user = form.save(commit=False)
data = form.cleaned_data
if 'first_name' in data and data['first_name'] != user.first_name:
user.first_name = data['first_name']
if 'last_name' in data and data['last_name'] != user.last_name:
user.last_name = data['last_name']
def hook_header_usuario(self, *args, **kwargs):
return 'Usuário'
if data['password1']:
user.set_password(data['password1'])
def hook_header_groups(self, *args, **kwargs):
return 'Grupos'
if data['user_active'] == 'True' and not user.is_active:
user.is_active = True
elif data['user_active'] == 'False' and user.is_active:
user.is_active = False
def hook_header_active(self, *args, **kwargs):
return 'is_active'
user.save()
def hook_usuario(self, *args, **kwargs):
return '{} <i>({})</i><br><small>{}</small>'.format(
args[0].get_full_name() or '...',
args[0].username,
args[0].email
), args[2]
for g in user.groups.all().exclude(name='Votante'):
g.user_set.remove(user)
def get_queryset(self):
qs = self.model.objects.all()
q_param = self.request.GET.get('q', '')
if q_param:
q = Q(first_name__icontains=q_param)
q |= Q(last_name__icontains=q_param)
q |= Q(email__icontains=q_param)
q |= Q(username__icontains=q_param)
qs = qs.filter(q)
groups = Group.objects.filter(id__in=data['roles'])
for g in groups:
g.user_set.add(user)
return qs
messages.success(self.request, self.success_message)
return super(EditUsuarioView, self).form_valid(form)
def dispatch(self, request, *args, **kwargs):
return Crud.ListView.dispatch(self, request, *args, **kwargs)
class CasaLegislativaCrud(CrudAux):

2
sapl/crud/base.py

@ -157,7 +157,7 @@ class ListWithSearchForm(forms.Form):
FieldWithButtons(
Field('q',
placeholder=_('Filtrar Lista'),
css_class='input-lg'),
css_class='form-control-lg'),
StrictButton(
_('Filtrar'), css_class='btn-outline-primary btn-lg',
type='submit'))

51
sapl/templates/auth/user_filter.html

@ -1,51 +0,0 @@
{% extends "crud/list.html" %}
{% load i18n %}
{% load crispy_forms_tags staticfiles %}
{% block base_content %}
{% if not show_results %}
{% crispy filter.form %}
<a href="{% url 'sapl.base:user_create' %}" class="btn btn-outline-primary">{% trans 'Criar usuário' %}</a>
{% endif %}
{% if show_results %}
<div class="actions btn-group float-right" role="group">
<a href="{% url 'sapl.base:usuario' %}" class="btn btn-outline-primary">{% trans 'Fazer nova pesquisa' %}</a>
<a href="{% url 'sapl.base:user_create' %}" class="btn btn-outline-primary">{% trans 'Criar usuário' %}</a>
</div>
<br /><br />
{% if numero_res > 0 %}
{% if numero_res == 1 %}
<p>Foi encontrado {{ numero_res }} resultado</p>
{% else %}
<p>Foram encontrados {{ numero_res }} resultados</p>
{% endif %}
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Nome de Usuário</th>
<th>Nome</th>
<th>E-mail do Usuário</th>
</tr>
</thead>
<tbody>
{% for usuario in page_obj %}
<tr>
<td>
<a href="{% url 'sapl.base:user_detail' usuario.pk %}">{{ usuario.username }}</a>
</td>
<td>{{ usuario.first_name }} {{ usuario.last_name }}</td>
<td>{{ usuario.email }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<font size="4"><p align="center">{{ NO_ENTRIES_MSG }}</p></font>
{% endif %}
{% endif %}
<br/>
{% include 'paginacao.html'%}
<br /><br /><br />
{% endblock base_content %}

35
sapl/templates/auth/user_form.html

@ -1,19 +1,20 @@
{% extends "base.html" %}
{% load i18n crispy_forms_tags %}
{% extends "crud/form.html" %}
{% load i18n %}
{% block base_content %}
{% block extra_js %}
<script type="text/javascript">
$(() => {
var $crf_token = $('[name="csrfmiddlewaretoken"]').attr('value');
$("#renovar-token").click(() => {
$.ajax({
url: "{% url 'sapl.api:recria_token' object.id %}",
type: "POST",
headers: { "X-CSRFToken": $crf_token },
dataType: "json",
success: (res) => $("#id_token").val(res.token)
});
});
});
</script>
<form action="" method="post">
{% csrf_token %}
{% if object.pk %}
<div class="actions btn-group float-left" role="group">
<a href="{% url 'sapl.base:usuario' %}" class="btn btn-outline-primary">{% trans 'Pesquisar usuários' %}</a>
<a href="{% url 'sapl.base:user_create' %}" class="btn btn-outline-primary">{% trans 'Criar usuário' %}</a>
</div>
<a href="{% url 'sapl.base:user_delete' object.pk %}" class="btn btn-outline-danger float-right">{% trans 'Remover usuário' %}</a>
<br /> <br />
{% endif %}
{% crispy form %}
</form>
<br /><br /><br />
{% endblock base_content %}
{% endblock %}

7
sapl/templates/base/layouts.yaml

@ -10,6 +10,13 @@ CasaLegislativa:
- email
- informacao_geral
UserDetail:
{% trans 'Usuário' %}:
- usuario username:3 is_active:2
- auth_token
- groups
- user_permissions
AppConfig:
{% trans 'Configurações Gerais' %}:

57
sapl/templates/base/usuario_detail.html

@ -1,57 +0,0 @@
{% extends "crud/detail.html" %}
{% load i18n %}
{% load crispy_forms_tags cropping %}
{% block base_content %}
<div class="actions btn-group float-right " role="group" style="margin: 0px 0px 20px">
<a href="{% url 'sapl.base:usuario' %}" class="btn btn-outline-primary">
{% blocktrans with verbose_name=view.verbose_name %} Fazer nova pesquisa {% endblocktrans %}
</a>
<a href="{% url 'sapl.base:user_edit' user.pk %}" class="btn btn-outline-primary">
{% blocktrans with verbose_name=view.verbose_name %} Editar usuário {% endblocktrans %}
</a>
</div>
<div>
<table class="table table-striped">
<tbody>
<tr>
<th scope="row">Usuário</th>
<td>{{ user.username }}</td>
</tr>
<tr>
<th scope="row">Token</th>
<td>{{ token }}</td>
</tr>
<tr>
<th scope="row">Nome</th>
<td>{% firstof user.first_name "-" %}</td>
</tr>
<tr>
<th scope="row">Sobrenome</th>
<td>{% firstof user.last_name "-" %}</td>
</tr>
<tr>
<th scope="row">Endereço de e-mail</th>
<td>{% firstof user.email "-" %}</td>
</tr>
<tr>
<th scope="row">Usuário ativo?</th>
<td>{% if user.is_active %} Sim {% else %} Não {% endif %}</td>
</tr>
<tr>
<th scope="row">Último acesso</th>
<td>{{ user.last_login }}</td>
</tr>
<tr>
<th scope="row">Roles</th>
<td><ul style="list-style-type:none">
{% for r in roles %}
<li><input type="checkbox" {{ r.checked }} disabled> {{r.group }}</li>
{% endfor %}
</ul></td>
</tr>
</tbody>
</table>
</div>
{% endblock base_content %}

20
sapl/templates/base/usuario_edit.html

@ -1,20 +0,0 @@
{% extends "crud/form.html" %}
{% load i18n %}
{% block extra_js %}
<script type="text/javascript">
$(() => {
var $crf_token = $('[name="csrfmiddlewaretoken"]').attr('value');
$("#renovar-token").click(() => {
$.ajax({
url: "{% url 'sapl.api:recria_token' user.id %}",
type: "POST",
headers: { "X-CSRFToken": $crf_token },
dataType: "json",
success: (res) => $("#id_token").val(res.token)
});
});
});
</script>
{% endblock %}

14
sapl/templates/crud/detail.html

@ -3,11 +3,9 @@
{% block base_content %}
<div class="d-flex context-actions justify-content-between align-items-center">
<div class="context-actions clearfix">
{% block actions %}
{% block sub_actions %}
<div class="actions btn-group btn-group-sm" role="group">
{% if view.list_url %}
<a href="{{ view.list_url }}" class="btn btn-outline-primary">{% trans 'Listar' %} {{view.verbose_name_plural}}</a>
@ -23,10 +21,10 @@
</div>
{% if view.extras_url %}
<div class="actions btn-group btn-group-sm" role="group">
{% for href, css_class, text in view.extras_url %}
<a href="{{href}}" class="btn btn-outline-primary {{css_class}}">
{{text}}
</a>
{% for href, css_class, text in view.extras_url %}
<a href="{{href}}" class="btn btn-outline-primary {{css_class}}">
{{text}}
</a>
{% endfor %}
</div>
{% endif %}
@ -35,7 +33,7 @@
{% block extra_actions %}
{% endblock extra_actions %}
<div class="editons">
<div class="editons float-right">
{% block editions %}
{% if view.update_url or view.delete_url %}
<div class="actions btn-group" role="group">

8
sapl/templates/crud/list.html

@ -3,16 +3,14 @@
{% block base_content %}
<div class="context-actions clearfix">
<div class="actions search">
<div class="d-flex context-actions justify-content-between align-items-start">
<div class="actions search flex-grow-1 pr-3">
{% if form %}
{% crispy form %}
{% endif %}
</div>
{% block actions %}
<div class="actions btn-group float-right btn-group-lg" role="group">
<div class="actions btn-group btn-group-lg" role="group">
{% if view.create_url %}
<a href="{{ view.create_url }}" class="btn btn-outline-primary">
{% blocktrans with verbose_name=view.verbose_name %} Adicionar {{ verbose_name }} {% endblocktrans %}

2
sapl/templates/materia/materialegislativa_detail.html

@ -60,7 +60,7 @@
<div class="controls">
<div class="form-control-static">
<div class="dont-break-out">
<a href="{% url 'sapl.base:user_edit' materia.user.pk %}">
<a href="{% url 'sapl.base:user_update' materia.user.pk %}">
{{ materia.user }}
</a>
</div>

6
sapl/templates/materia/materialegislativa_filter.html

@ -5,7 +5,7 @@
{% block actions %}
<div class="actions btn-group float-right" role="group">
<div class="actions btn-group" role="group">
{% if USE_SOLR %}
<a href="{% url 'sapl.base:haystack_search' %}" class="btn btn-outline-primary">
Pesquisa Textual
@ -79,9 +79,9 @@
{% endfor %}
</br>
{% endif %}
{% if not tipo_listagem or tipo_listagem == '1' %}
{% if m.tramitacao_set.first.unidade_tramitacao_destino %}
<strong>Localização Atual:</strong> &nbsp;{{m.tramitacao_set.first.unidade_tramitacao_destino}}</br>
{% endif %}

2
sapl/templates/materia/proposicao_detail.html

@ -173,7 +173,7 @@
<div class="controls">
<div class="form-control-static">
<div class="dont-break-out">
<a href="{% url 'sapl.base:user_edit' proposicao.user.pk %}">{{ proposicao.user }}</a>
<a href="{% url 'sapl.base:user_update' proposicao.user.pk %}">{{ proposicao.user }}</a>
</div>
</div>
</div>

6
sapl/templates/materia/tramitacao_detail.html

@ -8,11 +8,11 @@
{% if tramitacao.user %}
<div class="col-sm-4">
<div id="div_id_user" class="form-group">
<p class="control-label">Usuário</p>
<p class="control-label">Usuário</p>
<div class="controls">
<div class="form-control-static">
<div class="dont-break-out">
<a href="{% url 'sapl.base:user_edit' tramitacao.user.pk %}">
<a href="{% url 'sapl.base:user_update' tramitacao.user.pk %}">
{{ tramitacao.user }}
</a>
</div>
@ -24,7 +24,7 @@
{% if tramitacao.ip %}
<div class="col-sm-4">
<div id="div_ip_user" class="form-group">
<p class="control-label">IP</p>
<p class="control-label">IP</p>
<div class="controls">
<div class="form-control-static">
<div class="dont-break-out">

2
sapl/templates/navbar.yaml

@ -92,7 +92,7 @@
url: '/sistema'
check_permission: base.view_tabelas_auxiliares
- title: {% trans 'Administração de Usuários' %}
url: {% url 'sapl.base:usuario' %}
url: {% url 'sapl.base:user_list' %}
check_permission: user.is_superuser
- title: {% trans 'Inconsistências de Dados' %}
url: {% url 'sapl.base:lista_inconsistencias' %}

2
sapl/templates/norma/normajuridica_detail.html

@ -93,7 +93,7 @@
<div class="controls">
<div class="form-control-static">
<div class="dont-break-out">
<a href="{% url 'sapl.base:user_edit' object.user.pk %}">
<a href="{% url 'sapl.base:user_update' object.user.pk %}">
{{ object.user }}
</a>
</div>

2
sapl/templates/protocoloadm/documentoadministrativo_detail.html

@ -12,7 +12,7 @@
<div class="controls">
<div class="form-control-static">
<div class="dont-break-out">
<a href="{% url 'sapl.base:user_edit' documentoadministrativo.user.pk %}">
<a href="{% url 'sapl.base:user_update' documentoadministrativo.user.pk %}">
{{ documentoadministrativo.user }}
</a>
</div>

6
sapl/templates/protocoloadm/tramitacaoadministrativo_detail.html

@ -22,11 +22,11 @@
{% if tramitacaoadministrativo.user %}
<div class="col-sm-4">
<div id="div_id_user" class="form-group">
<p class="control-label">Usuário</p>
<p class="control-label">Usuário</p>
<div class="controls">
<div class="form-control-static">
<div class="dont-break-out">
<a href="{% url 'sapl.base:user_edit' tramitacaoadministrativo.user.pk %}">
<a href="{% url 'sapl.base:user_update' tramitacaoadministrativo.user.pk %}">
{{ tramitacaoadministrativo.user }}
</a>
</div>
@ -38,7 +38,7 @@
{% if tramitacaoadministrativo.ip %}
<div class="col-sm-4">
<div id="div_ip_user" class="form-group">
<p class="control-label">IP</p>
<p class="control-label">IP</p>
<div class="controls">
<div class="form-control-static">
<div class="dont-break-out">

Loading…
Cancel
Save