Skip to content
This repository was archived by the owner on Jun 27, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 5 additions & 25 deletions django_netjsongraph/base/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class Media:
static('netjsongraph/js/src/netjsongraph.js'),
static('netjsongraph/js/receive-url.js'),
static('netjsongraph/js/strategy-switcher.js'),
static('netjsongraph/js/topology-switcher.js'),
static('netjsongraph/js/visualize.js')]


Expand Down Expand Up @@ -85,9 +86,6 @@ def get_urls(self):
url(r'^visualize/(?P<pk>[^/]+)/$',
self.admin_site.admin_view(self.visualize_view),
name='{0}_visualize'.format(url_prefix)),
url(r'^visualize/history/(?P<pk>[^/]+)/$',
self.admin_site.admin_view(self.visualize_history_view),
name='{0}_visualize_history'.format(url_prefix))
] + super(AbstractTopologyAdmin, self).get_urls()

def _message(self, request, rows, suffix, level=messages.SUCCESS):
Expand Down Expand Up @@ -127,35 +125,17 @@ def unpublish_selected(self, request, queryset):
unpublish_selected.short_description = _('Unpublish selected items')

def visualize_view(self, request, pk):
api_url = reverse('network_graph', args=[pk])
graph_url = reverse('network_graph', args=[pk])
history_url = reverse('network_graph_history', args=[pk])
context = self.admin_site.each_context(request)
opts = self.model._meta
prefix = 'admin:{0}_{1}'.format(self.opts.app_label, self.model.__name__.lower())
graph_url = reverse('{0}_visualize_history'.format(prefix), args=[pk])
context.update({
'is_popup': True,
'opts': opts,
'change': False,
'media': self.media,
'api_url': api_url,
'graph_url': graph_url
})
return TemplateResponse(request, 'admin/%s/visualize.html' % opts.app_label, context)

def visualize_history_view(self, request, pk):
date = request.GET.get('date', '')
api_url = '{0}?date={1}'.format(reverse('network_graph_history', args=[pk]), date)
context = self.admin_site.each_context(request)
opts = self.model._meta
prefix = 'admin:{0}_{1}'.format(self.opts.app_label, self.model.__name__.lower())
graph_url = reverse('{0}_visualize_history'.format(prefix), args=[pk])
context.update({
'is_popup': True,
'opts': opts,
'change': False,
'media': self.media,
'api_url': api_url,
'graph_url': graph_url
'graph_url': graph_url,
'history_url': history_url
})
return TemplateResponse(request, 'admin/%s/visualize.html' % opts.app_label, context)

Expand Down
38 changes: 16 additions & 22 deletions django_netjsongraph/static/netjsongraph/js/topology-switcher.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,26 @@
$(function() {
window.initTopologyHistory = function($){
$('#dp').datepicker();
d = new Date();
month = d.getMonth() + 1;
day = d.getDate();
defaultDate = (month < 10 ? '0' : '') + month + '/' +
(day < 10 ? '0' : '') + day + '/' +
d.getFullYear();
var d = new Date(),
month = d.getMonth() + 1,
day = d.getDate(),
defaultDate = (month < 10 ? '0' : '') + month + '/' +
(day < 10 ? '0' : '') + day + '/' + d.getFullYear(),
currentDate = d.getFullYear() + '-' + (month < 10 ? '0' : '') +
month + '-' + (day < 10 ? '0' : '') + day;
$('#dp').val(defaultDate);
currentDate = d.getFullYear() + '-' +
(month < 10 ? '0' : '') + month + '-' +
(day < 10 ? '0' : '') + day;
$('#submit').click(function() {
queryDate = $('#dp').val();
date = queryDate.split('/').reverse();
var queryDate = $('#dp').val(),
date = queryDate.split('/').reverse(),
graphUrl;
if(date != []){
var x = date[1];
date[1] = date[2];
date[2] = x;
}
date = date.join('-');
graphUrl = $('.switcher').attr('graph-url') + '?date=' + date;
if(currentDate == date){
graphUrl = window.location.href;
}
body = $('body');
$.get(graphUrl, function(html) {
body.html(html);
$('#dp').val(queryDate);
});
graphUrl = $('.switcher').attr('data-history-api') + '?date=' + date;
// load latest data when looking currentDate
if(currentDate == date){ graphUrl = undefined }
window.graph = window.loadNetJsonGraph(graphUrl);
});
});
};
52 changes: 2 additions & 50 deletions django_netjsongraph/static/netjsongraph/js/visualize.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,18 @@ django.jQuery(function($) {
inner = overlay.find('.inner'),
visualizeUrl = $('.visualizelink').attr('data-url');

var d = new Date(),
month = d.getMonth() + 1,
day = d.getDate(),
default_date = (month < 10 ? '0': '') + month + '/' +
(day < 10 ? '0': '') + day + '/' +
d.getFullYear(),
current_date = d.getFullYear() + '-' +
(month < 10 ? '0': '') + month + '-' +
(day < 10 ? '0': '') + day;

var openOverlay = function() {
// show overlay
window.__njg_el__ = '.djnjg-overlay .inner';
$.get(visualizeUrl, function(html) {
inner.html(html);
$('svg').appendTo(inner);
$('.njg-overlay').appendTo(inner);
$('.njg-metadata').appendTo(inner);
overlay.show();
inner.html(html);
body.css('overflow', 'hidden');
inner.css('overflow', 'hidden');
overlay.find('.close').click(function(e){
e.preventDefault();
closeOverlay();
})
overlay.find('#dp').val(default_date);
overlay.find('#submit').click(function(e){
e.preventDefault();
getTopologyHistory();
})
})
.error(function(xhr) {
if (xhr.status == 400) {
Expand Down Expand Up @@ -78,35 +61,4 @@ django.jQuery(function($) {
e.preventDefault();
}
}

var getTopologyHistory = function(e) {
query_date = $('#dp').val();
date = query_date.split('/').reverse();
if(date != []){
var x = date[1];
date[1] = date[2];
date[2] = x;
}
date = date.join('-');
graph_url = $('.switcher').attr('graph-url') + '?date=' + date;
if(date == current_date) graph_url = visualizeUrl;
$.get(graph_url, function(html) {
inner.html(html);
$('svg').appendTo(inner);
$('.njg-overlay').appendTo(inner);
$('.njg-metadata').appendTo(inner);
overlay.find('#dp').val(query_date);
overlay.show();
body.css('overflow', 'hidden');
inner.css('overflow', 'hidden');
overlay.find('.close').click(function(e){
e.preventDefault();
closeOverlay();
})
overlay.find('#submit').click(function(e){
e.preventDefault();
getTopologyHistory();
})
})
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,9 @@
{% load static %}

{% block content %}
<div>
<a class="close" href="#">&times; {% trans 'Close' %}</a>
</div>
<div id="legend">
<p><span class="link up">&nbsp;</span>link up</p>
<p><span class="link down">&nbsp;</span>link down</p>
</div>
<div class="switcher" graph-url='{{graph_url}}'>
<label for="dp">Date</label>
<input type="text" id="dp" onclick="$('#dp').datepicker();$('#dp').datepicker('show');">
<button id="submit">Submit</button>
</div>
{% block script %}
{% include '../../netjsongraph/netjsongraph-script.html' %}
{% endblock %}
{% include '../../netjsongraph/netjsongraph-content.html' %}
{% block script %}
{% include '../../netjsongraph/netjsongraph-script.html' %}
{% endblock %}
{% endblock %}
9 changes: 1 addition & 8 deletions django_netjsongraph/templates/netjsongraph/detail.html
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
{% extends 'netjsongraph/base.html' %}
{% block title %}{{ topology.label }}{% endblock %}
{% block body %}
<div id="legend">
<p><span class="link up">&nbsp;</span> link up</p>
<p><span class="link down">&nbsp;</span> link down</p>
</div>
<div class="switcher" graph-url='{{ graph_url }}'>
<label for="dp">Date </label><input type="text" id="dp">
<button id="submit">Submit</button>
</div>
{% include './netjsongraph-content.html' %}
{% endblock %}
{% block script %}
{{ block.super }}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div id="legend">
<p><span class="link up">&nbsp;</span> link up</p>
<p><span class="link down">&nbsp;</span> link down</p>
</div>
<div class="switcher" data-history-api="{{ history_url }}">
<label for="dp">Date </label><input type="text" id="dp">
<button id="submit">Submit</button>
</div>
35 changes: 25 additions & 10 deletions django_netjsongraph/templates/netjsongraph/netjsongraph-script.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
<script>
var graph = d3.netJsonGraph("{{ api_url }}", {
linkClassProperty: "status",
defaultStyle: false,
labelDy: "-1.5em",
circleRadius: 7,
charge: -300,
gravity: 0.1,
linkDistance: 70,
linkStrength: 0.1
});
// the graph may be loaded elsewhere than body
window.__njg_el__ = window.__njg_el__ || "body";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is amazing! Didn't know we could do all these 😮

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably not optimal because not very easy to read, but a more elegant solution would require more time.
we basically reuse this piece of code to load and reload the graph in frontend, admin and when loading older snapshots, the difference is that in the admin we set window.__njg_el__ to the overlay, and when using snapshots we first fetch the data from the API and then pass the data in the graph directly to the library.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. I understand. I really liked how you made it reusable

// loadGraph wrapper is used to reload
// the graph with data from older snapshots
window.loadNetJsonGraph = function(url){
url = url || "{{ graph_url }}";
// destroy HTML elements if present
d3.select("svg").remove();
d3.select(".njg-overlay").remove();
d3.select(".njg-metadata").remove();
// load graph
return d3.netJsonGraph(url, {
el: window.__njg_el__,
linkClassProperty: "status",
defaultStyle: false,
labelDy: "-1.5em",
circleRadius: 7,
charge: -300,
gravity: 0.1,
linkDistance: 70,
linkStrength: 0.1
});
};
window.graph = window.loadNetJsonGraph();
window.initTopologyHistory(jQuery);
</script>
12 changes: 1 addition & 11 deletions django_netjsongraph/tests/base/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,4 @@ def test_topology_visualize_view(self):
t = self.topology_model.objects.first()
path = reverse('{0}_topology_visualize'.format(self.prefix), args=[t.pk])
response = self.client.get(path)
self.assertContains(response, 'var graph = d3.netJsonGraph')

def test_topology_visualize_history_view(self):
t = self.topology_model.objects.first()
t.save_snapshot()
date = t.snapshot_model.objects.first().date
api_url = '{0}?date={1}'.format(reverse('network_graph_history', args=[t.pk]), date)
admin_url = reverse('{0}_topology_visualize_history'.format(self.prefix), args=[t.pk])
path = '{0}?date={1}'.format(admin_url, date)
response = self.client.get(path)
self.assertContains(response, 'var graph = d3.netJsonGraph("{0}"'.format(api_url))
self.assertContains(response, 'd3.netJsonGraph(')
16 changes: 3 additions & 13 deletions django_netjsongraph/tests/base/visualizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ def test_detail(self):
t = self.topology_model.objects.first()
response = self.client.get(reverse('topology_detail', args=[t.pk]))
self.assertContains(response, t.pk)
# ensure switcher is present
self.assertContains(response, 'switcher')
self.assertContains(response, 'dp')

def test_list_unpublished(self):
self._unpublish()
Expand All @@ -31,16 +34,3 @@ def test_detail_uuid_exception(self):
t = self.topology_model.objects.first()
response = self.client.get(reverse('topology_detail', args=['{0}-wrong'.format(t.pk)]))
self.assertEqual(response.status_code, 404)

def test_switcher_button(self):
t = self.topology_model.objects.first()
response = self.client.get(reverse('topology_detail', args=[t.pk]))
self.assertContains(response, 'switcher')
self.assertContains(response, 'dp')

def test_topology_history(self):
t = self.topology_model.objects.first()
t.save_snapshot()
date = t.snapshot_set.model.objects.first().date
response = self.client.get('{0}?date={1}'.format(reverse('topology_history', args=[t.pk]), date))
self.assertEqual(response.status_code, 200)
3 changes: 0 additions & 3 deletions django_netjsongraph/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,5 @@ def get_visualizer_urls(views_module):
url(r'^topology/(?P<pk>[^/]+)/$',
views_module.topology_detail,
name='topology_detail'),
url(r'^topology/(?P<pk>[^/]+)/history/$',
views_module.topology_history,
name='topology_history'),
]
return urls
25 changes: 6 additions & 19 deletions django_netjsongraph/visualizer/generics.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,9 @@ def get(self, request):
class BaseTopologyDetailView(View):
def get(self, request, pk):
topology = get_object_or_404(self.topology_model, pk)
api_url = reverse('network_graph', args=[topology.pk])
graph_url = reverse('topology_history', args=[topology.pk])
return render_to_response('netjsongraph/detail.html',
{'api_url': api_url,
'graph_url': graph_url,
'topology': topology,
'VISUALIZER_CSS': VISUALIZER_CSS})


class BaseTopologyHistoryView(View):
def get(self, request, pk):
topology = get_object_or_404(self.topology_model, pk)
date = request.GET.get('date', '')
api_url = '{0}?date={1}'.format(reverse('network_graph_history', args=[topology.pk]), date)
graph_url = reverse('topology_history', args=[topology.pk])
return render_to_response('netjsongraph/detail.html',
{'api_url': api_url,
'graph_url': graph_url,
'VISUALIZER_CSS': VISUALIZER_CSS})
return render_to_response('netjsongraph/detail.html', {
'topology': topology,
'graph_url': reverse('network_graph', args=[topology.pk]),
'history_url': reverse('network_graph_history', args=[topology.pk]),
'VISUALIZER_CSS': VISUALIZER_CSS
})
8 changes: 1 addition & 7 deletions django_netjsongraph/visualizer/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from ..models import Topology
from .generics import (BaseTopologyDetailView, BaseTopologyHistoryView,
BaseTopologyListView)
from .generics import BaseTopologyDetailView, BaseTopologyListView


class TopologyListView(BaseTopologyListView):
Expand All @@ -11,10 +10,5 @@ class TopologyDetailView(BaseTopologyDetailView):
topology_model = Topology


class TopologyHistoryView(BaseTopologyHistoryView):
topology_model = Topology


topology_list = TopologyListView.as_view()
topology_detail = TopologyDetailView.as_view()
topology_history = TopologyHistoryView.as_view()