diff --git a/aleksis/core/forms.py b/aleksis/core/forms.py index 0fb1187ebde9f49de19a1dc51ab3390b0644d271..cd7f2184544e8aa464076a6d65a76be94cb1f42d 100644 --- a/aleksis/core/forms.py +++ b/aleksis/core/forms.py @@ -9,10 +9,12 @@ from django.utils import timezone from django.utils.translation import gettext_lazy as _ from django_select2.forms import ModelSelect2MultipleWidget, Select2Widget +from dynamic_preferences.forms import PreferenceForm from material import Layout, Fieldset, Row from .mixins import ExtensibleForm from .models import Group, Person, Announcement, AnnouncementRecipient +from .registries import site_preferences_registry, person_preferences_registry, group_preferences_registry class PersonAccountForm(forms.ModelForm): @@ -261,3 +263,16 @@ class AnnouncementForm(ExtensibleForm): class ChildGroupsForm(forms.Form): child_groups = forms.ModelMultipleChoiceField(queryset=Group.objects.all()) + + +class SitePreferenceForm(PreferenceForm): + registry = site_preferences_registry + + +class PersonPreferenceForm(PreferenceForm): + registry = person_preferences_registry + + +class GroupPreferenceForm(PreferenceForm): + registry = group_preferences_registry + diff --git a/aleksis/core/static/js/main.js b/aleksis/core/static/js/main.js index b625c105f4e0e8a51b581104049bd1d76bcbc200..dd57cbe262eb60e24646b680fa435c940008c4aa 100644 --- a/aleksis/core/static/js/main.js +++ b/aleksis/core/static/js/main.js @@ -59,6 +59,9 @@ $(document).ready( function () { // Initialize Modals [MAT] $('.modal').modal(); + // Intialize Tabs [Materialize] + $('.tabs').tabs(); + $('table.datatable').each(function (index) { $(this).DataTable({ "paging": false diff --git a/aleksis/core/templates/dynamic_preferences/form.html b/aleksis/core/templates/dynamic_preferences/form.html new file mode 100644 index 0000000000000000000000000000000000000000..d8de37802c09a14327b0d949b5935fb69660c666 --- /dev/null +++ b/aleksis/core/templates/dynamic_preferences/form.html @@ -0,0 +1,28 @@ +{% extends "core/base.html" %} +{% load i18n material_form %} + +{% block browser_title %} + {% trans "Preferences" %} +{% endblock %} +{% block page_title %} + {% if registry_name == "site" %} + {% blocktrans %}Site preferences{% endblocktrans %} + {% elif registry_name == "person" and instance == request.user.person %} + {% blocktrans %}My preferences{% endblocktrans %} + {% else %} + {% blocktrans with instace=instance %}Preferences for {{ instance }}{% endblocktrans %} + {% endif %} +{% endblock %} + +{% block content %} + <div class="row"> + {% include "dynamic_preferences/sections.html" with registry=registry sections=registry.sections active_section=section %} + </div> + <div class="row"> + <form action="" enctype="multipart/form-data" method="post"> + {% csrf_token %} + {% form form=form %}{% endform %} + {% include "core/save_button.html" with caption=_("Save preferences") %} + </form> + </div> +{% endblock %} diff --git a/aleksis/core/templates/dynamic_preferences/sections.html b/aleksis/core/templates/dynamic_preferences/sections.html new file mode 100644 index 0000000000000000000000000000000000000000..8630933ba01305f14fc99f4d5bd0a0e02d4dcd1e --- /dev/null +++ b/aleksis/core/templates/dynamic_preferences/sections.html @@ -0,0 +1,18 @@ +{% load i18n %} +<ul class="tabs"> + <li class="tab "> + <a href="{% url registry_url %}" + class="{% if not active_section %}active{% endif %}" + target="_self"> + {% trans "All" %} + </a> + {% for section in registry.section_objects.values %} + <li class="tab"> + <a class="{% if active_section == section.name %}active{% endif %}" + href="{% url registry_url section %}" + target="_self"> + {{ section.verbose_name }} + </a> + </li> + {% endfor %} +</ul> diff --git a/aleksis/core/urls.py b/aleksis/core/urls.py index be3143e994af82371519416e066e9fb99fe42e50..c8995b4c3cce5f80db99c99f8783cdedbcaf636a 100644 --- a/aleksis/core/urls.py +++ b/aleksis/core/urls.py @@ -48,6 +48,18 @@ urlpatterns = [ path("jsreverse.js", urls_js, name='js_reverse'), path("calendarweek_i18n.js", calendarweek.django.i18n_js, name="calendarweek_i18n_js"), path('gettext.js', JavaScriptCatalog.as_view(), name='javascript-catalog'), + path("preferences/site/", views.preferences, {"registry_name": "site"}, name="preferences_site"), + path("preferences/person/", views.preferences, {"registry_name": "person"}, name="preferences_person"), + path("preferences/group/", views.preferences, {"registry_name": "group"}, name="preferences_group"), + path("preferences/site/<int:pk>/", views.preferences, {"registry_name": "site"}, name="preferences_site"), + path("preferences/person/<int:pk>/", views.preferences, {"registry_name": "person"}, name="preferences_person"), + path("preferences/group/<int:pk>/", views.preferences, {"registry_name": "group"}, name="preferences_group"), + path("preferences/site/<int:pk>/<str:section>/", views.preferences, {"registry_name": "site"}, name="preferences_site" ), + path("preferences/person/<int:pk>/<str:section>/", views.preferences, {"registry_name": "person"}, name="preferences_person"), + path("preferences/group/<int:pk>/<str:section>/", views.preferences, {"registry_name": "group"}, name="preferences_group"), + path("preferences/site/<str:section>/", views.preferences, {"registry_name": "site"}, name="preferences_site"), + path("preferences/person/<str:section>/", views.preferences, {"registry_name": "person"}, name="preferences_person"), + path("preferences/group/<str:section>/", views.preferences, {"registry_name": "group"}, name="preferences_group"), ] # Serve static files from STATIC_ROOT to make it work with runserver diff --git a/aleksis/core/views.py b/aleksis/core/views.py index 4f504300612f3c6e3f326a7c0a4ea2d9ffe6efff..f5face969248b2d8762312d5b20e405967f813ae 100644 --- a/aleksis/core/views.py +++ b/aleksis/core/views.py @@ -5,11 +5,12 @@ from django.apps import apps from django.contrib.auth.mixins import PermissionRequiredMixin from django.core.exceptions import PermissionDenied from django.core.paginator import Paginator -from django.http import Http404, HttpRequest, HttpResponse +from django.http import HttpRequest, HttpResponse, HttpResponseNotFound from django.shortcuts import get_object_or_404, redirect, render from django.utils.translation import gettext_lazy as _ from django_tables2 import RequestConfig +from dynamic_preferences.forms import preference_form_builder from guardian.shortcuts import get_objects_for_user from haystack.inputs import AutoQuery from haystack.query import SearchQuerySet @@ -23,8 +24,12 @@ from .forms import ( PersonsAccountsFormSet, AnnouncementForm, ChildGroupsForm, + SitePreferenceForm, + PersonPreferenceForm, + GroupPreferenceForm, ) from .models import Activity, Group, Notification, Person, DashboardWidget, Announcement +from .registries import site_preferences_registry, group_preferences_registry, person_preferences_registry from .tables import GroupsTable, PersonsTable from .util import messages from .util.apps import AppConfig @@ -369,3 +374,49 @@ class PermissionSearchView(PermissionRequiredMixin, SearchView): if not self.has_permission(): return self.handle_no_permission() return render(self.request, self.template, context) + + +def preferences(request: HttpRequest, registry_name: str = "person", pk: Optional[int] = None, section: Optional[str] = None) -> HttpResponse: + """ View for changing preferences """ + + context = {} + + if registry_name == "site": + registry = site_preferences_registry + instance = request.site + form_class = SitePreferenceForm + + elif registry_name == "person": + registry = person_preferences_registry + if pk: + instance = get_object_or_404(Person, pk=pk) + else: + instance = request.user.person + form_class = PersonPreferenceForm + + elif registry_name == "group": + registry = group_preferences_registry + instance = get_object_or_404(Group, pk=pk) + form_class = GroupPreferenceForm + + else: + return HttpResponseNotFound() + + form_class = preference_form_builder(form_class, instance=instance, section=section) + + if request.method == "POST": + form = form_class(request.POST) + if form.is_valid(): + form.update_preferences() + messages.success(request, _("The preferences has been saved successfully.")) + else: + form = form_class() + + context["registry"] = registry + context["registry_name"] = registry_name + context["section"] = section + context["registry_url"] = "preferences_" + registry_name + context["form"] = form + context["instance"] = instance + + return render(request, "dynamic_preferences/form.html", context)