import copy from urlparse import urlparse from django.core.urlresolvers import resolve, reverse as django_reverse from django.db.models import Q from django.http import Http404 from django.shortcuts import redirect from django.utils.translation import ugettext as _ from mptt.forms import TreeNodeChoiceField from misago.admin import site from misago.apps.admin.widgets import * from misago.models import Forum from misago.utils.strings import slugify from misago.apps.admin.forums.forms import NewNodeForm, CategoryForm, ForumForm, RedirectForm, DeleteForm def reverse(route, target=None): if target: return django_reverse(route, kwargs={'target': target.pk, 'slug': target.slug}) return django_reverse(route) """ Views """ class List(ListWidget): admin = site.get_action('forums') id = 'list' columns = ( ('forum', _("Forum")), ) nothing_checked_message = _('You have to select at least one forum.') actions = ( ('resync_fast', _("Resynchronize forums (fast)")), ('resync', _("Resynchronize forums")), ) empty_message = _('No forums are currently defined.') def get_items(self): return self.admin.model.objects.get(special='root').get_descendants() def sort_items(self, page_items, sorting_method): return page_items.order_by('lft') def get_item_actions(self, item): if item.type == 'category': return ( self.action('chevron-up', _("Move Category Up"), reverse('admin_forums_up', item), post=True), self.action('chevron-down', _("Move Category Down"), reverse('admin_forums_down', item), post=True), self.action('pencil', _("Edit Category"), reverse('admin_forums_edit', item)), self.action('remove', _("Delete Category"), reverse('admin_forums_delete', item)), ) if item.type == 'forum': return ( self.action('chevron-up', _("Move Forum Up"), reverse('admin_forums_up', item), post=True), self.action('chevron-down', _("Move Forum Down"), reverse('admin_forums_down', item), post=True), self.action('pencil', _("Edit Forum"), reverse('admin_forums_edit', item)), self.action('remove', _("Delete Forum"), reverse('admin_forums_delete', item)), ) return ( self.action('chevron-up', _("Move Redirect Up"), reverse('admin_forums_up', item), post=True), self.action('chevron-down', _("Move Redirect Down"), reverse('admin_forums_down', item), post=True), self.action('pencil', _("Edit Redirect"), reverse('admin_forums_edit', item)), self.action('remove', _("Delete Redirect"), reverse('admin_forums_delete', item)), ) def action_resync_fast(self, items, checked): for forum in items: if forum.pk in checked: forum.sync() forum.save(force_update=True) return Message(_('Selected forums have been resynchronized successfully.'), 'success'), reverse('admin_forums') def action_resync(self, items, checked): clean_checked = [] for item in items: if item.pk in checked and item.type == 'forum': clean_checked.append(item.pk) if not clean_checked: return Message(_('Only forums can be resynchronized.'), 'error'), reverse('admin_forums') self.request.session['sync_forums'] = clean_checked return Message('Meh', 'success'), django_reverse('admin_forums_resync') def resync_forums(request, forum=0, progress=0): progress = int(progress) forums = request.session.get('sync_forums') if not forums: request.messages.set_flash(Message(_('No forums to resynchronize.')), 'info', 'forums') return redirect(reverse('admin_forums')) try: if not forum: forum = request.session['sync_forums'].pop() forum = Forum.objects.get(id=forum) except Forum.DoesNotExist: del request.session['sync_forums'] request.messages.set_flash(Message(_('Forum for resynchronization does not exist.')), 'error', 'forums') return redirect(reverse('admin_forums')) # Sync 50 threads threads_total = forum.thread_set.count() for thread in forum.thread_set.all()[progress:(progress+1)]: thread.sync() thread.save(force_update=True) progress += 1 if not threads_total: return redirect(django_reverse('admin_forums_resync')) # Render Progress response = request.theme.render_to_response('processing.html', { 'task_name': _('Resynchronizing Forums'), 'target_name': forum.name, 'message': _('Resynchronized %(progress)s from %(total)s threads') % {'progress': progress, 'total': threads_total}, 'progress': progress * 100 / threads_total, 'cancel_url': reverse('admin_forums'), }, context_instance=RequestContext(request)); # Redirect where to? if progress >= threads_total: forum.sync() forum.save(force_update=True) response['refresh'] = '2;url=%s' % django_reverse('admin_forums_resync') else: response['refresh'] = '2;url=%s' % django_reverse('admin_forums_resync', kwargs={'forum': forum.pk, 'progress': progress}) return response class NewNode(FormWidget): admin = site.get_action('forums') id = 'new' fallback = 'admin_forums' form = NewNodeForm submit_button = _("Save Node") def get_new_url(self, model): return reverse('admin_forums_new') def get_edit_url(self, model): return reverse('admin_forums_edit', model) def get_initial_data(self, model): print 'CALL!' if not self.request.session.get('forums_admin_preffs'): print 'NO PATTERN!' return {} ref = self.request.META.get('HTTP_REFERER') if ref: parsed = urlparse(self.request.META.get('HTTP_REFERER')); try: link = resolve(parsed.path) if not link.url_name == 'admin_forums_new': return {} except Http404: return {} try: init = self.request.session.get('forums_admin_preffs') del self.request.session['forums_admin_preffs'] return { 'parent': Forum.objects.get(id=init['parent']), 'perms': Forum.objects.get(id=init['perms']) if init['perms'] else None, 'role': init['role'], } except (KeyError, Forum.DoesNotExist): return {} def submit_form(self, form, target): new_forum = Forum( name=form.cleaned_data['name'], slug=slugify(form.cleaned_data['name']), type=form.cleaned_data['role'], attrs=form.cleaned_data['attrs'], style=form.cleaned_data['style'], ) new_forum.set_description(form.cleaned_data['description']) if form.cleaned_data['role'] == 'redirect': new_forum.redirect = form.cleaned_data['redirect'] else: new_forum.closed = form.cleaned_data['closed'] new_forum.show_details = form.cleaned_data['show_details'] new_forum.insert_at(form.cleaned_data['parent'], position='last-child', save=True) Forum.objects.populate_tree(True) if form.cleaned_data['perms']: new_forum.copy_permissions(form.cleaned_data['perms']) self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1 self.request.session['forums_admin_preffs'] = { 'parent': form.cleaned_data['parent'].pk, 'perms': form.cleaned_data['perms'].pk if form.cleaned_data['perms'] else None, 'role': form.cleaned_data['role'], } if form.cleaned_data['role'] == 'category': return new_forum, Message(_('New Category has been created.'), 'success') if form.cleaned_data['role'] == 'forum': return new_forum, Message(_('New Forum has been created.'), 'success') if form.cleaned_data['role'] == 'redirect': return new_forum, Message(_('New Redirect has been created.'), 'success') class Up(ButtonWidget): admin = site.get_action('forums') id = 'up' fallback = 'admin_forums' notfound_message = _('Requested Forum could not be found.') def action(self, target): previous_sibling = target.get_previous_sibling() if previous_sibling: target.move_to(previous_sibling, 'left') return Message(_('Forum "%(name)s" has been moved up.') % {'name': target.name}, 'success'), False return Message(_('Forum "%(name)s" is first child of its parent node and cannot be moved up.') % {'name': target.name}, 'info'), False class Down(ButtonWidget): admin = site.get_action('forums') id = 'down' fallback = 'admin_forums' notfound_message = _('Requested Forum could not be found.') def action(self, target): next_sibling = target.get_next_sibling() if next_sibling: target.move_to(next_sibling, 'right') return Message(_('Forum "%(name)s" has been moved down.') % {'name': target.name}, 'success'), False return Message(_('Forum "%(name)s" is last child of its parent node and cannot be moved down.') % {'name': target.name}, 'info'), False class Edit(FormWidget): admin = site.get_action('forums') id = 'edit' name = _("Edit Forum") fallback = 'admin_forums' form = ForumForm target_name = 'name' notfound_message = _('Requested Forum could not be found.') submit_fallback = True def get_url(self, model): return reverse('admin_forums_edit', model) def get_edit_url(self, model): return self.get_url(model) def get_form(self, target): if target.type == 'category': self.name = _("Edit Category") self.form = CategoryForm if target.type == 'redirect': self.name = _("Edit Redirect") self.form = RedirectForm return self.form def get_form_instance(self, form, target, initial, post=False): form_inst = super(Edit, self).get_form_instance(form, target, initial, post) valid_targets = Forum.objects.get(special='root').get_descendants(include_self=target.type == 'category').exclude(Q(lft__gte=target.lft) & Q(rght__lte=target.rght)) form_inst.fields['parent'] = TreeNodeChoiceField(queryset=valid_targets, level_indicator=u'- - ') form_inst.target_forum = target return form_inst def get_initial_data(self, model): initial = { 'parent': model.parent, 'name': model.name, 'description': model.description, } if model.type == 'redirect': initial['redirect'] = model.redirect else: initial['attrs'] = model.attrs initial['show_details'] = model.show_details initial['style'] = model.style initial['closed'] = model.closed if model.type == 'forum': initial['prune_start'] = model.prune_start initial['prune_last'] = model.prune_last initial['pruned_archive'] = model.pruned_archive return initial def submit_form(self, form, target): target.name = form.cleaned_data['name'] target.slug = slugify(form.cleaned_data['name']) target.set_description(form.cleaned_data['description']) if target.type == 'redirect': target.redirect = form.cleaned_data['redirect'] else: target.attrs = form.cleaned_data['attrs'] target.show_details = form.cleaned_data['show_details'] target.style = form.cleaned_data['style'] target.closed = form.cleaned_data['closed'] if target.type == 'forum': target.prune_start = form.cleaned_data['prune_start'] target.prune_last = form.cleaned_data['prune_last'] target.pruned_archive = form.cleaned_data['pruned_archive'] if form.cleaned_data['parent'].pk != target.parent.pk: target.move_to(form.cleaned_data['parent'], 'last-child') self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1 target.save(force_update=True) Forum.objects.populate_tree(True) if form.cleaned_data['perms']: target.copy_permissions(form.cleaned_data['perms']) if form.cleaned_data['parent'].pk != target.parent.pk or form.cleaned_data['perms']: self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1 if self.original_name != target.name: target.sync_name() return target, Message(_('Changes in forum "%(name)s" have been saved.') % {'name': self.original_name}, 'success') class Delete(FormWidget): admin = site.get_action('forums') id = 'delete' name = _("Delete Forum") fallback = 'admin_forums' template = 'delete' form = DeleteForm target_name = 'name' notfound_message = _('Requested Forum could not be found.') submit_fallback = True def get_url(self, model): return reverse('admin_forums_delete', model) def get_form(self, target): if target.type == 'category': self.name = _("Delete Category") if target.type == 'redirect': self.name = _("Delete Redirect") return self.form def get_form_instance(self, form, target, initial, post=False): if post: form_inst = form(self.request.POST, forum=target, request=self.request, initial=self.get_initial_data(target)) else: form_inst = form(forum=target, request=self.request, initial=self.get_initial_data(target)) if target.type != 'forum': del form_inst.fields['contents'] valid_targets = Forum.objects.get(special='root').get_descendants().exclude(Q(lft__gte=target.lft) & Q(rght__lte=target.rght)) form_inst.fields['subforums'] = TreeNodeChoiceField(queryset=valid_targets, required=False, empty_label=_("Remove with forum"), level_indicator=u'- - ') return form_inst def submit_form(self, form, target): if target.type == 'forum': new_forum = form.cleaned_data['contents'] if new_forum: target.move_content(new_forum) new_forum.sync() new_forum.save(force_update=True) new_parent = form.cleaned_data['subforums'] if new_parent: for child in target.get_descendants(): if child.parent_id == target.pk: child.move_to(new_parent, 'last-child') child.save(force_update=True) else: for child in target.get_descendants().order_by('-lft'): Forum.objects.get(id=child.pk).delete() Forum.objects.get(id=target.pk).delete() Forum.objects.populate_tree(True) self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1 return target, Message(_('Forum "%(name)s" has been deleted.') % {'name': self.original_name}, 'success')