views.py 9.7 KB
Newer Older
Sli's avatar
Sli committed
1
2
# -*- coding:utf-8 -*
#
3
# Copyright 2019
Sli's avatar
Sli committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# - Sli <antoine@bartuccio.fr>
#
# 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.
#
#

Sli's avatar
Sli committed
25
26
27
28
29
30
31
32
from django.views.generic import (
    CreateView,
    DeleteView,
    UpdateView,
    ListView,
    FormView,
    View,
)
33
from django.utils import html
34
from django.http import HttpResponse
35
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
36
from django.urls import reverse_lazy, reverse
Sli's avatar
Sli committed
37
from django.shortcuts import get_object_or_404
38
from django.conf import settings
Sli's avatar
Sli committed
39

Sli's avatar
Sli committed
40
41
42
from haystack.query import SearchQuerySet
from rest_framework.renderers import JSONRenderer

Sli's avatar
Sli committed
43
44
45
46
47
48
49
from core.views import (
    DetailFormView,
    CanCreateMixin,
    CanEditMixin,
    CanViewMixin,
    CanEditPropMixin,
)
50
from core.models import RealGroup, Notification
Sli's avatar
Sli committed
51

Sli's avatar
Sli committed
52
53
54
55
56
57
from pedagogy.forms import (
    UVForm,
    UVCommentForm,
    UVCommentReportForm,
    UVCommentModerationForm,
)
Sli's avatar
Sli committed
58
from pedagogy.models import UV, UVComment, UVCommentReport, UVSerializer
Sli's avatar
Sli committed
59

Sli's avatar
Sli committed
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# Some mixins


class CanCreateUVFunctionMixin(View):
    """
    Add the function can_create_uv(user) into the template
    """

    @staticmethod
    def can_create_uv(user):
        """
        Creates a dummy instance of UV and test is_owner
        """
        return user.is_owner(UV())

    def get_context_data(self, **kwargs):
        """
        Pass the function to the template
        """
        kwargs = super(CanCreateUVFunctionMixin, self).get_context_data(**kwargs)
        kwargs["can_create_uv"] = self.can_create_uv
        return kwargs


# Acutal views

Sli's avatar
Sli committed
86

Sli's avatar
Sli committed
87
class UVDetailFormView(CanViewMixin, CanCreateUVFunctionMixin, DetailFormView):
Sli's avatar
Sli committed
88
89
90
91
92
    """
    Dispaly every comment of an UV and detailed infos about it
    Allow to comment the UV
    """

Sli's avatar
Sli committed
93
94
95
96
    model = UV
    pk_url_kwarg = "uv_id"
    template_name = "pedagogy/uv_detail.jinja"
    form_class = UVCommentForm
Sli's avatar
Sli committed
97

98
99
100
101
    def get_form_kwargs(self):
        kwargs = super(UVDetailFormView, self).get_form_kwargs()
        kwargs["author_id"] = self.request.user.id
        kwargs["uv_id"] = self.get_object().id
102
        kwargs["is_creation"] = True
103
104
105
106
107
108
109
110
111
112
113
        return kwargs

    def form_valid(self, form):
        form.save()
        return super(UVDetailFormView, self).form_valid(form)

    def get_success_url(self):
        return reverse_lazy(
            "pedagogy:uv_detail", kwargs={"uv_id": self.get_object().id}
        )

Sli's avatar
Sli committed
114

115
class UVCommentUpdateView(CanEditPropMixin, UpdateView):
Sli's avatar
Sli committed
116
    """
117
    Allow edit of a given comment
Sli's avatar
Sli committed
118
119
    """

120
121
122
123
124
125
126
    model = UVComment
    form_class = UVCommentForm
    pk_url_kwarg = "comment_id"
    template_name = "core/edit.jinja"

    def get_form_kwargs(self):
        kwargs = super(UVCommentUpdateView, self).get_form_kwargs()
127
128
129
        obj = self.get_object()
        kwargs["author_id"] = obj.author.id
        kwargs["uv_id"] = obj.uv.id
130
        kwargs["is_creation"] = False
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

        return kwargs

    def get_success_url(self):
        return reverse_lazy("pedagogy:uv_detail", kwargs={"uv_id": self.object.uv.id})


class UVCommentDeleteView(CanEditPropMixin, DeleteView):
    """
    Allow delete of a given comment
    """

    model = UVComment
    pk_url_kwarg = "comment_id"
    template_name = "core/delete_confirm.jinja"

    def get_success_url(self):
        return reverse_lazy("pedagogy:uv_detail", kwargs={"uv_id": self.object.uv.id})
Sli's avatar
Sli committed
149
150


Sli's avatar
Sli committed
151
class UVListView(CanViewMixin, CanCreateUVFunctionMixin, ListView):
Sli's avatar
Sli committed
152
153
154
155
    """
    UV guide main page
    """

Sli's avatar
Sli committed
156
157
158
159
160
    # This is very basic and is prone to changment

    model = UV
    ordering = ["code"]
    template_name = "pedagogy/guide.jinja"
Sli's avatar
Sli committed
161

162
163
164
    def get(self, *args, **kwargs):
        if not self.request.GET.get("json", None):
            # Return normal full template response
165
            return super(UVListView, self).get(*args, **kwargs)
166
167
168

        # Return serialized response
        return HttpResponse(
Sli's avatar
Sli committed
169
            JSONRenderer().render(UVSerializer(self.get_queryset(), many=True).data),
170
171
172
            content_type="application/json",
        )

173
    def get_queryset(self):
Sli's avatar
Sli committed
174
        queryset = super(UVListView, self).get_queryset()
175
        search = self.request.GET.get("search", None)
176

Sli's avatar
Sli committed
177
178
179
180
181
182
183
184
185
186
        additional_filters = {}

        for filter_type in ["credit_type", "language", "department"]:
            arg = self.request.GET.get(filter_type, None)
            if arg:
                additional_filters[filter_type] = arg

        semester = self.request.GET.get("semester", None)
        if semester:
            if semester in ["AUTUMN", "SPRING"]:
Sli's avatar
Sli committed
187
                additional_filters["semester__in"] = [semester, "AUTUMN_AND_SPRING"]
Sli's avatar
Sli committed
188
189
190
            else:
                additional_filters["semester"] = semester

Sli's avatar
Sli committed
191
        queryset = queryset.filter(**additional_filters)
192
        if not search:
Sli's avatar
Sli committed
193
194
195
196
            return queryset

        if len(search) == 1:
            # It's a search with only one letter
Sli's avatar
Sli committed
197
            # Haystack doesn't work well with only one letter
198
            return queryset.filter(code__istartswith=search)
199
200

        try:
Sli's avatar
Sli committed
201
            qs = (
202
203
                SearchQuerySet()
                .models(self.model)
204
                .autocomplete(auto=html.escape(search))
205
206
207
208
            )
        except TypeError:
            return self.model.objects.none()

Sli's avatar
Sli committed
209
        return queryset.filter(id__in=([o.object.id for o in qs]))
210

Sli's avatar
Sli committed
211

Sli's avatar
Sli committed
212
class UVCommentReportCreateView(CanCreateMixin, CreateView):
Sli's avatar
Sli committed
213
214
215
216
    """
    Create a new report for an inapropriate comment
    """

Sli's avatar
Sli committed
217
218
219
    model = UVCommentReport
    form_class = UVCommentReportForm
    template_name = "core/edit.jinja"
Sli's avatar
Sli committed
220

Sli's avatar
Sli committed
221
222
223
    def dispatch(self, request, *args, **kwargs):
        self.uv_comment = get_object_or_404(UVComment, pk=kwargs["comment_id"])
        return super(UVCommentReportCreateView, self).dispatch(request, *args, **kwargs)
Sli's avatar
Sli committed
224

Sli's avatar
Sli committed
225
226
227
228
229
    def get_form_kwargs(self):
        kwargs = super(UVCommentReportCreateView, self).get_form_kwargs()
        kwargs["reporter_id"] = self.request.user.id
        kwargs["comment_id"] = self.uv_comment.id
        return kwargs
Sli's avatar
Sli committed
230

231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
    def form_valid(self, form):
        resp = super(UVCommentReportCreateView, self).form_valid(form)

        # Send a message to moderation admins
        for user in (
            RealGroup.objects.filter(id=settings.SITH_GROUP_PEDAGOGY_ADMIN_ID)
            .first()
            .users.all()
        ):
            if not user.notifications.filter(
                type="PEDAGOGY_MODERATION", viewed=False
            ).exists():
                Notification(
                    user=user,
                    url=reverse("pedagogy:moderation"),
                    type="PEDAGOGY_MODERATION",
                ).save()

        return resp

Sli's avatar
Sli committed
251
252
253
254
    def get_success_url(self):
        return reverse_lazy(
            "pedagogy:uv_detail", kwargs={"uv_id": self.uv_comment.uv.id}
        )
Sli's avatar
Sli committed
255
256


Sli's avatar
Sli committed
257
class UVModerationFormView(FormView):
Sli's avatar
Sli committed
258
    """
Sli's avatar
Sli committed
259
    Moderation interface (Privileged)
Sli's avatar
Sli committed
260
261
    """

Sli's avatar
Sli committed
262
263
264
265
266
267
268
269
270
271
    form_class = UVCommentModerationForm
    template_name = "pedagogy/moderation.jinja"

    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_owner(UV()):
            raise PermissionDenied
        return super(UVModerationFormView, self).dispatch(request, *args, **kwargs)

    def form_valid(self, form):
        form_clean = form.clean()
272
        for report in form_clean.get("accepted_reports", []):
273
274
275
276
277
            try:
                report.comment.delete()  # Delete the related comment
            except ObjectDoesNotExist:
                # To avoid errors when two reports points the same comment
                pass
278
        for report in form_clean.get("denied_reports", []):
279
280
281
282
283
            try:
                report.delete()  # Delete the report itself
            except ObjectDoesNotExist:
                # To avoid errors when two reports points the same comment
                pass
Sli's avatar
Sli committed
284
285
286
287
        return super(UVModerationFormView, self).form_valid(form)

    def get_success_url(self):
        return reverse_lazy("pedagogy:moderation")
Sli's avatar
Sli committed
288
289


Sli's avatar
Sli committed
290
class UVCreateView(CanCreateMixin, CreateView):
Sli's avatar
Sli committed
291
292
293
294
    """
    Add a new UV (Privileged)
    """

Sli's avatar
Sli committed
295
296
    model = UV
    form_class = UVForm
tleb's avatar
tleb committed
297
    template_name = "pedagogy/uv_create.jinja"
Sli's avatar
Sli committed
298
299
300
301
302
303
304
305

    def get_form_kwargs(self):
        kwargs = super(UVCreateView, self).get_form_kwargs()
        kwargs["author_id"] = self.request.user.id
        return kwargs

    def get_success_url(self):
        return reverse_lazy("pedagogy:uv_detail", kwargs={"uv_id": self.object.id})
Sli's avatar
Sli committed
306
307


Sli's avatar
Sli committed
308
class UVDeleteView(CanEditPropMixin, DeleteView):
Sli's avatar
Sli committed
309
310
311
312
    """
    Allow to delete an UV (Privileged)
    """

Sli's avatar
Sli committed
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
    model = UV
    pk_url_kwarg = "uv_id"
    template_name = "core/delete_confirm.jinja"

    def get_success_url(self):
        return reverse_lazy("pedagogy:guide")


class UVUpdateView(CanEditPropMixin, UpdateView):
    """
    Allow to edit an UV (Privilegied)
    """

    model = UV
    form_class = UVForm
    pk_url_kwarg = "uv_id"
    template_name = "core/edit.jinja"

    def get_form_kwargs(self):
        kwargs = super(UVUpdateView, self).get_form_kwargs()
333
334
        obj = self.get_object()
        kwargs["author_id"] = obj.author.id
Sli's avatar
Sli committed
335
336
337
338
        return kwargs

    def get_success_url(self):
        return reverse_lazy("pedagogy:uv_detail", kwargs={"uv_id": self.object.id})