diff --git a/ontology/forms.py b/ontology/forms.py index a00e9dd640559aa44162febf3e50762ed29dafea..b56eb6faedf9b65fed83d8d90f5cdedfb6727b50 100644 --- a/ontology/forms.py +++ b/ontology/forms.py @@ -17,6 +17,11 @@ class SelectTopicForm(forms.Form): topic = AutoCompleteSelectField('topic_lookup') +class SelectLinkedTopicForm(forms.Form): + topic = AutoCompleteSelectField('linked_topic_lookup', + label='Lookup topic (click to see) ', help_text='') + + class AddRelationAsymForm(forms.Form): A = AutoCompleteSelectField('topic_lookup', label='', help_text='') relation = forms.ChoiceField(choices=TOPIC_RELATIONS_ASYM, label='') diff --git a/ontology/templates/ontology/ontology.html b/ontology/templates/ontology/ontology.html index e5f3bbd31f4dc9100d725c2f9ed5437e78c38e0b..952213dbcd98bc4e9af09b2ca7788d1179c8e993 100644 --- a/ontology/templates/ontology/ontology.html +++ b/ontology/templates/ontology/ontology.html @@ -12,13 +12,30 @@ <div class="row"> <div class="col-12"> <h3 class="highlight">Ontology</h3> + <p> + Welcome to SciPost's Ontology, which is a curated set of interlinked Topics + pertaining to all of the sciences. + </p> + <p> + Topics and their relations are defined by Editorial-level personnel. + </p> <ul> {% if perms.scipost.can_manage_ontology %} <li><a href="{% url 'ontology:topic_create' %}">Add a Topic</a></li> {% endif %} <li><a href="{% url 'ontology:topics' %}">View list of Topics</a></li> + <li> + <ul class="list-inline"> + <li class="list-inline-item">{{ select_linked_topic_form }}</li> + </ul> + </li> </ul> </div> </div> {% endblock content %} + +{% block footer_script %} +{{ block.super }} +{{ select_linked_topic_form.media }} +{% endblock footer_script %} diff --git a/ontology/templates/ontology/topic_list.html b/ontology/templates/ontology/topic_list.html index 2dc3311a27b4a41a9f6be85d86fd074646783a74..fd383a1a18f7d6911d3361358771d9c196130744 100644 --- a/ontology/templates/ontology/topic_list.html +++ b/ontology/templates/ontology/topic_list.html @@ -25,7 +25,9 @@ </li> <li class="list-inline-item"><input class="btn btn-outline-secondary" type="submit" value="Filter"></li> </ul> - </form> + </form> + </li> + <li>{{ select_linked_topic_form }}</li> </ul> </div> </div> @@ -33,9 +35,10 @@ <div class="row"> <div class="col-12"> - <ul> + <h3>Topics</h3> + <ul class="list-inline"> {% for topic in object_list %} - <li><a href="{% url 'ontology:topic_details' slug=topic.slug %}">{{ topic }}</a></li> + <li class="list-inline-item p-1"><a href="{% url 'ontology:topic_details' slug=topic.slug %}">{{ topic }}</a></li> {% endfor %} </ul> @@ -50,3 +53,8 @@ </div> {% endblock content %} + +{% block footer_script %} +{{ block.super }} +{{ select_linked_topic_form.media }} +{% endblock footer_script %} diff --git a/ontology/templatetags/lookup.py b/ontology/templatetags/lookup.py index 2fec056a229e6071a9c84f41398113c33252cf8c..1e2b3d5616f9bda2e215ab523d13a083eeacb04a 100644 --- a/ontology/templatetags/lookup.py +++ b/ontology/templatetags/lookup.py @@ -3,6 +3,7 @@ __license__ = "AGPL v3" from django.core.exceptions import PermissionDenied +from django.shortcuts import render, reverse from ajax_select import register, LookupChannel @@ -43,3 +44,21 @@ class TopicLookup(LookupChannel): def check_auth(self, request): if not request.user.has_perm('scipost.can_manage_ontology'): raise PermissionDenied + + +@register('linked_topic_lookup') +class LinkedTopicLookup(LookupChannel): + model = Topic + + def get_query(self, q, request): + return (self.model.objects.filter(name__icontains=q)[:10]) + + def format_item_display(self, item): + return + + def format_match(self, item): + return "<span class='auto_lookup_display'><a href='%s'>%s</a></span>" % ( + reverse('ontology:topic_details', kwargs={'slug': item.slug}), item) + + def check_auth(self, request): + pass diff --git a/ontology/views.py b/ontology/views.py index a5d39ae9936fce962e942245301eeb529796a2cc..06eaae5e22c64e27d9995b5684b9dbc87d81b49e 100644 --- a/ontology/views.py +++ b/ontology/views.py @@ -14,14 +14,17 @@ from django.views.generic.list import ListView from guardian.decorators import permission_required from .models import Tag, Topic, RelationAsym, RelationSym -from .forms import SelectTagForm, AddRelationAsymForm +from .forms import SelectTagForm, SelectLinkedTopicForm, AddRelationAsymForm from scipost.forms import SearchTextForm from scipost.mixins import PaginationMixin, PermissionsMixin def ontology(request): - return render(request, 'ontology/ontology.html') + context = { + 'select_linked_topic_form': SelectLinkedTopicForm(), + } + return render(request, 'ontology/ontology.html', context=context) class TopicCreateView(PermissionsMixin, CreateView): @@ -69,7 +72,7 @@ def topic_remove_tag(request, slug, tag_id): class TopicListView(PaginationMixin, ListView): model = Topic - paginate_by = 25 + paginate_by = 100 def get_queryset(self): """ @@ -84,6 +87,7 @@ class TopicListView(PaginationMixin, ListView): context = super().get_context_data(**kwargs) context.update({ 'searchform': SearchTextForm(initial={'text': self.request.GET.get('text')}), + 'select_linked_topic_form': SelectLinkedTopicForm(), }) return context @@ -103,10 +107,13 @@ class TopicDetailView(DetailView): def add_relation_asym(request, slug): form = AddRelationAsymForm(request.POST or None) if form.is_valid(): - relation = RelationAsym(A=form.cleaned_data['A'], relation=form.cleaned_data['relation'], - B=form.cleaned_data['B']) - relation.save() - messages.success(request, 'Relation successfully created') + relation, created = RelationAsym.objects.get_or_create( + A=form.cleaned_data['A'], relation=form.cleaned_data['relation'], + B=form.cleaned_data['B']) + if created: + messages.success(request, 'Relation successfully created') + else: + messages.info(request, 'This relation already exists') else: for error_messages in form.errors.values(): messages.warning(request, *error_messages)