Skip to content

Commit

Permalink
Fix issue with custom icons which are higher than large.
Browse files Browse the repository at this point in the history
  • Loading branch information
genglert committed Nov 28, 2024
1 parent e01a2f8 commit a828ee1
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

Users side :
------------
# The render of custom menu icons has been fixed for non-square images.
# In mass-import form, the selector for properties was not our expected widget.
# In menu entries with custom URLs, links are now opened in a new tab.
# Some escaping issues have been fixed.
Expand Down
25 changes: 23 additions & 2 deletions creme/creme_core/templatetags/creme_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import logging
from base64 import b64encode
from io import BytesIO
from os.path import splitext

from django.conf import settings
Expand All @@ -30,6 +31,7 @@
from django.utils.html import urlize as django_urlize
from django.utils.safestring import mark_safe
from django.utils.translation import gettext as _
from PIL.Image import open as open_img

from ..gui.icons import (
BaseIcon,
Expand Down Expand Up @@ -139,14 +141,33 @@ def render(this, css_class=''):

with open(this.path, 'rb') as img:
_base_path, extension = splitext(path)
img_data = b64encode(img.read()).decode()
file_data = img.read()

# TODO: store width & height?
with open_img(BytesIO(file_data)) as img:
width, height = img.size

img_data = b64encode(file_data).decode()

if width > height:
size_attr = 'width'
# NB: we pad in order to center vertically the image
# tips: "this.size * height / width" gives the scaled height
padding = (this.size - int(round(this.size * height / width))) // 2
style = f'padding-top: {padding}px;' if padding else ''
else:
size_attr = 'height'
style = ''

return format_html(
'<img src="{url}" {attrs}title="{label}" alt="{label}" width="{size}px"/>',
'<img src="{url}" {attrs}title="{label}" alt="{label}" '
'{size_attr}="{size}px" style="{style}"/>',
size_attr=size_attr,
size=this.size,
label=this.label,
attrs=format_html('class="{}" ', final_css_class) if final_css_class else '',
url=f'data:image/{extension[1:]};base64, {img_data}',
style=style,
)

return InlinedIcon(path, size=size_px, label=label)
Expand Down
34 changes: 32 additions & 2 deletions creme/creme_core/tests/templatetags/test_creme_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,8 +443,9 @@ def test_widget_icon_instance(self):
render,
)

def test_widget_icon_data01(self):
def test_widget_icon_data__high(self):
path = Path(
# 16 x 16 px
settings.CREME_ROOT, 'static', 'icecream', 'images', 'remove_16.png',
)
self.assertTrue(path.exists())
Expand All @@ -466,14 +467,43 @@ def test_widget_icon_data01(self):
self.assertFalse(dom.children)

get_attribute = dict(dom.attributes).get
self.assertEqual('22px', get_attribute('width'))
self.assertEqual('22px', get_attribute('height'))
self.assertEqual(label, get_attribute('alt'))
self.assertEqual(label, get_attribute('title'))
self.assertEqual('', get_attribute('style'))
self.assertStartsWith(
get_attribute('src', ''),
'data:image/png;base64, iVBORw0KGgoAAAANSUh',
)

def test_widget_icon_data__large(self):
path = Path(
# 89 x 40 px
settings.CREME_ROOT, 'static', 'common', 'images', 'creme_powered.png',
)
self.assertTrue(path.exists())

label = 'Large image'

with self.assertNoException():
render = Template(
r'{% load creme_widgets %}'
r'{% widget_icon data=path label=label size="header-menu-home" %}'
).render(Context({
'THEME_NAME': 'icecream',
'path': path,
'label': label,
}))

dom = assert_and_parse_html(self, render, 'Rendered icon is not valid HTML', None)
self.assertEqual('img', dom.name)
self.assertFalse(dom.children)

get_attribute = dict(dom.attributes).get
self.assertEqual('30px', get_attribute('width'))
self.assertEqual('padding-top: 8px;', get_attribute('style'))
self.assertEqual(label, get_attribute('title'))

def test_widget_icon_named_error01(self):
with self.assertRaises(TemplateSyntaxError) as cm:
Template(
Expand Down

0 comments on commit a828ee1

Please sign in to comment.