mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Fixes #7153: Allow clearing of assigned device type images
This commit is contained in:
@ -1,8 +1,10 @@
|
|||||||
# NetBox v3.0
|
# NetBox v3.0
|
||||||
|
|
||||||
## v3.0.2 (FUTURE)
|
## v3.0.2 (FUTURE)
|
||||||
|
|
||||||
* [#7131](https://github.com/netbox-community/netbox/issues/7131) - Fix issue where Site fields were hidden when editing a VLAN group
|
* [#7131](https://github.com/netbox-community/netbox/issues/7131) - Fix issue where Site fields were hidden when editing a VLAN group
|
||||||
* [#7148](https://github.com/netbox-community/netbox/issues/7148) - Fix issue where static query parameters with multiple values were not queried properly
|
* [#7148](https://github.com/netbox-community/netbox/issues/7148) - Fix issue where static query parameters with multiple values were not queried properly
|
||||||
|
* [#7153](https://github.com/netbox-community/netbox/issues/7153) - Allow clearing of assigned device type images
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -23,10 +23,10 @@ from tenancy.forms import TenancyFilterForm, TenancyForm
|
|||||||
from tenancy.models import Tenant
|
from tenancy.models import Tenant
|
||||||
from utilities.forms import (
|
from utilities.forms import (
|
||||||
APISelect, APISelectMultiple, add_blank_choice, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect,
|
APISelect, APISelectMultiple, add_blank_choice, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect,
|
||||||
ColorField, CommentField, CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, CSVTypedChoiceField,
|
ClearableFileInput, ColorField, CommentField, CSVChoiceField, CSVContentTypeField, CSVModelChoiceField,
|
||||||
DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableNameField, form_from_model, JSONField,
|
CSVTypedChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableNameField, form_from_model,
|
||||||
NumericArrayField, SelectWithPK, SmallTextarea, SlugField, StaticSelect, StaticSelectMultiple, TagFilterField,
|
JSONField, NumericArrayField, SelectWithPK, SmallTextarea, SlugField, StaticSelect, StaticSelectMultiple,
|
||||||
BOOLEAN_WITH_BLANK_CHOICES,
|
TagFilterField, BOOLEAN_WITH_BLANK_CHOICES,
|
||||||
)
|
)
|
||||||
from virtualization.models import Cluster, ClusterGroup
|
from virtualization.models import Cluster, ClusterGroup
|
||||||
from .choices import *
|
from .choices import *
|
||||||
@ -1271,10 +1271,10 @@ class DeviceTypeForm(BootstrapMixin, CustomFieldModelForm):
|
|||||||
)
|
)
|
||||||
widgets = {
|
widgets = {
|
||||||
'subdevice_role': StaticSelect(),
|
'subdevice_role': StaticSelect(),
|
||||||
'front_image': forms.ClearableFileInput(attrs={
|
'front_image': ClearableFileInput(attrs={
|
||||||
'accept': DEVICETYPE_IMAGE_FORMATS
|
'accept': DEVICETYPE_IMAGE_FORMATS
|
||||||
}),
|
}),
|
||||||
'rear_image': forms.ClearableFileInput(attrs={
|
'rear_image': ClearableFileInput(attrs={
|
||||||
'accept': DEVICETYPE_IMAGE_FORMATS
|
'accept': DEVICETYPE_IMAGE_FORMATS
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -86,18 +86,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% elif field|widget_type == 'fileinput' or field|widget_type == 'clearablefileinput' %}
|
{% elif field|widget_type == 'fileinput' %}
|
||||||
<div class="input-group mb-3">
|
<div class="input-group mb-3">
|
||||||
<input
|
<input
|
||||||
class="form-control"
|
class="form-control"
|
||||||
type="file"
|
type="file"
|
||||||
name="{{ field.name }}"
|
name="{{ field.name }}"
|
||||||
placeholder="{{ field.placeholder }}"
|
placeholder="{{ field.placeholder }}"
|
||||||
id="id_{{ field.name }}"
|
id="id_{{ field.name }}"
|
||||||
accept="{{ field.field.widget.attrs.accept }}"
|
accept="{{ field.field.widget.attrs.accept }}"
|
||||||
{% if field.is_required %}required{% endif %}
|
{% if field.is_required %}required{% endif %}
|
||||||
/>
|
/>
|
||||||
<label for="{{ field.id_for_label }}" class="input-group-text">{{ field.label|bettertitle }}</label>
|
<label for="{{ field.id_for_label }}" class="input-group-text">{{ field.label|bettertitle }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% elif field|widget_type == 'clearablefileinput' %}
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="{{ field.id_for_label }}" class="form-label col col-md-3 text-lg-end{% if field.field.required %} required{% endif %}">
|
||||||
|
{{ field.label }}
|
||||||
|
</label>
|
||||||
|
<div class="col col-md-9">
|
||||||
|
{{ field }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% elif field|widget_type == 'selectmultiple' %}
|
{% elif field|widget_type == 'selectmultiple' %}
|
||||||
|
@ -4,7 +4,7 @@ import re
|
|||||||
import yaml
|
import yaml
|
||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
from .widgets import APISelect, APISelectMultiple, StaticSelect
|
from .widgets import APISelect, APISelectMultiple, ClearableFileInput, StaticSelect
|
||||||
|
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
@ -29,12 +29,12 @@ class BootstrapMixin(forms.BaseForm):
|
|||||||
|
|
||||||
exempt_widgets = [
|
exempt_widgets = [
|
||||||
forms.CheckboxInput,
|
forms.CheckboxInput,
|
||||||
forms.ClearableFileInput,
|
|
||||||
forms.FileInput,
|
forms.FileInput,
|
||||||
forms.RadioSelect,
|
forms.RadioSelect,
|
||||||
forms.Select,
|
forms.Select,
|
||||||
APISelect,
|
APISelect,
|
||||||
APISelectMultiple,
|
APISelectMultiple,
|
||||||
|
ClearableFileInput,
|
||||||
StaticSelect,
|
StaticSelect,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ __all__ = (
|
|||||||
'APISelect',
|
'APISelect',
|
||||||
'APISelectMultiple',
|
'APISelectMultiple',
|
||||||
'BulkEditNullBooleanSelect',
|
'BulkEditNullBooleanSelect',
|
||||||
|
'ClearableFileInput',
|
||||||
'ColorSelect',
|
'ColorSelect',
|
||||||
'ContentTypeSelect',
|
'ContentTypeSelect',
|
||||||
'DatePicker',
|
'DatePicker',
|
||||||
@ -135,6 +136,13 @@ class NumericArrayField(SimpleArrayField):
|
|||||||
return super().to_python(value)
|
return super().to_python(value)
|
||||||
|
|
||||||
|
|
||||||
|
class ClearableFileInput(forms.ClearableFileInput):
|
||||||
|
"""
|
||||||
|
Override Django's stock ClearableFileInput with a custom template.
|
||||||
|
"""
|
||||||
|
template_name = 'widgets/clearable_file_input.html'
|
||||||
|
|
||||||
|
|
||||||
class APISelect(SelectWithDisabled):
|
class APISelect(SelectWithDisabled):
|
||||||
"""
|
"""
|
||||||
A select widget populated via an API call
|
A select widget populated via an API call
|
||||||
|
24
netbox/utilities/templates/widgets/clearable_file_input.html
Normal file
24
netbox/utilities/templates/widgets/clearable_file_input.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
{% if widget.is_initial %}
|
||||||
|
<a href="{{ widget.value.url }}">{{ widget.value }}</a>
|
||||||
|
{% if not widget.required %}
|
||||||
|
<br />
|
||||||
|
<input type="checkbox" name="{{ widget.checkbox_name }}" id="{{ widget.checkbox_id }}"{% if widget.attrs.disabled %} disabled{% endif %}>
|
||||||
|
<label for="{{ widget.checkbox_id }}">{{ widget.clear_checkbox_label }}</label>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<span class="text-muted">None assigned</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<input
|
||||||
|
class="form-control"
|
||||||
|
type="{{ widget.type }}"
|
||||||
|
name="{{ widget.name }}"
|
||||||
|
id="id_{{ widget.name }}"
|
||||||
|
accept="{{ widget.attrs.accept }}"
|
||||||
|
{% if widget.required %}required{% endif %}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
Reference in New Issue
Block a user