Browse Source

WIP: Forums list template

Rafał Pitoń 10 years ago
parent
commit
1f40918f82

+ 2 - 2
misago/acl/panels.py

@@ -20,9 +20,9 @@ class MisagoACLPanel(Panel):
             return _("Anonymous user")
 
     def process_response(self, request, response):
-        if  hasattr(request.user, 'acl'):
+        try:
             misago_acl = request.user.acl
-        else:
+        except AttributeError:
             misago_acl = {}
 
         self.record_stats({

+ 4 - 1
misago/core/views.py

@@ -1,9 +1,12 @@
 from django.shortcuts import render
 
+from misago.forums.lists import get_forums_list
+
 from misago.users.online.ranks import get_ranks_online
 
 
 def forum_index(request):
     return render(request, 'misago/index.html', {
-        'ranks_online': get_ranks_online()
+        'categories': get_forums_list(request.user),
+        'ranks_online': get_ranks_online(),
     })

+ 30 - 0
misago/forums/lists.py

@@ -0,0 +1,30 @@
+from misago.forums.models import Forum
+
+
+def get_forums_list(user, parent=None):
+    if parent:
+        queryset = parent.get_descendants().order_by('lft')
+    else:
+        queryset = Forum.objects.all_forums()
+    queryset_with_acl = queryset.filter(id__in=user.acl['visible_forums'])
+
+    forums_dict = {}
+    forums_list = []
+
+    parent_level = parent.level + 1 if parent else 1
+
+    for forum in queryset_with_acl:
+        forum.is_read = True
+        forum.subforums = []
+        forums_dict[forum.pk] = forum
+        forums_list.append(forum)
+
+        if forum.level > 1:
+            forums_dict[forum.parent_id].subforums.append(forum)
+
+    flat_list = []
+    for forum in forums_list:
+        has_content = (forum.role != "category" or forum.subforums)
+        if forum.level == parent_level and has_content:
+            flat_list.append(forum)
+    return flat_list

+ 6 - 0
misago/forums/models.py

@@ -1,3 +1,5 @@
+from urlparse import urlparse
+
 from django.db import models
 from django.dispatch import receiver
 from django.utils.translation import ugettext_lazy as _
@@ -73,6 +75,10 @@ class Forum(MPTTModel):
         acl_version.invalidate()
         return super(Forum, self).delete(*args, **kwargs)
 
+    @property
+    def redirect_host(self):
+        return urlparse(self.redirect_url).hostname
+
     def set_name(self, name):
         self.name = name
         self.slug = slugify(name)

+ 64 - 2
misago/forums/permissions.py

@@ -1,6 +1,10 @@
 from django.utils.translation import ugettext_lazy as _
+
+
+from misago.acl import algebra
 from misago.core import forms
-from misago.forums.models import ForumRole
+
+from misago.forums.models import Forum, RoleForumACL, ForumRole
 
 
 """
@@ -23,4 +27,62 @@ def change_permissions_form(role):
 ACL Builder
 """
 def build_acl(acl, roles, key_name):
-    return acl
+    new_acl = {
+        'visible_forums': [],
+        'forums': {},
+    }
+    new_acl.update(acl)
+
+    forums_roles = get_forums_roles(roles)
+
+    for forum in Forum.objects.all_forums():
+        build_forum_acl(new_acl, forum, forums_roles, key_name)
+
+    return new_acl
+
+
+def get_forums_roles(roles):
+    queryset = RoleForumACL.objects.filter(role__in=roles)
+    queryset = queryset.select_related('forum_role')
+
+    forums_roles = {}
+    for acl_relation in queryset.iterator():
+        forum_role = acl_relation.forum_role
+        forums_roles.setdefault(acl_relation.forum_id, []).append(forum_role)
+    return forums_roles
+
+
+def build_forum_acl(acl, forum, forums_roles, key_name):
+    if forum.level > 1:
+        if forum.parent_id not in acl['visible_forums']:
+            # dont bother with child forums of invisible parents
+            return
+        elif not acl['forums'][forum.parent_id]['can_browse']:
+            # parent's visible, but its contents aint
+            return
+
+    forum_roles = forums_roles.get(forum.pk, [])
+
+    final_acl = {
+        'can_see': 0,
+        'can_browse': 0,
+    }
+
+    algebra.sum_acls(
+        final_acl, roles=forum_roles, key=key_name,
+        can_see=algebra.greater,
+        can_browse=algebra.greater)
+
+    if final_acl['can_see']:
+        acl['visible_forums'].append(forum.pk)
+        acl['forums'][forum.pk] = final_acl
+
+
+"""
+ACL's for targets
+"""
+
+
+"""
+ACL's for tests
+"""

+ 160 - 0
misago/static/misago/css/misago/forums.less

@@ -0,0 +1,160 @@
+//
+// Forums lists
+// --------------------------------------------------
+
+
+// Panel header
+//
+//==
+.forums-list {
+  .panel-forums {
+    .panel-heading {
+      border: 1px solid @panel-default-border;
+      margin: -1px;
+      margin-bottom: 0px;
+      padding-top: @padding-base-vertical;
+      padding-bottom: @padding-base-vertical;
+
+      h3 {
+        font-size: @font-size-small;
+        font-weight: bold;
+      }
+    }
+  }
+}
+
+
+// Panel forums
+//
+//==
+.forums-list {
+  .panel-forums {
+    .list-group {
+      .forum-icon {
+        padding-right: @line-height-computed;
+
+        color: @state-default;
+        font-size: @font-size-large * 1.3;
+
+        &.new {
+          color: @state-active;
+        }
+
+        &.fa-link {
+          position: relative;
+          top: 3px;
+
+          color: @brand-success;
+        }
+      }
+
+      .forum-name {
+        font-size: @font-size-large;
+      }
+
+      .dropdown {
+        .btn {
+          .box-shadow(none);
+          position: static;
+          margin: 0px;
+          margin-top: -2px;
+        }
+
+        .dropdown-menu {
+          a {
+            .forum-icon {
+              padding-right: 0px;
+              position: relative;
+              bottom: 2px;
+
+              font-size: @font-size-base;
+            }
+
+            &:hover, &:active, &:focus {
+              .fa {
+                color: @dropdown-bg;
+              }
+            }
+          }
+        }
+      }
+
+      footer {
+        border-left: 1px dotted @panel-inner-border;
+        float: right;
+        margin-top: -4px;
+        margin-left: @line-height-computed / 2;
+        padding-left: @line-height-computed / 2;
+        width: 33%;
+
+        &>em.text-muted {
+          display: block;
+          padding: ((@font-size-base / 2) + 1px) 0px;
+
+          font-size: @font-size-small;
+        }
+
+        &>a {
+          display: block;
+          overflow: hidden;
+
+          font-size: @font-size-small;
+          font-weight: bold;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+        }
+
+        .text-muted {
+          overflow: hidden;
+
+          font-size: @font-size-small - 1px;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+
+          .item-title {
+            font-weight: normal;
+          }
+        }
+      }
+    }
+  }
+}
+
+
+// Forum description tooltip
+//
+//==
+.tooltip.forum-description {
+  .tooltip-inner {
+    padding: @padding-base-vertical @padding-base-horizontal;
+
+    max-width: 300px;
+    text-align: left;
+
+    p {
+      margin-top: 0px;
+
+      font-size: @font-size-base;
+    }
+
+    ul {
+      margin: 0px;
+      overflow: auto;
+
+      li {
+        float: left;
+        margin-right: @line-height-computed;
+
+        color: darken(#fff, 15%);
+
+        strong {
+          color: #fff;
+        }
+
+        &:last-child {
+          margin-right: 0px;
+        }
+      }
+    }
+  }
+}

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

@@ -22,6 +22,7 @@
 @import "footer.less";
 
 @import "forms.less";
+@import "forums.less";
 @import "notifications.less";
 @import "userslists.less";
 

+ 4 - 0
misago/static/misago/css/misago/panels.less

@@ -8,6 +8,10 @@
 //==
 .panel {
   box-shadow: none;
+
+  &.panel-shadow {
+    box-shadow: 0px 0px 0px 3px @panel-shadow;
+  }
 }
 
 

+ 1 - 0
misago/static/misago/css/misago/variables.less

@@ -280,6 +280,7 @@
 //##
 
 @panel-bg:                    #fff;
+@panel-shadow:                darken(@body-bg, 5%);
 @panel-body-padding:          15px;
 
 @panel-default-border:        darken(@body-bg, 15%);

+ 5 - 5
misago/static/misago/js/misago-tooltips.js

@@ -1,10 +1,10 @@
 // Register tooltips
 $(function() {
   $.misago_dom().change(function() {
-    $('.tooltip-top').tooltip({placement: 'top', container: 'body'});
-    $('.tooltip-bottom').tooltip({placement: 'bottom', container: 'body'});
-    $('.tooltip-left').tooltip({placement: 'left', container: 'body'});
-    $('.tooltip-right').tooltip({placement: 'right', container: 'body'});
+    $('.tooltip-top').tooltip({placement: 'top'});
+    $('.tooltip-bottom').tooltip({placement: 'bottom'});
+    $('.tooltip-left').tooltip({placement: 'left'});
+    $('.tooltip-right').tooltip({placement: 'right'});
   });
 });
 
@@ -22,6 +22,6 @@ function misago_tooltip(element) {
   }
 
   if (placement) {
-    element.tooltip({placement: placement, container: 'body'})
+    element.tooltip({placement: placement})
   }
 }

+ 13 - 0
misago/templates/misago/forums/categories.html

@@ -0,0 +1,13 @@
+{% load i18n %}
+<div class="forums-list">
+{% for category in categories %}
+  {% if category.subforums %}
+  <div class="panel panel-default panel-shadow panel-forums {{ category.css_class }}">
+    <div class="panel-heading">
+      <h3 class="panel-title">{{ category.name }}</h3>
+    </div>
+    {% include "misago/forums/forums.html" %}
+  </div>
+  {% endif %}
+{% endfor %}
+</div>

+ 78 - 0
misago/templates/misago/forums/forums.html

@@ -0,0 +1,78 @@
+{% load humanize i18n misago_capture %}
+<ul class="list-group">
+  {% for forum in category.subforums %}
+  <li class="list-group-item">
+    {% if forum.role == 'redirect' %}
+    <span class="forum-icon fa fa-link fa-fw"></span>
+    {% else %}
+    <span class="forum-icon fa fa-comment{% if forum.is_read %}-o{% else %} new{% endif %} fa-fw"></span>
+    {% endif %}
+
+    <a href="/" class="item-title forum-name">{{ forum.name }}</a>
+
+    <div class="sr-only forum-description">
+      {% if forum.description %}
+      <p>{{ forum.description }}</p>
+      {% endif %}
+      <ul class="list-unstyled">
+        {% if forum.role == 'redirect' %}
+        <li>
+          {% trans "Clicks:" %} <strong>{{ forum.redirects_count|intcomma }}</strong>
+        </li>
+        {% else %}
+        <li>
+          {% trans "Posts:" %} <strong>{{ forum.posts|intcomma }}</strong>
+        </li>
+        <li>
+          {% trans "Threads:" %} <strong>{{ forum.threads|intcomma }}</strong>
+        </li>
+        {% endif %}
+      </ul>
+    </div>
+
+    <footer>
+      {% if forum.role == 'redirect' %}
+      <a href="#" class="item-title">{{ forum.redirect_host }}</a>
+      <div class="text-muted">
+        {% capture as clicks %}<strong>{{ forum.redirects_count|intcomma }}</strong>{% endcapture %}
+        {% blocktrans trimmed with clicks=clicks|safe count counter=forum.redirects_count %}
+        {{ clicks }} click
+        {% plural %}
+        {{ clicks }} clicks
+        {% endblocktrans %}
+      </div>
+      {% elif 0 %}
+      <a href="#" class="item-title">Lorem ipsum dolor met sit amet</a>
+      <div class="text-muted">
+        <a href="#" class="item-title">somebody</a>, <abbr>32 minutes ago</abbr>
+      </div>
+      {% else %}
+      <em class="text-muted">Some message</em>
+      {% endif %}
+    </footer>
+
+    {% if forum.subforums %}
+    <div class="dropdown pull-right">
+      <button class="btn btn-default btn-sm dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown">
+        <span class="sr-only">{% trans "Subforums" %}</span>
+        <span class="fa fa-reorder fa-lg"></span>
+      </button>
+      <ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
+        {% for subforum in forum.subforums %}
+        <li role="presentation">
+          <a role="menuitem" tabindex="-1" href="#">
+            {% if subforum.role == 'redirect' %}
+            <span class="forum-icon fa fa-link fa-fw"></span>
+            {% else %}
+            <span class="forum-icon fa fa-comment{% if subforum.is_read %}-o{% else %} new{% endif %} fa-fw "></span>
+            {% endif %}
+            {{ subforum.name }}
+          </a>
+        </li>
+        {% endfor %}
+      </ul>
+    </div>
+    {% endif %}
+  </li>
+  {% endfor %}
+</ul>

+ 16 - 0
misago/templates/misago/forums/js.html

@@ -0,0 +1,16 @@
+<script lang="JavaScript">
+$(function() {
+  $(".forum-description").each(function() {
+    var $forum = $(this).parents('li');
+    var $forum_title = $forum.find('.forum-name');
+
+    $forum_title.tooltip({
+      container: 'body',
+      html: true,
+      placement: 'right',
+      template: '<div class="tooltip forum-description" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
+      title: $(this).html()
+    });
+  });
+});
+</script>

+ 0 - 0
misago/templates/misago/forums/subforums.html


+ 14 - 1
misago/templates/misago/index.html

@@ -1,4 +1,5 @@
 {% extends "misago/base.html" %}
+{% load i18n %}
 
 
 {% block title %}
@@ -20,7 +21,13 @@
   <div class="row">
     <div class="col-md-8">
 
-      Hello world, I'm placeholder index template!
+      {% if categories %}
+        {% include "misago/forums/categories.html" %}
+      {% else %}
+      <p class="lead">
+        {% trans "No forums are set or you don't have permission to see them." %}
+      </p>
+      {% endif %}
 
     </div>
     <div class="col-md-4">
@@ -33,3 +40,9 @@
   </div>
 </div>
 {% endblock content %}
+
+
+{% block javascripts %}
+{{ block.super }}
+{% include "misago/forums/js.html" %}
+{% endblock javascripts %}