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

implement comment feature for activities #158

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions project/activities/migrations/0002_comment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Generated by Django 4.1.3 on 2022-11-19 22:37

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
("activities", "0001_initial"),
]

operations = [
migrations.CreateModel(
name="Comment",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("user_id", models.BigIntegerField()),
("text", models.CharField(max_length=250)),
("timestamp", models.DateTimeField(auto_now_add=True)),
(
"activity",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="comment",
to="activities.activity",
),
),
],
),
]
2 changes: 1 addition & 1 deletion project/activities/migrations/max_migration.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0001_initial
0002_comment
12 changes: 12 additions & 0 deletions project/activities/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,15 @@ def remaining_eligible_companions(self):
remaining_eligible_companions = companions.difference(current_participants)

return remaining_eligible_companions


class Comment(models.Model):
user_id = models.BigIntegerField()
text = models.CharField(max_length=250)
timestamp = models.DateTimeField(auto_now_add=True)
activity = models.ForeignKey(
to=Activity,
related_name="comment",
on_delete=models.CASCADE,
null=True,
)
25 changes: 25 additions & 0 deletions project/activities/templates/activities/comments_detail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{% extends 'base.html' %}

{% load crispy_forms_tags %}
{% load i18n %}


{% block content %}
<h1>{{ activity_name }}</h1>
<h1>{{activity_date }}</h1>
<div class="row row-cols-lg-5 row-cols-md-3 row-cols-2 g-4">

{% for comment in activity_comments_list %}
<div class="col">
<div class="card h-100">
<div class="card-body">
<h2> {{ comment.text }} </h2>
<p> {{ comment.name }} </p>
<p> {{ comment.timestamp }} </p>
</div>
</div>
</div>
{% endfor %}

</div>
{% endblock content %}
196 changes: 196 additions & 0 deletions project/activities/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,3 +501,199 @@ def test_remaining_eligible_companions(self):

# Non-companion should not be in eligible companions list
assert self.user_three not in remaining_eligible_companions




class ActivityAddCommentViewTest(TestCase):
def setUp(self):
self.companion_one = User.objects.create_user("[email protected]", "test12345")
self.companion_two = User.objects.create_user("[email protected]", "test12345")

self.circle = Circle.objects.create(name="Test circle")

Companion.objects.create(
circle=self.circle,
user=self.companion_one,
)
Companion.objects.create(
circle=self.circle,
user=self.companion_two,
)
self.user_without_circle = User.objects.create_user(
"[email protected]",
"test12345",
)

self.circle_with_companion = Circle.objects.create(name="Companion circle")
self.companionship_through = Companion.objects.create(
circle=self.circle_with_companion,
user=self.companion_one,
is_organizer=True,
)
self.activity_for_circle_with_companion = Activity.objects.create(
activity_type=Activity.ActivityTypeChoices.APPOINTMENT,
activity_date="2022-10-23",
circle=self.circle_with_companion,
)

def test_anonymous_add_comment(self):
"""Anonymous user should not be authorized to add comment"""
response = self.client.post(
reverse("activity-add-comment",
kwargs={
"activity_id": self.activity_for_circle_with_companion.id,
}),
{
"activity_id": self.activity_for_circle_with_companion.id,
},
)

self.assertEqual(response.status_code, HTTPStatus.FORBIDDEN)

def test_authenticated_non_companion_add_comment(self):
"""Authenticated user who is not companion should not be authorized to add comment"""
self.client.force_login(self.user_without_circle)

response = self.client.post(
reverse("activity-add-comment",
kwargs={
"activity_id": self.activity_for_circle_with_companion.id,
}),
{
"activity_id": self.activity_for_circle_with_companion.id,
"user_comment": "HELLO",
"user_id": self.companion_one.id,
},
)

self.assertEqual(response.status_code, HTTPStatus.FORBIDDEN)



def test_authenticated_organizer_add_comment(self):
"""Organizer of activity should be able to add comemnt"""
self.client.force_login(self.companion_one)

response = self.client.post(
reverse(
"activity-add-comment",
kwargs={
"activity_id": self.activity_for_circle_with_companion.id,
},
),
{
"activity_id": self.activity_for_circle_with_companion.id,
"user_comment": "HELLO",
"user_id": self.companion_one.id,
},
)

self.assertEqual(response.status_code, HTTPStatus.FOUND)

def test_participant_add_comment(self):
"""Participant of activity should be able to add comemnt"""
self.client.force_login(self.companion_one)
self.client.post(
reverse(
"activity-add-participant",
kwargs={
"activity_id": self.activity_for_circle_with_companion.id,
},
),
{
"user_id": self.companion_two.id,
},
)

response = self.client.post(
reverse(
"activity-add-comment",
kwargs={
"activity_id": self.activity_for_circle_with_companion.id,
},
),
{
"activity_id": self.activity_for_circle_with_companion.id,
"user_comment": "HELLO",
"user_id": self.companion_two.id,
},
)

self.assertEqual(response.status_code, HTTPStatus.FOUND)





class ActivityCommentViewTest(TestCase):
def setUp(self):
self.companion_one = User.objects.create_user("[email protected]", "test12345")
self.companion_two = User.objects.create_user("[email protected]", "test12345")

self.circle = Circle.objects.create(name="Test circle")

Companion.objects.create(
circle=self.circle,
user=self.companion_one,
is_organizer=True,
)
Companion.objects.create(
circle=self.circle,
user=self.companion_two,
)

self.activity_for_circle_with_companion = Activity.objects.create(
activity_type=Activity.ActivityTypeChoices.APPOINTMENT,
activity_date="2022-11-23",
circle=self.circle,
)



def test_anonymous_access(self):
"""Anonymous user should not be authorized to view the comment page"""
response = self.client.get(
reverse("activity-view-comments",
kwargs={
"activity_id": self.activity_for_circle_with_companion.id,
}),
{
"activity_id": self.activity_for_circle_with_companion.id,
},
)

self.assertEqual(response.status_code, HTTPStatus.FORBIDDEN)

def test_authenticated_access(self):
"""Authorized user should be authorized to view the comment page"""
self.client.force_login(self.companion_one)
comment= "wow, this activity looks cool!"

response = self.client.post(
reverse(
"activity-add-comment",
kwargs={
"activity_id": self.activity_for_circle_with_companion.id,
},
),
{
"activity_id": self.activity_for_circle_with_companion.id,
"user_comment": comment,
"user_id": self.companion_one.id,
},
)
response = self.client.get(
reverse(
"activity-view-comments",
kwargs={
"activity_id": self.activity_for_circle_with_companion.id,
},
),
{
"activity_id": self.activity_for_circle_with_companion.id,
},
)
self.assertEqual(response.status_code, HTTPStatus.OK)
self.assertContains(response, self.companion_two.display_name)
self.assertContains(response, comment)
12 changes: 12 additions & 0 deletions project/activities/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
ActivityRemoveParticipantView,
ActivitySetDoneView,
ActivityUpdateView,
ActivityAddCommentView,
ActivityViewCommentView,
)

urlpatterns = [
Expand Down Expand Up @@ -40,4 +42,14 @@
ActivitySetDoneView.as_view(),
name="activity-set-done",
),
path(
"update/<slug:activity_id>/add_comment",
ActivityAddCommentView.as_view(),
name="activity-add-comment",
),
path(
"<slug:activity_id>/comments",
ActivityViewCommentView.as_view(),
name="activity-view-comments",
),
]
62 changes: 60 additions & 2 deletions project/activities/views.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from circles.models import Circle
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.http import HttpResponseRedirect
from django.shortcuts import redirect
from django.shortcuts import redirect, render
from django.urls import reverse
from django.views.generic import View

from .forms import ActivityModelForm
from .models import Activity
from .models import Activity, Comment, User


class ActivityCreateView(UserPassesTestMixin, LoginRequiredMixin, View):
Expand Down Expand Up @@ -221,3 +221,61 @@ def get(self, request, activity_id, *args, **kwargs):
kwargs={"pk": self.activity.circle.id},
)
)


class ActivityAddCommentView(UserPassesTestMixin, LoginRequiredMixin, View):
raise_exception = True

def test_func(self, *args, **kwargs):
"""Only activity participants or circle's care organizers can comment activity"""
self.activity = Activity.objects.get(id=self.kwargs["activity_id"])

user_is_participant = self.request.user in self.activity.participants.all()
user_is_organizer = self.request.user in self.activity.circle.organizers

user_can_update_activity = user_is_participant or user_is_organizer

return user_can_update_activity

def post(self, request, activity_id, *args, **kwargs):
"""Adds user comments to the comment database."""
user_id = request.POST["user_id"]
text = request.POST["user_comment"]

activity = Activity.objects.get(id = activity_id)
new_comment = Comment(user_id=user_id, text=text, activity=activity)
new_comment.save()
return redirect(
reverse(
"circle-detail",
kwargs={"pk": activity.circle.id},
)
)


class ActivityViewCommentView(UserPassesTestMixin, LoginRequiredMixin, View):
raise_exception = True

def test_func(self, *args, **kwargs):
"""Allow everyone to view comments for activities"""

return True

def get(self, request, activity_id, *args, **kwargs):
"""Fetch all comments for activity with activity_id"""
activity = Activity.objects.get(id=activity_id)
activity_comments_list = Comment.objects.filter(activity = activity)
newList = [
{
"name": str(User.objects.get(id = t.user_id).display_name),
"text" : str(t.text),
"timestamp" : str(t.timestamp).split(".")[0]
} for t in activity_comments_list
]
context = {
"activity_name": str(activity),
"activity_date": activity.activity_date,
"activity_comments_list": newList,
}
template_name="activities/comments_detail.html"
return render(request, template_name, context)
Loading