diff --git a/aleksis/core/apps.py b/aleksis/core/apps.py index 0037842bc71590eb521aa67f25b5f4cc6b50fb92..aeda609326941428e483e05cabd6e5412b2832f7 100644 --- a/aleksis/core/apps.py +++ b/aleksis/core/apps.py @@ -2,6 +2,7 @@ from typing import Any, List, Optional, Tuple import django.apps from django.http import HttpRequest +from django.utils.module_loading import autodiscover_modules from dynamic_preferences.registries import preference_models @@ -36,6 +37,9 @@ class CoreConfig(AppConfig): def ready(self): super().ready() + # Autodiscover various modules defined by AlekSIS + autodiscover_modules("form_extensions", "model_extensions", "checks") + sitepreferencemodel = self.get_model("SitePreferenceModel") personpreferencemodel = self.get_model("PersonPreferenceModel") grouppreferencemodel = self.get_model("GroupPreferenceModel") diff --git a/aleksis/core/mixins.py b/aleksis/core/mixins.py index f6a8c18c483d0833d296abd6310cc2103331ba18..6b52fb3820c366c1040905eed1226cdc1d4c0e3f 100644 --- a/aleksis/core/mixins.py +++ b/aleksis/core/mixins.py @@ -164,17 +164,17 @@ class ExtensibleModel(models.Model, metaclass=_ExtensibleModelBase): @classmethod def property_(cls, func: Callable[[], Any], name: Optional[str] = None) -> None: """Add the passed callable as a property.""" - cls._safe_add(property(func), func.__name__) + cls._safe_add(property(func), name or func.__name__) @classmethod def method(cls, func: Callable[[], Any], name: Optional[str] = None) -> None: """Add the passed callable as a method.""" - cls._safe_add(func, func.__name__) + cls._safe_add(func, name or func.__name__) @classmethod def class_method(cls, func: Callable[[], Any], name: Optional[str] = None) -> None: """Add the passed callable as a classmethod.""" - cls._safe_add(classmethod(func), func.__name__) + cls._safe_add(classmethod(func), name or func.__name__) @classmethod def field(cls, **kwargs) -> None: diff --git a/aleksis/core/models.py b/aleksis/core/models.py index b5bb204c25139c463e6d53c27b7c1ddf51b75576..fe0d63d62713fbdfa6ff9b142844d1226c28be6f 100644 --- a/aleksis/core/models.py +++ b/aleksis/core/models.py @@ -302,7 +302,9 @@ class Group(ExtensibleModel): null=True, blank=True, ) - additional_fields = models.ManyToManyField(AdditionalField, verbose_name=_("Additional fields")) + additional_fields = models.ManyToManyField( + AdditionalField, verbose_name=_("Additional fields"), blank=True + ) def get_absolute_url(self) -> str: return reverse("group_by_id", args=[self.id]) diff --git a/aleksis/core/templates/403.html b/aleksis/core/templates/403.html index c84e7f57ed0fa82dead672fde7ffd2c20a8bdc81..00da4145121cafa2319c806884bb5637ad09a798 100644 --- a/aleksis/core/templates/403.html +++ b/aleksis/core/templates/403.html @@ -15,7 +15,7 @@ administrators: {% endblocktrans %} </p> - {% include "core/admins_list.html" %} + {% include "core/partials/admins_list.html" %} </div> </div> </div> diff --git a/aleksis/core/templates/404.html b/aleksis/core/templates/404.html index 45873cde006feaf32b27999cf357d4888d70f644..33c311fcaf4c106d44c53788b44426584d014c33 100644 --- a/aleksis/core/templates/404.html +++ b/aleksis/core/templates/404.html @@ -19,7 +19,7 @@ administrators: {% endblocktrans %} </p> - {% include "core/admins_list.html" %} + {% include "core/partials/admins_list.html" %} </div> </div> </div> diff --git a/aleksis/core/templates/500.html b/aleksis/core/templates/500.html index 621b9e424054cb321072450140c60548ebec3a0d..0759bfdd070f339fe0eec4f3d5806485e34e4664 100644 --- a/aleksis/core/templates/500.html +++ b/aleksis/core/templates/500.html @@ -15,7 +15,7 @@ error. You can also contact them directly: {% endblocktrans %} </p> - {% include "core/admins_list.html" %} + {% include "core/partials/admins_list.html" %} </div> </div> </div> diff --git a/aleksis/core/templates/503.html b/aleksis/core/templates/503.html index 9ed4fcecbaa5ef620264374fef1074288c4d7785..ac1dc4c3dea129f0798f18fd61dfdaaa5f291d17 100644 --- a/aleksis/core/templates/503.html +++ b/aleksis/core/templates/503.html @@ -14,7 +14,7 @@ This page is currently unavailable. If this error persists, contact your site administrators: {% endblocktrans %} </p> - {% include "core/admins_list.html" %} + {% include "core/partials/admins_list.html" %} </div> </div> </div> diff --git a/aleksis/core/templates/core/edit_additional_field.html b/aleksis/core/templates/core/additional_field/edit.html similarity index 100% rename from aleksis/core/templates/core/edit_additional_field.html rename to aleksis/core/templates/core/additional_field/edit.html diff --git a/aleksis/core/templates/core/additional_fields.html b/aleksis/core/templates/core/additional_field/list.html similarity index 100% rename from aleksis/core/templates/core/additional_fields.html rename to aleksis/core/templates/core/additional_field/list.html diff --git a/aleksis/core/templates/core/base.html b/aleksis/core/templates/core/base.html index e30d428f060f540cbf7d4dbbb483a1371dbddf38..2d112a4f0fe54f4f1926811fbd589b32351909cf 100644 --- a/aleksis/core/templates/core/base.html +++ b/aleksis/core/templates/core/base.html @@ -7,7 +7,7 @@ <!DOCTYPE html> <html lang="{{ LANGUAGE_CODE }}"> <head> - {% include "core/meta.html" %} + {% include "core/partials/meta.html" %} <title> {% block no_browser_title %} @@ -81,14 +81,14 @@ </li> {% endif %} <li class="no-padding"> - {% include "core/sidenav.html" %} + {% include "core/partials/sidenav.html" %} </li> </ul> </header> <main role="main"> - {% include 'core/no_person.html' %} + {% include 'core/partials/no_person.html' %} {% if messages %} {% for message in messages %} @@ -122,23 +122,23 @@ <div class="row no-margin footer-row-large"> <div class="col l6 s12 no-pad-left height-inherit"> <p class="white-text valign-bot"> - {% include 'core/language_form.html' %} + {% include 'core/partials/language_form.html' %} </p> </div> <div class="col xl15 l6 offset-xl01 s12 no-pad-right"> <ul class="no-margin right"> - {% include "core/footer-menu.html" %} + {% include "core/partials/footer-menu.html" %} </ul> </div> </div> <div class="row no-margin footer-row-small"> <span class="white-text make-it-higher"> - {% include 'core/language_form.html' %} + {% include 'core/partials/language_form.html' %} </span> <ul class="no-margin footer-ul"> - {% include "core/footer-menu.html" %} + {% include "core/partials/footer-menu.html" %} </ul> </div> </div> diff --git a/aleksis/core/templates/core/base_print.html b/aleksis/core/templates/core/base_print.html index 6059d664fccb38ce18a55eb9ea6d1a406a6e9ad4..b0739d3a2e7e0ceb6d81d21ce575d6ef967d810f 100644 --- a/aleksis/core/templates/core/base_print.html +++ b/aleksis/core/templates/core/base_print.html @@ -5,7 +5,7 @@ <!DOCTYPE html> <html lang="{{ LANGUAGE_CODE }}"> <head> - {% include "core/meta.html" %} + {% include "core/partials/meta.html" %} <title> {% block no_browser_title %} diff --git a/aleksis/core/templates/core/groups_child_groups.html b/aleksis/core/templates/core/group/child_groups.html similarity index 100% rename from aleksis/core/templates/core/groups_child_groups.html rename to aleksis/core/templates/core/group/child_groups.html diff --git a/aleksis/core/templates/core/edit_group.html b/aleksis/core/templates/core/group/edit.html similarity index 88% rename from aleksis/core/templates/core/edit_group.html rename to aleksis/core/templates/core/group/edit.html index e7b3188076125020958105ee97ab0de00bd5f766..b26a28d1efc5ee292a257220bca00754512c1b99 100644 --- a/aleksis/core/templates/core/edit_group.html +++ b/aleksis/core/templates/core/group/edit.html @@ -11,7 +11,7 @@ <form method="post"> {% csrf_token %} {% form form=edit_group_form %}{% endform %} - {% include "core/save_button.html" %} + {% include "core/partials/save_button.html" %} </form> {% endblock %} diff --git a/aleksis/core/templates/core/group_full.html b/aleksis/core/templates/core/group/full.html similarity index 75% rename from aleksis/core/templates/core/group_full.html rename to aleksis/core/templates/core/group/full.html index 0add6f1a3041b723e4a4e3d87972e07a8daebf97..2c778f837a785d431300ea57a1a283a05b6bd367 100644 --- a/aleksis/core/templates/core/group_full.html +++ b/aleksis/core/templates/core/group/full.html @@ -31,6 +31,25 @@ </p> {% endif %} + <table> + <tr> + <th> + <i class="material-icons center" title="{% trans "Group type" %}">category</i> + </th> + <td> + {{ group.group_type }} + </td> + </tr> + <tr> + <th> + <i class="material-icons center" title="{% trans "Parent groups" %}">vertical_align_top</i> + </th> + <td> + {{ group.parent_groups.all|join:", " }} + </td> + </tr> + </table> + <h5>{% blocktrans %}Owners{% endblocktrans %}</h5> {% render_table owners_table %} diff --git a/aleksis/core/templates/core/groups.html b/aleksis/core/templates/core/group/list.html similarity index 100% rename from aleksis/core/templates/core/groups.html rename to aleksis/core/templates/core/group/list.html diff --git a/aleksis/core/templates/core/edit_group_type.html b/aleksis/core/templates/core/group_type/edit.html similarity index 89% rename from aleksis/core/templates/core/edit_group_type.html rename to aleksis/core/templates/core/group_type/edit.html index c857de98b893cf243c3c108f3c76b5aa142e6037..843975b16bb6ccbd7cf8eeed8f2d5713f5320e23 100644 --- a/aleksis/core/templates/core/edit_group_type.html +++ b/aleksis/core/templates/core/group_type/edit.html @@ -11,7 +11,7 @@ <form method="post"> {% csrf_token %} {% form form=edit_group_type_form %}{% endform %} - {% include "core/save_button.html" %} + {% include "core/partials/save_button.html" %} </form> {% endblock %} diff --git a/aleksis/core/templates/core/group_types.html b/aleksis/core/templates/core/group_type/list.html similarity index 100% rename from aleksis/core/templates/core/group_types.html rename to aleksis/core/templates/core/group_type/list.html diff --git a/aleksis/core/templates/core/index.html b/aleksis/core/templates/core/index.html index ac5d19b71bc6ac4acd00d7d3c509e1c07f089dcc..683adca900d46a8ba50790829db4d3ecd0ba2716 100644 --- a/aleksis/core/templates/core/index.html +++ b/aleksis/core/templates/core/index.html @@ -27,7 +27,7 @@ </div> {% endfor %} - {% include "core/announcements.html" with announcements=announcements %} + {% include "core/partials/announcements.html" with announcements=announcements %} <div class="row" id="live_load"> {% for widget in widgets %} diff --git a/aleksis/core/templates/core/data_management.html b/aleksis/core/templates/core/management/data_management.html similarity index 87% rename from aleksis/core/templates/core/data_management.html rename to aleksis/core/templates/core/management/data_management.html index 520dcb6d54beb20c482158cfa538ccf5cf2dc1ab..fa8e61f5dac1d1e01e5a773b68015cc9befe8d8f 100644 --- a/aleksis/core/templates/core/data_management.html +++ b/aleksis/core/templates/core/management/data_management.html @@ -8,5 +8,5 @@ {% block content %} {% get_menu "DATA_MANAGEMENT_MENU" as menu %} - {% include "core/on_page_menu.html" %} + {% include "core/partials/on_page_menu.html" %} {% endblock %} diff --git a/aleksis/core/templates/core/about.html b/aleksis/core/templates/core/pages/about.html similarity index 100% rename from aleksis/core/templates/core/about.html rename to aleksis/core/templates/core/pages/about.html diff --git a/aleksis/core/templates/offline.html b/aleksis/core/templates/core/pages/offline.html similarity index 92% rename from aleksis/core/templates/offline.html rename to aleksis/core/templates/core/pages/offline.html index 6961e03de97ea1a51096df239ac55880729e0fe7..a6a70dc19f074e8c3f3ede50b5e9b5b80b5682f1 100644 --- a/aleksis/core/templates/offline.html +++ b/aleksis/core/templates/core/pages/offline.html @@ -13,5 +13,5 @@ administrators: {% endblocktrans %} </p> - {% include "core/admins_list.html" %} + {% include "core/partials/admins_list.html" %} {% endblock %} diff --git a/aleksis/core/templates/core/system_status.html b/aleksis/core/templates/core/pages/system_status.html similarity index 100% rename from aleksis/core/templates/core/system_status.html rename to aleksis/core/templates/core/pages/system_status.html diff --git a/aleksis/core/templates/core/admins_list.html b/aleksis/core/templates/core/partials/admins_list.html similarity index 100% rename from aleksis/core/templates/core/admins_list.html rename to aleksis/core/templates/core/partials/admins_list.html diff --git a/aleksis/core/templates/core/announcements.html b/aleksis/core/templates/core/partials/announcements.html similarity index 100% rename from aleksis/core/templates/core/announcements.html rename to aleksis/core/templates/core/partials/announcements.html diff --git a/aleksis/core/templates/core/crud_events.html b/aleksis/core/templates/core/partials/crud_events.html similarity index 100% rename from aleksis/core/templates/core/crud_events.html rename to aleksis/core/templates/core/partials/crud_events.html diff --git a/aleksis/core/templates/core/footer-menu.html b/aleksis/core/templates/core/partials/footer-menu.html similarity index 100% rename from aleksis/core/templates/core/footer-menu.html rename to aleksis/core/templates/core/partials/footer-menu.html diff --git a/aleksis/core/templates/core/language_form.html b/aleksis/core/templates/core/partials/language_form.html similarity index 100% rename from aleksis/core/templates/core/language_form.html rename to aleksis/core/templates/core/partials/language_form.html diff --git a/aleksis/core/templates/core/meta.html b/aleksis/core/templates/core/partials/meta.html similarity index 100% rename from aleksis/core/templates/core/meta.html rename to aleksis/core/templates/core/partials/meta.html diff --git a/aleksis/core/templates/core/no_person.html b/aleksis/core/templates/core/partials/no_person.html similarity index 100% rename from aleksis/core/templates/core/no_person.html rename to aleksis/core/templates/core/partials/no_person.html diff --git a/aleksis/core/templates/core/on_page_menu.html b/aleksis/core/templates/core/partials/on_page_menu.html similarity index 100% rename from aleksis/core/templates/core/on_page_menu.html rename to aleksis/core/templates/core/partials/on_page_menu.html diff --git a/aleksis/core/templates/core/save_button.html b/aleksis/core/templates/core/partials/save_button.html similarity index 100% rename from aleksis/core/templates/core/save_button.html rename to aleksis/core/templates/core/partials/save_button.html diff --git a/aleksis/core/templates/core/sidenav.html b/aleksis/core/templates/core/partials/sidenav.html similarity index 100% rename from aleksis/core/templates/core/sidenav.html rename to aleksis/core/templates/core/partials/sidenav.html diff --git a/aleksis/core/templates/core/turnable.html b/aleksis/core/templates/core/partials/turnable.html similarity index 100% rename from aleksis/core/templates/core/turnable.html rename to aleksis/core/templates/core/partials/turnable.html diff --git a/aleksis/core/templates/core/persons_accounts.html b/aleksis/core/templates/core/person/accounts.html similarity index 100% rename from aleksis/core/templates/core/persons_accounts.html rename to aleksis/core/templates/core/person/accounts.html diff --git a/aleksis/core/templates/core/edit_person.html b/aleksis/core/templates/core/person/edit.html similarity index 89% rename from aleksis/core/templates/core/edit_person.html rename to aleksis/core/templates/core/person/edit.html index 8a5d0ca39a8fa0cbfd437519a09723ce59278c2d..8f854610e3424b9da47f142cef41b71c9e0fb097 100644 --- a/aleksis/core/templates/core/edit_person.html +++ b/aleksis/core/templates/core/person/edit.html @@ -14,7 +14,7 @@ <form method="post" enctype="multipart/form-data"> {% csrf_token %} {% form form=edit_person_form %}{% endform %} - {% include "core/save_button.html" %} + {% include "core/partials/save_button.html" %} </form> {% endblock %} diff --git a/aleksis/core/templates/core/person_full.html b/aleksis/core/templates/core/person/full.html similarity index 100% rename from aleksis/core/templates/core/person_full.html rename to aleksis/core/templates/core/person/full.html diff --git a/aleksis/core/templates/core/persons.html b/aleksis/core/templates/core/person/list.html similarity index 100% rename from aleksis/core/templates/core/persons.html rename to aleksis/core/templates/core/person/list.html diff --git a/aleksis/core/templates/dynamic_preferences/form.html b/aleksis/core/templates/dynamic_preferences/form.html index d8de37802c09a14327b0d949b5935fb69660c666..da3d608285c43673bd27932d0d19cef303b1cef7 100644 --- a/aleksis/core/templates/dynamic_preferences/form.html +++ b/aleksis/core/templates/dynamic_preferences/form.html @@ -22,7 +22,7 @@ <form action="" enctype="multipart/form-data" method="post"> {% csrf_token %} {% form form=form %}{% endform %} - {% include "core/save_button.html" with caption=_("Save preferences") %} + {% include "core/partials/save_button.html" with caption=_("Save preferences") %} </form> </div> {% endblock %} diff --git a/aleksis/core/util/apps.py b/aleksis/core/util/apps.py index 1500537334ebf5d339955c55a480776053b01d03..d263feb9a2ba0c9e36d821a56e12f77726a7a672 100644 --- a/aleksis/core/util/apps.py +++ b/aleksis/core/util/apps.py @@ -1,4 +1,3 @@ -from importlib import import_module from typing import Any, List, Optional, Sequence, Tuple import django.apps @@ -19,15 +18,6 @@ class AppConfig(django.apps.AppConfig): def ready(self): super().ready() - # Run model extension code - try: - import_module( - ".".join(self.__class__.__module__.split(".")[:-1] + ["model_extensions"]) - ) - except ImportError: - # ImportErrors are non-fatal because model extensions are optional. - pass - # Register default listeners pre_migrate.connect(self.pre_migrate, sender=self) post_migrate.connect(self.post_migrate, sender=self) @@ -38,13 +28,6 @@ class AppConfig(django.apps.AppConfig): # Getting an app ready means it should look at its config once self.preference_updated(self) - # Register system checks of this app - try: - import_module(".".join(self.__class__.__module__.split(".")[:-1] + ["checks"])) - except ImportError: - # ImportErrors are non-fatal because checks are optional. - pass - @classmethod def get_name(cls): """Get name of application package.""" diff --git a/aleksis/core/views.py b/aleksis/core/views.py index 45b15be491c57a71f0375d7a962c4ab398cbaa18..92f0bf2fc5d5fd863c9427f4acac9a65081c5b5f 100644 --- a/aleksis/core/views.py +++ b/aleksis/core/views.py @@ -77,7 +77,7 @@ def index(request: HttpRequest) -> HttpResponse: def offline(request: HttpRequest) -> HttpResponse: """Offline message for PWA.""" - return render(request, "core/offline.html") + return render(request, "core/pages/offline.html") def about(request: HttpRequest) -> HttpResponse: @@ -88,7 +88,7 @@ def about(request: HttpRequest) -> HttpResponse: filter(lambda a: isinstance(a, AppConfig), apps.get_app_configs()) ) - return render(request, "core/about.html", context) + return render(request, "core/pages/about.html", context) @permission_required("core.view_persons") @@ -106,7 +106,7 @@ def persons(request: HttpRequest) -> HttpResponse: RequestConfig(request).configure(persons_table) context["persons_table"] = persons_table - return render(request, "core/persons.html", context) + return render(request, "core/person/list.html", context) @permission_required( @@ -127,7 +127,7 @@ def person(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse: RequestConfig(request).configure(groups_table) context["groups_table"] = groups_table - return render(request, "core/person_full.html", context) + return render(request, "core/person/full.html", context) @permission_required("core.view_group", fn=objectgetter_optional(Group, None, False)) @@ -157,7 +157,7 @@ def group(request: HttpRequest, id_: int) -> HttpResponse: RequestConfig(request).configure(owners_table) context["owners_table"] = owners_table - return render(request, "core/group_full.html", context) + return render(request, "core/group/full.html", context) @permission_required("core.view_groups") @@ -173,7 +173,7 @@ def groups(request: HttpRequest) -> HttpResponse: RequestConfig(request).configure(groups_table) context["groups_table"] = groups_table - return render(request, "core/groups.html", context) + return render(request, "core/group/list.html", context) @permission_required("core.link_persons_accounts") @@ -193,7 +193,7 @@ def persons_accounts(request: HttpRequest) -> HttpResponse: context["persons_accounts_formset"] = persons_accounts_formset - return render(request, "core/persons_accounts.html", context) + return render(request, "core/person/accounts.html", context) @permission_required("core.assign_child_groups_to_groups") @@ -230,7 +230,7 @@ def groups_child_groups(request: HttpRequest) -> HttpResponse: context["group"] = group context["form"] = form - return render(request, "core/groups_child_groups.html", context) + return render(request, "core/group/child_groups.html", context) @permission_required( @@ -255,7 +255,7 @@ def edit_person(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse context["edit_person_form"] = edit_person_form - return render(request, "core/edit_person.html", context) + return render(request, "core/person/edit.html", context) def get_group_by_id(request: HttpRequest, id_: Optional[int] = None): @@ -282,22 +282,22 @@ def edit_group(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse: if request.method == "POST": if edit_group_form.is_valid(): - edit_group_form.save(commit=True) + group = edit_group_form.save(commit=True) messages.success(request, _("The group has been saved.")) - return redirect("groups") + return redirect("group_by_id", group.pk) context["edit_group_form"] = edit_group_form - return render(request, "core/edit_group.html", context) + return render(request, "core/group/edit.html", context) @permission_required("core.manage_data") def data_management(request: HttpRequest) -> HttpResponse: """View with special menu for data management.""" context = {} - return render(request, "core/data_management.html", context) + return render(request, "core/management/data_management.html", context) @permission_required("core.view_system_status") @@ -315,7 +315,7 @@ def system_status(request: HttpRequest) -> HttpResponse: results.append(TaskResult.objects.filter(task_name=job).last()) context["tasks"] = results - return render(request, "core/system_status.html", context) + return render(request, "core/pages/system_status.html", context) @permission_required( @@ -499,7 +499,7 @@ def edit_additional_field(request: HttpRequest, id_: Optional[int] = None) -> Ht context["edit_additional_field_form"] = edit_additional_field_form - return render(request, "core/edit_additional_field.html", context) + return render(request, "core/additional_field/edit.html", context) @permission_required("core.view_additionalfield") @@ -517,7 +517,7 @@ def additional_fields(request: HttpRequest) -> HttpResponse: RequestConfig(request).configure(additional_fields_table) context["additional_fields_table"] = additional_fields_table - return render(request, "core/additional_fields.html", context) + return render(request, "core/additional_field/list.html", context) @permission_required( @@ -557,7 +557,7 @@ def edit_group_type(request: HttpRequest, id_: Optional[int] = None) -> HttpResp context["edit_group_type_form"] = edit_group_type_form - return render(request, "core/edit_group_type.html", context) + return render(request, "core/group_type/edit.html", context) @permission_required("core.view_grouptype") @@ -573,7 +573,7 @@ def group_types(request: HttpRequest) -> HttpResponse: RequestConfig(request).configure(group_types_table) context["group_types_table"] = group_types_table - return render(request, "core/group_types.html", context) + return render(request, "core/group_type/list.html", context) @permission_required("core.delete_grouptype", fn=objectgetter_optional(GroupType, None, False))