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

1import json 

2 

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 

9 

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 

15 

16 

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) 

27 

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 ) 

41 

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 

50 

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 

54 

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() 

65 

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}) 

73 

74 def post(self, request, *args, **kwargs): 

75 data = self._clean_post(request) 

76 

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) 

89 

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 

100 

101 

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) 

110 

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 ) 

117 

118 

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) 

127 

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 )