2019-05-16 14:51:30 +00:00
|
|
|
#
|
2019-09-04 18:49:17 +00:00
|
|
|
# Copyright 2019
|
2019-05-16 14:51:30 +00:00
|
|
|
# - 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.
|
|
|
|
#
|
|
|
|
#
|
|
|
|
|
2024-06-24 11:07:36 +00:00
|
|
|
from django.conf import settings
|
|
|
|
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
|
|
|
|
from django.http import HttpResponse
|
|
|
|
from django.shortcuts import get_object_or_404
|
|
|
|
from django.urls import reverse, reverse_lazy
|
|
|
|
from django.utils import html
|
2019-06-15 22:04:36 +00:00
|
|
|
from django.views.generic import (
|
|
|
|
CreateView,
|
|
|
|
DeleteView,
|
|
|
|
FormView,
|
2024-06-24 11:07:36 +00:00
|
|
|
ListView,
|
|
|
|
UpdateView,
|
2019-06-15 22:04:36 +00:00
|
|
|
View,
|
|
|
|
)
|
2019-07-05 18:11:33 +00:00
|
|
|
from haystack.query import SearchQuerySet
|
|
|
|
from rest_framework.renderers import JSONRenderer
|
|
|
|
|
2024-06-24 11:07:36 +00:00
|
|
|
from core.models import Notification, RealGroup
|
2019-06-15 15:01:25 +00:00
|
|
|
from core.views import (
|
|
|
|
CanCreateMixin,
|
|
|
|
CanEditPropMixin,
|
2024-06-24 11:07:36 +00:00
|
|
|
CanViewMixin,
|
|
|
|
DetailFormView,
|
2019-06-15 15:01:25 +00:00
|
|
|
)
|
2019-06-20 10:15:12 +00:00
|
|
|
from pedagogy.forms import (
|
|
|
|
UVCommentForm,
|
|
|
|
UVCommentModerationForm,
|
2024-06-24 11:07:36 +00:00
|
|
|
UVCommentReportForm,
|
|
|
|
UVForm,
|
2019-06-20 10:15:12 +00:00
|
|
|
)
|
2019-07-05 18:11:33 +00:00
|
|
|
from pedagogy.models import UV, UVComment, UVCommentReport, UVSerializer
|
2019-05-16 14:51:30 +00:00
|
|
|
|
2019-06-15 22:04:36 +00:00
|
|
|
# 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
|
|
|
|
"""
|
2024-06-27 12:46:43 +00:00
|
|
|
kwargs = super().get_context_data(**kwargs)
|
2019-06-15 22:04:36 +00:00
|
|
|
kwargs["can_create_uv"] = self.can_create_uv
|
|
|
|
return kwargs
|
|
|
|
|
|
|
|
|
|
|
|
# Acutal views
|
|
|
|
|
2019-05-16 14:51:30 +00:00
|
|
|
|
2019-06-16 00:19:56 +00:00
|
|
|
class UVDetailFormView(CanViewMixin, CanCreateUVFunctionMixin, DetailFormView):
|
2019-05-16 14:51:30 +00:00
|
|
|
"""
|
|
|
|
Dispaly every comment of an UV and detailed infos about it
|
|
|
|
Allow to comment the UV
|
|
|
|
"""
|
|
|
|
|
2019-06-16 00:19:56 +00:00
|
|
|
model = UV
|
|
|
|
pk_url_kwarg = "uv_id"
|
|
|
|
template_name = "pedagogy/uv_detail.jinja"
|
|
|
|
form_class = UVCommentForm
|
2019-05-16 14:51:30 +00:00
|
|
|
|
2019-06-16 15:02:45 +00:00
|
|
|
def get_form_kwargs(self):
|
2024-06-27 12:46:43 +00:00
|
|
|
kwargs = super().get_form_kwargs()
|
2019-06-16 15:02:45 +00:00
|
|
|
kwargs["author_id"] = self.request.user.id
|
|
|
|
kwargs["uv_id"] = self.get_object().id
|
2019-09-04 18:49:17 +00:00
|
|
|
kwargs["is_creation"] = True
|
2019-06-16 15:02:45 +00:00
|
|
|
return kwargs
|
|
|
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
form.save()
|
2024-06-27 12:46:43 +00:00
|
|
|
return super().form_valid(form)
|
2019-06-16 15:02:45 +00:00
|
|
|
|
|
|
|
def get_success_url(self):
|
|
|
|
return reverse_lazy(
|
|
|
|
"pedagogy:uv_detail", kwargs={"uv_id": self.get_object().id}
|
|
|
|
)
|
|
|
|
|
2019-05-16 14:51:30 +00:00
|
|
|
|
2019-06-16 15:02:45 +00:00
|
|
|
class UVCommentUpdateView(CanEditPropMixin, UpdateView):
|
2019-05-16 14:51:30 +00:00
|
|
|
"""
|
2019-06-16 15:02:45 +00:00
|
|
|
Allow edit of a given comment
|
2019-05-16 14:51:30 +00:00
|
|
|
"""
|
|
|
|
|
2019-06-16 15:02:45 +00:00
|
|
|
model = UVComment
|
|
|
|
form_class = UVCommentForm
|
|
|
|
pk_url_kwarg = "comment_id"
|
|
|
|
template_name = "core/edit.jinja"
|
|
|
|
|
|
|
|
def get_form_kwargs(self):
|
2024-06-27 12:46:43 +00:00
|
|
|
kwargs = super().get_form_kwargs()
|
2019-06-16 16:34:11 +00:00
|
|
|
obj = self.get_object()
|
|
|
|
kwargs["author_id"] = obj.author.id
|
|
|
|
kwargs["uv_id"] = obj.uv.id
|
2019-09-04 18:49:17 +00:00
|
|
|
kwargs["is_creation"] = False
|
2019-06-16 15:02:45 +00:00
|
|
|
|
|
|
|
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})
|
2019-05-16 14:51:30 +00:00
|
|
|
|
|
|
|
|
2019-06-15 22:04:36 +00:00
|
|
|
class UVListView(CanViewMixin, CanCreateUVFunctionMixin, ListView):
|
2019-05-16 14:51:30 +00:00
|
|
|
"""
|
|
|
|
UV guide main page
|
|
|
|
"""
|
|
|
|
|
2019-06-15 21:31:31 +00:00
|
|
|
# This is very basic and is prone to changment
|
|
|
|
|
|
|
|
model = UV
|
|
|
|
ordering = ["code"]
|
|
|
|
template_name = "pedagogy/guide.jinja"
|
2019-05-16 14:51:30 +00:00
|
|
|
|
2019-06-18 22:56:59 +00:00
|
|
|
def get(self, *args, **kwargs):
|
|
|
|
if not self.request.GET.get("json", None):
|
|
|
|
# Return normal full template response
|
2024-06-27 12:46:43 +00:00
|
|
|
return super().get(*args, **kwargs)
|
2019-06-18 22:56:59 +00:00
|
|
|
|
|
|
|
# Return serialized response
|
|
|
|
return HttpResponse(
|
2019-07-05 18:11:33 +00:00
|
|
|
JSONRenderer().render(UVSerializer(self.get_queryset(), many=True).data),
|
2019-06-18 22:56:59 +00:00
|
|
|
content_type="application/json",
|
|
|
|
)
|
|
|
|
|
2019-06-18 19:41:11 +00:00
|
|
|
def get_queryset(self):
|
2024-06-27 12:46:43 +00:00
|
|
|
queryset = super().get_queryset()
|
2019-06-18 23:53:02 +00:00
|
|
|
search = self.request.GET.get("search", None)
|
2019-06-18 19:41:11 +00:00
|
|
|
|
2019-06-18 23:26:11 +00:00
|
|
|
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"]:
|
2019-07-05 14:40:02 +00:00
|
|
|
additional_filters["semester__in"] = [semester, "AUTUMN_AND_SPRING"]
|
2019-06-18 23:26:11 +00:00
|
|
|
else:
|
|
|
|
additional_filters["semester"] = semester
|
|
|
|
|
2019-06-19 00:00:00 +00:00
|
|
|
queryset = queryset.filter(**additional_filters)
|
2019-06-18 23:53:02 +00:00
|
|
|
if not search:
|
2019-06-19 00:00:00 +00:00
|
|
|
return queryset
|
|
|
|
|
|
|
|
if len(search) == 1:
|
|
|
|
# It's a search with only one letter
|
2019-07-10 10:12:56 +00:00
|
|
|
# Haystack doesn't work well with only one letter
|
2019-07-07 16:55:23 +00:00
|
|
|
return queryset.filter(code__istartswith=search)
|
2019-06-18 19:41:11 +00:00
|
|
|
|
|
|
|
try:
|
2019-06-19 00:00:00 +00:00
|
|
|
qs = (
|
2019-06-18 19:41:11 +00:00
|
|
|
SearchQuerySet()
|
|
|
|
.models(self.model)
|
2019-06-18 23:53:02 +00:00
|
|
|
.autocomplete(auto=html.escape(search))
|
2019-06-18 19:41:11 +00:00
|
|
|
)
|
|
|
|
except TypeError:
|
|
|
|
return self.model.objects.none()
|
|
|
|
|
2023-05-02 11:07:36 +00:00
|
|
|
return queryset.filter(
|
|
|
|
id__in=([o.object.id for o in qs if o.object is not None])
|
|
|
|
)
|
2019-06-18 19:41:11 +00:00
|
|
|
|
2019-05-16 14:51:30 +00:00
|
|
|
|
2019-06-19 23:29:12 +00:00
|
|
|
class UVCommentReportCreateView(CanCreateMixin, CreateView):
|
2019-05-16 14:51:30 +00:00
|
|
|
"""
|
|
|
|
Create a new report for an inapropriate comment
|
|
|
|
"""
|
|
|
|
|
2019-06-19 23:29:12 +00:00
|
|
|
model = UVCommentReport
|
|
|
|
form_class = UVCommentReportForm
|
|
|
|
template_name = "core/edit.jinja"
|
2019-05-16 14:51:30 +00:00
|
|
|
|
2019-06-19 23:29:12 +00:00
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
|
|
self.uv_comment = get_object_or_404(UVComment, pk=kwargs["comment_id"])
|
2024-06-27 12:46:43 +00:00
|
|
|
return super().dispatch(request, *args, **kwargs)
|
2019-05-16 14:51:30 +00:00
|
|
|
|
2019-06-19 23:29:12 +00:00
|
|
|
def get_form_kwargs(self):
|
2024-06-27 12:46:43 +00:00
|
|
|
kwargs = super().get_form_kwargs()
|
2019-06-19 23:29:12 +00:00
|
|
|
kwargs["reporter_id"] = self.request.user.id
|
|
|
|
kwargs["comment_id"] = self.uv_comment.id
|
|
|
|
return kwargs
|
2019-05-16 14:51:30 +00:00
|
|
|
|
2019-07-04 13:32:00 +00:00
|
|
|
def form_valid(self, form):
|
2024-06-27 12:46:43 +00:00
|
|
|
resp = super().form_valid(form)
|
2019-07-04 13:32:00 +00:00
|
|
|
|
|
|
|
# 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
|
|
|
|
|
2019-06-19 23:29:12 +00:00
|
|
|
def get_success_url(self):
|
|
|
|
return reverse_lazy(
|
|
|
|
"pedagogy:uv_detail", kwargs={"uv_id": self.uv_comment.uv.id}
|
|
|
|
)
|
2019-05-16 14:51:30 +00:00
|
|
|
|
|
|
|
|
2019-06-20 10:15:12 +00:00
|
|
|
class UVModerationFormView(FormView):
|
2019-05-16 14:51:30 +00:00
|
|
|
"""
|
2019-06-19 23:29:12 +00:00
|
|
|
Moderation interface (Privileged)
|
2019-05-16 14:51:30 +00:00
|
|
|
"""
|
|
|
|
|
2019-06-20 10:15:12 +00:00
|
|
|
form_class = UVCommentModerationForm
|
|
|
|
template_name = "pedagogy/moderation.jinja"
|
|
|
|
|
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
|
|
if not request.user.is_owner(UV()):
|
|
|
|
raise PermissionDenied
|
2024-06-27 12:46:43 +00:00
|
|
|
return super().dispatch(request, *args, **kwargs)
|
2019-06-20 10:15:12 +00:00
|
|
|
|
|
|
|
def form_valid(self, form):
|
|
|
|
form_clean = form.clean()
|
2019-06-20 11:19:35 +00:00
|
|
|
for report in form_clean.get("accepted_reports", []):
|
2019-06-20 12:22:06 +00:00
|
|
|
try:
|
|
|
|
report.comment.delete() # Delete the related comment
|
|
|
|
except ObjectDoesNotExist:
|
|
|
|
# To avoid errors when two reports points the same comment
|
|
|
|
pass
|
2019-06-20 11:19:35 +00:00
|
|
|
for report in form_clean.get("denied_reports", []):
|
2019-06-20 12:22:06 +00:00
|
|
|
try:
|
|
|
|
report.delete() # Delete the report itself
|
|
|
|
except ObjectDoesNotExist:
|
|
|
|
# To avoid errors when two reports points the same comment
|
|
|
|
pass
|
2024-06-27 12:46:43 +00:00
|
|
|
return super().form_valid(form)
|
2019-06-20 10:15:12 +00:00
|
|
|
|
|
|
|
def get_success_url(self):
|
|
|
|
return reverse_lazy("pedagogy:moderation")
|
2019-05-16 14:51:30 +00:00
|
|
|
|
|
|
|
|
2019-06-15 15:01:25 +00:00
|
|
|
class UVCreateView(CanCreateMixin, CreateView):
|
2019-05-16 14:51:30 +00:00
|
|
|
"""
|
|
|
|
Add a new UV (Privileged)
|
|
|
|
"""
|
|
|
|
|
2019-06-15 15:01:25 +00:00
|
|
|
model = UV
|
|
|
|
form_class = UVForm
|
2019-10-21 15:10:16 +00:00
|
|
|
template_name = "pedagogy/uv_edit.jinja"
|
2019-06-15 15:01:25 +00:00
|
|
|
|
|
|
|
def get_form_kwargs(self):
|
2024-06-27 12:46:43 +00:00
|
|
|
kwargs = super().get_form_kwargs()
|
2019-06-15 15:01:25 +00:00
|
|
|
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})
|
2019-05-16 14:51:30 +00:00
|
|
|
|
|
|
|
|
2019-06-15 22:04:36 +00:00
|
|
|
class UVDeleteView(CanEditPropMixin, DeleteView):
|
2019-05-16 14:51:30 +00:00
|
|
|
"""
|
|
|
|
Allow to delete an UV (Privileged)
|
|
|
|
"""
|
|
|
|
|
2019-06-15 22:04:36 +00:00
|
|
|
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"
|
2019-10-21 15:10:16 +00:00
|
|
|
template_name = "pedagogy/uv_edit.jinja"
|
2019-06-15 22:04:36 +00:00
|
|
|
|
|
|
|
def get_form_kwargs(self):
|
2024-06-27 12:46:43 +00:00
|
|
|
kwargs = super().get_form_kwargs()
|
2019-08-27 20:46:41 +00:00
|
|
|
obj = self.get_object()
|
|
|
|
kwargs["author_id"] = obj.author.id
|
2019-06-15 22:04:36 +00:00
|
|
|
return kwargs
|
|
|
|
|
|
|
|
def get_success_url(self):
|
|
|
|
return reverse_lazy("pedagogy:uv_detail", kwargs={"uv_id": self.object.id})
|