views.py 11 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# -*- coding:utf-8 -*
#
# Copyright 2016,2017
# - Skia <skia@libskia.so>
#
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
# http://ae.utbm.fr.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License a published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307, USA.
#
#

Skia's avatar
Skia committed
25
26
27
from django.shortcuts import render, get_object_or_404
from django.views.generic import ListView, DetailView, RedirectView
from django.views.generic.edit import UpdateView, CreateView, DeleteView
Skia's avatar
Skia committed
28
from django.views.generic.detail import SingleObjectMixin
Skia's avatar
Skia committed
29
30
31
32
33
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse, reverse_lazy
from django.utils import timezone
from django.conf import settings
from django import forms
Skia's avatar
Skia committed
34
from django.db import models
Skia's avatar
Skia committed
35
from django.core.exceptions import PermissionDenied
36
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
Skia's avatar
Skia committed
37

38
from ajax_select import make_ajax_form, make_ajax_field
Skia's avatar
Skia committed
39

40
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, CanCreateMixin, TabedViewMixin
41
from core.views.forms import MarkdownInput
42
from core.models import Page
Skia's avatar
Skia committed
43
from forum.models import Forum, ForumMessage, ForumTopic, ForumMessageMeta
Skia's avatar
Skia committed
44

Skia's avatar
Skia committed
45
class ForumMainView(ListView):
46
    queryset = Forum.objects.filter(parent=None).prefetch_related("children___last_message__author", "children___last_message__topic")
Skia's avatar
Skia committed
47
48
    template_name = "forum/main.jinja"

Skia's avatar
Skia committed
49
50
51
52
53
54
55
56
57
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()
58
59
            for m in request.user.read_messages.filter(date__lt=fi.last_read_date):
                m.readers.remove(request.user) # Clean up to keep table low in data
Skia's avatar
Skia committed
60
61
62
63
64
65
        except: pass
        return super(ForumMarkAllAsRead, self).get(request, *args, **kwargs)

class ForumLastUnread(ListView):
    model = ForumTopic
    template_name = "forum/last_unread.jinja"
Skia's avatar
Skia committed
66
    paginate_by = settings.SITH_FORUM_PAGE_LENGTH / 2
Skia's avatar
Skia committed
67
68

    def get_queryset(self):
69
70
71
        topic_list = self.model.objects.filter(_last_message__date__gt=self.request.user.forum_infos.last_read_date)\
                .exclude(_last_message__readers=self.request.user)\
                .order_by('-_last_message__date')\
Skia's avatar
Skia committed
72
73
                .select_related('_last_message__author', 'author')\
                .prefetch_related('forum__edit_groups')
74
        return topic_list
Skia's avatar
Skia committed
75

76
77
78
class ForumForm(forms.ModelForm):
    class Meta:
        model = Forum
Skia's avatar
Skia committed
79
        fields = ['name', 'parent', 'number', 'owner_club', 'is_category', 'edit_groups', 'view_groups']
80
81
82
    edit_groups = make_ajax_field(Forum, 'edit_groups', 'groups', help_text="")
    view_groups = make_ajax_field(Forum, 'view_groups', 'groups', help_text="")

83
class ForumCreateView(CanCreateMixin, CreateView):
Skia's avatar
Skia committed
84
    model = Forum
85
    form_class = ForumForm
Skia's avatar
Skia committed
86
87
88
89
    template_name = "core/create.jinja"

    def get_initial(self):
        init = super(ForumCreateView, self).get_initial()
Skia's avatar
Skia committed
90
91
92
        try:
            parent = Forum.objects.filter(id=self.request.GET['parent']).first()
            init['parent'] = parent
93
            init['owner_club'] = parent.owner_club
94
95
            init['edit_groups'] = parent.edit_groups.all()
            init['view_groups'] = parent.view_groups.all()
Skia's avatar
Skia committed
96
        except: pass
Skia's avatar
Skia committed
97
98
        return init

99
class ForumEditForm(ForumForm):
100
101
    recursive = forms.BooleanField(label=_("Apply rights and club owner recursively"), required=False)

102
class ForumEditView(CanEditPropMixin, UpdateView):
Skia's avatar
Skia committed
103
104
    model = Forum
    pk_url_kwarg = "forum_id"
105
    form_class = ForumEditForm
Skia's avatar
Skia committed
106
107
108
    template_name = "core/edit.jinja"
    success_url = reverse_lazy('forum:main')

109
110
111
112
113
114
115
116
117
118
119
120
    def form_valid(self, form):
        ret = super(ForumEditView, self).form_valid(form)
        if form.cleaned_data['recursive']:
            self.object.apply_rights_recursively()
        return ret

class ForumDeleteView(CanEditPropMixin, DeleteView):
    model = Forum
    pk_url_kwarg = "forum_id"
    template_name = "core/delete_confirm.jinja"
    success_url = reverse_lazy('forum:main')

121
class ForumDetailView(CanViewMixin, DetailView):
Skia's avatar
Skia committed
122
123
124
125
    model = Forum
    template_name = "forum/forum.jinja"
    pk_url_kwarg = "forum_id"

Skia's avatar
Skia committed
126
127
    def get_context_data(self, **kwargs):
        kwargs = super(ForumDetailView, self).get_context_data(**kwargs)
Skia's avatar
Skia committed
128
129
        qs = self.object.topics.order_by('-_last_message__date')\
                .select_related('_last_message__author', 'author')\
130
                .prefetch_related("forum__edit_groups")
Skia's avatar
Skia committed
131
132
133
134
135
136
137
138
139
        paginator = Paginator(qs,
                settings.SITH_FORUM_PAGE_LENGTH)
        page = self.request.GET.get('topic_page')
        try:
            kwargs["topics"] = paginator.page(page)
        except PageNotAnInteger:
            kwargs["topics"] = paginator.page(1)
        except EmptyPage:
            kwargs["topics"] = paginator.page(paginator.num_pages)
Skia's avatar
Skia committed
140
141
        return kwargs

142
143
144
145
class TopicForm(forms.ModelForm):
    class Meta:
        model = ForumMessage
        fields = ['title', 'message']
146
147
148
        widgets = {
            'message': MarkdownInput,
            }
Skia's avatar
Skia committed
149
    title = forms.CharField(required=True, label=_("Title"))
150

151
class ForumTopicCreateView(CanCreateMixin, CreateView):
Skia's avatar
Skia committed
152
    model = ForumMessage
153
    form_class = TopicForm
Skia's avatar
Skia committed
154
    template_name = "forum/reply.jinja"
Skia's avatar
Skia committed
155
156
157
158
159
160
161
162

    def dispatch(self, request, *args, **kwargs):
        self.forum = get_object_or_404(Forum, id=self.kwargs['forum_id'], is_category=False)
        if not request.user.can_view(self.forum):
            raise PermissionDenied
        return super(ForumTopicCreateView, self).dispatch(request, *args, **kwargs)

    def form_valid(self, form):
Krophil's avatar
Krophil committed
163
        topic = ForumTopic(_title=form.instance.title, author=self.request.user, forum=self.forum)
Skia's avatar
Skia committed
164
165
        topic.save()
        form.instance.topic = topic
Skia's avatar
Skia committed
166
167
168
        form.instance.author = self.request.user
        return super(ForumTopicCreateView, self).form_valid(form)

Skia's avatar
Skia committed
169
class ForumTopicEditView(CanEditMixin, UpdateView):
Skia's avatar
Skia committed
170
    model = ForumTopic
Skia's avatar
Skia committed
171
    fields = ['forum']
Skia's avatar
Skia committed
172
173
174
    pk_url_kwarg = "topic_id"
    template_name = "core/edit.jinja"

175
class ForumTopicDetailView(CanViewMixin, DetailView):
Skia's avatar
Skia committed
176
177
178
179
    model = ForumTopic
    pk_url_kwarg = "topic_id"
    template_name = "forum/topic.jinja"
    context_object_name = "topic"
Skia's avatar
Skia committed
180
    queryset = ForumTopic.objects.select_related('forum__parent')
Skia's avatar
Skia committed
181

Skia's avatar
Skia committed
182
183
184
    def get_context_data(self, **kwargs):
        kwargs = super(ForumTopicDetailView, self).get_context_data(**kwargs)
        try:
Skia's avatar
Skia committed
185
            msg = self.object.get_first_unread_message(self.request.user)
Skia's avatar
Skia committed
186
187
            kwargs['first_unread_message_id'] = msg.id
        except:
188
            kwargs['first_unread_message_id'] = float("inf")
189
190
        paginator = Paginator(self.object.messages.select_related('author__avatar_pict')\
                .prefetch_related('topic__forum__edit_groups', 'readers').order_by('date'),
191
192
                settings.SITH_FORUM_PAGE_LENGTH)
        page = self.request.GET.get('page')
Skia's avatar
Skia committed
193
        try:
194
195
196
197
198
            kwargs["msgs"] = paginator.page(page)
        except PageNotAnInteger:
            kwargs["msgs"] = paginator.page(1)
        except EmptyPage:
            kwargs["msgs"] = paginator.page(paginator.num_pages)
Skia's avatar
Skia committed
199
200
        return kwargs

201
202
203
204
205
206
207
208
209
class ForumMessageView(SingleObjectMixin, RedirectView):
    model = ForumMessage
    pk_url_kwarg = "message_id"
    permanent = False

    def get_redirect_url(self, *args, **kwargs):
        self.object = self.get_object()
        return self.object.get_url()

Skia's avatar
Skia committed
210
211
class ForumMessageEditView(CanEditMixin, UpdateView):
    model = ForumMessage
212
    form_class = forms.modelform_factory(model=ForumMessage, fields=['title', 'message',], widgets={'message': MarkdownInput})
213
    template_name = "forum/reply.jinja"
Skia's avatar
Skia committed
214
215
    pk_url_kwarg = "message_id"

Skia's avatar
Skia committed
216
217
218
219
    def form_valid(self, form):
        ForumMessageMeta(message=self.object, user=self.request.user, action="EDIT").save()
        return super(ForumMessageEditView, self).form_valid(form)

220
221
222
223
224
    def get_context_data(self, **kwargs):
        kwargs = super(ForumMessageEditView, self).get_context_data(**kwargs)
        kwargs['topic'] = self.object.topic
        return kwargs

Skia's avatar
Skia committed
225
226
227
228
229
230
class ForumMessageDeleteView(SingleObjectMixin, RedirectView):
    model = ForumMessage
    pk_url_kwarg = "message_id"
    permanent = False

    def get_redirect_url(self, *args, **kwargs):
Skia's avatar
Skia committed
231
        self.object = self.get_object()
Skia's avatar
Skia committed
232
233
234
235
236
237
238
239
240
241
        if self.object.can_be_moderated_by(self.request.user):
            ForumMessageMeta(message=self.object, user=self.request.user, action="DELETE").save()
        return self.object.get_absolute_url()

class ForumMessageUndeleteView(SingleObjectMixin, RedirectView):
    model = ForumMessage
    pk_url_kwarg = "message_id"
    permanent = False

    def get_redirect_url(self, *args, **kwargs):
Skia's avatar
Skia committed
242
        self.object = self.get_object()
Skia's avatar
Skia committed
243
244
245
246
        if self.object.can_be_moderated_by(self.request.user):
            ForumMessageMeta(message=self.object, user=self.request.user, action="UNDELETE").save()
        return self.object.get_absolute_url()

247
class ForumMessageCreateView(CanCreateMixin, CreateView):
Skia's avatar
Skia committed
248
    model = ForumMessage
249
    form_class = forms.modelform_factory(model=ForumMessage, fields=['title', 'message',], widgets={'message': MarkdownInput})
Skia's avatar
Skia committed
250
    template_name = "forum/reply.jinja"
Skia's avatar
Skia committed
251
252
253
254
255
256
257
258
259
260

    def dispatch(self, request, *args, **kwargs):
        self.topic = get_object_or_404(ForumTopic, id=self.kwargs['topic_id'])
        if not request.user.can_view(self.topic):
            raise PermissionDenied
        return super(ForumMessageCreateView, self).dispatch(request, *args, **kwargs)

    def get_initial(self):
        init = super(ForumMessageCreateView, self).get_initial()
        try:
Skia's avatar
Skia committed
261
262
263
264
            message = ForumMessage.objects.select_related('author').filter(id=self.request.GET['quote_id']).first()
            init['message'] = "> ##### %s\n" % (_("%(author)s said") % {'author': message.author.get_short_name()})
            init['message'] += "\n".join([
                "> " + line for line in message.message.split('\n')
Skia's avatar
Skia committed
265
                ])
Skia's avatar
Skia committed
266
267
268
            init['message'] += "\n\n"
        except Exception as e:
            print(repr(e))
Skia's avatar
Skia committed
269
270
271
272
273
274
275
        return init

    def form_valid(self, form):
        form.instance.topic = self.topic
        form.instance.author = self.request.user
        return super(ForumMessageCreateView, self).form_valid(form)

Skia's avatar
Skia committed
276
277
278
279
    def get_context_data(self, **kwargs):
        kwargs = super(ForumMessageCreateView, self).get_context_data(**kwargs)
        kwargs['topic'] = self.topic
        return kwargs
Skia's avatar
Skia committed
280