Browse Source

Refactored large portions of code

Ralfp 12 years ago
parent
commit
1eac8d953c
42 changed files with 289 additions and 99 deletions
  1. 2 1
      misago/acl/builder.py
  2. 1 1
      misago/acl/permissions/special.py
  3. 3 3
      misago/acl/permissions/threads.py
  4. 1 1
      misago/acl/permissions/usercp.py
  5. 8 8
      misago/apps/admin/forums/forms.py
  6. 5 5
      misago/apps/admin/forums/views.py
  7. 8 8
      misago/apps/admin/roles/views.py
  8. 0 0
      misago/apps/announcements/__init__.py
  9. 2 0
      misago/apps/announcements/mixins.py
  10. 6 0
      misago/apps/announcements/urls.py
  11. 5 0
      misago/apps/errors.py
  12. 56 0
      misago/apps/forumbase/list.py
  13. 0 0
      misago/apps/oldthreads/__init__.py
  14. 3 3
      misago/apps/oldthreads/forms.py
  15. 34 0
      misago/apps/oldthreads/urls.py
  16. 0 0
      misago/apps/oldthreads/views/__init__.py
  17. 0 0
      misago/apps/oldthreads/views/base.py
  18. 0 0
      misago/apps/oldthreads/views/changelog.py
  19. 0 0
      misago/apps/oldthreads/views/delete.py
  20. 0 0
      misago/apps/oldthreads/views/details.py
  21. 0 0
      misago/apps/oldthreads/views/jumps.py
  22. 0 0
      misago/apps/oldthreads/views/karmas.py
  23. 3 3
      misago/apps/oldthreads/views/list.py
  24. 0 0
      misago/apps/oldthreads/views/posting.py
  25. 2 2
      misago/apps/oldthreads/views/thread.py
  26. 0 0
      misago/apps/privatethreads/__init__.py
  27. 2 0
      misago/apps/privatethreads/mixins.py
  28. 6 0
      misago/apps/privatethreads/urls.py
  29. 2 0
      misago/apps/reports/mixins.py
  30. 6 0
      misago/apps/reports/urls.py
  31. 2 0
      misago/apps/threads/mixins.py
  32. 33 30
      misago/apps/threads/urls.py
  33. 56 0
      misago/apps/threads/views.py
  34. 4 4
      misago/fixtures/forums.py
  35. 4 4
      misago/fixtures/userroles.py
  36. 1 1
      misago/management/commands/adduser.py
  37. 5 5
      misago/migrations/0001_initial.py
  38. 16 9
      misago/models/forummodel.py
  39. 5 4
      misago/models/rolemodel.py
  40. 2 2
      misago/models/usermodel.py
  41. 4 1
      misago/urls.py
  42. 2 4
      templates/cranefly/threads/posting.html

+ 2 - 1
misago/acl/builder.py

@@ -60,7 +60,8 @@ def acl(request, user):
 
 
 def build_acl(request, roles):
 def build_acl(request, roles):
     acl = ACL(request.monitor['acl_version'])
     acl = ACL(request.monitor['acl_version'])
-    forums = Forum.objects.get(token='root').get_descendants().order_by('lft')
+    forums = (Forum.objects.filter(special__in=('announcements', 'private', 'reports'))
+              | Forum.objects.get(special='root').get_descendants().order_by('lft'))
     perms = []
     perms = []
     forum_roles = {}
     forum_roles = {}
 
 

+ 1 - 1
misago/acl/permissions/special.py

@@ -4,7 +4,7 @@ from misago.acl.builder import BaseACL
 from misago.forms import YesNoSwitch
 from misago.forms import YesNoSwitch
 
 
 def make_form(request, role, form):
 def make_form(request, role, form):
-    if not role.token and request.user.is_god():
+    if not role.special and request.user.is_god():
         form.base_fields['can_use_acp'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
         form.base_fields['can_use_acp'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
         form.base_fields['can_use_mcp'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
         form.base_fields['can_use_mcp'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
         form.layout.append((
         form.layout.append((

+ 3 - 3
misago/acl/permissions/threads.py

@@ -48,7 +48,7 @@ def make_forum_form(request, role, form):
     form.base_fields['can_pin_threads'] = forms.TypedChoiceField(choices=(
     form.base_fields['can_pin_threads'] = forms.TypedChoiceField(choices=(
                                                                  (0, _("No")),
                                                                  (0, _("No")),
                                                                  (1, _("Yes, to stickies")),
                                                                  (1, _("Yes, to stickies")),
-                                                                 (2, _("Yes, to annoucements")),
+                                                                 (2, _("Yes, to announcements")),
                                                                  ), coerce=int)
                                                                  ), coerce=int)
     form.base_fields['can_edit_threads_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
     form.base_fields['can_edit_threads_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
     form.base_fields['can_move_threads_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
     form.base_fields['can_move_threads_posts'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
@@ -121,7 +121,7 @@ def make_forum_form(request, role, form):
                          ('can_approve', {'label': _("Can accept threads and posts")}),
                          ('can_approve', {'label': _("Can accept threads and posts")}),
                          ('can_edit_labels', {'label': _("Can edit thread labels")}),
                          ('can_edit_labels', {'label': _("Can edit thread labels")}),
                          ('can_see_changelog', {'label': _("Can see edits history")}),
                          ('can_see_changelog', {'label': _("Can see edits history")}),
-                         ('can_make_annoucements', {'label': _("Can make annoucements")}),
+                         ('can_make_announcements', {'label': _("Can make announcements")}),
                          ('can_pin_threads', {'label': _("Can change threads weight")}),
                          ('can_pin_threads', {'label': _("Can change threads weight")}),
                          ('can_edit_threads_posts', {'label': _("Can edit threads and posts")}),
                          ('can_edit_threads_posts', {'label': _("Can edit threads and posts")}),
                          ('can_move_threads_posts', {'label': _("Can move, merge and split threads and posts")}),
                          ('can_move_threads_posts', {'label': _("Can move, merge and split threads and posts")}),
@@ -560,7 +560,7 @@ def build_forums(acl, perms, forums, forum_roles):
                      'can_approve': False,
                      'can_approve': False,
                      'can_edit_labels': False,
                      'can_edit_labels': False,
                      'can_see_changelog': False,
                      'can_see_changelog': False,
-                     'can_make_annoucements': False,
+                     'can_make_announcements': False,
                      'can_pin_threads': 0,
                      'can_pin_threads': 0,
                      'can_edit_threads_posts': False,
                      'can_edit_threads_posts': False,
                      'can_move_threads_posts': False,
                      'can_move_threads_posts': False,

+ 1 - 1
misago/acl/permissions/usercp.py

@@ -6,7 +6,7 @@ from misago.acl.builder import BaseACL
 from misago.forms import YesNoSwitch
 from misago.forms import YesNoSwitch
 
 
 def make_form(request, role, form):
 def make_form(request, role, form):
-    if role.token != 'guest':
+    if role.special != 'guest':
         form.base_fields['name_changes_allowed'] = forms.IntegerField(min_value=0, initial=1)
         form.base_fields['name_changes_allowed'] = forms.IntegerField(min_value=0, initial=1)
         form.base_fields['changes_expire'] = forms.IntegerField(min_value=0, initial=0)
         form.base_fields['changes_expire'] = forms.IntegerField(min_value=0, initial=0)
         form.base_fields['can_use_signature'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)
         form.base_fields['can_use_signature'] = forms.BooleanField(widget=YesNoSwitch, initial=False, required=False)

+ 8 - 8
misago/apps/admin/forums/forms.py

@@ -40,8 +40,8 @@ class CategoryForm(Form):
              )
              )
 
 
     def finalize_form(self):
     def finalize_form(self):
-        self.fields['parent'] = TreeNodeChoiceField(queryset=Forum.tree.get(token='root').get_descendants(include_self=True), level_indicator=u'- - ')
-        self.fields['perms'] = TreeNodeChoiceField(queryset=Forum.tree.get(token='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions"))
+        self.fields['parent'] = TreeNodeChoiceField(queryset=Forum.tree.get(special='root').get_descendants(include_self=True), level_indicator=u'- - ')
+        self.fields['perms'] = TreeNodeChoiceField(queryset=Forum.tree.get(special='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions"))
 
 
     def clean_attrs(self):
     def clean_attrs(self):
         clean = []
         clean = []
@@ -97,8 +97,8 @@ class ForumForm(Form):
               )
               )
 
 
     def finalize_form(self):
     def finalize_form(self):
-        self.fields['parent'] = TreeNodeChoiceField(queryset=Forum.tree.get(token='root').get_descendants(), level_indicator=u'- - ')
-        self.fields['perms'] = TreeNodeChoiceField(queryset=Forum.tree.get(token='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions"))
+        self.fields['parent'] = TreeNodeChoiceField(queryset=Forum.tree.get(special='root').get_descendants(), level_indicator=u'- - ')
+        self.fields['perms'] = TreeNodeChoiceField(queryset=Forum.tree.get(special='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions"))
 
 
     def clean_attrs(self):
     def clean_attrs(self):
         clean = []
         clean = []
@@ -141,8 +141,8 @@ class RedirectForm(Form):
               )
               )
 
 
     def finalize_form(self):
     def finalize_form(self):
-        self.fields['parent'] = TreeNodeChoiceField(queryset=Forum.tree.get(token='root').get_descendants(), level_indicator=u'- - ')
-        self.fields['perms'] = TreeNodeChoiceField(queryset=Forum.tree.get(token='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions"))
+        self.fields['parent'] = TreeNodeChoiceField(queryset=Forum.tree.get(special='root').get_descendants(), level_indicator=u'- - ')
+        self.fields['perms'] = TreeNodeChoiceField(queryset=Forum.tree.get(special='root').get_descendants(), level_indicator=u'- - ', required=False, empty_label=_("Don't copy permissions"))
 
 
 
 
 class DeleteForm(Form):
 class DeleteForm(Form):
@@ -161,8 +161,8 @@ class DeleteForm(Form):
         super(DeleteForm, self).__init__(*args, **kwargs)
         super(DeleteForm, self).__init__(*args, **kwargs)
 
 
     def finalize_form(self):
     def finalize_form(self):
-        self.fields['contents'] = TreeNodeChoiceField(queryset=Forum.tree.get(token='root').get_descendants(), required=False, empty_label=_("Remove with forum"), level_indicator=u'- - ')
-        self.fields['subforums'] = TreeNodeChoiceField(queryset=Forum.tree.get(token='root').get_descendants(), required=False, empty_label=_("Remove with forum"), level_indicator=u'- - ')
+        self.fields['contents'] = TreeNodeChoiceField(queryset=Forum.tree.get(special='root').get_descendants(), required=False, empty_label=_("Remove with forum"), level_indicator=u'- - ')
+        self.fields['subforums'] = TreeNodeChoiceField(queryset=Forum.tree.get(special='root').get_descendants(), required=False, empty_label=_("Remove with forum"), level_indicator=u'- - ')
 
 
     def clean_contents(self):
     def clean_contents(self):
         data = self.cleaned_data['contents']
         data = self.cleaned_data['contents']

+ 5 - 5
misago/apps/admin/forums/views.py

@@ -32,7 +32,7 @@ class List(ListWidget):
     empty_message = _('No forums are currently defined.')
     empty_message = _('No forums are currently defined.')
 
 
     def get_items(self):
     def get_items(self):
-        return self.admin.model.objects.get(token='root').get_descendants()
+        return self.admin.model.objects.get(special='root').get_descendants()
 
 
     def sort_items(self, page_items, sorting_method):
     def sort_items(self, page_items, sorting_method):
         return page_items.order_by('lft')
         return page_items.order_by('lft')
@@ -138,7 +138,7 @@ class NewForum(FormWidget):
         return new_forum, Message(_('New Forum has been created.'), 'success')
         return new_forum, Message(_('New Forum has been created.'), 'success')
 
 
     def __call__(self, request):
     def __call__(self, request):
-        if self.admin.model.objects.get(token='root').get_descendants().count() == 0:
+        if self.admin.model.objects.get(special='root').get_descendants().count() == 0:
             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)
             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)
             return redirect(self.get_fallback_url())
             return redirect(self.get_fallback_url())
         return super(NewForum, self).__call__(request)
         return super(NewForum, self).__call__(request)
@@ -176,7 +176,7 @@ class NewRedirect(FormWidget):
         return new_forum, Message(_('New Redirect has been created.'), 'success')
         return new_forum, Message(_('New Redirect has been created.'), 'success')
 
 
     def __call__(self, request):
     def __call__(self, request):
-        if self.admin.model.objects.get(token='root').get_descendants().count() == 0:
+        if self.admin.model.objects.get(special='root').get_descendants().count() == 0:
             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)
             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)
             return redirect(self.get_fallback_url())
             return redirect(self.get_fallback_url())
         return super(NewRedirect, self).__call__(request)
         return super(NewRedirect, self).__call__(request)
@@ -237,7 +237,7 @@ class Edit(FormWidget):
 
 
     def get_form_instance(self, form, target, initial, post=False):
     def get_form_instance(self, form, target, initial, post=False):
         form_inst = super(Edit, self).get_form_instance(form, target, initial, post)
         form_inst = super(Edit, self).get_form_instance(form, target, initial, post)
-        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))
+        valid_targets = Forum.tree.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.fields['parent'] = TreeNodeChoiceField(queryset=valid_targets, level_indicator=u'- - ')
         return form_inst
         return form_inst
 
 
@@ -322,7 +322,7 @@ class Delete(FormWidget):
             form_inst = form(forum=target, request=self.request, initial=self.get_initial_data(target))
             form_inst = form(forum=target, request=self.request, initial=self.get_initial_data(target))
         if target.type != 'forum':
         if target.type != 'forum':
             del form_inst.fields['contents']
             del form_inst.fields['contents']
-        valid_targets = Forum.tree.get(token='root').get_descendants().exclude(Q(lft__gte=target.lft) & Q(rght__lte=target.rght))
+        valid_targets = Forum.tree.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'- - ')
         form_inst.fields['subforums'] = TreeNodeChoiceField(queryset=valid_targets, required=False, empty_label=_("Remove with forum"), level_indicator=u'- - ')
         return form_inst
         return form_inst
 
 

+ 8 - 8
misago/apps/admin/roles/views.py

@@ -44,7 +44,7 @@ class List(ListWidget):
     def action_delete(self, items, checked):
     def action_delete(self, items, checked):
         for item in items:
         for item in items:
             if unicode(item.pk) in checked:
             if unicode(item.pk) in checked:
-                if item.token:
+                if item.special:
                     return Message(_('You cannot delete system roles.'), 'error'), reverse('admin_roles')
                     return Message(_('You cannot delete system roles.'), 'error'), reverse('admin_roles')
                 if item.protected and not self.request.user.is_god():
                 if item.protected and not self.request.user.is_god():
                     return Message(_('You cannot delete protected roles.'), 'error'), reverse('admin_roles')
                     return Message(_('You cannot delete protected roles.'), 'error'), reverse('admin_roles')
@@ -127,16 +127,16 @@ class Forums(ListWidget):
         return reverse('admin_roles_masks', self.role) 
         return reverse('admin_roles_masks', self.role) 
     
     
     def get_items(self):
     def get_items(self):
-        return Forum.objects.get(token='root').get_descendants()
+        return Forum.objects.get(special='root').get_descendants()
     
     
     def sort_items(self, page_items, sorting_method):
     def sort_items(self, page_items, sorting_method):
         final_items = []
         final_items = []
-        for forum in Forum.objects.filter(token__in=['annoucements', 'reports', 'private']).order_by('token'):
-            if forum.token == 'annoucements':
-                forum.name = _("Global Annoucements")
-            if forum.token == 'reports':
+        for forum in Forum.objects.filter(special__in=['announcements', 'reports', 'private']).order_by('special'):
+            if forum.special == 'announcements':
+                forum.name = _("Global Announcements")
+            if forum.special == 'reports':
                 forum.name = _("Reports")
                 forum.name = _("Reports")
-            if forum.token == 'private':
+            if forum.special == 'private':
                 forum.name = _("Private Discussions")
                 forum.name = _("Private Discussions")
             final_items.append(forum)
             final_items.append(forum)
         for forum in page_items.order_by('lft').all():
         for forum in page_items.order_by('lft').all():
@@ -249,7 +249,7 @@ class Delete(ButtonWidget):
     notfound_message = _('Requested Role could not be found.')
     notfound_message = _('Requested Role could not be found.')
     
     
     def action(self, target):
     def action(self, target):
-        if target.token:
+        if target.special:
             return Message(_('You cannot delete system roles.'), 'error'), reverse('admin_roles')
             return Message(_('You cannot delete system roles.'), 'error'), reverse('admin_roles')
         if target.protected and not self.request.user.is_god():
         if target.protected and not self.request.user.is_god():
             return Message(_('This role is protected.'), 'error'), reverse('admin_roles')
             return Message(_('This role is protected.'), 'error'), reverse('admin_roles')

+ 0 - 0
misago/apps/annoucements/__init__.py → misago/apps/announcements/__init__.py


+ 2 - 0
misago/apps/announcements/mixins.py

@@ -0,0 +1,2 @@
+class TypeMixin(object):
+    templates_prefix = 'announcements'

+ 6 - 0
misago/apps/announcements/urls.py

@@ -0,0 +1,6 @@
+from django.conf.urls import patterns, url
+
+urlpatterns = patterns('misago.apps.announcements.views',
+    url(r'^$', 'ThreadsListView', name="announcements"),
+    url(r'^(?P<slug>(\w|-)+)-(?P<forum>\d+)/(?P<page>\d+)/$', 'ThreadsView', name="announcements"),
+)

+ 5 - 0
misago/apps/errors.py

@@ -1,5 +1,10 @@
 from django.template import RequestContext
 from django.template import RequestContext
 
 
+def error_not_implemented(request, *args, **kwargs):
+    """Generic "NOT IMPLEMENTED!" Error"""
+    raise NotImplemenetedError("This action is not implemented!")
+
+
 def error_view(request, error, message):
 def error_view(request, error, message):
     response = request.theme.render_to_response(('error%s.html' % error),
     response = request.theme.render_to_response(('error%s.html' % error),
                                                 {
                                                 {

+ 56 - 0
misago/apps/forumbase/list.py

@@ -0,0 +1,56 @@
+from django.template import RequestContext
+from misago.acl.exceptions import ACLError403, ACLError404
+from misago.apps.errors import error403, error404
+from misago.forms import FormFields
+from misago.models import Forum
+from misago.readstrackers import ForumsTracker, ThreadsTracker
+
+class ThreadsListBaseView(object):
+    def _fetch_forum(self):
+        self.fetch_forum()
+        self.proxy = Forum.objects.parents_aware_forum(self.forum)
+        self.request.acl.forums.allow_forum_view(self.forum)
+        if self.forum.level:
+            self.parents = Forum.objects.forum_parents(self.forum.pk)
+        if self.forum.lft + 1 != self.forum.rght:
+            self.forum.subforums = Forum.objects.treelist(self.request.acl.forums, self.forum, tracker=ForumsTracker(self.request.user))
+        self.tracker = ThreadsTracker(self.request, self.forum)
+    
+    def __new__(cls, request, **kwargs):
+        obj = super(ThreadsListBaseView, cls).__new__(cls)
+        return obj(request, **kwargs)
+
+    def __call__(self, request, **kwargs):
+        self.request = request
+        self.kwargs = kwargs
+        self.pagination = {}
+        self.parents = []
+        self.message = request.messages.get_message('threads')
+        try:
+            self._fetch_forum()
+            self.fetch_threads()
+            self.form = None
+            #self.make_form()
+            #if self.form:
+            #    response = self.handle_form()
+            #    if response:
+            #        return response
+        except Forum.DoesNotExist:
+            return error404(request)
+        except ACLError403 as e:
+            return error403(request, e.message)
+        except ACLError404 as e:
+            return error404(request, e.message)
+        # Merge proxy into forum
+        self.forum.closed = self.proxy.closed
+        return request.theme.render_to_response(('%s/list.html' % self.templates_prefix),
+                                                {
+                                                 'message': self.message,
+                                                 'forum': self.forum,
+                                                 'parents': self.parents,
+                                                 'count': self.count,
+                                                 'list_form': FormFields(self.form).fields if self.form else None,
+                                                 'threads': self.threads,
+                                                 'pagination': self.pagination,
+                                                 },
+                                                context_instance=RequestContext(request));

+ 0 - 0
misago/apps/forumbase/list/__init__.py → misago/apps/oldthreads/__init__.py


+ 3 - 3
misago/apps/threads/forms.py → misago/apps/oldthreads/forms.py

@@ -90,7 +90,7 @@ class SplitThreadForm(Form, ThreadNameMixin):
                                                                                     _("Thread name must contain at least one alpha-numeric character."),
                                                                                     _("Thread name must contain at least one alpha-numeric character."),
                                                                                     _("Thread name is too long. Try shorter name.")
                                                                                     _("Thread name is too long. Try shorter name.")
                                                                                     )])
                                                                                     )])
-        self.fields['thread_forum'] = ForumChoiceField(queryset=Forum.tree.get(token='root').get_descendants().filter(pk__in=self.request.acl.forums.acl['can_browse']))
+        self.fields['thread_forum'] = ForumChoiceField(queryset=Forum.tree.get(special='root').get_descendants().filter(pk__in=self.request.acl.forums.acl['can_browse']))
 
 
     def clean_thread_forum(self):
     def clean_thread_forum(self):
         new_forum = self.cleaned_data['thread_forum']
         new_forum = self.cleaned_data['thread_forum']
@@ -149,7 +149,7 @@ class MoveThreadsForm(Form):
         super(MoveThreadsForm, self).__init__(data, request=request, *args, **kwargs)
         super(MoveThreadsForm, self).__init__(data, request=request, *args, **kwargs)
 
 
     def finalize_form(self):
     def finalize_form(self):
-        self.fields['new_forum'] = ForumChoiceField(queryset=Forum.tree.get(token='root').get_descendants().filter(pk__in=self.request.acl.forums.acl['can_browse']))
+        self.fields['new_forum'] = ForumChoiceField(queryset=Forum.tree.get(special='root').get_descendants().filter(pk__in=self.request.acl.forums.acl['can_browse']))
         self.layout = [
         self.layout = [
                        [
                        [
                         None,
                         None,
@@ -175,7 +175,7 @@ class MergeThreadsForm(Form, ThreadNameMixin):
         super(MergeThreadsForm, self).__init__(data, request=request, *args, **kwargs)
         super(MergeThreadsForm, self).__init__(data, request=request, *args, **kwargs)
 
 
     def finalize_form(self):
     def finalize_form(self):
-        self.fields['new_forum'] = ForumChoiceField(queryset=Forum.tree.get(token='root').get_descendants().filter(pk__in=self.request.acl.forums.acl['can_browse']), initial=self.threads[0].forum)
+        self.fields['new_forum'] = ForumChoiceField(queryset=Forum.tree.get(special='root').get_descendants().filter(pk__in=self.request.acl.forums.acl['can_browse']), initial=self.threads[0].forum)
         self.fields['thread_name'] = forms.CharField(
         self.fields['thread_name'] = forms.CharField(
                                                      max_length=self.request.settings['thread_name_max'],
                                                      max_length=self.request.settings['thread_name_max'],
                                                      initial=self.threads[0].name,
                                                      initial=self.threads[0].name,

+ 34 - 0
misago/apps/oldthreads/urls.py

@@ -0,0 +1,34 @@
+from django.conf.urls import patterns, url
+
+urlpatterns = patterns('misago.apps.threads.views',
+    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/$', 'ThreadsView', name="forum"),
+    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/(?P<page>\d+)/$', 'ThreadsView', name="forum"),
+    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/new/$', 'PostingNewThreadView', name="thread_new"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/$', 'ThreadView', name="thread"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/last/$', 'LastReplyView', name="thread_last"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/find-(?P<post>\d+)/$', 'FindReplyView', name="thread_find"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/new/$', 'NewReplyView', name="thread_new"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/moderated/$', 'FirstModeratedView', name="thread_moderated"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/reported/$', 'FirstReportedView', name="thread_reported"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/show-hidden/$', 'ShowHiddenRepliesView', name="thread_show_hidden"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/watch/$', 'WatchThreadView', name="thread_watch"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/watch/email/$', 'WatchEmailThreadView', name="thread_watch_email"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/unwatch/$', 'UnwatchThreadView', name="thread_unwatch"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/unwatch/email/$', 'UnwatchEmailThreadView', name="thread_unwatch_email"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<page>\d+)/$', 'ThreadView', name="thread"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/reply/$', 'PostingView', name="thread_reply", kwargs={'mode': 'new_post'}),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<quote>\d+)/reply/$', 'PostingNewReplyView', name="thread_reply"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/edit/$', 'PostingEditThreadView', name="thread_edit"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/edit/$', 'PostingEditReplyView', name="post_edit"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/delete/$', 'DeleteView', name="thread_delete", kwargs={'mode': 'delete_thread'}),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/hide/$', 'DeleteView', name="thread_hide", kwargs={'mode': 'hide_thread'}),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/delete/$', 'DeleteView', name="post_delete", kwargs={'mode': 'delete_post'}),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/hide/$', 'DeleteView', name="post_hide", kwargs={'mode': 'hide_post'}),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/info/$', 'DetailsView', name="post_info"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/upvote/$', 'UpvotePostView', name="post_upvote"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/downvote/$', 'DownvotePostView', name="post_downvote"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/votes/$', 'KarmaVotesView', name="post_votes"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/$', 'ChangelogView', name="changelog"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/(?P<change>\d+)/$', 'ChangelogDiffView', name="changelog_diff"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/(?P<change>\d+)/revert/$', 'ChangelogRevertView', name="changelog_revert"),
+)

+ 0 - 0
misago/apps/threads/views/__init__.py → misago/apps/oldthreads/views/__init__.py


+ 0 - 0
misago/apps/threads/views/base.py → misago/apps/oldthreads/views/base.py


+ 0 - 0
misago/apps/threads/views/changelog.py → misago/apps/oldthreads/views/changelog.py


+ 0 - 0
misago/apps/threads/views/delete.py → misago/apps/oldthreads/views/delete.py


+ 0 - 0
misago/apps/threads/views/details.py → misago/apps/oldthreads/views/details.py


+ 0 - 0
misago/apps/threads/views/jumps.py → misago/apps/oldthreads/views/jumps.py


+ 0 - 0
misago/apps/threads/views/karmas.py → misago/apps/oldthreads/views/karmas.py


+ 3 - 3
misago/apps/threads/views/list.py → misago/apps/oldthreads/views/list.py

@@ -32,7 +32,7 @@ class ThreadsView(BaseView):
         self.pagination = make_pagination(page, self.count, self.request.settings.threads_per_page)
         self.pagination = make_pagination(page, self.count, self.request.settings.threads_per_page)
         self.threads = []
         self.threads = []
         ignored_users = []
         ignored_users = []
-        queryset_anno = Thread.objects.filter(Q(forum=Forum.objects.token_to_pk('annoucements')) | (Q(forum=self.forum) & Q(weight=2)))
+        queryset_anno = Thread.objects.filter(Q(forum=Forum.objects.special_pk('announcements')) | (Q(forum=self.forum) & Q(weight=2)))
         queryset_threads = self.request.acl.threads.filter_threads(self.request, self.forum, Thread.objects.filter(forum=self.forum).filter(weight__lt=2)).order_by('-weight', '-last')
         queryset_threads = self.request.acl.threads.filter_threads(self.request, self.forum, Thread.objects.filter(forum=self.forum).filter(weight__lt=2)).order_by('-weight', '-last')
         if self.request.user.is_authenticated():
         if self.request.user.is_authenticated():
             ignored_users = self.request.user.ignored_users()
             ignored_users = self.request.user.ignored_users()
@@ -58,7 +58,7 @@ class ThreadsView(BaseView):
             if acl['can_approve']:
             if acl['can_approve']:
                 actions.append(('accept', _('Accept threads')))
                 actions.append(('accept', _('Accept threads')))
             if acl['can_pin_threads'] == 2:
             if acl['can_pin_threads'] == 2:
-                actions.append(('annouce', _('Change to annoucements')))
+                actions.append(('annouce', _('Change to announcements')))
             if acl['can_pin_threads'] > 0:
             if acl['can_pin_threads'] > 0:
                 actions.append(('sticky', _('Change to sticky threads')))
                 actions.append(('sticky', _('Change to sticky threads')))
             if acl['can_pin_threads'] > 0:
             if acl['can_pin_threads'] > 0:
@@ -174,7 +174,7 @@ class ThreadsView(BaseView):
                 annouced.append(thread.pk)
                 annouced.append(thread.pk)
         if annouced:
         if annouced:
             Thread.objects.filter(id__in=annouced).update(weight=2)
             Thread.objects.filter(id__in=annouced).update(weight=2)
-            self.request.messages.set_flash(Message(_('Selected threads have been turned into annoucements.')), 'success', 'threads')
+            self.request.messages.set_flash(Message(_('Selected threads have been turned into announcements.')), 'success', 'threads')
 
 
     def action_sticky(self, ids):
     def action_sticky(self, ids):
         acl = self.request.acl.threads.get_role(self.forum)
         acl = self.request.acl.threads.get_role(self.forum)

+ 0 - 0
misago/apps/threads/views/posting.py → misago/apps/oldthreads/views/posting.py


+ 2 - 2
misago/apps/threads/views/thread.py → misago/apps/oldthreads/views/thread.py

@@ -340,7 +340,7 @@ class ThreadView(BaseView):
             if acl['can_approve'] and self.thread.moderated:
             if acl['can_approve'] and self.thread.moderated:
                 actions.append(('accept', _('Accept this thread')))
                 actions.append(('accept', _('Accept this thread')))
             if acl['can_pin_threads'] == 2 and self.thread.weight < 2:
             if acl['can_pin_threads'] == 2 and self.thread.weight < 2:
-                actions.append(('annouce', _('Change this thread to annoucement')))
+                actions.append(('annouce', _('Change this thread to announcement')))
             if acl['can_pin_threads'] > 0 and self.thread.weight != 1:
             if acl['can_pin_threads'] > 0 and self.thread.weight != 1:
                 actions.append(('sticky', _('Change this thread to sticky')))
                 actions.append(('sticky', _('Change this thread to sticky')))
             if acl['can_pin_threads'] > 0:
             if acl['can_pin_threads'] > 0:
@@ -419,7 +419,7 @@ class ThreadView(BaseView):
     def thread_action_annouce(self):
     def thread_action_annouce(self):
         self.thread.weight = 2
         self.thread.weight = 2
         self.thread.save(force_update=True)
         self.thread.save(force_update=True)
-        self.request.messages.set_flash(Message(_('Thread has been turned into annoucement.')), 'success', 'threads')
+        self.request.messages.set_flash(Message(_('Thread has been turned into announcement.')), 'success', 'threads')
 
 
     def thread_action_sticky(self):
     def thread_action_sticky(self):
         self.thread.weight = 1
         self.thread.weight = 1

+ 0 - 0
misago/apps/privatethreads/__init__.py


+ 2 - 0
misago/apps/privatethreads/mixins.py

@@ -0,0 +1,2 @@
+class TypeMixin(object):
+    templates_prefix = 'private'

+ 6 - 0
misago/apps/privatethreads/urls.py

@@ -0,0 +1,6 @@
+from django.conf.urls import patterns, url
+
+urlpatterns = patterns('misago.apps.privatethreads.views',
+    url(r'^$', 'ThreadsListView', name="private_threads"),
+    url(r'^(?P<page>\d+)/$', 'ThreadsView', name="private_threads"),
+)

+ 2 - 0
misago/apps/reports/mixins.py

@@ -0,0 +1,2 @@
+class TypeMixin(object):
+    templates_prefix = 'reports'

+ 6 - 0
misago/apps/reports/urls.py

@@ -0,0 +1,6 @@
+from django.conf.urls import patterns, url
+
+urlpatterns = patterns('misago.apps.reports.views',
+    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/$', 'ThreadsListView', name="reports"),
+    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/(?P<page>\d+)/$', 'ThreadsView', name="reports"),
+)

+ 2 - 0
misago/apps/threads/mixins.py

@@ -0,0 +1,2 @@
+class TypeMixin(object):
+    templates_prefix = 'threads'

+ 33 - 30
misago/apps/threads/urls.py

@@ -1,34 +1,37 @@
 from django.conf.urls import patterns, url
 from django.conf.urls import patterns, url
 
 
 urlpatterns = patterns('misago.apps.threads.views',
 urlpatterns = patterns('misago.apps.threads.views',
-    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/$', 'ThreadsView', name="forum"),
-    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/(?P<page>\d+)/$', 'ThreadsView', name="forum"),
-    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/new/$', 'PostingNewThreadView', name="thread_new"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/$', 'ThreadView', name="thread"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/last/$', 'LastReplyView', name="thread_last"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/find-(?P<post>\d+)/$', 'FindReplyView', name="thread_find"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/new/$', 'NewReplyView', name="thread_new"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/moderated/$', 'FirstModeratedView', name="thread_moderated"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/reported/$', 'FirstReportedView', name="thread_reported"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/show-hidden/$', 'ShowHiddenRepliesView', name="thread_show_hidden"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/watch/$', 'WatchThreadView', name="thread_watch"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/watch/email/$', 'WatchEmailThreadView', name="thread_watch_email"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/unwatch/$', 'UnwatchThreadView', name="thread_unwatch"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/unwatch/email/$', 'UnwatchEmailThreadView', name="thread_unwatch_email"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<page>\d+)/$', 'ThreadView', name="thread"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/reply/$', 'PostingView', name="thread_reply", kwargs={'mode': 'new_post'}),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<quote>\d+)/reply/$', 'PostingNewReplyView', name="thread_reply"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/edit/$', 'PostingEditThreadView', name="thread_edit"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/edit/$', 'PostingEditReplyView', name="post_edit"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/delete/$', 'DeleteView', name="thread_delete", kwargs={'mode': 'delete_thread'}),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/hide/$', 'DeleteView', name="thread_hide", kwargs={'mode': 'hide_thread'}),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/delete/$', 'DeleteView', name="post_delete", kwargs={'mode': 'delete_post'}),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/hide/$', 'DeleteView', name="post_hide", kwargs={'mode': 'hide_post'}),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/info/$', 'DetailsView', name="post_info"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/upvote/$', 'UpvotePostView', name="post_upvote"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/downvote/$', 'DownvotePostView', name="post_downvote"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/votes/$', 'KarmaVotesView', name="post_votes"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/$', 'ChangelogView', name="changelog"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/(?P<change>\d+)/$', 'ChangelogDiffView', name="changelog_diff"),
-    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/(?P<change>\d+)/revert/$', 'ChangelogRevertView', name="changelog_revert"),
+    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/$', 'ThreadsListView', name="forum"),
+    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/(?P<page>\d+)/$', 'ThreadsListView', name="forum"),
+)
+
+urlpatterns += patterns('misago.apps.errors',
+    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/new/$', 'error_not_implemented', name="thread_new"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/$', 'error_not_implemented', name="thread"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/last/$', 'error_not_implemented', name="thread_last"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/find-(?P<post>\d+)/$', 'error_not_implemented', name="thread_find"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/new/$', 'error_not_implemented', name="thread_new"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/moderated/$', 'error_not_implemented', name="thread_moderated"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/reported/$', 'error_not_implemented', name="thread_reported"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/show-hidden/$', 'error_not_implemented', name="thread_show_hidden"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/watch/$', 'error_not_implemented', name="thread_watch"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/watch/email/$', 'error_not_implemented', name="thread_watch_email"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/unwatch/$', 'error_not_implemented', name="thread_unwatch"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/unwatch/email/$', 'error_not_implemented', name="thread_unwatch_email"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<page>\d+)/$', 'error_not_implemented', name="thread"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/reply/$', 'error_not_implemented', name="thread_reply", kwargs={'mode': 'new_post'}),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<quote>\d+)/reply/$', 'error_not_implemented', name="thread_reply"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/edit/$', 'error_not_implemented', name="thread_edit"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/edit/$', 'error_not_implemented', name="post_edit"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/delete/$', 'error_not_implemented', name="thread_delete", kwargs={'mode': 'delete_thread'}),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/hide/$', 'error_not_implemented', name="thread_hide", kwargs={'mode': 'hide_thread'}),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/delete/$', 'error_not_implemented', name="post_delete", kwargs={'mode': 'delete_post'}),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/hide/$', 'error_not_implemented', name="post_hide", kwargs={'mode': 'hide_post'}),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/info/$', 'error_not_implemented', name="post_info"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/upvote/$', 'error_not_implemented', name="post_upvote"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/downvote/$', 'error_not_implemented', name="post_downvote"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/votes/$', 'error_not_implemented', name="post_votes"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/$', 'error_not_implemented', name="changelog"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/(?P<change>\d+)/$', 'error_not_implemented', name="changelog_diff"),
+    url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/(?P<post>\d+)/changelog/(?P<change>\d+)/revert/$', 'error_not_implemented', name="changelog_revert"),
 )
 )

+ 56 - 0
misago/apps/threads/views.py

@@ -0,0 +1,56 @@
+from misago.apps.forumbase.list import ThreadsListBaseView
+from misago.models import Forum, Thread
+from misago.utils.pagination import make_pagination
+from misago.apps.threads.mixins import TypeMixin
+
+class ThreadsListView(ThreadsListBaseView, TypeMixin):
+    def fetch_forum(self):
+        self.forum = Forum.objects.get(pk=self.kwargs.get('forum'), type='forum')
+
+    def threads_queryset(self):
+        announcements = Forum.objects.special_model('announcements')
+        annos_global = self.request.acl.threads.filter_threads(self.request, announcements, announcements.thread_set).order_by('-weight')
+        annos_forum = self.request.acl.threads.filter_threads(self.request, self.forum, self.forum.thread_set).filter(weight=2)
+        rest = self.request.acl.threads.filter_threads(self.request, self.forum, self.forum.thread_set).filter(weight=2)
+
+        # Dont display threads by ignored users (unless they are important)
+        if self.request.user.is_authenticated():
+            ignored_users = self.request.user.ignored_users()
+            if ignored_users:
+                rest = rest.extra(where=["`threads_thread`.`start_poster_id` IS NULL OR `threads_thread`.`start_poster_id` NOT IN (%s)" % ','.join([str(i) for i in ignored_users])])
+
+        # Return two 
+        if self.request.settings.avatars_on_threads_list:
+            return ((annos_global | annos_forum | rest).prefetch_related('start_poster', 'last_poster'),
+                    rest.prefetch_related('start_poster', 'last_poster'))
+        return (annos_global | annos_forum | rest), rest
+
+    def fetch_threads(self):
+        self.threads = []
+        ignored_users = []
+        queryset, threads = self.threads_queryset()
+        for thread in queryset:
+            self.threads.append(thread)
+        self.count =threads.count()
+        self.pagination = make_pagination(self.kwargs.get('page', 0), self.count, self.request.settings.threads_per_page)
+        """
+        queryset_anno = Thread.objects.filter(Q(forum=Forum.objects.token_to_pk('announcements')) | (Q(forum=self.forum) & Q(weight=2)))
+        queryset_threads = self.request.acl.threads.filter_threads(self.request, self.forum, Thread.objects.filter(forum=self.forum).filter(weight__lt=2)).order_by('-weight', '-last')
+        if self.request.user.is_authenticated():
+            ignored_users = self.request.user.ignored_users()
+            if ignored_users:
+                queryset_threads = queryset_threads.extra(where=["`threads_thread`.`start_poster_id` IS NULL OR `threads_thread`.`start_poster_id` NOT IN (%s)" % ','.join([str(i) for i in ignored_users])])
+        if self.request.settings.avatars_on_threads_list:
+            queryset_anno = queryset_anno.prefetch_related('start_poster', 'last_post')
+            queryset_threads = queryset_threads.prefetch_related('start_poster', 'last_poster')
+        for thread in queryset_anno:
+            self.threads.append(thread)
+        for thread in queryset_threads:
+            self.threads.append(thread)
+        if self.request.settings.threads_per_page < self.count:
+            self.threads = self.threads[self.pagination['start']:self.pagination['stop']]
+        for thread in self.threads:
+            if thread.forum_id == self.forum.pk:
+                thread.is_read = self.tracker.is_read(thread)
+            thread.last_poster_ignored = thread.last_poster_id in ignored_users
+        """

+ 4 - 4
misago/fixtures/forums.py

@@ -4,11 +4,11 @@ from misago.utils.fixtures import load_monitor_fixture
 from misago.utils.strings import slugify
 from misago.utils.strings import slugify
 
 
 def load():
 def load():
-    Forum(token='annoucements', name='annoucements', slug='annoucements', type='forum').insert_at(None, save=True)
-    Forum(token='private', name='private', slug='private', type='forum').insert_at(None, save=True)
-    Forum(token='reports', name='reports', slug='reports', type='forum').insert_at(None, save=True)
+    Forum(special='announcements', name='announcements', slug='announcements', type='forum').insert_at(None, save=True)
+    Forum(special='private', name='private', slug='private', type='forum').insert_at(None, save=True)
+    Forum(special='reports', name='reports', slug='reports', type='forum').insert_at(None, save=True)
 
 
-    root = Forum(token='root', name='root', slug='root')
+    root = Forum(special='root', name='root', slug='root')
     root.insert_at(None, save=True)
     root.insert_at(None, save=True)
     cat = Forum(type='category', name='First Category', slug='first-category')
     cat = Forum(type='category', name='First Category', slug='first-category')
     cat.insert_at(root, save=True)
     cat.insert_at(root, save=True)

+ 4 - 4
misago/fixtures/userroles.py

@@ -2,7 +2,7 @@ from misago.models import Role
 from misago.utils.translation import ugettext_lazy as _
 from misago.utils.translation import ugettext_lazy as _
 
 
 def load():
 def load():
-    role = Role(name=_("Administrator").message, token='admin', protected=True)
+    role = Role(name=_("Administrator").message, _special='admin', protected=True)
     role.permissions = {
     role.permissions = {
                         'name_changes_allowed': 5,
                         'name_changes_allowed': 5,
                         'changes_expire': 7,
                         'changes_expire': 7,
@@ -19,7 +19,7 @@ def load():
                        }
                        }
     role.save(force_insert=True)
     role.save(force_insert=True)
     
     
-    role = Role(name=_("Moderator").message, token='mod', protected=True)
+    role = Role(name=_("Moderator").message, _special='mod', protected=True)
     role.permissions = {
     role.permissions = {
                         'name_changes_allowed': 3,
                         'name_changes_allowed': 3,
                         'changes_expire': 14,
                         'changes_expire': 14,
@@ -34,7 +34,7 @@ def load():
                        }
                        }
     role.save(force_insert=True)
     role.save(force_insert=True)
     
     
-    role = Role(name=_("Registered").message, token='registered')
+    role = Role(name=_("Registered").message, _special='registered')
     role.permissions = {
     role.permissions = {
                         'name_changes_allowed': 2,
                         'name_changes_allowed': 2,
                         'can_use_signature': False,
                         'can_use_signature': False,
@@ -43,7 +43,7 @@ def load():
                        }
                        }
     role.save(force_insert=True)
     role.save(force_insert=True)
     
     
-    role = Role(name=_("Guest").message, token='guest')
+    role = Role(name=_("Guest").message, _special='guest')
     role.permissions = {
     role.permissions = {
                         'can_search_users': True,
                         'can_search_users': True,
                         'forums': {5: 6, 6: 6, 7: 6},
                         'forums': {5: 6, 6: 6, 7: 6},

+ 1 - 1
misago/management/commands/adduser.py

@@ -27,7 +27,7 @@ class Command(BaseCommand):
 
 
         # Set admin role
         # Set admin role
         if options['admin']:
         if options['admin']:
-            new_user.roles.add(Role.objects.get(token='admin'))
+            new_user.roles.add(Role.objects.get(_special='admin'))
             new_user.make_acl_key(True)
             new_user.make_acl_key(True)
             new_user.save(force_update=True)
             new_user.save(force_update=True)
 
 

+ 5 - 5
misago/migrations/0001_initial.py

@@ -78,7 +78,7 @@ class Migration(SchemaMigration):
             (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
             (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
             ('parent', self.gf('mptt.fields.TreeForeignKey')(blank=True, related_name='children', null=True, to=orm['misago.Forum'])),
             ('parent', self.gf('mptt.fields.TreeForeignKey')(blank=True, related_name='children', null=True, to=orm['misago.Forum'])),
             ('type', self.gf('django.db.models.fields.CharField')(max_length=12)),
             ('type', self.gf('django.db.models.fields.CharField')(max_length=12)),
-            ('token', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
+            ('special', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
             ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
             ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
             ('slug', self.gf('django.db.models.fields.SlugField')(max_length=255)),
             ('slug', self.gf('django.db.models.fields.SlugField')(max_length=255)),
             ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
             ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
@@ -242,7 +242,7 @@ class Migration(SchemaMigration):
         db.create_table(u'misago_role', (
         db.create_table(u'misago_role', (
             (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
             (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
             ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
             ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
-            ('token', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
+            ('_special', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, db_column='special', blank=True)),
             ('protected', self.gf('django.db.models.fields.BooleanField')(default=False)),
             ('protected', self.gf('django.db.models.fields.BooleanField')(default=False)),
             ('_permissions', self.gf('django.db.models.fields.TextField')(null=True, db_column='permissions', blank=True)),
             ('_permissions', self.gf('django.db.models.fields.TextField')(null=True, db_column='permissions', blank=True)),
         ))
         ))
@@ -642,10 +642,10 @@ class Migration(SchemaMigration):
             'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
             'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
             'show_details': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
             'show_details': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
             'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
             'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
+            'special': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
             'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
             'style': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
             'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
             'threads': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
             'threads_delta': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
             'threads_delta': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
             'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
             'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
             'type': ('django.db.models.fields.CharField', [], {'max_length': '12'})
             'type': ('django.db.models.fields.CharField', [], {'max_length': '12'})
         },
         },
@@ -749,10 +749,10 @@ class Migration(SchemaMigration):
         'misago.role': {
         'misago.role': {
             'Meta': {'object_name': 'Role'},
             'Meta': {'object_name': 'Role'},
             '_permissions': ('django.db.models.fields.TextField', [], {'null': 'True', 'db_column': "'permissions'", 'blank': 'True'}),
             '_permissions': ('django.db.models.fields.TextField', [], {'null': 'True', 'db_column': "'permissions'", 'blank': 'True'}),
+            '_special': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'db_column': "'special'", 'blank': 'True'}),
             u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
             u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
             'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
             'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
-            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
-            'token': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
+            'protected': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
         },
         },
         'misago.session': {
         'misago.session': {
             'Meta': {'object_name': 'Session'},
             'Meta': {'object_name': 'Session'},

+ 16 - 9
misago/models/forummodel.py

@@ -8,12 +8,13 @@ from misago.signals import delete_forum_content, move_forum_content, rename_user
 class ForumManager(models.Manager):
 class ForumManager(models.Manager):
     forums_tree = None
     forums_tree = None
 
 
-    def token_to_pk(self, token):
+    def special_pk(self, name):
         self.populate_tree()
         self.populate_tree()
-        try:
-            return self.forums_tree[token].pk
-        except KeyError:
-            return 0
+        return self.forums_tree[name].pk
+
+    def special_model(self, name):
+        self.populate_tree()
+        return self.forums_tree[name]
 
 
     def populate_tree(self, force=False):
     def populate_tree(self, force=False):
         if not self.forums_tree:
         if not self.forums_tree:
@@ -22,8 +23,8 @@ class ForumManager(models.Manager):
             self.forums_tree = {}
             self.forums_tree = {}
             for forum in Forum.objects.order_by('lft'):
             for forum in Forum.objects.order_by('lft'):
                 self.forums_tree[forum.pk] = forum
                 self.forums_tree[forum.pk] = forum
-                if forum.token:
-                    self.forums_tree[forum.token] = forum
+                if forum.special:
+                    self.forums_tree[forum.special] = forum
             cache.set('forums_tree', self.forums_tree)
             cache.set('forums_tree', self.forums_tree)
 
 
     def forum_parents(self, forum, include_self=False):
     def forum_parents(self, forum, include_self=False):
@@ -114,7 +115,7 @@ class ForumManager(models.Manager):
 class Forum(MPTTModel):
 class Forum(MPTTModel):
     parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
     parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
     type = models.CharField(max_length=12)
     type = models.CharField(max_length=12)
-    token = models.CharField(max_length=255, null=True, blank=True)
+    special = models.CharField(max_length=255, null=True, blank=True)
     name = models.CharField(max_length=255)
     name = models.CharField(max_length=255)
     slug = models.SlugField(max_length=255)
     slug = models.SlugField(max_length=255)
     description = models.TextField(null=True, blank=True)
     description = models.TextField(null=True, blank=True)
@@ -151,7 +152,13 @@ class Forum(MPTTModel):
         super(Forum, self).delete(*args, **kwargs)
         super(Forum, self).delete(*args, **kwargs)
 
 
     def __unicode__(self):
     def __unicode__(self):
-        if self.token == 'root':
+        if self.special == 'announcements':
+           return unicode(_('Global Announcements'))
+        if self.special == 'private':
+           return unicode(_('Private Threads'))
+        if self.special == 'reports':
+           return unicode(_('Content Report'))
+        if self.special == 'root':
            return unicode(_('Root Category'))
            return unicode(_('Root Category'))
         return unicode(self.name)
         return unicode(self.name)
 
 

+ 5 - 4
misago/models/rolemodel.py

@@ -11,9 +11,9 @@ class Role(models.Model):
     Misago User Role model
     Misago User Role model
     """
     """
     name = models.CharField(max_length=255)
     name = models.CharField(max_length=255)
-    token = models.CharField(max_length=255,null=True,blank=True)
+    _special = models.CharField(db_column='special', max_length=255,null=True,blank=True)
     protected = models.BooleanField(default=False)
     protected = models.BooleanField(default=False)
-    _permissions = models.TextField(db_column = 'permissions', null=True, blank=True)
+    _permissions = models.TextField(db_column='permissions', null=True, blank=True)
     permissions_cache = {}
     permissions_cache = {}
 
 
     class Meta:
     class Meta:
@@ -22,8 +22,9 @@ class Role(models.Model):
     def __unicode__(self):
     def __unicode__(self):
         return unicode(_(self.name))
         return unicode(_(self.name))
     
     
-    def is_special(self):
-        return token
+    @property
+    def special(self):
+        return _special
 
 
     @property
     @property
     def permissions(self):
     def permissions(self):

+ 2 - 2
misago/models/usermodel.py

@@ -85,7 +85,7 @@ class UserManager(models.Manager):
         # Set user roles?
         # Set user roles?
         if not no_roles:
         if not no_roles:
             from misago.models import Role
             from misago.models import Role
-            new_user.roles.add(Role.objects.get(token='registered'))
+            new_user.roles.add(Role.objects.get(_special='registered'))
             new_user.make_acl_key()
             new_user.make_acl_key()
             new_user.save(force_update=True)
             new_user.save(force_update=True)
 
 
@@ -514,7 +514,7 @@ class Guest(object):
 
 
     def get_roles(self):
     def get_roles(self):
         from misago.models import Role
         from misago.models import Role
-        return Role.objects.filter(token='guest')
+        return Role.objects.filter(_special='guest')
 
 
     def make_acl_key(self):
     def make_acl_key(self):
         return 'acl_guest'
         return 'acl_guest'

+ 4 - 1
misago/urls.py

@@ -25,9 +25,12 @@ urlpatterns += patterns('',
     (r'^users/', include('misago.apps.profiles.urls')),
     (r'^users/', include('misago.apps.profiles.urls')),
     (r'^usercp/', include('misago.apps.usercp.urls')),
     (r'^usercp/', include('misago.apps.usercp.urls')),
     (r'^activate/', include('misago.apps.activation.urls')),
     (r'^activate/', include('misago.apps.activation.urls')),
+    (r'^watched-threads/', include('misago.apps.watchedthreads.urls')),
     (r'^reset-password/', include('misago.apps.resetpswd.urls')),
     (r'^reset-password/', include('misago.apps.resetpswd.urls')),
     (r'^', include('misago.apps.threads.urls')),
     (r'^', include('misago.apps.threads.urls')),
-    (r'^watched-threads/', include('misago.apps.watchedthreads.urls')),
+    #(r'^private-discussions/', include('misago.apps.privatethreads.urls')),
+    #(r'^announcements/', include('misago.apps.announcements.urls')),
+    #(r'^reports/', include('misago.apps.reports.urls')),
 )
 )
 
 
 
 

+ 2 - 4
templates/cranefly/threads/posting.html

@@ -182,12 +182,10 @@
 {% macro get_button() -%}
 {% macro get_button() -%}
 {% if mode == 'new_thread' -%}
 {% if mode == 'new_thread' -%}
 {% trans %}Post Thread{% endtrans %}
 {% trans %}Post Thread{% endtrans %}
-{%- elif mode == 'edit_thread' -%}
-{% trans %}Edit Thread{% endtrans %}
 {%- elif mode in ['new_post', 'new_post_quick'] -%}
 {%- elif mode in ['new_post', 'new_post_quick'] -%}
 {% trans %}Post Reply{% endtrans %}
 {% trans %}Post Reply{% endtrans %}
-{%- elif mode == 'edit_post' -%}
-{% trans %}Edit Reply{% endtrans %}
+{%- else -%}
+{% trans %}Save Changes{% endtrans %}
 {%- endif %}
 {%- endif %}
 {%- endmacro %}
 {%- endmacro %}