Coverage for src / mesh / views / views_discussion.py: 32%
81 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-08-27 14:14 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-08-27 14:14 +0000
1import json
3from django.contrib.auth.mixins import LoginRequiredMixin
4from django.core.exceptions import PermissionDenied
5from django.http import HttpResponseRedirect, JsonResponse
6from django.shortcuts import render
7from django.urls import reverse
8from django.views import View
10from mesh.crud.comments import submission_roles
11from mesh.crud.discussion import make_discussion_unread
12from mesh.models import Submission, User
13from mesh.models.orm import Discussion, Inbox
14from mesh.views.forms.discussion_forms import DiscussionForm
17# todo : add html and url
18class DiscussionCreateView(LoginRequiredMixin, View):
19 def dispatch(self, request, *args, **kwargs):
20 self.submission = Submission.objects.get(pk=kwargs["submission_pk"])
21 # todo : check user permission
22 if "discussion_pk" in kwargs:
23 self.discussion = Discussion.objects.get(pk=kwargs["discussion_pk"])
24 else:
25 self.discussion = None
26 return super().dispatch(request, *args, **kwargs)
28 def get(self, request, *args, **kwargs):
29 eligible = self._eligible_users_with_roles(self.submission, self.discussion)
30 return render(
31 request,
32 "mesh/submission/comment/discussion_create_modal.html",
33 {
34 "form": DiscussionForm(instance=self.discussion, submission=self.submission),
35 "discussion": self.discussion,
36 "eligible_users": eligible,
37 "submission_pk": kwargs["submission_pk"],
38 "form_action_url": self._form_action_url(),
39 },
40 )
42 def _eligible_users_with_roles(self, submission, discussion):
43 users = self._eligible_users(submission)
44 members_pks = set(discussion.members.values_list("pk", flat=True)) if discussion else set()
45 result = []
46 for u in users:
47 roles = submission_roles(u, submission)
48 result.append({"user": u, "roles": sorted(roles), "is_member": u.pk in members_pks})
49 return result
51 def _eligible_users(self, submission):
52 # users ayant un rôle sur la submission : auteur, reviewers, éditeurs
53 from django.db.models import Q
55 # todo : move to submission_model.py
56 return User.objects.filter(
57 Q(pk=submission.created_by_id)
58 | Q(
59 pk__in=submission.versions.filter(reviews__isnull=False).values(
60 "reviews__reviewer"
61 )
62 )
63 | Q(pk__in=submission.editors.values("user"))
64 ).distinct()
66 def _form_action_url(self):
67 if self.discussion:
68 return reverse(
69 "mesh:discussion_edit",
70 kwargs={"submission_pk": self.submission.pk, "discussion_pk": self.discussion.pk},
71 )
72 return reverse("mesh:discussion_create", kwargs={"submission_pk": self.submission.pk})
74 def post(self, request, *args, **kwargs):
75 data = self._clean_post(request)
77 form = DiscussionForm(data, submission=self.submission, instance=self.discussion)
78 if form.is_valid():
79 discussion = form.save(commit=False)
80 discussion.submission = self.submission
81 discussion.save()
82 form.save_m2m()
83 discussion.members.add(request.user)
84 discussion.validate_members() # double garde
85 return HttpResponseRedirect(
86 reverse("mesh:submission_details", kwargs={"submission_pk": self.submission.pk})
87 )
88 return JsonResponse({"messages": form.errors.as_json()}, status=400)
90 def _clean_post(self, request):
91 data = request.POST.copy()
92 members = []
93 for value in data.getlist("members"):
94 if value.startswith("["):
95 members.extend(str(pk) for pk in json.loads(value))
96 else:
97 members.append(value)
98 data.setlist("members", sorted(set(members)))
99 return data
102class DiscussionDeleteView(LoginRequiredMixin, View):
103 def dispatch(self, request, *args, **kwargs):
104 self.submission = Submission.objects.get(pk=kwargs["submission_pk"])
105 if "editor" not in submission_roles(request.user, self.submission):
106 raise PermissionDenied
107 if "discussion_pk" in kwargs:
108 self.discussion = Discussion.objects.get(pk=kwargs["discussion_pk"])
109 return super().dispatch(request, *args, **kwargs)
111 def post(self, request, *args, **kwargs):
112 Inbox.objects.filter(comments__discussion=self.discussion).delete()
113 self.discussion.delete()
114 return HttpResponseRedirect(
115 reverse("mesh:submission_details", kwargs={"submission_pk": self.submission.pk})
116 )
119class DiscussionUnreadView(LoginRequiredMixin, View):
120 def dispatch(self, request, *args, **kwargs):
121 self.submission = Submission.objects.get(pk=kwargs["submission_pk"])
122 if "editor" not in submission_roles(request.user, self.submission):
123 raise PermissionDenied
124 if "discussion_pk" in kwargs:
125 self.discussion = Discussion.objects.get(pk=kwargs["discussion_pk"])
126 return super().dispatch(request, *args, **kwargs)
128 def post(self, request, *args, **kwargs):
129 make_discussion_unread(discussion=self.discussion, user=request.user)
130 return HttpResponseRedirect(
131 reverse("mesh:submission_details", kwargs={"submission_pk": self.submission.pk})
132 )