views.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. import copy
  2. from django.core.urlresolvers import reverse as django_reverse
  3. from django.db.models import Q
  4. from django.utils.translation import ugettext as _
  5. from mptt.forms import TreeNodeChoiceField
  6. from misago.admin import site
  7. from misago.admin.widgets import *
  8. from misago.forums.forms import CategoryForm, ForumForm, RedirectForm, DeleteForm
  9. from misago.forums.models import Forum
  10. from misago.utils import slugify
  11. def reverse(route, target=None):
  12. if target:
  13. return django_reverse(route, kwargs={'target': target.pk, 'slug': target.slug})
  14. return django_reverse(route)
  15. """
  16. Views
  17. """
  18. class List(ListWidget):
  19. admin = site.get_action('forums')
  20. id = 'list'
  21. columns = (
  22. ('forum', _("Forum")),
  23. )
  24. nothing_checked_message = _('You have to select at least one forum.')
  25. actions = (
  26. ('resync', _("Resynchronise forums")),
  27. ('prune', _("Prune forums"), _("Are you sure you want to delete all content from selected forums?")),
  28. )
  29. empty_message = _('No forums are currently defined.')
  30. def get_items(self):
  31. return self.admin.model.objects.get(token='root').get_descendants()
  32. def sort_items(self, page_items, sorting_method):
  33. return page_items.order_by('lft')
  34. def get_item_actions(self, item):
  35. if item.type == 'category':
  36. return (
  37. self.action('chevron-up', _("Move Category Up"), reverse('admin_forums_up', item), post=True),
  38. self.action('chevron-down', _("Move Category Down"), reverse('admin_forums_down', item), post=True),
  39. self.action('pencil', _("Edit Category"), reverse('admin_forums_edit', item)),
  40. self.action('remove', _("Delete Category"), reverse('admin_forums_delete', item)),
  41. )
  42. if item.type == 'forum':
  43. return (
  44. self.action('chevron-up', _("Move Forum Up"), reverse('admin_forums_up', item), post=True),
  45. self.action('chevron-down', _("Move Forum Down"), reverse('admin_forums_down', item), post=True),
  46. self.action('pencil', _("Edit Forum"), reverse('admin_forums_edit', item)),
  47. self.action('remove', _("Delete Forum"), reverse('admin_forums_delete', item)),
  48. )
  49. return (
  50. self.action('chevron-up', _("Move Redirect Up"), reverse('admin_forums_up', item), post=True),
  51. self.action('chevron-down', _("Move Redirect Down"), reverse('admin_forums_down', item), post=True),
  52. self.action('pencil', _("Edit Redirect"), reverse('admin_forums_edit', item)),
  53. self.action('remove', _("Delete Redirect"), reverse('admin_forums_delete', item)),
  54. )
  55. def action_resync(self, items, checked):
  56. return Message(_('Selected forums have been resynchronised successfully.'), 'success'), reverse('admin_forums')
  57. def action_prune(self, items, checked):
  58. return Message(_('Selected forums have been pruned successfully.'), 'success'), reverse('admin_forums')
  59. class NewCategory(FormWidget):
  60. admin = site.get_action('forums')
  61. id = 'new_category'
  62. fallback = 'admin_forums'
  63. form = CategoryForm
  64. submit_button = _("Save Category")
  65. def get_new_url(self, model):
  66. return reverse('admin_forums_new_category')
  67. def get_edit_url(self, model):
  68. return reverse('admin_forums_edit', model)
  69. def submit_form(self, form, target):
  70. new_forum = Forum(
  71. name=form.cleaned_data['name'],
  72. slug=slugify(form.cleaned_data['name']),
  73. type='category',
  74. template=form.cleaned_data['template'],
  75. show_details=form.cleaned_data['show_details'],
  76. style=form.cleaned_data['style'],
  77. closed=form.cleaned_data['closed'],
  78. )
  79. new_forum.set_description(form.cleaned_data['description'])
  80. new_forum.insert_at(form.cleaned_data['parent'], position='last-child', save=True)
  81. Forum.objects.populate_tree(True)
  82. if form.cleaned_data['perms']:
  83. new_forum.copy_permissions(form.cleaned_data['perms'])
  84. self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
  85. return new_forum, Message(_('New Category has been created.'), 'success')
  86. class NewForum(FormWidget):
  87. admin = site.get_action('forums')
  88. id = 'new_forum'
  89. fallback = 'admin_forums'
  90. form = ForumForm
  91. submit_button = _("Save Forum")
  92. def get_new_url(self, model):
  93. return reverse('admin_forums_new_forum')
  94. def get_edit_url(self, model):
  95. return reverse('admin_forums_edit', model)
  96. def submit_form(self, form, target):
  97. new_forum = Forum(
  98. name=form.cleaned_data['name'],
  99. slug=slugify(form.cleaned_data['name']),
  100. type='forum',
  101. template=form.cleaned_data['template'],
  102. show_details=form.cleaned_data['show_details'],
  103. style=form.cleaned_data['style'],
  104. closed=form.cleaned_data['closed'],
  105. prune_start=form.cleaned_data['prune_start'],
  106. prune_last=form.cleaned_data['prune_last'],
  107. )
  108. new_forum.set_description(form.cleaned_data['description'])
  109. new_forum.insert_at(form.cleaned_data['parent'], position='last-child', save=True)
  110. Forum.objects.populate_tree(True)
  111. if form.cleaned_data['perms']:
  112. new_forum.copy_permissions(form.cleaned_data['perms'])
  113. self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
  114. return new_forum, Message(_('New Forum has been created.'), 'success')
  115. def __call__(self, request):
  116. if self.admin.model.objects.get(token='root').get_descendants().count() == 0:
  117. request.messages.set_flash(Message(_("You have to create at least one category before you will be able to create forums.")), 'error', self.admin.id)
  118. return redirect(self.get_fallback_url())
  119. return super(NewForum, self).__call__(request)
  120. class NewRedirect(FormWidget):
  121. admin = site.get_action('forums')
  122. id = 'new_redirect'
  123. fallback = 'admin_forums'
  124. form = RedirectForm
  125. submit_button = _("Save Forum")
  126. def get_new_url(self, model):
  127. return reverse('admin_forums_new_redirect')
  128. def get_edit_url(self, model):
  129. return reverse('admin_forums_edit', model)
  130. def submit_form(self, form, target):
  131. new_forum = Forum(
  132. name=form.cleaned_data['name'],
  133. slug=slugify(form.cleaned_data['name']),
  134. redirect=form.cleaned_data['redirect'],
  135. style=form.cleaned_data['style'],
  136. type='redirect',
  137. )
  138. new_forum.set_description(form.cleaned_data['description'])
  139. new_forum.insert_at(form.cleaned_data['parent'], position='last-child', save=True)
  140. Forum.objects.populate_tree(True)
  141. if form.cleaned_data['perms']:
  142. new_forum.copy_permissions(form.cleaned_data['perms'])
  143. self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
  144. return new_forum, Message(_('New Redirect has been created.'), 'success')
  145. def __call__(self, request):
  146. if self.admin.model.objects.get(token='root').get_descendants().count() == 0:
  147. request.messages.set_flash(Message(_("You have to create at least one category before you will be able to create redirects.")), 'error', self.admin.id)
  148. return redirect(self.get_fallback_url())
  149. return super(NewRedirect, self).__call__(request)
  150. class Up(ButtonWidget):
  151. admin = site.get_action('forums')
  152. id = 'up'
  153. fallback = 'admin_forums'
  154. notfound_message = _('Requested Forum could not be found.')
  155. def action(self, target):
  156. previous_sibling = target.get_previous_sibling()
  157. if previous_sibling:
  158. target.move_to(previous_sibling, 'left')
  159. return Message(_('Forum "%(name)s" has been moved up.') % {'name': target.name}, 'success'), False
  160. return Message(_('Forum "%(name)s" is first child of its parent node and cannot be moved up.') % {'name': target.name}, 'info'), False
  161. class Down(ButtonWidget):
  162. admin = site.get_action('forums')
  163. id = 'down'
  164. fallback = 'admin_forums'
  165. notfound_message = _('Requested Forum could not be found.')
  166. def action(self, target):
  167. next_sibling = target.get_next_sibling()
  168. if next_sibling:
  169. target.move_to(next_sibling, 'right')
  170. return Message(_('Forum "%(name)s" has been moved down.') % {'name': target.name}, 'success'), False
  171. return Message(_('Forum "%(name)s" is last child of its parent node and cannot be moved down.') % {'name': target.name}, 'info'), False
  172. class Edit(FormWidget):
  173. admin = site.get_action('forums')
  174. id = 'edit'
  175. name = _("Edit Forum")
  176. fallback = 'admin_forums'
  177. form = ForumForm
  178. target_name = 'name'
  179. notfound_message = _('Requested Forum could not be found.')
  180. submit_fallback = True
  181. def get_url(self, model):
  182. return reverse('admin_forums_edit', model)
  183. def get_edit_url(self, model):
  184. return self.get_url(model)
  185. def get_form(self, target):
  186. if target.type == 'category':
  187. self.name = _("Edit Category")
  188. self.form = CategoryForm
  189. if target.type == 'redirect':
  190. self.name = _("Edit Redirect")
  191. self.form = RedirectForm
  192. return self.form
  193. def get_form_instance(self, form, target, initial, post=False):
  194. form_inst = super(Edit, self).get_form_instance(form, target, initial, post)
  195. valid_targets = Forum.tree.get(token='root').get_descendants(include_self=target.type == 'category').exclude(Q(lft__gte=target.lft) & Q(rght__lte=target.rght))
  196. form_inst.fields['parent'] = TreeNodeChoiceField(queryset=valid_targets, level_indicator=u'- - ')
  197. return form_inst
  198. def get_initial_data(self, model):
  199. initial = {
  200. 'parent': model.parent,
  201. 'name': model.name,
  202. 'description': model.description,
  203. }
  204. if model.type == 'redirect':
  205. initial['redirect'] = model.redirect
  206. else:
  207. initial['template'] = model.template
  208. initial['show_details'] = model.show_details
  209. initial['style'] = model.style
  210. initial['closed'] = model.closed
  211. if model.type == 'forum':
  212. initial['prune_start'] = model.prune_start
  213. initial['prune_last'] = model.prune_last
  214. return initial
  215. def submit_form(self, form, target):
  216. target.name = form.cleaned_data['name']
  217. target.slug = slugify(form.cleaned_data['name'])
  218. target.set_description(form.cleaned_data['description'])
  219. if target.type == 'redirect':
  220. target.redirect = form.cleaned_data['redirect']
  221. else:
  222. target.template = form.cleaned_data['template']
  223. target.show_details = form.cleaned_data['show_details']
  224. target.style = form.cleaned_data['style']
  225. target.closed = form.cleaned_data['closed']
  226. if target.type == 'forum':
  227. target.prune_start = form.cleaned_data['prune_start']
  228. target.prune_last = form.cleaned_data['prune_last']
  229. if form.cleaned_data['parent'].pk != target.parent.pk:
  230. target.move_to(form.cleaned_data['parent'], 'last-child')
  231. self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
  232. target.save(force_update=True)
  233. Forum.objects.populate_tree(True)
  234. if form.cleaned_data['perms']:
  235. target.copy_permissions(form.cleaned_data['perms'])
  236. if form.cleaned_data['parent'].pk != target.parent.pk or form.cleaned_data['perms']:
  237. self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
  238. return target, Message(_('Changes in forum "%(name)s" have been saved.') % {'name': self.original_name}, 'success')
  239. class Delete(FormWidget):
  240. admin = site.get_action('forums')
  241. id = 'delete'
  242. name = _("Delete Forum")
  243. fallback = 'admin_forums'
  244. template = 'delete'
  245. form = DeleteForm
  246. target_name = 'name'
  247. notfound_message = _('Requested Forum could not be found.')
  248. submit_fallback = True
  249. def get_url(self, model):
  250. return reverse('admin_forums_delete', model)
  251. def get_form(self, target):
  252. if target.type == 'category':
  253. self.name = _("Delete Category")
  254. if target.type == 'redirect':
  255. self.name = _("Delete Redirect")
  256. return self.form
  257. def get_form_instance(self, form, target, initial, post=False):
  258. if post:
  259. form_inst = form(self.request.POST, forum=target, request=self.request, initial=self.get_initial_data(target))
  260. else:
  261. form_inst = form(forum=target, request=self.request, initial=self.get_initial_data(target))
  262. if target.type != 'forum':
  263. del form_inst.fields['contents']
  264. valid_targets = Forum.tree.get(token='root').get_descendants().exclude(Q(lft__gte=target.lft) & Q(rght__lte=target.rght))
  265. form_inst.fields['subforums'] = TreeNodeChoiceField(queryset=valid_targets, required=False, empty_label=_("Remove with forum"), level_indicator=u'- - ')
  266. return form_inst
  267. def submit_form(self, form, target):
  268. if target.type == 'forum':
  269. new_forum = form.cleaned_data['contents']
  270. if new_forum:
  271. target.move_content(new_forum)
  272. new_forum.sync()
  273. new_forum.save(force_update=True)
  274. new_parent = form.cleaned_data['subforums']
  275. if new_parent:
  276. for child in target.get_descendants():
  277. if child.parent_id == target.pk:
  278. child.move_to(new_parent, 'last-child')
  279. child.save(force_update=True)
  280. else:
  281. for child in target.get_descendants().order_by('-lft'):
  282. Forum.objects.get(id=child.pk).delete()
  283. Forum.objects.get(id=target.pk).delete()
  284. Forum.objects.populate_tree(True)
  285. self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
  286. return target, Message(_('Forum "%(name)s" has been deleted.') % {'name': self.original_name}, 'success')