Closes #3485: Enable embedded graphs for devices

This commit is contained in:
Jeremy Stretch 2019-09-18 15:59:52 -04:00
parent a0545568cd
commit 51fb0b59ec
7 changed files with 30 additions and 10 deletions

View File

@ -6,6 +6,7 @@ v2.6.4 (FUTURE)
* [#3027](https://github.com/netbox-community/netbox/issues/3028) - Add `local_context_data` boolean filter for devices
* [#3318](https://github.com/netbox-community/netbox/issues/3318) - Increase length of platform name and slug to 100 characters
* [#3341](https://github.com/netbox-community/netbox/issues/3341) - Enable inline VLAN assignment while editing an interface
* [#3485](https://github.com/netbox-community/netbox/issues/3485) - Enable embedded graphs for devices
* [#3510](https://github.com/netbox-community/netbox/issues/3510) - Add minimum/maximum prefix length enforcement for `IPNetworkVar`
## Bug Fixes

View File

@ -35,7 +35,7 @@ class ProviderViewSet(CustomFieldModelViewSet):
filterset_class = filters.ProviderFilter
@action(detail=True)
def graphs(self, request, pk=None):
def graphs(self, request, pk):
"""
A convenience method for rendering graphs for a particular provider.
"""

View File

@ -23,7 +23,8 @@ from dcim.models import (
)
from extras.api.serializers import RenderedGraphSerializer
from extras.api.views import CustomFieldModelViewSet
from extras.models import Graph, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE
from extras.constants import GRAPH_TYPE_DEVICE, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE
from extras.models import Graph
from ipam.models import Prefix, VLAN
from utilities.api import (
get_serializer_for_model, IsAuthenticatedOrLoginNotRequired, FieldChoicesViewSet, ModelViewSet, ServiceUnavailable,
@ -123,7 +124,7 @@ class SiteViewSet(CustomFieldModelViewSet):
filterset_class = filters.SiteFilter
@action(detail=True)
def graphs(self, request, pk=None):
def graphs(self, request, pk):
"""
A convenience method for rendering graphs for a particular site.
"""
@ -346,6 +347,17 @@ class DeviceViewSet(CustomFieldModelViewSet):
return serializers.DeviceWithConfigContextSerializer
@action(detail=True)
def graphs(self, request, pk):
"""
A convenience method for rendering graphs for a particular Device.
"""
device = get_object_or_404(Device, pk=pk)
queryset = Graph.objects.filter(type=GRAPH_TYPE_DEVICE)
serializer = RenderedGraphSerializer(queryset, many=True, context={'graphed_object': device})
return Response(serializer.data)
@action(detail=True, url_path='napalm')
def napalm(self, request, pk):
"""
@ -458,7 +470,7 @@ class InterfaceViewSet(CableTraceMixin, ModelViewSet):
filterset_class = filters.InterfaceFilter
@action(detail=True)
def graphs(self, request, pk=None):
def graphs(self, request, pk):
"""
A convenience method for rendering graphs for a particular interface.
"""

View File

@ -16,7 +16,8 @@ from django.utils.safestring import mark_safe
from django.views.generic import View
from circuits.models import Circuit
from extras.models import Graph, TopologyMap, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE
from extras.constants import GRAPH_TYPE_DEVICE, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE
from extras.models import Graph, TopologyMap
from extras.views import ObjectConfigContextView
from ipam.models import Prefix, VLAN
from ipam.tables import InterfaceIPAddressTable, InterfaceVLANTable
@ -972,9 +973,6 @@ class DeviceView(PermissionRequiredMixin, View):
'rack', 'device_type__manufacturer'
)[:10]
# Show graph button on interfaces only if at least one graph has been created.
show_graphs = Graph.objects.filter(type=GRAPH_TYPE_INTERFACE).exists()
return render(request, 'dcim/device.html', {
'device': device,
'console_ports': console_ports,
@ -989,7 +987,8 @@ class DeviceView(PermissionRequiredMixin, View):
'secrets': secrets,
'vc_members': vc_members,
'related_devices': related_devices,
'show_graphs': show_graphs,
'show_graphs': Graph.objects.filter(type=GRAPH_TYPE_DEVICE).exists(),
'show_interface_graphs': Graph.objects.filter(type=GRAPH_TYPE_INTERFACE).exists(),
})

View File

@ -88,10 +88,12 @@ BUTTON_CLASS_CHOICES = (
# Graph types
GRAPH_TYPE_INTERFACE = 100
GRAPH_TYPE_DEVICE = 150
GRAPH_TYPE_PROVIDER = 200
GRAPH_TYPE_SITE = 300
GRAPH_TYPE_CHOICES = (
(GRAPH_TYPE_INTERFACE, 'Interface'),
(GRAPH_TYPE_DEVICE, 'Device'),
(GRAPH_TYPE_PROVIDER, 'Provider'),
(GRAPH_TYPE_SITE, 'Site'),
)

View File

@ -35,6 +35,12 @@
</div>
</div>
<div class="pull-right noprint">
{% if show_graphs %}
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#graphs_modal" data-obj="{{ device.name }}" data-url="{% url 'dcim-api:device-graphs' pk=device.pk %}" title="Show graphs">
<i class="fa fa-signal" aria-hidden="true"></i>
Graphs
</button>
{% endif %}
{% if perms.dcim.change_device %}
<div class="btn-group">
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">

View File

@ -135,7 +135,7 @@
{# Buttons #}
<td class="text-right text-nowrap noprint">
{% if show_graphs %}
{% if show_interface_graphs %}
{% if iface.connected_endpoint %}
<button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#graphs_modal" data-obj="{{ device.name }} - {{ iface.name }}" data-url="{% url 'dcim-api:interface-graphs' pk=iface.pk %}" title="Show graphs">
<i class="glyphicon glyphicon-signal" aria-hidden="true"></i>