Browse Source

non-js private threads list

Rafał Pitoń 8 years ago
parent
commit
4dd09dcad6

+ 5 - 5
misago/templates/misago/threadslist/category.html

@@ -5,14 +5,14 @@
 {% block title %}
 {% if list_name %}
   {% if paginator.page > 1 %}
-    {{ list_name }} ({% blocktrans with page=paginator.page %}page: {{ page }}{% endblocktrans %}) | {{ category.name }} | {{ block.super }}
+    {{ list_name }} ({% blocktrans with page=paginator.page %}page: {{ page }}{% endblocktrans %}) | {{ category }} | {{ block.super }}
   {% else %}
-    {{ list_name }} | {{ category.name }} | {{ block.super }}
+    {{ list_name }} | {{ category }} | {{ block.super }}
   {% endif %}
 {% elif paginator.page > 1 %}
-  {{ category.name }} ({% blocktrans with page=paginator.page %}page: {{ page }}{% endblocktrans %}) | {{ block.super }}
+  {{ category }} ({% blocktrans with page=paginator.page %}page: {{ page }}{% endblocktrans %}) | {{ block.super }}
 {% else %}
-  {{ category.name }} | {{ block.super }}
+  {{ category }} | {{ block.super }}
 {% endif %}
 {% endblock title %}
 
@@ -41,7 +41,7 @@
     </a>
 
     <h1 class="pull-left">
-      {{ category.name }}
+      {{ category }}
     </h1>
   </div>
   {% if user.is_authenticated %}

+ 69 - 0
misago/templates/misago/threadslist/private_threads.html

@@ -0,0 +1,69 @@
+{% extends "misago/threadslist/base.html" %}
+{% load i18n misago_shorthands misago_stringutils %}
+
+
+{% block title %}
+{% if list_name %}
+  {% if paginator.page > 1 %}
+    {{ list_name }} ({% blocktrans with page=paginator.page %}page: {{ page }}{% endblocktrans %}) | {{ category }} | {{ block.super }}
+  {% else %}
+    {{ list_name }} | {{ category }} | {{ block.super }}
+  {% endif %}
+{% elif paginator.page > 1 %}
+  {{ category }} ({% blocktrans with page=paginator.page %}page: {{ page }}{% endblocktrans %}) | {{ block.super }}
+{% else %}
+  {{ category }} | {{ block.super }}
+{% endif %}
+{% endblock title %}
+
+
+{% block extra-css %}
+page-private-threads
+{% endblock extra-css %}
+
+
+{% block page-header %}
+<div class="page-header tabbed">
+  <div class="container">
+    <a href="{{ category.parent.get_absolute_url }}{% if list_type != 'all' %}{{ list_type }}/{% endif %}" class="btn btn-default btn-aligned btn-icon btn-go-back pull-left">
+      <span class="material-icon">
+        keyboard_arrow_left
+      </span>
+    </a>
+
+    <h1 class="pull-left">
+      {{ category }}
+    </h1>
+  </div>
+  {% if user.is_authenticated %}
+    {% include "misago/threadslist/tabs.html" with hide_unapproved=True %}
+  {% endif %}
+</div>
+{% endblock page-header %}
+
+
+{% block list-container %}
+  <div class="category-description">
+    <div class="page-lead">
+      <p>{% trans "Private threads are threads which only those that started them and those they have invited may see and participate in." %}</p>
+    </div>
+  </div>
+
+  {{ block.super }}
+{% endblock list-container%}
+
+
+{% block thread %}
+  {% include "misago/threadslist/thread.html" with hide_path=True %}
+{% endblock thread %}
+
+
+{% block list-empty-message %}
+  {% if list_type == 'all' %}
+    <p class="lead">
+      {% trans "You aren't participating in any private threads." %}
+    </p>
+  {% else %}
+    {% trans "No threads matching specified criteria were found." %}
+  {% endif %}
+{% endblock list-empty-message %}

+ 1 - 1
misago/templates/misago/threadslist/tabs.html

@@ -32,7 +32,7 @@
           <span class="hidden-md hidden-lg">{% trans "Subscribed threads" %}</span>
         </a>
       </li>
-      {% if user.acl.can_see_unapproved_content_lists %}
+      {% if user.acl.can_see_unapproved_content_lists and not hide_unapproved %}
         <li{% if list_type == 'unapproved' %} class="active"{% endif %}>
           <a href="{{ category.get_absolute_url }}unapproved/">
             <span class="hidden-xs hidden-sm">{% trans "Unapproved" %}</span>

+ 2 - 2
misago/templates/misago/threadslist/thread.html

@@ -132,7 +132,7 @@
         </span>
       </li>
       {% endif %}
-      {% if thread.top_category %}
+      {% if thread.top_category and not hide_path %}
       <li class="thread-path">
         <a href="{{ thread.top_category.get_absolute_url }}{% if list_type != 'all' %}{{ list_type }}/{% endif %}" class="thread-category{% if thread.top_category.css_class %} thread-category-{{ thread.top_category.css_class }}{% endif %}">
           {{ thread.top_category.name }}
@@ -173,7 +173,7 @@
       </li>
     </ul>
     <ul class="thread-details-compact list-inline">
-      {% if thread.top_category %}
+      {% if thread.top_category and not hide_path %}
         {% if thread.top_category != thread.category %}
         <li class="thread-path">
           <a href="{{ thread.category.get_absolute_url }}{% if list_type != 'all' %}{{ list_type }}/{% endif %}" class="thread-category{% if thread.category.css_class %} thread-category-{{ thread.category.css_class }}{% endif %}">

+ 0 - 10
misago/threads/api/rest_permissions.py

@@ -1,10 +0,0 @@
-from rest_framework.permissions import BasePermission
-
-from ..permissions.privatethreads import allow_use_private_threads
-
-
-class PrivateThreadsPermission(BasePermission):
-    def has_permission(self, request, view):
-        allow_use_private_threads(request.user)
-
-        return True

+ 0 - 3
misago/threads/api/threads.py

@@ -13,7 +13,6 @@ from ..models import Post, Thread
 from ..moderation import threads as moderation
 from ..viewmodels import ForumThread
 from .postingendpoint import PostingEndpoint
-from .rest_permissions import PrivateThreadsPermission
 from .threadendpoints.editor import thread_start_editor
 from .threadendpoints.list import threads_list_endpoint, private_threads_list_endpoint
 from .threadendpoints.merge import thread_merge_endpoint, threads_merge_endpoint
@@ -110,8 +109,6 @@ class ThreadViewSet(ViewSet):
 
 
 class PrivateThreadViewSet(ViewSet):
-    permission_classes = (PrivateThreadsPermission,)
-
     def list(self, request):
         return private_threads_list_endpoint(request)
 

+ 0 - 2
misago/threads/permissions/privatethreads.py

@@ -129,8 +129,6 @@ def build_acl(acl, roles, key_name):
             'can_protect_posts': 1,
             'can_merge_posts': 1,
             'can_see_reports': 1,
-            'can_see_reports': 1,
-            'can_approve_content': 1,
             'can_hide_events': 2,
         })
 

+ 55 - 1
misago/threads/tests/test_privatethreadslists.py

@@ -1,4 +1,4 @@
-from django.core.urlresolvers import reverse
+from django.urls import reverse
 
 from misago.acl.testutils import override_acl
 
@@ -67,3 +67,57 @@ class PrivateThreadsApiTests(PrivateThreadsApiTestCase):
         self.assertEqual(response_json['count'], 2)
         self.assertEqual(response_json['results'][0]['id'], reported.id)
         self.assertEqual(response_json['results'][1]['id'], visible.id)
+
+
+class PrivateThreadsListTests(PrivateThreadsApiTestCase):
+    def setUp(self):
+        super(PrivateThreadsListTests, self).setUp()
+
+        self.test_link = reverse('misago:private-threads')
+
+    def test_unauthenticated(self):
+        """view requires user to sign in and be able to access it"""
+        self.logout_user()
+
+        response = self.client.get(self.test_link)
+        self.assertContains(response, "sign in to use private threads", status_code=403)
+
+    def test_no_permission(self):
+        """view requires user to have permission to be able to access it"""
+        override_acl(self.user, {
+            'can_use_private_threads': 0
+        })
+
+        response = self.client.get(self.test_link)
+        self.assertContains(response, "use private threads", status_code=403)
+
+    def test_empty_list(self):
+        """view has no showstoppers on returning empty list"""
+        response = self.client.get(self.test_link)
+        self.assertEqual(response.status_code, 200)
+        self.assertContains(response, "empty-message")
+
+    def test_thread_visibility(self):
+        """only participated threads are returned by private threads view"""
+        visible = testutils.post_thread(category=self.category, poster=self.user)
+        hidden = testutils.post_thread(category=self.category, poster=self.user)
+        reported = testutils.post_thread(category=self.category, poster=self.user)
+
+        add_owner(visible, self.user)
+
+        reported.has_reported_posts = True
+        reported.save()
+
+        response = self.client.get(self.test_link)
+        self.assertEqual(response.status_code, 200)
+        self.assertContains(response, visible.get_absolute_url())
+
+        # threads with reported posts will also show to moderators
+        override_acl(self.user, {
+            'can_moderate_private_threads': 1
+        })
+
+        response = self.client.get(self.test_link)
+        self.assertEqual(response.status_code, 200)
+        self.assertContains(response, reported.get_absolute_url())
+        self.assertContains(response, visible.get_absolute_url())

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

@@ -66,13 +66,12 @@ urlpatterns += threads_list_patterns('category', CategoryThreads, (
 ))
 
 
-urlpatterns += threads_list_patterns('private-threads', CategoryThreads, (
+urlpatterns += threads_list_patterns('private-threads', PrivateThreads, (
     r'^private-threads/$',
     r'^private-threads/my/$',
     r'^private-threads/new/$',
     r'^private-threads/unread/$',
     r'^private-threads/subscribed/$',
-    r'^private-threads/unapproved/$',
 ))
 
 

+ 7 - 0
misago/threads/viewmodels/category.py

@@ -7,6 +7,8 @@ from misago.categories.serializers import BasicCategorySerializer
 from misago.core.viewmodel import ViewModel as BaseViewModel
 from misago.core.shortcuts import validate_slug
 
+from ..permissions import allow_use_private_threads
+
 
 __all__ = ['ThreadsRootCategory', 'ThreadsCategory', 'PrivateThreadsCategory']
 
@@ -82,3 +84,8 @@ class ThreadsCategory(ThreadsRootCategory):
 class PrivateThreadsCategory(ViewModel):
     def get_categories(self, request):
         return [Category.objects.private_threads()]
+
+    def get_category(self, request, categories, **kwargs):
+        allow_use_private_threads(request.user)
+
+        return categories[0]