Started work on notification and user homepage + method for a comment to find back its page in his annotation's comments
--- a/src/iconolab/auth/views.py Tue Aug 02 11:13:52 2016 +0200
+++ b/src/iconolab/auth/views.py Wed Aug 03 15:47:03 2016 +0200
@@ -62,7 +62,6 @@
form = self.get_form()
if form.is_valid():
form.save()
- print(request.POST)
user = authenticate(username=request.POST["username"], password=request.POST["password1"])
login(request, user)
return HttpResponseRedirect(self.success_url)
--- a/src/iconolab/fixtures/demo_data.json Tue Aug 02 11:13:52 2016 +0200
+++ b/src/iconolab/fixtures/demo_data.json Wed Aug 03 15:47:03 2016 +0200
@@ -222,7 +222,7 @@
"pk": 2,
"fields": {
"collection": 1,
- "label": "Appel à expert"
+ "label": "Appel à expertise"
}
},{
"model": "iconolab.MetaCategory",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/migrations/0005_auto_20160802_1211.py Wed Aug 03 15:47:03 2016 +0200
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-08-02 12:11
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('iconolab', '0004_auto_20160711_1514'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='iconolabcomment',
+ options={'ordering': ['thread_id', 'id']},
+ ),
+ migrations.AddField(
+ model_name='annotationstats',
+ name='awaiting_revisions_count',
+ field=models.IntegerField(blank=True, default=0, null=True),
+ ),
+ ]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/migrations/0006_metacategory_triggers_notifications.py Wed Aug 03 15:47:03 2016 +0200
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-08-02 12:52
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('iconolab', '0005_auto_20160802_1211'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='metacategory',
+ name='triggers_notifications',
+ field=models.IntegerField(choices=[(0, 'none'), (1, 'contributors'), (2, 'commenters'), (3, 'collection admins')], default=0),
+ ),
+ ]
--- a/src/iconolab/models.py Tue Aug 02 11:13:52 2016 +0200
+++ b/src/iconolab/models.py Wed Aug 03 15:47:03 2016 +0200
@@ -132,6 +132,7 @@
class AnnotationStats(models.Model):
annotation = models.OneToOneField('Annotation', related_name='stats', blank=False, null=False)
submitted_revisions_count = models.IntegerField(blank=True, null=True, default=1)
+ awaiting_revisions_count = models.IntegerField(blank=True, null=True, default=0)
accepted_revisions_count = models.IntegerField(blank=True, null=True, default=1)
contributors_count = models.IntegerField(blank=True, null=True, default=1)
views_count = models.IntegerField(blank=True, null=True, default=0)
@@ -140,11 +141,13 @@
@property
def contributors(self):
- contributors = []
- for revision in self.annotation.revisions.filter(state__in=[AnnotationRevision.ACCEPTED, AnnotationRevision.STUDIED]):
- if revision.author not in contributors:
- contributors.append(revision.author)
- return contributors
+ user_ids_list = self.annotation.revisions.filter(state__in=[AnnotationRevision.ACCEPTED, AnnotationRevision.STUDIED]).values_list("author__id", flat=True)
+ return User.objects.filter(id__in=user_ids_list).distinct()
+
+ @property
+ def commenters(self):
+ user_ids_list = IconolabComment.objects.filter(content_type__app_label="iconolab", content_type__model="annotation", object_pk=self.annotation.id).values_list("user__id", flat=True)
+ return User.objects.filter(id__in=user_ids_list).distinct()
def set_tags_stats(self):
self.tag_count = Tag.objects.filter(tagginginfo__revision__annotation = self.annotation).distinct().count()
@@ -155,6 +158,8 @@
# submitted_revisions_count
annotation_revisions = self.annotation.revisions
self.submitted_revisions_count = annotation_revisions.count()
+ # aawaiting_revisions_count
+ self.awaiting_revisions_count = annotation_revisions.filter(state=AnnotationRevision.AWAITING).count()
# accepted_revisions_count
self.accepted_revisions_count = annotation_revisions.filter(state=AnnotationRevision.ACCEPTED).count() + annotation_revisions.filter(state=AnnotationRevision.STUDIED).count()
# comment_count
@@ -178,6 +183,11 @@
objects = AnnotationManager()
+ @property
+ def awaiting_revisions_count(self):
+ return self.revisions.filter(state=AnnotationRevision.AWAITING).distinct().count()
+
+
# Call to create a new revision, possibly from a merge
@transaction.atomic
def make_new_revision(self, author, title, description, fragment, tags_json):
@@ -362,10 +372,31 @@
class Meta:
ordering = ["thread_id", "id"]
+ # Get page for considered comment, with COMMENTS_PER_PAGE_DEFAULT comments per page
+ def get_comment_page(self):
+ return self._default_manager.filter(
+ object_pk=self.object_pk,
+ content_type__app_label=self.content_type.app_label,
+ content_type__model=self.content_type.model
+ ).order_by("thread_id", "-order").filter(thread_id__lt=self.thread_id, order__gt=self.order).count() // settings.COMMENTS_PER_PAGE_DEFAULT + 1
+
class MetaCategory(models.Model):
+ NONE = 0 # Notifies nobody
+ CONTRIBUTORS = 1 # Notifies contributors (revision owners) on target annotation
+ COMMENTERS = 2 # Notifies commenters (contributors + comment owners) on target annotation
+ COLLECTION_ADMINS = 3 # Notifies collection admins
+
+ NOTIFIED_USERS = (
+ (NONE, 'none'),
+ (CONTRIBUTORS, 'contributors'),
+ (COMMENTERS, 'commenters'),
+ (COLLECTION_ADMINS, 'collection admins'),
+ )
+
collection = models.ForeignKey(Collection)
label = models.CharField(max_length=255)
-
+ triggers_notifications = models.IntegerField(choices=NOTIFIED_USERS, default=NONE)
+
def __str__(self):
return self.label
--- a/src/iconolab/settings/__init__.py Tue Aug 02 11:13:52 2016 +0200
+++ b/src/iconolab/settings/__init__.py Wed Aug 03 15:47:03 2016 +0200
@@ -58,12 +58,14 @@
'django_comments_xtd',
'iconolab.apps.IconolabApp',
'sorl.thumbnail',
+ 'notifications'
]
COMMENTS_APP = "django_comments_xtd"
COMMENTS_XTD_MODEL = "iconolab.models.IconolabComment"
COMMENTS_XTD_FORM_CLASS = 'iconolab.forms.comments.IconolabCommentForm'
COMMENTS_XTD_MAX_THREAD_LEVEL = 100
+COMMENTS_PER_PAGE_DEFAULT = 10
SITE_ID = 1
--- a/src/iconolab/settings/dev.py.tmpl Tue Aug 02 11:13:52 2016 +0200
+++ b/src/iconolab/settings/dev.py.tmpl Wed Aug 03 15:47:03 2016 +0200
@@ -57,11 +57,14 @@
'reversion_compare',
'iconolab.apps.IconolabApp',
'sorl.thumbnail',
+ 'notifications'
]
COMMENTS_APP = "django_comments_xtd"
COMMENTS_XTD_MODEL = "iconolab.models.IconolabComment"
+COMMENTS_XTD_FORM_CLASS = 'iconolab.forms.comments.IconolabCommentForm'
COMMENTS_XTD_MAX_THREAD_LEVEL = 100
+COMMENTS_PER_PAGE_DEFAULT = 10
SITE_ID = 1
--- a/src/iconolab/signals/handlers.py Tue Aug 02 11:13:52 2016 +0200
+++ b/src/iconolab/signals/handlers.py Wed Aug 03 15:47:03 2016 +0200
@@ -1,11 +1,12 @@
from django.apps import apps
from django.db.models.signals import post_save
from django.dispatch import Signal, receiver
-
+from notifications.signals import notify
+from django_comments.signals import comment_was_posted
# Signal sent during method Annotation.validate_existing_revision to update stats
-revision_accepted = Signal(providing_args=["instance"])
-revision_created = Signal(providing_args=["instance"])
+revision_accepted = Signal(providing_args=['instance'])
+revision_created = Signal(providing_args=['instance'])
def increment_stats_on_new_revision(sender, instance, **kwargs):
@@ -16,6 +17,8 @@
annotation.stats.submitted_revisions_count += 1
if instance.state in [AnnotationRevision.ACCEPTED, AnnotationRevision.STUDIED]:
annotation.stats.accepted_revisions_count += 1
+ if instance.state in [AnnotationRevision.AWAITING]:
+ annotation.stats.awaiting_revisions_count += 1
annotation.stats.set_tags_stats()
annotation.stats.save()
# Image stats
@@ -23,7 +26,7 @@
image.stats.submitted_revisions_count += 1
image.stats.set_tags_stats()
image.stats.save()
-
+
def increment_stats_on_new_comments(sender, instance, created, **kwargs):
from iconolab.models import IconolabComment
@@ -53,8 +56,50 @@
image.stats.set_tags_stats()
image.stats.save()
+
+def notify_users_on_new_comment(sender, comment, **kwargs):
+ from iconolab.models import IconolabComment, Annotation, MetaCategory
+ if sender == IconolabComment and instance.content_type.app_label == 'iconolab' and instance.content_type.model == 'annotation':
+ comment_annotation = Annotation.objects.get(id=instance.object_pk)
+ # Notifying new user comment
+ if instance.user != comment_annotation.author:
+ notify.send(instance.user, recipient=comment_annotation.author, verb='a écrit un commentaire sur votre annotation', action_object=instance, target=comment_annotation)
+ print(instance.parent_id)
+ print(instance.id)
+ if instance.level > 0:
+ parent_comment = IconolabComment.objects.get(id=instance.parent_id)
+ notify.send(instance.user, recipient=parent_comment.user, verb='a répondu à votre commentaire', action_object=instance, target=comment_annotation)
+ for metacategory in instance.metacategories.all():
+ if metacategory.triggers_notifications == MetaCategory.COMMENTERS:
+ for commenter in comment_annotation.stats.commenters.exclude(id=instance.user.id).all():
+ notify.send(instance.user, recipient=commenter, verb='a fait un appel à contribution', action_object=instance, target=comment_annotation)
+ elif metacategory.triggers_notifications == MetaCategory.CONTRIBUTORS:
+ for contributor in comment_annotation.stats.contributors.exclude(id=instance.user.id).all():
+ notify.send(instance.user, recipient=contributor, verb='a fait un appel à contribution', action_object=instance, target=comment_annotation)
+ if metacategory.triggers_notifications == MetaCategory.COLLECTION_ADMINS:
+ pass
+
+def notify_users_on_new_revision(sender, instance, **kwargs):
+ from iconolab.models import AnnotationRevision
+ if sender == AnnotationRevision:
+ if instance.author != instance.annotation.author:
+ notify.send(instance.author, recipient=instance.annotation.author, verb='a proposé une révision sur votre annotation', action_object=instance, target=instance.annotation)
+
+
+def notify_users_on_accepted_revision(sender, instance, **kwargs):
+ from iconolab.models import AnnotationRevision
+ if sender == AnnotationRevision:
+ if instance.author != instance.annotation.author and instance.state in [AnnotationRevision.ACCEPTED, AnnotationRevision.STUDIED]:
+ notify.send(instance.annotation.author, recipient=instance.author, verb='a étudié votre révision', action_object=instance, target=instance.annotation)
+
+
+# Stats handlers connect
post_save.connect(increment_annotations_count)
post_save.connect(increment_stats_on_new_comments)
revision_created.connect(increment_stats_on_new_revision)
revision_accepted.connect(increment_accepted_revisions)
+# Notifications handlers connect
+comment_was_posted.connect(notify_users_on_new_comment)
+revision_created.connect(notify_users_on_new_revision)
+revision_accepted.connect(notify_users_on_accepted_revision)
\ No newline at end of file
--- a/src/iconolab/static/iconolab/css/iconolab.css Tue Aug 02 11:13:52 2016 +0200
+++ b/src/iconolab/static/iconolab/css/iconolab.css Wed Aug 03 15:47:03 2016 +0200
@@ -68,4 +68,39 @@
.pagination-shortcut{
cursor: pointer;
+}
+
+.badge-error {
+ background-color: #b94a48;
+}
+.badge-error:hover {
+ background-color: #953b39;
+}
+.badge-warning {
+ background-color: #f89406;
+}
+.badge-warning:hover {
+ background-color: #c67605;
+}
+.badge-success {
+ background-color: #468847;
+}
+.badge-success:hover {
+ background-color: #356635;
+}
+.badge-info {
+ background-color: #3a87ad;
+}
+.badge-info:hover {
+ background-color: #2d6987;
+}
+.badge-inverse {
+ background-color: #333333;
+}
+.badge-inverse:hover {
+ background-color: #1a1a1a;
+}
+
+.notif-badge{
+ margin-bottom: 5px;
}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/templates/iconolab/user_home.html Wed Aug 03 15:47:03 2016 +0200
@@ -0,0 +1,106 @@
+{% extends 'iconolab_base.html' %}
+
+{% load staticfiles %}
+
+{% load thumbnail %}
+
+{% load iconolab_tags %}
+{% load notifications_tags %}
+
+{% block content %}
+ <div id="user-profile-block" class="row" style="border: 1px solid gray;">
+ <div class="col-md-12">
+
+ <h3>{% if profile_user == request.user %}Mon espace:{% else %}Profil: {% endif %} {{profile_user.username}}</h3>
+ <div class="panel panel-default" style="padding-left: 10px; padding-right: 10px;">
+ {% if profile_user == request.user %}
+ <h4><span class="badge notif-badge {% if notifications.unread %}badge-error{% endif %}">{{notifications.unread.count}}</span> Notifications non lues
+ <a href=# class="btn btn-default btn-xs">Voir toutes mes notifications</a>
+ <a href=# class="btn btn-default btn-xs">Tout marquer comme lu</a>
+ </h4>
+ <div class="row">
+ <div class="col-md-12">
+ {% if notifications %}
+ <ul class="list-group">
+ {% for notification in notifications.unread %}
+ <a
+ {% if notification.target and notification.action_object %}
+ {% with notification.target as annotation %}
+ class="list-group-item"
+ {% if notification.action_object.get_comment_page %}
+ href="{% url 'annotation_detail' annotation.image.item.collection.name annotation.image.image_guid annotation.annotation_guid %}?page={{notification.action_object.get_comment_page}}#c{{notification.action_object.id}}"
+ {% else %}
+ href="{% url 'revision_detail' annotation.image.item.collection.name annotation.image.image_guid annotation.annotation_guid notification.action_object.revision_guid %}"
+ {% endif %}
+ {% endwith %}
+ {% else %}
+ class="list-group-item disabled"
+ {% endif %}>
+ <b>{{notification.actor.username}}</b> {{notification.verb}} <small> - {{notification.timesince}}</small>
+ </a>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ <hr>
+ </div>
+ </div>
+ {% endif %}
+ <div class="row">
+ <div class="col-md-6">
+ <h4>{% if profile_user == request.user %}Mes annotations:{% else %}Annotations de {{profile_user.username}}{% endif %} </h4>
+ <ul class="list-inline">
+ {% for annotation in user_annotations.all %}
+ <li>
+ <div class="panel panel-default" style="min-width: 375px;">
+ <div class="panel-heading">Title</div>
+ <div class="fragment-container" style="position:relative; display:inline-block">
+ {% thumbnail annotation.image.media "150x150" crop=False as im %}
+ <a href="{% url 'annotation_detail' annotation.image.item.collection.name annotation.image.image_guid annotation.annotation_guid %}">
+ <img v-el:small-image src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" />
+ <svg width="{{ im.width }}" height="{{ im.height }}" version="1.1" style="position:absolute; top:0px; left: 0px">
+ <g transform="matrix({% transform_matrix im_width=im.width im_height=im.height max_x=100 max_y=100 %})">
+ <path d="{{ annotation.current_revision.fragment|clean_path }}" opacity="0.7" fill="orange"></path>
+ </g>
+ </svg>
+ </a>
+ {% endthumbnail %}
+ </div>
+ <div class="annotation-detail" style="display:inline-block; position:relative; margin-right: 15px;">
+ <dl class="dl-horizontal">
+ <dt>Commentaires: </dt>
+ <dd><span class="badge">{{annotation.stats.comments_count}}</span></dd>
+ <dt>Révisions en attente:</dt>
+ <dd><span class="badge {% if annotation.awaiting_revisions_count > 0 %}badge-warning{% endif %}">{{annotation.awaiting_revisions_count}}</span></dd>
+ </dl>
+ </div>
+ </div>
+ </li>
+ {% endfor %}
+ </ul>
+ </div>
+ <div class="col-md-6">
+ <h4>{% if profile_user == request.user %}Mes autres contributions:{% else %}Contributions de {{profile_user.username}}{% endif %} </h4>
+ <dl>
+ <dt>
+ {% if profile_user == request.user %}
+ Annotations sur lesquelles j'ai commenté:
+ {% else %}
+ Annotations sur lesquelles {{profile_user.username}} a commenté:
+ {% endif %}
+ </dt>
+ <dd>{{user_comments_annotations.all}}</dd>
+ <dt>
+ {% if profile_user == request.user %}
+ Annotations sur lesquelles j'ai proposé des révisions
+ {% else %}
+ Annotations sur lesquelles {{profile_user.username}} a proposé des révisions:
+ {% endif %}
+ </dt>
+ <dd>{{user_revisions_annotations.all}}</dd>
+ </dl>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+{% endblock %}
\ No newline at end of file
--- a/src/iconolab/templates/iconolab/user_page.html Tue Aug 02 11:13:52 2016 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-{% extends 'iconolab_base.html' %}
-
-{% load staticfiles %}
-
-{% load thumbnail %}
-
-{% load iconolab_tags %}
-
-{% block content %}
- <div id="user-profile-block" class="row" style="border: 1px solid gray;padding-top: 10px;"></div>
-{% endblock %}
\ No newline at end of file
--- a/src/iconolab/templates/partials/header.html Tue Aug 02 11:13:52 2016 +0200
+++ b/src/iconolab/templates/partials/header.html Wed Aug 03 15:47:03 2016 +0200
@@ -24,8 +24,8 @@
</form>
<ul class="nav navbar-nav navbar-right">
- {% if user.is_authenticated %}
- <li><a href="{% url 'user_profile' %}">{{user.username}}: Mon espace</a></li>
+ {% if request.user.is_authenticated %}
+ <li><a href="{% url 'user_home' request.user.id %}">{{user.username}}: Mon espace</a></li>
<li><a href="{% url 'account:logout' %}">Se déconnecter</a></li>
{% else %}
<li><a href="{% url 'account:register' %}">Créer un compte</a></li>
--- a/src/iconolab/templates/partials/image_annotations_list.html Tue Aug 02 11:13:52 2016 +0200
+++ b/src/iconolab/templates/partials/image_annotations_list.html Wed Aug 03 15:47:03 2016 +0200
@@ -38,8 +38,8 @@
<td>{{ annotation.created|date:'d-m-Y' }}</td>
<td>{{ annotation.current_revision.created|date:'d-m-Y' }}</td>
<td>
- {% for contributor in annotation.stats.contributors %}
- {{ contributor }}{% if not forloop.last %}, {% endif %}
+ {% for contributor in annotation.stats.contributors.all %}
+ {{ contributor.username }}{% if not forloop.last %}, {% endif %}
{% endfor %}
</td>
<td>
--- a/src/iconolab/urls.py Tue Aug 02 11:13:52 2016 +0200
+++ b/src/iconolab/urls.py Wed Aug 03 15:47:03 2016 +0200
@@ -22,6 +22,7 @@
from django.conf.urls.static import static
from django.contrib.auth.decorators import login_required
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
+import notifications.urls
urlpatterns = [
url(r'^$', views.iconolab.RedirectView.as_view(url=reverse_lazy("home"))),
@@ -35,12 +36,13 @@
url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/edit$', login_required(views.iconolab.EditAnnotationView.as_view()), name='annotation_edit'),
url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/revisions/(?P<revision_guid>[^/]+)/detail', views.iconolab.ShowRevisionView.as_view(), name='revision_detail'),
url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/revisions/(?P<revision_guid>[^/]+)/merge$', login_required(views.iconolab.MergeProposalView.as_view()), name='annotation_merge'),
- url(r'^user/profile', login_required(views.iconolab.UserProfileView.as_view()), name="user_profile"),
+ url(r'^user/(?P<slug>[a-z0-9\-]+)/home/', views.iconolab.UserHomeView.as_view(), name="user_home"),
url(r'^errors/404', views.iconolab.NotFoundErrorView.as_view(), name="404error"),
url(r'^rest', include('restapi.urls')),
url(r'^account/', include('iconolab.auth.urls', namespace='account')),
url(r'^comments/', include('django_comments_xtd.urls')),
- url(r'^comments/annotation/post', views.comments.post_comment_iconolab, name="post_comment")
+ url(r'^comments/annotation/post', views.comments.post_comment_iconolab, name="post_comment"),
+ url('^user/notifications/', include(notifications.urls, namespace='notifications')),
]
urlpatterns += staticfiles_urlpatterns()
--- a/src/iconolab/views/comments.py Tue Aug 02 11:13:52 2016 +0200
+++ b/src/iconolab/views/comments.py Wed Aug 03 15:47:03 2016 +0200
@@ -7,6 +7,7 @@
from django_comments import signals
from django_comments.views.utils import next_redirect, confirmation_view
from django_comments.views.comments import CommentPostBadRequest
+from iconolab.models import MetaCategoryInfo
@csrf_protect
@require_POST
--- a/src/iconolab/views/iconolab.py Tue Aug 02 11:13:52 2016 +0200
+++ b/src/iconolab/views/iconolab.py Wed Aug 03 15:47:03 2016 +0200
@@ -1,7 +1,8 @@
from django.shortcuts import HttpResponse, get_object_or_404, render
from django.http import Http404
from django.contrib.auth.decorators import login_required
-from django.views.generic import View, RedirectView
+from django.contrib.auth.models import User
+from django.views.generic import View, DetailView, RedirectView
from django.views.generic.base import ContextMixin
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.core.urlresolvers import reverse
@@ -9,6 +10,7 @@
from django.contrib.contenttypes.models import ContentType
from django.contrib.sites.models import Site
from django.conf import settings
+from notifications.models import Notification
from iconolab.models import Annotation, AnnotationRevision, Collection, Item, Image, IconolabComment, MetaCategory, MetaCategoryInfo
from iconolab.forms.annotations import AnnotationRevisionForm
@@ -20,10 +22,39 @@
return render(request, 'iconolab/home.html', context)
-class UserProfileView(View):
+class UserHomeView(DetailView):
+ model = User
+ slug_field = "id"
+
+ def get_context_data(self, **kwargs):
+ context = super(UserHomeView, self).get_context_data(**kwargs)
+ return context
+
def get(self, request, *args, **kwargs):
- context = {}
- return render(request, 'iconolab/user_page.html', context)
+ self.object = self.get_object()
+ context = self.get_context_data()
+ profile_user = self.object
+ context["profile_user"] = profile_user
+ context["user_annotations"] = Annotation.objects.filter(author=profile_user).prefetch_related(
+ "current_revision",
+ "revisions",
+ "image",
+ "image__item",
+ "image__item__collection"
+ )
+ context["user_revisions_annotations"] = Annotation.objects.filter(revisions__author=profile_user).exclude(author=profile_user).prefetch_related(
+ "current_revision",
+ "revisions",
+ "image",
+ "image__item",
+ "image__item__collection"
+ ).distinct()
+ comments_annotations_str_id = IconolabComment.objects.filter(user=profile_user, content_type__app_label="iconolab", content_type__model="annotation").values_list("object_pk", flat=True)
+ comments_annotations_id = [int(str_id) for str_id in comments_annotations_str_id]
+ context["user_comments_annotations"] = Annotation.objects.filter(id__in=comments_annotations_id).exclude(author=profile_user).distinct()
+ if request.user.is_authenticated() and self.object == request.user:
+ context["notifications"] = Notification.objects.filter(recipient=request.user)
+ return render(request, 'iconolab/user_home.html', context)
class CollectionHomepageView(View, ContextMixin):