postsactions.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. from django.contrib import messages
  2. from django.db.transaction import atomic
  3. from django.http import Http404
  4. from django.shortcuts import redirect
  5. from django.utils.translation import ungettext, ugettext_lazy, ugettext as _
  6. from misago.threads import moderation
  7. from misago.threads.paginator import Paginator
  8. from misago.threads.views.generic.actions import ActionsBase, ReloadAfterDelete
  9. __all__ = ['PostsActions']
  10. def atomic_post_action(f):
  11. def decorator(self, request, posts):
  12. with atomic():
  13. self.thread.lock()
  14. for post in posts:
  15. post.thread = self.thread
  16. response = f(self, request, posts)
  17. self.thread.synchronize()
  18. self.thread.save()
  19. self.forum.lock()
  20. self.forum.synchronize()
  21. self.forum.save()
  22. return response
  23. return decorator
  24. class PostsActions(ActionsBase):
  25. select_items_message = ugettext_lazy(
  26. "You have to select at least one post.")
  27. is_mass_action = True
  28. def redirect_after_deletion(self, request, queryset):
  29. paginator = Paginator(queryset, 10, 3)
  30. current_page = int(request.resolver_match.kwargs.get('page', 0))
  31. if paginator.num_pages < current_page:
  32. namespace = request.resolver_match.namespace
  33. url_name = request.resolver_match.url_name
  34. kwars = request.resolver_match.kwargs
  35. kwars['page'] = paginator.num_pages
  36. if kwars['page'] == 1:
  37. del kwars['page']
  38. return redirect('%s:%s' % (namespace, url_name), **kwars)
  39. else:
  40. return redirect(request.path)
  41. def get_available_actions(self, kwargs):
  42. self.thread = kwargs['thread']
  43. self.forum = self.thread.forum
  44. actions = []
  45. if self.forum.acl['can_protect_posts']:
  46. actions.append({
  47. 'action': 'unprotect',
  48. 'icon': 'unlock-alt',
  49. 'name': _("Release posts")
  50. })
  51. actions.append({
  52. 'action': 'protect',
  53. 'icon': 'lock',
  54. 'name': _("Protect posts")
  55. })
  56. if self.forum.acl['can_hide_posts']:
  57. actions.append({
  58. 'action': 'unhide',
  59. 'icon': 'eye',
  60. 'name': _("Reveal posts")
  61. })
  62. actions.append({
  63. 'action': 'hide',
  64. 'icon': 'eye-slash',
  65. 'name': _("Hide posts")
  66. })
  67. if self.forum.acl['can_hide_posts'] == 2:
  68. actions.append({
  69. 'action': 'delete',
  70. 'icon': 'times',
  71. 'name': _("Delete posts"),
  72. 'confirmation': _("Are you sure you want to delete selected "
  73. "posts? This action can't be undone.")
  74. })
  75. return actions
  76. def action_unprotect(self, request, posts):
  77. changed_posts = 0
  78. for post in posts:
  79. if moderation.unprotect_post(request.user, post):
  80. changed_posts += 1
  81. if changed_posts:
  82. message = ungettext(
  83. '%(changed)d post was released from protection.',
  84. '%(changed)d posts were released from protection.',
  85. changed_posts)
  86. messages.success(request, message % {'changed': changed_posts})
  87. else:
  88. message = _("No posts were released from protection.")
  89. messages.info(request, message)
  90. def action_protect(self, request, posts):
  91. changed_posts = 0
  92. for post in posts:
  93. if moderation.protect_post(request.user, post):
  94. changed_posts += 1
  95. if changed_posts:
  96. message = ungettext(
  97. '%(changed)d post was made protected.',
  98. '%(changed)d posts were made protected.',
  99. changed_posts)
  100. messages.success(request, message % {'changed': changed_posts})
  101. else:
  102. message = _("No posts were made protected.")
  103. messages.info(request, message)
  104. @atomic_post_action
  105. def action_unhide(self, request, posts):
  106. changed_posts = 0
  107. for post in posts:
  108. if moderation.unhide_post(request.user, post):
  109. changed_posts += 1
  110. if changed_posts:
  111. message = ungettext(
  112. '%(changed)d post was made visible.',
  113. '%(changed)d posts were made visible.',
  114. changed_posts)
  115. messages.success(request, message % {'changed': changed_posts})
  116. else:
  117. message = _("No posts were made visible.")
  118. messages.info(request, message)
  119. @atomic_post_action
  120. def action_hide(self, request, posts):
  121. changed_posts = 0
  122. for post in posts:
  123. if moderation.hide_post(request.user, post):
  124. changed_posts += 1
  125. if changed_posts:
  126. message = ungettext(
  127. '%(changed)d post was hidden.',
  128. '%(changed)d posts were hidden.',
  129. changed_posts)
  130. messages.success(request, message % {'changed': changed_posts})
  131. else:
  132. message = _("No posts were hidden.")
  133. messages.info(request, message)
  134. @atomic_post_action
  135. def action_delete(self, request, posts):
  136. changed_posts = 0
  137. first_deleted = None
  138. for post in posts:
  139. if moderation.delete_post(request.user, post):
  140. changed_posts += 1
  141. if not first_deleted:
  142. first_deleted = post
  143. if changed_posts:
  144. message = ungettext(
  145. '%(changed)d post was deleted.',
  146. '%(changed)d posts were deleted.',
  147. changed_posts)
  148. messages.success(request, message % {'changed': changed_posts})
  149. return ReloadAfterDelete()
  150. else:
  151. message = _("No posts were deleted.")
  152. messages.info(request, message)