diff --git a/netbox_lifecycle/template_content.py b/netbox_lifecycle/template_content.py
new file mode 100644
index 0000000..44837c7
--- /dev/null
+++ b/netbox_lifecycle/template_content.py
@@ -0,0 +1,76 @@
+
+from django.contrib.contenttypes.models import ContentType
+from django.template import Template
+from netbox.plugins import PluginTemplateExtension
+
+from .models import hardware, contract
+
+
+class DeviceHardwareInfoExtension(PluginTemplateExtension):
+ def right_page(self):
+ object = self.context.get('object')
+ support_contract = contract.SupportContractAssignment.objects.filter(device_id=self.context['object'].id).first()
+ match self.kind:
+ case "device":
+ content_type = ContentType.objects.get(app_label="dcim", model="devicetype")
+ lifecycle_info = hardware.HardwareLifecycle.objects.filter(assigned_object_id=self.context['object'].device_type_id,
+ assigned_object_type_id=content_type.id).first()
+ case "module":
+ content_type = ContentType.objects.get(app_label="dcim", model="moduletype")
+ lifecycle_info = hardware.HardwareLifecycle.objects.filter(assigned_object_id=self.context['object'].module_type_id,
+ assigned_object_type_id=content_type.id).first()
+ case "devicetype" | "moduletype":
+ content_type = ContentType.objects.get(app_label="dcim", model=self.kind)
+ lifecycle_info = hardware.HardwareLifecycle.objects.filter(assigned_object_id=self.context['object'].id,
+ assigned_object_type_id=content_type.id).first()
+ context = {'support_contract': support_contract, 'lifecycle_info': lifecycle_info}
+ return self.render('netbox_lifecycle/inc/support_contract_info.html', extra_context=context)
+
+
+class TypeInfoExtension(PluginTemplateExtension):
+ def right_page(self):
+ object = self.context.get('object')
+ match self.kind:
+ case "device":
+ content_type = ContentType.objects.get(app_label="dcim", model="devicetype")
+ lifecycle_info = hardware.HardwareLifecycle.objects.filter(assigned_object_id=self.context['object'].device_type_id,
+ assigned_object_type_id=content_type.id).first()
+ case "module":
+ content_type = ContentType.objects.get(app_label="dcim", model="moduletype")
+ lifecycle_info = hardware.HardwareLifecycle.objects.filter(assigned_object_id=self.context['object'].module_type_id,
+ assigned_object_type_id=content_type.id).first()
+ case "devicetype" | "moduletype":
+ content_type = ContentType.objects.get(app_label="dcim", model=self.kind)
+ lifecycle_info = hardware.HardwareLifecycle.objects.filter(assigned_object_id=self.context['object'].id,
+ assigned_object_type_id=content_type.id).first()
+
+ context = {'lifecycle_info': lifecycle_info}
+ return self.render('netbox_lifecycle/inc/hardware_lifecycle_info.html', extra_context=context)
+
+
+class DeviceHardwareLifecycleInfo(DeviceHardwareInfoExtension):
+ model = 'dcim.device'
+ kind = 'device'
+
+
+class ModuleHardwareLifecycleInfo(TypeInfoExtension):
+ model = 'dcim.module'
+ kind = 'module'
+
+
+class DeviceTypeHardwareLifecycleInfo(TypeInfoExtension):
+ model = 'dcim.devicetype'
+ kind = 'devicetype'
+
+
+class ModuleTypeHardwareLifecycleInfo(TypeInfoExtension):
+ model = 'dcim.moduletype'
+ kind = 'moduletype'
+
+
+template_extensions = (
+ DeviceHardwareLifecycleInfo,
+ ModuleHardwareLifecycleInfo,
+ DeviceTypeHardwareLifecycleInfo,
+ ModuleTypeHardwareLifecycleInfo,
+)
diff --git a/netbox_lifecycle/templates/netbox_lifecycle/hardwarelifecycle.html b/netbox_lifecycle/templates/netbox_lifecycle/hardwarelifecycle.html
index 862fd84..197ea46 100644
--- a/netbox_lifecycle/templates/netbox_lifecycle/hardwarelifecycle.html
+++ b/netbox_lifecycle/templates/netbox_lifecycle/hardwarelifecycle.html
@@ -2,6 +2,7 @@
{% load buttons %}
{% load custom_links %}
{% load helpers %}
+{% load filters %}
{% load perms %}
{% load plugins %}
{% load tabs %}
@@ -34,23 +35,23 @@
End of Sale |
- {{ object.end_of_sale }} |
+ {{ object.end_of_sale }} |
End of Maintenance Updates |
- {{ object.end_of_maintenance }} |
+ {{ object.end_of_maintenance }} |
End of Security Updates |
- {{ object.end_of_security }} |
+ {{ object.end_of_security }} |
Last Support Contract Purchase Date |
- {{ object.last_contract_date }} |
+ {{ object.last_contract_date }} |
End of Support |
- {{ object.end_of_support }} |
+ {{ object.end_of_support }} |
diff --git a/netbox_lifecycle/templates/netbox_lifecycle/inc/hardware_lifecycle_info.html b/netbox_lifecycle/templates/netbox_lifecycle/inc/hardware_lifecycle_info.html
new file mode 100644
index 0000000..a639d88
--- /dev/null
+++ b/netbox_lifecycle/templates/netbox_lifecycle/inc/hardware_lifecycle_info.html
@@ -0,0 +1,34 @@
+
+{% load filters %}
+{% load helpers %}
+{# renders panel on object with lifecycle info assigned to it #}
+
+
+
+ {% if lifecycle_info %}
+
+
+ End of Sale |
+ {{ lifecycle_info.end_of_sale }} |
+
+
+ End of Maintenance Updates |
+ {{ lifecycle_info.end_of_maintenance }} |
+
+
+ End of Security Updates |
+ {{ lifecycle_info.end_of_security }} |
+
+
+ Last Support Contract Purchase Date |
+ {{ lifecycle_info.last_contract_date }} |
+
+
+ End of Support |
+ {{ lifecycle_info.end_of_support }} |
+
+
+ {% else %}
+
No Lifecycle Dates Defined
+ {% endif %}
+
diff --git a/netbox_lifecycle/templates/netbox_lifecycle/inc/support_contract_info.html b/netbox_lifecycle/templates/netbox_lifecycle/inc/support_contract_info.html
new file mode 100644
index 0000000..3919229
--- /dev/null
+++ b/netbox_lifecycle/templates/netbox_lifecycle/inc/support_contract_info.html
@@ -0,0 +1,36 @@
+
+{% load filters %}
+{% load helpers %}
+{# renders panel on object (device) with support contract info assigned to it #}
+
+
+
+ {% if support_contract %}
+
+
+ Contract Number |
+ {{ support_contract.contract.contract_id|linkify|placeholder }} |
+
+
+ Support SKU |
+ {{ support_contract.sku }} |
+
+
+ Start Date |
+ {{ support_contract.contract.start }} |
+
+
+ End Date |
+ {% if support_contract.end == None %}
+ {{ support_contract.contract.end }} |
+ {% else %}
+ {{ support_contract.end }} |
+ {% endif %}
+
+
+ {% else %}
+
No Support Contract Assigned
+ {% endif %}
+
+
+{% include "netbox_lifecycle/inc/hardware_lifecycle_info.html" %}
diff --git a/netbox_lifecycle/templatetags/__init__.py b/netbox_lifecycle/templatetags/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/netbox_lifecycle/templatetags/filters.py b/netbox_lifecycle/templatetags/filters.py
new file mode 100644
index 0000000..7efb587
--- /dev/null
+++ b/netbox_lifecycle/templatetags/filters.py
@@ -0,0 +1,27 @@
+from datetime import datetime, date
+from dateutil.relativedelta import relativedelta
+from django import template
+from django.utils.safestring import mark_safe
+
+register = template.Library()
+
+
+def is_expired(value):
+ return value < datetime.now().date()
+
+
+def expires_within_six_months(value):
+ return value < (date.today() + relativedelta(months=+6))
+
+
+@register.filter(is_safe=True)
+def date_badge_class(value):
+ if not value:
+ return
+
+ if is_expired(value):
+ return mark_safe('class="badge text-bg-danger"')
+ elif expires_within_six_months(value):
+ return mark_safe('class="badge text-bg-warning"')
+ else:
+ return mark_safe('class="badge text-bg-success"')