mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Changelog & cleanup for #9166
This commit is contained in:
@ -12,6 +12,7 @@
|
|||||||
* [#8471](https://github.com/netbox-community/netbox/issues/8471) - Add `status` field to Cluster
|
* [#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
|
* [#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
|
* [#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
|
### Other Changes
|
||||||
|
|
||||||
@ -20,7 +21,7 @@
|
|||||||
### REST API Changes
|
### REST API Changes
|
||||||
|
|
||||||
* extras.CustomField
|
* extras.CustomField
|
||||||
* Added `group_name` field
|
* Added `group_name` and `ui_visibility` fields
|
||||||
* ipam.IPAddress
|
* ipam.IPAddress
|
||||||
* The `nat_inside` field no longer requires a unique value
|
* 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
|
* The `nat_outside` field has changed from a single IP address instance to a list of multiple IP addresses
|
||||||
|
@ -90,8 +90,8 @@ class CustomFieldSerializer(ValidatedModelSerializer):
|
|||||||
model = CustomField
|
model = CustomField
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'url', 'display', 'content_types', 'type', 'object_type', 'data_type', 'name', 'label', 'group_name',
|
'id', 'url', 'display', 'content_types', 'type', 'object_type', 'data_type', 'name', 'label', 'group_name',
|
||||||
'description', 'required', 'filter_logic', 'default', 'weight', 'validation_minimum', 'validation_maximum',
|
'description', 'required', 'filter_logic', 'ui_visibility', 'default', 'weight', 'validation_minimum',
|
||||||
'validation_regex', 'choices', 'created', 'last_updated', 'ui_visibility',
|
'validation_maximum', 'validation_regex', 'choices', 'created', 'last_updated',
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_data_type(self, obj):
|
def get_data_type(self, obj):
|
||||||
|
@ -63,7 +63,8 @@ class CustomFieldFilterSet(BaseFilterSet):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = CustomField
|
model = CustomField
|
||||||
fields = [
|
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):
|
def search(self, queryset, name, value):
|
||||||
|
@ -37,7 +37,8 @@ class CustomFieldCSVForm(CSVModelForm):
|
|||||||
model = CustomField
|
model = CustomField
|
||||||
fields = (
|
fields = (
|
||||||
'name', 'label', 'group_name', 'type', 'content_types', 'required', 'description', 'weight', 'filter_logic',
|
'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',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,6 +51,10 @@ class CustomFieldsMixin:
|
|||||||
|
|
||||||
if customfield.ui_visibility == CustomFieldVisibilityChoices.VISIBILITY_READ_ONLY:
|
if customfield.ui_visibility == CustomFieldVisibilityChoices.VISIBILITY_READ_ONLY:
|
||||||
self.fields[field_name].disabled = True
|
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
|
# Annotate the field in the list of CustomField form fields
|
||||||
self.custom_fields[field_name] = customfield
|
self.custom_fields[field_name] = customfield
|
||||||
|
@ -59,7 +59,7 @@ class CustomFieldFilterForm(FilterForm):
|
|||||||
ui_visibility = forms.ChoiceField(
|
ui_visibility = forms.ChoiceField(
|
||||||
choices=add_blank_choice(CustomFieldVisibilityChoices),
|
choices=add_blank_choice(CustomFieldVisibilityChoices),
|
||||||
required=False,
|
required=False,
|
||||||
label=_('UI Visibility'),
|
label=_('UI visibility'),
|
||||||
widget=StaticSelect()
|
widget=StaticSelect()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -41,9 +41,9 @@ class CustomFieldForm(BootstrapMixin, forms.ModelForm):
|
|||||||
|
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
('Custom Field', (
|
('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')),
|
('Values', ('default', 'choices')),
|
||||||
('Validation', ('validation_minimum', 'validation_maximum', 'validation_regex')),
|
('Validation', ('validation_minimum', 'validation_maximum', 'validation_regex')),
|
||||||
)
|
)
|
||||||
|
@ -140,7 +140,8 @@ class CustomField(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel):
|
|||||||
max_length=50,
|
max_length=50,
|
||||||
choices=CustomFieldVisibilityChoices,
|
choices=CustomFieldVisibilityChoices,
|
||||||
default=CustomFieldVisibilityChoices.VISIBILITY_READ_WRITE,
|
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()
|
objects = CustomFieldManager()
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ class CustomFieldTable(NetBoxTable):
|
|||||||
model = CustomField
|
model = CustomField
|
||||||
fields = (
|
fields = (
|
||||||
'pk', 'id', 'name', 'content_types', 'label', 'type', 'group_name', 'required', 'weight', 'default',
|
'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')
|
default_columns = ('pk', 'name', 'content_types', 'label', 'group_name', 'type', 'required', 'description')
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ class CustomFieldsMixin(models.Model):
|
|||||||
|
|
||||||
def get_custom_fields_by_group(self):
|
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)
|
grouped_custom_fields = defaultdict(dict)
|
||||||
for cf, value in self.get_custom_fields(omit_hidden=True).items():
|
for cf, value in self.get_custom_fields(omit_hidden=True).items():
|
||||||
|
@ -42,6 +42,10 @@
|
|||||||
<th scope="row">Weight</th>
|
<th scope="row">Weight</th>
|
||||||
<td>{{ object.weight }}</td>
|
<td>{{ object.weight }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Filter Logic</th>
|
||||||
|
<td>{{ object.get_filter_logic_display }}</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">UI Visibility</th>
|
<th scope="row">UI Visibility</th>
|
||||||
<td>{{ object.get_ui_visibility_display }}</td>
|
<td>{{ object.get_ui_visibility_display }}</td>
|
||||||
@ -69,10 +73,6 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<th scope="row">Filter Logic</th>
|
|
||||||
<td>{{ object.get_filter_logic_display }}</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Reference in New Issue
Block a user