diff --git a/aleksis/core/forms.py b/aleksis/core/forms.py index e1c0be7ef4f28e609c93f3b58208aa0ea4d58b3a..969cb4b22e9be1aa91f109d6a5b399cb4d4d8809 100644 --- a/aleksis/core/forms.py +++ b/aleksis/core/forms.py @@ -7,6 +7,7 @@ from django.utils.translation import gettext_lazy as _ from django_select2.forms import ModelSelect2MultipleWidget, Select2Widget from dynamic_preferences.forms import PreferenceForm +from image_cropping import ImageCropWidget from material import Fieldset, Layout, Row from .mixins import ExtensibleForm, SchoolTermRelatedExtensibleForm @@ -309,3 +310,13 @@ class SchoolTermForm(ExtensibleForm): class Meta: model = SchoolTerm exclude = [] + +class EditPersonPhotoForm(ExtensibleForm): + """Form to edit a persons photo.""" + + class Meta: + model = Person + fields = ["photo"] + widgets = { + 'photo': ImageCropWidget, + } diff --git a/aleksis/core/templates/core/person/edit_photo.html b/aleksis/core/templates/core/person/edit_photo.html new file mode 100644 index 0000000000000000000000000000000000000000..17e6c79bc0384b10bb9636723748aeaa471e67a1 --- /dev/null +++ b/aleksis/core/templates/core/person/edit_photo.html @@ -0,0 +1,23 @@ +{# -*- engine:django -*- #} + +{% extends "core/base.html" %} + +{% load i18n %} + +{% block extra_head %} + {{ photo_form.media }} +{% endblock %} + +{% block browser_title %}{% blocktrans %}Edit photo{% endblocktrans %}{% endblock %} +{% block page_title %}{% blocktrans %}Edit photo{% endblocktrans %}{% endblock %} + + +{% block content %} + + <form method="post" enctype="multipart/form-data"> + {% csrf_token %} + {{ photo_form }} + {% 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 index 80aff9b9fe0b2d3c4146929758430b3401bf5270..41bd848bc22df7308b1ef377b291633bcaf50778 100644 --- a/aleksis/core/templates/core/person/full.html +++ b/aleksis/core/templates/core/person/full.html @@ -22,6 +22,10 @@ <i class="material-icons left">edit</i> {% trans "Edit" %} </a> + <a href="{% url 'edit_person_photo_by_id' person.id %}" class="btn waves-effect waves-light"> + <i class="material-icons left">insert_photo</i> + {% trans "Edit photo" %} + </a> {% endif %} {% if can_delete_person %} diff --git a/aleksis/core/urls.py b/aleksis/core/urls.py index 51048e5c83bdb6c540254a36754f32cdc3059591..19c4a9c5b1d9953627240b39e3eba9d290cd28b9 100644 --- a/aleksis/core/urls.py +++ b/aleksis/core/urls.py @@ -32,6 +32,7 @@ urlpatterns = [ path("person/create", views.edit_person, name="create_person"), path("person/<int:id_>", views.person, name="person_by_id"), path("person/<int:id_>/edit", views.edit_person, name="edit_person_by_id"), + path("person/<int:id_>/photo/edit", views.edit_person_photo, name="edit_person_photo_by_id"), path("person/<int:id_>/delete", views.delete_person, name="delete_person_by_id"), path("groups", views.groups, name="groups"), path("groups/additional_fields", views.additional_fields, name="additional_fields"), diff --git a/aleksis/core/views.py b/aleksis/core/views.py index af2f285a7ec48c5499015c9f54388818e68d2bc1..9ab49dfcb85d95f060c89c8b02e346cec15a9ea1 100644 --- a/aleksis/core/views.py +++ b/aleksis/core/views.py @@ -678,3 +678,25 @@ def delete_group_type(request: HttpRequest, id_: int) -> HttpResponse: messages.success(request, _("The group type has been deleted.")) return redirect("group_types") + +@permission_required("core.edit_person", fn=objectgetter_optional(Person)) +def edit_person_photo(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse: + """Edit view for a single person, defaulting to logged-in person.""" + context = {} + + person = get_object_or_404(Person, id_) + context["person"] = person + + # Edit form for existing group + edit_person_photo_form = EditPersonPhotoForm( + request.POST or None, request.FILES or None, instance=person + ) + if request.method == "POST": + if edit_person_photo_form.is_valid(): + with reversion.create_revision(): + edit_person_photo_form.save(commit=True) + messages.success(request, _("The person has been saved.")) + + context["edit_person_photo_form"] = edit_person_photo_form + + return render(request, "core/person/edit_photo.html", context)