Browse Source

Added prefixes to other pages, changed styling and links. #201

Rafał Pitoń 11 years ago
parent
commit
16961cc2e2

+ 2 - 1
misago/apps/newthreads.py

@@ -5,7 +5,7 @@ from django.shortcuts import redirect
 from django.template import RequestContext
 from django.template import RequestContext
 from django.utils import timezone
 from django.utils import timezone
 from misago.conf import settings
 from misago.conf import settings
-from misago.models import Forum, Thread
+from misago.models import Forum, Thread, ThreadPrefix
 from misago.shortcuts import render_to_response
 from misago.shortcuts import render_to_response
 from misago.utils.pagination import make_pagination
 from misago.utils.pagination import make_pagination
 
 
@@ -27,6 +27,7 @@ def new_threads(request, page=0):
                               {
                               {
                               'items_total': items_total,
                               'items_total': items_total,
                               'threads': Thread.objects.with_reads(queryset, request.user),
                               'threads': Thread.objects.with_reads(queryset, request.user),
+                              'prefixes': ThreadPrefix.objects.all_prefixes(),
                               'pagination': pagination,
                               'pagination': pagination,
                               },
                               },
                               context_instance=RequestContext(request));
                               context_instance=RequestContext(request));

+ 2 - 1
misago/apps/popularthreads.py

@@ -5,7 +5,7 @@ from django.shortcuts import redirect
 from django.template import RequestContext
 from django.template import RequestContext
 from django.utils import timezone
 from django.utils import timezone
 from misago.conf import settings
 from misago.conf import settings
-from misago.models import Forum, Thread
+from misago.models import Forum, Thread, ThreadPrefix
 from misago.shortcuts import render_to_response
 from misago.shortcuts import render_to_response
 from misago.utils.pagination import make_pagination
 from misago.utils.pagination import make_pagination
 
 
@@ -27,6 +27,7 @@ def popular_threads(request, page=0):
                               {
                               {
                               'items_total': items_total,
                               'items_total': items_total,
                               'threads': Thread.objects.with_reads(queryset, request.user),
                               'threads': Thread.objects.with_reads(queryset, request.user),
+                              'prefixes': ThreadPrefix.objects.all_prefixes(),
                               'pagination': pagination,
                               'pagination': pagination,
                               },
                               },
                               context_instance=RequestContext(request));
                               context_instance=RequestContext(request));

+ 9 - 46
misago/apps/threads/list.py

@@ -19,10 +19,14 @@ class ThreadsListView(ThreadsListBaseView, ThreadsListModeration, TypeMixin):
         self.forum = Forum.objects.get(pk=self.kwargs.get('forum'), type='forum')
         self.forum = Forum.objects.get(pk=self.kwargs.get('forum'), type='forum')
 
 
         self.prefixes = ThreadPrefix.objects.forum_prefixes(self.forum)
         self.prefixes = ThreadPrefix.objects.forum_prefixes(self.forum)
-        self.active_prefix = self.request.session.get('forum_prefix_%s' % self.forum.pk)
-
-        if self.active_prefix and self.active_prefix.pk not in self.prefixes:
-            self.active_prefix = None
+        self.active_prefix = self.kwargs.get('prefix', None)
+        if self.active_prefix:
+            for prefix in self.prefixes.values():
+                if self.active_prefix == prefix.slug:
+                    self.active_prefix = prefix
+                    break
+            else:
+                raise ACLError404()
 
 
     def template_vars(self, context):
     def template_vars(self, context):
         context['prefixes'] = self.prefixes
         context['prefixes'] = self.prefixes
@@ -131,45 +135,4 @@ class ThreadsListView(ThreadsListBaseView, ThreadsListModeration, TypeMixin):
                 thread.prefix_id = None
                 thread.prefix_id = None
                 thread.set_checkpoint(self.request, 'removed_prefix', self.request.user, self.forum)
                 thread.set_checkpoint(self.request, 'removed_prefix', self.request.user, self.forum)
                 thread.save(force_update=True)
                 thread.save(force_update=True)
-        return changed
-
-
-class ForumSwitchThreadPrefix(ThreadsListView):
-    def __call__(self, request, **kwargs):
-        self.request = request
-        self.kwargs = kwargs
-        self.pagination = {}
-        self.parents = []
-        self.threads = []
-        self.message = request.messages.get_message('threads')
-        try:
-            self._type_available()
-            self._fetch_forum()
-            return self.change_prefix()
-        except (Forum.DoesNotExist, Thread.DoesNotExist):
-            return error404(request)
-        except ACLError403 as e:
-            return error403(request, unicode(e))
-        except ACLError404 as e:
-            return error404(request, unicode(e))
-
-    def change_prefix(self):
-        @check_csrf
-        def view(request):
-            session_key = 'forum_prefix_%s' % self.forum.pk
-            try:
-                new_prefix = int(self.request.POST.get('switch_prefix', 0))
-            except ValueError:
-                new_prefix = 0
-
-            if self.prefixes and new_prefix in self.prefixes:
-                self.request.session[session_key] = self.prefixes[new_prefix]
-                messages.info(self.request, _('Displaying only threads that are prefixed with "%(prefix)s".') % {'prefix': _(self.prefixes[new_prefix].name)}, 'threads')
-            else:
-                self.request.session[session_key] = None
-                messages.info(self.request, _("Displaying all threads."), 'threads')
-
-            if 'retreat' in self.request.POST:
-                return redirect(self.request.POST.get('retreat'))
-            return self.threads_list_redirect()
-        return view(self.request)
+        return changed

+ 2 - 1
misago/apps/threads/urls.py

@@ -3,7 +3,8 @@ from django.conf.urls import patterns, url
 urlpatterns = patterns('misago.apps.threads',
 urlpatterns = patterns('misago.apps.threads',
     url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/$', 'list.ThreadsListView', name="forum"),
     url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/$', 'list.ThreadsListView', name="forum"),
     url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/(?P<page>[1-9]([0-9]+)?)/$', 'list.ThreadsListView', name="forum"),
     url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/(?P<page>[1-9]([0-9]+)?)/$', 'list.ThreadsListView', name="forum"),
-    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/switch-prefix/$', 'list.ForumSwitchThreadPrefix', name="forum_switch_prefix"),
+    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/(?P<prefix>(\w|-)+)/$', 'list.ThreadsListView', name="forum_prefixed"),
+    url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/(?P<prefix>(\w|-)+)/(?P<page>[1-9]([0-9]+)?)/$', 'list.ThreadsListView', name="forum_prefixed"),
     url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/start/$', 'posting.NewThreadView', name="thread_start"),
     url(r'^forum/(?P<slug>(\w|-)+)-(?P<forum>\d+)/start/$', 'posting.NewThreadView', name="thread_start"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/edit/$', 'posting.EditThreadView', name="thread_edit"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/edit/$', 'posting.EditThreadView', name="thread_edit"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/reply/$', 'posting.NewReplyView', name="thread_reply"),
     url(r'^thread/(?P<slug>(\w|-)+)-(?P<thread>\d+)/reply/$', 'posting.NewReplyView', name="thread_reply"),

+ 2 - 1
misago/apps/watchedthreads/views.py

@@ -7,7 +7,7 @@ from django.utils.translation import ugettext as _
 from misago.apps.errors import error403
 from misago.apps.errors import error403
 from misago.conf import settings
 from misago.conf import settings
 from misago.decorators import block_guest
 from misago.decorators import block_guest
-from misago.models import Forum, WatchedThread
+from misago.models import Forum, WatchedThread, ThreadPrefix
 from misago.shortcuts import render_to_response
 from misago.shortcuts import render_to_response
 from misago.utils.pagination import make_pagination
 from misago.utils.pagination import make_pagination
 
 
@@ -60,6 +60,7 @@ def watched_threads(request, page=0, new=False):
                               'pagination': pagination,
                               'pagination': pagination,
                               'new': new,
                               'new': new,
                               'threads': threads,
                               'threads': threads,
+                              'prefixes': ThreadPrefix.objects.all_prefixes(),
                               'message': request.messages.get_message('threads'),
                               'message': request.messages.get_message('threads'),
                               },
                               },
                               context_instance=RequestContext(request))
                               context_instance=RequestContext(request))

+ 8 - 8
misago/models/threadprefixmodel.py

@@ -11,13 +11,6 @@ class ThreadPrefixManager(models.Manager):
     def flush_cache(self):
     def flush_cache(self):
         cache.delete('threads_prefixes')
         cache.delete('threads_prefixes')
 
 
-    def get_cache(self):
-        try:
-            return _thread_local.misago_thread_prefixes
-        except AttributeError:
-            _thread_local.misago_thread_prefixes = self.make_cache()
-        return _thread_local.misago_thread_prefixes
-
     def make_cache(self):
     def make_cache(self):
         raw_prefixes = cache.get('threads_prefixes', 'nada')
         raw_prefixes = cache.get('threads_prefixes', 'nada')
         if raw_prefixes == 'nada':
         if raw_prefixes == 'nada':
@@ -28,9 +21,16 @@ class ThreadPrefixManager(models.Manager):
             dict_result[prefix.pk] = prefix
             dict_result[prefix.pk] = prefix
         return dict_result
         return dict_result
 
 
+    def all_prefixes(self):
+        try:
+            return _thread_local.misago_thread_prefixes
+        except AttributeError:
+            _thread_local.misago_thread_prefixes = self.make_cache()
+        return _thread_local.misago_thread_prefixes
+
     def forum_prefixes(self, forum):
     def forum_prefixes(self, forum):
         forum_prefixes = []
         forum_prefixes = []
-        for prefix in self.get_cache().values():
+        for prefix in self.all_prefixes().values():
             if forum in prefix.forums.all():
             if forum in prefix.forums.all():
                 forum_prefixes.append((prefix.pk, prefix))
                 forum_prefixes.append((prefix.pk, prefix))
         return SortedDict(forum_prefixes)
         return SortedDict(forum_prefixes)

+ 26 - 14
static/cranefly/css/cranefly.css

@@ -714,7 +714,7 @@ a.label:hover,a.label:focus,a.badge:hover,a.badge:focus{color:#fff;text-decorati
 .header-primary .breadcrumb li .divider{color:#999}
 .header-primary .breadcrumb li .divider{color:#999}
 .header-primary h1{color:#555;font-size:35px;font-weight:normal}
 .header-primary h1{color:#555;font-size:35px;font-weight:normal}
 .header-primary .header-stats{overflow:visible;margin-bottom:0;color:#999}.header-primary .header-stats li{float:left;margin-right:14px}.header-primary .header-stats li .thread-prefix{margin-left:2px;position:relative;bottom:1px}
 .header-primary .header-stats{overflow:visible;margin-bottom:0;color:#999}.header-primary .header-stats li{float:left;margin-right:14px}.header-primary .header-stats li .thread-prefix{margin-left:2px;position:relative;bottom:1px}
-.header-primary .header-stats li>a{color:#999}.header-primary .header-stats li>a:hover,.header-primary .header-stats li>a:active{color:#333}
+.header-primary .header-stats li>a:not(.label){color:#999}.header-primary .header-stats li>a:not(.label):hover,.header-primary .header-stats li>a:not(.label):active{color:#333}
 .header-primary .header-stats li>i{opacity:.5;filter:alpha(opacity=50)}
 .header-primary .header-stats li>i{opacity:.5;filter:alpha(opacity=50)}
 .header-primary .header-stats li.stats-form{float:right}.header-primary .header-stats li.stats-form form{margin:0;margin-bottom:-12px;padding:0}.header-primary .header-stats li.stats-form form button{position:relative;bottom:12px}.header-primary .header-stats li.stats-form form button>i{position:relative;top:0}
 .header-primary .header-stats li.stats-form{float:right}.header-primary .header-stats li.stats-form form{margin:0;margin-bottom:-12px;padding:0}.header-primary .header-stats li.stats-form form button{position:relative;bottom:12px}.header-primary .header-stats li.stats-form form button>i{position:relative;top:0}
 .header-primary .header-tabs{border-bottom:0;margin:0;margin-top:-10px;position:relative;top:9px}.header-primary .header-tabs li a:link,.header-primary .header-tabs li a:visited{background:none;border:none;border-radius:0;margin-bottom:4px;padding:6.666666666666667px 10px;color:#888;font-weight:bold}
 .header-primary .header-tabs{border-bottom:0;margin:0;margin-top:-10px;position:relative;top:9px}.header-primary .header-tabs li a:link,.header-primary .header-tabs li a:visited{background:none;border:none;border-radius:0;margin-bottom:4px;padding:6.666666666666667px 10px;color:#888;font-weight:bold}
@@ -731,6 +731,16 @@ footer{background-color:#eee;border-top:1px solid #dadada;height:90px;padding:11
 footer .container .credits p{margin-bottom:0;color:#555;font-size:90%}footer .container .credits p a:link,footer .container .credits p a:active,footer .container .credits p a:visited,footer .container .credits p a:hover{color:#555}
 footer .container .credits p{margin-bottom:0;color:#555;font-size:90%}footer .container .credits p a:link,footer .container .credits p a:active,footer .container .credits p a:visited,footer .container .credits p a:hover{color:#555}
 ::selection{background:#f89406;color:#fff}
 ::selection{background:#f89406;color:#fff}
 ::-moz-selection{background:#f89406;color:#fff}
 ::-moz-selection{background:#f89406;color:#fff}
+.label-important,.badge-important{background-color:#cf402e}
+.label-important[href],.badge-important[href]{background-color:#cf402e}
+.label-warning,.badge-warning{background-color:#f89406}
+.label-warning[href],.badge-warning[href]{background-color:#f89406}
+.label-success,.badge-success{background-color:#46a546}
+.label-success[href],.badge-success[href]{background-color:#46a546}
+.label-info,.badge-info{background-color:#049cdb}
+.label-info[href],.badge-info[href]{background-color:#049cdb}
+.label-inverse,.badge-inverse{background-color:#333}
+.label-inverse[href],.badge-inverse[href]{background-color:#333}
 #ajax-loader{display:none;position:fixed;top:0;height:auto;width:100%;z-index:1060}#ajax-loader .bar{background:#cf402e;background-image:-webkit-gradient(linear, 0 0, 100% 100%, color-stop(.25, rgba(255,255,255,0.2)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.2)), color-stop(.75, rgba(255,255,255,0.2)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255,255,255,0.2) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.2) 50%, rgba(255,255,255,0.2) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255,255,255,0.2) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.2) 50%, rgba(255,255,255,0.2) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255,255,255,0.2) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.2) 50%, rgba(255,255,255,0.2) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255,255,255,0.2) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.2) 50%, rgba(255,255,255,0.2) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255,255,255,0.2) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.2) 50%, rgba(255,255,255,0.2) 75%, transparent 75%, transparent);-webkit-background-size:15px 15px;-moz-background-size:15px 15px;background-size:15px 15px;height:6px}
 #ajax-loader{display:none;position:fixed;top:0;height:auto;width:100%;z-index:1060}#ajax-loader .bar{background:#cf402e;background-image:-webkit-gradient(linear, 0 0, 100% 100%, color-stop(.25, rgba(255,255,255,0.2)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.2)), color-stop(.75, rgba(255,255,255,0.2)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255,255,255,0.2) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.2) 50%, rgba(255,255,255,0.2) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255,255,255,0.2) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.2) 50%, rgba(255,255,255,0.2) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255,255,255,0.2) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.2) 50%, rgba(255,255,255,0.2) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255,255,255,0.2) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.2) 50%, rgba(255,255,255,0.2) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255,255,255,0.2) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.2) 50%, rgba(255,255,255,0.2) 75%, transparent 75%, transparent);-webkit-background-size:15px 15px;-moz-background-size:15px 15px;background-size:15px 15px;height:6px}
 .navbar-header .navbar-inner{background:none;background-color:#f3f3f3;border-bottom:1px solid #dfdfdf;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.navbar-header .navbar-inner .container{background:url("../img/logo.png");background-position:left center;background-repeat:no-repeat}
 .navbar-header .navbar-inner{background:none;background-color:#f3f3f3;border-bottom:1px solid #dfdfdf;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.navbar-header .navbar-inner .container{background:url("../img/logo.png");background-position:left center;background-repeat:no-repeat}
 .navbar-header .navbar-inner .brand{margin-left:10px;text-shadow:none}.navbar-header .navbar-inner .brand:link,.navbar-header .navbar-inner .brand:active,.navbar-header .navbar-inner .brand:visited,.navbar-header .navbar-inner .brand:hover{color:#c24a3b;font-size:200%}.navbar-header .navbar-inner .brand:link span,.navbar-header .navbar-inner .brand:active span,.navbar-header .navbar-inner .brand:visited span,.navbar-header .navbar-inner .brand:hover span{color:#c0c0c0}
 .navbar-header .navbar-inner .brand{margin-left:10px;text-shadow:none}.navbar-header .navbar-inner .brand:link,.navbar-header .navbar-inner .brand:active,.navbar-header .navbar-inner .brand:visited,.navbar-header .navbar-inner .brand:hover{color:#c24a3b;font-size:200%}.navbar-header .navbar-inner .brand:link span,.navbar-header .navbar-inner .brand:active span,.navbar-header .navbar-inner .brand:visited span,.navbar-header .navbar-inner .brand:hover span{color:#c0c0c0}
@@ -813,7 +823,6 @@ textarea{resize:vertical}
 .btn.btn-icon{padding-left:0 !important;padding-right:0 !important;width:32px;text-align:center}.btn.btn-icon i{margin:0}
 .btn.btn-icon{padding-left:0 !important;padding-right:0 !important;width:32px;text-align:center}.btn.btn-icon i{margin:0}
 a.btn-link:hover,a.btn-link:active,a.btn-link:focus{color:#333;text-decoration:none}
 a.btn-link:hover,a.btn-link:active,a.btn-link:focus{color:#333;text-decoration:none}
 .pagination{margin:0;padding:0}.pagination .count{margin-right:10.5px;padding:4px 0;color:#999}
 .pagination{margin:0;padding:0}.pagination .count{margin-right:10.5px;padding:4px 0;color:#999}
-.pagination .separator{margin-left:14px;margin-right:10.5px;padding:4px 0;color:#555;font-weight:bold}
 .pagination ul{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.pagination ul li{float:left;margin:0;margin-right:4.666666666666667px;padding:0}.pagination ul li a:link,.pagination ul li a:visited{background-color:#fff;border:1px solid #f0f0f0;border-radius:3px;padding:3px 7px;color:#999}.pagination ul li a:link i,.pagination ul li a:visited i{display:inline-block;width:12px;text-align:center}
 .pagination ul{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.pagination ul li{float:left;margin:0;margin-right:4.666666666666667px;padding:0}.pagination ul li a:link,.pagination ul li a:visited{background-color:#fff;border:1px solid #f0f0f0;border-radius:3px;padding:3px 7px;color:#999}.pagination ul li a:link i,.pagination ul li a:visited i{display:inline-block;width:12px;text-align:center}
 .pagination ul li a:active,.pagination ul li a:hover{border:1px solid #999;color:#555}
 .pagination ul li a:active,.pagination ul li a:hover{border:1px solid #999;color:#555}
 .editor{background-color:#fff;border:1px solid #e6e6e6;border-radius:3px;margin-bottom:20px}.editor .editor-error{padding:10.5px;padding-bottom:0;margin-bottom:-10.5px}.editor .editor-error .help-block{color:#cf402e;font-weight:bold}
 .editor{background-color:#fff;border:1px solid #e6e6e6;border-radius:3px;margin-bottom:20px}.editor .editor-error{padding:10.5px;padding-bottom:0;margin-bottom:-10.5px}.editor .editor-error .help-block{color:#cf402e;font-weight:bold}
@@ -986,7 +995,7 @@ a.btn-link:hover,a.btn-link:active,a.btn-link:focus{color:#333;text-decoration:n
 .forum-threads-list{background-color:#fff;border:1px solid #d5d5d5;border-radius:2px;-webkit-box-shadow:0 0 0 3px #eee;-moz-box-shadow:0 0 0 3px #eee;box-shadow:0 0 0 3px #eee;margin-bottom:20px}.forum-threads-list .threads-list-empty{padding:28px 0;color:#999;font-size:26.25px;text-align:center}.forum-threads-list .threads-list-empty .thread-prefix{position:relative;bottom:5px}
 .forum-threads-list{background-color:#fff;border:1px solid #d5d5d5;border-radius:2px;-webkit-box-shadow:0 0 0 3px #eee;-moz-box-shadow:0 0 0 3px #eee;box-shadow:0 0 0 3px #eee;margin-bottom:20px}.forum-threads-list .threads-list-empty{padding:28px 0;color:#999;font-size:26.25px;text-align:center}.forum-threads-list .threads-list-empty .thread-prefix{position:relative;bottom:5px}
 .forum-threads-list>ul{list-style:none;margin:0}.forum-threads-list>ul>li{border-bottom:1px solid #d5d5d5;padding:9.9px 0;overflow:auto}.forum-threads-list>ul>li .thread-icon{float:left;margin-bottom:-2px;position:relative;bottom:1px;height:22px;width:39.5px;font-size:22px;text-align:center}.forum-threads-list>ul>li .thread-icon a:link,.forum-threads-list>ul>li .thread-icon a:active,.forum-threads-list>ul>li .thread-icon a:visited,.forum-threads-list>ul>li .thread-icon a:hover{color:#d5d5d5;text-decoration:none}
 .forum-threads-list>ul{list-style:none;margin:0}.forum-threads-list>ul>li{border-bottom:1px solid #d5d5d5;padding:9.9px 0;overflow:auto}.forum-threads-list>ul>li .thread-icon{float:left;margin-bottom:-2px;position:relative;bottom:1px;height:22px;width:39.5px;font-size:22px;text-align:center}.forum-threads-list>ul>li .thread-icon a:link,.forum-threads-list>ul>li .thread-icon a:active,.forum-threads-list>ul>li .thread-icon a:visited,.forum-threads-list>ul>li .thread-icon a:hover{color:#d5d5d5;text-decoration:none}
 .forum-threads-list>ul>li .thread-body{margin:-9.9px 0;margin-left:39.5px;padding:9.9px 0}.forum-threads-list>ul>li .thread-body .thread-prefix{margin-right:7px;position:relative;bottom:2px}
 .forum-threads-list>ul>li .thread-body{margin:-9.9px 0;margin-left:39.5px;padding:9.9px 0}.forum-threads-list>ul>li .thread-body .thread-prefix{margin-right:7px;position:relative;bottom:2px}
-.forum-threads-list>ul>li .thread-body .thread-title{display:block}.forum-threads-list>ul>li .thread-body .thread-title a:link,.forum-threads-list>ul>li .thread-body .thread-title a:active,.forum-threads-list>ul>li .thread-body .thread-title a:visited,.forum-threads-list>ul>li .thread-body .thread-title a:hover{color:#555;font-size:17.5px}
+.forum-threads-list>ul>li .thread-body .thread-title{display:block}.forum-threads-list>ul>li .thread-body .thread-title .thread-link:link,.forum-threads-list>ul>li .thread-body .thread-title .thread-link:active,.forum-threads-list>ul>li .thread-body .thread-title .thread-link:visited,.forum-threads-list>ul>li .thread-body .thread-title .thread-link:hover{color:#555;font-size:17.5px}
 .forum-threads-list>ul>li .thread-body .thread-activity{float:right;list-style:none;margin:0;margin-top:-9.9px;margin-bottom:-6px;padding:6px 0;padding-right:8px;overflow:auto;position:relative;top:1px;z-index:2}.forum-threads-list>ul>li .thread-body .thread-activity li{float:left;margin:0;margin-left:10px;padding:0}.forum-threads-list>ul>li .thread-body .thread-activity li.thread-replies,.forum-threads-list>ul>li .thread-body .thread-activity li.thread-replies-reported,.forum-threads-list>ul>li .thread-body .thread-activity li.thread-replies-moderated{position:relative;top:2px;color:#555;font-size:17.5px;font-weight:bold}
 .forum-threads-list>ul>li .thread-body .thread-activity{float:right;list-style:none;margin:0;margin-top:-9.9px;margin-bottom:-6px;padding:6px 0;padding-right:8px;overflow:auto;position:relative;top:1px;z-index:2}.forum-threads-list>ul>li .thread-body .thread-activity li{float:left;margin:0;margin-left:10px;padding:0}.forum-threads-list>ul>li .thread-body .thread-activity li.thread-replies,.forum-threads-list>ul>li .thread-body .thread-activity li.thread-replies-reported,.forum-threads-list>ul>li .thread-body .thread-activity li.thread-replies-moderated{position:relative;top:2px;color:#555;font-size:17.5px;font-weight:bold}
 .forum-threads-list>ul>li .thread-body .thread-activity li.thread-replies-reported{color:#cf402e}
 .forum-threads-list>ul>li .thread-body .thread-activity li.thread-replies-reported{color:#cf402e}
 .forum-threads-list>ul>li .thread-body .thread-activity li.thread-replies-moderated{color:#7a43b6}
 .forum-threads-list>ul>li .thread-body .thread-activity li.thread-replies-moderated{color:#7a43b6}
@@ -1013,17 +1022,20 @@ a.btn-link:hover,a.btn-link:active,a.btn-link:focus{color:#333;text-decoration:n
 .forum-threads-list .threads-actions{background-color:#fbfbfb;border-top:1px solid #d5d5d5;border-radius:0 0 2px 2px;overflow:auto;padding:4px;color:#999;font-size:11.9px}.forum-threads-list .threads-actions form{margin-bottom:0}
 .forum-threads-list .threads-actions{background-color:#fbfbfb;border-top:1px solid #d5d5d5;border-radius:0 0 2px 2px;overflow:auto;padding:4px;color:#999;font-size:11.9px}.forum-threads-list .threads-actions form{margin-bottom:0}
 .forum-threads-extra{overflow:auto}.forum-threads-extra.extra-top{margin-bottom:20px}
 .forum-threads-extra{overflow:auto}.forum-threads-extra.extra-top{margin-bottom:20px}
 .forum-threads-extra .threads-signin-message{float:right}.forum-threads-extra .threads-signin-message a:link,.forum-threads-extra .threads-signin-message a:visited{color:#333}
 .forum-threads-extra .threads-signin-message{float:right}.forum-threads-extra .threads-signin-message a:link,.forum-threads-extra .threads-signin-message a:visited{color:#333}
-.form-prefix{margin:0;padding:0}.form-prefix .btn{background-color:#d4d4d4;border-color:#a2a2a2;margin:0 2px;padding:2px 8px;position:relative;top:1px;opacity:.9;filter:alpha(opacity=90);outline:none;color:#555;font-size:14px;text-shadow:none}.form-prefix .btn.btn-active{background-color:#555;border-color:#222;color:#fff;text-shadow:0 1px 1px #222}
-.form-prefix .btn.btn-cancel{background-color:#fff;border-color:#b3b3b3}.form-prefix .btn.btn-cancel:hover,.form-prefix .btn.btn-cancel:active{background-color:#555;border-color:#222;color:#fff;text-shadow:0 1px 1px #222}
-.form-prefix .btn.btn-success,.form-prefix .btn.btn-success:hover,.form-prefix .btn.btn-success:active{background-color:#cdeacd;border-color:#86cb86;color:#46a546}
-.form-prefix .btn.btn-success.btn-active{background-color:#46a546;border-color:#285d28;color:#fff;text-shadow:0 1px 1px #285d28}
-.form-prefix .btn.btn-info,.form-prefix .btn.btn-info:hover,.form-prefix .btn.btn-info:active{background-color:#ade6fe;border-color:#49c7fc;color:#049cdb}
-.form-prefix .btn.btn-info.btn-active{background-color:#049cdb;border-color:#025577;color:#fff;text-shadow:0 1px 1px #025577}
-.form-prefix .btn.btn-warning,.form-prefix .btn.btn-warning:hover,.form-prefix .btn.btn-warning:active{background-color:#fee9cc;border-color:#fbbf69;color:#df8505}
-.form-prefix .btn.btn-warning.btn-active{background-color:#f89406;border-color:#945904;color:#fff;text-shadow:0 1px 1px #945904}
-.form-prefix .btn.btn-important,.form-prefix .btn.btn-important:hover,.form-prefix .btn.btn-important:active{background-color:#f5d7d4;border-color:#e38b80;color:#cf402e}
-.form-prefix .btn.btn-important.btn-active{background-color:#cf402e;border-color:#7c261b;color:#fff;text-shadow:0 1px 1px #7c261b}
-.form-prefix .btn.btn-active,.form-prefix .btn:hover,.form-prefix .btn:active{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:1;filter:alpha(opacity=100)}
+.prefix-select{margin:0;padding:0}.prefix-select ul{overflow:auto}.prefix-select ul li{float:left;list-style:none;margin:0;padding:4px 0}
+.prefix-select .selection-title{padding:4px 0;color:#555;font-weight:bold}
+.prefix-select .label{margin:0 4px;position:relative;bottom:0;opacity:.9;filter:alpha(opacity=90);outline:none}.prefix-select .label.label-cancel{background-color:#fbfbfb;color:#555}.prefix-select .label.label-cancel:hover,.prefix-select .label.label-cancel:active{color:#333}
+.prefix-select .label.label-success,.prefix-select .label.label-success:hover,.prefix-select .label.label-success:active{background-color:#cdeacd;border-color:#86cb86;color:#46a546;text-shadow:none}
+.prefix-select .label.label-success.label-active{background-color:#46a546;border-color:#285d28;color:#fff;text-shadow:0 -1px 0 #285d28}
+.prefix-select .label.label-info,.prefix-select .label.label-info:hover,.prefix-select .label.label-info:active{background-color:#ade6fe;border-color:#49c7fc;color:#049cdb;text-shadow:none}
+.prefix-select .label.label-info.label-active{background-color:#049cdb;border-color:#025577;color:#fff;text-shadow:0 -1px 0 #025577}
+.prefix-select .label.label-warning,.prefix-select .label.label-warning:hover,.prefix-select .label.label-warning:active{background-color:#fee9cc;border-color:#fbbf69;color:#f89406;text-shadow:none}
+.prefix-select .label.label-warning.label-active{background-color:#f89406;border-color:#945904;color:#fff;text-shadow:0 -1px 0 #945904}
+.prefix-select .label.label-important,.prefix-select .label.label-important:hover,.prefix-select .label.label-important:active{background-color:#f5d7d4;border-color:#e38b80;color:#cf402e;text-shadow:none}
+.prefix-select .label.label-important.label-active{background-color:#cf402e;border-color:#7c261b;color:#fff;text-shadow:0 -1px 0 #7c261b}
+.prefix-select .label.label-inverse,.prefix-select .label.label-inverse:hover,.prefix-select .label.label-inverse:active{background-color:#999;border-color:#666;color:#333;text-shadow:none}
+.prefix-select .label.label-inverse.label-active{background-color:#333;border-color:#000;color:#fff;text-shadow:0 -1px 0 #000}
+.prefix-select .label.btn-active,.prefix-select .label:hover,.prefix-select .label:active{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;opacity:1;filter:alpha(opacity=100)}
 .thread-buttons{overflow:auto}.thread-buttons .pull-right{margin-left:14px}
 .thread-buttons{overflow:auto}.thread-buttons .pull-right{margin-left:14px}
 .thread-buttons .thread-signin-message{float:right}.thread-buttons .thread-signin-message a:link,.thread-buttons .thread-signin-message a:visited{color:#333}
 .thread-buttons .thread-signin-message{float:right}.thread-buttons .thread-signin-message a:link,.thread-buttons .thread-signin-message a:visited{color:#333}
 .thread-poll-body{background-color:#fff;border:1px solid #d5d5d5;border-radius:2px;-webkit-box-shadow:0 0 0 3px #eee;-moz-box-shadow:0 0 0 3px #eee;box-shadow:0 0 0 3px #eee;margin-bottom:20px;padding:10px 20px}.thread-poll-body h2{margin-left:180px;margin-bottom:20px}
 .thread-poll-body{background-color:#fff;border:1px solid #d5d5d5;border-radius:2px;-webkit-box-shadow:0 0 0 3px #eee;-moz-box-shadow:0 0 0 3px #eee;box-shadow:0 0 0 3px #eee;margin-bottom:20px;padding:10px 20px}.thread-poll-body h2{margin-left:180px;margin-bottom:20px}

+ 1 - 0
static/cranefly/css/cranefly.less

@@ -66,6 +66,7 @@
 // Cranefly theme
 // Cranefly theme
 @import "cranefly/header.less";
 @import "cranefly/header.less";
 @import "cranefly/scaffolding.less";
 @import "cranefly/scaffolding.less";
+@import "cranefly/labels-badges.less";
 @import "cranefly/loader.less";
 @import "cranefly/loader.less";
 @import "cranefly/navbar.less";
 @import "cranefly/navbar.less";
 @import "cranefly/midman.less";
 @import "cranefly/midman.less";

+ 81 - 57
static/cranefly/css/cranefly/forum.less

@@ -358,9 +358,11 @@
         .thread-title {
         .thread-title {
           display: block;
           display: block;
 
 
-          a:link, a:active, a:visited, a:hover {
-            color: @gray;
-            font-size: @fontSizeLarge;
+          .thread-link {
+            &:link, &:active, &:visited, &:hover {
+              color: @gray;
+              font-size: @fontSizeLarge;
+            }
           }
           }
         }
         }
 
 
@@ -605,110 +607,132 @@
   }
   }
 }
 }
 
 
-.form-prefix {
+.prefix-select {
   margin: 0px;
   margin: 0px;
   padding: 0px;
   padding: 0px;
 
 
-  .btn {
-    background-color: lighten(@gray, 50%);
-    border-color: lighten(@gray, 30%);
-    margin: 0px 2px;
-    padding: 2px 8px;
-    position: relative;
-    top: 1px;
-    .opacity(90);
-    outline: none;
+  ul {
+    overflow: auto;
+
+    li {
+      float: left;
+      list-style: none;
+      margin: 0px;
+      padding: 4px 0px;
+    }
+  }
+
+  .selection-title {
+    padding: 4px 0px;
 
 
     color: @gray;
     color: @gray;
-    font-size: @baseFontSize;
-    text-shadow: none;
+    font-weight: bold;
+  }
 
 
-    &.btn-active {
-      background-color: @gray;
-      border-color: darken(@gray, 20%);
+  .label {
+    margin: 0px 4px;
+    position: relative;
+    bottom: 0px;
+    .opacity(90);
+    outline: none;
 
 
-      color: @white;
-      text-shadow: 0px 1px 1px darken(@gray, 20%);
-    }
+    &.label-cancel {
+      background-color: @bodyBackground;
 
 
-    &.btn-cancel {
-      background-color: @white;
-      border-color: darken(@white, 30%);
+      color: @gray;
 
 
       &:hover, &:active {
       &:hover, &:active {
-        background-color: @gray;
-        border-color: darken(@gray, 20%);
-
-        color: @white;
-        text-shadow: 0px 1px 1px darken(@gray, 20%);
+        color: @textColor;
       }
       }
     }
     }
 
 
-    &.btn-success {
+    &.label-success {
       &, &:hover, &:active {
       &, &:hover, &:active {
-        background-color: lighten(@green, 40%);
-        border-color: lighten(@green, 20%);
+        background-color: lighten(@successText, 40%);
+        border-color: lighten(@successText, 20%);
 
 
-        color: @green;
+        color: @successText;
+        text-shadow: none;
       }
       }
 
 
-      &.btn-active {
-        background-color: @green;
-        border-color: darken(@green, 20%);
+      &.label-active {
+        background-color: @successText;
+        border-color: darken(@successText, 20%);
 
 
         color: @white;
         color: @white;
-        text-shadow: 0px 1px 1px darken(@green, 20%);
+        text-shadow: 0px -1px 0px darken(@successText, 20%);
       }
       }
     }
     }
 
 
-    &.btn-info {
+    &.label-info {
       &, &:hover, &:active {
       &, &:hover, &:active {
-        background-color: lighten(@blue, 40%);
-        border-color: lighten(@blue, 20%);
+        background-color: lighten(@infoText, 40%);
+        border-color: lighten(@infoText, 20%);
 
 
-        color: @blue;
+        color: @infoText;
+        text-shadow: none;
       }
       }
 
 
-      &.btn-active {
-        background-color: @blue;
-        border-color: darken(@blue, 20%);
+      &.label-active {
+        background-color: @infoText;
+        border-color: darken(@infoText, 20%);
 
 
         color: @white;
         color: @white;
-        text-shadow: 0px 1px 1px darken(@blue, 20%);
+        text-shadow: 0px -1px 0px darken(@infoText, 20%);
       }
       }
     }
     }
 
 
-    &.btn-warning {
+    &.label-warning {
       &, &:hover, &:active {
       &, &:hover, &:active {
         background-color: lighten(@orange, 40%);
         background-color: lighten(@orange, 40%);
         border-color: lighten(@orange, 20%);
         border-color: lighten(@orange, 20%);
 
 
-        color: darken(@orange, 5%);
+        color: @orange;
+        text-shadow: none;
       }
       }
 
 
-      &.btn-active {
+      &.label-active {
         background-color: @orange;
         background-color: @orange;
         border-color: darken(@orange, 20%);
         border-color: darken(@orange, 20%);
 
 
         color: @white;
         color: @white;
-        text-shadow: 0px 1px 1px darken(@orange, 20%);
+        text-shadow: 0px -1px 0px darken(@orange, 20%);
+      }
+    }
+
+    &.label-important {
+      &, &:hover, &:active {
+        background-color: lighten(@errorText, 40%);
+        border-color: lighten(@errorText, 20%);
+
+        color: @errorText;
+        text-shadow: none;
+      }
+
+      &.label-active {
+        background-color: @errorText;
+        border-color: darken(@errorText, 20%);
+
+        color: @white;
+        text-shadow: 0px -1px 0px darken(@errorText, 20%);
       }
       }
     }
     }
 
 
-    &.btn-important {
+    &.label-inverse {
       &, &:hover, &:active {
       &, &:hover, &:active {
-        background-color: lighten(@red, 40%);
-        border-color: lighten(@red, 20%);
+        background-color: lighten(@grayDark, 40%);
+        border-color: lighten(@grayDark, 20%);
 
 
-        color: @red;
+        color: @grayDark;
+        text-shadow: none;
       }
       }
 
 
-      &.btn-active {
-        background-color: @red;
-        border-color: darken(@red, 20%);
+      &.label-active {
+        background-color: @grayDark;
+        border-color: darken(@grayDark, 20%);
 
 
         color: @white;
         color: @white;
-        text-shadow: 0px 1px 1px darken(@red, 20%);
+        text-shadow: 0px -1px 0px darken(@grayDark, 20%);
       }
       }
     }
     }
 
 

+ 1 - 1
static/cranefly/css/cranefly/header.less

@@ -55,7 +55,7 @@
         bottom: 1px;
         bottom: 1px;
       }
       }
 
 
-      &>a {
+      &>a:not(.label) {
         color: @grayLight;
         color: @grayLight;
 
 
         &:hover, &:active {
         &:hover, &:active {

+ 21 - 0
static/cranefly/css/cranefly/labels-badges.less

@@ -0,0 +1,21 @@
+// Bootstrap overrides
+// -------------------------
+
+.label,
+.badge {
+  // Important (red)
+  &-important         { background-color: @errorText; }
+  &-important[href]   { background-color: @errorText; }
+  // Warnings (orange)
+  &-warning           { background-color: @orange; }
+  &-warning[href]     { background-color: @orange; }
+  // Success (green)
+  &-success           { background-color: @successText; }
+  &-success[href]     { background-color: @successText; }
+  // Info (turquoise)
+  &-info              { background-color: @infoText; }
+  &-info[href]        { background-color: @infoText; }
+  // Inverse (black)
+  &-inverse           { background-color: @grayDark; }
+  &-inverse[href]     { background-color: @grayDark; }
+}

+ 0 - 9
static/cranefly/css/cranefly/pagination.less

@@ -11,15 +11,6 @@
     color: @grayLight;
     color: @grayLight;
   }
   }
 
 
-  .separator {
-    margin-left: @baseFontSize;
-    margin-right: @baseFontSize * 0.75;
-    padding: 4px 0px;
-
-    color: @gray;
-    font-weight: bold;
-  }
-
   ul {
   ul {
     .box-shadow(none);
     .box-shadow(none);
 
 

+ 6 - 1
templates/cranefly/new_threads.html

@@ -102,7 +102,8 @@
             </li>
             </li>
           </ul>
           </ul>
           <div class="thread-title">
           <div class="thread-title">
-            <a href="{{ url('thread', thread=thread.pk, slug=thread.slug) }}">{{ thread.name }}</a>
+            {% if thread.prefix_id %}{{ draw_prefix(thread.forum, prefixes[thread.prefix_id]) }}{% endif %}
+            <a href="{{ url('thread', thread=thread.pk, slug=thread.slug) }}" class="thread-link">{{ thread.name }}</a>
           </div>
           </div>
         </div>
         </div>
       </li>
       </li>
@@ -127,4 +128,8 @@
   </ul>
   </ul>
 </div>
 </div>
 {% endif %}
 {% endif %}
+{%- endmacro %}
+
+{% macro draw_prefix(forum, prefix) -%}
+<a href="{{ url('forum_prefixed', slug=forum.slug, forum=forum.id, prefix=prefix.slug) }}" class="label{% if prefix.style %} label-{{ prefix.style }}{% endif %} thread-prefix thread-prefix-active">{{ _(prefix.name) }}</a>
 {%- endmacro %}
 {%- endmacro %}

+ 6 - 1
templates/cranefly/popular_threads.html

@@ -102,7 +102,8 @@
             </li>
             </li>
           </ul>
           </ul>
           <div class="thread-title">
           <div class="thread-title">
-            <a href="{{ url('thread', thread=thread.pk, slug=thread.slug) }}">{{ thread.name }}</a>
+            {% if thread.prefix_id %}{{ draw_prefix(thread.forum, prefixes[thread.prefix_id]) }}{% endif %}
+            <a href="{{ url('thread', thread=thread.pk, slug=thread.slug) }}" class="thread-link">{{ thread.name }}</a>
           </div>
           </div>
         </div>
         </div>
       </li>
       </li>
@@ -127,4 +128,8 @@
   </ul>
   </ul>
 </div>
 </div>
 {% endif %}
 {% endif %}
+{%- endmacro %}
+
+{% macro draw_prefix(forum, prefix) -%}
+<a href="{{ url('forum_prefixed', slug=forum.slug, forum=forum.id, prefix=prefix.slug) }}" class="label{% if prefix.style %} label-{{ prefix.style }}{% endif %} thread-prefix thread-prefix-active">{{ _(prefix.name) }}</a>
 {%- endmacro %}
 {%- endmacro %}

+ 1 - 1
templates/cranefly/private_threads/list.html

@@ -96,7 +96,7 @@
             {% endif %}
             {% endif %}
           </ul>
           </ul>
           <div class="thread-title">
           <div class="thread-title">
-            <a href="{{ url('private_thread', thread=thread.pk, slug=thread.slug) }}">{{ thread.name }}</a>
+            <a href="{{ url('private_thread', thread=thread.pk, slug=thread.slug) }}" class="thread-link">{{ thread.name }}</a>
           </div>
           </div>
         </div>
         </div>
       </li>
       </li>

+ 1 - 1
templates/cranefly/reports/list.html

@@ -126,7 +126,7 @@
             {% endif %}
             {% endif %}
           </ul>
           </ul>
           <div class="thread-title">
           <div class="thread-title">
-            <a href="{{ url('report', thread=thread.pk, slug=thread.slug) }}">{{ thread.name }}</a>
+            <a href="{{ url('report', thread=thread.pk, slug=thread.slug) }}" class="thread-link">{{ thread.name }}</a>
           </div>
           </div>
         </div>
         </div>
       </li>
       </li>

+ 24 - 21
templates/cranefly/threads/list.html

@@ -105,7 +105,8 @@
   {% endif %}
   {% endif %}
 
 
   <div class="forum-threads-extra extra-top">
   <div class="forum-threads-extra extra-top">
-    {{ pager(True) }}
+    {{ pager() }}
+    {{ prefix_selection() }}
     {% if user.is_authenticated() and acl.threads.can_start_threads(forum) %}
     {% if user.is_authenticated() and acl.threads.can_start_threads(forum) %}
     <a href="{{ url('thread_start', forum=forum.pk, slug=forum.slug) }}" class="btn btn-inverse pull-right"><i class="icon-plus"></i> {% trans %}New Thread{% endtrans %}</a>
     <a href="{{ url('thread_start', forum=forum.pk, slug=forum.slug) }}" class="btn btn-inverse pull-right"><i class="icon-plus"></i> {% trans %}New Thread{% endtrans %}</a>
     {% endif %}
     {% endif %}
@@ -208,7 +209,8 @@
             {% endif %}
             {% endif %}
           </ul>
           </ul>
           <div class="thread-title">
           <div class="thread-title">
-            {% if thread.prefix_id %}{{ draw_prefix(prefixes[thread.prefix_id]) }} {% endif %}<a href="{{ url('thread', thread=thread.pk, slug=thread.slug) }}">{{ thread.name }}</a>
+            {% if thread.prefix_id %}{{ draw_prefix(prefixes[thread.prefix_id]) }}{% endif %}
+            <a href="{{ url('thread', thread=thread.pk, slug=thread.slug) }}" class="thread-link">{{ thread.name }}</a>
           </div>
           </div>
         </div>
         </div>
       </li>
       </li>
@@ -284,46 +286,47 @@
 <strong{% if delta < number %} class="stat-increment"{% endif %}>{{ number|intcomma }}</strong>
 <strong{% if delta < number %} class="stat-increment"{% endif %}>{{ number|intcomma }}</strong>
 {%- endmacro %}
 {%- endmacro %}
 
 
-{% macro pager(first=False) %}
+{% macro pager() %}
 {% if pagination['total'] > 0 %}
 {% if pagination['total'] > 0 %}
 <div class="pagination pull-left">
 <div class="pagination pull-left">
   <ul>
   <ul>
     <li class="count">{{ macros.pager_label(pagination) }}</li>
     <li class="count">{{ macros.pager_label(pagination) }}</li>
+    {% if active_prefix %}
+    {%- if pagination['prev'] > 1 %}<li><a href="{{ url('forum_prefixed', slug=forum.slug, forum=forum.id, prefix=active_prefix.slug) }}" class="tooltip-top" title="{% trans %}First Page{% endtrans %}"><i class="icon-chevron-left"></i> {% trans %}First{% endtrans %}</a></li>{% endif -%}
+    {%- if pagination['prev'] > 0 %}<li><a href="{%- if pagination['prev'] > 1 %}{{ url('forum_prefixed', slug=forum.slug, forum=forum.id, prefix=active_prefix.slug, page=pagination['prev']) }}{% else %}{{ url('forum_prefixed', slug=forum.slug, forum=forum.id, prefix=active_prefix.slug) }}{% endif %}" class="tooltip-top" title="{% trans %}Newest Threads{% endtrans %}"><i class="icon-chevron-left"></i></a></li>{% endif -%}
+    {%- if pagination['next'] > 0 %}<li><a href="{{ url('forum_prefixed', slug=forum.slug, forum=forum.id, prefix=active_prefix.slug, page=pagination['next']) }}" class="tooltip-top" title="{% trans %}Older Threads{% endtrans %}"><i class="icon-chevron-right"></i></a></li>{% endif -%}
+    {% else %}
     {%- if pagination['prev'] > 1 %}<li><a href="{{ url('forum', slug=forum.slug, forum=forum.id) }}" class="tooltip-top" title="{% trans %}First Page{% endtrans %}"><i class="icon-chevron-left"></i> {% trans %}First{% endtrans %}</a></li>{% endif -%}
     {%- if pagination['prev'] > 1 %}<li><a href="{{ url('forum', slug=forum.slug, forum=forum.id) }}" class="tooltip-top" title="{% trans %}First Page{% endtrans %}"><i class="icon-chevron-left"></i> {% trans %}First{% endtrans %}</a></li>{% endif -%}
     {%- if pagination['prev'] > 0 %}<li><a href="{%- if pagination['prev'] > 1 %}{{ url('forum', slug=forum.slug, forum=forum.id, page=pagination['prev']) }}{% else %}{{ url('forum', slug=forum.slug, forum=forum.id) }}{% endif %}" class="tooltip-top" title="{% trans %}Newest Threads{% endtrans %}"><i class="icon-chevron-left"></i></a></li>{% endif -%}
     {%- if pagination['prev'] > 0 %}<li><a href="{%- if pagination['prev'] > 1 %}{{ url('forum', slug=forum.slug, forum=forum.id, page=pagination['prev']) }}{% else %}{{ url('forum', slug=forum.slug, forum=forum.id) }}{% endif %}" class="tooltip-top" title="{% trans %}Newest Threads{% endtrans %}"><i class="icon-chevron-left"></i></a></li>{% endif -%}
     {%- if pagination['next'] > 0 %}<li><a href="{{ url('forum', slug=forum.slug, forum=forum.id, page=pagination['next']) }}" class="tooltip-top" title="{% trans %}Older Threads{% endtrans %}"><i class="icon-chevron-right"></i></a></li>{% endif -%}
     {%- if pagination['next'] > 0 %}<li><a href="{{ url('forum', slug=forum.slug, forum=forum.id, page=pagination['next']) }}" class="tooltip-top" title="{% trans %}Older Threads{% endtrans %}"><i class="icon-chevron-right"></i></a></li>{% endif -%}
-    {% if first%}
-    {% if prefixes %}
-    <li class="separator">{% trans %}Show Threads:{% endtrans %}</li>
     {% endif %}
     {% endif %}
-    {% if prefixes and active_prefix %}
+  </ul>
+</div>
+{% endif %}
+{% endmacro %}
+
+{% macro prefix_selection() %}
+{% if prefixes %}
+<div class="prefix-select pull-left">
+  <ul>
+    <li class="selection-title">{% trans %}Show Threads:{% endtrans %}</li>
+    {% if active_prefix %}
     <li>
     <li>
-      <form class="form-prefix" action="{{ url('forum_switch_prefix', slug=forum.slug, forum=forum.id) }}" method="POST">
-        <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
-        <input type="hidden" name="retreat" value="{{ request_path }}">
-        <input type="hidden" name="switch_prefix" value="0">
-        <button type="submit" class="btn btn-cancel">{% trans %}All{% endtrans %}</button>
-      </form>
+      <a href="{{ url('forum', slug=forum.slug, forum=forum.id) }}" class="label label-cancel">{% trans %}All threads{% endtrans %}</a>
     </li>
     </li>
     {% endif %}
     {% endif %}
     {% for prefix in prefixes.values() %}
     {% for prefix in prefixes.values() %}
     <li>
     <li>
-      <form class="form-prefix" action="{{ url('forum_switch_prefix', slug=forum.slug, forum=forum.id) }}" method="POST">
-        <input type="hidden" name="{{ csrf_id }}" value="{{ csrf_token }}">
-        <input type="hidden" name="retreat" value="{{ request_path }}">
-        <input type="hidden" name="switch_prefix" value="{% if active_prefix == prefix %}0{% else %}{{ prefix.pk }}{% endif %}">
-        <button type="submit" class="btn{% if prefix.style %} btn-{{ prefix.style }}{% endif %}{% if active_prefix == prefix %} btn-active{% endif %}">{{ _(prefix.name) }}</button>
-      </form>
+      <a href="{{ url('forum_prefixed', slug=forum.slug, forum=forum.id, prefix=prefix.slug) }}" class="label{% if prefix.style %} label-{{ prefix.style }}{% endif %}{% if active_prefix == prefix %} label-active{% endif %}">{{ _(prefix.name) }}</a>
     </li>
     </li>
     {% endfor %}
     {% endfor %}
-    {% endif %}
   </ul>
   </ul>
 </div>
 </div>
 {% endif %}
 {% endif %}
 {% endmacro %}
 {% endmacro %}
 
 
 {% macro draw_prefix(prefix) -%}
 {% macro draw_prefix(prefix) -%}
-<span class="label{% if prefix.style %} label-{{ prefix.style }}{% endif %} thread-prefix">{{ _(prefix.name) }}</span>
+<a href="{{ url('forum_prefixed', slug=forum.slug, forum=forum.id, prefix=prefix.slug) }}" class="label{% if prefix.style %} label-{{ prefix.style }}{% endif %} thread-prefix">{{ _(prefix.name) }}</a>
 {%- endmacro %}
 {%- endmacro %}
 
 
 {% block javascripts -%}{{ super() }}
 {% block javascripts -%}{{ super() }}

+ 1 - 1
templates/cranefly/threads/thread.html

@@ -19,7 +19,7 @@
     </ul>
     </ul>
     <h1>{{ thread.name }}</h1>
     <h1>{{ thread.name }}</h1>
     <ul class="unstyled header-stats">
     <ul class="unstyled header-stats">
-      {% if prefix %}<li><i class="icon-tag"></i> <span class="label{% if prefix.style %} label-{{ prefix.style }}{% endif %} thread-prefix">{{ _(prefix.name) }}</span></li>{% endif %}
+      {% if prefix %}<li><i class="icon-tag"></i> <a href="{{ url('forum_prefixed', forum=forum.pk, slug=forum.slug, prefix=prefix.slug) }}" class="label{% if prefix.style %} label-{{ prefix.style }}{% endif %} thread-prefix">{{ _(prefix.name) }}</a></li>{% endif %}
       {% if thread.moderated %}<li><i class="icon-eye-close"></i> {% trans %}Not Reviewed{% endtrans %}</li>{% endif %}
       {% if thread.moderated %}<li><i class="icon-eye-close"></i> {% trans %}Not Reviewed{% endtrans %}</li>{% endif %}
       <li><i class="icon-time"></i> {{ thread.last|reltimesince }}</li>
       <li><i class="icon-time"></i> {{ thread.last|reltimesince }}</li>
       <li><i class="icon-user"></i> {% if thread.start_poster_id %}<a href="{{ url('user', user=thread.start_poster_id, username=thread.start_poster_slug) }}">{{ thread.start_poster_name }}</a>{% else %}{{ thread.start_poster_name }}{% endif %}</li>
       <li><i class="icon-user"></i> {% if thread.start_poster_id %}<a href="{{ url('user', user=thread.start_poster_id, username=thread.start_poster_slug) }}">{{ thread.start_poster_name }}</a>{% else %}{{ thread.start_poster_name }}{% endif %}</li>

+ 6 - 1
templates/cranefly/watched.html

@@ -71,7 +71,8 @@
             </form>
             </form>
           </div>
           </div>
           <div class="thread-title">
           <div class="thread-title">
-            <a href="{{ thread_url(thread) }}">{{ thread.name }}</a>
+            {% if thread.prefix_id %}{{ draw_prefix(thread.forum, prefixes[thread.prefix_id]) }}{% endif %}
+            <a href="{{ thread_url(thread) }}" class="thread-link">{{ thread.name }}</a>
           </div>
           </div>
           <ul class="thread-details">
           <ul class="thread-details">
             <li><a href="{{ thread.forum.url }}" class="forum-link">{{ thread.forum }}</a></li>
             <li><a href="{{ thread.forum.url }}" class="forum-link">{{ thread.forum }}</a></li>
@@ -141,6 +142,10 @@
 {% endif %}
 {% endif %}
 {%- endmacro %}
 {%- endmacro %}
 
 
+{% macro draw_prefix(forum, prefix) -%}
+<a href="{{ url('forum_prefixed', slug=forum.slug, forum=forum.id, prefix=prefix.slug) }}" class="label{% if prefix.style %} label-{{ prefix.style }}{% endif %} thread-prefix thread-prefix-active">{{ _(prefix.name) }}</a>
+{%- endmacro %}
+
 {% macro delete_retreat(loop) -%}
 {% macro delete_retreat(loop) -%}
 {%- if pagination['page'] == 1 -%}
 {%- if pagination['page'] == 1 -%}
   {{ request_path }}{% if not (loop.first and loop.last) %}#watch-{{ loop.index }}{% endif %}
   {{ request_path }}{% if not (loop.first and loop.last) %}#watch-{{ loop.index }}{% endif %}