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): """