From 9b1dbe3d0b3bfbf94a73a9b594c102fea5a8ec6b Mon Sep 17 00:00:00 2001 From: Tom Teichler <tom.teichler@teckids.org> Date: Thu, 4 Jun 2020 17:44:40 +0200 Subject: [PATCH] Revert "Revert "Merge branch '239-frontend-for-additional-fields-for-group' into 'master'"" This reverts commit 53d82e486346ff1811e29d9e4b00e007922725fd. --- aleksis/core/forms.py | 13 +++- aleksis/core/menus.py | 11 +++ aleksis/core/rules.py | 29 ++++++- aleksis/core/tables.py | 12 +++ .../templates/core/additional_fields.html | 18 +++++ .../templates/core/edit_additional_field.html | 17 ++++ aleksis/core/urls.py | 16 ++++ aleksis/core/views.py | 78 ++++++++++++++++++- 8 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 aleksis/core/templates/core/additional_fields.html create mode 100644 aleksis/core/templates/core/edit_additional_field.html diff --git a/aleksis/core/forms.py b/aleksis/core/forms.py index b2fd7980f..abd45aabd 100644 --- a/aleksis/core/forms.py +++ b/aleksis/core/forms.py @@ -10,7 +10,7 @@ from dynamic_preferences.forms import PreferenceForm from material import Fieldset, Layout, Row from .mixins import ExtensibleForm -from .models import Announcement, Group, GroupType, Person +from .models import AdditionalField, Announcement, Group, GroupType, Person from .registries import ( group_preferences_registry, person_preferences_registry, @@ -127,7 +127,7 @@ class EditGroupForm(ExtensibleForm): layout = Layout( Fieldset(_("Common data"), "name", "short_name", "group_type"), Fieldset(_("Persons"), "members", "owners", "parent_groups"), - Fieldset(_("Additional fields"), "additional_fields"), + Fieldset(_("Additional data"), "additional_fields"), ) class Meta: @@ -151,6 +151,7 @@ class EditGroupForm(ExtensibleForm): "parent_groups": ModelSelect2MultipleWidget( search_fields=["name__icontains", "short_name__icontains"] ), + "additional_fields": ModelSelect2MultipleWidget(search_fields=["title__icontains",]), } @@ -283,6 +284,14 @@ class GroupPreferenceForm(PreferenceForm): registry = group_preferences_registry +class EditAdditionalFieldForm(forms.ModelForm): + """Form to manage additional fields.""" + + class Meta: + model = AdditionalField + exclude = [] + + class EditGroupTypeForm(forms.ModelForm): """Form to manage group types.""" diff --git a/aleksis/core/menus.py b/aleksis/core/menus.py index 4767a8f34..c1b19bb39 100644 --- a/aleksis/core/menus.py +++ b/aleksis/core/menus.py @@ -186,6 +186,17 @@ MENUS = { ) ], }, + { + "name": _("Additional fields"), + "url": "additional_fields", + "icon": "style", + "validators": [ + ( + "aleksis.core.util.predicates.permission_validator", + "core.view_additionalfield", + ) + ], + }, ], }, ], diff --git a/aleksis/core/rules.py b/aleksis/core/rules.py index 3325f136a..4f97eafdd 100644 --- a/aleksis/core/rules.py +++ b/aleksis/core/rules.py @@ -1,6 +1,6 @@ from rules import add_perm, always_allow -from .models import Announcement, Group, GroupType, Person +from .models import AdditionalField, Announcement, Group, GroupType, Person from .util.predicates import ( has_any_object, has_global_perm, @@ -195,6 +195,33 @@ change_group_preferences = has_person & ( ) add_perm("core.change_group_preferences", change_group_preferences) + +# Edit additional field +change_additional_field_predicate = has_person & ( + has_global_perm("core.change_additionalfield") | has_object_perm("core.change_additionalfield") +) +add_perm("core.change_additionalfield", change_additional_field_predicate) + +# Edit additional field +create_additional_field_predicate = has_person & ( + has_global_perm("core.create_additionalfield") | has_object_perm("core.create_additionalfield") +) +add_perm("core.create_additionalfield", create_additional_field_predicate) + + +# Delete additional field +delete_additional_field_predicate = has_person & ( + has_global_perm("core.delete_additionalfield") | has_object_perm("core.delete_additionalfield") +) +add_perm("core.delete_additionalfield", delete_additional_field_predicate) + +# View additional fields +view_additional_field_predicate = has_person & ( + has_global_perm("core.view_additionalfield") + | has_any_object("core.view_additionalfield", AdditionalField) +) +add_perm("core.view_additionalfield", view_additional_field_predicate) + # Edit group type change_group_type_predicate = has_person & ( has_global_perm("core.change_grouptype") | has_object_perm("core.change_grouptype") diff --git a/aleksis/core/tables.py b/aleksis/core/tables.py index ff8fd871e..8ca4fd593 100644 --- a/aleksis/core/tables.py +++ b/aleksis/core/tables.py @@ -24,6 +24,18 @@ class GroupsTable(tables.Table): short_name = tables.LinkColumn("group_by_id", args=[A("id")]) +class AdditionalFieldsTable(tables.Table): + """Table to list group types.""" + + class Meta: + attrs = {"class": "responsive-table hightlight"} + + title = tables.LinkColumn("edit_additional_field_by_id", args=[A("id")]) + delete = tables.LinkColumn( + "delete_additional_field_by_id", args=[A("id")], verbose_name=_("Delete"), text=_("Delete") + ) + + class GroupTypesTable(tables.Table): """Table to list group types.""" diff --git a/aleksis/core/templates/core/additional_fields.html b/aleksis/core/templates/core/additional_fields.html new file mode 100644 index 000000000..1ba2a77a3 --- /dev/null +++ b/aleksis/core/templates/core/additional_fields.html @@ -0,0 +1,18 @@ +{# -*- engine:django -*- #} + +{% extends "core/base.html" %} + +{% load i18n %} +{% load render_table from django_tables2 %} + +{% block browser_title %}{% blocktrans %}Additional fields{% endblocktrans %}{% endblock %} +{% block page_title %}{% blocktrans %}Additional fields{% endblocktrans %}{% endblock %} + +{% block content %} + <a class="btn green waves-effect waves-light" href="{% url 'create_additional_field' %}"> + <i class="material-icons left">add</i> + {% trans "Create additional field" %} + </a> + + {% render_table additional_fields_table %} +{% endblock %} diff --git a/aleksis/core/templates/core/edit_additional_field.html b/aleksis/core/templates/core/edit_additional_field.html new file mode 100644 index 000000000..b1487eb25 --- /dev/null +++ b/aleksis/core/templates/core/edit_additional_field.html @@ -0,0 +1,17 @@ +{# -*- engine:django -*- #} + +{% extends "core/base.html" %} +{% load material_form i18n %} + +{% block browser_title %}{% blocktrans %}Edit additional field{% endblocktrans %}{% endblock %} +{% block page_title %}{% blocktrans %}Edit additional field{% endblocktrans %}{% endblock %} + +{% block content %} + + <form method="post"> + {% csrf_token %} + {% form form=edit_additional_field_form %}{% endform %} + {% include "core/save_button.html" %} + </form> + +{% endblock %} diff --git a/aleksis/core/urls.py b/aleksis/core/urls.py index 47cb1d63c..07736f7b8 100644 --- a/aleksis/core/urls.py +++ b/aleksis/core/urls.py @@ -27,7 +27,23 @@ urlpatterns = [ path("person/<int:id_>", views.person, name="person_by_id"), path("person/<int:id_>/edit", views.edit_person, name="edit_person_by_id"), path("groups", views.groups, name="groups"), + path("groups/additional_fields", views.additional_fields, name="additional_fields"), path("groups/child_groups/", views.groups_child_groups, name="groups_child_groups"), + path( + "groups/additional_field/<int:id_>/edit", + views.edit_additional_field, + name="edit_additional_field_by_id", + ), + path( + "groups/additional_field/create", + views.edit_additional_field, + name="create_additional_field", + ), + path( + "groups/additional_field/<int:id_>/delete", + views.delete_additional_field, + name="delete_additional_field_by_id", + ), path("group/create", views.edit_group, name="create_group"), path("group/<int:id_>", views.group, name="group_by_id"), path("group/<int:id_>/edit", views.edit_group, name="edit_group_by_id"), diff --git a/aleksis/core/views.py b/aleksis/core/views.py index b5415c45d..45b15be49 100644 --- a/aleksis/core/views.py +++ b/aleksis/core/views.py @@ -21,6 +21,7 @@ from .filters import GroupFilter from .forms import ( AnnouncementForm, ChildGroupsForm, + EditAdditionalFieldForm, EditGroupForm, EditGroupTypeForm, EditPersonForm, @@ -29,13 +30,21 @@ from .forms import ( PersonsAccountsFormSet, SitePreferenceForm, ) -from .models import Announcement, DashboardWidget, Group, GroupType, Notification, Person +from .models import ( + AdditionalField, + Announcement, + DashboardWidget, + Group, + GroupType, + Notification, + Person, +) from .registries import ( group_preferences_registry, person_preferences_registry, site_preferences_registry, ) -from .tables import GroupsTable, GroupTypesTable, PersonsTable +from .tables import AdditionalFieldsTable, GroupsTable, GroupTypesTable, PersonsTable from .util import messages from .util.apps import AppConfig from .util.core_helpers import objectgetter_optional @@ -458,6 +467,71 @@ def preferences( return render(request, "dynamic_preferences/form.html", context) +@permission_required( + "core.change_additionalfield", fn=objectgetter_optional(AdditionalField, None, False) +) +def edit_additional_field(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse: + """View to edit or create a additional_field.""" + context = {} + + additional_field = objectgetter_optional(AdditionalField, None, False)(request, id_) + context["additional_field"] = additional_field + + if id_: + # Edit form for existing additional_field + edit_additional_field_form = EditAdditionalFieldForm( + request.POST or None, instance=additional_field + ) + else: + if request.user.has_perm("core.create_additionalfield"): + # Empty form to create a new additional_field + edit_additional_field_form = EditAdditionalFieldForm(request.POST or None) + else: + raise PermissionDenied() + + if request.method == "POST": + if edit_additional_field_form.is_valid(): + edit_additional_field_form.save(commit=True) + + messages.success(request, _("The additional_field has been saved.")) + + return redirect("additional_fields") + + context["edit_additional_field_form"] = edit_additional_field_form + + return render(request, "core/edit_additional_field.html", context) + + +@permission_required("core.view_additionalfield") +def additional_fields(request: HttpRequest) -> HttpResponse: + """List view for listing all additional fields.""" + context = {} + + # Get all additional fields + additional_fields = get_objects_for_user( + request.user, "core.view_additionalfield", AdditionalField + ) + + # Build table + additional_fields_table = AdditionalFieldsTable(additional_fields) + RequestConfig(request).configure(additional_fields_table) + context["additional_fields_table"] = additional_fields_table + + return render(request, "core/additional_fields.html", context) + + +@permission_required( + "core.delete_additionalfield", fn=objectgetter_optional(AdditionalField, None, False) +) +def delete_additional_field(request: HttpRequest, id_: int) -> HttpResponse: + """View to delete an additional field.""" + additional_field = objectgetter_optional(AdditionalField, None, False)(request, id_) + additional_field.delete() + messages.success(request, _("The additional field has been deleted.")) + + return redirect("additional_fields") + + @permission_required("core.change_grouptype", fn=objectgetter_optional(GroupType, None, False)) def edit_group_type(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse: """View to edit or create a group_type.""" -- GitLab