Use embedded table to show assigned services under object view

This commit is contained in:
jeremystretch 2023-01-25 20:25:06 -05:00 committed by jeremystretch
parent 8f7c100e22
commit 0f6995e92a
7 changed files with 39 additions and 104 deletions

View File

@ -1807,10 +1807,7 @@ class DeviceView(generic.ObjectView):
else:
vc_members = []
services = Service.objects.restrict(request.user, 'view').filter(device=instance)
return {
'services': services,
'vc_members': vc_members,
'svg_extra': f'highlight=id:{instance.pk}'
}

View File

@ -716,28 +716,10 @@ class IPAddressView(generic.ObjectView):
related_ips_table = tables.IPAddressTable(related_ips, orderable=False)
related_ips_table.configure(request)
# Find services belonging to the IP
service_filter = Q(ipaddresses=instance)
# Find services listening on all IPs on the assigned device/vm
try:
if instance.assigned_object and instance.assigned_object.parent_object:
parent_object = instance.assigned_object.parent_object
if isinstance(parent_object, VirtualMachine):
service_filter |= (Q(virtual_machine=parent_object) & Q(ipaddresses=None))
elif isinstance(parent_object, Device):
service_filter |= (Q(device=parent_object) & Q(ipaddresses=None))
except AttributeError:
pass
services = Service.objects.restrict(request.user, 'view').filter(service_filter)
return {
'parent_prefixes_table': parent_prefixes_table,
'duplicate_ips_table': duplicate_ips_table,
'related_ips_table': related_ips_table,
'services': services,
}

View File

@ -282,7 +282,20 @@
</div>
</div>
{% endif %}
{% include 'inc/panels/services.html' %}
<div class="card">
<h5 class="card-header">Services</h5>
<div class="card-body htmx-container table-responsive"
hx-get="{% url 'ipam:service_list' %}?device_id={{ object.pk }}"
hx-trigger="load"
></div>
{% if perms.ipam.add_service %}
<div class="card-footer text-end noprint">
<a href="{% url 'ipam:service_add' %}?device={{ object.pk }}" class="btn btn-sm btn-primary">
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add a service
</a>
</div>
{% endif %}
</div>
{% include 'inc/panels/contacts.html' %}
{% include 'inc/panels/image_attachments.html' %}
{% if object.rack and object.position %}

View File

@ -1,50 +0,0 @@
<div class="card">
<h5 class="card-header">Services</h5>
<div class="card-body">
{% if services %}
<table class="table table-hover">
{% for service in services %}
<tr>
<td>{{ service|linkify:"name" }}</td>
<td>{{ service.get_protocol_display }}</td>
<td>{{ service.port_list }}</td>
<td>
{% for ip in service.ipaddresses.all %}
<a href="{{ ip.get_absolute_url }}">{{ ip.address.ip }}</a><br />
{% empty %}
<span class="text-muted">All IPs</span>
{% endfor %}
</td>
<td>{{ service.description }}</td>
<td class="text-end noprint">
<a href="{% url 'ipam:service_changelog' pk=service.pk %}" class="btn btn-sm btn-outline-secondary" title="Change Log">
<i class="mdi mdi-history"></i>
</a>
{% if perms.ipam.change_service %}
<a href="{% url 'ipam:service_edit' pk=service.pk %}?return_url={{ service.parent.get_absolute_url }}" class="btn btn-warning btn-sm" title="Edit Service">
<i class="mdi mdi-pencil"></i>
</a>
{% endif %}
{% if perms.ipam.delete_service %}
<a href="{% url 'ipam:service_delete' pk=service.pk %}?return_url={{ service.parent.get_absolute_url }}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" title="Delete Service"></i>
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% else %}
<div class="text-muted">None</div>
{% endif %}
</div>
{% if perms.ipam.add_service %}
{% with object|meta:"model_name" as object_type %}
<div class="card-footer text-end noprint">
<a href="{% url 'ipam:service_add' %}{% if object_type == "device" %}?device={{ object.pk }}{% elif object_type == "virtualmachine" %}?virtual_machine={{ object.pk }}{% endif %}" class="btn btn-sm btn-primary">
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add Service
</a>
</div>
{% endwith %}
{% endif %}
</div>

View File

@ -117,11 +117,16 @@
{% include 'inc/panel_table.html' with table=duplicate_ips_table heading='Duplicate IPs' panel_class='danger' %}
{% endif %}
{% include 'inc/panel_table.html' with table=related_ips_table heading='Related IPs' %}
{% include 'inc/panels/services.html' %}
<div class="card">
<h5 class="card-header">Services</h5>
<div class="card-body htmx-container table-responsive"
hx-get="{% url 'ipam:service_list' %}?ipaddress_id={{ object.pk }}"
hx-trigger="load"
></div>
</div>
{% plugin_right_page object %}
</div>
</div>
<div class="row">
<div class="col col-md-12">
{% plugin_full_width_page object %}

View File

@ -144,7 +144,20 @@
</table>
</div>
</div>
{% include 'inc/panels/services.html' %}
<div class="card">
<h5 class="card-header">Services</h5>
<div class="card-body htmx-container table-responsive"
hx-get="{% url 'ipam:service_list' %}?virtual_machine_id={{ object.pk }}"
hx-trigger="load"
></div>
{% if perms.ipam.add_service %}
<div class="card-footer text-end noprint">
<a href="{% url 'ipam:service_add' %}?virtual_machine={{ object.pk }}" class="btn btn-sm btn-primary">
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add a service
</a>
</div>
{% endif %}
</div>
{% include 'inc/panels/contacts.html' %}
{% plugin_right_page object %}
</div>

View File

@ -327,32 +327,7 @@ class VirtualMachineListView(generic.ObjectListView):
@register_model_view(VirtualMachine)
class VirtualMachineView(generic.ObjectView):
queryset = VirtualMachine.objects.prefetch_related('tenant__group')
def get_extra_context(self, request, instance):
# Interfaces
vminterfaces = VMInterface.objects.restrict(request.user, 'view').filter(
virtual_machine=instance
).prefetch_related(
Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user))
)
vminterface_table = tables.VirtualMachineVMInterfaceTable(vminterfaces, user=request.user, orderable=False)
if request.user.has_perm('virtualization.change_vminterface') or \
request.user.has_perm('virtualization.delete_vminterface'):
vminterface_table.columns.show('pk')
# Services
services = Service.objects.restrict(request.user, 'view').filter(
virtual_machine=instance
).prefetch_related(
Prefetch('ipaddresses', queryset=IPAddress.objects.restrict(request.user)),
'virtual_machine'
)
return {
'vminterface_table': vminterface_table,
'services': services,
}
queryset = VirtualMachine.objects.all()
@register_model_view(VirtualMachine, 'interfaces')