1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Standardize on get_FOO_color() method for returning ChoiceField colors

This commit is contained in:
jeremystretch
2022-02-11 14:25:13 -05:00
parent 9cf9f1bdba
commit 1319b62acb
31 changed files with 81 additions and 60 deletions

View File

@ -132,6 +132,9 @@ class Circuit(NetBoxModel):
def get_absolute_url(self):
return reverse('circuits:circuit', args=[self.pk])
def get_status_color(self):
return CircuitStatusChoices.colors.get(self.status)
class CircuitTermination(WebhooksMixin, ChangeLoggedModel, LinkTermination):
circuit = models.ForeignKey(

View File

@ -286,6 +286,9 @@ class Cable(NetBoxModel):
# Update the private pk used in __str__ in case this is a new object (i.e. just got its pk)
self._pk = self.pk
def get_status_color(self):
return LinkStatusChoices.colors.get(self.status)
def get_compatible_types(self):
"""
Return all termination types compatible with termination A.

View File

@ -1001,6 +1001,9 @@ class Device(NetBoxModel, ConfigContextModel):
"""
return Device.objects.filter(parent_bay__device=self.pk)
def get_status_color(self):
return DeviceStatusChoices.colors.get(self.status)
class Module(NetBoxModel, ConfigContextModel):
"""

View File

@ -169,3 +169,9 @@ class PowerFeed(NetBoxModel, PathEndpoint, LinkTermination):
@property
def parent_object(self):
return self.power_panel
def get_type_color(self):
return PowerFeedTypeChoices.colors.get(self.type)
def get_status_color(self):
return PowerFeedStatusChoices.colors.get(self.status)

View File

@ -247,6 +247,9 @@ class Rack(NetBoxModel):
else:
return reversed(range(1, self.u_height + 1))
def get_status_color(self):
return RackStatusChoices.colors.get(self.status)
def get_rack_units(self, user=None, face=DeviceFaceChoices.FACE_FRONT, exclude=None, expand_devices=True):
"""
Return a list of rack units as dictionaries. Example: {'device': None, 'face': 0, 'id': 48, 'name': 'U48'}

View File

@ -309,6 +309,9 @@ class Site(NetBoxModel):
def get_absolute_url(self):
return reverse('dcim:site', args=[self.pk])
def get_status_color(self):
return SiteStatusChoices.colors.get(self.status)
#
# Locations

View File

@ -31,7 +31,7 @@ DEVICE_LINK = """
DEVICEBAY_STATUS = """
{% if record.installed_device_id %}
<span class="badge bg-{{ record.installed_device.get_status_class }}">
<span class="badge bg-{{ record.installed_device.get_status_color }}">
{{ record.installed_device.get_status_display }}
</span>
{% else %}
@ -43,7 +43,7 @@ INTERFACE_IPADDRESSES = """
<div class="table-badge-group">
{% for ip in record.ip_addresses.all %}
{% if ip.status != 'active' %}
<a href="{{ ip.get_absolute_url }}" class="table-badge badge bg-{{ ip.get_status_class }}" data-bs-toggle="tooltip" data-bs-placement="left" title="{{ ip.get_status_display }}">{{ ip }}</a>
<a href="{{ ip.get_absolute_url }}" class="table-badge badge bg-{{ ip.get_status_color }}" data-bs-toggle="tooltip" data-bs-placement="left" title="{{ ip.get_status_display }}">{{ ip }}</a>
{% else %}
<a href="{{ ip.get_absolute_url }}" class="table-badge">{{ ip }}</a>
{% endif %}

View File

@ -102,3 +102,6 @@ class ObjectChange(models.Model):
def get_absolute_url(self):
return reverse('extras:objectchange', args=[self.pk])
def get_action_color(self):
return ObjectChangeActionChoices.colors.get(self.action)

View File

@ -458,6 +458,9 @@ class JournalEntry(WebhooksMixin, ChangeLoggedModel):
def get_absolute_url(self):
return reverse('extras:journalentry', args=[self.pk])
def get_kind_color(self):
return JournalEntryKindChoices.colors.get(self.kind)
class JobResult(models.Model):
"""

View File

@ -437,6 +437,9 @@ class Prefix(GetAvailablePrefixesMixin, NetBoxModel):
self.prefix.prefixlen = value
prefix_length = property(fset=_set_prefix_length)
def get_status_color(self):
return PrefixStatusChoices.colors.get(self.status)
def get_parents(self, include_self=False):
"""
Return all containing Prefixes in the hierarchy.
@ -703,6 +706,9 @@ class IPRange(NetBoxModel):
self.end_address.prefixlen = value
prefix_length = property(fset=_set_prefix_length)
def get_status_color(self):
return IPRangeStatusChoices.colors.get(self.status)
def get_child_ips(self):
"""
Return all IPAddresses within this IPRange and VRF.
@ -916,3 +922,9 @@ class IPAddress(NetBoxModel):
if self.address is not None:
self.address.prefixlen = value
mask_length = property(fset=_set_mask_length)
def get_status_color(self):
return IPAddressStatusChoices.colors.get(self.status)
def get_role_color(self):
return IPAddressRoleChoices.colors.get(self.role)

View File

@ -211,6 +211,9 @@ class VLAN(NetBoxModel):
f"{self.group}"
})
def get_status_color(self):
return VLANStatusChoices.colors.get(self.status)
def get_interfaces(self):
# Return all device interfaces assigned to this VLAN
return Interface.objects.filter(

View File

@ -167,19 +167,20 @@ class ActionsColumn(tables.Column):
class ChoiceFieldColumn(tables.Column):
"""
Render a model's static ChoiceField with its value from `get_FOO_display()` as a colored badge. Colors are derived
from the ChoiceSet associated with the model field.
Render a model's static ChoiceField with its value from `get_FOO_display()` as a colored badge. Background color is
set by the instance's get_FOO_color() method, if defined.
"""
DEFAULT_BG_COLOR = 'secondary'
def render(self, record, bound_column, value):
if value in self.empty_values:
return self.default
accessor = tables.A(bound_column.accessor)
field = accessor.get_field(record)
raw_value = accessor.resolve(record) # `value` is from get_FOO_display()
# Determine the background color to use
bg_color = field.choices.colors.get(raw_value, 'secondary')
# Determine the background color to use (try calling object.get_FOO_color())
try:
bg_color = getattr(record, f'get_{bound_column.name}_color')()
except AttributeError:
bg_color = self.DEFAULT_BG_COLOR
return mark_safe(f'<span class="badge bg-{bg_color}">{value}</span>')

View File

@ -32,9 +32,7 @@
</tr>
<tr>
<th scope="row">Status</th>
<td>
<span class="badge bg-{{ object.get_status_class }}">{{ object.get_status_display }}</span>
</td>
<td>{% badge object.get_status_display bg_color=object.get_status_color %}</td>
</tr>
<tr>
<th scope="row">Tenant</th>

View File

@ -19,9 +19,7 @@
</tr>
<tr>
<th scope="row">Status</th>
<td>
<span class="badge bg-{{ object.get_status_class }}">{{ object.get_status_display }}</span>
</td>
<td>{% badge object.get_status_display bg_color=object.get_status_color %}</td>
</tr>
<tr>
<th scope="row">Tenant</th>

View File

@ -163,9 +163,7 @@
<table class="table table-hover attr-table">
<tr>
<th scope="row">Status</th>
<td>
<span class="badge bg-{{ object.get_status_class }}">{{ object.get_status_display }}</span>
</td>
<td>{% badge object.get_status_display bg_color=object.get_status_color %}</td>
</tr>
<tr>
<th scope="row">Role</th>

View File

@ -40,15 +40,11 @@
</tr>
<tr>
<th scope="row">Type</th>
<td>
<span class="badge bg-{{ object.get_type_class }}">{{ object.get_type_display }}</span>
</td>
<td>{% badge object.get_type_display bg_color=object.get_type_color %}</td>
</tr>
<tr>
<th scope="row">Status</th>
<td>
<span class="badge bg-{{ object.get_status_class }}">{{ object.get_status_display }}</span>
</td>
<td>{% badge object.get_status_display bg_color=object.get_status_color %}</td>
</tr>
<tr>
<th scope="row">Connected Device</th>

View File

@ -76,9 +76,7 @@
</tr>
<tr>
<th scope="row">Status</th>
<td>
<span class="badge bg-{{ object.get_status_class }}">{{ object.get_status_display }}</span>
</td>
<td>{% badge object.get_status_display bg_color=object.get_status_color %}</td>
</tr>
<tr>
<th scope="row">Role</th>
@ -188,10 +186,10 @@
<a href="{{ powerfeed.get_absolute_url }}">{{ powerfeed.name }}</a>
</td>
<td>
<span class="badge bg-{{ powerfeed.get_status_class }}">{{ powerfeed.get_status_display }}</span>
{% badge powerfeed.get_status_display bg_color=powerfeed.get_status_color %}
</td>
<td>
<span class="badge bg-{{ powerfeed.get_type_class }}">{{ powerfeed.get_type_display }}</span>
{% badge powerfeed.get_type_display bg_color=powerfeed.get_type_color %}
</td>
{% with power_port=powerfeed.connected_endpoint %}
{% if power_port %}

View File

@ -53,9 +53,7 @@
</tr>
<tr>
<th scope="row">Status</th>
<td>
<span class="badge bg-{{ object.get_status_class }}">{{ object.get_status_display }}</span>
</td>
<td>{% badge object.get_status_display bg_color=object.get_status_color %}</td>
</tr>
<tr>
<th scope="row">Tenant</th>

View File

@ -12,7 +12,7 @@
{% if cable.length %}
({{ cable.length|floatformat }} {{ cable.get_length_unit_display }})<br />
{% endif %}
<span class="badge bg-{{ cable.get_status_class }}">{{ cable.get_status_display }}</span><br />
{% badge object.get_status_display bg_color=object.get_status_color %}<br />
{% for tag in cable.tags.all %}
{% tag tag 'dcim:cable_list' %}
{% endfor %}

View File

@ -36,9 +36,7 @@
</tr>
<tr>
<th scope="row">Kind</th>
<td>
<span class="badge bg-{{ object.get_kind_class }}">{{ object.get_kind_display }}</span>
</td>
<td>{% badge object.get_kind_display bg_color=object.get_kind_color %}</td>
</tr>
</table>
</div>

View File

@ -52,7 +52,7 @@ Context:
<li class="nav-item" role="presentation">
<button class="nav-link" id="filters-form-tab" data-bs-toggle="tab" data-bs-target="#filters-form" type="button" role="tab" aria-controls="object-list" aria-selected="false">
Filters
{% if filter_form %}{% badge filter_form.changed_data|length bg_class="primary" %}{% endif %}
{% if filter_form %}{% badge filter_form.changed_data|length bg_color="primary" %}{% endif %}
</button>
</li>
{% endif %}

View File

@ -48,9 +48,7 @@
</tr>
<tr>
<th scope="row">Status</th>
<td>
<span class="badge bg-{{ object.get_status_class }}">{{ object.get_status_display }}</span>
</td>
<td>{% badge object.get_status_display bg_color=object.get_status_color %}</td>
</tr>
<tr>
<th scope="row">Role</th>

View File

@ -55,9 +55,7 @@
</tr>
<tr>
<th scope="row">Status</th>
<td>
<span class="badge bg-{{ object.get_status_class }}">{{ object.get_status_display }}</span>
</td>
<td>{% badge object.get_status_display bg_color=object.get_status_color %}</td>
</tr>
<tr>
<th scope="row">Tenant</th>

View File

@ -75,9 +75,7 @@
</tr>
<tr>
<th scope="row">Status</th>
<td>
<span class="badge bg-{{ object.get_status_class }}">{{ object.get_status_display }}</span>
</td>
<td>{% badge object.get_status_display bg_color=object.get_status_color %}</td>
</tr>
<tr>
<th scope="row">Role</th>

View File

@ -58,9 +58,7 @@
</tr>
<tr>
<th scope="row">Status</th>
<td>
<span class="badge bg-{{ object.get_status_class }}">{{ object.get_status_display }}</span>
</td>
<td>{% badge object.get_status_display bg_color=object.get_status_color %}</td>
</tr>
<tr>
<th scope="row">Role</th>

View File

@ -19,9 +19,7 @@
</tr>
<tr>
<th scope="row">Status</th>
<td>
<span class="badge bg-{{ object.get_status_class }}">{{ object.get_status_display }}</span>
</td>
<td>{% badge object.get_status_display bg_color=object.get_status_color %}</td>
</tr>
<tr>
<th scope="row">Role</th>

View File

@ -17,9 +17,7 @@
<table class="table table-hover attr-table">
<tr>
<th scope="row">Status</th>
<td>
<span class="badge bg-{{ object.get_status_class }}">{{ object.get_status_display }}</span>
</td>
<td>{% badge object.get_status_display bg_color=object.get_status_color %}</td>
</tr>
<tr>
<th scope="row">SSID</th>

View File

@ -1 +1 @@
{% if value or show_empty %}<span class="badge bg-{{ bg_class }}">{{ value }}</span>{% endif %}
{% if value or show_empty %}<span class="badge bg-{{ bg_color }}">{{ value }}</span>{% endif %}

View File

@ -19,18 +19,18 @@ def tag(value, viewname=None):
@register.inclusion_tag('builtins/badge.html')
def badge(value, bg_class='secondary', show_empty=False):
def badge(value, bg_color='secondary', show_empty=False):
"""
Display the specified number as a badge.
Args:
value: The value to be displayed within the badge
bg_class: Bootstrap 5 background CSS name
bg_color: Background color CSS name
show_empty: If true, display the badge even if value is None or zero
"""
return {
'value': value,
'bg_class': bg_class,
'bg_color': bg_color,
'show_empty': show_empty,
}

View File

@ -322,6 +322,9 @@ class VirtualMachine(NetBoxModel, ConfigContextModel):
field: f"The specified IP address ({ip}) is not assigned to this VM.",
})
def get_status_color(self):
return VirtualMachineStatusChoices.colors.get(self.status)
@property
def primary_ip(self):
if get_config().PREFER_IPV4 and self.primary_ip4:

View File

@ -177,6 +177,9 @@ class WirelessLink(WirelessAuthenticationBase, NetBoxModel):
def get_absolute_url(self):
return reverse('wireless:wirelesslink', args=[self.pk])
def get_status_color(self):
return LinkStatusChoices.colors.get(self.status)
def clean(self):
# Validate interface types