From bbdc7dccba65a124312a61eed02d33acd2d2fb8c Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 20 May 2016 15:32:17 -0400 Subject: [PATCH] Added JS for SlugField autofill --- netbox/circuits/forms.py | 4 +++- netbox/dcim/forms.py | 9 +++++++-- netbox/ipam/forms.py | 6 +++++- netbox/project-static/js/forms.js | 21 ++++++++++++++++++++ netbox/secrets/forms.py | 3 ++- netbox/templates/circuits/provider_edit.html | 1 - netbox/utilities/forms.py | 9 +++++++++ 7 files changed, 47 insertions(+), 6 deletions(-) diff --git a/netbox/circuits/forms.py b/netbox/circuits/forms.py index e92d94471..fabdad25d 100644 --- a/netbox/circuits/forms.py +++ b/netbox/circuits/forms.py @@ -4,6 +4,7 @@ from django.db.models import Count from dcim.models import Site, Device, Interface, Rack, IFACE_FF_VIRTUAL from utilities.forms import ( APISelect, BootstrapMixin, BulkImportForm, CommentField, ConfirmationForm, CSVDataField, Livesearch, SmallTextarea, + SlugField, ) from .models import PORT_SPEED_CHOICES, Circuit, CircuitType, Provider @@ -14,6 +15,7 @@ from .models import PORT_SPEED_CHOICES, Circuit, CircuitType, Provider # class ProviderForm(forms.ModelForm, BootstrapMixin): + slug = SlugField() comments = CommentField() class Meta: @@ -25,7 +27,6 @@ class ProviderForm(forms.ModelForm, BootstrapMixin): } help_texts = { 'name': "Full name of the provider", - 'slug': "URL-friendly unique shorthand (e.g. 'decix' for DE-CIX)", 'asn': "BGP autonomous system number (if applicable)", 'portal_url': "URL of the provider's customer support portal", 'noc_contact': "NOC email address and phone number", @@ -63,6 +64,7 @@ class ProviderBulkDeleteForm(ConfirmationForm): # class CircuitTypeForm(forms.ModelForm, BootstrapMixin): + slug = SlugField() class Meta: model = CircuitType diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 231e3c012..d97b52ce6 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -6,7 +6,7 @@ from django.db.models import Count, Q from ipam.models import IPAddress from utilities.forms import ( APISelect, BootstrapMixin, BulkImportForm, CommentField, ConfirmationForm, CSVDataField, ExpandableNameField, - FlexibleModelChoiceField, Livesearch, SelectWithDisabled, SmallTextarea, + FlexibleModelChoiceField, Livesearch, SelectWithDisabled, SmallTextarea, SlugField, ) from .models import ( @@ -43,6 +43,7 @@ def get_device_by_name_or_pk(name): # class SiteForm(forms.ModelForm, BootstrapMixin): + slug = SlugField() comments = CommentField() class Meta: @@ -54,7 +55,6 @@ class SiteForm(forms.ModelForm, BootstrapMixin): } help_texts = { 'name': "Full name of the site", - 'slug': "URL-friendly unique shorthand (e.g. 'nyc3' for NYC3)", 'facility': "Data center provider and facility (e.g. Equinix NY7)", 'asn': "BGP autonomous system number", 'physical_address': "Physical location of the building (e.g. for GPS)", @@ -78,6 +78,7 @@ class SiteImportForm(BulkImportForm, BootstrapMixin): # class RackGroupForm(forms.ModelForm, BootstrapMixin): + slug = SlugField() class Meta: model = RackGroup @@ -195,6 +196,7 @@ class RackFilterForm(forms.Form, BootstrapMixin): # class ManufacturerForm(forms.ModelForm, BootstrapMixin): + slug = SlugField() class Meta: model = Manufacturer @@ -210,6 +212,7 @@ class ManufacturerBulkDeleteForm(ConfirmationForm): # class DeviceTypeForm(forms.ModelForm, BootstrapMixin): + slug = SlugField(slug_source='model') class Meta: model = DeviceType @@ -286,6 +289,7 @@ class InterfaceTemplateForm(forms.ModelForm, BootstrapMixin): # class DeviceRoleForm(forms.ModelForm, BootstrapMixin): + slug = SlugField() class Meta: model = DeviceRole @@ -301,6 +305,7 @@ class DeviceRoleBulkDeleteForm(ConfirmationForm): # class PlatformForm(forms.ModelForm, BootstrapMixin): + slug = SlugField() class Meta: model = Platform diff --git a/netbox/ipam/forms.py b/netbox/ipam/forms.py index 28ad755bf..91e73e790 100644 --- a/netbox/ipam/forms.py +++ b/netbox/ipam/forms.py @@ -4,7 +4,9 @@ from django import forms from django.db.models import Count from dcim.models import Site, Device, Interface -from utilities.forms import BootstrapMixin, ConfirmationForm, APISelect, Livesearch, CSVDataField, BulkImportForm +from utilities.forms import ( + BootstrapMixin, ConfirmationForm, APISelect, Livesearch, CSVDataField, BulkImportForm, SlugField, +) from .models import ( Aggregate, IPAddress, Prefix, PREFIX_STATUS_CHOICES, RIR, Role, VLAN, VLAN_STATUS_CHOICES, VRF, @@ -53,6 +55,7 @@ class VRFBulkDeleteForm(ConfirmationForm): # class RIRForm(forms.ModelForm, BootstrapMixin): + slug = SlugField() class Meta: model = RIR @@ -118,6 +121,7 @@ class AggregateFilterForm(forms.Form, BootstrapMixin): # class RoleForm(forms.ModelForm, BootstrapMixin): + slug = SlugField() class Meta: model = Role diff --git a/netbox/project-static/js/forms.js b/netbox/project-static/js/forms.js index a6988e767..793a7c8e2 100644 --- a/netbox/project-static/js/forms.js +++ b/netbox/project-static/js/forms.js @@ -5,6 +5,27 @@ $(document).ready(function() { $(this).parents('table').find('td input:checkbox').prop('checked', $(this).prop('checked')); }); + // Slugify + function slugify(s, num_chars) { + s = s.replace(/[^-\.\+\w\s]/g, ''); // Remove unneeded chars + s = s.replace(/^\s+|\s+$/g, ''); // Trim leading/trailing spaces + s = s.replace(/[-\s]+/g, '-'); // Convert spaces to hyphens + s = s.toLowerCase(); // Convert to lowercase + return s.substring(0, num_chars); // Trim to first num_chars chars + } + var slug_field = $('#id_slug'); + slug_field.change(function() { + $(this).attr('_changed', true); + }); + if (slug_field) { + var slug_source = $('#id_' + slug_field.attr('slug-source')); + slug_source.keyup(function() { + if (slug_field && !slug_field.attr('_changed')) { + slug_field.val(slugify($(this).val(), 50)); + } + }) + } + // Helper select fields $('select.helper-parent').change(function () { diff --git a/netbox/secrets/forms.py b/netbox/secrets/forms.py index 478381b45..dfa3102f4 100644 --- a/netbox/secrets/forms.py +++ b/netbox/secrets/forms.py @@ -5,7 +5,7 @@ from django import forms from django.db.models import Count from dcim.models import Device -from utilities.forms import BootstrapMixin, BulkImportForm, ConfirmationForm, CSVDataField +from utilities.forms import BootstrapMixin, BulkImportForm, ConfirmationForm, CSVDataField, SlugField from .models import Secret, SecretRole, UserKey @@ -35,6 +35,7 @@ def validate_rsa_key(key, is_secret=True): # class SecretRoleForm(forms.ModelForm, BootstrapMixin): + slug = SlugField() class Meta: model = SecretRole diff --git a/netbox/templates/circuits/provider_edit.html b/netbox/templates/circuits/provider_edit.html index 7bdfd47d2..c137ccdff 100644 --- a/netbox/templates/circuits/provider_edit.html +++ b/netbox/templates/circuits/provider_edit.html @@ -7,7 +7,6 @@
{% render_field form.name %} {% render_field form.slug %} - {% render_field form.category %} {% render_field form.asn %}
diff --git a/netbox/utilities/forms.py b/netbox/utilities/forms.py index a796392f9..f392ae931 100644 --- a/netbox/utilities/forms.py +++ b/netbox/utilities/forms.py @@ -203,6 +203,15 @@ class FlexibleModelChoiceField(forms.ModelChoiceField): return value +class SlugField(forms.SlugField): + + def __init__(self, slug_source='name', *args, **kwargs): + label = kwargs.pop('label', "Slug") + help_text = kwargs.pop('help_text', "URL-friendly unique shorthand") + super(SlugField, self).__init__(label=label, help_text=help_text, *args, **kwargs) + self.widget.attrs['slug-source'] = slug_source + + # # Forms #