Просмотр исходного кода

Added "new threads" view, changed popular threads view a little

Ralfp 12 лет назад
Родитель
Сommit
61c69e0d23

+ 2 - 0
misago/urls.py

@@ -22,6 +22,8 @@ urlpatterns = patterns('',
     url(r'^read/$', 'misago.views.read_all', name="read_all"),
     url(r'^forum-map/$', 'misago.views.forum_map', name="forum_map"),
     url(r'^popular/$', 'misago.views.popular_threads', name="popular_threads"),
+    url(r'^new/$', 'misago.views.new_threads', name="new_threads"),
+    url(r'^new/(?P<page>[0-9]+)/$', 'misago.views.new_threads', name="new_threads"),
 )
 
 # Include admin patterns

+ 29 - 1
misago/views.py

@@ -13,7 +13,8 @@ from misago.readstracker.models import Record
 from misago.readstracker.trackers import ForumsTracker
 from misago.ranks.models import Rank
 from misago.sessions.models import Session
-from misago.threads.models import Thread
+from misago.threads.models import Thread, Post
+from misago.utils import make_pagination
 
 def home(request):
     # Threads ranking
@@ -149,6 +150,33 @@ def popular_threads(request):
                                             context_instance=RequestContext(request));
 
 
+def new_threads(request, page=0):
+    threads = []
+    queryset = Thread.objects.filter(forum_id__in=request.acl.threads.get_readable_forums(request.acl)).filter(deleted=False).filter(moderated=False).filter(start__gte=(timezone.now() - timedelta(days=2)))
+    items_total = queryset.count();
+    pagination = None
+    if items_total > 0:
+        pagination = make_pagination(page, items_total, 30)
+        threads_dict = {}
+
+        for thread in Thread.objects.filter(forum_id__in=request.acl.threads.get_readable_forums(request.acl)).filter(deleted=False).filter(moderated=False).order_by('-start').prefetch_related('start_poster', 'forum')[pagination['start']:pagination['stop']]:
+            thread.has_reply = False
+            threads.append(thread)
+            threads_dict[thread.pk] = thread
+
+        if request.user.is_authenticated():
+            for post in Post.objects.values('thread_id').distinct().filter(user=request.user).filter(thread_id__in=threads_dict.keys()):
+                threads_dict[post['thread_id']].has_reply = True
+
+    return request.theme.render_to_response('new_threads.html',
+                                            {
+                                             'items_total': items_total,
+                                             'threads': threads,
+                                             'pagination': pagination,
+                                             },
+                                            context_instance=RequestContext(request));
+
+
 def redirect_message(request, message, type='info', owner=None):
     request.messages.set_flash(message, type, owner)
     return redirect(reverse('index'))

+ 11 - 3
static/cranefly/css/cranefly.css

@@ -872,8 +872,9 @@ footer .credits{color:#555555;font-size:90%;}footer .credits a:link,footer .cred
 .navbar .navbar-inner .navbar-blocks{margin-left:6px;}.navbar .navbar-inner .navbar-blocks li{margin-left:6px;}.navbar .navbar-inner .navbar-blocks li form{margin:0px;padding:0px;}
 .navbar .navbar-inner .navbar-blocks li a:link,.navbar .navbar-inner .navbar-blocks li a:visited,.navbar .navbar-inner .navbar-blocks li .btn-link{background-color:#f8f8f8;border:1px solid #dadada;border-radius:3px;padding:5px 8px;margin-top:9px;}.navbar .navbar-inner .navbar-blocks li a:link i,.navbar .navbar-inner .navbar-blocks li a:visited i,.navbar .navbar-inner .navbar-blocks li .btn-link i{opacity:0.7;filter:alpha(opacity=70);}
 .navbar .navbar-inner .navbar-blocks li a:link .label,.navbar .navbar-inner .navbar-blocks li a:visited .label,.navbar .navbar-inner .navbar-blocks li .btn-link .label{background-color:#cf402e;margin-left:4px;padding-left:6px;padding-right:5px;position:relative;bottom:1px;}
-.navbar .navbar-inner .navbar-blocks li a:hover,.navbar .navbar-inner .navbar-blocks li a:active,.navbar .navbar-inner .navbar-blocks li .btn-link:hover,.navbar .navbar-inner .navbar-blocks li .btn-link:active{background-color:#0088cc;border-color:#0088cc;}.navbar .navbar-inner .navbar-blocks li a:hover.danger,.navbar .navbar-inner .navbar-blocks li a:active.danger,.navbar .navbar-inner .navbar-blocks li .btn-link:hover.danger,.navbar .navbar-inner .navbar-blocks li .btn-link:active.danger{background-color:#cf402e;border-color:#cf402e;}
-.navbar .navbar-inner .navbar-blocks li a:hover.hot,.navbar .navbar-inner .navbar-blocks li a:active.hot,.navbar .navbar-inner .navbar-blocks li .btn-link:hover.hot,.navbar .navbar-inner .navbar-blocks li .btn-link:active.hot{background-color:#f89406;border-color:#f89406;}
+.navbar .navbar-inner .navbar-blocks li a:hover,.navbar .navbar-inner .navbar-blocks li a:active,.navbar .navbar-inner .navbar-blocks li .btn-link:hover,.navbar .navbar-inner .navbar-blocks li .btn-link:active{background-color:#0088cc;border-color:#006699;}.navbar .navbar-inner .navbar-blocks li a:hover.danger,.navbar .navbar-inner .navbar-blocks li a:active.danger,.navbar .navbar-inner .navbar-blocks li .btn-link:hover.danger,.navbar .navbar-inner .navbar-blocks li .btn-link:active.danger{background-color:#cf402e;border-color:#a53325;}
+.navbar .navbar-inner .navbar-blocks li a:hover.hot,.navbar .navbar-inner .navbar-blocks li a:active.hot,.navbar .navbar-inner .navbar-blocks li .btn-link:hover.hot,.navbar .navbar-inner .navbar-blocks li .btn-link:active.hot{background-color:#f89406;border-color:#c67605;}
+.navbar .navbar-inner .navbar-blocks li a:hover.fresh,.navbar .navbar-inner .navbar-blocks li a:active.fresh,.navbar .navbar-inner .navbar-blocks li .btn-link:hover.fresh,.navbar .navbar-inner .navbar-blocks li .btn-link:active.fresh{background-color:#46a546;border-color:#378137;}
 .navbar .navbar-inner .navbar-blocks li a:hover i,.navbar .navbar-inner .navbar-blocks li a:active i,.navbar .navbar-inner .navbar-blocks li .btn-link:hover i,.navbar .navbar-inner .navbar-blocks li .btn-link:active i{background-image:url("../img/glyphicons-halflings-white.png");opacity:1;filter:alpha(opacity=100);}
 .navbar .navbar-inner .navbar-blocks li a:hover .label,.navbar .navbar-inner .navbar-blocks li a:active .label,.navbar .navbar-inner .navbar-blocks li .btn-link:hover .label,.navbar .navbar-inner .navbar-blocks li .btn-link:active .label{background-color:#eeeeee;color:#333333;}
 .navbar .navbar-inner .navbar-blocks li.user-profile a:link,.navbar .navbar-inner .navbar-blocks li.user-profile a:visited,.navbar .navbar-inner .navbar-blocks li.user-profile a:hover,.navbar .navbar-inner .navbar-blocks li.user-profile a:active{background:none;border:none;margin-right:8px;margin-top:5px;font-weight:bold;text-shadow:none;}.navbar .navbar-inner .navbar-blocks li.user-profile a:link img,.navbar .navbar-inner .navbar-blocks li.user-profile a:visited img,.navbar .navbar-inner .navbar-blocks li.user-profile a:hover img,.navbar .navbar-inner .navbar-blocks li.user-profile a:active img{background-color:#ffffff;border-radius:3px;-webkit-box-shadow:0px 0px 4px #eeeeee;-moz-box-shadow:0px 0px 4px #eeeeee;box-shadow:0px 0px 4px #eeeeee;margin-right:4px;width:32px;height:32px;position:relative;bottom:1px;}
@@ -1001,7 +1002,7 @@ a.btn-link:hover,a.btn-link:active,a.btn-link:focus{opacity:0.9;filter:alpha(opa
 .forum-map-category.forum-map-category-inverse caption{background-color:#333333;border:1px solid #1a1a1a;color:#eeeeee;text-shadow:0px 1px 0px #000000;}.forum-map-category.forum-map-category-inverse caption small{color:#b3b3b3;text-shadow:none;}
 .forum-map-category.forum-map-category-info caption{background-color:#3c85a3;border:1px solid #2e677e;color:#ffffff;text-shadow:0px 1px 0px #1a3946;}.forum-map-category.forum-map-category-info caption small{color:#1a3946;text-shadow:none;}
 .popular-threads hr{margin:14px 0px;border:none;border-top:1px solid #eeeeee;}
-.popular-threads .popular-thread{overflow:auto;}.popular-threads .popular-thread .popular-thread-warmth{display:block;float:left;margin-top:1px;margin-right:14px;padding:10.5px;color:#ffffff;text-align:center;font-weight:bold;text-shadow:0px 1px 0px #3b3b3b;}.popular-threads .popular-thread .popular-thread-warmth i{background-image:url("../img/glyphicons-halflings-white.png");}
+.popular-threads .popular-thread{overflow:auto;}.popular-threads .popular-thread .popular-thread-warmth{display:block;float:left;margin-top:1px;margin-right:14px;padding:10.5px;}.popular-threads .popular-thread .popular-thread-warmth i{background-image:url("../img/glyphicons-halflings-white.png");}
 .popular-threads .popular-thread .popular-thread-warmth.popular-thread-warmth-0{background-color:#cf402e;border:1px solid #a53325;}
 .popular-threads .popular-thread .popular-thread-warmth.popular-thread-warmth-1{background-color:#a95d54;border:1px solid #874b43;}
 .popular-threads .popular-thread .popular-thread-warmth.popular-thread-warmth-2{background-color:#90716d;border:1px solid #735a57;}
@@ -1020,6 +1021,13 @@ a.btn-link:hover,a.btn-link:active,a.btn-link:focus{opacity:0.9;filter:alpha(opa
 .watched-threads .table .thread-replies{color:#999999;text-align:right;}
 .watched-threads .table .thread-forum a:link,.watched-threads .table .thread-forum a:visited{color:#555555;}
 .watched-threads .table .thread-forum a:active,.watched-threads .table .thread-forum a:hover{color:#333333;}
+.new-threads table td{vertical-align:middle;}
+.new-threads .thread-reply{background-color:#333333;border:1px solid #1a1a1a;margin-top:1px;margin-right:7px;padding:3px 4px;}.new-threads .thread-reply i{background-image:url("../img/glyphicons-halflings-white.png");}
+.new-threads .thread-reply.has-reply{background-color:#46a546;border:1px solid #378137;}
+.new-threads .thread-title:link,.new-threads .thread-title:visited{color:#555555;font-weight:bold;}
+.new-threads .thread-title:hover,.new-threads .thread-title:active{color:#333333;}
+.new-threads .thread-details{color:#999999;font-size:11.9px;}.new-threads .thread-details a:link,.new-threads .thread-details a:visited{color:#555555;}
+.new-threads .thread-details a:hover,.new-threads .thread-details a:active{color:#333333;}
 .user-alerts td{vertical-align:middle;}.user-alerts td.alert-icon .label{background-color:#555555;border:1px solid #2f2f2f;border-radius:3px;padding:4px;padding-top:3px;}.user-alerts td.alert-icon .label i{background-image:url("../img/glyphicons-halflings-white.png");}
 .user-alerts td.alert-icon .label.label-warning{background-color:#cf402e;border:1px solid #902d20;}
 .user-alerts td.alert-message{color:#555555;font-size:16.8px;}.user-alerts td.alert-message a:link,.user-alerts td.alert-message a:visited{color:#333333;font-weight:bold;}

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

@@ -82,6 +82,7 @@
 @import "cranefly/forummap.less";
 @import "cranefly/popularthreads.less";
 @import "cranefly/watchedthreads.less";
+@import "cranefly/newthreads.less";
 @import "cranefly/alerts.less";
 @import "cranefly/newsfeed.less";
 @import "cranefly/category.less";

+ 8 - 3
static/cranefly/css/cranefly/navbar.less

@@ -88,16 +88,21 @@
 
         a:hover, a:active, .btn-link:hover, .btn-link:active {
           background-color: @linkColor;
-          border-color: @linkColor;
+          border-color: darken(@linkColor, 10%);
 
           &.danger {
             background-color: @red;
-            border-color: @red;
+            border-color: darken(@red, 10%);
           }
 
           &.hot {
             background-color: @orange;
-            border-color: @orange;
+            border-color: darken(@orange, 10%);
+          }
+
+          &.fresh {
+            background-color: @green;
+            border-color: darken(@green, 10%);
           }
 
           i {

+ 51 - 0
static/cranefly/css/cranefly/newthreads.less

@@ -0,0 +1,51 @@
+// New threads
+// -------------------------
+
+.new-threads {
+  table {
+    td {
+      vertical-align: middle; 
+    }
+  }
+
+  .thread-reply {
+    background-color: @grayDark;
+    border: 1px solid darken(@grayDark, 10%);
+    margin-top: 1px;
+    margin-right: @baseFontSize / 2;
+    padding: 3px 4px;
+
+    i {
+      background-image: url("@{iconWhiteSpritePath}");
+    }
+
+    &.has-reply {
+      background-color: @green;
+      border: 1px solid darken(@green, 10%);
+    }
+  }
+
+  .thread-title {
+    &:link, &:visited {
+      color: @gray;
+      font-weight: bold;
+    }
+
+    &:hover, &:active {
+      color: @textColor;
+    }
+  }
+
+  .thread-details {
+    color: @grayLight;
+    font-size: @fontSizeSmall;
+
+    a:link, a:visited {
+      color: @gray;
+    }
+
+    a:hover, a:active {
+      color: @textColor;
+    }
+  }
+}

+ 0 - 5
static/cranefly/css/cranefly/popularthreads.less

@@ -18,11 +18,6 @@
       margin-right: @baseFontSize;
       padding: @fontSizeMini;
 
-      color: @white;
-      text-align: center;
-      font-weight: bold;
-      text-shadow: 0px 1px 0px darken(@gray, 10%);
-
       i {
         background-image: url("@{iconWhiteSpritePath}");
       }

+ 2 - 1
templates/cranefly/layout.html

@@ -20,7 +20,8 @@
         {% endif %}
         <ul class="nav navbar-blocks pull-left">
           <li><a href="{% url 'index' %}" title="{% trans %}Forum Home{% endtrans %}" class="tooltip-bottom"><i class="icon-th-list"></i></a></li>
-          <li><a href="{% url 'popular_threads' %}" title="{% trans %}Popular Threads{% endtrans %}" class="hot tooltip-bottom"><i class="icon-fire"></i></a></li>{% if not user.crawler %}
+          <li><a href="{% url 'popular_threads' %}" title="{% trans %}Popular Threads{% endtrans %}" class="hot tooltip-bottom"><i class="icon-fire"></i></a></li>
+          <li><a href="{% url 'new_threads' %}" title="{% trans %}New Threads{% endtrans %}" class="fresh tooltip-bottom"><i class="icon-leaf"></i></a></li>{% if not user.crawler %}
           <li><a href="#" title="{% trans %}Search Community{% endtrans %}" class="tooltip-bottom"><i class="icon-search"></i></a></li>{% endif %}
           <li><a href="{% url 'users' %}" title="{% trans %}Browse Users{% endtrans %}" class="tooltip-bottom"><i class="icon-user"></i></a></li>
           {% if settings.tos_url or settings.tos_content %}<li><a href="{% if settings.tos_url %}{{ settings.tos_url }}{% else %}{% url 'tos' %}{% endif %}" title="{% if settings.tos_title %}{{ settings.tos_title }}{% else %}{% trans %}Forum Terms of Service{% endtrans %}{% endif %}" class="tooltip-bottom"><i class="icon-certificate"></i></a></li>{% endif %}

+ 70 - 0
templates/cranefly/new_threads.html

@@ -0,0 +1,70 @@
+{% extends "cranefly/layout.html" %}
+{% load i18n %}
+{% import "cranefly/macros.html" as macros with context %}
+
+{% block title %}{{ macros.page_title(title=_('New Threads')) }}{% endblock %}
+
+{% block container %}
+<div class="page-header header-primary">
+  <div class="container">
+    {{ messages_list(messages) }}
+    <h1>{% trans %}New Threads{% endtrans %}</h1>
+  </div>
+</div>
+
+<div class="container container-primary">
+  {% if threads %}
+  <div class="new-threads">
+    <table class="table">
+      <thead>
+        <tr>
+          <th>{% trans %}Thread{% endtrans %}</th>
+          <th class="span6">{% trans %}Started{% endtrans %}</th>
+        </tr>
+      </thead>
+      <tbody>
+        {% for thread in threads %}
+        <tr>
+          <td>
+            <a href="{% url 'thread_new' thread=thread.pk, slug=thread.slug %}" class="label thread-reply{% if thread.has_reply %} has-reply{% endif %} tooltip-top" title="{% if thread.has_reply %}{% trans %}You've replied to this thread{% endtrans %}{% else %}{% trans %}This thread waits for your voice{% endtrans %}{% endif %}"><i class="icon-comment"></i></a>
+            <a href="{% url 'thread' thread=thread.pk, slug=thread.slug %}" class="thread-title">{{ thread.name }}</a>
+          </td>
+          <td class="thread-details">
+            {% trans forum=forum(thread.forum), starter=username(thread.start_poster_id, thread.start_poster_name, thread.start_poster_slug), start=thread.start|reltimesince %}{{ start }} - by {{ starter }} - {{ forum }}{% endtrans %}
+          </td>
+        </tr>
+        {% endfor %}
+      </tbody>
+    </table>
+  </div>
+  {{ pager() }}
+  {% else %}
+  <p class="lead">{% trans %}No new threads were started in last 48 hours.{% endtrans %}</p>
+  {% endif %}
+</div>
+{% endblock %}
+
+
+{% macro forum(forum) -%}
+<a href="{% url 'forum' forum=forum.pk, slug=forum.slug %}">{{ forum.name }}</a>
+{%- endmacro %}
+
+{% macro username(id, username, slug) -%}
+{%- if id -%}
+<a href="{% url 'user' user=id, username=slug %}">{{ username }}</a>
+{%- else -%}
+{{ username }}
+{%- endif -%}
+{%- endmacro %}
+
+{% macro pager() -%}
+{% if items_total > 0 and pagination['total'] > 1 %}
+<div class="pagination">
+  <ul>
+    <li class="count">{{ macros.pager_label(pagination) }}</li>
+    {%- if pagination['prev'] > 0 %}<li><a href="{%- if pagination['prev'] > 1 %}{% url 'new_threads' page=pagination['prev'] %}{% else %}{% url 'new_threads' %}{% endif %}" class="tooltip-top" title="{% trans %}Previous Page{% endtrans %}"><i class="icon-chevron-left"></i></a></li>{% endif -%}
+    {%- if pagination['next'] > 0 %}<li><a href="{% url 'new_threads' page=pagination['next'] %}" class="tooltip-top" title="{% trans %}Next Page{% endtrans %}"><i class="icon-chevron-right"></i></a></li>{% endif -%}
+  </ul>
+</div>
+{% endif %}
+{%- endmacro %}

+ 1 - 1
templates/cranefly/popular_threads.html

@@ -27,7 +27,7 @@
           <div class="popular-thread-details">
             <a href="{% url 'thread' thread=thread.pk, slug=thread.slug %}" class="popular-thread-title tooltip-top" title="{% trans %}Jump to thread start{% endtrans %}">{{ thread.name }}</a>
             <p class="popular-thread-info">
-              {% trans forum=forum(thread.forum), starter=username(thread.start_poster_id, thread.start_poster_name, thread.start_poster_slug), last=thread.last|reldate, replies=replies(thread.replies) %}By {{ starter }} - {{ forum }} - {{ replies }} - last on {{ last }}.{% endtrans %}
+              {% trans forum=forum(thread.forum), starter=username(thread.start_poster_id, thread.start_poster_name, thread.start_poster_slug), last=thread.last|reldate, replies=replies(thread.replies) %}By {{ starter }} - {{ forum }} - {{ replies }} - last on {{ last }}{% endtrans %}
             </p>
           </div>
         </div>