diff --git a/docs/release-notes/version-2.8.md b/docs/release-notes/version-2.8.md index 720e4b1a7..d761020ad 100644 --- a/docs/release-notes/version-2.8.md +++ b/docs/release-notes/version-2.8.md @@ -9,6 +9,7 @@ * [#4651](https://github.com/netbox-community/netbox/issues/4651) - Add `csrf_token` context for plugin templates * [#4652](https://github.com/netbox-community/netbox/issues/4652) - Add permissions context for plugin templates * [#4665](https://github.com/netbox-community/netbox/issues/4665) - Add NEMA L14 and L21 power port/outlet types +* [#4672](https://github.com/netbox-community/netbox/issues/4672) - Set default color for rack and devices roles ### Bug Fixes diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index 5bc6dd7f0..8c24180bb 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -4,7 +4,7 @@ from django.contrib.auth.models import User from extras.filters import CustomFieldFilterSet, LocalConfigContextFilterSet, CreatedUpdatedFilterSet from tenancy.filters import TenancyFilterSet from tenancy.models import Tenant -from utilities.constants import COLOR_CHOICES +from utilities.choices import ColorChoices from utilities.filters import ( BaseFilterSet, MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter, NameSlugSearchFilterSet, TagFilter, TreeNodeMultipleChoiceFilter, @@ -1084,7 +1084,7 @@ class CableFilterSet(BaseFilterSet): choices=CableStatusChoices ) color = django_filters.MultipleChoiceFilter( - choices=COLOR_CHOICES + choices=ColorChoices ) device_id = MultiValueNumberFilter( method='filter_device' diff --git a/netbox/dcim/migrations/0106_role_default_color.py b/netbox/dcim/migrations/0106_role_default_color.py new file mode 100644 index 000000000..c4df1b33f --- /dev/null +++ b/netbox/dcim/migrations/0106_role_default_color.py @@ -0,0 +1,24 @@ +# Generated by Django 3.0.6 on 2020-05-26 13:33 + +from django.db import migrations +import utilities.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('dcim', '0105_interface_name_collation'), + ] + + operations = [ + migrations.AlterField( + model_name='devicerole', + name='color', + field=utilities.fields.ColorField(default='9e9e9e', max_length=6), + ), + migrations.AlterField( + model_name='rackrole', + name='color', + field=utilities.fields.ColorField(default='9e9e9e', max_length=6), + ), + ] diff --git a/netbox/dcim/models/__init__.py b/netbox/dcim/models/__init__.py index 490667153..1f6478119 100644 --- a/netbox/dcim/models/__init__.py +++ b/netbox/dcim/models/__init__.py @@ -23,6 +23,7 @@ from dcim.fields import ASNField from dcim.elevations import RackElevationSVG from extras.models import ConfigContextModel, CustomFieldModel, ObjectChange, TaggedItem from extras.utils import extras_features +from utilities.choices import ColorChoices from utilities.fields import ColorField, NaturalOrderingField from utilities.models import ChangeLoggedModel from utilities.utils import serialize_object, to_meters @@ -379,7 +380,9 @@ class RackRole(ChangeLoggedModel): slug = models.SlugField( unique=True ) - color = ColorField() + color = ColorField( + default=ColorChoices.COLOR_GREY + ) description = models.CharField( max_length=200, blank=True, @@ -1190,7 +1193,9 @@ class DeviceRole(ChangeLoggedModel): slug = models.SlugField( unique=True ) - color = ColorField() + color = ColorField( + default=ColorChoices.COLOR_GREY + ) vm_role = models.BooleanField( default=True, verbose_name='VM Role', diff --git a/netbox/extras/models/tags.py b/netbox/extras/models/tags.py index 3bad7fa8b..d68ca2ce6 100644 --- a/netbox/extras/models/tags.py +++ b/netbox/extras/models/tags.py @@ -3,6 +3,7 @@ from django.urls import reverse from django.utils.text import slugify from taggit.models import TagBase, GenericTaggedItemBase +from utilities.choices import ColorChoices from utilities.fields import ColorField from utilities.models import ChangeLoggedModel @@ -13,7 +14,7 @@ from utilities.models import ChangeLoggedModel class Tag(TagBase, ChangeLoggedModel): color = ColorField( - default='9e9e9e' + default=ColorChoices.COLOR_GREY ) description = models.CharField( max_length=200, diff --git a/netbox/utilities/choices.py b/netbox/utilities/choices.py index aba64e63b..ce0929a8b 100644 --- a/netbox/utilities/choices.py +++ b/netbox/utilities/choices.py @@ -80,6 +80,70 @@ def unpack_grouped_choices(choices): return unpacked_choices +# +# Generic color choices +# + +class ColorChoices(ChoiceSet): + COLOR_DARK_RED = 'aa1409' + COLOR_RED = 'f44336' + COLOR_PINK = 'e91e63' + COLOR_ROSE = 'ffe4e1' + COLOR_FUCHSIA = 'ff66ff' + COLOR_PURPLE = '9c27b0' + COLOR_DARK_PURPLE = '673ab7' + COLOR_INDIGO = '3f51b5' + COLOR_BLUE = '2196f3' + COLOR_LIGHT_BLUE = '03a9f4' + COLOR_CYAN = '00bcd4' + COLOR_TEAL = '009688' + COLOR_AQUA = '00ffff' + COLOR_DARK_GREEN = '2f6a31' + COLOR_GREEN = '4caf50' + COLOR_LIGHT_GREEN = '8bc34a' + COLOR_LIME = 'cddc39' + COLOR_YELLOW = 'ffeb3b' + COLOR_AMBER = 'ffc107' + COLOR_ORANGE = 'ff9800' + COLOR_DARK_ORANGE = 'ff5722' + COLOR_BROWN = '795548' + COLOR_LIGHT_GREY = 'c0c0c0' + COLOR_GREY = '9e9e9e' + COLOR_DARK_GREY = '607d8b' + COLOR_BLACK = '111111' + COLOR_WHITE = 'ffffff' + + CHOICES = ( + (COLOR_DARK_RED, 'Dark red'), + (COLOR_RED, 'Red'), + (COLOR_PINK, 'Pink'), + (COLOR_ROSE, 'Rose'), + (COLOR_FUCHSIA, 'Fuchsia'), + (COLOR_PURPLE, 'Purple'), + (COLOR_DARK_PURPLE, 'Dark purple'), + (COLOR_INDIGO, 'Indigo'), + (COLOR_BLUE, 'Blue'), + (COLOR_LIGHT_BLUE, 'Light blue'), + (COLOR_CYAN, 'Cyan'), + (COLOR_TEAL, 'Teal'), + (COLOR_AQUA, 'Aqua'), + (COLOR_DARK_GREEN, 'Dark green'), + (COLOR_GREEN, 'Green'), + (COLOR_LIGHT_GREEN, 'Light green'), + (COLOR_LIME, 'Lime'), + (COLOR_YELLOW, 'Yellow'), + (COLOR_AMBER, 'Amber'), + (COLOR_ORANGE, 'Orange'), + (COLOR_DARK_ORANGE, 'Dark orange'), + (COLOR_BROWN, 'Brown'), + (COLOR_LIGHT_GREY, 'Light grey'), + (COLOR_GREY, 'Grey'), + (COLOR_DARK_GREY, 'Dark grey'), + (COLOR_BLACK, 'Black'), + (COLOR_WHITE, 'White'), + ) + + # # Button color choices # diff --git a/netbox/utilities/constants.py b/netbox/utilities/constants.py index bdcdeef11..9a3a7d028 100644 --- a/netbox/utilities/constants.py +++ b/netbox/utilities/constants.py @@ -1,34 +1,3 @@ -COLOR_CHOICES = ( - ('aa1409', 'Dark red'), - ('f44336', 'Red'), - ('e91e63', 'Pink'), - ('ffe4e1', 'Rose'), - ('ff66ff', 'Fuschia'), - ('9c27b0', 'Purple'), - ('673ab7', 'Dark purple'), - ('3f51b5', 'Indigo'), - ('2196f3', 'Blue'), - ('03a9f4', 'Light blue'), - ('00bcd4', 'Cyan'), - ('009688', 'Teal'), - ('00ffff', 'Aqua'), - ('2f6a31', 'Dark green'), - ('4caf50', 'Green'), - ('8bc34a', 'Light green'), - ('cddc39', 'Lime'), - ('ffeb3b', 'Yellow'), - ('ffc107', 'Amber'), - ('ff9800', 'Orange'), - ('ff5722', 'Dark orange'), - ('795548', 'Brown'), - ('c0c0c0', 'Light grey'), - ('9e9e9e', 'Grey'), - ('607d8b', 'Dark grey'), - ('111111', 'Black'), - ('ffffff', 'White'), -) - - # # Filter lookup expressions # diff --git a/netbox/utilities/forms.py b/netbox/utilities/forms.py index bfc783631..17ef4dd84 100644 --- a/netbox/utilities/forms.py +++ b/netbox/utilities/forms.py @@ -14,8 +14,7 @@ from django.forms import BoundField from django.forms.models import fields_for_model from django.urls import reverse -from .choices import unpack_grouped_choices -from .constants import * +from .choices import ColorChoices, unpack_grouped_choices from .validators import EnhancedURLValidator NUMERIC_EXPANSION_PATTERN = r'\[((?:\d+[?:,-])+\d+)\]' @@ -163,7 +162,7 @@ class ColorSelect(forms.Select): option_template_name = 'widgets/colorselect_option.html' def __init__(self, *args, **kwargs): - kwargs['choices'] = add_blank_choice(COLOR_CHOICES) + kwargs['choices'] = add_blank_choice(ColorChoices) super().__init__(*args, **kwargs) self.attrs['class'] = 'netbox-select2-color-picker'