_thread.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. from django.db.models import Q
  2. from django.shortcuts import redirect
  3. from django.utils.translation import ungettext, ugettext_lazy, ugettext as _
  4. from misago.acl import add_acl
  5. from misago.forums.lists import get_forum_path
  6. from misago.threads.models import Label
  7. from misago.readtracker import threadstracker
  8. from misago.users.online.utils import get_user_state
  9. from misago.threads.events import add_events_to_posts
  10. from misago.threads.paginator import paginate
  11. from misago.threads.views.generic.actions import ActionsBase
  12. from misago.threads.views.generic.base import ViewBase
  13. __all__ = ['ThreadActions']
  14. class ThreadActions(ActionsBase):
  15. query_key = 'thread_action'
  16. is_mass_action = False
  17. def get_available_actions(self, kwargs):
  18. self.thread = kwargs['thread']
  19. self.forum = self.thread.forum
  20. actions = []
  21. if self.forum.acl['can_change_threads_labels'] == 2:
  22. self.forum.labels = Label.objects.get_forum_labels(self.forum)
  23. for label in self.forum.labels:
  24. if label.pk != self.thread.label_id:
  25. name = _('Label as "%(label)s"') % {'label': label.name}
  26. actions.append({
  27. 'action': 'label:%s' % label.slug,
  28. 'icon': 'tag',
  29. 'name': name
  30. })
  31. if self.forum.labels and self.thread.label_id:
  32. actions.append({
  33. 'action': 'unlabel',
  34. 'icon': 'times-circle',
  35. 'name': _("Remove label")
  36. })
  37. if self.forum.acl['can_pin_threads']:
  38. if self.thread.is_pinned:
  39. actions.append({
  40. 'action': 'unpin',
  41. 'icon': 'circle',
  42. 'name': _("Unpin thread")
  43. })
  44. else:
  45. actions.append({
  46. 'action': 'pin',
  47. 'icon': 'star',
  48. 'name': _("Pin thread")
  49. })
  50. if self.forum.acl['can_review_moderated_content']:
  51. if self.thread.is_moderated:
  52. actions.append({
  53. 'action': 'approve',
  54. 'icon': 'check',
  55. 'name': _("Approve thread")
  56. })
  57. if self.forum.acl['can_move_threads']:
  58. actions.append({
  59. 'action': 'move',
  60. 'icon': 'arrow-right',
  61. 'name': _("Move thread")
  62. })
  63. if self.forum.acl['can_close_threads']:
  64. if self.thread.is_closed:
  65. actions.append({
  66. 'action': 'open',
  67. 'icon': 'unlock-alt',
  68. 'name': _("Open thread")
  69. })
  70. else:
  71. actions.append({
  72. 'action': 'close',
  73. 'icon': 'lock',
  74. 'name': _("Close thread")
  75. })
  76. if self.forum.acl['can_hide_threads']:
  77. if self.thread.is_hidden:
  78. actions.append({
  79. 'action': 'unhide',
  80. 'icon': 'eye',
  81. 'name': _("Unhide thread")
  82. })
  83. else:
  84. actions.append({
  85. 'action': 'hide',
  86. 'icon': 'eye-slash',
  87. 'name': _("Hide thread")
  88. })
  89. if self.forum.acl['can_hide_threads'] == 2:
  90. actions.append({
  91. 'action': 'delete',
  92. 'icon': 'times',
  93. 'name': _("Delete thread"),
  94. 'confirmation': _("Are you sure you want to delete this "
  95. "thread? This action can't be undone.")
  96. })
  97. return actions
  98. class PostsActions(ActionsBase):
  99. select_items_message = ugettext_lazy(
  100. "You have to select at least one post.")
  101. is_mass_action = True
  102. def get_available_actions(self, kwargs):
  103. return []
  104. class ThreadView(ViewBase):
  105. """
  106. Basic view for threads
  107. """
  108. ThreadActions = ThreadActions
  109. PostsActions = PostsActions
  110. template = 'misago/thread/replies.html'
  111. def get_posts(self, user, forum, thread, kwargs):
  112. queryset = self.get_posts_queryset(user, forum, thread)
  113. page = paginate(queryset, kwargs.get('page', 0), 10, 5)
  114. posts = []
  115. for post in page.object_list:
  116. add_acl(user, post)
  117. if post.poster:
  118. poster_state = get_user_state(post.poster, user.acl)
  119. post.poster.online_state = poster_state
  120. posts.append(post)
  121. if page.next_page_first_item:
  122. add_events_to_posts(
  123. user, thread, posts, page.next_page_first_item.posted_on)
  124. else:
  125. add_events_to_posts(user, thread, posts)
  126. return page, posts
  127. def get_posts_queryset(self, user, forum, thread):
  128. queryset = thread.post_set.select_related(
  129. 'poster', 'poster__rank', 'poster__bancache', 'poster__online')
  130. if user.is_authenticated():
  131. if forum.acl['can_review_moderated_content']:
  132. visibility_condition = Q(is_moderated=False) | Q(poster=user)
  133. queryset = queryset.filter(visibility_condition)
  134. else:
  135. queryset = queryset.filter(is_moderated=False)
  136. return queryset.order_by('id')
  137. def dispatch(self, request, *args, **kwargs):
  138. relations = ['forum', 'starter', 'last_poster', 'first_post']
  139. thread = self.fetch_thread(request, select_related=relations, **kwargs)
  140. forum = thread.forum
  141. self.check_forum_permissions(request, forum)
  142. self.check_thread_permissions(request, thread)
  143. threadstracker.make_read_aware(request.user, thread)
  144. thread_actions = self.ThreadActions(user=request.user, thread=thread)
  145. posts_actions = self.PostsActions(user=request.user, thread=thread)
  146. page, posts = self.get_posts(request.user, forum, thread, kwargs)
  147. threadstracker.make_posts_read_aware(request.user, thread, posts)
  148. threadstracker.read_thread(request.user, thread, posts[-1])
  149. return self.render(request, {
  150. 'link_name': thread.get_url(),
  151. 'links_params': {
  152. 'thread_id': thread.id, 'thread_slug': thread.slug
  153. },
  154. 'forum': forum,
  155. 'path': get_forum_path(forum),
  156. 'thread': thread,
  157. 'thread_actions': thread_actions.get_list(),
  158. 'posts': posts,
  159. 'posts_actions': posts_actions.get_list(),
  160. 'paginator': page.paginator,
  161. 'page': page,
  162. })