Skip to content

Commit ac3061b

Browse files
committed
[#1160] Added cropping for profile image
1 parent 4b09a8c commit ac3061b

File tree

15 files changed

+143
-8
lines changed

15 files changed

+143
-8
lines changed

requirements/base.in

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ django-open-forms-client
4747
django-htmx
4848
playwright
4949
django-yubin
50+
django-image-cropping
5051

5152
# API libraries
5253
djangorestframework

requirements/base.txt

+5-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@ django==3.2.15
111111
django-admin-index==1.5.0
112112
# via -r requirements/base.in
113113
django-appconf==1.0.5
114-
# via django-timeline-logger
114+
# via
115+
# django-image-cropping
116+
# django-timeline-logger
115117
django-autoslug==1.9.8
116118
# via -r requirements/base.in
117119
django-axes==5.25.0
@@ -151,6 +153,8 @@ django-hijack==3.0.4
151153
# via -r requirements/base.in
152154
django-htmx==1.13.0
153155
# via -r requirements/base.in
156+
django-image-cropping==1.7
157+
# via -r requirements/base.in
154158
django-import-export==2.6.1
155159
# via -r requirements/base.in
156160
django-ipware==4.0.0

requirements/ci.txt

+5
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ django-appconf==1.0.5
176176
# via
177177
# -c requirements/base.txt
178178
# -r requirements/base.txt
179+
# django-image-cropping
179180
# django-timeline-logger
180181
django-autoslug==1.9.8
181182
# via
@@ -250,6 +251,10 @@ django-htmx==1.13.0
250251
# via
251252
# -c requirements/base.txt
252253
# -r requirements/base.txt
254+
django-image-cropping==1.7
255+
# via
256+
# -c requirements/base.txt
257+
# -r requirements/base.txt
253258
django-import-export==2.6.1
254259
# via
255260
# -c requirements/base.txt

requirements/dev.txt

+5
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ django-appconf==1.0.5
201201
# via
202202
# -c requirements/ci.txt
203203
# -r requirements/ci.txt
204+
# django-image-cropping
204205
# django-timeline-logger
205206
django-autoslug==1.9.8
206207
# via
@@ -279,6 +280,10 @@ django-htmx==1.13.0
279280
# via
280281
# -c requirements/ci.txt
281282
# -r requirements/ci.txt
283+
django-image-cropping==1.7
284+
# via
285+
# -c requirements/ci.txt
286+
# -r requirements/ci.txt
282287
django-import-export==2.6.1
283288
# via
284289
# -c requirements/ci.txt

src/open_inwoner/accounts/admin.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from django.utils.html import format_html
77
from django.utils.translation import ngettext, ugettext_lazy as _
88

9+
from image_cropping import ImageCroppingMixin
910
from privates.admin import PrivateMediaMixin
1011

1112
from open_inwoner.utils.mixins import UUIDAdminFirstInOrder
@@ -52,7 +53,7 @@ def clean(self, *args, **kwargs):
5253

5354

5455
@admin.register(User)
55-
class _UserAdmin(UserAdmin):
56+
class _UserAdmin(ImageCroppingMixin, UserAdmin):
5657
form = _UserChangeForm
5758
add_form = _UserCreationForm
5859
hijack_success_url = reverse_lazy("root")
@@ -74,6 +75,7 @@ class _UserAdmin(UserAdmin):
7475
"oidc_id",
7576
"birthday",
7677
"image",
78+
"cropping",
7779
"street",
7880
"housenumber",
7981
"postcode",

src/open_inwoner/accounts/forms.py

+3
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,15 @@ class Meta:
6969
"email",
7070
"phonenumber",
7171
"image",
72+
"cropping",
7273
)
7374

7475
def __init__(self, user, *args, **kwargs):
7576
super().__init__(*args, **kwargs)
7677

7778
if user.contact_type != ContactTypeChoices.begeleider:
7879
del self.fields["image"]
80+
del self.fields["cropping"]
7981

8082

8183
class UserForm(BaseUserForm):
@@ -93,6 +95,7 @@ class Meta:
9395
"postcode",
9496
"city",
9597
"image",
98+
"cropping",
9699
)
97100

98101

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Generated by Django 3.2.15 on 2023-03-07 07:52
2+
3+
from django.db import migrations
4+
import image_cropping.fields
5+
import open_inwoner.accounts.models
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
("accounts", "0055_user_image"),
12+
]
13+
14+
operations = [
15+
migrations.AddField(
16+
model_name="user",
17+
name="cropping",
18+
field=image_cropping.fields.ImageRatioField(
19+
"image",
20+
"150x150",
21+
adapt_rotation=False,
22+
allow_fullsize=False,
23+
free_crop=False,
24+
help_text=None,
25+
hide_image_field=False,
26+
size_warning=True,
27+
verbose_name="cropping",
28+
),
29+
),
30+
migrations.AlterField(
31+
model_name="user",
32+
name="image",
33+
field=image_cropping.fields.ImageCropField(
34+
blank=True,
35+
help_text="Image",
36+
null=True,
37+
upload_to=open_inwoner.accounts.models.generate_uuid_image_name,
38+
verbose_name="Image",
39+
),
40+
),
41+
]

src/open_inwoner/accounts/models.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from django.utils.crypto import get_random_string
1212
from django.utils.translation import ugettext_lazy as _
1313

14+
from image_cropping import ImageCropField, ImageRatioField
1415
from localflavor.nl.models import NLBSNField, NLZipCodeField
1516
from mail_editor.helpers import find_template
1617
from privates.storages import PrivateMediaFileSystemStorage
@@ -73,13 +74,14 @@ class User(AbstractBaseUser, PermissionsMixin):
7374
max_length=15,
7475
validators=[validate_phone_number],
7576
)
76-
image = models.ImageField(
77+
image = ImageCropField(
7778
verbose_name=_("Image"),
7879
null=True,
7980
blank=True,
8081
upload_to=generate_uuid_image_name,
8182
help_text=_("Image"),
8283
)
84+
cropping = ImageRatioField("image", "150x150", size_warning=True)
8385
is_staff = models.BooleanField(
8486
verbose_name=_("Staff status"),
8587
default=False,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{% load form_tags %}
2+
3+
<div class="form__control {{ extra_classes|default:"" }}">
4+
<label class="label">
5+
{{ field.label }}
6+
{{ field|addclass:"image-ratio" }}
7+
{% if field.help_text and not no_help %}
8+
<p class="p">{{ field.help_text }}</p>
9+
{% endif %}
10+
11+
{% if field.errors %}
12+
{% errors errors=field.errors %}
13+
{% endif %}
14+
</label>
15+
</div>

src/open_inwoner/components/templatetags/form_tags.py

+5
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,11 @@ def date_field(field, **kwargs):
272272
return {**kwargs, "field": field}
273273

274274

275+
@register.inclusion_tag("components/Form/ImageCrop.html")
276+
def image_crop(field, **kwargs):
277+
return {**kwargs, "field": field}
278+
279+
275280
@register.inclusion_tag("components/Form/Search.html")
276281
def search(field, **kwargs):
277282
"""

src/open_inwoner/conf/base.py

+10
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@
145145
"localflavor",
146146
"treebeard",
147147
"easy_thumbnails", # used by filer
148+
"image_cropping",
148149
"filer",
149150
"mptt",
150151
"hijack.contrib.admin",
@@ -525,6 +526,15 @@
525526
},
526527
}
527528

529+
from easy_thumbnails.conf import Settings as thumbnail_settings
530+
531+
THUMBNAIL_PROCESSORS = (
532+
"image_cropping.thumbnail_processors.crop_corners",
533+
) + thumbnail_settings.THUMBNAIL_PROCESSORS
534+
535+
IMAGE_CROPPING_BACKEND = "image_cropping.backends.easy_thumbs.EasyThumbnailsBackend"
536+
IMAGE_CROPPING_JQUERY_URL = "/static/admin/js/vendor/jquery/jquery.min.js"
537+
528538
SENDFILE_ROOT = PRIVATE_MEDIA_ROOT
529539
SENDFILE_BACKEND = "django_sendfile.backends.simple"
530540
PRIVATE_MEDIA_URL = "/private_files/"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.crop-thumb {
2+
@extend .input;
3+
4+
margin-top: var(--spacing-medium);
5+
}

src/open_inwoner/scss/components/_index.scss

+1
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,4 @@
8585
@import './modal/modal';
8686
@import './Emoji/Emoji.scss';
8787
@import './Profile/personal-information';
88+
@import './Profile/edit.scss';

src/open_inwoner/templates/master.html

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
}
2727
</style>
2828
{% block extra_css %}{% endblock %}
29+
{% block extra_head %}{% endblock %}
2930

3031
{% include "analytics/google.html" %}
3132
{% include "analytics/matomo.html" %}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,45 @@
11
{% extends 'master.html' %}
2-
{% load i18n l10n link_tags file_tags button_tags utils icon_tags form_tags %}
2+
{% load i18n l10n form_tags %}
3+
4+
{% block extra_head %}
5+
{{form.media}}
6+
{% endblock %}
37

48
{% block content %}
5-
<h1 class="h1" id="title">
6-
{% trans "Profiel bewerken" %}
7-
</h1>
9+
<h1 class="h1" id="title">
10+
{% trans "Profiel bewerken" %}
11+
</h1>
12+
13+
{% render_form id="profile-edit" method="POST" form=form form_action=form_action enctype="multipart/form-data" %}
14+
{% csrf_token %}
15+
16+
{% with request.user as user %}
17+
{% if user.is_digid_and_brp %}
18+
{% input form.display_name %}
19+
{% input form.email %}
20+
{% input form.phonenumber %}
21+
{% if user.contact_type == "begeleider" %}
22+
{% input form.image no_help=True %}
23+
{% image_crop form.cropping %}
24+
{% endif %}
25+
{% else %}
26+
{% input form.first_name %}
27+
{% input form.last_name %}
28+
{% input form.display_name %}
29+
{% input form.email %}
30+
{% input form.phonenumber %}
31+
{% date_field form.birthday no_help=True %}
32+
{% input form.street %}
33+
{% input form.housenumber %}
34+
{% input form.postcode %}
35+
{% input form.city %}
36+
{% if user.contact_type == "begeleider" %}
37+
{% input form.image no_help=True %}
38+
{% image_crop form.cropping %}
39+
{% endif %}
40+
{% endif %}
41+
{% endwith %}
42+
{% form_actions primary_text=_("Opslaan") primary_icon="arrow_forward" secondary_href='accounts:my_profile' secondary_text=_('Terug') secondary_icon='arrow_backward' secondary_icon_position="before" enctype="multipart/form-data" %}
43+
{% endrender_form %}
844

9-
{% form form_object=form method="POST" id="profile-edit" submit_text=_("Opslaan") secondary_href='accounts:my_profile' secondary_text=_('Terug') secondary_icon='arrow_backward' secondary_icon_position="before" enctype="multipart/form-data" %}
1045
{% endblock content %}

0 commit comments

Comments
 (0)