Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature 217 view issue threads without logging in #1505

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
4 changes: 2 additions & 2 deletions project/core/templates/about.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{% load static %}
{% load i18n %}
{% block extra_css %}
<link type="text/css" rel="stylesheet/less" href="{% static " less/about.less" %}" />
<link type="text/css" rel="stylesheet/less" href="{% static "less/about.less" %}" />
{% endblock extra_css %}

{% block page_title %}{% trans "About Us" %}{% endblock page_title %}
Expand Down Expand Up @@ -186,7 +186,7 @@ <h3 class="title">{% trans "Sponsors" %} </h3>

{% include "static_nav.html" %}
<div id="about"></div>
<script src="{% static " js/static/about_view.js" %}" type="text/javascript"></script>
<script src="{% static "js/static/about_view.js" %}" type="text/javascript"></script>
<script type="text/javascript">
var aboutView = new cw.AboutView();
</script>
Expand Down
2 changes: 1 addition & 1 deletion project/core/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@

{% include "global_nav.html" %}

{% include "static_footer.html" %}
{%block content%}{%endblock content%}
{% include "static_footer.html" %}
{% block extra_js %}{% endblock extra_js %}

</body>
Expand Down
4 changes: 2 additions & 2 deletions project/core/templates/how_it_works.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<!-- How it Works -->
{% block extra_css %}
<link type="text/css" rel="stylesheet/less" href="{% static " less/how_it_works.less" %}" />
<link type="text/css" rel="stylesheet/less" href="{% static "less/how_it_works.less" %}" />
ashfaq1934 marked this conversation as resolved.
Show resolved Hide resolved
{% endblock extra_css %}
{%block content%}
<script id="howitworks-template" type="text/template">
Expand Down Expand Up @@ -40,7 +40,7 @@ <h4 class="dark-purple">{% trans "Still not sure about something in CiviWiki?" %

{% include "static_nav.html" %}
<div id="howitworks"></div>
<script src="{% static " js/static/how_it_works_view.js" %}" type="text/javascript"></script>
<script src="{% static "js/static/how_it_works_view.js" %}" type="text/javascript"></script>
<script type="text/javascript">
var howitworksView = new cw.HowItWorksView();
</script>
Expand Down
1 change: 1 addition & 0 deletions project/core/templates/landing.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ <h1>
<a href="/howitworks/" class="nav-items">How OpenCiviWiki Works</a>
<a href="/about/" class="nav-items">About Us</a>
<a href="/support_us/" class="nav-items">Support Us</a>
<a href="{% url 'feeds' %}" class="nav-items">Visit The Discussion</a>
<a href="/login/" class="">
<button class="ripple">Login/SignUp</button>
</a>
Expand Down
7 changes: 3 additions & 4 deletions project/core/templates/static/less/feed.less
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
@import 'base';

html {
overflow: hidden;
}
body {
background-color: #f7f6f8;

Expand Down Expand Up @@ -163,6 +159,9 @@ body {
.col {
padding-top: 8px;
}
.stats .col {
padding-top: unset;
}
}
.issue-item {
box-shadow: 0 1px 0px 1px rgba(0, 0, 0, 0.02);
Expand Down
4 changes: 4 additions & 0 deletions project/core/templates/static/less/utils.less
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,10 @@

@box-shadow-z1: 0 2px 2px 0 rgba(0,0,0,0.14), 0 1px 5px 0 rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.2);

.nowrap{
white-space: nowrap;
}

.dropdown-menu-wrapper{
display: block;
margin-top: -12px;
Expand Down
60 changes: 42 additions & 18 deletions project/threads/templates/threads/feed.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,16 @@
</nav>
<div class="content">
<div class="row">
<div class="col s12 m3 l2 push-l1">
<div class="col s2 offset-s1">
<div class="row center">
<div class="col s6 m12">
<div class="new-thread-wrapper center-block">
<div class="prompt">Can't find the issue that you're interested in?</div>
{% if user.is_authenticated %}
<button class="new-thread btn waves-effect modal-trigger"><i class="material-icons left">note_add</i>New Thread</button>
ashfaq1934 marked this conversation as resolved.
Show resolved Hide resolved
{% else %}
<a class="new-thread btn waves-effect modal-trigger" href="{% url 'accounts_login' %}"><i class="material-icons left">note_add</i>New Thread</a>
{% endif %}
</div>
</div>
<div class="col s6 m12">
Expand All @@ -56,35 +60,55 @@
</div>
<div class="divider"></div>
<div class="list">
{% for thread in trending_issues %}
<div class="list-item left-align"><a class="list-text" href="thread/{{thread.id}}">{{thread.title}}</a></div>
{% for thread in trending %}
<div class="list-item left-align"><a class="list-text" href="{% url 'thread-detail' thread.id %}">{{thread.title}}</a></div>
{% endfor %}
</div>
</div>
</div>
</div>

<div id="feed-list">
{% if threads %}
{% for thread in threads %}
<div>THREAD CARD PLACEHOLDER</div>
{% endfor %}
{% else %}
<div class="section no-state">
<div class="container">
<div class="section">
<div class="center title-lato grey-text">NO THREADS</div>
<div class="section center">
<div class="subtitle-lato grey-text section">Be the first to start a discussion in this category!</div>
<button class="new-thread btn waves-effect modal-trigger"><i class="material-icons left">note_add</i>New Thread</button>
</div>
</div>
</div>
{% if threads %}
<div class="col s8">
<ul>
{% for thread in threads %}
<li>
<div class="col">
<div class="card horizontal">
<div class="card-image col s2">
<a href="{% url 'thread-detail' thread.thread.id %}"><img class="responsive-img" src="{{ thread.thread.image }}"></a>
</div>
<div class="col s8">
<div>
<span class="card-title"><a href="{% url 'thread-detail' thread.thread.id %}">{{ thread.thread.title }}</a></span>
<p>{{ thread.thread.summary }}</p>
</div>
<div class="stats gray-text">
<div class="col center-align s2">
<span class="material-icons container">remove_red_eye</span>
<span class="nowrap">{{ thread.stats.num_views }} Views</span>
</div>
<div class="col center-align s2">
<span class="material-icons container">question_answer</span>
<span class="nowrap">{{ thread.stats.num_civis }} Civis</span>
</div>
<div class="col center-align s2">
<span class="material-icons container">emoji_objects</span>
<span class="nowrap">{{ thread.stats.num_solutions }} Solutions</span>
</div>
</div>
</div>
</div>
{% endif %}
</div>
</div>
</div>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
</div>
</div>
Expand Down
32 changes: 13 additions & 19 deletions project/threads/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import json

from categories.models import Category
from django.contrib.auth import get_user_model
from django.test import TestCase
from rest_framework.test import APIClient
from django.urls import reverse
from categories.models import Category
from rest_framework.test import APIClient
from threads.models import Civi, Thread


Expand Down Expand Up @@ -53,7 +54,7 @@ class ThreadViewSetTests(BaseTestCase):
"""A class to test ThreadViewSet"""

def setUp(self) -> None:
super(ThreadViewSetTests, self).setUp()
super().setUp()
self.client = APIClient()

def test_anonymous_user_can_list_threads(self):
Expand Down Expand Up @@ -111,41 +112,34 @@ class BaseViewTests(BaseTestCase):
"""A class to test base_view function"""

def setUp(self) -> None:
super(BaseViewTests, self).setUp()
super().setUp()
self.client.login(username=self.user.username, password="password123")
self.url = reverse("base")
self.response = self.client.get(self.url)

def test_anonymous_users_are_redirected_to_landing_page(self):
"""Whether unauthenticated users are redirected to the landing page"""

def test_landing_page(self):
self.client.logout()
self.response = self.client.get(self.url)
self.response = self.client.get(reverse("base"))
self.assertEqual(self.response.status_code, 200)
self.assertTemplateUsed(self.response, "base.html")
self.assertTemplateUsed(self.response, "landing.html")
self.assertTemplateUsed(self.response, "static_nav.html")
self.assertTemplateUsed(self.response, "static_footer.html")
self.assertContains(self.response, "Why CiviWiki?")
self.assertNotContains(self.response, "Wrong Content!")

def test_authenticated_users_are_redirected_to_feed_page(self):
"""Whether authenticated users are redirected to the feed page"""

def test_anonymous_users_can_access_feed(self):
"""Whether unauthenticated users can access feeds"""
self.client.logout()
self.response = self.client.get(reverse("feeds"))
self.assertEqual(self.response.status_code, 200)
self.assertTemplateUsed(self.response, "base.html")
self.assertTemplateUsed(self.response, "feed.html")
self.assertTemplateUsed(self.response, "global_nav.html")
self.assertTemplateUsed(self.response, "static_footer.html")
self.assertContains(self.response, "Trending Issues")
self.assertNotContains(self.response, "Wrong Content!")
self.assertContains(self.response, "New Thread")


class IssueThreadTests(BaseTestCase):
"""A class to test issue_thread function"""

def setUp(self) -> None:
super(IssueThreadTests, self).setUp()
super().setUp()
self.client.login(username=self.user.username, password="password123")

def test_nonexistent_threads_redirect_to_404_page(self):
Expand Down
2 changes: 1 addition & 1 deletion project/threads/urls/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from django.urls import path
from threads import views


urlpatterns = [
path("thread/<int:thread_id>/csv/", views.civi2csv, name="civi2csv"),
path("thread/<int:pk>/", views.ThreadDetailView.as_view(), name="thread-detail"),
Expand All @@ -10,5 +9,6 @@
path("howitworks/", views.HowItWorksView.as_view(), name="how-it-works"),
path("declaration/", views.DeclarationView.as_view(), name="declaration"),
path("create-group/", views.create_group, name="create-group"),
path("feeds/", views.feeds, name="feeds"),
path("", views.base_view, name="base"),
]
48 changes: 24 additions & 24 deletions project/threads/views.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import json

from accounts.models import Profile
from accounts.utils import get_account
from categories.models import Category
from core.custom_decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse
from django.template.response import TemplateResponse
from django.views.decorators.csrf import csrf_exempt
Expand All @@ -24,14 +21,14 @@
)


class ThreadDetailView(LoginRequiredMixin, DetailView):
class ThreadDetailView(DetailView):
model = Thread
context_object_name = "thread"
template_name = "thread.html"
login_url = "accounts_login"

def get_context_data(self, **kwargs):
context = super(ThreadDetailView, self).get_context_data(**kwargs)
context = super().get_context_data(**kwargs)
context["categories"] = Category.objects.all()
return context

Expand Down Expand Up @@ -130,35 +127,38 @@ def images(self, request, pk=None):


def base_view(request):
if not request.user.is_authenticated:
return TemplateResponse(request, "landing.html", {})

Profile_filter = Profile.objects.get(user=request.user)
if "login_user_image" not in request.session.keys():
request.session["login_user_image"] = Profile_filter.profile_image_thumb_url
return TemplateResponse(request, "landing.html", {})

categories = [{"id": c.id, "name": c.name} for c in Category.objects.all()]

def feeds(request):
all_categories = list(Category.objects.values_list("id", flat=True))
user_categories = (
list(Profile_filter.categories.values_list("id", flat=True)) or all_categories
)

categories = [{"id": c.id, "name": c.name} for c in Category.objects.all()]
feed_threads = [
Thread.objects.summarize(t)
for t in Thread.objects.exclude(is_draft=True).order_by("-created")
for t in Thread.objects.exclude(is_draft=False).order_by("-created")
]
top5_threads = list(
Thread.objects.filter(is_draft=False)
.order_by("-num_views")[:5]
.values("id", "title")
)
my_draft_threads = [
Thread.objects.summarize(t)
for t in Thread.objects.filter(author_id=Profile_filter.id)
.exclude(is_draft=False)
.order_by("-created")
]
if request.user.is_authenticated:
Profile_filter = Profile.objects.get(user=request.user)
if "login_user_image" not in request.session.keys():
request.session["login_user_image"] = Profile_filter.profile_image_thumb_url
my_draft_threads = [
Thread.objects.summarize(t)
for t in Thread.objects.filter(author_id=Profile_filter.id)
.exclude(is_draft=False)
.order_by("-created")
]
user_categories = (
list(Profile_filter.categories.values_list("id", flat=True))
or all_categories
)
else:
my_draft_threads = []
user_categories = []

data = {
"categories": categories,
Expand All @@ -168,7 +168,7 @@ def base_view(request):
"draft_threads": my_draft_threads,
}

return TemplateResponse(request, "feed.html", {"data": json.dumps(data)})
return TemplateResponse(request, "feed.html", data)


@csrf_exempt
Expand Down