Skip to content

Commit

Permalink
Use bootstrap_alert for bootstrap_messages
Browse files Browse the repository at this point in the history
  • Loading branch information
dyve committed Mar 17, 2021
1 parent 6d30584 commit df7f90d
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 146 deletions.
5 changes: 3 additions & 2 deletions src/django_bootstrap5/components.py
@@ -1,3 +1,4 @@
from django.template.defaultfilters import capfirst
from django.utils.html import format_html
from django.utils.translation import gettext as _

Expand All @@ -7,15 +8,15 @@
ALERT_TYPES = ["primary", "secondary", "succes", "danger", "warning", "info", "light", "dark"]


def render_alert(content, alert_type="info", dismissible=True):
def render_alert(content, alert_type="info", dismissible=True, extra_classes=""):
"""Render a Bootstrap alert."""
button = ""
if alert_type not in ALERT_TYPES:
raise ValueError(f"Value {alert_type} is not a valid alert type. Please choose from {', '.join(ALERT_TYPES)}.")
css_classes = [f"alert alert-{alert_type}"]
if dismissible:
css_classes.append("alert-dismissible fade show")
close = _("close")
close = capfirst(_("close"))
button = f'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="{close}"></button>'
css_classes = merge_css_classes(*css_classes)
return render_tag(
Expand Down
@@ -1,7 +1,4 @@
{% load i18n %}{% load django_bootstrap5 %}
{% load django_bootstrap5 %}
{% for message in messages %}
<div class="{{ message|bootstrap_message_classes }} alert-dismissible fade show" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="{% trans 'close' %}">&#215;</button>
{{ message }}
</div>
{% bootstrap_alert message alert_type=message|bootstrap_message_alert_type extra_classes=message.extra_tags %}
{% endfor %}
41 changes: 19 additions & 22 deletions src/django_bootstrap5/templatetags/django_bootstrap5.py
Expand Up @@ -23,12 +23,12 @@
from ..html import render_link_tag, render_script_tag
from ..utils import handle_var, parse_token_contents, render_template_file, url_replace_param

MESSAGE_LEVEL_CLASSES = {
message_constants.DEBUG: "alert alert-warning",
message_constants.INFO: "alert alert-info",
message_constants.SUCCESS: "alert alert-success",
message_constants.WARNING: "alert alert-warning",
message_constants.ERROR: "alert alert-danger",
MESSAGE_ALERT_TYPES = {
message_constants.DEBUG: "warning",
message_constants.INFO: "info",
message_constants.SUCCESS: "success",
message_constants.WARNING: "warning",
message_constants.ERROR: "danger",
}

register = template.Library()
Expand All @@ -46,26 +46,18 @@ def bootstrap_setting(value):


@register.filter
def bootstrap_message_classes(message):
"""Return the message classes for a message."""
extra_tags = None
try:
extra_tags = message.extra_tags
except AttributeError:
pass
if not extra_tags:
extra_tags = ""
classes = [extra_tags]
def bootstrap_message_alert_type(message):
"""Return the alert type for a bootstrap message, defaults to empty string."""
try:
level = message.level
except AttributeError:
pass
else:
try:
classes.append(MESSAGE_LEVEL_CLASSES[level])
return MESSAGE_ALERT_TYPES[level]
except KeyError:
classes.append("alert alert-danger")
return " ".join(classes).strip()
pass
return "info"


@register.simple_tag
Expand Down Expand Up @@ -578,7 +570,7 @@ def bootstrap_button(*args, **kwargs):


@register.simple_tag
def bootstrap_alert(content, alert_type="info", dismissible=True):
def bootstrap_alert(content, alert_type="info", dismissible=True, extra_classes=""):
"""
Render an alert.
Expand All @@ -604,15 +596,20 @@ def bootstrap_alert(content, alert_type="info", dismissible=True):
:default: ``True``
extra_classes
string, extra CSS classes for alert
:default: ""
**Usage**::
{% bootstrap_alert content %}
**Example**::
{% bootstrap_alert "Something went wrong" alert_type='error' %}
{% bootstrap_alert "Something went wrong" alert_type="error" %}
"""
return render_alert(content, alert_type, dismissible)
return render_alert(content, alert_type, dismissible, extra_classes)


@register.tag("buttons")
Expand Down
4 changes: 2 additions & 2 deletions tests/test_bootstrap_alert.py
Expand Up @@ -11,12 +11,12 @@ def test_bootstrap_alert(self):
)

def test_bootstrap_alert_dismissible(self):
self.assertHTMLEqual(
self.assertEqual(
render_template_with_bootstrap('{% bootstrap_alert "content" %}'),
(
'<div class="alert alert-info alert-dismissible fade show" role="alert">'
"content"
'<button aria-label="close" class="btn-close" data-bs-dismiss="alert" type="button">'
'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>'
"</div>"
),
)
Expand Down
80 changes: 80 additions & 0 deletions tests/test_bootstrap_messages.py
@@ -0,0 +1,80 @@
import re

from django.contrib.messages import constants as DEFAULT_MESSAGE_LEVELS
from django.test import TestCase

from tests.test_templates import render_template_with_form


class MessagesTest(TestCase):
def test_bootstrap_messages(self):
class FakeMessage(object):
"""Follows the `django.contrib.messages.storage.base.Message` API."""

level = None
message = None
extra_tags = None

def __init__(self, level, message, extra_tags=None):
self.level = level
self.extra_tags = extra_tags
self.message = message

def __str__(self):
return self.message

pattern = re.compile(r"\s+")
messages = [FakeMessage(DEFAULT_MESSAGE_LEVELS.WARNING, "hello")]
res = render_template_with_form("{% bootstrap_messages messages %}", {"messages": messages})
expected = (
'<div class="alert alert-warning alert-dismissible fade show" role="alert">'
"hello"
'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>'
"</div>"
)
self.maxDiff = None
self.assertEqual(re.sub(pattern, "", res), re.sub(pattern, "", expected))

messages = [FakeMessage(DEFAULT_MESSAGE_LEVELS.ERROR, "hello")]
res = render_template_with_form("{% bootstrap_messages messages %}", {"messages": messages})
expected = (
'<div class="alert alert-danger alert-dismissible fade show" role="alert">'
"hello"
'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>'
"</div>"
)
self.assertEqual(re.sub(pattern, "", res), re.sub(pattern, "", expected))

messages = [FakeMessage(None, "hello")]
res = render_template_with_form("{% bootstrap_messages messages %}", {"messages": messages})
expected = (
'<div class="alert alert-info alert-dismissible fade show" role="alert">'
"hello"
'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>'
"</div>"
)

self.assertEqual(re.sub(pattern, "", res), re.sub(pattern, "", expected))

messages = [FakeMessage(DEFAULT_MESSAGE_LEVELS.ERROR, "hello http://example.com")]
res = render_template_with_form("{% bootstrap_messages messages %}", {"messages": messages})
expected = (
'<div class="alert alert-danger alert-dismissible fade show" role="alert">'
"hello http://example.com"
'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>'
"</div>"
)
self.assertEqual(
re.sub(pattern, "", res),
re.sub(pattern, "", expected),
)

messages = [FakeMessage(DEFAULT_MESSAGE_LEVELS.ERROR, "hello\nthere")]
res = render_template_with_form("{% bootstrap_messages messages %}", {"messages": messages})
expected = (
'<div class="alert alert-danger alert-dismissible fade show" role="alert">'
"hello there"
'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>'
"</div>"
)
self.assertEqual(re.sub(pattern, "", res), re.sub(pattern, "", expected))
10 changes: 4 additions & 6 deletions tests/test_components.py
Expand Up @@ -7,15 +7,13 @@


class AlertsTest(TestCase):
CLOSE = '<button aria-label="close" class="btn-close" data-bs-dismiss="alert" type="button">'

def test_render_alert_without_type(self):
self.assertEqual(
render_alert("content"),
(
'<div class="alert alert-info alert-dismissible fade show" role="alert">'
"content"
'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="close"></button>'
'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>'
"</div>"
),
)
Expand All @@ -26,7 +24,7 @@ def test_render_alert_with_type(self):
(
'<div class="alert alert-danger alert-dismissible fade show" role="alert">'
"content"
'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="close"></button>'
'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>'
"</div>"
),
)
Expand All @@ -37,7 +35,7 @@ def test_render_alert_with_safe_content(self):
(
'<div class="alert alert-info alert-dismissible fade show" role="alert">'
'This is <a href="https://example.com" class="alert-link">a safe link</a>!'
'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="close"></button>'
'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>'
"</div>"
),
)
Expand All @@ -48,7 +46,7 @@ def test_render_alert_with_unsafe_content(self):
(
'<div class="alert alert-info alert-dismissible fade show" role="alert">'
"This is &lt;b&gt;unsafe&lt;/b&gt;!"
'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="close"></button>'
'<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>'
"</div>"
),
)
Expand Down
14 changes: 14 additions & 0 deletions tests/test_css.py
@@ -0,0 +1,14 @@
from django.test import TestCase

from django_bootstrap5.css import merge_css_classes


class CssTest(TestCase):
def test_merge_css_classes(self):
css_classes = "one two"
css_class = "three four"
classes = merge_css_classes(css_classes, css_class)
self.assertEqual(classes, "one two three four")

classes = merge_css_classes(css_class, css_classes)
self.assertEqual(classes, "three four one two")
10 changes: 10 additions & 0 deletions tests/test_html.py
@@ -0,0 +1,10 @@
from django.test import TestCase

from django_bootstrap5.html import render_tag


class HtmlTest(TestCase):
def test_render_tag(self):
self.assertEqual(render_tag("span"), "<span></span>")
self.assertEqual(render_tag("span", content="foo"), "<span>foo</span>")
self.assertEqual(render_tag("span", attrs={"bar": 123}, content="foo"), '<span bar="123">foo</span>')

0 comments on commit df7f90d

Please sign in to comment.