diff --git a/netbox/templates/extras/dashboard/widget.html b/netbox/templates/extras/dashboard/widget.html
index 1559363d3..1f0fb0bbf 100644
--- a/netbox/templates/extras/dashboard/widget.html
+++ b/netbox/templates/extras/dashboard/widget.html
@@ -1,4 +1,5 @@
{% load dashboard %}
+{% load helpers %}
+ >
{% if widget.title %}
- {{ widget.title }}
+ {{ widget.title }}
{% endif %}
diff --git a/netbox/utilities/colors.py b/netbox/utilities/colors.py
new file mode 100644
index 000000000..248116833
--- /dev/null
+++ b/netbox/utilities/colors.py
@@ -0,0 +1,34 @@
+import colorsys
+
+
+def hex_to_rgb(hex_str):
+ """Returns a tuple representing the given hex string as RGB.
+ """
+ if hex_str.startswith('#'):
+ hex_str = hex_str[1:]
+ return tuple([int(hex_str[i:i + 2], 16) for i in range(0, len(hex_str), 2)])
+
+
+def rgb_to_hex(rgb):
+ """Converts an rgb tuple to hex string for web.
+ """
+ return ''.join(["%0.2X" % int(c) for c in rgb])
+
+
+def adjust_color_lightness(r, g, b, factor):
+ hue, luminous, saturation = colorsys.rgb_to_hls(r / 255.0, g / 255.0, b / 255.0)
+ luminous = max(min(luminous * factor, 0.9), 0.1)
+ r, g, b = colorsys.hls_to_rgb(hue, luminous, saturation)
+ return int(r * 255), int(g * 255), int(b * 255)
+
+
+def lighten_color(color, factor=0.1):
+ color = color.strip('#')
+ r, g, b = hex_to_rgb(color)
+ return rgb_to_hex(adjust_color_lightness(r, g, b, 1 + factor))
+
+
+def darken_color(color, factor=0.1):
+ color = color.strip('#')
+ r, g, b = hex_to_rgb(color)
+ return rgb_to_hex(adjust_color_lightness(r, g, b, 1 - factor))
diff --git a/netbox/utilities/templatetags/builtins/filters.py b/netbox/utilities/templatetags/builtins/filters.py
index a52a38116..9dfc61033 100644
--- a/netbox/utilities/templatetags/builtins/filters.py
+++ b/netbox/utilities/templatetags/builtins/filters.py
@@ -11,6 +11,8 @@ from markdown import markdown
from netbox.config import get_config
from utilities.markdown import StrikethroughExtension
+from utilities.choices import ButtonColorChoices
+from utilities.colors import lighten_color
from utilities.utils import clean_html, foreground_color, title
__all__ = (
@@ -30,11 +32,36 @@ __all__ = (
register = template.Library()
+BOOTSTRAP_BUTTON_COLOR_MAP = {
+ "outline-dark": "ffffff",
+ "primary": "337ab7",
+ "secondary": "6c757d",
+ "success": "198754",
+ "info": "54d6f0",
+ "warning": "ffc107",
+ "danger": "dc3545",
+ "light": "e9ecef",
+ "dark": "343a40",
+ "blue": "0d6efd",
+ "indigo": "6610f2",
+ "purple": "6f42c1",
+ "pink": "d63384",
+ "red": "dc3545",
+ "orange": "fd7e14",
+ "yellow": "ffc107",
+ "green": "198754",
+ "teal": "20c997",
+ "cyan": "0dcaf0",
+ "gray": "adb5bd",
+ "black": "000000",
+ "white": "ffffff",
+}
#
# General
#
+
@register.filter()
def linkify(instance, attr=None):
"""
@@ -77,10 +104,20 @@ def fgcolor(value, dark='000000', light='ffffff'):
"""
value = value.lower().strip('#')
if not re.match('^[0-9a-f]{6}$', value):
- return ''
+ colors = [color[0] for color in ButtonColorChoices.CHOICES]
+ if value in colors:
+ value = BOOTSTRAP_BUTTON_COLOR_MAP[value]
+ else:
+ return ''
return f'#{foreground_color(value, dark, light)}'
+@register.filter()
+def lighten(color, amount=0.5):
+ c = lighten_color(color, factor=0.5)
+ return f'#{c}'
+
+
@register.filter()
def meta(model, attr):
"""