From 1eddade01e48227289fbe885dc77e842a9f4925c Mon Sep 17 00:00:00 2001 From: Jamie Murphy Date: Mon, 29 May 2023 21:14:20 +0100 Subject: [PATCH] MVP: custom field. url open in new_window adds new_window support to the custom_fields URL type. as discussed in #11300 --- netbox/extras/filtersets.py | 2 +- netbox/extras/forms/filtersets.py | 8 +++++++- netbox/extras/forms/model_forms.py | 2 +- .../migrations/0093_customfield_new_window.py | 18 ++++++++++++++++++ netbox/extras/models/customfields.py | 6 +++++- netbox/extras/tables/tables.py | 2 +- .../templates/builtins/customfield_value.html | 6 +++++- 7 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 netbox/extras/migrations/0093_customfield_new_window.py diff --git a/netbox/extras/filtersets.py b/netbox/extras/filtersets.py index 5253ae7b0..1f543fe3b 100644 --- a/netbox/extras/filtersets.py +++ b/netbox/extras/filtersets.py @@ -77,7 +77,7 @@ class CustomFieldFilterSet(BaseFilterSet): model = CustomField fields = [ 'id', 'content_types', 'name', 'group_name', 'required', 'search_weight', 'filter_logic', 'ui_visibility', - 'weight', 'is_cloneable', 'description', + 'weight', 'is_cloneable', 'description', 'new_window', ] def search(self, queryset, name, value): diff --git a/netbox/extras/forms/filtersets.py b/netbox/extras/forms/filtersets.py index fae15d041..9bc959819 100644 --- a/netbox/extras/forms/filtersets.py +++ b/netbox/extras/forms/filtersets.py @@ -36,7 +36,7 @@ class CustomFieldFilterForm(SavedFiltersMixin, FilterForm): fieldsets = ( (None, ('q', 'filter_id')), ('Attributes', ( - 'type', 'content_type_id', 'group_name', 'weight', 'required', 'ui_visibility', 'is_cloneable', + 'type', 'content_type_id', 'group_name', 'weight', 'required', 'ui_visibility', 'is_cloneable', 'new_window', )), ) content_type_id = ContentTypeMultipleChoiceField( @@ -72,6 +72,12 @@ class CustomFieldFilterForm(SavedFiltersMixin, FilterForm): choices=BOOLEAN_WITH_BLANK_CHOICES ) ) + new_window = forms.NullBooleanField( + required=False, + widget=forms.Select( + choices=BOOLEAN_WITH_BLANK_CHOICES + ) + ) class CustomLinkFilterForm(SavedFiltersMixin, FilterForm): diff --git a/netbox/extras/forms/model_forms.py b/netbox/extras/forms/model_forms.py index 2f617b682..5c2c2eb09 100644 --- a/netbox/extras/forms/model_forms.py +++ b/netbox/extras/forms/model_forms.py @@ -50,7 +50,7 @@ class CustomFieldForm(BootstrapMixin, forms.ModelForm): ('Custom Field', ( 'content_types', 'name', 'label', 'group_name', 'type', 'object_type', 'required', 'description', )), - ('Behavior', ('search_weight', 'filter_logic', 'ui_visibility', 'weight', 'is_cloneable')), + ('Behavior', ('search_weight', 'filter_logic', 'ui_visibility', 'weight', 'is_cloneable', 'new_window')), ('Values', ('default', 'choices')), ('Validation', ('validation_minimum', 'validation_maximum', 'validation_regex')), ) diff --git a/netbox/extras/migrations/0093_customfield_new_window.py b/netbox/extras/migrations/0093_customfield_new_window.py new file mode 100644 index 000000000..a54b419ee --- /dev/null +++ b/netbox/extras/migrations/0093_customfield_new_window.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.9 on 2023-05-29 19:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('extras', '0092_delete_jobresult'), + ] + + operations = [ + migrations.AddField( + model_name='customfield', + name='new_window', + field=models.BooleanField(default=False), + ), + ] diff --git a/netbox/extras/models/customfields.py b/netbox/extras/models/customfields.py index be3540f08..7dd19f8bc 100644 --- a/netbox/extras/models/customfields.py +++ b/netbox/extras/models/customfields.py @@ -176,13 +176,17 @@ class CustomField(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel): verbose_name='Cloneable', help_text=_('Replicate this value when cloning objects') ) + new_window = models.BooleanField( + default=False, + help_text=_("Force link to open in a new window") + ) objects = CustomFieldManager() clone_fields = ( 'content_types', 'type', 'object_type', 'group_name', 'description', 'required', 'search_weight', 'filter_logic', 'default', 'weight', 'validation_minimum', 'validation_maximum', 'validation_regex', 'choices', - 'ui_visibility', 'is_cloneable', + 'ui_visibility', 'is_cloneable', 'new_window', ) class Meta: diff --git a/netbox/extras/tables/tables.py b/netbox/extras/tables/tables.py index 8d046b85d..2cd2f1bac 100644 --- a/netbox/extras/tables/tables.py +++ b/netbox/extras/tables/tables.py @@ -38,7 +38,7 @@ class CustomFieldTable(NetBoxTable): fields = ( 'pk', 'id', 'name', 'content_types', 'label', 'type', 'group_name', 'required', 'default', 'description', 'search_weight', 'filter_logic', 'ui_visibility', 'is_cloneable', 'weight', 'choices', 'created', - 'last_updated', + 'last_updated', 'new_window', ) default_columns = ('pk', 'name', 'content_types', 'label', 'group_name', 'type', 'required', 'description') diff --git a/netbox/utilities/templates/builtins/customfield_value.html b/netbox/utilities/templates/builtins/customfield_value.html index a2b27ed2a..134cbb812 100644 --- a/netbox/utilities/templates/builtins/customfield_value.html +++ b/netbox/utilities/templates/builtins/customfield_value.html @@ -12,7 +12,11 @@ {% elif customfield.type == 'datetime' and value %} {{ value|annotated_date }} {% elif customfield.type == 'url' and value %} - {{ value|truncatechars:70 }} + {% if customfield.new_window %} + {{ value|truncatechars:70 }} + {% else %} + {{ value|truncatechars:70 }} + {% endif %} {% elif customfield.type == 'json' and value %}
{{ value|json }}
{% elif customfield.type == 'multiselect' and value %}