mirror of
https://github.com/ae-utbm/sith.git
synced 2024-11-22 14:13:21 +00:00
Add last unread function
This commit is contained in:
parent
4cc57c183e
commit
254126fd79
@ -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%;
|
||||
}
|
||||
|
26
forum/migrations/0004_forumuserinfo.py
Normal file
26
forum/migrations/0004_forumuserinfo.py
Normal file
@ -0,0 +1,26 @@
|
||||
# -*- 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)),
|
||||
],
|
||||
),
|
||||
]
|
19
forum/migrations/0005_forumuserinfo_read_messages.py
Normal file
19
forum/migrations/0005_forumuserinfo_read_messages.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- 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'),
|
||||
),
|
||||
]
|
25
forum/migrations/0006_auto_20170128_2243.py
Normal file
25
forum/migrations/0006_auto_20170128_2243.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- 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"))
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
{% 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 %}
|
||||
|
||||
|
24
forum/templates/forum/last_unread.jinja
Normal file
24
forum/templates/forum/last_unread.jinja
Normal file
@ -0,0 +1,24 @@
|
||||
{% 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 %}
|
||||
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
{% 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>
|
||||
{% 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 %}
|
||||
<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) %}
|
||||
<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) }}
|
||||
|
@ -1,6 +1,10 @@
|
||||
{% 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']
|
||||
|
Loading…
Reference in New Issue
Block a user