Coverage for src / mesh / crud / discussion.py: 21%
105 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-10-22 07:20 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-10-22 07:20 +0000
1from datetime import timedelta
3from django.utils import timezone
5from mesh.crud.comments import submission_roles
6from mesh.models import User
7from mesh.models.orm.comment_models import Comment
8from mesh.models.orm.discussion_models import Discussion, DiscussionRead
9from mesh.models.orm.inbox_model import Inbox
10from mesh.models.roles.base_role import Role
11from mesh.views.components.button import build_comment_actions
12from mesh.views.components.ckeditor_config import sanitize_html_input
13from mesh.views.components.icon import build_icon
16def role_icon(role: str):
17 role_icon = (
18 (role == "editor") * "fa-newspaper"
19 + (role == "author") * "fa-user-pen"
20 + (role == "reviewer") * "fa-microscope"
21 )
22 return role_icon
25def create_comment(discussion: Discussion, content, user, parent=None):
26 def role_of(user: User, discussion: Discussion):
27 roles = submission_roles(user=user, submission=discussion.submission)
28 for r in ("editor", "reviewer", "author"):
29 if r in roles:
30 return r
32 comment = Comment.objects.create(
33 discussion=discussion,
34 raw_html=content,
35 sanitized_html=sanitize_html_input(content),
36 author=user,
37 parent=parent,
38 role=role_of(user=user, discussion=discussion),
39 )
40 update_date_last_seen(discussion=discussion, user=user)
41 add_inbox_item(comment, comment_user=user)
44def edit_comment(discussion: Discussion, user: User, content, comment_pk):
45 comment = Comment.objects.get(
46 pk=comment_pk,
47 discussion=discussion,
48 )
49 comment.raw_html = content
50 comment.sanitized_html = sanitize_html_input(content)
51 comment.save()
52 update_date_last_seen(discussion=discussion, user=user)
53 add_inbox_item(comment, comment_user=user)
56def get_comment(discussion: Discussion, comment_pk):
57 return Comment.objects.select_related("author", "parent").get(
58 pk=comment_pk, discussion=discussion
59 )
62def get_comments(discussion: Discussion, user: User, role: Role, nesting: bool = True):
63 comments = Comment.objects.filter(discussion=discussion, is_deleted=False)
64 discussion_read, _created = DiscussionRead.objects.get_or_create(
65 discussion=discussion, user=user
66 )
67 date_last_seen = discussion_read.date_last_seen
69 def has_seen(comment):
70 if date_last_seen is None:
71 return False
72 return date_last_seen >= comment.date_last_modified
74 def entry_of(comment: Comment):
75 role_str = comment.role
76 return {
77 "content": comment,
78 "role": role_str,
79 "role_icon": comment.role_icon_class,
80 "icon": build_icon(comment.role_icon_class, icon_attrs={"data-tooltip": [role_str]}),
81 "role_color": comment.role_color,
82 "current_user_comment": comment.author == user,
83 "can_edit": role.can_edit_comment(comment),
84 "has_seen": has_seen(comment),
85 "comment_actions": build_comment_actions(comment, user),
86 }
88 ordered = [entry_of(comment) for comment in comments]
89 return ordered
92def update_date_last_seen(discussion: Discussion, user: User, date_last_seen=None):
93 if date_last_seen is None:
94 date_last_seen = timezone.now()
95 user_discussion_read = DiscussionRead.objects.get(discussion=discussion, user=user)
96 user_discussion_read.date_last_seen = date_last_seen
97 user_discussion_read.save()
100def add_inbox_item(comment: Comment, comment_user: User):
101 discussion_users = comment.discussion.members.all()
102 for user in discussion_users:
103 if user != comment_user:
104 user_inbox, _ = Inbox.objects.get_or_create(user=user)
105 user_inbox.comments.add(comment)
108def remove_inbox_item(user: User, comment: Comment = None, discussion: Discussion = None):
109 try:
110 inbox = Inbox.objects.get(user=user)
111 except Inbox.DoesNotExist:
112 return
114 def remove_inbox_comment(ibx: Inbox, com: Comment):
115 inbox.comments.remove(com)
116 if not ibx.comments.exists():
117 ibx.delete()
119 if discussion:
120 comments = inbox.comments.filter(discussion=discussion)
121 [remove_inbox_comment(ibx=inbox, com=com) for com in comments]
123 if comment:
124 remove_inbox_comment(ibx=inbox, com=comment)
127def delete_comment(discussion: Discussion, comment: Comment, user: User, role: Role):
128 comment.is_deleted = True
129 comment.save(update_fields=["is_deleted"])
130 comment.refresh_from_db()
132 # delete responses
133 discussion_comments = get_comments(discussion=discussion, user=user, role=role)
134 for child_comment in discussion_comments:
135 child_comment = child_comment["content"]
136 if child_comment.parent and child_comment.parent.pk == comment.pk:
137 child_comment.is_deleted = True
138 child_comment.save(update_fields=["is_deleted"])
139 child_comment.refresh_from_db()
140 return True
143def get_inbox_comments(user: User):
144 def get_comment_preview(comment: Comment):
145 role_str = comment.role
147 return {
148 "content": comment,
149 "role": role_str,
150 "role_icon": comment.role_icon_class,
151 "submission_name": comment.discussion.submission.name,
152 "discussion_title": comment.discussion.title,
153 "submission_pk": comment.discussion.submission.pk,
154 "discussion_pk": comment.discussion.pk,
155 }
157 try:
158 user_inbox = Inbox.objects.get(user=user)
159 comments = user_inbox.comments.all()
160 ordered_comments = [get_comment_preview(comment) for comment in comments[::-1]]
161 return ordered_comments
162 except Inbox.DoesNotExist:
163 return None
166def make_discussion_unread(discussion: Discussion, user: User, days_to_subtract=1):
167 discussion_last_comment = (
168 Comment.objects.filter(discussion=discussion).order_by("date_last_modified").first()
169 )
171 if discussion_last_comment is None:
172 return
174 # mark discussion last comment as unreaden
175 discussion_last_comment_date = discussion_last_comment.date_last_modified
176 update_date_last_seen(
177 discussion=discussion,
178 user=user,
179 date_last_seen=discussion_last_comment_date - timedelta(days=days_to_subtract),
180 )
182 # add discussion last comment to inbox
183 user_inbox, inbox_created = Inbox.objects.get_or_create(user=user)
184 if inbox_created:
185 return
186 user_inbox.comments.add(discussion_last_comment)
187 user_inbox.save()