Implement list filtering forms (#57)
Closes #54 Signed-off-by: wkoot <3715211+wkoot@users.noreply.github.com>
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
* Toggle to show plugin as top level menu item (#42)
|
* Toggle to show plugin as top level menu item (#42)
|
||||||
* Bulk import except `LaxURLFields` (#4)
|
* Bulk import except `LaxURLFields` (#4)
|
||||||
* Changelog with backdated changes (#51)
|
* Changelog with backdated changes (#51)
|
||||||
|
* List filtering (#54)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ class SoftwareProductSerializer(NetBoxModelSerializer):
|
|||||||
brief_fields = ("id", "display", "url", "name", "description")
|
brief_fields = ("id", "display", "url", "name", "description")
|
||||||
|
|
||||||
def get_display(self, obj):
|
def get_display(self, obj):
|
||||||
|
# TODO - does not match form and filter views, display manufacturer separately?
|
||||||
return f"{obj.manufacturer} - {obj}"
|
return f"{obj.manufacturer} - {obj}"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,22 @@
|
|||||||
|
from django_filters import CharFilter, ModelMultipleChoiceFilter, MultipleChoiceFilter
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
||||||
|
from dcim.models import Device, Manufacturer
|
||||||
from netbox.filtersets import NetBoxModelFilterSet
|
from netbox.filtersets import NetBoxModelFilterSet
|
||||||
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation, SoftwareLicense
|
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation, SoftwareLicense, SoftwareReleaseTypes
|
||||||
|
from virtualization.models import VirtualMachine, Cluster
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductFilterSet(NetBoxModelFilterSet):
|
class SoftwareProductFilterSet(NetBoxModelFilterSet):
|
||||||
"""Filter capabilities for SoftwareProduct instances."""
|
"""Filter capabilities for SoftwareProduct instances."""
|
||||||
|
|
||||||
|
name = CharFilter(lookup_expr="icontains")
|
||||||
|
description = CharFilter(lookup_expr="icontains")
|
||||||
|
|
||||||
|
manufacturer = ModelMultipleChoiceFilter(
|
||||||
|
queryset=Manufacturer.objects.all()
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SoftwareProduct
|
model = SoftwareProduct
|
||||||
fields = tuple()
|
fields = tuple()
|
||||||
@@ -27,9 +37,24 @@ class SoftwareProductFilterSet(NetBoxModelFilterSet):
|
|||||||
class SoftwareProductVersionFilterSet(NetBoxModelFilterSet):
|
class SoftwareProductVersionFilterSet(NetBoxModelFilterSet):
|
||||||
"""Filter capabilities for SoftwareProductVersion instances."""
|
"""Filter capabilities for SoftwareProductVersion instances."""
|
||||||
|
|
||||||
|
name = CharFilter(lookup_expr="icontains")
|
||||||
|
filename = CharFilter(lookup_expr="icontains")
|
||||||
|
|
||||||
|
release_type = MultipleChoiceFilter(choices=SoftwareReleaseTypes.choices)
|
||||||
|
|
||||||
|
manufacturer = ModelMultipleChoiceFilter(
|
||||||
|
field_name="software_product__manufacturer",
|
||||||
|
queryset=Manufacturer.objects.all(),
|
||||||
|
)
|
||||||
|
|
||||||
|
software_product = ModelMultipleChoiceFilter(
|
||||||
|
queryset=SoftwareProduct.objects.all(),
|
||||||
|
label="Software Product",
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SoftwareProductVersion
|
model = SoftwareProductVersion
|
||||||
fields = ("software_product",)
|
fields = tuple()
|
||||||
|
|
||||||
def search(self, queryset, name, value):
|
def search(self, queryset, name, value):
|
||||||
"""Perform the filtered search."""
|
"""Perform the filtered search."""
|
||||||
@@ -47,9 +72,27 @@ class SoftwareProductVersionFilterSet(NetBoxModelFilterSet):
|
|||||||
class SoftwareProductInstallationFilterSet(NetBoxModelFilterSet):
|
class SoftwareProductInstallationFilterSet(NetBoxModelFilterSet):
|
||||||
"""Filter capabilities for SoftwareProductInstallation instances."""
|
"""Filter capabilities for SoftwareProductInstallation instances."""
|
||||||
|
|
||||||
|
device = ModelMultipleChoiceFilter(
|
||||||
|
queryset=Device.objects.all()
|
||||||
|
)
|
||||||
|
virtualmachine = ModelMultipleChoiceFilter(
|
||||||
|
queryset=VirtualMachine.objects.all(),
|
||||||
|
label="Virtual Machine",
|
||||||
|
)
|
||||||
|
cluster = ModelMultipleChoiceFilter(
|
||||||
|
queryset=Cluster.objects.all()
|
||||||
|
)
|
||||||
|
software_product = ModelMultipleChoiceFilter(
|
||||||
|
queryset=SoftwareProduct.objects.all(),
|
||||||
|
label="Software Product",
|
||||||
|
)
|
||||||
|
version = ModelMultipleChoiceFilter(
|
||||||
|
queryset=SoftwareProductVersion.objects.all()
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SoftwareProductInstallation
|
model = SoftwareProductInstallation
|
||||||
fields = ("software_product",)
|
fields = tuple()
|
||||||
|
|
||||||
def search(self, queryset, name, value):
|
def search(self, queryset, name, value):
|
||||||
"""Perform the filtered search."""
|
"""Perform the filtered search."""
|
||||||
@@ -67,9 +110,25 @@ class SoftwareProductInstallationFilterSet(NetBoxModelFilterSet):
|
|||||||
class SoftwareLicenseFilterSet(NetBoxModelFilterSet):
|
class SoftwareLicenseFilterSet(NetBoxModelFilterSet):
|
||||||
"""Filter capabilities for SoftwareLicense instances."""
|
"""Filter capabilities for SoftwareLicense instances."""
|
||||||
|
|
||||||
|
name = CharFilter(lookup_expr="icontains")
|
||||||
|
description = CharFilter(lookup_expr="icontains")
|
||||||
|
type = CharFilter(lookup_expr="icontains")
|
||||||
|
stored_location = CharFilter(lookup_expr="icontains")
|
||||||
|
|
||||||
|
software_product = ModelMultipleChoiceFilter(
|
||||||
|
queryset=SoftwareProduct.objects.all(),
|
||||||
|
label="Software Product",
|
||||||
|
)
|
||||||
|
version = ModelMultipleChoiceFilter(
|
||||||
|
queryset=SoftwareProductVersion.objects.all()
|
||||||
|
)
|
||||||
|
installation = ModelMultipleChoiceFilter(
|
||||||
|
queryset=SoftwareProductInstallation.objects.all()
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SoftwareLicense
|
model = SoftwareLicense
|
||||||
fields = tuple()
|
fields = ("support",)
|
||||||
|
|
||||||
def search(self, queryset, name, value):
|
def search(self, queryset, name, value):
|
||||||
"""Perform the filtered search."""
|
"""Perform the filtered search."""
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
from django.forms import DateField
|
from django.forms import CharField, DateField, ChoiceField
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
|
|
||||||
from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm, NetBoxModelImportForm
|
from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm, NetBoxModelImportForm
|
||||||
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation, SoftwareLicense
|
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation, SoftwareLicense
|
||||||
from utilities.forms.fields import CommentField, DynamicModelChoiceField, TagFilterField, LaxURLField
|
from utilities.forms.constants import BOOLEAN_WITH_BLANK_CHOICES
|
||||||
|
from utilities.forms.fields import CommentField, DynamicModelChoiceField, TagFilterField, LaxURLField, DynamicModelMultipleChoiceField
|
||||||
from utilities.forms.rendering import FieldSet
|
from utilities.forms.rendering import FieldSet
|
||||||
from utilities.forms.widgets import APISelect, DatePicker
|
from utilities.forms.widgets import APISelect, DatePicker
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ class SoftwareLicenseForm(NetBoxModelForm):
|
|||||||
software_product = DynamicModelChoiceField(
|
software_product = DynamicModelChoiceField(
|
||||||
queryset=SoftwareProduct.objects.all(),
|
queryset=SoftwareProduct.objects.all(),
|
||||||
required=True,
|
required=True,
|
||||||
|
label="Software Product",
|
||||||
widget=APISelect(attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproduct-list")}),
|
widget=APISelect(attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproduct-list")}),
|
||||||
)
|
)
|
||||||
version = DynamicModelChoiceField(
|
version = DynamicModelChoiceField(
|
||||||
@@ -63,9 +65,34 @@ class SoftwareLicenseForm(NetBoxModelForm):
|
|||||||
|
|
||||||
class SoftwareLicenseFilterForm(NetBoxModelFilterSetForm):
|
class SoftwareLicenseFilterForm(NetBoxModelFilterSetForm):
|
||||||
model = SoftwareLicense
|
model = SoftwareLicense
|
||||||
fieldsets = (FieldSet(None, ("q", "tag")),)
|
fieldsets = (
|
||||||
|
FieldSet("q", "filter_id", "tag"),
|
||||||
|
FieldSet("name", "description", "type", "stored_location", "support", "software_product", "version", "installation"),
|
||||||
|
)
|
||||||
|
selector_fields = ("q", "filter_id", "name")
|
||||||
|
|
||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
|
||||||
|
name = CharField(required=False)
|
||||||
|
description = CharField(required=False)
|
||||||
|
type = CharField(required=False)
|
||||||
|
stored_location = CharField(required=False)
|
||||||
|
support = ChoiceField(required=False, choices=BOOLEAN_WITH_BLANK_CHOICES)
|
||||||
|
|
||||||
|
software_product = DynamicModelMultipleChoiceField(
|
||||||
|
queryset=SoftwareProduct.objects.all(),
|
||||||
|
required=False,
|
||||||
|
label="Software Product",
|
||||||
|
)
|
||||||
|
version = DynamicModelMultipleChoiceField(
|
||||||
|
queryset=SoftwareProductVersion.objects.all(),
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
installation = DynamicModelMultipleChoiceField(
|
||||||
|
queryset=SoftwareProductInstallation.objects.all(),
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SoftwareLicenseBulkImportForm(NetBoxModelImportForm):
|
class SoftwareLicenseBulkImportForm(NetBoxModelImportForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
from django.forms import CharField
|
||||||
|
|
||||||
from dcim.models import Manufacturer
|
from dcim.models import Manufacturer
|
||||||
from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm, NetBoxModelImportForm
|
from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm, NetBoxModelImportForm
|
||||||
from netbox_slm.models import SoftwareProduct
|
from netbox_slm.models import SoftwareProduct
|
||||||
from utilities.forms.fields import CommentField, DynamicModelChoiceField, TagFilterField
|
from utilities.forms.fields import CommentField, DynamicModelChoiceField, TagFilterField, DynamicModelMultipleChoiceField
|
||||||
from utilities.forms.rendering import FieldSet
|
from utilities.forms.rendering import FieldSet
|
||||||
|
|
||||||
|
|
||||||
@@ -28,9 +30,21 @@ class SoftwareProductForm(NetBoxModelForm):
|
|||||||
|
|
||||||
class SoftwareProductFilterForm(NetBoxModelFilterSetForm):
|
class SoftwareProductFilterForm(NetBoxModelFilterSetForm):
|
||||||
model = SoftwareProduct
|
model = SoftwareProduct
|
||||||
fieldsets = (FieldSet(None, ("q", "tag")),)
|
fieldsets = (
|
||||||
|
FieldSet("q", "filter_id", "tag"),
|
||||||
|
FieldSet("name", "description", "manufacturer"),
|
||||||
|
)
|
||||||
|
selector_fields = ("q", "filter_id", "name")
|
||||||
|
|
||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
|
||||||
|
name = CharField(required=False)
|
||||||
|
description = CharField(required=False)
|
||||||
|
manufacturer = DynamicModelMultipleChoiceField(
|
||||||
|
queryset=Manufacturer.objects.all(),
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductBulkImportForm(NetBoxModelImportForm):
|
class SoftwareProductBulkImportForm(NetBoxModelImportForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from django.urls import reverse_lazy
|
|||||||
from dcim.models import Device
|
from dcim.models import Device
|
||||||
from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm, NetBoxModelImportForm
|
from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm, NetBoxModelImportForm
|
||||||
from netbox_slm.models import SoftwareProductInstallation, SoftwareProduct, SoftwareProductVersion
|
from netbox_slm.models import SoftwareProductInstallation, SoftwareProduct, SoftwareProductVersion
|
||||||
from utilities.forms.fields import CommentField, DynamicModelChoiceField, TagFilterField
|
from utilities.forms.fields import CommentField, DynamicModelChoiceField, TagFilterField, DynamicModelMultipleChoiceField
|
||||||
from utilities.forms.rendering import FieldSet
|
from utilities.forms.rendering import FieldSet
|
||||||
from utilities.forms.widgets import APISelect
|
from utilities.forms.widgets import APISelect
|
||||||
from virtualization.models import VirtualMachine, Cluster
|
from virtualization.models import VirtualMachine, Cluster
|
||||||
@@ -16,11 +16,16 @@ class SoftwareProductInstallationForm(NetBoxModelForm):
|
|||||||
comments = CommentField()
|
comments = CommentField()
|
||||||
|
|
||||||
device = DynamicModelChoiceField(queryset=Device.objects.all(), required=False)
|
device = DynamicModelChoiceField(queryset=Device.objects.all(), required=False)
|
||||||
virtualmachine = DynamicModelChoiceField(queryset=VirtualMachine.objects.all(), required=False)
|
virtualmachine = DynamicModelChoiceField(
|
||||||
|
queryset=VirtualMachine.objects.all(),
|
||||||
|
required=False,
|
||||||
|
label="Virtual Machine",
|
||||||
|
)
|
||||||
cluster = DynamicModelChoiceField(queryset=Cluster.objects.all(), required=False)
|
cluster = DynamicModelChoiceField(queryset=Cluster.objects.all(), required=False)
|
||||||
software_product = DynamicModelChoiceField(
|
software_product = DynamicModelChoiceField(
|
||||||
queryset=SoftwareProduct.objects.all(),
|
queryset=SoftwareProduct.objects.all(),
|
||||||
required=True,
|
required=True,
|
||||||
|
label="Software Product",
|
||||||
widget=APISelect(attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproduct-list")}),
|
widget=APISelect(attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproduct-list")}),
|
||||||
)
|
)
|
||||||
version = DynamicModelChoiceField(
|
version = DynamicModelChoiceField(
|
||||||
@@ -57,9 +62,37 @@ class SoftwareProductInstallationForm(NetBoxModelForm):
|
|||||||
|
|
||||||
class SoftwareProductInstallationFilterForm(NetBoxModelFilterSetForm):
|
class SoftwareProductInstallationFilterForm(NetBoxModelFilterSetForm):
|
||||||
model = SoftwareProductInstallation
|
model = SoftwareProductInstallation
|
||||||
fieldsets = (FieldSet(None, ("q", "tag")),)
|
fieldsets = (
|
||||||
|
FieldSet("q", "filter_id", "tag"),
|
||||||
|
FieldSet("device", "virtualmachine", "cluster", "software_product", "version"),
|
||||||
|
)
|
||||||
|
selector_fields = ("filter_id", "q")
|
||||||
|
|
||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
|
||||||
|
device = DynamicModelMultipleChoiceField(
|
||||||
|
queryset=Device.objects.all(),
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
virtualmachine = DynamicModelMultipleChoiceField(
|
||||||
|
queryset=VirtualMachine.objects.all(),
|
||||||
|
required=False,
|
||||||
|
label="Virtual Machine",
|
||||||
|
)
|
||||||
|
cluster = DynamicModelMultipleChoiceField(
|
||||||
|
queryset=Cluster.objects.all(),
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
software_product = DynamicModelMultipleChoiceField(
|
||||||
|
queryset=SoftwareProduct.objects.all(),
|
||||||
|
required=False,
|
||||||
|
label="Software Product",
|
||||||
|
)
|
||||||
|
version = DynamicModelMultipleChoiceField(
|
||||||
|
queryset=SoftwareProductVersion.objects.all(),
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductInstallationBulkImportForm(NetBoxModelImportForm):
|
class SoftwareProductInstallationBulkImportForm(NetBoxModelImportForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
from django.forms import DateField
|
from django.forms import DateField, CharField, MultipleChoiceField
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
|
|
||||||
|
from dcim.models import Manufacturer
|
||||||
from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm, NetBoxModelImportForm
|
from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm, NetBoxModelImportForm
|
||||||
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion
|
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareReleaseTypes
|
||||||
from utilities.forms.fields import CommentField, DynamicModelChoiceField, TagFilterField
|
from utilities.forms.fields import CommentField, DynamicModelChoiceField, TagFilterField, DynamicModelMultipleChoiceField
|
||||||
from utilities.forms.rendering import FieldSet
|
from utilities.forms.rendering import FieldSet
|
||||||
from utilities.forms.widgets import APISelect, DatePicker
|
from utilities.forms.widgets import APISelect, DatePicker
|
||||||
|
|
||||||
@@ -18,6 +19,8 @@ class SoftwareProductVersionForm(NetBoxModelForm):
|
|||||||
|
|
||||||
software_product = DynamicModelChoiceField(
|
software_product = DynamicModelChoiceField(
|
||||||
queryset=SoftwareProduct.objects.all(),
|
queryset=SoftwareProduct.objects.all(),
|
||||||
|
required=True,
|
||||||
|
label="Software Product",
|
||||||
widget=APISelect(attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproduct-list")}),
|
widget=APISelect(attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproduct-list")}),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -40,9 +43,29 @@ class SoftwareProductVersionForm(NetBoxModelForm):
|
|||||||
|
|
||||||
class SoftwareProductVersionFilterForm(NetBoxModelFilterSetForm):
|
class SoftwareProductVersionFilterForm(NetBoxModelFilterSetForm):
|
||||||
model = SoftwareProductVersion
|
model = SoftwareProductVersion
|
||||||
fieldsets = (FieldSet(None, ("q", "tag")),)
|
fieldsets = (
|
||||||
|
FieldSet("q", "filter_id", "tag"),
|
||||||
|
FieldSet("name", "filename", "release_type", "manufacturer", "software_product"),
|
||||||
|
)
|
||||||
|
selector_fields = ("q", "filter_id", "name")
|
||||||
|
|
||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
|
||||||
|
name = CharField(required=False)
|
||||||
|
filename = CharField(required=False)
|
||||||
|
|
||||||
|
release_type = MultipleChoiceField(required=False, choices=SoftwareReleaseTypes.choices)
|
||||||
|
|
||||||
|
manufacturer = DynamicModelMultipleChoiceField(
|
||||||
|
queryset=Manufacturer.objects.all(),
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
software_product = DynamicModelMultipleChoiceField(
|
||||||
|
queryset=SoftwareProduct.objects.all(),
|
||||||
|
required=False,
|
||||||
|
label="Software Product",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductVersionBulkImportForm(NetBoxModelImportForm):
|
class SoftwareProductVersionBulkImportForm(NetBoxModelImportForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ class SoftwareProductInstallationTable(NetBoxTable):
|
|||||||
return queryset_union.order_by(f"{'-' if is_descending else ''}render_type"), True
|
return queryset_union.order_by(f"{'-' if is_descending else ''}render_type"), True
|
||||||
|
|
||||||
def render_software_product(self, value, **kwargs):
|
def render_software_product(self, value, **kwargs):
|
||||||
|
# TODO - does not match form and filter views, display manufacturer separately?
|
||||||
return f"{kwargs['record'].software_product.manufacturer.name} - {value}"
|
return f"{kwargs['record'].software_product.manufacturer.name} - {value}"
|
||||||
|
|
||||||
|
|
||||||
@@ -190,6 +191,7 @@ class SoftwareLicenseTable(NetBoxTable):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def render_software_product(self, value, **kwargs):
|
def render_software_product(self, value, **kwargs):
|
||||||
|
# TODO - does not match form and filter views, display manufacturer separately?
|
||||||
return f"{kwargs['record'].software_product.manufacturer.name} - {value}"
|
return f"{kwargs['record'].software_product.manufacturer.name} - {value}"
|
||||||
|
|
||||||
def render_installation(self, **kwargs):
|
def render_installation(self, **kwargs):
|
||||||
|
|||||||
@@ -20,6 +20,18 @@
|
|||||||
<th scope="row">Description</th>
|
<th scope="row">Description</th>
|
||||||
<td>{{ object.description }}</td>
|
<td>{{ object.description }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Software Product</th>
|
||||||
|
<td>{{ object.software_product|linkify }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Version</th>
|
||||||
|
<td>{{ object.version|linkify }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Installation</th>
|
||||||
|
<td>{{ object.installation|linkify }}</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Type</th>
|
<th scope="row">Type</th>
|
||||||
<td>{{ object.type }}</td>
|
<td>{{ object.type }}</td>
|
||||||
@@ -40,14 +52,6 @@
|
|||||||
<th scope="row">Expiration date</th>
|
<th scope="row">Expiration date</th>
|
||||||
<td>{{ object.expiration_date }}</td>
|
<td>{{ object.expiration_date }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<th scope="row">Software Product</th>
|
|
||||||
<td>{{ object.software_product|linkify }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th scope="row">Version</th>
|
|
||||||
<td>{{ object.version|linkify }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Support</th>
|
<th scope="row">Support</th>
|
||||||
<td>{{ object.support }}</td>
|
<td>{{ object.support }}</td>
|
||||||
@@ -56,10 +60,6 @@
|
|||||||
<th scope="row">License amount</th>
|
<th scope="row">License amount</th>
|
||||||
<td>{{ object.license_amount }}</td>
|
<td>{{ object.license_amount }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<th scope="row">Installation</th>
|
|
||||||
<td>{{ object.installation|linkify }}</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{% include 'inc/panels/custom_fields.html' %}
|
{% include 'inc/panels/custom_fields.html' %}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% elif object.virtualmachine %}
|
{% elif object.virtualmachine %}
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Virtualmachine</th>
|
<th scope="row">Virtual Machine</th>
|
||||||
<td>{{ object.virtualmachine|linkify }}</td>
|
<td>{{ object.virtualmachine|linkify }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|||||||
@@ -16,14 +16,14 @@
|
|||||||
<th scope="row">Name</th>
|
<th scope="row">Name</th>
|
||||||
<td>{{ object.name }}</td>
|
<td>{{ object.name }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<th scope="row">Software Product</th>
|
|
||||||
<td>{{ object.software_product|linkify }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Manufacturer</th>
|
<th scope="row">Manufacturer</th>
|
||||||
<td>{{ object.software_product.manufacturer|linkify }}</td>
|
<td>{{ object.software_product.manufacturer|linkify }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Software Product</th>
|
||||||
|
<td>{{ object.software_product|linkify }}</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Release date</th>
|
<th scope="row">Release date</th>
|
||||||
<td>{{ object.release_date }}</td>
|
<td>{{ object.release_date }}</td>
|
||||||
|
|||||||
Reference in New Issue
Block a user