mirror of
https://github.com/Southampton-RSG/breccia-mapper.git
synced 2026-03-03 11:27:09 +00:00
feat(people): Add network view
Network view shows people and relationships between them Resolves #21 Resolves #20 Part of #14
This commit is contained in:
26
people/serializers.py
Normal file
26
people/serializers.py
Normal file
@@ -0,0 +1,26 @@
|
||||
"""
|
||||
Serialize models to and deserialize from JSON.
|
||||
"""
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from . import models
|
||||
|
||||
|
||||
class PersonSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = models.Person
|
||||
fields = [
|
||||
'pk',
|
||||
'name',
|
||||
]
|
||||
|
||||
|
||||
class RelationshipSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = models.Relationship
|
||||
fields = [
|
||||
'pk',
|
||||
'source',
|
||||
'target',
|
||||
]
|
||||
120
people/templates/people/network.html
Normal file
120
people/templates/people/network.html
Normal file
@@ -0,0 +1,120 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item active" aria-current="page">Network</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<hr>
|
||||
|
||||
<div id="cy"
|
||||
style="width: 100%; min-height: 1000px; flex-grow: 1; border: 2px solid black"></div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_script %}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.14.0/cytoscape.min.js"
|
||||
integrity="sha256-rI7zH7xDqO306nxvXUw9gqkeBpvvmddDdlXJjJM7rEM="
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
var cy;
|
||||
|
||||
/**
|
||||
* Get all :class:`Person` records from people:person.api.list endpoint.
|
||||
*
|
||||
* @returns JQuery Promise from AJAX
|
||||
*/
|
||||
function get_people_ajax(){
|
||||
return $.ajax({
|
||||
url: '{% url "people:person.api.list" %}',
|
||||
success: success_people_ajax,
|
||||
error: function (xhr, status, error) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add nodes to Cytoscape network from :class:`Person` JSON.
|
||||
*
|
||||
* @param data: JSON representation of people
|
||||
* @param status: unused
|
||||
* @param xhr: unused
|
||||
*/
|
||||
function success_people_ajax(data, status, xhr) {
|
||||
for (var person of data) {
|
||||
cy.add({
|
||||
group: 'nodes',
|
||||
data: {
|
||||
id: 'person-' + person.pk.toString(),
|
||||
name: person.name
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all :class:`Relationship` records from people:relationship.api.list endpoint.
|
||||
*
|
||||
* @returns JQuery Promise from AJAX
|
||||
*/
|
||||
function get_relationships_ajax() {
|
||||
return $.ajax({
|
||||
url: '{% url "people:relationship.api.list" %}',
|
||||
success: success_relationships_ajax,
|
||||
error: function (xhr, status, error) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add edges to Cytoscape network from :class:`Relationship` JSON.
|
||||
*
|
||||
* @param data: JSON representation of relationships
|
||||
* @param status: unused
|
||||
* @param xhr: unused
|
||||
*/
|
||||
function success_relationships_ajax(data, status, xhr) {
|
||||
for (var relationship of data) {
|
||||
cy.add({
|
||||
group: 'edges',
|
||||
data: {
|
||||
id: 'relationship-' + relationship.pk.toString(),
|
||||
source: 'person-' + relationship.source.toString(),
|
||||
target: 'person-' + relationship.target.toString()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate a Cytoscape network from :class:`Person` and :class:`Relationship` API.
|
||||
*/
|
||||
function get_network() {
|
||||
cy = cytoscape({
|
||||
container: document.getElementById('cy')
|
||||
});
|
||||
|
||||
$.when(get_people_ajax()).then(function() {
|
||||
get_relationships_ajax()
|
||||
|
||||
}).then(function() {
|
||||
var layout = cy.layout({
|
||||
name: 'circle',
|
||||
randomize: true,
|
||||
animate: false
|
||||
});
|
||||
|
||||
layout.run();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
$( window ).on('load', get_network());
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -37,4 +37,16 @@ urlpatterns = [
|
||||
path('relationships/<int:relationship_pk>/update',
|
||||
views.RelationshipUpdateView.as_view(),
|
||||
name='relationship.update'),
|
||||
|
||||
path('api/people',
|
||||
views.PersonApiView.as_view(),
|
||||
name='person.api.list'),
|
||||
|
||||
path('api/relationships',
|
||||
views.RelationshipApiView.as_view(),
|
||||
name='relationship.api.list'),
|
||||
|
||||
path('network',
|
||||
views.NetworkView.as_view(),
|
||||
name='network'),
|
||||
]
|
||||
|
||||
@@ -4,9 +4,11 @@ Views for displaying or manipulating models in the 'people' app.
|
||||
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.urls import reverse
|
||||
from django.views.generic import CreateView, DetailView, FormView, ListView, UpdateView
|
||||
from django.views.generic import CreateView, DetailView, ListView, TemplateView, UpdateView
|
||||
|
||||
from . import forms, models, permissions
|
||||
from rest_framework.views import APIView, Response
|
||||
|
||||
from . import forms, models, permissions, serializers
|
||||
|
||||
|
||||
class PersonCreateView(CreateView):
|
||||
@@ -176,3 +178,36 @@ class RelationshipUpdateView(permissions.UserIsLinkedPersonMixin, CreateView):
|
||||
form.save()
|
||||
|
||||
return HttpResponseRedirect(self.relationship.get_absolute_url())
|
||||
|
||||
|
||||
class PersonApiView(APIView):
|
||||
"""
|
||||
List all :class:`Person` instances.
|
||||
"""
|
||||
def get(self, request, format=None):
|
||||
"""
|
||||
List all :class:`Person` instances.
|
||||
"""
|
||||
serializer = serializers.PersonSerializer(models.Person.objects.all(),
|
||||
many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
|
||||
class RelationshipApiView(APIView):
|
||||
"""
|
||||
List all :class:`Relationship` instances.
|
||||
"""
|
||||
def get(self, request, format=None):
|
||||
"""
|
||||
List all :class:`Relationship` instances.
|
||||
"""
|
||||
serializer = serializers.RelationshipSerializer(models.Relationship.objects.all(),
|
||||
many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
|
||||
class NetworkView(TemplateView):
|
||||
"""
|
||||
View to display relationship network.
|
||||
"""
|
||||
template_name = 'people/network.html'
|
||||
|
||||
Reference in New Issue
Block a user