Skip to content

Commit b3ed545

Browse files
committed
Closes #3682: Add color field to front and rear ports
1 parent 8a74737 commit b3ed545

File tree

12 files changed

+183
-50
lines changed

12 files changed

+183
-50
lines changed

docs/release-notes/version-3.0.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ CustomValidator can also be subclassed to enforce more complex logic by overridi
3535

3636
* [#2434](https://github.com/netbox-community/netbox/issues/2434) - Add option to assign IP address upon creating a new interface
3737
* [#3665](https://github.com/netbox-community/netbox/issues/3665) - Enable rendering export templates via REST API
38+
* [#3682](https://github.com/netbox-community/netbox/issues/3682) - Add `color` field to front and rear ports
3839
* [#4609](https://github.com/netbox-community/netbox/issues/4609) - Allow marking prefixes as fully utilized
3940
* [#5806](https://github.com/netbox-community/netbox/issues/5806) - Add kilometer and mile as choices for cable length unit
4041
* [#6154](https://github.com/netbox-community/netbox/issues/6154) - Allow decimal values for cable lengths
@@ -54,8 +55,16 @@ CustomValidator can also be subclassed to enforce more complex logic by overridi
5455
* Removed the `display_name` attribute (use `display` instead)
5556
* dcim.DeviceType
5657
* Removed the `display_name` attribute (use `display` instead)
58+
* dcim.FrontPort
59+
* Added `color` field
60+
* dcim.FrontPortTemplate
61+
* Added `color` field
5762
* dcim.Rack
5863
* Removed the `display_name` attribute (use `display` instead)
64+
* dcim.RearPort
65+
* Added `color` field
66+
* dcim.RearPortTemplate
67+
* Added `color` field
5968
* dcim.Site
6069
* `latitude` and `longitude` are now decimal fields rather than strings
6170
* extras.ContentType

netbox/dcim/api/serializers.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,8 @@ class RearPortTemplateSerializer(ValidatedModelSerializer):
384384
class Meta:
385385
model = RearPortTemplate
386386
fields = [
387-
'id', 'url', 'display', 'device_type', 'name', 'label', 'type', 'positions', 'description', 'created',
388-
'last_updated',
387+
'id', 'url', 'display', 'device_type', 'name', 'label', 'type', 'color', 'positions', 'description',
388+
'created', 'last_updated',
389389
]
390390

391391

@@ -398,7 +398,7 @@ class FrontPortTemplateSerializer(ValidatedModelSerializer):
398398
class Meta:
399399
model = FrontPortTemplate
400400
fields = [
401-
'id', 'url', 'display', 'device_type', 'name', 'label', 'type', 'rear_port', 'rear_port_position',
401+
'id', 'url', 'display', 'device_type', 'name', 'label', 'type', 'color', 'rear_port', 'rear_port_position',
402402
'description', 'created', 'last_updated',
403403
]
404404

@@ -665,8 +665,9 @@ class RearPortSerializer(PrimaryModelSerializer, CableTerminationSerializer):
665665
class Meta:
666666
model = RearPort
667667
fields = [
668-
'id', 'url', 'display', 'device', 'name', 'label', 'type', 'positions', 'description', 'mark_connected',
669-
'cable', 'cable_peer', 'cable_peer_type', 'tags', 'custom_fields', 'created', 'last_updated', '_occupied',
668+
'id', 'url', 'display', 'device', 'name', 'label', 'type', 'color', 'positions', 'description',
669+
'mark_connected', 'cable', 'cable_peer', 'cable_peer_type', 'tags', 'custom_fields', 'created',
670+
'last_updated', '_occupied',
670671
]
671672

672673

@@ -691,9 +692,9 @@ class FrontPortSerializer(PrimaryModelSerializer, CableTerminationSerializer):
691692
class Meta:
692693
model = FrontPort
693694
fields = [
694-
'id', 'url', 'display', 'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description',
695-
'mark_connected', 'cable', 'cable_peer', 'cable_peer_type', 'tags', 'custom_fields', 'created',
696-
'last_updated', '_occupied',
695+
'id', 'url', 'display', 'device', 'name', 'label', 'type', 'color', 'rear_port', 'rear_port_position',
696+
'description', 'mark_connected', 'cable', 'cable_peer', 'cable_peer_type', 'tags', 'custom_fields',
697+
'created', 'last_updated', '_occupied',
697698
]
698699

699700

netbox/dcim/filtersets.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ class FrontPortTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponent
538538

539539
class Meta:
540540
model = FrontPortTemplate
541-
fields = ['id', 'name', 'type']
541+
fields = ['id', 'name', 'type', 'color']
542542

543543

544544
class RearPortTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentFilterSet):
@@ -549,7 +549,7 @@ class RearPortTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentF
549549

550550
class Meta:
551551
model = RearPortTemplate
552-
fields = ['id', 'name', 'type', 'positions']
552+
fields = ['id', 'name', 'type', 'color', 'positions']
553553

554554

555555
class DeviceBayTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentFilterSet):
@@ -1027,7 +1027,7 @@ class FrontPortFilterSet(PrimaryModelFilterSet, DeviceComponentFilterSet, CableT
10271027

10281028
class Meta:
10291029
model = FrontPort
1030-
fields = ['id', 'name', 'label', 'type', 'description']
1030+
fields = ['id', 'name', 'label', 'type', 'color', 'description']
10311031

10321032

10331033
class RearPortFilterSet(PrimaryModelFilterSet, DeviceComponentFilterSet, CableTerminationFilterSet):
@@ -1038,7 +1038,7 @@ class RearPortFilterSet(PrimaryModelFilterSet, DeviceComponentFilterSet, CableTe
10381038

10391039
class Meta:
10401040
model = RearPort
1041-
fields = ['id', 'name', 'label', 'type', 'positions', 'description']
1041+
fields = ['id', 'name', 'label', 'type', 'color', 'positions', 'description']
10421042

10431043

10441044
class DeviceBayFilterSet(PrimaryModelFilterSet, DeviceComponentFilterSet):

netbox/dcim/forms.py

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,7 +1610,7 @@ class FrontPortTemplateForm(BootstrapMixin, forms.ModelForm):
16101610
class Meta:
16111611
model = FrontPortTemplate
16121612
fields = [
1613-
'device_type', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'description',
1613+
'device_type', 'name', 'label', 'type', 'color', 'rear_port', 'rear_port_position', 'description',
16141614
]
16151615
widgets = {
16161616
'device_type': forms.HiddenInput(),
@@ -1639,7 +1639,7 @@ class FrontPortTemplateCreateForm(ComponentTemplateCreateForm):
16391639
help_text='Select one rear port assignment for each front port being created.',
16401640
)
16411641
field_order = (
1642-
'manufacturer', 'device_type', 'name_pattern', 'label_pattern', 'type', 'rear_port_set', 'description',
1642+
'manufacturer', 'device_type', 'name_pattern', 'label_pattern', 'type', 'color', 'rear_port_set', 'description',
16431643
)
16441644

16451645
def __init__(self, *args, **kwargs):
@@ -1703,6 +1703,11 @@ class FrontPortTemplateBulkEditForm(BootstrapMixin, BulkEditForm):
17031703
required=False,
17041704
widget=StaticSelect2()
17051705
)
1706+
color = forms.CharField(
1707+
max_length=6, # RGB color code
1708+
required=False,
1709+
widget=ColorSelect()
1710+
)
17061711
description = forms.CharField(
17071712
required=False
17081713
)
@@ -1716,7 +1721,7 @@ class RearPortTemplateForm(BootstrapMixin, forms.ModelForm):
17161721
class Meta:
17171722
model = RearPortTemplate
17181723
fields = [
1719-
'device_type', 'name', 'label', 'type', 'positions', 'description',
1724+
'device_type', 'name', 'label', 'type', 'color', 'positions', 'description',
17201725
]
17211726
widgets = {
17221727
'device_type': forms.HiddenInput(),
@@ -1729,13 +1734,20 @@ class RearPortTemplateCreateForm(ComponentTemplateCreateForm):
17291734
choices=PortTypeChoices,
17301735
widget=StaticSelect2(),
17311736
)
1737+
color = forms.CharField(
1738+
max_length=6, # RGB color code
1739+
required=False,
1740+
widget=ColorSelect()
1741+
)
17321742
positions = forms.IntegerField(
17331743
min_value=REARPORT_POSITIONS_MIN,
17341744
max_value=REARPORT_POSITIONS_MAX,
17351745
initial=1,
17361746
help_text='The number of front ports which may be mapped to each rear port'
17371747
)
1738-
field_order = ('manufacturer', 'device_type', 'name_pattern', 'label_pattern', 'type', 'positions', 'description')
1748+
field_order = (
1749+
'manufacturer', 'device_type', 'name_pattern', 'label_pattern', 'type', 'color', 'positions', 'description',
1750+
)
17391751

17401752

17411753
class RearPortTemplateBulkEditForm(BootstrapMixin, BulkEditForm):
@@ -1752,6 +1764,11 @@ class RearPortTemplateBulkEditForm(BootstrapMixin, BulkEditForm):
17521764
required=False,
17531765
widget=StaticSelect2()
17541766
)
1767+
color = forms.CharField(
1768+
max_length=6, # RGB color code
1769+
required=False,
1770+
widget=ColorSelect()
1771+
)
17551772
description = forms.CharField(
17561773
required=False
17571774
)
@@ -3427,7 +3444,7 @@ def clean_enabled(self):
34273444

34283445
class FrontPortFilterForm(DeviceComponentFilterForm):
34293446
field_groups = [
3430-
['name', 'label', 'type'],
3447+
['name', 'label', 'type', 'color'],
34313448
['region_id', 'site_group_id', 'site_id'],
34323449
['tag']
34333450
]
@@ -3437,6 +3454,11 @@ class FrontPortFilterForm(DeviceComponentFilterForm):
34373454
required=False,
34383455
widget=StaticSelect2Multiple()
34393456
)
3457+
color = forms.CharField(
3458+
max_length=6, # RGB color code
3459+
required=False,
3460+
widget=ColorSelect()
3461+
)
34403462
tag = TagFilterField(model)
34413463

34423464

@@ -3449,8 +3471,8 @@ class FrontPortForm(BootstrapMixin, CustomFieldModelForm):
34493471
class Meta:
34503472
model = FrontPort
34513473
fields = [
3452-
'device', 'name', 'label', 'type', 'rear_port', 'rear_port_position', 'mark_connected', 'description',
3453-
'tags',
3474+
'device', 'name', 'label', 'type', 'color', 'rear_port', 'rear_port_position', 'mark_connected',
3475+
'description', 'tags',
34543476
]
34553477
widgets = {
34563478
'device': forms.HiddenInput(),
@@ -3475,13 +3497,19 @@ class FrontPortCreateForm(ComponentCreateForm):
34753497
choices=PortTypeChoices,
34763498
widget=StaticSelect2(),
34773499
)
3500+
color = forms.CharField(
3501+
max_length=6, # RGB color code
3502+
required=False,
3503+
widget=ColorSelect()
3504+
)
34783505
rear_port_set = forms.MultipleChoiceField(
34793506
choices=[],
34803507
label='Rear ports',
34813508
help_text='Select one rear port assignment for each front port being created.',
34823509
)
34833510
field_order = (
3484-
'device', 'name_pattern', 'label_pattern', 'type', 'rear_port_set', 'mark_connected', 'description', 'tags',
3511+
'device', 'name_pattern', 'label_pattern', 'type', 'color', 'rear_port_set', 'mark_connected', 'description',
3512+
'tags',
34853513
)
34863514

34873515
def __init__(self, *args, **kwargs):
@@ -3540,7 +3568,7 @@ def get_iterative_data(self, iteration):
35403568

35413569

35423570
class FrontPortBulkEditForm(
3543-
form_from_model(FrontPort, ['label', 'type', 'mark_connected', 'description']),
3571+
form_from_model(FrontPort, ['label', 'type', 'color', 'mark_connected', 'description']),
35443572
BootstrapMixin,
35453573
AddRemoveTagsForm,
35463574
CustomFieldBulkEditForm
@@ -3572,7 +3600,8 @@ class FrontPortCSVForm(CustomFieldModelCSVForm):
35723600
class Meta:
35733601
model = FrontPort
35743602
fields = (
3575-
'device', 'name', 'label', 'type', 'mark_connected', 'rear_port', 'rear_port_position', 'description',
3603+
'device', 'name', 'label', 'type', 'color', 'mark_connected', 'rear_port', 'rear_port_position',
3604+
'description',
35763605
)
35773606
help_texts = {
35783607
'rear_port_position': 'Mapped position on corresponding rear port',
@@ -3608,7 +3637,7 @@ def __init__(self, *args, **kwargs):
36083637
class RearPortFilterForm(DeviceComponentFilterForm):
36093638
model = RearPort
36103639
field_groups = [
3611-
['name', 'label', 'type'],
3640+
['name', 'label', 'type', 'color'],
36123641
['region_id', 'site_group_id', 'site_id'],
36133642
['tag']
36143643
]
@@ -3617,6 +3646,11 @@ class RearPortFilterForm(DeviceComponentFilterForm):
36173646
required=False,
36183647
widget=StaticSelect2Multiple()
36193648
)
3649+
color = forms.CharField(
3650+
max_length=6, # RGB color code
3651+
required=False,
3652+
widget=ColorSelect()
3653+
)
36203654
tag = TagFilterField(model)
36213655

36223656

@@ -3629,7 +3663,7 @@ class RearPortForm(BootstrapMixin, CustomFieldModelForm):
36293663
class Meta:
36303664
model = RearPort
36313665
fields = [
3632-
'device', 'name', 'label', 'type', 'positions', 'mark_connected', 'description', 'tags',
3666+
'device', 'name', 'label', 'type', 'color', 'positions', 'mark_connected', 'description', 'tags',
36333667
]
36343668
widgets = {
36353669
'device': forms.HiddenInput(),
@@ -3643,27 +3677,33 @@ class RearPortCreateForm(ComponentCreateForm):
36433677
choices=PortTypeChoices,
36443678
widget=StaticSelect2(),
36453679
)
3680+
color = forms.CharField(
3681+
max_length=6, # RGB color code
3682+
required=False,
3683+
widget=ColorSelect()
3684+
)
36463685
positions = forms.IntegerField(
36473686
min_value=REARPORT_POSITIONS_MIN,
36483687
max_value=REARPORT_POSITIONS_MAX,
36493688
initial=1,
36503689
help_text='The number of front ports which may be mapped to each rear port'
36513690
)
36523691
field_order = (
3653-
'device', 'name_pattern', 'label_pattern', 'type', 'positions', 'mark_connected', 'description', 'tags',
3692+
'device', 'name_pattern', 'label_pattern', 'type', 'color', 'positions', 'mark_connected', 'description',
3693+
'tags',
36543694
)
36553695

36563696

36573697
class RearPortBulkCreateForm(
3658-
form_from_model(RearPort, ['type', 'positions', 'mark_connected']),
3698+
form_from_model(RearPort, ['type', 'color', 'positions', 'mark_connected']),
36593699
DeviceBulkAddComponentForm
36603700
):
36613701
model = RearPort
36623702
field_order = ('name_pattern', 'label_pattern', 'type', 'positions', 'mark_connected', 'description', 'tags')
36633703

36643704

36653705
class RearPortBulkEditForm(
3666-
form_from_model(RearPort, ['label', 'type', 'mark_connected', 'description']),
3706+
form_from_model(RearPort, ['label', 'type', 'color', 'mark_connected', 'description']),
36673707
BootstrapMixin,
36683708
AddRemoveTagsForm,
36693709
CustomFieldBulkEditForm
@@ -3689,7 +3729,7 @@ class RearPortCSVForm(CustomFieldModelCSVForm):
36893729

36903730
class Meta:
36913731
model = RearPort
3692-
fields = ('device', 'name', 'label', 'type', 'mark_connected', 'positions', 'description')
3732+
fields = ('device', 'name', 'label', 'type', 'color', 'mark_connected', 'positions', 'description')
36933733
help_texts = {
36943734
'positions': 'Number of front ports which may be mapped'
36953735
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from django.db import migrations
2+
import utilities.fields
3+
4+
5+
class Migration(migrations.Migration):
6+
7+
dependencies = [
8+
('dcim', '0132_cable_length'),
9+
]
10+
11+
operations = [
12+
migrations.AddField(
13+
model_name='frontport',
14+
name='color',
15+
field=utilities.fields.ColorField(blank=True, max_length=6),
16+
),
17+
migrations.AddField(
18+
model_name='frontporttemplate',
19+
name='color',
20+
field=utilities.fields.ColorField(blank=True, max_length=6),
21+
),
22+
migrations.AddField(
23+
model_name='rearport',
24+
name='color',
25+
field=utilities.fields.ColorField(blank=True, max_length=6),
26+
),
27+
migrations.AddField(
28+
model_name='rearporttemplate',
29+
name='color',
30+
field=utilities.fields.ColorField(blank=True, max_length=6),
31+
),
32+
]

0 commit comments

Comments
 (0)