jeremystretch 3 лет назад
Родитель
Сommit
31024ce672

+ 2 - 1
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

+ 2 - 2
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):

+ 2 - 1
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):

+ 2 - 1
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',
         )
 
 

+ 4 - 0
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 += '<br />'
+                self.fields[field_name].help_text += '<i class="mdi mdi-alert-circle-outline"></i> ' \
+                                                     'Field is set to read-only.'
 
             # Annotate the field in the list of CustomField form fields
             self.custom_fields[field_name] = customfield

+ 1 - 1
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()
     )
 

+ 2 - 2
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')),
     )

+ 2 - 1
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()
 

+ 1 - 1
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')
 

+ 1 - 1
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():

+ 4 - 4
netbox/templates/extras/customfield.html

@@ -42,6 +42,10 @@
             <th scope="row">Weight</th>
             <td>{{ object.weight }}</td>
           </tr>
+          <tr>
+            <th scope="row">Filter Logic</th>
+            <td>{{ object.get_filter_logic_display }}</td>
+          </tr>
           <tr>
             <th scope="row">UI Visibility</th>
             <td>{{ object.get_ui_visibility_display }}</td>
@@ -69,10 +73,6 @@
               {% endif %}
             </td>
           </tr>
-          <tr>
-            <th scope="row">Filter Logic</th>
-            <td>{{ object.get_filter_logic_display }}</td>
-          </tr>
         </table>
       </div>
     </div>