Parcourir la source

Custom link cleanup

Jeremy Stretch il y a 6 ans
Parent
commit
2ec7ac1ea3

+ 15 - 0
netbox/extras/admin.py

@@ -81,9 +81,24 @@ class CustomFieldAdmin(admin.ModelAdmin):
 # Custom links
 # Custom links
 #
 #
 
 
+class CustomLinkForm(forms.ModelForm):
+
+    class Meta:
+        model = CustomLink
+        exclude = []
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+
+        # Format ContentType choices
+        order_content_types(self.fields['content_type'])
+        self.fields['content_type'].choices.insert(0, ('', '---------'))
+
+
 @admin.register(CustomLink, site=admin_site)
 @admin.register(CustomLink, site=admin_site)
 class CustomLinkAdmin(admin.ModelAdmin):
 class CustomLinkAdmin(admin.ModelAdmin):
     list_display = ['name', 'content_type', 'group_name', 'weight']
     list_display = ['name', 'content_type', 'group_name', 'weight']
+    form = CustomLinkForm
 
 
 
 
 #
 #

+ 24 - 1
netbox/extras/constants.py

@@ -36,6 +36,29 @@ CF_FILTER_CHOICES = (
 )
 )
 
 
 # Custom links
 # Custom links
+CUSTOM_LINK_MODELS = [
+    'circuits.circuit',
+    'circuits.provider',
+    'dcim.cable',
+    'dcim.device',
+    'dcim.devicetype',
+    'dcim.powerpanel',
+    'dcim.powerfeed',
+    'dcim.rack',
+    'dcim.site',
+    'dcim.region',
+    'ipam.aggregate',
+    'ipam.ipaddress',
+    'ipam.prefix',
+    'ipam.service',
+    'ipam.vlan',
+    'ipam.vrf',
+    'secrets.secret',
+    'tenancy.tenant',
+    'virtualization.cluster',
+    'virtualization.virtualmachine',
+]
+
 BUTTON_CLASS_DEFAULT = 'default'
 BUTTON_CLASS_DEFAULT = 'default'
 BUTTON_CLASS_PRIMARY = 'primary'
 BUTTON_CLASS_PRIMARY = 'primary'
 BUTTON_CLASS_SUCCESS = 'success'
 BUTTON_CLASS_SUCCESS = 'success'
@@ -50,7 +73,7 @@ BUTTON_CLASS_CHOICES = (
     (BUTTON_CLASS_INFO, 'Info (aqua)'),
     (BUTTON_CLASS_INFO, 'Info (aqua)'),
     (BUTTON_CLASS_WARNING, 'Warning (orange)'),
     (BUTTON_CLASS_WARNING, 'Warning (orange)'),
     (BUTTON_CLASS_DANGER, 'Danger (red)'),
     (BUTTON_CLASS_DANGER, 'Danger (red)'),
-    (BUTTON_CLASS_LINK, 'None'),
+    (BUTTON_CLASS_LINK, 'None (link)'),
 )
 )
 
 
 # Graph types
 # Graph types

+ 1 - 1
netbox/extras/migrations/0022_custom_links.py

@@ -21,7 +21,7 @@ class Migration(migrations.Migration):
                 ('url', models.CharField(max_length=200)),
                 ('url', models.CharField(max_length=200)),
                 ('weight', models.PositiveSmallIntegerField(default=100)),
                 ('weight', models.PositiveSmallIntegerField(default=100)),
                 ('group_name', models.CharField(blank=True, max_length=50)),
                 ('group_name', models.CharField(blank=True, max_length=50)),
-                ('button_class', models.CharField(max_length=30)),
+                ('button_class', models.CharField(default='default', max_length=30)),
                 ('new_window', models.BooleanField()),
                 ('new_window', models.BooleanField()),
                 ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
                 ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
             ],
             ],

+ 17 - 5
netbox/extras/models.py

@@ -304,6 +304,13 @@ class CustomFieldChoice(models.Model):
 # Custom links
 # Custom links
 #
 #
 
 
+def get_custom_link_models():
+    # TODO: This should match on the app_label as well as the model name to avoid potential duplicate names
+    return {
+        'model__in': [model.split('.')[1] for model in CUSTOM_LINK_MODELS],
+    }
+
+
 class CustomLink(models.Model):
 class CustomLink(models.Model):
     """
     """
     A custom link to an external representation of a NetBox object. The link text and URL fields accept Jinja2 template
     A custom link to an external representation of a NetBox object. The link text and URL fields accept Jinja2 template
@@ -311,7 +318,8 @@ class CustomLink(models.Model):
     """
     """
     content_type = models.ForeignKey(
     content_type = models.ForeignKey(
         to=ContentType,
         to=ContentType,
-        on_delete=models.CASCADE
+        on_delete=models.CASCADE,
+        limit_choices_to=get_custom_link_models
     )
     )
     name = models.CharField(
     name = models.CharField(
         max_length=100,
         max_length=100,
@@ -319,22 +327,26 @@ class CustomLink(models.Model):
     )
     )
     text = models.CharField(
     text = models.CharField(
         max_length=200,
         max_length=200,
-        help_text="Template code for link text"
+        help_text="Jinja2 template code for link text"
     )
     )
     url = models.CharField(
     url = models.CharField(
         max_length=200,
         max_length=200,
-        help_text="Template code for link URL"
+        verbose_name='URL',
+        help_text="Jinja2 template code for link URL"
     )
     )
     weight = models.PositiveSmallIntegerField(
     weight = models.PositiveSmallIntegerField(
         default=100
         default=100
     )
     )
     group_name = models.CharField(
     group_name = models.CharField(
         max_length=50,
         max_length=50,
-        blank=True
+        blank=True,
+        help_text="Links with the same group will appear as a dropdown menu"
     )
     )
     button_class = models.CharField(
     button_class = models.CharField(
         max_length=30,
         max_length=30,
-        choices=BUTTON_CLASS_CHOICES
+        choices=BUTTON_CLASS_CHOICES,
+        default=BUTTON_CLASS_DEFAULT,
+        help_text="The class of the first link in a group will be used for the dropdown button"
     )
     )
     new_window = models.BooleanField(
     new_window = models.BooleanField(
         help_text="Force link to open in a new window"
         help_text="Force link to open in a new window"