Browse Source

User avatars on threads list.

Ralfp 12 years ago
parent
commit
26209e3c61

+ 7 - 0
misago/threads/fixtures.py

@@ -40,6 +40,13 @@ settings_fixtures = (
                 'name':         _("Threads per page"),
                 'name':         _("Threads per page"),
                 'description':  _("Number of threads displayed on page in forum view."),
                 'description':  _("Number of threads displayed on page in forum view."),
             }),
             }),
+            ('avatars_on_threads_list', {
+                'value':        True,
+                'type':         "boolean",
+                'input':        "yesno",
+                'name':         _("Display avatars on threads list"),
+                'description':  _("Unlike basic user data, avatars are not cached - turning this option on will cause one extra query on threads lists."),
+            }),
             ('post_length_min', {
             ('post_length_min', {
                 'value':        5,
                 'value':        5,
                 'type':         "integer",
                 'type':         "integer",

+ 0 - 1
misago/threads/forms.py

@@ -44,7 +44,6 @@ class PostForm(Form, ThreadNameMixin):
                        ]
                        ]
     
     
         if self.mode not in ['edit_thread', 'new_thread']:
         if self.mode not in ['edit_thread', 'new_thread']:
-            del self.fields['thread_name']
             del self.layout[0][1][0]
             del self.layout[0][1][0]
         else:
         else:
             self.fields['thread_name'] = forms.CharField(
             self.fields['thread_name'] = forms.CharField(

+ 7 - 2
misago/threads/views/list.py

@@ -30,9 +30,14 @@ class ThreadsView(BaseView, ThreadsFormMixin):
         self.count = self.request.acl.threads.filter_threads(self.request, self.forum, Thread.objects.filter(forum=self.forum).filter(weight__lt=2)).count()
         self.count = self.request.acl.threads.filter_threads(self.request, self.forum, Thread.objects.filter(forum=self.forum).filter(weight__lt=2)).count()
         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 = []
-        for thread in Thread.objects.filter(Q(forum=self.request.monitor['anno']) | (Q(forum=self.forum) & Q(weight=2))):
+        queryset_anno = Thread.objects.filter(Q(forum=self.request.monitor['anno']) | (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.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)
             self.threads.append(thread)
-        for thread in self.request.acl.threads.filter_threads(self.request, self.forum, Thread.objects.filter(forum=self.forum).filter(weight__lt=2)).order_by('-weight', '-last'):
+        for thread in queryset_threads:
             self.threads.append(thread)
             self.threads.append(thread)
         if self.request.settings.threads_per_page < self.count:
         if self.request.settings.threads_per_page < self.count:
             self.threads = self.threads[self.pagination['start']:self.pagination['stop']]
             self.threads = self.threads[self.pagination['start']:self.pagination['stop']]

+ 3 - 1
static/sora/css/sora.css

@@ -847,6 +847,7 @@ textarea{resize:vertical;}
 .form-avatar-select .form-button:hover img{border:1px solid #0088cc;border:1px solid #0088cc;-webkit-box-shadow:0 1px 3px #0088cc;-moz-box-shadow:0 1px 3px #0088cc;box-shadow:0 1px 3px #0088cc;}
 .form-avatar-select .form-button:hover img{border:1px solid #0088cc;border:1px solid #0088cc;-webkit-box-shadow:0 1px 3px #0088cc;-moz-box-shadow:0 1px 3px #0088cc;box-shadow:0 1px 3px #0088cc;}
 .form-avatar-select hr{margin-top:16px;}
 .form-avatar-select hr{margin-top:16px;}
 .table-footer{background:#e8e8e8;border-top:1px solid #cfcfcf;-webkit-border-radius:0px 0px 3px 3px;-moz-border-radius:0px 0px 3px 3px;border-radius:0px 0px 3px 3px;margin-top:-20px;margin-bottom:20px;overflow:auto;padding:0px 12px;}.table-footer .form-inline{margin:0px;padding:6px 0px;}
 .table-footer{background:#e8e8e8;border-top:1px solid #cfcfcf;-webkit-border-radius:0px 0px 3px 3px;-moz-border-radius:0px 0px 3px 3px;border-radius:0px 0px 3px 3px;margin-top:-20px;margin-bottom:20px;overflow:auto;padding:0px 12px;}.table-footer .form-inline{margin:0px;padding:6px 0px;}
+.table td{vertical-align:middle;}
 td.check-cell,th.check-cell{width:32px;}
 td.check-cell,th.check-cell{width:32px;}
 td .checkbox,th .checkbox{margin-bottom:0px;position:relative;bottom:1px;}td .checkbox input,th .checkbox input{position:relative;left:9px;}
 td .checkbox,th .checkbox{margin-bottom:0px;position:relative;bottom:1px;}td .checkbox input,th .checkbox input{position:relative;left:9px;}
 td.lead-cell{color:#555555;font-weight:bold;}
 td.lead-cell{color:#555555;font-weight:bold;}
@@ -888,7 +889,7 @@ td.lead-cell{color:#555555;font-weight:bold;}
 .avatar-big{border-radius:3px;width:125px;height:125px;}
 .avatar-big{border-radius:3px;width:125px;height:125px;}
 .avatar-normal{border-radius:3px;width:64px;height:64px;}
 .avatar-normal{border-radius:3px;width:64px;height:64px;}
 .avatar-small{border-radius:3px;width:28px;height:28px;}
 .avatar-small{border-radius:3px;width:28px;height:28px;}
-.avatar-tiny{border-radius:3px;width:16px;height:16px;}
+.avatar-tiny{border-radius:3px;margin:-8px 0px;width:24px;height:24px;position:relative;bottom:1px;}
 .navbar .avatar-small{margin:-10px 0px;position:relative;bottom:2px;}
 .navbar .avatar-small{margin:-10px 0px;position:relative;bottom:2px;}
 .page-header .avatar,.page-header .avatar-big{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
 .page-header .avatar,.page-header .avatar-big{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
 .page-header h1 .avatar{width:46px;height:46px;}
 .page-header h1 .avatar{width:46px;height:46px;}
@@ -967,6 +968,7 @@ td.lead-cell{color:#555555;font-weight:bold;}
 .threads-list .jump:hover.jump-last{background-color:#049cdb;}
 .threads-list .jump:hover.jump-last{background-color:#049cdb;}
 .threads-list .jump:hover i{background-image:url("../img/glyphicons-halflings-white.png");}
 .threads-list .jump:hover i{background-image:url("../img/glyphicons-halflings-white.png");}
 .threads-list .thread-stat{text-align:right;}
 .threads-list .thread-stat{text-align:right;}
+.threads-list .thread-author,.threads-list .thread-poster{font-weight:bold;}.threads-list .thread-author a,.threads-list .thread-poster a{color:#333333;}
 .threads-list .thread-closed{background-color:#9d261d;}
 .threads-list .thread-closed{background-color:#9d261d;}
 .threads-list .thread-new{background-color:#0088cc;}
 .threads-list .thread-new{background-color:#0088cc;}
 .threads-list .thread-flags{float:right;margin:0px;padding:0px;}.threads-list .thread-flags li{float:right;margin:0px;margin-left:6px;padding:0px;}
 .threads-list .thread-flags{float:right;margin:0px;padding:0px;}.threads-list .thread-flags li{float:right;margin:0px;margin-left:6px;padding:0px;}

+ 5 - 2
static/sora/css/sora/avatars.less

@@ -20,8 +20,11 @@
 
 
 .avatar-tiny {
 .avatar-tiny {
   border-radius: 3px;
   border-radius: 3px;
-  width: 16px;
-  height: 16px;
+  margin: -8px 0px;
+  width: 24px;
+  height: 24px;
+  position: relative;
+  bottom: 1px;
 }
 }
 
 
 // Handle small avatar within different places
 // Handle small avatar within different places

+ 7 - 0
static/sora/css/sora/tables.less

@@ -15,6 +15,13 @@
   }
   }
 }
 }
 
 
+// Vertically centered table
+.table {
+  td {
+    vertical-align: middle;
+  }
+}
+
 // Checkbox cell
 // Checkbox cell
 td, th {
 td, th {
   &.check-cell {
   &.check-cell {

+ 8 - 0
static/sora/css/sora/threads.less

@@ -46,6 +46,14 @@
     text-align: right;
     text-align: right;
   }
   }
   
   
+  .thread-author, .thread-poster {
+    font-weight: bold;
+        
+    a {
+      color: @textColor;
+    }
+  }
+  
   .thread-closed {
   .thread-closed {
     background-color: @red; 
     background-color: @red; 
   }
   }

+ 6 - 1
templates/sora/macros.html

@@ -4,7 +4,12 @@
 {% if title %}{{ title }}{% if page > 1 %} | {% trans page=page %}Page {{ page }}{% endtrans %}{% endif %} | {% if parent %}{{ parent }} | {% endif %}{% endif %}{{ settings.board_name }}
 {% if title %}{{ title }}{% if page > 1 %} | {% trans page=page %}Page {{ page }}{% endtrans %}{% endif %} | {% if parent %}{{ parent }} | {% endif %}{% endif %}{{ settings.board_name }}
 {%- endmacro %}
 {%- endmacro %}
 
 
-{# Messages list marco #}
+{# Guest avatar #}
+{% macro avatar_guest() -%}
+{{ STATIC_URL }}avatars/avatar_guest.jpg
+{%- endmacro %}
+
+{# Messages list macro #}
 {% macro messages_list(messages) %}{% if messages %}<div class="alerts-list">{% for message in messages %}
 {% macro messages_list(messages) %}{% if messages %}<div class="alerts-list">{% for message in messages %}
   {{ draw_message(message) }}
   {{ draw_message(message) }}
 {% endfor %}</div>{% endif %}
 {% endfor %}</div>{% endif %}

+ 2 - 2
templates/sora/threads/list.html

@@ -71,9 +71,9 @@
           {% if thread.deleted %}<li><span class="tooltip-top" title="{% trans %}This thread has been deleted.{% endtrans %}"><i class="icon-remove"></i></span></li>{% endif %}
           {% if thread.deleted %}<li><span class="tooltip-top" title="{% trans %}This thread has been deleted.{% endtrans %}"><i class="icon-remove"></i></span></li>{% endif %}
         </ul>
         </ul>
       </td>
       </td>
-      <td class="span2">{% if thread.start_poster_id %}<a href="{% url 'user' user=thread.start_poster_id, username=thread.start_poster_slug %}" class="tooltip-top" title="{{ thread.start|reltimesince }}">{{ thread.start_poster_name }}</a>{% else %}<em class="tooltip-top muted" title="{{ thread.start|reltimesince }}">{{ thread.start_poster_name }}</em>{% endif %}</td>
+      <td class="span2 thread-author"><span class="tooltip-top" title="{{ thread.start|reltimesince }}">{% if thread.start_poster_id %}{% if settings.avatars_on_threads_list %}<img src="{{ thread.start_poster.get_avatar() }}" alt="" class="avatar-tiny"> {% endif %}<a href="{% url 'user' user=thread.start_poster_id, username=thread.start_poster_slug %}">{{ thread.start_poster_name }}</a>{% else %}{% if settings.avatars_on_threads_list %}<img src="{{ macros.avatar_guest() }}" alt="" class="avatar-tiny"> {% endif %}<em class="muted">{{ thread.start_poster_name }}</em>{% endif %}</span></td>
       <td class="span1 thread-stat">{{ thread.replies|intcomma }}</td>
       <td class="span1 thread-stat">{{ thread.replies|intcomma }}</td>
-      <td class="span2">{% if thread.last_poster_id %}<a href="{% url 'user' user=thread.last_poster_id, username=thread.last_poster_slug %}" class="tooltip-top" title="{{ thread.last|reltimesince }}">{{ thread.last_poster_name }}</a>{% else %}<em class="tooltip-top muted" title="{{ thread.last|reltimesince }}">{{ thread.last_poster_name }}</em>{% endif %}</td>
+      <td class="span2 thread-poster"><span class="tooltip-top"title="{{ thread.last|reltimesince }}">{% if thread.last_poster_id %}{% if settings.avatars_on_threads_list %}<img src="{{ thread.last_poster.get_avatar() }}" alt="" class="avatar-tiny"> {% endif %}<a href="{% url 'user' user=thread.last_poster_id, username=thread.last_poster_slug %}">{{ thread.last_poster_name }}</a>{% else %}{% if settings.avatars_on_threads_list %}<img src="{{ macros.avatar_guest() }}" alt="" class="avatar-tiny"> {% endif %}<em class="muted">{{ thread.last_poster_name }}</em>{% endif %}</span></td>
       {% if user.is_authenticated() and list_form %}
       {% if user.is_authenticated() and list_form %}
       <td class="check-cell">{% if thread.forum_id == forum.pk %}<label class="checkbox"><input form="threads_form" name="{{ list_form['list_items']['html_name'] }}" type="checkbox" class="checkbox-member" value="{{ thread.pk }}"{% if list_form['list_items']['has_value'] and ('' ~ thread.pk) in list_form['list_items']['value'] %} checked="checked"{% endif %}></label>{% else %}&nbsp;{% endif %}</td>
       <td class="check-cell">{% if thread.forum_id == forum.pk %}<label class="checkbox"><input form="threads_form" name="{{ list_form['list_items']['html_name'] }}" type="checkbox" class="checkbox-member" value="{{ thread.pk }}"{% if list_form['list_items']['has_value'] and ('' ~ thread.pk) in list_form['list_items']['value'] %} checked="checked"{% endif %}></label>{% else %}&nbsp;{% endif %}</td>
       {% endif %}
       {% endif %}