mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-14 01:41:22 -06:00
17195 Add color to PowerOutlet (#17623)
* 17195 Add color to PowerOutlet * 17195 Add color to PowerOutlet * Reorder serializer fields * Misc cleanup --------- Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
This commit is contained in:
parent
8cd0a3215c
commit
2c68aca344
@ -29,6 +29,10 @@ An alternative physical label identifying the power outlet.
|
|||||||
|
|
||||||
The type of power outlet.
|
The type of power outlet.
|
||||||
|
|
||||||
|
### Color
|
||||||
|
|
||||||
|
The power outlet's color (optional).
|
||||||
|
|
||||||
### Power Port
|
### 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.
|
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.
|
||||||
|
@ -155,7 +155,7 @@ class PowerOutletSerializer(NetBoxModelSerializer, CabledObjectSerializer, Conne
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = PowerOutlet
|
model = PowerOutlet
|
||||||
fields = [
|
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',
|
'feed_leg', 'description', 'mark_connected', 'cable', 'cable_end', 'link_peers', 'link_peers_type',
|
||||||
'connected_endpoints', 'connected_endpoints_type', 'connected_endpoints_reachable', 'tags', 'custom_fields',
|
'connected_endpoints', 'connected_endpoints_type', 'connected_endpoints_reachable', 'tags', 'custom_fields',
|
||||||
'created', 'last_updated', '_occupied',
|
'created', 'last_updated', '_occupied',
|
||||||
|
@ -1594,7 +1594,7 @@ class PowerOutletFilterSet(
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = PowerOutlet
|
model = PowerOutlet
|
||||||
fields = (
|
fields = (
|
||||||
'id', 'name', 'label', 'feed_leg', 'description', 'mark_connected', 'cable_end',
|
'id', 'name', 'label', 'feed_leg', 'description', 'color', 'mark_connected', 'cable_end',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ class PowerPortBulkCreateForm(
|
|||||||
|
|
||||||
|
|
||||||
class PowerOutletBulkCreateForm(
|
class PowerOutletBulkCreateForm(
|
||||||
form_from_model(PowerOutlet, ['type', 'feed_leg', 'mark_connected']),
|
form_from_model(PowerOutlet, ['type', 'color', 'feed_leg', 'mark_connected']),
|
||||||
DeviceBulkAddComponentForm
|
DeviceBulkAddComponentForm
|
||||||
):
|
):
|
||||||
model = PowerOutlet
|
model = PowerOutlet
|
||||||
|
@ -1361,7 +1361,7 @@ class PowerPortBulkEditForm(
|
|||||||
|
|
||||||
class PowerOutletBulkEditForm(
|
class PowerOutletBulkEditForm(
|
||||||
ComponentBulkEditForm,
|
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(
|
mark_connected = forms.NullBooleanField(
|
||||||
label=_('Mark connected'),
|
label=_('Mark connected'),
|
||||||
@ -1371,7 +1371,7 @@ class PowerOutletBulkEditForm(
|
|||||||
|
|
||||||
model = PowerOutlet
|
model = PowerOutlet
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
FieldSet('module', 'type', 'label', 'description', 'mark_connected'),
|
FieldSet('module', 'type', 'label', 'description', 'mark_connected', 'color'),
|
||||||
FieldSet('feed_leg', 'power_port', name=_('Power')),
|
FieldSet('feed_leg', 'power_port', name=_('Power')),
|
||||||
)
|
)
|
||||||
nullable_fields = ('module', 'label', 'type', 'feed_leg', 'power_port', 'description')
|
nullable_fields = ('module', 'label', 'type', 'feed_leg', 'power_port', 'description')
|
||||||
|
@ -798,7 +798,7 @@ class PowerOutletImportForm(NetBoxModelImportForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = PowerOutlet
|
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):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
@ -1303,7 +1303,7 @@ class PowerOutletFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
|
|||||||
model = PowerOutlet
|
model = PowerOutlet
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
FieldSet('q', 'filter_id', 'tag'),
|
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('region_id', 'site_group_id', 'site_id', 'location_id', 'rack_id', name=_('Location')),
|
||||||
FieldSet(
|
FieldSet(
|
||||||
'device_type_id', 'device_role_id', 'device_id', 'device_status', 'virtual_chassis_id',
|
'device_type_id', 'device_role_id', 'device_id', 'device_status', 'virtual_chassis_id',
|
||||||
@ -1317,6 +1317,10 @@ class PowerOutletFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
|
|||||||
required=False
|
required=False
|
||||||
)
|
)
|
||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
color = ColorField(
|
||||||
|
label=_('Color'),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
|
class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
|
||||||
|
@ -1285,7 +1285,7 @@ class PowerOutletForm(ModularDeviceComponentForm):
|
|||||||
|
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
FieldSet(
|
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',
|
'tags',
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -1293,7 +1293,7 @@ class PowerOutletForm(ModularDeviceComponentForm):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = PowerOutlet
|
model = PowerOutlet
|
||||||
fields = [
|
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',
|
'tags',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -568,6 +568,7 @@ class PowerFeedType(NetBoxObjectType, CabledObjectMixin, PathEndpointMixin):
|
|||||||
)
|
)
|
||||||
class PowerOutletType(ModularComponentType, CabledObjectMixin, PathEndpointMixin):
|
class PowerOutletType(ModularComponentType, CabledObjectMixin, PathEndpointMixin):
|
||||||
power_port: Annotated["PowerPortType", strawberry.lazy('dcim.graphql.types')] | None
|
power_port: Annotated["PowerPortType", strawberry.lazy('dcim.graphql.types')] | None
|
||||||
|
color: str
|
||||||
|
|
||||||
|
|
||||||
@strawberry_django.type(
|
@strawberry_django.type(
|
||||||
|
19
netbox/dcim/migrations/0191_poweroutlet_color.py
Normal file
19
netbox/dcim/migrations/0191_poweroutlet_color.py
Normal file
@ -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),
|
||||||
|
),
|
||||||
|
]
|
@ -481,6 +481,10 @@ class PowerOutlet(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracki
|
|||||||
blank=True,
|
blank=True,
|
||||||
help_text=_('Phase (for three-phase feeds)')
|
help_text=_('Phase (for three-phase feeds)')
|
||||||
)
|
)
|
||||||
|
color = ColorField(
|
||||||
|
verbose_name=_('color'),
|
||||||
|
blank=True
|
||||||
|
)
|
||||||
|
|
||||||
clone_fields = ('device', 'module', 'type', 'power_port', 'feed_leg')
|
clone_fields = ('device', 'module', 'type', 'power_port', 'feed_leg')
|
||||||
|
|
||||||
|
@ -512,6 +512,7 @@ class PowerOutletTable(ModularDeviceComponentTable, PathEndpointTable):
|
|||||||
verbose_name=_('Power Port'),
|
verbose_name=_('Power Port'),
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
|
color = columns.ColorColumn()
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
url_name='dcim:poweroutlet_list'
|
url_name='dcim:poweroutlet_list'
|
||||||
)
|
)
|
||||||
@ -520,10 +521,10 @@ class PowerOutletTable(ModularDeviceComponentTable, PathEndpointTable):
|
|||||||
model = models.PowerOutlet
|
model = models.PowerOutlet
|
||||||
fields = (
|
fields = (
|
||||||
'pk', 'id', 'name', 'device', 'module_bay', 'module', 'label', 'type', 'description', 'power_port',
|
'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',
|
'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):
|
class DevicePowerOutletTable(PowerOutletTable):
|
||||||
@ -540,11 +541,11 @@ class DevicePowerOutletTable(PowerOutletTable):
|
|||||||
class Meta(CableTerminationTable.Meta, DeviceComponentTable.Meta):
|
class Meta(CableTerminationTable.Meta, DeviceComponentTable.Meta):
|
||||||
model = models.PowerOutlet
|
model = models.PowerOutlet
|
||||||
fields = (
|
fields = (
|
||||||
'pk', 'id', 'name', 'module_bay', 'module', 'label', 'type', 'power_port', 'feed_leg', 'description',
|
'pk', 'id', 'name', 'module_bay', 'module', 'label', 'type', 'color', 'power_port', 'feed_leg',
|
||||||
'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'tags', 'actions',
|
'description', 'mark_connected', 'cable', 'cable_color', 'link_peer', 'connection', 'tags', 'actions',
|
||||||
)
|
)
|
||||||
default_columns = (
|
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',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -3421,9 +3421,9 @@ class PowerOutletTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedF
|
|||||||
PowerPort.objects.bulk_create(power_ports)
|
PowerPort.objects.bulk_create(power_ports)
|
||||||
|
|
||||||
power_outlets = (
|
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[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'),
|
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'),
|
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)
|
PowerOutlet.objects.bulk_create(power_outlets)
|
||||||
|
|
||||||
@ -3444,6 +3444,10 @@ class PowerOutletTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedF
|
|||||||
params = {'description': ['First', 'Second']}
|
params = {'description': ['First', 'Second']}
|
||||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
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):
|
def test_feed_leg(self):
|
||||||
params = {'feed_leg': [PowerOutletFeedLegChoices.FEED_LEG_A, PowerOutletFeedLegChoices.FEED_LEG_B]}
|
params = {'feed_leg': [PowerOutletFeedLegChoices.FEED_LEG_A, PowerOutletFeedLegChoices.FEED_LEG_B]}
|
||||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||||
|
@ -40,6 +40,16 @@
|
|||||||
<th scope="row">{% trans "Description" %}</th>
|
<th scope="row">{% trans "Description" %}</th>
|
||||||
<td>{{ object.description|placeholder }}</td>
|
<td>{{ object.description|placeholder }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Color" %}</th>
|
||||||
|
<td>
|
||||||
|
{% if object.color %}
|
||||||
|
<span class="badge color-label" style="background-color: #{{ object.color }}"> </span>
|
||||||
|
{% else %}
|
||||||
|
{{ ''|placeholder }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">{% trans "Power Port" %}</th>
|
<th scope="row">{% trans "Power Port" %}</th>
|
||||||
<td>{{ object.power_port|linkify|placeholder }}</td>
|
<td>{{ object.power_port|linkify|placeholder }}</td>
|
||||||
|
Loading…
Reference in New Issue
Block a user