Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: site icon/logo modes #194

Merged
merged 1 commit into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,16 @@ UNFOLD = {
"SITE_TITLE": None,
"SITE_HEADER": None,
"SITE_URL": "/",
"SITE_ICON": lambda request: static("logo.svg"),
# "SITE_ICON": lambda request: static("icon.svg"), # both modes, optimise for 32px height
"SITE_ICON": {
"light": lambda request: static("icon-light.svg"), # light mode
"dark": lambda request: static("icon-dark.svg"), # dark mode
},
# "SITE_LOGO": lambda request: static("logo.svg"), # both modes, optimise for 32px height
"SITE_LOGO": {
"light": lambda request: static("logo-light.svg"), # light mode
"dark": lambda request: static("logo-dark.svg"), # dark mode
},
"SITE_SYMBOL": "speed", # symbol from icon set
"ENVIRONMENT": "sample_app.environment_callback",
"DASHBOARD_CALLBACK": "sample_app.dashboard_callback",
Expand Down
1 change: 1 addition & 0 deletions src/unfold/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"SITE_URL": "/",
"SITE_ICON": None,
"SITE_SYMBOL": None,
"SITE_LOGO": None,
"COLORS": {
"primary": {
"50": "250 245 255",
Expand Down
29 changes: 23 additions & 6 deletions src/unfold/sites.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,16 @@ def each_context(self, request: HttpRequest) -> Dict[str, Any]:
"form_classes": {
"text_input": INPUT_CLASSES,
},
"logo": self._get_value(
get_config(self.settings_name)["SIDEBAR"].get("logo"), request
"site_logo": self._get_mode_images(
get_config(self.settings_name)["SITE_LOGO"], request
),
"colors": get_config(self.settings_name)["COLORS"],
"icon": self._get_value(
"site_icon": self._get_mode_images(
get_config(self.settings_name)["SITE_ICON"], request
),
"symbol": self._get_value(
"site_symbol": self._get_value(
get_config(self.settings_name)["SITE_SYMBOL"], request
),
"colors": get_config(self.settings_name)["COLORS"],
"tab_list": self.get_tabs_list(request),
"styles": [
self._get_value(style, request)
Expand Down Expand Up @@ -283,6 +283,20 @@ def get_tabs_list(self, request: HttpRequest) -> List[Dict[str, Any]]:

return tabs

def _get_mode_images(
self, images: Union[Dict[str, callable], callable, str], request: HttpRequest
) -> Union[Dict[str, str], str, None]:
if isinstance(images, dict):
if "light" in images and "dark" in images:
return {
"light": self._get_value(images["light"], request),
"dark": self._get_value(images["dark"], request),
}

return None

return self._get_value(images, request)

def _call_permission_callback(
self, callback: Union[str, Callable, None], request: HttpRequest
):
Expand All @@ -303,7 +317,10 @@ def _get_value(
if isinstance(instance, str):
return instance

return instance(*args)
if isinstance(instance, Callable):
return instance(*args)

return None

def _replace_values(self, target: Dict, source: Dict, request: HttpRequest):
for key in source.keys():
Expand Down
2 changes: 1 addition & 1 deletion src/unfold/static/unfold/css/styles.css

Large diffs are not rendered by default.

6 changes: 2 additions & 4 deletions src/unfold/templates/unfold/helpers/navigation.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
<nav id="nav-sidebar" class="bg-gray-50 border-r border-gray-200 flex flex-col fixed max-h-screen min-h-screen min-w-sidebar transition-width w-sidebar dark:bg-gray-900 dark:border-gray-800">
<div class="border-b border-gray-200 mb-5 py-3 dark:border-gray-800">
<div class="flex font-medium h-10 items-center px-6 text-gray-700 dark:text-gray-200">
{% if logo %}
<img src="{{ logo }}" alt="{% trans "Home" %}"/>
{% if site_logo %}
{% include "unfold/helpers/site_logo.html" %}
{% elif branding %}
{% include "unfold/helpers/site_icon.html" %}

{{ branding }}
{% endif %}
</div>
</div>
Expand Down
14 changes: 11 additions & 3 deletions src/unfold/templates/unfold/helpers/site_icon.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
{% load i18n %}

{% if icon %}
{% if site_icon %}
<a href="{% url "admin:index" %}">
<img src="{{ icon }}" class="h-8 mr-4" alt="{% trans "Home" %}"/>
{% if site_icon.light and site_icon.dark %}
<img src="{{ site_icon.dark }}" alt="{% trans 'Home' %}" class="h-8 hidden mr-4 dark:block"/>

<img src="{{ site_icon.light }}" alt="{% trans 'Home' %}" class="block h-8 mr-4 dark:hidden" />
{% else %}
<img src="{{ site_icon }}" class="h-8 mr-4" alt="{% trans 'Home' %}" />
{% endif %}
</a>
{% else %}
<a href="{% url "admin:index" %}" class="bg-primary-600 flex h-8 items-center justify-center rounded-md mr-4 text-white text-xs w-8">
<span class="material-symbols-outlined md-18">{% if symbol %}{{ symbol }}{% else %}settings{% endif %}</span>
<span class="material-symbols-outlined md-18">{% if site_symbol %}{{ site_symbol }}{% else %}settings{% endif %}</span>
</a>
{% endif %}

{{ branding }}
11 changes: 11 additions & 0 deletions src/unfold/templates/unfold/helpers/site_logo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% load i18n %}

<a href="{% url "admin:index" %}">
{% if site_logo.light and site_logo.dark %}
<img src="{{ site_logo.dark }}" alt="{% trans 'Home' %}" class="h-8 hidden mr-4 dark:block"/>

<img src="{{ site_logo.light }}" alt="{% trans 'Home' %}" class="block h-8 mr-4 dark:hidden" />
{% else %}
<img src="{{ site_logo }}" class="h-8 mr-4" alt="{% trans 'Home' %}" />
{% endif %}
</a>
2 changes: 0 additions & 2 deletions tests/test_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ def test_incorrect_environment_callback(self):
request = RequestFactory().get("/rand")
request.user = AnonymousUser()
context = admin_site.each_context(request)
print(context)
self.assertTrue("environment" not in context)
get_config.cache_clear()

Expand All @@ -50,7 +49,6 @@ def test_correct_environment_callback(self):
request = RequestFactory().get("/rand")
request.user = AnonymousUser()
context = admin_site.each_context(request)
print(context)
self.assertTrue("environment" in context)
self.assertEqual(context["environment"], ["Testing Environment", "warning"])
get_config.cache_clear()
151 changes: 151 additions & 0 deletions tests/test_site_branding.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
from django.contrib.auth.models import AnonymousUser
from django.templatetags.static import static
from django.test import TestCase
from django.test.client import RequestFactory
from django.test.utils import override_settings
from unfold.settings import CONFIG_DEFAULTS, get_config
from unfold.sites import UnfoldAdminSite


class SiteBrandingTestCase(TestCase):
@override_settings(
UNFOLD={
**CONFIG_DEFAULTS,
**{
"SITE_ICON": lambda request: static("icon.svg"),
},
}
)
def test_correct_callback_site_icon(self):
admin_site = UnfoldAdminSite()
request = RequestFactory().get("/rand")
request.user = AnonymousUser()
context = admin_site.each_context(request)
self.assertEqual(context["site_icon"], "icon.svg")
get_config.cache_clear()

@override_settings(
UNFOLD={
**CONFIG_DEFAULTS,
**{
"SITE_ICON": "hardcoded-icon.svg",
},
}
)
def test_correct_string_site_icon(self):
admin_site = UnfoldAdminSite()
request = RequestFactory().get("/rand")
request.user = AnonymousUser()
context = admin_site.each_context(request)
self.assertEqual(context["site_icon"], "hardcoded-icon.svg")
get_config.cache_clear()

@override_settings(
UNFOLD={
**CONFIG_DEFAULTS,
**{
"SITE_ICON": {
"light": lambda request: static("icon-light.svg"),
"dark": lambda request: static("icon-dark.svg"),
}
},
}
)
def test_correct_mode_site_icon(self):
admin_site = UnfoldAdminSite()
request = RequestFactory().get("/rand")
request.user = AnonymousUser()
context = admin_site.each_context(request)
self.assertDictEqual(
context["site_icon"], {"light": "icon-light.svg", "dark": "icon-dark.svg"}
)
get_config.cache_clear()

@override_settings(
UNFOLD={
**CONFIG_DEFAULTS,
**{
"SITE_ICON": {
"light": lambda request: static("icon.svg"),
}
},
}
)
def test_incorrect_mode_site_icon(self):
admin_site = UnfoldAdminSite()
request = RequestFactory().get("/rand")
request.user = AnonymousUser()
context = admin_site.each_context(request)
self.assertIsNone(context["site_icon"])
get_config.cache_clear()

@override_settings(
UNFOLD={
**CONFIG_DEFAULTS,
**{
"SITE_LOGO": lambda request: static("logo.svg"),
},
}
)
def test_correct_callback_site_logo(self):
admin_site = UnfoldAdminSite()
request = RequestFactory().get("/rand")
request.user = AnonymousUser()
context = admin_site.each_context(request)
self.assertEqual(context["site_logo"], "logo.svg")
get_config.cache_clear()

@override_settings(
UNFOLD={
**CONFIG_DEFAULTS,
**{
"SITE_LOGO": "hardcoded-logo.svg",
},
}
)
def test_correct_string_site_logo(self):
admin_site = UnfoldAdminSite()
request = RequestFactory().get("/rand")
request.user = AnonymousUser()
context = admin_site.each_context(request)
self.assertEqual(context["site_logo"], "hardcoded-logo.svg")
get_config.cache_clear()

@override_settings(
UNFOLD={
**CONFIG_DEFAULTS,
**{
"SITE_LOGO": {
"light": lambda request: static("logo-light.svg"),
"dark": lambda request: static("logo-dark.svg"),
}
},
}
)
def test_correct_mode_site_logo(self):
admin_site = UnfoldAdminSite()
request = RequestFactory().get("/rand")
request.user = AnonymousUser()
context = admin_site.each_context(request)
self.assertDictEqual(
context["site_logo"], {"light": "logo-light.svg", "dark": "logo-dark.svg"}
)
get_config.cache_clear()

@override_settings(
UNFOLD={
**CONFIG_DEFAULTS,
**{
"SITE_LOGO": {
"light": lambda request: static("logo.svg"),
}
},
}
)
def test_incorrect_mode_site_logo(self):
admin_site = UnfoldAdminSite()
request = RequestFactory().get("/rand")
request.user = AnonymousUser()
context = admin_site.each_context(request)
self.assertIsNone(context["site_logo"])
get_config.cache_clear()