From 5c1d665324b10cca142df9b7799ea58cd3e4be82 Mon Sep 17 00:00:00 2001 From: "J.-S. Caux" <J.S.Caux@uva.nl> Date: Wed, 13 Apr 2016 21:15:40 +0200 Subject: [PATCH] Graph and Node further developed --- scipost/forms.py | 17 +++++++ scipost/models.py | 23 ++++++++-- scipost/templates/scipost/add_graph_node.html | 20 +++++++++ .../templates/scipost/add_team_member.html | 4 +- scipost/templates/scipost/graph.html | 25 ++++++++++- scipost/urls.py | 3 +- scipost/views.py | 44 ++++++++++++++----- 7 files changed, 120 insertions(+), 16 deletions(-) create mode 100644 scipost/templates/scipost/add_graph_node.html diff --git a/scipost/forms.py b/scipost/forms.py index 2f22a11e0..980520f5e 100644 --- a/scipost/forms.py +++ b/scipost/forms.py @@ -137,3 +137,20 @@ class CreateGraphForm(forms.ModelForm): self.fields['teams_with_access'] = forms.ModelMultipleChoiceField( queryset=Team.objects.filter(Q(leader=contributor) | Q(members__in=[contributor]))) self.fields['teams_with_access'].widget.attrs.update({'placeholder': 'Team to be given access rights:'}) + + +class CreateNodeForm(forms.ModelForm): + arcs_out = forms.ModelMultipleChoiceField(Node, required=False) + class Meta: + model = Node + fields = ['name', 'description', 'annotation', 'arcs_in', 'arcs_out'] + + def __init__(self, *args, **kwargs): + graph = kwargs.pop('graph') + super(CreateNodeForm, self).__init__(*args, **kwargs) + self.fields['arcs_in'] = forms.ModelMultipleChoiceField( + queryset=Node.objects.filter(graph=graph)) + self.fields['arcs_in'].required=False + self.fields['arcs_out'] = forms.ModelMultipleChoiceField( + queryset=Node.objects.filter(graph=graph)) + self.fields['arcs_out'].required=False diff --git a/scipost/models.py b/scipost/models.py index 18b7cec94..622b92025 100644 --- a/scipost/models.py +++ b/scipost/models.py @@ -330,7 +330,7 @@ class Node(models.Model): added_by = models.ForeignKey(Contributor, default=None) created = models.DateTimeField(default=timezone.now) name = models.CharField(max_length=100) - arcs_in = models.ManyToManyField('self', blank=True, related_name='node_arcs_in') # arcs pointing into this node + arcs_in = models.ManyToManyField('self', blank=True, related_name='node_arcs_in', symmetrical=False) # arcs from another node pointing into this node description = models.TextField(blank=True, null=True) submissions = models.ManyToManyField('submissions.Submission', blank=True, related_name='node_submissions') commentaries = models.ManyToManyField('commentaries.Commentary', blank=True, related_name='node_commentaries') @@ -338,6 +338,23 @@ class Node(models.Model): annotation = models.TextField(blank=True, null=True) def __str__(self): - return self.graph.title[:20] + ': ' + self.name[:20] + ' (owner: ' + self.owner.user.first_name + ' ' + self.owner.user.last_name + ')' + return self.graph.title[:20] + ': ' + self.name[:20] - + def header_as_p(self): + context = Context({'graph_id': self.graph.id, 'id': self.id, 'name': self.name}) + output = '<p><a href="{% url \'scipost:graph\' graph_id=graph_id node_id=id %}">{{ name }}</a></p>' + template = Template(output) + return template.render(context) + + def contents(self): + context = Context({'graph_id': self.graph.id, 'id': self.id, 'name': self.name, + 'description': self.description, 'annotation': self.annotation}) + output = '''<h3><a href="{% url 'scipost:graph' graph_id=graph_id node_id=id %}">{{ name }}</a></h3> + <p>{{ description }}</p><p>{{ annotation }}</p>''' + template = Template(output) + return template.render(context) + + def contents_small(self): + output = '<div style="font-size: 60%">' + self.contents + '</div>' + template = Template(output) + return template.render() diff --git a/scipost/templates/scipost/add_graph_node.html b/scipost/templates/scipost/add_graph_node.html new file mode 100644 index 000000000..785f9ab50 --- /dev/null +++ b/scipost/templates/scipost/add_graph_node.html @@ -0,0 +1,20 @@ +{% extends 'scipost/base.html' %} + +{% block pagetitle %}: add graph node{% endblock pagetitle %} + +{% block bodysup %} + +<section> + <h1>Add Node to Graph</h1> + + <form action="{% url 'scipost:add_graph_node' graph_id=graph.id %}" method="post"> + {% csrf_token %} + <table> + {{ create_node_form.as_table }} + </table> + <input type="submit" value="Create Node" /> + </form> + +</section> + +{% endblock bodysup %} diff --git a/scipost/templates/scipost/add_team_member.html b/scipost/templates/scipost/add_team_member.html index de02025bc..a12e2c154 100644 --- a/scipost/templates/scipost/add_team_member.html +++ b/scipost/templates/scipost/add_team_member.html @@ -24,7 +24,9 @@ <p>Add a member to the Team:</p> <form action="{% url 'scipost:add_team_member' team_id=team.id %}" method="post"> {% csrf_token %} - {{ add_team_member_form }} + <table> + {{ add_team_member_form.as_table }} + </table> <input type="submit" value="Search" /> </form> {% endif %} diff --git a/scipost/templates/scipost/graph.html b/scipost/templates/scipost/graph.html index 8b14e6e4c..f4c4b1517 100644 --- a/scipost/templates/scipost/graph.html +++ b/scipost/templates/scipost/graph.html @@ -6,9 +6,32 @@ <section> <h1>Graph</h1> - {{ graph.contents }} + <hr class="hr6"/> + + {% if node.arcs_in.all %} + <h3>Pointed to from:</h3> + <ul> + {% for node_in in node.arcs_in.all %} + {{ node_in.header_as_p }} + {% endfor %} + </ul> + {% endif %} + + {{ node.contents }} + + {% if nodes_out %} + <h3>Pointing to:</h3> + <ul> + {% for node_out in nodes_out.all %} + {{ node_out.header_as_p }} + {% endfor %} + </ul> + {% endif %} + + <hr class="hr6"/> + <h3><a href="{% url 'scipost:add_graph_node' graph_id=node.graph.id %}">Add a Node</a></h3> </section> diff --git a/scipost/urls.py b/scipost/urls.py index 299141a0a..0868067d6 100644 --- a/scipost/urls.py +++ b/scipost/urls.py @@ -68,6 +68,7 @@ urlpatterns = [ # Graphs url(r'^create_graph$', views.create_graph, name='create_graph'), -# url(r'^add_graph_node/(?P<graph_id>[0-9]+)$', views.add_graph_node, name='add_graph_node'), + url(r'^add_graph_node/(?P<graph_id>[0-9]+)$', views.add_graph_node, name='add_graph_node'), url(r'^graph/(?P<graph_id>[0-9]+)$', views.graph, name='graph'), + url(r'^graph/(?P<graph_id>[0-9]+)/(?P<node_id>[0-9]+)$', views.graph, name='graph'), ] diff --git a/scipost/views.py b/scipost/views.py index f346e7ddd..56ee93eb2 100644 --- a/scipost/views.py +++ b/scipost/views.py @@ -653,15 +653,39 @@ def create_graph(request): @permission_required('scipost.can_create_graph', raise_exception=True) def graph(request, graph_id, node_id=None): graph = get_object_or_404(Graph, pk=graph_id) -# if node_id is not None: -# node = get_object_or_404(Node, pk=node_id) -# base_node = Node.objects.filter(graph=graph, arcs_in=None) - context = {'graph': graph} - return render(request, 'scipost/graph.html', context) + if node_id is not None: + node = get_object_or_404(Node, pk=node_id) + nodes_out = Node.objects.filter(graph=graph, arcs_in__in=[node]) + context = {'graph': graph, 'node': node, 'nodes_out': nodes_out} + return render(request, 'scipost/graph.html', context) + elif Node.objects.filter(graph=graph).exists(): + node = Node.objects.filter(graph=graph).first() + return redirect(reverse('scipost:graph', kwargs={'graph_id': graph.id, 'node_id': node.id})) + else: + return redirect(reverse('scipost:add_graph_node', kwargs={'graph_id': graph.id})) -@permission_required('scipost.can_create_graph', raise_exception=True) -def add_node_upstream(request, graph_id, node_id): - """ Adds a node upstream from the one at node_id """ - node = get_object_or_404(Node, pk=node_id) - +@permission_required('scipost.can_create_graph', raise_exception=True) +def add_graph_node(request, graph_id): + """ Adds a node """ + graph = get_object_or_404(Graph, pk=graph_id) + if request.method == "POST": + create_node_form = CreateNodeForm(request.POST, graph=graph) + if create_node_form.is_valid(): + newnode = Node(graph=graph, + added_by=request.user.contributor, + created=timezone.now(), + name=create_node_form.cleaned_data['name'], + description=create_node_form.cleaned_data['description'], + annotation=create_node_form.cleaned_data['annotation']) + newnode.save() # Need to save first, before addressing attribute in next line + newnode.arcs_in = create_node_form.cleaned_data['arcs_in'] + newnode.save() + for outnode in create_node_form.cleaned_data['arcs_out']: + outnode.arcs_in.add(newnode) + outnode.save() + return redirect(reverse('scipost:graph', kwargs={'graph_id': graph.id, 'node_id': newnode.id})) + else: + create_node_form = CreateNodeForm(graph=graph) + context = {'graph': graph, 'create_node_form': create_node_form} + return render(request, 'scipost/add_graph_node.html', context) -- GitLab