Skip to content

Commit

Permalink
feat: environment label (#189)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasvinclav authored Nov 10, 2023
1 parent a4bac55 commit 31e9c20
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 60 deletions.
21 changes: 12 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Unfold is theme for Django admin incorporating most common practises for buildin
- **Tabs:** define custom tab navigations for models
- **Colors:** possibility to override default color scheme
- **Third party packages:** default support for multiple popular applications
- **Environment label**: distinguish between environments by displaying a label

## Table of contents <!-- omit from toc -->

Expand Down Expand Up @@ -155,10 +156,11 @@ UNFOLD = {
"SITE_URL": "/",
"SITE_ICON": lambda request: static("logo.svg"),
"SITE_SYMBOL": "speed", # symbol from icon set
"ENVIRONMENT": "sample_app.environment_callback",
"DASHBOARD_CALLBACK": "sample_app.dashboard_callback",
"LOGIN": {
"image": lambda r: static("sample/login-bg.jpg"),
"redirect_after": lambda r: reverse_lazy("admin:APP_MODEL_changelist"),
"image": lambda request: static("sample/login-bg.jpg"),
"redirect_after": lambda request: reverse_lazy("admin:APP_MODEL_changelist"),
},
"STYLES": [
lambda request: static("css/style.css"),
Expand Down Expand Up @@ -244,6 +246,14 @@ def dashboard_callback(request, context):
return context


def environment_callback(request):
"""
Callback has to return a list of two values represeting text value and the color
type of the label displayed in top right corner.
"""
return ["Production", "danger"] # info, danger, warning, success


def badge_callback(request):
return 3

Expand Down Expand Up @@ -808,12 +818,6 @@ Below you can find a more complex example which is using multiple components and
```html+django
{% load i18n %}
{% block content_before %}
{% component "unfold/components/header.html" %}
{% trans "Unfold Dashboard" %}
{% endcomponent %}
{% endblock %}
{% block content %}
{% component "unfold/components/container.html" %}
{% component "unfold/components/flex.html" with class="gap-4"%}
Expand Down Expand Up @@ -851,7 +855,6 @@ Below you can find a more complex example which is using multiple components and
| unfold/components/card.html | Card component | class, title, footer, label |
| unfold/components/container.html | Wrapper for settings max width | class |
| unfold/components/flex.html | Flex items | class, col |
| unfold/components/header.html | Page header, user links | class |
| unfold/components/navigation.html | List of navigation links | class, items |
| unfold/components/progress.html | Percentual progress bar | class, value, title, description |
| unfold/components/separator.html | Separator, horizontal rule | class |
Expand Down
1 change: 1 addition & 0 deletions src/unfold/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
},
},
"DASHBOARD_CALLBACK": None,
"ENVIRONMENT": None,
"STYLES": [],
"SCRIPTS": [],
"SIDEBAR": {
Expand Down
9 changes: 9 additions & 0 deletions src/unfold/sites.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@ def each_context(self, request: HttpRequest) -> Dict[str, Any]:
}
)

environment = get_config(self.settings_name)["ENVIRONMENT"]

if environment and isinstance(environment, str):
try:
callback = import_string(environment)
context.update({"environment": callback(request)})
except ImportError:
pass

return context

def index(
Expand Down
24 changes: 1 addition & 23 deletions src/unfold/templates/admin/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,7 @@
{% endif %}

<div id="main" class="flex-grow">
{% if not is_popup %}
{% block header %}
<div class="border-b border-gray-200 mb-6 px-4 lg:px-12 dark:border-gray-800">
<div class="container flex items-center h-16 mx-auto py-4">
<div id="header-inner" class="flex items-center w-full">
<div class="flex items-center w-full">
{% block usertools %}
{% if has_permission %}
{% block welcome-msg %}
{% include 'unfold/helpers/welcomemsg.html' %}
{% endblock %}

{% block userlinks %}
{% include 'unfold/helpers/userlinks.html' %}
{% endblock %}
{% endif %}
{% endblock %}
</div>
</div>
</div>
</div>
{% endblock %}
{% endif %}
{% include "unfold/helpers/header.html" %}

{% if not is_popup %}
{% spaceless %}
Expand Down
4 changes: 2 additions & 2 deletions src/unfold/templates/unfold/components/container.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<div class="max-w-7xl mx-auto{% if class %} {{ class }}{% endif %}">
{{ children }}
<div class="mx-auto{% if class %} {{ class }}{% endif %}">
{{ children }}
</div>
17 changes: 0 additions & 17 deletions src/unfold/templates/unfold/components/header.html

This file was deleted.

2 changes: 1 addition & 1 deletion src/unfold/templates/unfold/helpers/field.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="{% if field.errors %}errors {% endif %}flex group mb-6 flex-col last:mb-4">
{% include "unfold/helpers/label.html" with field=field %}
{% include "unfold/helpers/form_label.html" with field=field %}

{{ field }}

Expand Down
7 changes: 7 additions & 0 deletions src/unfold/templates/unfold/helpers/form_label.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<label for="{{ field.id_for_label }}" class="block font-medium mb-2 text-gray-900 text-sm dark:text-gray-200">
{{ field.label }}

{% if field.field.required %}
<span class="text-red-600">*</span>
{% endif %}
</label>
23 changes: 23 additions & 0 deletions src/unfold/templates/unfold/helpers/header.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{% if not is_popup %}
{% block header %}
<div class="border-b border-gray-200 mb-6 px-4 lg:px-12 dark:border-gray-800">
<div class="container flex items-center h-16 mx-auto py-4">
<div id="header-inner" class="flex items-center w-full">
<div class="flex items-center w-full">
{% block usertools %}
{% if has_permission %}
{% block welcome-msg %}
{% include 'unfold/helpers/welcomemsg.html' %}
{% endblock %}

{% block userlinks %}
{% include 'unfold/helpers/userlinks.html' %}
{% endblock %}
{% endif %}
{% endblock %}
</div>
</div>
</div>
</div>
{% endblock %}
{% endif %}
20 changes: 14 additions & 6 deletions src/unfold/templates/unfold/helpers/label.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
<label for="{{ field.id_for_label }}" class="block font-medium mb-2 text-gray-900 text-sm dark:text-gray-200">
{{ field.label }}

{% if field.field.required %}
<span class="text-red-600">*</span>
<span class="border font-semibold leading-none mr-2 px-2 py-1 rounded shadow-sm text-xxs uppercase whitespace-nowrap last:mr-0
{% if type == 'info' %}
bg-blue-50 border-blue-200 text-blue-500 dark:bg-blue-500/20 dark:border-blue-500/10
{% elif type == 'danger' %}
bg-red-50 border-red-200 text-red-500 dark:bg-red-500/20 dark:border-red-500/10
{% elif type == 'warning' %}
bg-orange-50 border-orange-200 text-orange-500 dark:bg-orange-500/20 dark:border-orange-500/10
{% elif type == 'success' %}
bg-green-50 border-green-200 text-green-500 dark:bg-green-500/20 dark:border-green-500/10
{% else %}
bg-white border-gray-200 text-gray-400 dark:bg-white/[.04] dark:border-gray-800 dark:text-gray-400
{% endif %}
</label>
">
{{ text }}
</span>
6 changes: 5 additions & 1 deletion src/unfold/templates/unfold/helpers/userlinks.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

<div class="flex items-center ml-auto">
<div class="flex flex-row group items-center leading-none relative">
<div class="flex gap-4">
<div class="flex gap-4 items-center">
{% if environment %}
{% include "unfold/helpers/label.html" with text=environment.0 type=environment.1 %}
{% endif %}

{% include "unfold/helpers/theme_switch.html" %}

{% include "unfold/helpers/account_links.html" %}
Expand Down
4 changes: 3 additions & 1 deletion src/unfold/templates/unfold/layouts/base_simple.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
{% endif %}

<div id="main" class="shadow flex-grow">
{% block content_before %}{% endblock %}
{% block content_before %}
{% include "unfold/helpers/header.html" %}
{% endblock %}

<div class="p-4 lg:p-12">
<div id="content" class="container mx-auto {% block coltype %}colM{% endblock %}">
Expand Down
56 changes: 56 additions & 0 deletions tests/test_environment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from django.contrib.auth.models import AnonymousUser
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


def environment_callback(request):
return ["Testing Environment", "warning"]


class EnvironmentTestCase(TestCase):
@override_settings(UNFOLD={**CONFIG_DEFAULTS})
def test_empty_environment_callback(self):
admin_site = UnfoldAdminSite()
request = RequestFactory().get("/rand")
request.user = AnonymousUser()
context = admin_site.each_context(request)
self.assertTrue("environment" not in context)
get_config.cache_clear()

@override_settings(
UNFOLD={
**CONFIG_DEFAULTS,
**{
"ENVIRONMENT": "tests.test_environment.non_existing_environment_callback",
},
}
)
def test_incorrect_environment_callback(self):
admin_site = UnfoldAdminSite()
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()

@override_settings(
UNFOLD={
**CONFIG_DEFAULTS,
**{
"ENVIRONMENT": "tests.test_environment.environment_callback",
},
}
)
def test_correct_environment_callback(self):
admin_site = UnfoldAdminSite()
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()

0 comments on commit 31e9c20

Please sign in to comment.