Skip to content

Commit

Permalink
Merge in Changes from Daniel's Branch
Browse files Browse the repository at this point in the history
  • Loading branch information
shiva-menta committed Apr 26, 2024
1 parent 3cbf128 commit f5e1a51
Show file tree
Hide file tree
Showing 7 changed files with 322 additions and 129 deletions.
33 changes: 33 additions & 0 deletions backend/courses/migrations/0066_auto_20240426_0611.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 3.2.23 on 2024-04-26 10:11

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


class Migration(migrations.Migration):

dependencies = [
('courses', '0065_auto_20240424_2243'),
]

operations = [
migrations.RemoveField(
model_name='comment',
name='parent_id',
),
migrations.AddField(
model_name='comment',
name='base',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='courses.comment'),
),
migrations.AddField(
model_name='comment',
name='parent',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='courses.comment'),
),
migrations.AlterField(
model_name='comment',
name='section',
field=models.ForeignKey(help_text='\nThe section with which a comment is associated. Section was chosen instead of topics for\nhosting comments because topics are SOFT STATE and are recomputed regularly.\n', null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.section'),
),
]
26 changes: 15 additions & 11 deletions backend/courses/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1521,32 +1521,36 @@ class Comment(models.Model):
section = models.ForeignKey(
Section,
on_delete=models.CASCADE,
default=None,
help_text=dedent(
"""
The section with which a comment is associated. Section was chosen instead of courses
for hosting topics to support lower levels of filtering.
The section with which a comment is associated. Section was chosen instead of topics for
hosting comments because topics are SOFT STATE and are recomputed regularly.
"""
)
),
null=True
)

parent_id = models.ForeignKey(
base = models.ForeignKey(
"self",
on_delete=models.SET_NULL, # redundant due to special deletion conditions
null=True
null=True,
)
parent = models.ForeignKey(
"self",
on_delete=models.SET_NULL, # similarly redundant
null=True,
related_name="children"
)
path = models.TextField(db_index=True)

def level(self):
return len(self.path.split('.'))
def save(self, **kwargs):
prefix = self.parent.path + '.' if self.parent else ''
self.path = prefix + '{:0{}d}'.format(self.id, self._N)
super().save(**kwargs)

def delete(self, **kwargs):
if Comment.objects.filter(parent_id=self).exists():
self.text = "This comment has been removed."
self.likes.clear()
self.upvotes.clear()
self.downvotes.clear()
self.author = None
self.save()
else:
Expand Down
47 changes: 39 additions & 8 deletions backend/courses/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,15 +468,46 @@ def to_representation(self, instance):

class CommentSerializer(serializers.ModelSerializer):
author_name = serializers.CharField(source="author.username", read_only=True)
likes = serializers.SerializerMethodField()
course = serializers.CharField(source="course.full_code", read_only=True)
parent_id = serializers.SerializerMethodField()
votes = serializers.SerializerMethodField()
section = serializers.CharField(source="section.full_code", read_only=True)
base = serializers.SerializerMethodField()
parent = serializers.SerializerMethodField()

def get_votes(self, obj):
return len(obj.upvotes.values_list('id')) - len(obj.downvotes.values_list('id'))
def get_base(self, obj):
if obj.base is None:
return None
return obj.base.id
def get_parent(self, obj):
if obj.parent is None:
return None
return obj.parent.id

class Meta:
model = Comment
fields = ['id', 'text', 'created_at', 'modified_at', 'author_name', 'votes', 'section', 'base', 'parent', 'path']

def get_likes(self, obj):
return len(obj.likes.values_list('id'))
def get_parent_id(self, obj):
return obj.parent_id.id
class CommentListSerializer(serializers.ModelSerializer):
author_name = serializers.CharField(source="author.username", read_only=True)
votes = serializers.SerializerMethodField()
section = serializers.CharField(source="section.full_code", read_only=True)
base = serializers.SerializerMethodField()
parent = serializers.SerializerMethodField()
user_upvoted = serializers.BooleanField()
user_downvoted = serializers.BooleanField()

def get_votes(self, obj):
return len(obj.upvotes.values_list('id')) - len(obj.downvotes.values_list('id'))
def get_base(self, obj):
if obj.base is None:
return None
return obj.base.id
def get_parent(self, obj):
if obj.parent is None:
return None
return obj.parent.id

class Meta:
model = Comment
fields = ['id', 'text', 'created_at', 'modified_at', 'author_name', 'likes', 'course', 'parent_id', 'path']
fields = ['id', 'text', 'created_at', 'modified_at', 'author_name', 'votes', 'section', 'base', 'parent', 'path', 'user_upvoted', 'user_downvoted']
9 changes: 4 additions & 5 deletions backend/courses/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@ def get_semesters(semesters: str = None) -> list[str]:
raise ValueError(f"Provided semester {s} was not found in the db.")
return sorted(semesters)

def get_section_from_course_professor_semester(course_code, professors, semester):
def get_section_from_course_instructor_semester(course_code, professors, semester):
"""
Attempts to return a course section that matches the given parameters.
ValueError is raised if the section does not exist.
Expand All @@ -724,12 +724,11 @@ def get_section_from_course_professor_semester(course_code, professors, semester
course__semester=semester
)

professors_query = Q(instructors__username=professors[0])
professors_query = Q(instructors__name=professors[0])
for professor in professors[1:]:
professors_query &= Q(instructors__username=professor)
professors_query &= Q(instructors__name=professor)
matching_sections = sections.filter(professors_query).distinct()

if matching_sections.count() == 1:
return matching_sections.first()
raise ValueError(f"No section exists with course code ({course_code}), professor ({professor}), semester ({semester})")

raise ValueError(f"No section exists with course code ({course_code}), professor ({professors[0]}), semester ({semester})")
23 changes: 17 additions & 6 deletions backend/review/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
department_reviews,
instructor_for_course_reviews,
instructor_reviews,
handle_vote,
get_comment_children,
CommentList,
CommentViewSet,
handle_vote
CommentViewSet
)


Expand Down Expand Up @@ -47,17 +48,27 @@
path("autocomplete", cache_page(MONTH_IN_SECONDS)(autocomplete), name="review-autocomplete"),
path(
"<slug:semester>/course_comments/<slug:course_code>",
cache_page(DAY_IN_SECONDS)(CommentList),
CommentList.as_view(),
name="course-comments"
),
path(
"comments/votes/",
"comment/vote/",
handle_vote,
name="comment-votes"
name="comment-vote"
),
path(
"comment/<slug:pk>",
CommentViewSet.as_view(actions={'get': 'retrieve', "delete": "destroy", "put": "update"}),
name="comment"
),
path(
"comment/children/<slug:pk>",
get_comment_children,
name="comment-children"
),
path(
"comment",
cache_page(DAY_IN_SECONDS)(CommentViewSet),
CommentViewSet.as_view(actions={"post": "create"}),
name="comment"
)
]
Loading

0 comments on commit f5e1a51

Please sign in to comment.