Rafał Pitoń 10 лет назад
Родитель
Сommit
b4d6ffedc3

+ 6 - 0
docs/developers/settings.rst

@@ -254,6 +254,12 @@ Some lists act as rankings, displaying users in order of certain scoring criteri
 This setting controls maximum age in days of items that should count to ranking.
 This setting controls maximum age in days of items that should count to ranking.
 
 
 
 
+MISAGO_RANKING_SIZE
+-------------------
+
+Maximum number of items on ranking page.
+
+
 MISAGO_READ_RECORD_LENGTH
 MISAGO_READ_RECORD_LENGTH
 -------------------------
 -------------------------
 Controls amount of data used in resolving read/unread states of threads and forums. Any activity older than number of days specified in this setting is assumed to be read and not tracked anymore. Active forums can try lowering this value while less active ones may wish to increase this number.
 Controls amount of data used in resolving read/unread states of threads and forums. Any activity older than number of days specified in this setting is assumed to be read and not tracked anymore. Active forums can try lowering this value while less active ones may wish to increase this number.

+ 2 - 0
misago/conf/defaults.py

@@ -278,6 +278,8 @@ MISAGO_AVATAR_SERVER_PATH = '/user-avatar'
 # You don't have to be overzelous with this as user rankings are cached for 24h
 # You don't have to be overzelous with this as user rankings are cached for 24h
 MISAGO_RANKING_LENGTH = 30
 MISAGO_RANKING_LENGTH = 30
 
 
+# Controls max number of items displayed on ranked lists
+MISAGO_RANKING_SIZE = 30
 
 
 # Controls amount of data used in resolving read/unread states of threads and
 # Controls amount of data used in resolving read/unread states of threads and
 # forums. Any activity older than number of days below is assumed to be read
 # forums. Any activity older than number of days below is assumed to be read

+ 1 - 0
misago/static/misago/admin/css/style.css

@@ -6413,6 +6413,7 @@ body {
 }
 }
 .yes-no-switch {
 .yes-no-switch {
   margin-top: 5px;
   margin-top: 5px;
+  margin-bottom: 0px;
   cursor: pointer;
   cursor: pointer;
 }
 }
 .yes-no-switch .fa {
 .yes-no-switch .fa {

+ 32 - 0
misago/static/misago/css/misago/userslists.less

@@ -77,3 +77,35 @@
     }
     }
   }
   }
 }
 }
+
+
+// Users ranking
+//
+//==
+.users-ranking {
+  &>tbody {
+    &>tr {
+      &>td {
+        vertical-align: middle;
+
+        .avatar {
+          border-radius: @border-radius-base;
+        }
+
+        .item-title {
+          font-size: @font-size-large;
+        }
+      }
+
+      &.highlight {
+        color: @brand-accent;
+
+        .item-title {
+          &:link, &:visited {
+            color: @brand-accent;
+          }
+        }
+      }
+    }
+  }
+}

+ 56 - 29
misago/templates/misago/userslists/active_posters.html

@@ -1,5 +1,5 @@
 {% extends "misago/userslists/base.html" %}
 {% extends "misago/userslists/base.html" %}
-{% load humanize i18n %}
+{% load humanize i18n misago_avatars %}
 
 
 
 
 {% block meta-description %}{% blocktrans trimmed with days=tracked_period %}
 {% block meta-description %}{% blocktrans trimmed with days=tracked_period %}
@@ -7,33 +7,60 @@ List of users that have posted new messages during last {{ days }} days.
 {% endblocktrans %}{% endblock meta-description %}
 {% endblocktrans %}{% endblock meta-description %}
 
 
 
 
-{% block users-list %}
-<p class="lead">
-  {% blocktrans trimmed with posters=users.paginator.count|intcomma days=tracked_period count counter=users.paginator.count %}
-  {{ posters }} user has posted new messages posting during last {{ days }} days.
-  {% plural %}
-  {{ posters }} users posted new messages during last {{ days }} days.
-  {% endblocktrans %}
-</p>
+{% block users %}
+{% if users_count %}
+  <p class="lead">
+    {% blocktrans trimmed with posters=users_count|intcomma days=tracked_period count counter=users_count %}
+    {{ posters }} user has posted new messages posting during last {{ days }} days.
+    {% plural %}
+    {{ posters }} users posted new messages during last {{ days }} days.
+    {% endblocktrans %}
+  </p>
 
 
-{{ block.super }}
-{% endblock users-list %}
+  <table class="table users-ranking">
+    <thead>
+      <tr>
+        <th colspan="2">{% trans "User" %}</th>
+        <th class="text-center">{% trans "Rank" %}</th>
+        <th class="text-center">{% trans "Posts" %}</th>
+        <th class="text-center">{% trans "Total" %}</th>
+      </tr>
+    </thead>
+    <tbody>
+      {% for ranked in users %}
+      {% url USER_PROFILE_URL user_slug=ranked.slug user_id=ranked.id as user_url %}
+      <tr {% if ranked.pk == user.pk %}class="highlight"{% endif %}>
+        <td style="width: 1%;">
+          <a href="{{ user_url }}">
+            <img src="{{ ranked|avatar:30 }}" alt="{% trans "Avatar" %}"class="avatar">
+          </a>
+        </td>
+        <td>
+          <a href="{{ user_url }}" class="item-title">{{ ranked.username }}</a>
+        </td>
+        <td class="lead text-center">
+          #{{ forloop.counter }}
+        </td>
+        <td class="lead text-center">
+          {{ ranked.num_posts }}
+        </td>
+        <td class="lead text-center">
+          {% if ranked.num_posts > ranked.posts %}
+          {{ ranked.num_posts }}
+          {% else %}
+          {{ ranked.posts }}
+          {% endif %}
+        </td>
+      </tr>
+      {% endfor %}
+    </tbody>
+  </table>
+{% else %}
+  <p class="lead">
+    {% blocktrans trimmed with days=tracked_period %}
+    No users have posted any new messages during last {{ days }} days.
+    {% endblocktrans %}
+  </p>
+{% endif %}
+{% endblock users %}
 
 
-
-{% block user-card-footer %}
-{{ block.super }}
-<small>
-  {% blocktrans trimmed with posts=user.followers|intcomma count counter=user.followers %}
-  {{ posts }} post
-  {% plural %}
-  {{ posts }} posts
-  {% endblocktrans %}
-</small>
-{% endblock user-card-footer %}
-
-
-{% block empty-list %}
-{% blocktrans trimmed with days=tracked_period %}
-No users have posted any new messages during last {{ days }} days.
-{% endblocktrans %}
-{% endblock empty-list %}

+ 31 - 29
misago/templates/misago/userslists/base.html

@@ -31,40 +31,42 @@
 </div>
 </div>
 
 
 <div class="container">
 <div class="container">
-  {% if users.object_list %}
-    {% block users-list %}
-    <div class="users-cards">
-      {% for row in users.object_list|batch:6 %}
-      <div class="row">
-        {% for card in row %}
-        <div class="col-md-2">
+  {% block users %}
+    {% if users.object_list %}
+      {% block users-list %}
+      <div class="users-cards">
+        {% for row in users.object_list|batch:6 %}
+        <div class="row">
+          {% for card in row %}
+          <div class="col-md-2">
 
 
-          {% block user-card %}
-          <a href="{% url USER_PROFILE_URL user_slug=card.slug user_id=card.id %}" class="user-card {% if card.rank.css_class %}card-{{ card.rank.css_class }}{% endif %}">
-            <img src="{{ card|avatar:400 }}" alt="{% trans "Avatar" %}">
-            <div class="card-footer">
-              {% block user-card-footer %}
-              <h4 class="user-name">{{ card.username }}</h4>
-              {% endblock user-card-footer %}
-            </div>
-          </a>
-          {% endblock user-card %}
+            {% block user-card %}
+            <a href="{% url USER_PROFILE_URL user_slug=card.slug user_id=card.id %}" class="user-card {% if card.rank.css_class %}card-{{ card.rank.css_class }}{% endif %}">
+              <img src="{{ card|avatar:400 }}" alt="{% trans "Avatar" %}">
+              <div class="card-footer">
+                {% block user-card-footer %}
+                <h4 class="user-name">{{ card.username }}</h4>
+                {% endblock user-card-footer %}
+              </div>
+            </a>
+            {% endblock user-card %}
 
 
+          </div>
+          {% endfor %}
         </div>
         </div>
         {% endfor %}
         {% endfor %}
       </div>
       </div>
-      {% endfor %}
-    </div>
-    {% endblock users-list %}
+      {% endblock users-list %}
 
 
-    {% block list-pagination %}
-      {% pagination users "misago/userslists/pagination.html" active_page.link %}
-    {% endblock list-pagination %}
-  {% else %}
-    <p class="lead">
-      {% block empty-list %}
-      {% endblock empty-list %}
-    </p>
-  {% endif %}
+      {% block list-pagination %}
+        {% pagination users "misago/userslists/pagination.html" active_page.link %}
+      {% endblock list-pagination %}
+    {% else %}
+      <p class="lead">
+        {% block empty-list %}
+        {% endblock empty-list %}
+      </p>
+    {% endif %}
+  {% endblock users %}
 </div>
 </div>
 {% endblock content%}
 {% endblock content%}

+ 1 - 1
misago/threads/migrations/0001_initial.py

@@ -40,7 +40,7 @@ class Migration(migrations.Migration):
                 ('checksum', models.CharField(max_length=64)),
                 ('checksum', models.CharField(max_length=64)),
                 ('has_attachments', models.BooleanField(default=False)),
                 ('has_attachments', models.BooleanField(default=False)),
                 ('pickled_attachments', models.TextField(null=True, blank=True)),
                 ('pickled_attachments', models.TextField(null=True, blank=True)),
-                ('posted_on', models.DateTimeField()),
+                ('posted_on', models.DateTimeField(db_index=True)),
                 ('updated_on', models.DateTimeField()),
                 ('updated_on', models.DateTimeField()),
                 ('edits', models.PositiveIntegerField(default=0)),
                 ('edits', models.PositiveIntegerField(default=0)),
                 ('last_editor_name', models.CharField(max_length=255, null=True, blank=True)),
                 ('last_editor_name', models.CharField(max_length=255, null=True, blank=True)),

+ 1 - 1
misago/threads/models/post.py

@@ -20,7 +20,7 @@ class Post(models.Model):
                                       related_name="mention_set")
                                       related_name="mention_set")
     has_attachments = models.BooleanField(default=False)
     has_attachments = models.BooleanField(default=False)
     pickled_attachments = models.TextField(null=True, blank=True)
     pickled_attachments = models.TextField(null=True, blank=True)
-    posted_on = models.DateTimeField()
+    posted_on = models.DateTimeField(db_index=True)
     updated_on = models.DateTimeField()
     updated_on = models.DateTimeField()
     edits = models.PositiveIntegerField(default=0)
     edits = models.PositiveIntegerField(default=0)
     last_editor = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='+',
     last_editor = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='+',

+ 19 - 7
misago/users/views/lists.py

@@ -1,8 +1,9 @@
-import warnings
+from datetime import timedelta
 
 
 from django.conf import settings
 from django.conf import settings
 from django.contrib.auth import get_user_model
 from django.contrib.auth import get_user_model
 from django.core.urlresolvers import reverse
 from django.core.urlresolvers import reverse
+from django.db.models import Count
 from django.shortcuts import redirect, render as django_render
 from django.shortcuts import redirect, render as django_render
 from django.utils import timezone
 from django.utils import timezone
 from django.views.decorators.cache import cache_page
 from django.views.decorators.cache import cache_page
@@ -62,18 +63,29 @@ def list_view(request, template, queryset, page, context=None):
     return render(request, template, context)
     return render(request, template, context)
 
 
 
 
+def ranking_view(request, template, queryset, context=None):
+    context = context or {}
+    context.update({
+        'users': queryset[:settings.MISAGO_RANKING_SIZE],
+        'users_count': queryset.count()
+    })
+    return render(request, template, context)
+
+
+#@cache_page(18 * 3600)
 @allow_see_list()
 @allow_see_list()
-@cache_page(24 * 3600)
 def active_posters(request, page=0):
 def active_posters(request, page=0):
-    warnings.warn("Not implemented yet! See #404 for details.",
-                  FutureWarning)
-
     tracked_period = settings.MISAGO_RANKING_LENGTH
     tracked_period = settings.MISAGO_RANKING_LENGTH
+    tracked_since = timezone.now() - timedelta(days=tracked_period)
+
     User = get_user_model()
     User = get_user_model()
-    queryset = User.objects.all().select_related('user__rank')
+    queryset = User.objects.filter(post__posted_on__gte=tracked_since)
+    queryset = queryset.annotate(num_posts=Count('post'))
+    queryset = queryset.select_related('user__rank')
+    queryset = queryset.order_by('-num_posts')
 
 
     template = "misago/userslists/active_posters.html"
     template = "misago/userslists/active_posters.html"
-    return list_view(request, template, queryset, page, {
+    return ranking_view(request, template, queryset, {
         'tracked_period': tracked_period
         'tracked_period': tracked_period
     })
     })