From d33eddbc11e9dbf3253cb7fbd5098a6d6f8138b7 Mon Sep 17 00:00:00 2001 From: "J.-S. Caux" <J.S.Caux@uva.nl> Date: Sat, 27 Oct 2018 17:50:15 +0200 Subject: [PATCH] Start work on Ontology --- SciPost_v1/settings/base.py | 1 + SciPost_v1/urls.py | 1 + ontology/__init__.py | 0 ontology/admin.py | 19 +++++++++ ontology/migrations/0001_initial.py | 38 +++++++++++++++++ .../migrations/0002_auto_20181027_1748.py | 27 ++++++++++++ .../migrations/0003_auto_20181027_1748.py | 20 +++++++++ ontology/migrations/__init__.py | 0 ontology/models.py | 28 +++++++++++++ ontology/templates/ontology/base.html | 13 ++++++ ontology/templates/ontology/topic_form.html | 21 ++++++++++ ontology/templates/ontology/topic_list.html | 34 +++++++++++++++ ontology/urls.py | 25 +++++++++++ ontology/views.py | 42 +++++++++++++++++++ organizations/views.py | 1 - .../commands/add_groups_and_permissions.py | 10 +++++ 16 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 ontology/__init__.py create mode 100644 ontology/admin.py create mode 100644 ontology/migrations/0001_initial.py create mode 100644 ontology/migrations/0002_auto_20181027_1748.py create mode 100644 ontology/migrations/0003_auto_20181027_1748.py create mode 100644 ontology/migrations/__init__.py create mode 100644 ontology/models.py create mode 100644 ontology/templates/ontology/base.html create mode 100644 ontology/templates/ontology/topic_form.html create mode 100644 ontology/templates/ontology/topic_list.html create mode 100644 ontology/urls.py create mode 100644 ontology/views.py diff --git a/SciPost_v1/settings/base.py b/SciPost_v1/settings/base.py index 966b7dd41..1f517a0c5 100644 --- a/SciPost_v1/settings/base.py +++ b/SciPost_v1/settings/base.py @@ -106,6 +106,7 @@ INSTALLED_APPS = ( 'submissions', 'theses', 'virtualmeetings', + 'ontology', 'organizations', 'proceedings', 'production', diff --git a/SciPost_v1/urls.py b/SciPost_v1/urls.py index d8fe905e9..9f9948655 100644 --- a/SciPost_v1/urls.py +++ b/SciPost_v1/urls.py @@ -57,6 +57,7 @@ urlpatterns = [ url(r'^meetings/', include('virtualmeetings.urls', namespace="virtualmeetings")), url(r'^news/', include('news.urls', namespace="news")), url(r'^notifications/', include('notifications.urls', namespace="notifications")), + url(r'^ontology/', include('ontology.urls', namespace="ontology")), url(r'^organizations/', include('organizations.urls', namespace="organizations")), url(r'^petitions/', include('petitions.urls', namespace="petitions")), url(r'^preprints/', include('preprints.urls', namespace="preprints")), diff --git a/ontology/__init__.py b/ontology/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ontology/admin.py b/ontology/admin.py new file mode 100644 index 000000000..d02a46aa6 --- /dev/null +++ b/ontology/admin.py @@ -0,0 +1,19 @@ +__copyright__ = "Copyright 2016-2018, Stichting SciPost (SciPost Foundation)" +__license__ = "AGPL v3" + + +from django.contrib import admin + +from .models import Tag, Topic + + +class TagAdmin(admin.ModelAdmin): + pass + +admin.site.register(Tag, TagAdmin) + + +class TopicAdmin(admin.ModelAdmin): + pass + +admin.site.register(Topic, TopicAdmin) diff --git a/ontology/migrations/0001_initial.py b/ontology/migrations/0001_initial.py new file mode 100644 index 000000000..56b3e3058 --- /dev/null +++ b/ontology/migrations/0001_initial.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-10-27 15:31 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Relation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ], + ), + migrations.CreateModel( + name='Tag', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=32, unique=True)), + ], + ), + migrations.CreateModel( + name='Topic', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=256, unique=True)), + ('slug', models.SlugField(allow_unicode=True, unique=True)), + ('tags', models.ManyToManyField(to='ontology.Tag')), + ], + ), + ] diff --git a/ontology/migrations/0002_auto_20181027_1748.py b/ontology/migrations/0002_auto_20181027_1748.py new file mode 100644 index 000000000..6618082b2 --- /dev/null +++ b/ontology/migrations/0002_auto_20181027_1748.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-10-27 15:48 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ontology', '0001_initial'), + ] + + operations = [ + migrations.DeleteModel( + name='Relation', + ), + migrations.AlterModelOptions( + name='tag', + options={'ordering': ['name']}, + ), + migrations.AlterField( + model_name='topic', + name='tags', + field=models.ManyToManyField(blank=True, null=True, to='ontology.Tag'), + ), + ] diff --git a/ontology/migrations/0003_auto_20181027_1748.py b/ontology/migrations/0003_auto_20181027_1748.py new file mode 100644 index 000000000..4d3c2cfca --- /dev/null +++ b/ontology/migrations/0003_auto_20181027_1748.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2018-10-27 15:48 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ontology', '0002_auto_20181027_1748'), + ] + + operations = [ + migrations.AlterField( + model_name='topic', + name='tags', + field=models.ManyToManyField(blank=True, to='ontology.Tag'), + ), + ] diff --git a/ontology/migrations/__init__.py b/ontology/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ontology/models.py b/ontology/models.py new file mode 100644 index 000000000..fe750e8c2 --- /dev/null +++ b/ontology/models.py @@ -0,0 +1,28 @@ +__copyright__ = "Copyright 2016-2018, Stichting SciPost (SciPost Foundation)" +__license__ = "AGPL v3" + + +from django.db import models + + +class Tag(models.Model): + """ + Tags can be attached to a Topic to specify which category it fits. + Examples: Concept, Device, Model, Theory, ... + """ + name = models.CharField(max_length=32, unique=True) + + class Meta: + ordering = ['name'] + + +class Topic(models.Model): + """ + A Topic represents one of the nodes in the ontology. + """ + name = models.CharField(max_length=256, unique=True) + slug = models.SlugField(unique=True, allow_unicode=True) + tags = models.ManyToManyField(Tag, blank=True) + + def __str__(self): + return self.name diff --git a/ontology/templates/ontology/base.html b/ontology/templates/ontology/base.html new file mode 100644 index 000000000..2c038d8d6 --- /dev/null +++ b/ontology/templates/ontology/base.html @@ -0,0 +1,13 @@ +{% extends 'scipost/base.html' %} + +{% block breadcrumb %} + <div class="container-outside header"> + <div class="container"> + <nav class="breadcrumb hidden-sm-down"> + {% block breadcrumb_items %} + <a href="{% url 'ontology:topics' %}" class="breadcrumb-item">Topics</a> + {% endblock %} + </nav> + </div> + </div> +{% endblock %} diff --git a/ontology/templates/ontology/topic_form.html b/ontology/templates/ontology/topic_form.html new file mode 100644 index 000000000..e9636848b --- /dev/null +++ b/ontology/templates/ontology/topic_form.html @@ -0,0 +1,21 @@ +{% extends 'ontology/base.html' %} + +{% load bootstrap %} + +{% block breadcrumb_items %} + {{ block.super }} + <span class="breadcrumb-item">{% if form.instance.id %}Update {{ form.instance }}{% else %}Add new Topic{% endif %}</span> +{% endblock %} + +{% block pagetitle %}: Topics{% endblock pagetitle %} + +{% block content %} +<div class="row"> + <div class="col-12"> + <form action="" method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <input type="submit" value="Submit" class="btn btn-primary"> + </div> +</div> +{% endblock content %} diff --git a/ontology/templates/ontology/topic_list.html b/ontology/templates/ontology/topic_list.html new file mode 100644 index 000000000..66c3e0c85 --- /dev/null +++ b/ontology/templates/ontology/topic_list.html @@ -0,0 +1,34 @@ +{% extends 'ontology/base.html' %} + +{% block pagetitle %}: Topics{% endblock pagetitle %} + +{% block breadcrumb_items %} +{{ block.super }} +<span class="breadcrumb-item">Topics</span> +{% endblock %} + +{% block content %} + +<div class="row"> + <div class="col-12"> + <h3 class="highlight">Topics</h3> + {% if perms.scipost.can_manage_ontology %} + <ul> + <li><a href="{% url 'ontology:topic_create' %}">Add a Topic</a></li> + </ul> + {% endif %} + </div> +</div> + + +<div class="row"> + <div class="col-12"> + <ul> + {% for topic in object_list %} + <li>{{ topic }}</li> + {% endfor %} + </ul> + </div> +</div> + +{% endblock content %} diff --git a/ontology/urls.py b/ontology/urls.py new file mode 100644 index 000000000..e65bd07d9 --- /dev/null +++ b/ontology/urls.py @@ -0,0 +1,25 @@ +__copyright__ = "Copyright 2016-2018, Stichting SciPost (SciPost Foundation)" +__license__ = "AGPL v3" + + +from django.conf.urls import url + +from . import views + +urlpatterns = [ + url( + r'^topic/add/$', + views.TopicCreateView.as_view(), + name='topic_create' + ), + url( + r'^topic/(?P<slug>[-\w]+)/update/$', + views.TopicCreateView.as_view(), + name='topic_update' + ), + url( + r'^topics/$', + views.TopicListView.as_view(), + name='topics' + ), +] diff --git a/ontology/views.py b/ontology/views.py new file mode 100644 index 000000000..a3164e028 --- /dev/null +++ b/ontology/views.py @@ -0,0 +1,42 @@ +__copyright__ = "Copyright 2016-2018, Stichting SciPost (SciPost Foundation)" +__license__ = "AGPL v3" + + +from django.core.urlresolvers import reverse_lazy +from django.views.generic.detail import DetailView +from django.views.generic.edit import CreateView, UpdateView +from django.views.generic.list import ListView + +from .models import Topic + +from scipost.mixins import PermissionsMixin + + +class TopicCreateView(PermissionsMixin, CreateView): + """ + Create a new Topic for an Ontology. + """ + permission_required = 'scipost.can_manage_ontology' + model = Topic + fields = '__all__' + template_name = 'ontology/topic_form.html' + success_url = reverse_lazy('ontology:topics') + + +class TopicUpdateView(PermissionsMixin, UpdateView): + """ + Update a Topic for an Ontology. + """ + permission_required = 'scipost.can_manage_ontology' + model = Topic + fields = '__all__' + template_name = 'ontology/topic_form.html' + success_url = reverse_lazy('ontology:topics') + + +class TopicListView(ListView): + model = Topic + + +class TopicDetailView(DetailView): + model = Topic diff --git a/organizations/views.py b/organizations/views.py index d11f618d3..d10c41317 100644 --- a/organizations/views.py +++ b/organizations/views.py @@ -3,7 +3,6 @@ __license__ = "AGPL v3" from django.core.urlresolvers import reverse_lazy -from django.shortcuts import render from django.utils import timezone from django.views.generic.detail import DetailView from django.views.generic.edit import CreateView, UpdateView, DeleteView diff --git a/scipost/management/commands/add_groups_and_permissions.py b/scipost/management/commands/add_groups_and_permissions.py index f701e296f..a6be4d4a0 100644 --- a/scipost/management/commands/add_groups_and_permissions.py +++ b/scipost/management/commands/add_groups_and_permissions.py @@ -318,6 +318,13 @@ class Command(BaseCommand): name='Can manage Mailchimp settings', content_type=content_type) + # Ontology + can_manage_ontology, created = Permission.objects.get_or_create( + codename='can_manage_ontology', + name='Can manage ontology', + content_type=content_type) + + # Assign permissions to groups SciPostAdmin.permissions.set([ can_read_all_privacy_sensitive_data, @@ -347,6 +354,7 @@ class Command(BaseCommand): can_view_statistics, can_create_profiles, can_view_profiles, + can_manage_ontology, ]) FinancialAdmin.permissions.set([ @@ -388,6 +396,7 @@ class Command(BaseCommand): can_view_statistics, can_create_profiles, can_view_profiles, + can_manage_ontology, ]) EditorialCollege.permissions.set([ @@ -395,6 +404,7 @@ class Command(BaseCommand): can_take_charge_of_submissions, can_attend_VGMs, can_view_statistics, + can_manage_ontology, ]) VettingEditors.permissions.set([ -- GitLab