1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Enable the association of inventory item templates with component templates

This commit is contained in:
jeremystretch
2021-12-29 16:30:44 -05:00
parent 4c15f4a84f
commit 791cc093f4
6 changed files with 40 additions and 27 deletions

View File

@ -1092,7 +1092,7 @@ class InventoryItemTemplateForm(BootstrapMixin, forms.ModelForm):
) )
component_type = ContentTypeChoiceField( component_type = ContentTypeChoiceField(
queryset=ContentType.objects.all(), queryset=ContentType.objects.all(),
limit_choices_to=MODULAR_COMPONENT_MODELS, limit_choices_to=MODULAR_COMPONENT_TEMPLATE_MODELS,
required=False, required=False,
widget=forms.HiddenInput widget=forms.HiddenInput
) )

View File

@ -8,6 +8,7 @@ from dcim.models import (
from utilities.tables import ( from utilities.tables import (
BaseTable, BooleanColumn, ButtonsColumn, ColorColumn, LinkedCountColumn, MarkdownColumn, TagColumn, ToggleColumn, BaseTable, BooleanColumn, ButtonsColumn, ColorColumn, LinkedCountColumn, MarkdownColumn, TagColumn, ToggleColumn,
) )
from .template_code import MODULAR_COMPONENT_TEMPLATE_BUTTONS
__all__ = ( __all__ = (
'ConsolePortTemplateTable', 'ConsolePortTemplateTable',
@ -114,7 +115,8 @@ class ComponentTemplateTable(BaseTable):
class ConsolePortTemplateTable(ComponentTemplateTable): class ConsolePortTemplateTable(ComponentTemplateTable):
actions = ButtonsColumn( actions = ButtonsColumn(
model=ConsolePortTemplate, model=ConsolePortTemplate,
buttons=('edit', 'delete') buttons=('edit', 'delete'),
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
) )
class Meta(ComponentTemplateTable.Meta): class Meta(ComponentTemplateTable.Meta):
@ -126,7 +128,8 @@ class ConsolePortTemplateTable(ComponentTemplateTable):
class ConsoleServerPortTemplateTable(ComponentTemplateTable): class ConsoleServerPortTemplateTable(ComponentTemplateTable):
actions = ButtonsColumn( actions = ButtonsColumn(
model=ConsoleServerPortTemplate, model=ConsoleServerPortTemplate,
buttons=('edit', 'delete') buttons=('edit', 'delete'),
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
) )
class Meta(ComponentTemplateTable.Meta): class Meta(ComponentTemplateTable.Meta):
@ -138,7 +141,8 @@ class ConsoleServerPortTemplateTable(ComponentTemplateTable):
class PowerPortTemplateTable(ComponentTemplateTable): class PowerPortTemplateTable(ComponentTemplateTable):
actions = ButtonsColumn( actions = ButtonsColumn(
model=PowerPortTemplate, model=PowerPortTemplate,
buttons=('edit', 'delete') buttons=('edit', 'delete'),
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
) )
class Meta(ComponentTemplateTable.Meta): class Meta(ComponentTemplateTable.Meta):
@ -150,7 +154,8 @@ class PowerPortTemplateTable(ComponentTemplateTable):
class PowerOutletTemplateTable(ComponentTemplateTable): class PowerOutletTemplateTable(ComponentTemplateTable):
actions = ButtonsColumn( actions = ButtonsColumn(
model=PowerOutletTemplate, model=PowerOutletTemplate,
buttons=('edit', 'delete') buttons=('edit', 'delete'),
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
) )
class Meta(ComponentTemplateTable.Meta): class Meta(ComponentTemplateTable.Meta):
@ -165,7 +170,8 @@ class InterfaceTemplateTable(ComponentTemplateTable):
) )
actions = ButtonsColumn( actions = ButtonsColumn(
model=InterfaceTemplate, model=InterfaceTemplate,
buttons=('edit', 'delete') buttons=('edit', 'delete'),
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
) )
class Meta(ComponentTemplateTable.Meta): class Meta(ComponentTemplateTable.Meta):
@ -181,7 +187,8 @@ class FrontPortTemplateTable(ComponentTemplateTable):
color = ColorColumn() color = ColorColumn()
actions = ButtonsColumn( actions = ButtonsColumn(
model=FrontPortTemplate, model=FrontPortTemplate,
buttons=('edit', 'delete') buttons=('edit', 'delete'),
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
) )
class Meta(ComponentTemplateTable.Meta): class Meta(ComponentTemplateTable.Meta):
@ -194,7 +201,8 @@ class RearPortTemplateTable(ComponentTemplateTable):
color = ColorColumn() color = ColorColumn()
actions = ButtonsColumn( actions = ButtonsColumn(
model=RearPortTemplate, model=RearPortTemplate,
buttons=('edit', 'delete') buttons=('edit', 'delete'),
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
) )
class Meta(ComponentTemplateTable.Meta): class Meta(ComponentTemplateTable.Meta):

View File

@ -93,6 +93,19 @@ LOCATION_ELEVATIONS = """
</a> </a>
""" """
#
# Device component templatebuttons
#
MODULAR_COMPONENT_TEMPLATE_BUTTONS = """
{% load helpers %}
{% if perms.dcim.add_invnetoryitemtemplate %}
<a href="{% url 'dcim:inventoryitemtemplate_add' %}?device_type={{ record.device_type.pk }}&component_type={{ record|content_type_id }}&component_id={{ record.pk }}&return_url={{ request.path }}" title="Add inventory item" class="btn btn-primary btn-sm">
<i class="mdi mdi-plus-thick" aria-hidden="true"></i>
</a>
{% endif %}
"""
# #
# Device component buttons # Device component buttons
# #

View File

@ -1379,6 +1379,7 @@ class InventoryItemTemplateCreateView(generic.ComponentCreateView):
queryset = InventoryItemTemplate.objects.all() queryset = InventoryItemTemplate.objects.all()
form = forms.DeviceTypeComponentCreateForm form = forms.DeviceTypeComponentCreateForm
model_form = forms.InventoryItemTemplateForm model_form = forms.InventoryItemTemplateForm
template_name = 'dcim/inventoryitem_create.html'
def alter_object(self, instance, request): def alter_object(self, instance, request):
# Set component (if any) # Set component (if any)

View File

@ -737,6 +737,7 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
'return_url': self.get_return_url(request), 'return_url': self.get_return_url(request),
}) })
# TODO: Refactor this method for clarity & better error reporting
def validate_form(self, request, form): def validate_form(self, request, form):
""" """
Validate form values and set errors on the form object as they are detected. If Validate form values and set errors on the form object as they are detected. If
@ -763,17 +764,7 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
if component_form.is_valid(): if component_form.is_valid():
new_components.append(component_form) new_components.append(component_form)
else: if not form.errors and not component_form.errors:
for field, errors in component_form.errors.as_data().items():
# Assign errors on the child form's name/label field to name_pattern/label_pattern on the parent form
if field == 'name':
field = 'name_pattern'
elif field == 'label':
field = 'label_pattern'
for e in errors:
form.add_error(field, '{}: {}'.format(name, ', '.join(e)))
if not form.errors:
try: try:
with transaction.atomic(): with transaction.atomic():
# Create the new components # Create the new components

View File

@ -1,17 +1,17 @@
{% extends 'dcim/component_create.html' %} {% extends 'generic/object_edit.html' %}
{% load helpers %} {% load helpers %}
{% load form_helpers %}
{% block form %} {% block form %}
{% render_form replication_form %}
{% if obj.component %} {% if obj.component %}
<div class="row mb-3"> <div class="row mb-3">
<label class="col-sm-3 col-form-label text-lg-end required"> <label class="col-sm-3 col-form-label text-lg-end">
{{ obj.component|meta:"verbose_name"|bettertitle }} {{ obj.component|meta:"verbose_name"|bettertitle }}
</label> </label>
<div class="col-sm-9"> <div class="col">
<div class="form-control-plaintext"> <input class="form-control" value="{{ obj.component }}" disabled />
<a href="{{ obj.component.get_absolute_url }}" class="">{{ obj.component }}</a>
</div> </div>
</div>
</div> </div>
{% endif %} {% endif %}
{{ block.super }} {{ block.super }}