actions.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. from django.contrib import messages
  2. from django.db.transaction import atomic
  3. from django.shortcuts import render
  4. from django.utils.translation import ugettext_lazy, ugettext as _, ungettext
  5. from misago.forums.lists import get_forum_path
  6. from misago.threads import moderation
  7. from misago.threads.forms.moderation import MoveThreadsForm
  8. from misago.threads.views.generic.threads import Actions
  9. __all__ = ['ForumActions']
  10. class ForumActions(Actions):
  11. def get_available_actions(self, kwargs):
  12. self.forum = kwargs['forum']
  13. actions = []
  14. if self.forum.acl['can_change_threads_labels'] == 2:
  15. for label in self.forum.labels:
  16. actions.append({
  17. 'action': 'label:%s' % label.slug,
  18. 'icon': 'tag',
  19. 'name': _('Label as "%(label)s"') % {'label': label.name}
  20. })
  21. if self.forum.labels:
  22. actions.append({
  23. 'action': 'unlabel',
  24. 'icon': 'times-circle',
  25. 'name': _("Remove labels")
  26. })
  27. if self.forum.acl['can_change_threads_weight'] == 2:
  28. actions.append({
  29. 'action': 'announce',
  30. 'icon': 'star',
  31. 'name': _("Change to announcements")
  32. })
  33. if self.forum.acl['can_change_threads_weight']:
  34. actions.append({
  35. 'action': 'pin',
  36. 'icon': 'bookmark',
  37. 'name': _("Change to pinned")
  38. })
  39. actions.append({
  40. 'action': 'reset',
  41. 'icon': 'circle',
  42. 'name': _("Reset weight")
  43. })
  44. if self.forum.acl['can_review_moderated_content']:
  45. actions.append({
  46. 'action': 'approve',
  47. 'icon': 'check',
  48. 'name': _("Approve threads")
  49. })
  50. if self.forum.acl['can_move_threads']:
  51. actions.append({
  52. 'action': 'move',
  53. 'icon': 'arrow-right',
  54. 'name': _("Move threads")
  55. })
  56. if self.forum.acl['can_merge_threads']:
  57. actions.append({
  58. 'action': 'merge',
  59. 'icon': 'reply-all',
  60. 'name': _("Merge threads")
  61. })
  62. if self.forum.acl['can_close_threads']:
  63. actions.append({
  64. 'action': 'open',
  65. 'icon': 'unlock-alt',
  66. 'name': _("Open threads")
  67. })
  68. actions.append({
  69. 'action': 'close',
  70. 'icon': 'lock',
  71. 'name': _("Close threads")
  72. })
  73. if self.forum.acl['can_hide_threads']:
  74. actions.append({
  75. 'action': 'unhide',
  76. 'icon': 'eye',
  77. 'name': _("Unhide threads")
  78. })
  79. actions.append({
  80. 'action': 'hide',
  81. 'icon': 'eye-slash',
  82. 'name': _("Hide threads")
  83. })
  84. if self.forum.acl['can_hide_threads'] == 2:
  85. actions.append({
  86. 'action': 'delete',
  87. 'icon': 'times',
  88. 'name': _("Delete threads"),
  89. 'confirmation': _("Are you sure you want to delete selected "
  90. "threads? This action can't be undone.")
  91. })
  92. return actions
  93. def action_label(self, request, threads, label_slug):
  94. for label in self.forum.labels:
  95. if label.slug == label_slug:
  96. break
  97. else:
  98. raise ModerationError(_("Requested action is invalid."))
  99. changed_threads = 0
  100. for thread in threads:
  101. if moderation.label_thread(request.user, thread, label):
  102. changed_threads += 1
  103. if changed_threads:
  104. message = ungettext(
  105. '%(changed)d thread was labeled "%(label)s".',
  106. '%(changed)d threads were labeled "%(label)s".',
  107. changed_threads)
  108. messages.success(request, message % {
  109. 'changed': changed_threads,
  110. 'label': label.name
  111. })
  112. else:
  113. message = _("No threads were labeled.")
  114. messages.info(request, message)
  115. def action_unlabel(self, request, threads):
  116. changed_threads = 0
  117. for thread in threads:
  118. if moderation.unlabel_thread(request.user, thread):
  119. changed_threads += 1
  120. if changed_threads:
  121. message = ungettext(
  122. '%(changed)d thread label was remoded.',
  123. '%(changed)d threads labels were removed.',
  124. changed_threads)
  125. messages.success(request, message % {'changed': changed_threads})
  126. else:
  127. message = _("No threads were unlabeled.")
  128. messages.info(request, message)
  129. def action_announce(self, request, threads):
  130. changed_threads = 0
  131. for thread in threads:
  132. if moderation.announce_thread(request.user, thread):
  133. changed_threads += 1
  134. if changed_threads:
  135. message = ungettext(
  136. '%(changed)d thread was changed to announcement.',
  137. '%(changed)d threads were changed to announcements.',
  138. changed_threads)
  139. messages.success(request, message % {'changed': changed_threads})
  140. else:
  141. message = _("No threads were changed to announcements.")
  142. messages.info(request, message)
  143. def action_pin(self, request, threads):
  144. changed_threads = 0
  145. for thread in threads:
  146. if moderation.pin_thread(request.user, thread):
  147. changed_threads += 1
  148. if changed_threads:
  149. message = ungettext(
  150. '%(changed)d thread was pinned.',
  151. '%(changed)d threads were pinned.',
  152. changed_threads)
  153. messages.success(request, message % {'changed': changed_threads})
  154. else:
  155. message = _("No threads were pinned.")
  156. messages.info(request, message)
  157. def action_reset(self, request, threads):
  158. changed_threads = 0
  159. for thread in threads:
  160. if moderation.reset_thread(request.user, thread):
  161. changed_threads += 1
  162. if changed_threads:
  163. message = ungettext(
  164. '%(changed)d thread weight was reset.',
  165. '%(changed)d threads weight was reset.',
  166. changed_threads)
  167. messages.success(request, message % {'changed': changed_threads})
  168. else:
  169. message = _("No threads weight was reset.")
  170. messages.info(request, message)
  171. move_threads_template = 'misago/threads/move.html'
  172. def action_move(self, request, threads):
  173. form = MoveThreadsForm(user=request.user, forum=self.forum)
  174. if request.method == "POST" and 'submit' in request.POST:
  175. form = MoveThreadsForm(
  176. request.POST, user=request.user, forum=self.forum)
  177. if form.is_valid():
  178. new_forum = form.cleaned_data['new_forum']
  179. for thread in threads:
  180. moderation.move_thread(request.user, thread, new_forum)
  181. with atomic():
  182. self.forum.synchronize()
  183. self.forum.save()
  184. new_forum.synchronize()
  185. new_forum.save()
  186. changed_threads = len(threads)
  187. message = ungettext(
  188. '%(changed)d thread was moved to %(forum)s.',
  189. '%(changed)d threads were moved to %(forum)s.',
  190. changed_threads)
  191. messages.success(request, message % {
  192. 'changed': changed_threads,
  193. 'forum': new_forum.name
  194. })
  195. return None # trigger threads list refresh
  196. return render(request, self.move_threads_template, {
  197. 'form': form,
  198. 'forum': self.forum,
  199. 'path': get_forum_path(self.forum),
  200. 'threads': threads
  201. })
  202. def action_close(self, request, threads):
  203. changed_threads = 0
  204. for thread in threads:
  205. if moderation.close_thread(request.user, thread):
  206. changed_threads += 1
  207. if changed_threads:
  208. message = ungettext(
  209. '%(changed)d thread was closed.',
  210. '%(changed)d threads were closed.',
  211. changed_threads)
  212. messages.success(request, message % {'changed': changed_threads})
  213. else:
  214. message = _("No threads were closed.")
  215. messages.info(request, message)
  216. def action_open(self, request, threads):
  217. changed_threads = 0
  218. for thread in threads:
  219. if moderation.open_thread(request.user, thread):
  220. changed_threads += 1
  221. if changed_threads:
  222. message = ungettext(
  223. '%(changed)d thread was opened.',
  224. '%(changed)d threads were opened.',
  225. changed_threads)
  226. messages.success(request, message % {'changed': changed_threads})
  227. else:
  228. message = _("No threads were opened.")
  229. messages.info(request, message)
  230. def action_unhide(self, request, threads):
  231. changed_threads = 0
  232. for thread in threads:
  233. if moderation.unhide_thread(request.user, thread):
  234. changed_threads += 1
  235. if changed_threads:
  236. with atomic():
  237. self.forum.synchronize()
  238. self.forum.save()
  239. message = ungettext(
  240. '%(changed)d thread was made visible.',
  241. '%(changed)d threads were made visible.',
  242. changed_threads)
  243. messages.success(request, message % {'changed': changed_threads})
  244. else:
  245. message = _("No threads were made visible.")
  246. messages.info(request, message)
  247. def action_hide(self, request, threads):
  248. changed_threads = 0
  249. for thread in threads:
  250. if moderation.hide_thread(request.user, thread):
  251. changed_threads += 1
  252. if changed_threads:
  253. with atomic():
  254. self.forum.synchronize()
  255. self.forum.save()
  256. message = ungettext(
  257. '%(changed)d thread was hidden.',
  258. '%(changed)d threads were hidden.',
  259. changed_threads)
  260. messages.success(request, message % {'changed': changed_threads})
  261. else:
  262. message = _("No threads were hidden.")
  263. messages.info(request, message)
  264. def action_delete(self, request, threads):
  265. changed_threads = 0
  266. for thread in threads:
  267. if moderation.delete_thread(request.user, thread):
  268. changed_threads += 1
  269. if changed_threads:
  270. with atomic():
  271. self.forum.synchronize()
  272. self.forum.save()
  273. message = ungettext(
  274. '%(changed)d thread was deleted.',
  275. '%(changed)d threads were deleted.',
  276. changed_threads)
  277. messages.success(request, message % {'changed': changed_threads})
  278. else:
  279. message = _("No threads were deleted.")
  280. messages.info(request, message)