Compare commits

..

No commits in common. "539d7e9d58944c5dd443418892c0972af5c34b02" and "e2a8829156a55da93b1b275cd608e611bca8ff53" have entirely different histories.

12 changed files with 13 additions and 280 deletions

Binary file not shown.

View File

@ -1,182 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-12-22 16:24+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: apps.py:8
msgid "GAS"
msgstr "GAS"
#: forms.py:25
msgid "roles"
msgstr "roles"
#: gas/config.py:6
msgid "Users with access to gas control panel."
msgstr "Usuarios con acceso al panel de control."
#: gas/config.py:7
msgid "Users with access to everithing inside control panel."
msgstr "Usuarios con acceso a todo el panel de control."
#: gas/config.py:14 gas/users/views.py:31 gas/users/views.py:38
#: gas/users/views.py:48 gas/users/views.py:59 gas/users/views.py:95
#: gas/users/views.py:107
msgid "Users"
msgstr "Usuarios"
#: gas/users/forms.py:9 templates/gas/users/user_list.html:10
msgid "Username"
msgstr "Usuario"
#: gas/users/forms.py:10 templates/gas/users/user_list.html:11
msgid "Active"
msgstr "Activo"
#: gas/users/forms.py:12 templates/gas/users/user_list.html:12
msgid "Roles"
msgstr "Roles"
#: gas/users/views.py:33
msgid "New user"
msgstr "Nuevo usuario"
#: gas/users/views.py:43
msgid "Create user"
msgstr "Crear usuario"
#: gas/users/views.py:44
msgid "User created"
msgstr "Usuario creado"
#: gas/users/views.py:49
msgid "Create"
msgstr "Crear"
#: gas/users/views.py:54
msgid "Update user"
msgstr "Actulizar usuario"
#: gas/users/views.py:55
msgid "User updated"
msgstr "Usuario actualizado"
#: gas/users/views.py:61
msgid "Update"
msgstr "Actualizar"
#: gas/users/views.py:68
msgid "User password updated"
msgstr "Contraseña de usuario actualizada"
#: gas/users/views.py:75
#, python-brace-format
msgid "Change {username} user password"
msgstr "Cambiar la contraseña del usuario {username}"
#: gas/users/views.py:97 templates/gas/base.html:23
#: templates/gas/users/user_list.html:29
msgid "Change password"
msgstr "Cambiar contraseña"
#: gas/users/views.py:102
msgid "Delete user"
msgstr "Borrar usuario"
#: gas/users/views.py:103
msgid "User deleted"
msgstr "Usuario borrado"
#: gas/users/views.py:109 templates/gas/delete_confirmation.html:20
#: templates/gas/users/user_list.html:30
msgid "Delete"
msgstr "Borrar"
#: models.py:8
msgid "role"
msgstr "rol"
#: models.py:10
msgid "user"
msgstr "usuario"
#: models.py:14
msgid "user role"
msgstr "rol de usuario"
#: models.py:15
msgid "user roles"
msgstr "roles de usuario"
#: templates/gas/base.html:24
msgid "Logout"
msgstr "Salir"
#: templates/gas/base.html:44
msgid "Home"
msgstr "Inicio"
#: templates/gas/base_form.html:20 templates/gas/delete_confirmation.html:21
msgid "Cancel"
msgstr "Cancelar"
#: templates/gas/base_form.html:23
msgid "Save"
msgstr "Guardar"
#: templates/gas/base_form.html:26
msgid "Save and continue"
msgstr "Guardar y continuar"
#: templates/gas/base_list.html:24
msgid "Filter"
msgstr "Filtrar"
#: templates/gas/delete_confirmation.html:5
msgid "Delete confirmation"
msgstr "Confirmación de borrado"
#: templates/gas/delete_confirmation.html:10
msgid "Summary"
msgstr "Resumen"
#: templates/gas/delete_confirmation.html:16
msgid "Objects"
msgstr "Objetos"
#: templates/gas/login.html:7 templates/gas/login.html:15
msgid "Login"
msgstr "Login"
#: templates/gas/users/user_list.html:28
msgid "Edit"
msgstr "Editar"
#: views.py:44
msgid "Operation successful."
msgstr "Operación realizada."
#: views.py:170
#, python-brace-format
msgid "Are your sure you want to delete {object}?"
msgstr "¿Seguro que quieres borrar {object}?"
#: views.py:171
#, python-format
msgid "%(obj)s deleted."
msgstr ""

View File

@ -22,8 +22,8 @@ class Migration(migrations.Migration):
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_roles', to=settings.AUTH_USER_MODEL, verbose_name='user')), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_roles', to=settings.AUTH_USER_MODEL, verbose_name='user')),
], ],
options={ options={
'verbose_name': 'user role', 'verbose_name': 'role',
'verbose_name_plural': 'user roles', 'verbose_name_plural': 'roles',
}, },
), ),
] ]

View File

@ -7,20 +7,14 @@ from django.utils.translation import gettext_lazy as _
class Entry: class Entry:
def __init__(self, name, label, icon=None, url=None, roles=None, parent=None, order=None): def __init__(self, name, label, icon=None, url=None, roles=None, parent=None, children=None):
self.name = name self.name = name
self.label = label self.label = label
self.icon = icon self.icon = icon
self.url = url self.url = url
self.roles = roles self.roles = roles
self.children = dict() self.children = children or dict()
self.parent = parent self.parent = parent
self.order = order if order is not None else float("inf")
def __lt__(self, other):
if isinstance(other, Entry):
return (self.parent, self.order, self.label) < (other.parent, other.order, other.label)
return super().__lt__(other)
class GASSite(object): class GASSite(object):
@ -48,7 +42,7 @@ class GASSite(object):
raise ImproperlyConfigured("Prefix {0} already in use".format(prefix)) raise ImproperlyConfigured("Prefix {0} already in use".format(prefix))
self._registry['urls'][prefix] = urls self._registry['urls'][prefix] = urls
def register_menu(self, name, label, url=None, icon=None, roles=None, parent=None, order=None): def register_menu(self, name, label, url=None, icon=None, roles=None, parent=None):
if name in self._registry['menu']: if name in self._registry['menu']:
raise ImproperlyConfigured("Menu entry '{0}' already registered.".format(name)) raise ImproperlyConfigured("Menu entry '{0}' already registered.".format(name))
@ -59,7 +53,7 @@ class GASSite(object):
roles.add(self.base_role) roles.add(self.base_role)
entry = Entry(name, label, icon, url, roles, parent=parent, order=order) entry = Entry(name, label, icon, url, roles, parent=parent)
if parent: if parent:
try: try:

View File

@ -194,17 +194,3 @@ label {
.required label { .required label {
font-weight: bold; font-weight: bold;
} }
#login {
background: #eee;
}
#login form {
border: 1px solid gray;
border-radius: 0.5em;
background: #fff;
margin: 2em auto;
width: 20em;
padding: 1em;
}

View File

@ -16,7 +16,6 @@
{% endblock %} {% endblock %}
<ul class="actions"> <ul class="actions">
{% block actions %}
{% if not is_popup %} {% if not is_popup %}
<li><a href="{{ view.get_success_url }}">{% trans "Cancel" %}</a></li> <li><a href="{{ view.get_success_url }}">{% trans "Cancel" %}</a></li>
{% endif %} {% endif %}
@ -27,11 +26,6 @@
<li><button name="save_and_continue" type="submit">{% trans "Save and continue" %}</button> <li><button name="save_and_continue" type="submit">{% trans "Save and continue" %}</button>
{% endif %} {% endif %}
{% block extra_actions %}{% endblock %} {% block extra_actions %}{% endblock %}
{% endblock actions %}
</ul> </ul>
</form> </form>
{% endblock %} {% endblock %}
{% block extra_js %}
{{ form.media }}
{% endblock %}

View File

@ -18,6 +18,6 @@
<form method="post" action=".">{% csrf_token %} <form method="post" action=".">{% csrf_token %}
<button type="submit">{% trans 'Delete' %}</button> <button type="submit">{% trans 'Delete' %}</button>
<a href="{{ cancel_url }}">{% trans 'Cancel' %}</a> <a href="{{ back_url }}">{% trans 'Cancel' %}</a>
</form> </form>
{% endblock %} {% endblock %}

View File

@ -3,10 +3,10 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<title>Login</title>
<title>{{ gas_title }} {% trans "Login" %}</title> <title>{{ gas_title }} {% trans "Login" %}</title>
<link href="{% static "gas/css/gas.css" %}" rel="stylesheet" type="text/css" />
</head> </head>
<body id="login"> <body>
<form action="." method="POST">{% csrf_token %} <form action="." method="POST">{% csrf_token %}
{% form_errors form %} {% form_errors form %}
{% form_field form.username %} {% form_field form.username %}

View File

@ -15,7 +15,7 @@ def show_navigation(user):
if user.is_superuser: if user.is_superuser:
user_roles.add('admins') user_roles.add('admins')
menu = site.get_root_menu(user_roles) menu = site.get_root_menu(user_roles)
menu.sort() menu.sort(key=lambda a: a.label)
return { return {
'menu': menu, 'menu': menu,
'user_roles': user_roles, 'user_roles': user_roles,
@ -29,6 +29,7 @@ def get_children(entry, roles):
child for child in entry.children.values() child for child in entry.children.values()
if child.roles.intersection(roles) if child.roles.intersection(roles)
], ],
key=lambda a: a.label
) )

View File

@ -84,66 +84,6 @@ class SiteTestCase(TestCase):
url="gas:role_list", url="gas:role_list",
) )
def test_menu_ordering(self):
test_site = GASSite()
admin_roles = set(('admins',))
# With no explicit order, sort by label
test_site.register_menu(name='c', label="c")
test_site.register_menu(name='b', label="b")
test_site.register_menu(name='a', label="a")
entries = [
entry.name
for entry in sorted(test_site.get_root_menu(admin_roles))
]
self.assertEqual(entries, ['a', 'b', 'c'])
# Explicit order takes preference
test_site.register_menu(name='z', label="z", order=1)
entries = [
entry.name
for entry in sorted(test_site.get_root_menu(admin_roles))
]
self.assertEqual(entries, ['z', 'a', 'b', 'c'])
# Explicit order inside parent don't change the order
test_site.register_menu(name='y', label="y", order=2, parent='a')
entries = [
entry.name
for entry in sorted(test_site.get_root_menu(admin_roles))
]
self.assertEqual(entries, ['z', 'a', 'b', 'c'])
# With same explicit order, sort by label
test_site.register_menu(name='x', label="x", order=1)
entries = [
entry.name
for entry in sorted(test_site.get_root_menu(admin_roles))
]
self.assertEqual(entries, ['x', 'z', 'a', 'b', 'c'])
def test_menu_visibility(self):
test_site = GASSite()
admin_roles = set(('admins',))
staff_roles = set(('staff',))
test_site.register_menu(name='a', label='a', roles=admin_roles)
test_site.register_menu(name='b', label='b', roles=staff_roles)
# Admins gets all menu
entries = [
entry.name
for entry in test_site.get_root_menu(admin_roles)
]
self.assertEqual(entries, ['a', 'b'])
# Staff gets filtered menu
entries = [
entry.name
for entry in test_site.get_root_menu(staff_roles)
]
self.assertEqual(entries, ['b'])
class SampleAppIntegrationTest(TestCase): class SampleAppIntegrationTest(TestCase):
def test_gas_autodiscover(self): def test_gas_autodiscover(self):

View File

@ -168,7 +168,7 @@ class GASUpdateView(GASMixin, UpdateView):
class GASDeleteView(GASMixin, DeleteView): class GASDeleteView(GASMixin, DeleteView):
template_name = "gas/delete_confirmation.html" template_name = "gas/delete_confirmation.html"
confirmation_text = _("Are your sure you want to delete {object}?") confirmation_text = _("Are your sure you want to delete {object}?")
deleted_text = _("{object} deleted.") deleted_text = _("%(obj)s deleted.")
def get_confirmation_text(self): def get_confirmation_text(self):
return self.confirmation_text.format(object=self.object) return self.confirmation_text.format(object=self.object)

View File

@ -13,7 +13,7 @@ classifiers =
Framework :: Django Framework :: Django
Framework :: Django :: 3.1 Framework :: Django :: 3.1
Intended Audience :: Developers Intended Audience :: Developers
License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+) License :: OSI Approved :: BSD License
Operating System :: OS Independent Operating System :: OS Independent
Programming Language :: Python Programming Language :: Python
Programming Language :: Python :: 3 Programming Language :: Python :: 3