Browse Source

Refatora interface de Administração de Usuários (#2517)

* Implementar pesquisa de usuário

Adequar layouts dos botões

Adicionar confirmação para deletar usuário

Adicionar success_message ao deletar

Capturar e tratar ProtectedError em DeleteUsuario

Subir pequena alteração

Atualizar self.form.helper

* Update sapl/base/views.py

Co-Authored-By: rjoao <cont.joaorodrigues@gmail.com>

* Atualizar sapl/base/views.py
pull/2527/head
João Rodrigues 6 years ago
committed by Edward
parent
commit
5e89f9513e
  1. 30
      sapl/base/forms.py
  2. 4
      sapl/base/urls.py
  3. 105
      sapl/base/views.py
  4. 51
      sapl/templates/auth/user_filter.html
  5. 11
      sapl/templates/auth/user_form.html
  6. 35
      sapl/templates/auth/user_list.html
  7. 2
      sapl/templates/navbar.yaml

30
sapl/base/forms.py

@ -112,8 +112,6 @@ class UsuarioCreateForm(ModelForm):
[('password1', 6), [('password1', 6),
('password2', 6)]) ('password2', 6)])
row4 = to_row([(form_actions(label='Confirmar'), 6)])
self.helper = SaplFormHelper() self.helper = SaplFormHelper()
self.helper.layout = Layout( self.helper.layout = Layout(
row0, row0,
@ -121,7 +119,31 @@ class UsuarioCreateForm(ModelForm):
row3, row3,
row2, row2,
'roles', 'roles',
row4) 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'))
)
class UsuarioEditForm(ModelForm): class UsuarioEditForm(ModelForm):
@ -159,7 +181,7 @@ class UsuarioEditForm(ModelForm):
row1, row1,
row2, row2,
'roles', 'roles',
row3) form_actions(label='Salvar Alterações'))
def clean(self): def clean(self):
super(UsuarioEditForm, self).clean() super(UsuarioEditForm, self).clean()

4
sapl/base/urls.py

@ -15,7 +15,7 @@ from .apps import AppConfig
from .forms import LoginForm, NovaSenhaForm, RecuperarSenhaForm from .forms import LoginForm, NovaSenhaForm, RecuperarSenhaForm
from .views import (AlterarSenha, AppConfigCrud, CasaLegislativaCrud, from .views import (AlterarSenha, AppConfigCrud, CasaLegislativaCrud,
CreateUsuarioView, DeleteUsuarioView, EditUsuarioView, CreateUsuarioView, DeleteUsuarioView, EditUsuarioView,
HelpTopicView, ListarUsuarioView, LogotipoView, HelpTopicView, PesquisarUsuarioView, LogotipoView,
RelatorioAtasView, RelatorioAudienciaView, RelatorioAtasView, RelatorioAudienciaView,
RelatorioDataFimPrazoTramitacaoView, RelatorioDataFimPrazoTramitacaoView,
RelatorioHistoricoTramitacaoView, RelatorioHistoricoTramitacaoView,
@ -41,7 +41,7 @@ from .views import (AlterarSenha, AppConfigCrud, CasaLegislativaCrud,
app_name = AppConfig.name app_name = AppConfig.name
admin_user = [ admin_user = [
url(r'^sistema/usuario/$', ListarUsuarioView.as_view(), name='user_list'), url(r'^sistema/usuario/$', PesquisarUsuarioView.as_view(), name='usuario'),
url(r'^sistema/usuario/create$', CreateUsuarioView.as_view(), name='user_create'), url(r'^sistema/usuario/create$', CreateUsuarioView.as_view(), name='user_create'),
url(r'^sistema/usuario/(?P<pk>\d+)/edit$', EditUsuarioView.as_view(), name='user_edit'), 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/(?P<pk>\d+)/delete$', DeleteUsuarioView.as_view(), name='user_delete')

105
sapl/base/views.py

@ -4,15 +4,16 @@ import datetime
import logging import logging
import os import os
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.contrib.auth.models import Group from django.contrib.auth.models import Group, User
from django.contrib.auth.tokens import default_token_generator from django.contrib.auth.tokens import default_token_generator
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied from django.core.exceptions import 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, reverse_lazy
from django.db import connection from django.db import connection
from django.db.models import Count, Q from django.db.models import Count, Q, ProtectedError
from django.http import Http404, HttpResponseRedirect from django.http import Http404, HttpResponseRedirect
from django.template import TemplateDoesNotExist from django.template import TemplateDoesNotExist
from django.template.loader import get_template from django.template.loader import get_template
@ -56,7 +57,7 @@ from .forms import (AlterarSenhaForm, CasaLegislativaForm,
RelatorioReuniaoFilterSet, UsuarioCreateForm, RelatorioReuniaoFilterSet, UsuarioCreateForm,
UsuarioEditForm, RelatorioNormasMesFilterSet, UsuarioEditForm, RelatorioNormasMesFilterSet,
RelatorioNormasVigenciaFilterSet, RelatorioNormasVigenciaFilterSet,
EstatisticasAcessoNormasForm) EstatisticasAcessoNormasForm, UsuarioFilterSet)
from .models import AppConfig, CasaLegislativa from .models import AppConfig, CasaLegislativa
@ -1266,35 +1267,72 @@ class ListarProtocolosDuplicadosView(PermissionRequiredMixin, ListView):
return context return context
class ListarUsuarioView(PermissionRequiredMixin, ListView): class PesquisarUsuarioView(PermissionRequiredMixin, FilterView):
model = get_user_model() model = User
template_name = 'auth/user_list.html' filterset_class = UsuarioFilterSet
context_object_name = 'user_list'
permission_required = ('base.list_appconfig',) permission_required = ('base.list_appconfig',)
paginate_by = 10 paginate_by = 10
def get_queryset(self): def get_filterset_kwargs(self, filterset_class):
qs = super(ListarUsuarioView, self).get_queryset() super(PesquisarUsuarioView,
return qs.order_by('username') 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): def get_context_data(self, **kwargs):
context = super(ListarUsuarioView, self).get_context_data(**kwargs) context = super(PesquisarUsuarioView,
self).get_context_data(**kwargs)
paginator = context['paginator'] paginator = context['paginator']
page_obj = context['page_obj'] page_obj = context['page_obj']
context['page_range'] = make_pagination( context['page_range'] = make_pagination(
page_obj.number, paginator.num_pages) page_obj.number, paginator.num_pages)
context['NO_ENTRIES_MSG'] = 'Nenhum usuário cadastrado.'
context['NO_ENTRIES_MSG'] = 'Nenhum usuário encontrado!'
context['title'] = _('Usuários')
return context return context
def get(self, request, *args, **kwargs):
super(PesquisarUsuarioView, self).get(request)
data = self.filterset.data
url = ''
if data:
url = "&" + str(self.request.environ['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 CreateUsuarioView(PermissionRequiredMixin, CreateView): class CreateUsuarioView(PermissionRequiredMixin, CreateView):
model = get_user_model() model = get_user_model()
form_class = UsuarioCreateForm form_class = UsuarioCreateForm
success_message = 'Usuário criado com sucesso' success_message = 'Usuário criado com sucesso!'
permission_required = ('base.add_appconfig',) permission_required = ('base.add_appconfig',)
def get_success_url(self): def get_success_url(self):
return reverse('sapl.base:user_list') return reverse('sapl.base:usuario')
def form_valid(self, form): def form_valid(self, form):
@ -1313,33 +1351,49 @@ class CreateUsuarioView(PermissionRequiredMixin, CreateView):
for g in groups: for g in groups:
g.user_set.add(new_user) g.user_set.add(new_user)
messages.success(self.request, self.success_message)
return HttpResponseRedirect(self.get_success_url()) return HttpResponseRedirect(self.get_success_url())
class DeleteUsuarioView(PermissionRequiredMixin, DeleteView): class DeleteUsuarioView(PermissionRequiredMixin, DeleteView):
model = get_user_model() model = get_user_model()
template_name = "crud/confirm_delete.html"
permission_required = ('base.delete_appconfig',) permission_required = ('base.delete_appconfig',)
success_url = reverse_lazy('sapl.base:usuario')
success_message = "Usuário removido com sucesso!"
def get_success_url(self): def delete(self, request, *args, **kwargs):
return reverse('sapl.base:user_list') 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
)
error_message += '</ul>'
messages.error(self.request, error_message)
return HttpResponseRedirect(error_url)
def get(self, request, *args, **kwargs): messages.success(self.request, self.success_message)
return self.post(request, *args, **kwargs) return HttpResponseRedirect(self.success_url)
def get_queryset(self): @property
qs = super(DeleteUsuarioView, self).get_queryset() def cancel_url(self):
return qs.filter(id=self.kwargs['pk']) return reverse('sapl.base:user_edit',
kwargs={'pk': self.kwargs['pk']})
class EditUsuarioView(PermissionRequiredMixin, UpdateView): class EditUsuarioView(PermissionRequiredMixin, UpdateView):
model = get_user_model() model = get_user_model()
form_class = UsuarioEditForm form_class = UsuarioEditForm
success_message = 'Usuário editado com sucesso' success_message = 'Usuário editado com sucesso!'
permission_required = ('base.change_appconfig',) permission_required = ('base.change_appconfig',)
def get_success_url(self): def get_success_url(self):
return reverse('sapl.base:user_list') return reverse('sapl.base:usuario')
def get_initial(self): def get_initial(self):
initial = super(EditUsuarioView, self).get_initial() initial = super(EditUsuarioView, self).get_initial()
@ -1376,6 +1430,7 @@ class EditUsuarioView(PermissionRequiredMixin, UpdateView):
for g in groups: for g in groups:
g.user_set.add(user) g.user_set.add(user)
messages.success(self.request, self.success_message)
return super(EditUsuarioView, self).form_valid(form) return super(EditUsuarioView, self).form_valid(form)

51
sapl/templates/auth/user_filter.html

@ -0,0 +1,51 @@
{% 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_edit' 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 %}

11
sapl/templates/auth/user_form.html

@ -5,10 +5,15 @@
<form action="" method="post"> <form action="" method="post">
{% csrf_token %} {% csrf_token %}
{% crispy form %}
{% if object.pk %} {% if object.pk %}
<a class="btn btn-warning" href="{% url 'sapl.base:user_delete' object.pk %}">Remover usuário</a> <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 %} {% endif %}
{% crispy form %}
</form> </form>
<br /><br /><br />
{% endblock base_content %} {% endblock base_content %}

35
sapl/templates/auth/user_list.html

@ -1,35 +0,0 @@
{% extends "base.html" %}
{% load i18n %}
{% load tz %}
{% load common_tags %}
{% block base_content %}
<fieldset>
<h1>Lista de usuários</h1>
{% if not user_list %}
<p>{{ NO_ENTRIES_MSG }}</p>
{% else %}
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Nome de Login</th>
<th>Nome</th>
<th>E-mail do Usuário</th>
</tr>
</thead>
<tbody>
{% for user in user_list %}
<tr>
<td>
<a href="{% url 'sapl.base:user_edit' user.pk %}">{{ user.username }}</a>
</td>
<td>{{ user.first_name }} {{ user.last_name }}</td>
<td>{{ user.email }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<a class="btn btn-outline-primary" href="{% url 'sapl.base:user_create' %}">Criar Usuário</a>
</fieldset>
{% include 'paginacao.html'%}
{% endblock base_content %}

2
sapl/templates/navbar.yaml

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

Loading…
Cancel
Save