Skip to content

Commit

Permalink
17195 Add color to PowerOutlet (#17623)
Browse files Browse the repository at this point in the history
* 17195 Add color to PowerOutlet

* 17195 Add color to PowerOutlet

* Reorder serializer fields

* Misc cleanup

---------

Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
  • Loading branch information
2 people authored and bctiemann committed Oct 16, 2024
1 parent cfb23ad commit 0544189
Show file tree
Hide file tree
Showing 14 changed files with 64 additions and 17 deletions.
4 changes: 4 additions & 0 deletions docs/models/dcim/poweroutlet.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ An alternative physical label identifying the power outlet.

The type of power outlet.

### Color

The power outlet's color (optional).

### Power Port

When modeling a device which redistributes power from an upstream supply, such as a power distribution unit (PDU), each power outlet should be mapped to the respective [power port](./powerport.md) on the device which supplies power. For example, a 24-outlet PDU may two power ports, each distributing power to 12 of its outlets.
Expand Down
2 changes: 1 addition & 1 deletion netbox/dcim/api/serializers_/device_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ class PowerOutletSerializer(NetBoxModelSerializer, CabledObjectSerializer, Conne
class Meta:
model = PowerOutlet
fields = [
'id', 'url', 'display_url', 'display', 'device', 'module', 'name', 'label', 'type', 'power_port',
'id', 'url', 'display_url', 'display', 'device', 'module', 'name', 'label', 'type', 'color', 'power_port',
'feed_leg', 'description', 'mark_connected', 'cable', 'cable_end', 'link_peers', 'link_peers_type',
'connected_endpoints', 'connected_endpoints_type', 'connected_endpoints_reachable', 'tags', 'custom_fields',
'created', 'last_updated', '_occupied',
Expand Down
2 changes: 1 addition & 1 deletion netbox/dcim/filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1594,7 +1594,7 @@ class PowerOutletFilterSet(
class Meta:
model = PowerOutlet
fields = (
'id', 'name', 'label', 'feed_leg', 'description', 'mark_connected', 'cable_end',
'id', 'name', 'label', 'feed_leg', 'description', 'color', 'mark_connected', 'cable_end',
)


Expand Down
2 changes: 1 addition & 1 deletion netbox/dcim/forms/bulk_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class PowerPortBulkCreateForm(


class PowerOutletBulkCreateForm(
form_from_model(PowerOutlet, ['type', 'feed_leg', 'mark_connected']),
form_from_model(PowerOutlet, ['type', 'color', 'feed_leg', 'mark_connected']),
DeviceBulkAddComponentForm
):
model = PowerOutlet
Expand Down
4 changes: 2 additions & 2 deletions netbox/dcim/forms/bulk_edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -1361,7 +1361,7 @@ class PowerPortBulkEditForm(

class PowerOutletBulkEditForm(
ComponentBulkEditForm,
form_from_model(PowerOutlet, ['label', 'type', 'feed_leg', 'power_port', 'mark_connected', 'description'])
form_from_model(PowerOutlet, ['label', 'type', 'color', 'feed_leg', 'power_port', 'mark_connected', 'description'])
):
mark_connected = forms.NullBooleanField(
label=_('Mark connected'),
Expand All @@ -1371,7 +1371,7 @@ class PowerOutletBulkEditForm(

model = PowerOutlet
fieldsets = (
FieldSet('module', 'type', 'label', 'description', 'mark_connected'),
FieldSet('module', 'type', 'label', 'description', 'mark_connected', 'color'),
FieldSet('feed_leg', 'power_port', name=_('Power')),
)
nullable_fields = ('module', 'label', 'type', 'feed_leg', 'power_port', 'description')
Expand Down
2 changes: 1 addition & 1 deletion netbox/dcim/forms/bulk_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,7 @@ class PowerOutletImportForm(NetBoxModelImportForm):

class Meta:
model = PowerOutlet
fields = ('device', 'name', 'label', 'type', 'mark_connected', 'power_port', 'feed_leg', 'description', 'tags')
fields = ('device', 'name', 'label', 'type', 'color', 'mark_connected', 'power_port', 'feed_leg', 'description', 'tags')

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand Down
6 changes: 5 additions & 1 deletion netbox/dcim/forms/filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1303,7 +1303,7 @@ class PowerOutletFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
model = PowerOutlet
fieldsets = (
FieldSet('q', 'filter_id', 'tag'),
FieldSet('name', 'label', 'type', name=_('Attributes')),
FieldSet('name', 'label', 'type', 'color', name=_('Attributes')),
FieldSet('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
FieldSet(
'device_type_id', 'device_role_id', 'device_id', 'device_status', 'virtual_chassis_id',
Expand All @@ -1317,6 +1317,10 @@ class PowerOutletFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
required=False
)
tag = TagFilterField(model)
color = ColorField(
label=_('Color'),
required=False
)


class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
Expand Down
4 changes: 2 additions & 2 deletions netbox/dcim/forms/model_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -1285,15 +1285,15 @@ class PowerOutletForm(ModularDeviceComponentForm):

fieldsets = (
FieldSet(
'device', 'module', 'name', 'label', 'type', 'power_port', 'feed_leg', 'mark_connected', 'description',
'device', 'module', 'name', 'label', 'type', 'color', 'power_port', 'feed_leg', 'mark_connected', 'description',
'tags',
),
)

class Meta:
model = PowerOutlet
fields = [
'device', 'module', 'name', 'label', 'type', 'power_port', 'feed_leg', 'mark_connected', 'description',
'device', 'module', 'name', 'label', 'type', 'color', 'power_port', 'feed_leg', 'mark_connected', 'description',
'tags',
]

Expand Down
1 change: 1 addition & 0 deletions netbox/dcim/graphql/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,7 @@ class PowerFeedType(NetBoxObjectType, CabledObjectMixin, PathEndpointMixin):
)
class PowerOutletType(ModularComponentType, CabledObjectMixin, PathEndpointMixin):
power_port: Annotated["PowerPortType", strawberry.lazy('dcim.graphql.types')] | None
color: str


@strawberry_django.type(
Expand Down
19 changes: 19 additions & 0 deletions netbox/dcim/migrations/0191_poweroutlet_color.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 5.0.9 on 2024-09-26 19:31

import utilities.fields
from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('dcim', '0190_nested_modules'),
]

operations = [
migrations.AddField(
model_name='poweroutlet',
name='color',
field=utilities.fields.ColorField(blank=True, max_length=6),
),
]
4 changes: 4 additions & 0 deletions netbox/dcim/models/device_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,10 @@ class PowerOutlet(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracki
blank=True,
help_text=_('Phase (for three-phase feeds)')
)
color = ColorField(
verbose_name=_('color'),
blank=True
)

clone_fields = ('device', 'module', 'type', 'power_port', 'feed_leg')

Expand Down
11 changes: 6 additions & 5 deletions netbox/dcim/tables/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ class PowerOutletTable(ModularDeviceComponentTable, PathEndpointTable):
verbose_name=_('Power Port'),
linkify=True
)
color = columns.ColorColumn()
tags = columns.TagColumn(
url_name='dcim:poweroutlet_list'
)
Expand All @@ -520,10 +521,10 @@ class Meta(DeviceComponentTable.Meta):
model = models.PowerOutlet
fields = (
'pk', 'id', 'name', 'device', 'module_bay', 'module', 'label', 'type', 'description', 'power_port',
'feed_leg', 'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'inventory_items',
'color', 'feed_leg', 'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'inventory_items',
'tags', 'created', 'last_updated',
)
default_columns = ('pk', 'name', 'device', 'label', 'type', 'power_port', 'feed_leg', 'description')
default_columns = ('pk', 'name', 'device', 'label', 'type', 'color', 'power_port', 'feed_leg', 'description')


class DevicePowerOutletTable(PowerOutletTable):
Expand All @@ -540,11 +541,11 @@ class DevicePowerOutletTable(PowerOutletTable):
class Meta(CableTerminationTable.Meta, DeviceComponentTable.Meta):
model = models.PowerOutlet
fields = (
'pk', 'id', 'name', 'module_bay', 'module', 'label', 'type', 'power_port', 'feed_leg', 'description',
'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'tags', 'actions',
'pk', 'id', 'name', 'module_bay', 'module', 'label', 'type', 'color', 'power_port', 'feed_leg',
'description', 'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'tags', 'actions',
)
default_columns = (
'pk', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'cable', 'connection',
'pk', 'name', 'label', 'type', 'color', 'power_port', 'feed_leg', 'description', 'cable', 'connection',
)


Expand Down
10 changes: 7 additions & 3 deletions netbox/dcim/tests/test_filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -3421,9 +3421,9 @@ def setUpTestData(cls):
PowerPort.objects.bulk_create(power_ports)

power_outlets = (
PowerOutlet(device=devices[0], module=modules[0], name='Power Outlet 1', label='A', feed_leg=PowerOutletFeedLegChoices.FEED_LEG_A, description='First'),
PowerOutlet(device=devices[1], module=modules[1], name='Power Outlet 2', label='B', feed_leg=PowerOutletFeedLegChoices.FEED_LEG_B, description='Second'),
PowerOutlet(device=devices[2], module=modules[2], name='Power Outlet 3', label='C', feed_leg=PowerOutletFeedLegChoices.FEED_LEG_C, description='Third'),
PowerOutlet(device=devices[0], module=modules[0], name='Power Outlet 1', label='A', feed_leg=PowerOutletFeedLegChoices.FEED_LEG_A, description='First', color='ff0000'),
PowerOutlet(device=devices[1], module=modules[1], name='Power Outlet 2', label='B', feed_leg=PowerOutletFeedLegChoices.FEED_LEG_B, description='Second', color='00ff00'),
PowerOutlet(device=devices[2], module=modules[2], name='Power Outlet 3', label='C', feed_leg=PowerOutletFeedLegChoices.FEED_LEG_C, description='Third', color='0000ff'),
)
PowerOutlet.objects.bulk_create(power_outlets)

Expand All @@ -3444,6 +3444,10 @@ def test_description(self):
params = {'description': ['First', 'Second']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)

def test_color(self):
params = {'color': ['ff0000', '00ff00']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)

def test_feed_leg(self):
params = {'feed_leg': [PowerOutletFeedLegChoices.FEED_LEG_A, PowerOutletFeedLegChoices.FEED_LEG_B]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
Expand Down
10 changes: 10 additions & 0 deletions netbox/templates/dcim/poweroutlet.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ <h2 class="card-header">{% trans "Power Outlet" %}</h2>
<th scope="row">{% trans "Description" %}</th>
<td>{{ object.description|placeholder }}</td>
</tr>
<tr>
<th scope="row">{% trans "Color" %}</th>
<td>
{% if object.color %}
<span class="badge color-label" style="background-color: #{{ object.color }}">&nbsp;</span>
{% else %}
{{ ''|placeholder }}
{% endif %}
</td>
</tr>
<tr>
<th scope="row">{% trans "Power Port" %}</th>
<td>{{ object.power_port|linkify|placeholder }}</td>
Expand Down

0 comments on commit 0544189

Please sign in to comment.