Commit 254126fd authored by Skia's avatar Skia

Add last unread function

parent 4cc57c18
Pipeline #746 passed with stage
in 3 minutes and 25 seconds
......@@ -18,7 +18,7 @@ from subscription.models import Subscription
from counter.models import Customer, ProductType, Product, Counter
from com.models import Sith, Weekmail
from election.models import Election, Role, Candidature, ElectionList
from forum.models import Forum, ForumMessage
from forum.models import Forum, ForumMessage, ForumTopic
class Command(BaseCommand):
......@@ -438,8 +438,10 @@ Welcome to the wiki page!
room.save()
Forum(name="AE", description="Réservé au bureau AE", parent=room).save()
Forum(name="BdF", description="Réservé au bureau BdF", parent=room).save()
Forum(name="Hall de discussions", description="Pour toutes les discussions", parent=room).save()
hall = Forum(name="Hall de discussions", description="Pour toutes les discussions", parent=room)
hall.save()
various = Forum(name="Divers", description="Pour causer de rien", is_category=True)
various.save()
Forum(name="Promos", description="Réservé aux Promos", parent=various).save()
ForumTopic(forum=hall)
......@@ -426,6 +426,16 @@ class User(AbstractBaseUser):
def subscribed(self):
return self.is_in_group(settings.SITH_MAIN_MEMBERS_GROUP)
@property
def forum_infos(self):
try:
return self._forum_infos
except:
from forum.models import ForumUserInfo
infos = ForumUserInfo(user=self)
infos.save()
return infos
class AnonymousUser(AuthAnonymousUser):
def __init__(self, request):
super(AnonymousUser, self).__init__()
......
......@@ -412,6 +412,9 @@ textarea {
margin: 2px;
background: skyblue;
}
.unread {
background: #e6ddad;
}
.message h5 {
font-size: 100%;
}
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
from django.conf import settings
from django.utils.timezone import utc
import datetime
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('forum', '0003_forum_owner_club'),
]
operations = [
migrations.CreateModel(
name='ForumUserInfo',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)),
('last_read_date', models.DateTimeField(verbose_name='last read date', default=datetime.datetime(1999, 1, 1, 0, 0, tzinfo=utc))),
('user', models.OneToOneField(related_name='_forum_infos', to=settings.AUTH_USER_MODEL)),
],
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('forum', '0004_forumuserinfo'),
]
operations = [
migrations.AddField(
model_name='forumuserinfo',
name='read_messages',
field=models.ManyToManyField(to='forum.ForumMessage', related_name='readers', verbose_name='read messages'),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('forum', '0005_forumuserinfo_read_messages'),
]
operations = [
migrations.RemoveField(
model_name='forumuserinfo',
name='read_messages',
),
migrations.AddField(
model_name='forummessage',
name='readers',
field=models.ManyToManyField(to=settings.AUTH_USER_MODEL, related_name='read_messages', verbose_name='readers'),
),
]
......@@ -7,6 +7,9 @@ from django.db import IntegrityError, transaction
from django.core.urlresolvers import reverse
from django.utils import timezone
from datetime import datetime
import pytz
from core.models import User, MetaGroup, Group, SithFile
from club.models import Club
......@@ -136,10 +139,14 @@ class ForumMessage(models.Model):
title = models.CharField(_("title"), default="", max_length=64, blank=True)
message = models.TextField(_("message"), default="")
date = models.DateTimeField(_('date'), default=timezone.now)
readers = models.ManyToManyField(User, related_name="read_messages", verbose_name=_("readers"))
class Meta:
ordering = ['id']
def __str__(self):
return "%s" % (self.title)
def is_owned_by(self, user):
return self.topic.is_owned_by(user) or user.id == self.author.id
......@@ -150,5 +157,14 @@ class ForumMessage(models.Model):
return user.can_view(self.topic)
def get_absolute_url(self):
return self.topic.get_absolute_url()
return self.topic.get_absolute_url() + "#first_unread"
def mark_as_read(self, user):
self.readers.add(user)
class ForumUserInfo(models.Model):
user = models.OneToOneField(User, related_name="_forum_infos")
last_read_date = models.DateTimeField(_('last read date'), default=datetime(year=settings.SITH_SCHOOL_START_YEAR,
month=1, day=1, tzinfo=pytz.UTC))
# read_messages = models.ManyToManyField(ForumMessage, related_name="readers", verbose_name=_("read messages"))
{% extends "core/base.jinja" %}
{% from 'forum/macros.jinja' import display_forum %}
{% from 'core/macros.jinja' import user_profile_link %}
{% from 'forum/macros.jinja' import display_forum, display_topic %}
{% block title %}
{{ forum }}
{% endblock %}
{% block content %}
<div>
......@@ -21,34 +24,7 @@
{{ display_forum(f, user) }}
{% endfor %}
{% for t in topics %}
<div class="topic">
<div class="ib w_medium">
<a class="ib w_big" href="{{ url('forum:view_topic', topic_id=t.id) }}">
<h5>{{ t.title }}</h5>
<p>{{ t.description }}</p>
</a>
{% if user.is_owner(t) %}
<div class="ib" style="text-align: center;">
<a href="{{ url('forum:edit_topic', topic_id=t.id) }}">Edit</a>
</div>
{% endif %}
</div>
<div class="ib w_medium">
<div class="ib w_medium">
<div class="ib w_medium" style="text-align: center;">
{{ user_profile_link(t.author) }}
</div>
<div class="ib w_medium" style="text-align: center;">
{{ t.messages.count() }}
</div>
</div>
<div class="ib w_medium" style="text-align: center;">
{% set last_msg = t.messages.order_by('id').last() %}
{{ user_profile_link(last_msg.author) }} <br/>
{{ last_msg.date|date(DATETIME_FORMAT) }} {{ last_msg.date|time(DATETIME_FORMAT) }}
</div>
</div>
</div>
{{ display_topic(t, user) }}
{% endfor %}
{% endblock %}
......
{% extends "core/base.jinja" %}
{% from 'forum/macros.jinja' import display_topic %}
{% block title %}
{% trans %}Last unread messages{% endtrans %}
{% endblock %}
{% block content %}
<p>
<a href="{{ url('forum:main') }}">Forum</a> >
</p>
<h3>{% trans %}Forum{% endtrans %}</h3>
<h4>{% trans %}Last unread messages{% endtrans %}</h4>
<p>
<a class="ib" href="{{ url('forum:mark_all_as_read') }}">{% trans %}Mark all as read{% endtrans %}</a>
<a class="ib" href="{{ url('forum:last_unread') }}">{% trans %}Refresh{% endtrans %}</a>
</p>
{% for t in forumtopic_list %}
{{ display_topic(t, user, True) }}
{% endfor %}
{% endblock %}
{% from 'core/macros.jinja' import user_profile_link %}
{% macro display_forum(forum, user) %}
<div class="forum {% if forum.is_category %}category{% endif %}">
<div class="ib w_big">
......@@ -35,4 +37,38 @@
</div>
{% endmacro %}
{% macro display_topic(topic, user, first_unread=False) %}
<div class="topic">
<div class="ib w_medium">
{% if first_unread %}
<a class="ib w_big" href="{{ url('forum:view_topic', topic_id=topic.id) }}#first_unread">
{% else %}
<a class="ib w_big" href="{{ url('forum:view_topic', topic_id=topic.id) }}">
{% endif %}
<h5>{{ topic.title }}</h5>
<p>{{ topic.description }}</p>
</a>
{% if user.is_owner(topic) %}
<div class="ib" style="text-align: center;">
<a href="{{ url('forum:edit_topic', topic_id=topic.id) }}">{% trans %}Edit{% endtrans %}</a>
</div>
{% endif %}
</div>
<div class="ib w_medium">
<div class="ib w_medium">
<div class="ib w_medium" style="text-align: center;">
{{ user_profile_link(topic.author) }}
</div>
<div class="ib w_medium" style="text-align: center;">
{{ topic.messages.count() }}
</div>
</div>
<div class="ib w_medium" style="text-align: center;">
{% set last_msg = topic.messages.order_by('id').last() %}
{{ user_profile_link(last_msg.author) }} <br/>
{{ last_msg.date|date(DATETIME_FORMAT) }} {{ last_msg.date|time(DATETIME_FORMAT) }}
</div>
</div>
</div>
{% endmacro %}
......@@ -2,16 +2,25 @@
{% from 'core/macros.jinja' import user_profile_link %}
{% from 'forum/macros.jinja' import display_forum %}
{% block title %}
{% trans %}Forum{% endtrans %}
{% endblock %}
{% block content %}
<p>
<a href="{{ url('forum:main') }}">Forum</a> >
</p>
<h3>{% trans %}Forum{% endtrans %}</h3>
<p>
<a class="ib" href="{{ url('forum:last_unread') }}">{% trans %}View last unread messages{% endtrans %}</a>
<a class="ib" href="{{ url('forum:mark_all_as_read') }}">{% trans %}Mark all as read{% endtrans %}</a>
<a class="ib" href="{{ url('forum:main') }}">{% trans %}Refresh{% endtrans %}</a>
</p>
{% if user.is_in_group(settings.SITH_GROUP_FORUM_ADMIN_ID) or user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) %}
<a href="{{ url('forum:new_forum') }}">New forum</a>
{% endif %}
<p>
<a href="{{ url('forum:new_forum') }}">{% trans %}New forum{% endtrans %}</a>
</p>
{% endif %}
{% for f in forum_list %}
<div style="padding: 4px; margin: 4px">
{{ display_forum(f, user) }}
......
{% extends "core/base.jinja" %}
{% from 'core/macros.jinja' import user_profile_link %}
{% block title %}
{{ topic }}
{% endblock %}
{% block head %}
{{ super() }}
<style type="text/css" media="all">
......@@ -32,8 +36,16 @@
<h3>{{ topic.title }}</h3>
<p>{{ topic.description }}</p>
<p><a href="{{ url('forum:new_message', topic_id=topic.id) }}">Reply</a></p>
{% set unread = False %}
{% for m in topic.messages.all() %}
{% if m.id == first_unread_message_id %}
<div class="message unread" id="first_unread">
{% set unread = True %}
{% elif unread %}
<div class="message unread">
{% else %}
<div class="message">
{% endif %}
<div class="msg_author">
{% if m.author.profile_pict %}
<img src="{{ m.author.profile_pict.get_download_url() }}" alt="{% trans %}Profile{% endtrans %}" id="picture" />
......@@ -64,6 +76,7 @@
</div>
</div>
</div>
{# m.mark_as_read(user) or "" #}
{% endfor %}
{% endblock %}
......
......@@ -5,6 +5,8 @@ from forum.views import *
urlpatterns = [
url(r'^$', ForumMainView.as_view(), name='main'),
url(r'^new_forum$', ForumCreateView.as_view(), name='new_forum'),
url(r'^mark_all_as_read$', ForumMarkAllAsRead.as_view(), name='mark_all_as_read'),
url(r'^last_unread$', ForumLastUnread.as_view(), name='last_unread'),
url(r'^(?P<forum_id>[0-9]+)$', ForumDetailView.as_view(), name='view_forum'),
url(r'^(?P<forum_id>[0-9]+)/edit$', ForumEditView.as_view(), name='edit_forum'),
url(r'^(?P<forum_id>[0-9]+)/delete$', ForumDeleteView.as_view(), name='delete_forum'),
......
......@@ -16,6 +16,29 @@ class ForumMainView(CanViewMixin, ListView):
queryset = Forum.objects.filter(parent=None)
template_name = "forum/main.jinja"
class ForumMarkAllAsRead(RedirectView):
permanent = False
url = reverse_lazy('forum:last_unread')
def get(self, request, *args, **kwargs):
try:
fi = request.user.forum_infos
fi.last_read_date = timezone.now()
fi.save()
except: pass
return super(ForumMarkAllAsRead, self).get(request, *args, **kwargs)
class ForumLastUnread(ListView):
model = ForumTopic
template_name = "forum/last_unread.jinja"
def get_queryset(self):
l = ForumMessage.objects.exclude(readers=self.request.user).filter(
date__gt=self.request.user.forum_infos.last_read_date).values_list('topic') # TODO try to do better
return self.model.objects.filter(id__in=l).annotate(models.Max('messages__date')).order_by('-messages__date__max')
# return self.model.objects.exclude(messages__readers=self.request.user).distinct().annotate(
# models.Max('messages__date')).order_by('-messages__date__max')
class ForumCreateView(CanCreateMixin, CreateView):
model = Forum
fields = ['name', 'parent', 'owner_club', 'is_category', 'edit_groups', 'view_groups']
......@@ -95,6 +118,15 @@ class ForumTopicDetailView(CanViewMixin, DetailView):
template_name = "forum/topic.jinja"
context_object_name = "topic"
def get_context_data(self, **kwargs):
kwargs = super(ForumTopicDetailView, self).get_context_data(**kwargs)
msg = self.object.messages.exclude(readers=self.request.user).order_by('id').first()
try:
kwargs['first_unread_message_id'] = msg.id
except:
kwargs['first_unread_message_id'] = -1
return kwargs
class ForumMessageEditView(CanEditMixin, UpdateView):
model = ForumMessage
fields = ['title', 'message']
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment