diff --git a/docs/release-notes/version-3.3.md b/docs/release-notes/version-3.3.md index d1b6b4cda..cefab428e 100644 --- a/docs/release-notes/version-3.3.md +++ b/docs/release-notes/version-3.3.md @@ -12,6 +12,7 @@ * [#8471](https://github.com/netbox-community/netbox/issues/8471) - Add `status` field to Cluster * [#8495](https://github.com/netbox-community/netbox/issues/8495) - Enable custom field grouping * [#8995](https://github.com/netbox-community/netbox/issues/8995) - Enable arbitrary ordering of REST API results +* [#9166](https://github.com/netbox-community/netbox/issues/9166) - Add UI visibility toggle for custom fields ### Other Changes @@ -20,7 +21,7 @@ ### REST API Changes * extras.CustomField - * Added `group_name` field + * Added `group_name` and `ui_visibility` fields * ipam.IPAddress * The `nat_inside` field no longer requires a unique value * The `nat_outside` field has changed from a single IP address instance to a list of multiple IP addresses diff --git a/netbox/extras/api/serializers.py b/netbox/extras/api/serializers.py index 1a26faec1..cb317d6c7 100644 --- a/netbox/extras/api/serializers.py +++ b/netbox/extras/api/serializers.py @@ -90,8 +90,8 @@ class CustomFieldSerializer(ValidatedModelSerializer): model = CustomField fields = [ 'id', 'url', 'display', 'content_types', 'type', 'object_type', 'data_type', 'name', 'label', 'group_name', - 'description', 'required', 'filter_logic', 'default', 'weight', 'validation_minimum', 'validation_maximum', - 'validation_regex', 'choices', 'created', 'last_updated', 'ui_visibility', + 'description', 'required', 'filter_logic', 'ui_visibility', 'default', 'weight', 'validation_minimum', + 'validation_maximum', 'validation_regex', 'choices', 'created', 'last_updated', ] def get_data_type(self, obj): diff --git a/netbox/extras/filtersets.py b/netbox/extras/filtersets.py index ea74dfc82..b59e28018 100644 --- a/netbox/extras/filtersets.py +++ b/netbox/extras/filtersets.py @@ -63,7 +63,8 @@ class CustomFieldFilterSet(BaseFilterSet): class Meta: model = CustomField fields = [ - 'id', 'content_types', 'name', 'group_name', 'required', 'filter_logic', 'weight', 'description', 'ui_visibility' + 'id', 'content_types', 'name', 'group_name', 'required', 'filter_logic', 'ui_visibility', 'weight', + 'description', ] def search(self, queryset, name, value): diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py index c0483d36e..95de7a2fe 100644 --- a/netbox/extras/forms/bulk_import.py +++ b/netbox/extras/forms/bulk_import.py @@ -37,7 +37,8 @@ class CustomFieldCSVForm(CSVModelForm): model = CustomField fields = ( 'name', 'label', 'group_name', 'type', 'content_types', 'required', 'description', 'weight', 'filter_logic', - 'default', 'choices', 'weight', 'validation_minimum', 'validation_maximum', 'validation_regex', 'ui_visibility', + 'default', 'choices', 'weight', 'validation_minimum', 'validation_maximum', 'validation_regex', + 'ui_visibility', ) diff --git a/netbox/extras/forms/customfields.py b/netbox/extras/forms/customfields.py index c4496c5f8..4cf8b5e0a 100644 --- a/netbox/extras/forms/customfields.py +++ b/netbox/extras/forms/customfields.py @@ -51,6 +51,10 @@ class CustomFieldsMixin: if customfield.ui_visibility == CustomFieldVisibilityChoices.VISIBILITY_READ_ONLY: self.fields[field_name].disabled = True + if self.fields[field_name].help_text: + self.fields[field_name].help_text += '
' + self.fields[field_name].help_text += ' ' \ + 'Field is set to read-only.' # Annotate the field in the list of CustomField form fields self.custom_fields[field_name] = customfield diff --git a/netbox/extras/forms/filtersets.py b/netbox/extras/forms/filtersets.py index cd59a9db1..aaeb45dbe 100644 --- a/netbox/extras/forms/filtersets.py +++ b/netbox/extras/forms/filtersets.py @@ -59,7 +59,7 @@ class CustomFieldFilterForm(FilterForm): ui_visibility = forms.ChoiceField( choices=add_blank_choice(CustomFieldVisibilityChoices), required=False, - label=_('UI Visibility'), + label=_('UI visibility'), widget=StaticSelect() ) diff --git a/netbox/extras/forms/models.py b/netbox/extras/forms/models.py index 16874c49e..ab423e2fb 100644 --- a/netbox/extras/forms/models.py +++ b/netbox/extras/forms/models.py @@ -41,9 +41,9 @@ class CustomFieldForm(BootstrapMixin, forms.ModelForm): fieldsets = ( ('Custom Field', ( - 'content_types', 'name', 'label', 'group_name', 'type', 'object_type', 'weight', 'required', 'description', 'ui_visibility', + 'content_types', 'name', 'label', 'group_name', 'type', 'object_type', 'weight', 'required', 'description', )), - ('Behavior', ('filter_logic',)), + ('Behavior', ('filter_logic', 'ui_visibility')), ('Values', ('default', 'choices')), ('Validation', ('validation_minimum', 'validation_maximum', 'validation_regex')), ) diff --git a/netbox/extras/models/customfields.py b/netbox/extras/models/customfields.py index c48b6895c..c91f96c15 100644 --- a/netbox/extras/models/customfields.py +++ b/netbox/extras/models/customfields.py @@ -140,7 +140,8 @@ class CustomField(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel): max_length=50, choices=CustomFieldVisibilityChoices, default=CustomFieldVisibilityChoices.VISIBILITY_READ_WRITE, - help_text='Specifies the visibility of custom field in the UI.' + verbose_name='UI visibility', + help_text='Specifies the visibility of custom field in the UI' ) objects = CustomFieldManager() diff --git a/netbox/extras/tables/tables.py b/netbox/extras/tables/tables.py index d294fd231..540034696 100644 --- a/netbox/extras/tables/tables.py +++ b/netbox/extras/tables/tables.py @@ -34,7 +34,7 @@ class CustomFieldTable(NetBoxTable): model = CustomField fields = ( 'pk', 'id', 'name', 'content_types', 'label', 'type', 'group_name', 'required', 'weight', 'default', - 'description', 'filter_logic', 'choices', 'created', 'last_updated', 'ui_visibility', + 'description', 'filter_logic', 'ui_visibility', 'choices', 'created', 'last_updated', ) default_columns = ('pk', 'name', 'content_types', 'label', 'group_name', 'type', 'required', 'description') diff --git a/netbox/netbox/models/features.py b/netbox/netbox/models/features.py index 76b546192..817da526b 100644 --- a/netbox/netbox/models/features.py +++ b/netbox/netbox/models/features.py @@ -125,7 +125,7 @@ class CustomFieldsMixin(models.Model): def get_custom_fields_by_group(self): """ - Return a dictionary of custom field/value mappings organized by group. + Return a dictionary of custom field/value mappings organized by group. Hidden fields are omitted. """ grouped_custom_fields = defaultdict(dict) for cf, value in self.get_custom_fields(omit_hidden=True).items(): diff --git a/netbox/templates/extras/customfield.html b/netbox/templates/extras/customfield.html index 72dc2e4c3..aca0b5012 100644 --- a/netbox/templates/extras/customfield.html +++ b/netbox/templates/extras/customfield.html @@ -42,6 +42,10 @@ Weight {{ object.weight }} + + Filter Logic + {{ object.get_filter_logic_display }} + UI Visibility {{ object.get_ui_visibility_display }} @@ -69,10 +73,6 @@ {% endif %} - - Filter Logic - {{ object.get_filter_logic_display }} -