Просмотр исходного кода

12216 Add color to circuit-type and add to SVG rendering (#14098)

* 12216 add color to model

* 12216 add forms, serializers for color

* 12216 color to detail view, add type to svg

* 12216 add color to svg

* 12216 review changes
Arthur Hanson 2 лет назад
Родитель
Сommit
ae447bd187

+ 1 - 1
netbox/circuits/api/serializers.py

@@ -85,7 +85,7 @@ class CircuitTypeSerializer(NetBoxModelSerializer):
     class Meta:
         model = CircuitType
         fields = [
-            'id', 'url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields', 'created', 'last_updated',
+            'id', 'url', 'display', 'name', 'slug', 'color', 'description', 'tags', 'custom_fields', 'created', 'last_updated',
             'circuit_count',
         ]
 

+ 1 - 1
netbox/circuits/filtersets.py

@@ -137,7 +137,7 @@ class CircuitTypeFilterSet(OrganizationalModelFilterSet):
 
     class Meta:
         model = CircuitType
-        fields = ['id', 'name', 'slug', 'description']
+        fields = ['id', 'name', 'slug', 'color', 'description']
 
 
 class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet):

+ 7 - 3
netbox/circuits/forms/bulk_edit.py

@@ -7,7 +7,7 @@ from ipam.models import ASN
 from netbox.forms import NetBoxModelBulkEditForm
 from tenancy.models import Tenant
 from utilities.forms import add_blank_choice
-from utilities.forms.fields import CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField
+from utilities.forms.fields import ColorField, CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField
 from utilities.forms.widgets import DatePicker, NumberWithOptions
 
 __all__ = (
@@ -91,6 +91,10 @@ class ProviderNetworkBulkEditForm(NetBoxModelBulkEditForm):
 
 
 class CircuitTypeBulkEditForm(NetBoxModelBulkEditForm):
+    color = ColorField(
+        label=_('Color'),
+        required=False
+    )
     description = forms.CharField(
         label=_('Description'),
         max_length=200,
@@ -99,9 +103,9 @@ class CircuitTypeBulkEditForm(NetBoxModelBulkEditForm):
 
     model = CircuitType
     fieldsets = (
-        (None, ('description',)),
+        (None, ('color', 'description')),
     )
-    nullable_fields = ('description',)
+    nullable_fields = ('color', 'description')
 
 
 class CircuitBulkEditForm(NetBoxModelBulkEditForm):

+ 5 - 1
netbox/circuits/forms/bulk_import.py

@@ -3,6 +3,7 @@ from django import forms
 from circuits.choices import CircuitStatusChoices
 from circuits.models import *
 from dcim.models import Site
+from django.utils.safestring import mark_safe
 from django.utils.translation import gettext_lazy as _
 from netbox.forms import NetBoxModelImportForm
 from tenancy.models import Tenant
@@ -64,7 +65,10 @@ class CircuitTypeImportForm(NetBoxModelImportForm):
 
     class Meta:
         model = CircuitType
-        fields = ('name', 'slug', 'description', 'tags')
+        fields = ('name', 'slug', 'color', 'description', 'tags')
+        help_texts = {
+            'color': mark_safe(_('RGB color in hexadecimal. Example:') + ' <code>00ff00</code>'),
+        }
 
 
 class CircuitImportForm(NetBoxModelImportForm):

+ 10 - 1
netbox/circuits/forms/filtersets.py

@@ -7,7 +7,7 @@ from dcim.models import Region, Site, SiteGroup
 from ipam.models import ASN
 from netbox.forms import NetBoxModelFilterSetForm
 from tenancy.forms import TenancyFilterForm, ContactModelFilterForm
-from utilities.forms.fields import DynamicModelMultipleChoiceField, TagFilterField
+from utilities.forms.fields import ColorField, DynamicModelMultipleChoiceField, TagFilterField
 from utilities.forms.widgets import DatePicker, NumberWithOptions
 
 __all__ = (
@@ -97,8 +97,17 @@ class ProviderNetworkFilterForm(NetBoxModelFilterSetForm):
 
 class CircuitTypeFilterForm(NetBoxModelFilterSetForm):
     model = CircuitType
+    fieldsets = (
+        (None, ('q', 'filter_id', 'tag')),
+        (_('Attributes'), ('color',)),
+    )
     tag = TagFilterField(model)
 
+    color = ColorField(
+        label=_('Color'),
+        required=False
+    )
+
 
 class CircuitFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm):
     model = Circuit

+ 2 - 2
netbox/circuits/forms/model_forms.py

@@ -76,14 +76,14 @@ class CircuitTypeForm(NetBoxModelForm):
 
     fieldsets = (
         (_('Circuit Type'), (
-            'name', 'slug', 'description', 'tags',
+            'name', 'slug', 'color', 'description', 'tags',
         )),
     )
 
     class Meta:
         model = CircuitType
         fields = [
-            'name', 'slug', 'description', 'tags',
+            'name', 'slug', 'color', 'description', 'tags',
         ]
 
 

+ 18 - 0
netbox/circuits/migrations/0043_circuittype_color.py

@@ -0,0 +1,18 @@
+# Generated by Django 4.2.5 on 2023-10-20 21:25
+
+from django.db import migrations
+import utilities.fields
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ('circuits', '0042_provideraccount'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='circuittype',
+            name='color',
+            field=utilities.fields.ColorField(blank=True, max_length=6),
+        ),
+    ]

+ 6 - 0
netbox/circuits/models/circuits.py

@@ -7,6 +7,7 @@ from circuits.choices import *
 from dcim.models import CabledObjectModel
 from netbox.models import ChangeLoggedModel, OrganizationalModel, PrimaryModel
 from netbox.models.features import ContactsMixin, CustomFieldsMixin, CustomLinksMixin, ImageAttachmentsMixin, TagsMixin
+from utilities.fields import ColorField
 
 __all__ = (
     'Circuit',
@@ -20,6 +21,11 @@ class CircuitType(OrganizationalModel):
     Circuits can be organized by their functional role. For example, a user might wish to define CircuitTypes named
     "Long Haul," "Metro," or "Out-of-Band".
     """
+    color = ColorField(
+        verbose_name=_('color'),
+        blank=True
+    )
+
     def get_absolute_url(self):
         return reverse('circuits:circuittype', args=[self.pk])
 

+ 2 - 1
netbox/circuits/tables/circuits.py

@@ -28,6 +28,7 @@ class CircuitTypeTable(NetBoxTable):
         linkify=True,
         verbose_name=_('Name'),
     )
+    color = columns.ColorColumn()
     tags = columns.TagColumn(
         url_name='circuits:circuittype_list'
     )
@@ -40,7 +41,7 @@ class CircuitTypeTable(NetBoxTable):
     class Meta(NetBoxTable.Meta):
         model = CircuitType
         fields = (
-            'pk', 'id', 'name', 'circuit_count', 'description', 'slug', 'tags', 'created', 'last_updated', 'actions',
+            'pk', 'id', 'name', 'circuit_count', 'color', 'description', 'slug', 'tags', 'created', 'last_updated', 'actions',
         )
         default_columns = ('pk', 'name', 'circuit_count', 'description', 'slug')
 

+ 3 - 0
netbox/dcim/svg/cables.py

@@ -159,6 +159,7 @@ class CableTraceSVG:
             labels.append(location_label)
         elif instance._meta.model_name == 'circuit':
             labels[0] = f'Circuit {instance}'
+            labels.append(instance.type)
             labels.append(instance.provider)
             if instance.description:
                 labels.append(instance.description)
@@ -181,6 +182,8 @@ class CableTraceSVG:
         if hasattr(instance, 'role'):
             # Device
             return instance.role.color
+        elif instance._meta.model_name == 'circuit' and instance.type.color:
+            return instance.type.color
         else:
             # Other parent object
             return 'e0e0e0'

+ 10 - 0
netbox/templates/circuits/circuittype.html

@@ -29,6 +29,16 @@
             <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>
         </table>
       </div>
     </div>