Merge remote-tracking branch 'origin/review-votes' into develop
This commit is contained in:
commit
723def350d
|
@ -10,6 +10,8 @@ urlpatterns = [
|
||||||
# /api/postings/reviews/1/ Returns data for one Review.
|
# /api/postings/reviews/1/ Returns data for one Review.
|
||||||
path('reviews/<int:pk>', ReviewView.as_view(), name='review'),
|
path('reviews/<int:pk>', ReviewView.as_view(), name='review'),
|
||||||
|
|
||||||
|
path('reviews/<int:review_id>/helpful_vote/', review_helpful_vote, name='review_helpful_vote'),
|
||||||
|
|
||||||
# /api/postings/universities/ Lists all university objects.
|
# /api/postings/universities/ Lists all university objects.
|
||||||
path('universities/', UniversitiesView.as_view(), name='universities'),
|
path('universities/', UniversitiesView.as_view(), name='universities'),
|
||||||
# /api/postings/universities/1/ Returns data for one University.
|
# /api/postings/universities/1/ Returns data for one University.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from rest_framework import generics, mixins
|
from rest_framework import generics, mixins
|
||||||
from postings.models import UniversityReview, Review
|
from postings.models import UniversityReview, Review, ReviewHelpfulVote
|
||||||
from .serializers import *
|
from .serializers import *
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
||||||
|
@ -66,3 +66,22 @@ class ProfessorsView(generics.ListAPIView):
|
||||||
class ProfessorView(generics.RetrieveUpdateDestroyAPIView):
|
class ProfessorView(generics.RetrieveUpdateDestroyAPIView):
|
||||||
queryset = Professor.objects.all()
|
queryset = Professor.objects.all()
|
||||||
serializer_class = ProfessorSerializer
|
serializer_class = ProfessorSerializer
|
||||||
|
|
||||||
|
def review_helpful_vote(request, review_id):
|
||||||
|
if request.method == 'POST':
|
||||||
|
helpful = request.POST.get('helpful')
|
||||||
|
if helpful is None:
|
||||||
|
return HttpResponseBadRequest("Bad Request")
|
||||||
|
helpful = True if helpful == 'true' else False
|
||||||
|
|
||||||
|
try:
|
||||||
|
review = Review.objects.get(pk=review_id)
|
||||||
|
except Review.DoesNotExist:
|
||||||
|
raise HttpResponseBadRequest("Bad Request: Invalid review id.")
|
||||||
|
|
||||||
|
vote = ReviewHelpfulVote.objects.create(
|
||||||
|
review=review,
|
||||||
|
helpful=helpful
|
||||||
|
)
|
||||||
|
|
||||||
|
return HttpResponseBadRequest("Bad Request")
|
|
@ -63,11 +63,11 @@ class Review(models.Model):
|
||||||
|
|
||||||
# Gets the total number of votes which marked this review as 'helpful'.
|
# Gets the total number of votes which marked this review as 'helpful'.
|
||||||
def getHelpfulVoteCount(self):
|
def getHelpfulVoteCount(self):
|
||||||
ReviewHelpfulVote.objects.filter(pk=self.pk, helpful=True).count()
|
return ReviewHelpfulVote.objects.filter(pk=self.pk, helpful=True).count()
|
||||||
|
|
||||||
# Gets the total number of votes which marked this review as 'unhelpful'.
|
# Gets the total number of votes which marked this review as 'unhelpful'.
|
||||||
def getUnhelpfulVoteCount(self):
|
def getUnhelpfulVoteCount(self):
|
||||||
ReviewHelpfulVote.objects.filter(pk=self.pk, helpful=False).count()
|
return ReviewHelpfulVote.objects.filter(pk=self.pk, helpful=False).count()
|
||||||
|
|
||||||
# A vote for a review as either positive or negative.
|
# A vote for a review as either positive or negative.
|
||||||
class ReviewHelpfulVote(models.Model):
|
class ReviewHelpfulVote(models.Model):
|
||||||
|
|
|
@ -162,7 +162,7 @@
|
||||||
<a class="btn btn-danger btn-sm" href="#" id="close-review-box" style="display:none; margin-right: 10px;">
|
<a class="btn btn-danger btn-sm" href="#" id="close-review-box" style="display:none; margin-right: 10px;">
|
||||||
<span class="glyphicon glyphicon-remove"></span>Cancel</a>
|
<span class="glyphicon glyphicon-remove"></span>Cancel</a>
|
||||||
<input type="hidden" id="rating_input" name="rating" value="1">
|
<input type="hidden" id="rating_input" name="rating" value="1">
|
||||||
{% csrf_token %}
|
<div id="csrf-token">{% csrf_token %}</div>
|
||||||
<input type="hidden" name="entity_id" value="{{ entity.pk }}">
|
<input type="hidden" name="entity_id" value="{{ entity.pk }}">
|
||||||
<button class="btn btn-success btn-lg" type="submit">Save</button>
|
<button class="btn btn-success btn-lg" type="submit">Save</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -193,5 +193,6 @@
|
||||||
|
|
||||||
<!-- Custom scripts -->
|
<!-- Custom scripts -->
|
||||||
<script src="js/main.js"></script>
|
<script src="js/main.js"></script>
|
||||||
|
<script src="js/voting.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -11,10 +11,18 @@
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="review-block-rate" data-rating="{{ review.rating }}">
|
<div class="review-block-rate" data-rating="{{ review.rating }}">
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="review-block-title">{{ review.title }}</div>
|
<div class="review-block-title">{{ review.title }}</div>
|
||||||
<div class="review-block-description">{{ review.content }}</div>
|
<div class="review-block-description">{{ review.content }}</div>
|
||||||
|
|
||||||
|
<div id="review-votes-{{ review.pk }}">
|
||||||
|
<div class="review-vote-buttons">
|
||||||
|
Was this review helpful?
|
||||||
|
<a data-review-id="{{ review.pk }}" class="btn btn-light btn-sm vote-up"><span class="glyphicon glyphicon-thumbs-up"></span> Yes</a>
|
||||||
|
<a data-review-id="{{ review.pk }}" class="btn btn-light btn-sm vote-down"><span class="glyphicon glyphicon-thumbs-down"></span> No</a>
|
||||||
|
</div>
|
||||||
|
<span title="{{ review.getHelpfulVoteCount }} people found this review helpful"><span class="votes-helpful">{{ review.getHelpfulVoteCount }}</span> <span class="glyphicon glyphicon-thumbs-up"></span></span> /
|
||||||
|
<span title="{{ review.getUnhelpfulVoteCount }} people found this review unhelpful"><span class="votes-unhelpful">{{ review.getUnhelpfulVoteCount }}</span> <span class="glyphicon glyphicon-thumbs-down"></span></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -0,0 +1,34 @@
|
||||||
|
$(function() {
|
||||||
|
var csrftoken = $("#csrf-token input").val();
|
||||||
|
|
||||||
|
$(".vote-up").click(function() {
|
||||||
|
var reviewId = $(this).attr("data-review-id");
|
||||||
|
var data = {
|
||||||
|
'csrfmiddlewaretoken': csrftoken,
|
||||||
|
'helpful': true
|
||||||
|
};
|
||||||
|
// Vote up
|
||||||
|
$.post(
|
||||||
|
'/api/postings/reviews/' + reviewId + '/helpful_vote/',
|
||||||
|
data,
|
||||||
|
function(result) { console.log(result); }
|
||||||
|
);
|
||||||
|
// Hide vote buttons
|
||||||
|
$("#review-votes-" + reviewId + " .review-vote-buttons").hide();
|
||||||
|
});
|
||||||
|
$(".vote-down").click(function() {
|
||||||
|
var reviewId = $(this).attr("data-review-id");
|
||||||
|
var data = {
|
||||||
|
'csrfmiddlewaretoken': csrftoken,
|
||||||
|
'helpful': false
|
||||||
|
};
|
||||||
|
// Vote down
|
||||||
|
$.post(
|
||||||
|
'/api/postings/reviews/' + reviewId + '/helpful_vote/',
|
||||||
|
data,
|
||||||
|
function(result) { console.log(result); }
|
||||||
|
);
|
||||||
|
// Hide vote buttons
|
||||||
|
$("#review-votes-" + reviewId + " .review-vote-buttons").hide();
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue