Skip to content
Open
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
*.sublime-*
*.sqlite3*
*.sass-cache
*app.js
*services.js
*controllers.js
*directives.js


/node_modules
Expand Down
10 changes: 10 additions & 0 deletions djangular/frontend/app.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ app.config(($interpolateProvider, $stateProvider, $urlRouterProvider) ->
question.get($stateParams.questionId)
return question
)
.state('questionResults'
url: '/{questionId:[0-9]+}/results'
templateUrl: 'questionResults'
controller: 'questionResultsController'
resolve:
question : ($stateParams, $log, Question)->
question = new Question(null)
question.get($stateParams.questionId)
return question
)
)


Expand Down
26 changes: 18 additions & 8 deletions djangular/frontend/controllers.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,31 @@ controllers = angular.module('pollApp.controllers', [])

controllers.controller('questionListController', ($scope, $state, $log, questions) ->
$scope.questions = questions.all
$scope.sortQuestions = (questions) ->
questions.sort((a,b) -> b.upvotes - a.upvotes )

$scope.upvote = (question) ->
question.upvote()
$scope.questions = $scope.sortQuestions($scope.questions)

$scope.downvote = (question) ->
question.downvote()
$scope.questions = $scope.sortQuestions($scope.questions)
)

controllers.controller('questionDetailController', ($scope, $state, $log, question) ->
$scope.question = question
$scope.voted = false
$scope.voteChoice = 0

$scope.vote = ->
for choice in $scope.question.choices
if choice.id == parseInt($scope.voteChoice)
choice.votes+=1
$scope.question.totalVotes+=1
choice.update()
break
$scope.voted = true
question.voteOnChoice(parseInt($scope.voteChoice), () -> $state.go('questionResults', {questionId:question.id}))
)

controllers.controller('questionResultsController', ($scope, $state, $log, question) ->
$scope.question = question

$scope.submitFeedback = ->
question.addFeedback($scope.feedbackToSubmit.feedback_text)
$scope.feedbackToSubmit.feedback_text = ''
)

75 changes: 73 additions & 2 deletions djangular/frontend/services.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,40 @@ services.factory('Choice', ($http, $log)->
@id = data.id
@votes = data.votes

update : ->
update : (cb) ->
data = {'votes' : @votes, 'choice_text' : @choice_text}
$http({method: 'PUT', url: '/polls/choices/' + @id + '/', data:data})
.success (data) =>
$log.info("Succesfully voted")
cb()
.error (data) =>
$log.info("Failed to vote.")
cb()

return Choice
)

services.factory('Question', (Choice, $http, $log) ->
services.factory('Feedback', ($http, $log)->
#log = $log
class Feedback
constructor: (data) ->
@feedback_text = data.feedback_text
@id = data.id
@pub_date = data.pub_date
@pub_date_fmt = moment(data.pub_date).calendar()

update : ->
data = {'feedback_text' : @feedback_text}
$http({method: 'PUT', url: '/polls/feedbacks/' + @id + '/', data:data})
.success (data) =>
$log.info("Succesfully left feedback")
.error (data) =>
$log.info("Failed to leave feedback.")

return Feedback
)

services.factory('Question', (Choice, Feedback, $http, $log) ->
class Question
constructor : (data) ->
if data != null
Expand All @@ -28,11 +50,41 @@ services.factory('Question', (Choice, $http, $log) ->
@question_text = data.question_text
@id = data.id
@choices = []
@feedbacks = []
@totalVotes = 0
@lastResponseDate = data.last_response_date
@lastResponseDateFmt = moment(data.last_response_date).fromNow()
@upvotes = data.upvotes
for choice in data.choices
c = new Choice(choice)
@totalVotes += c.votes
@choices.push(new Choice(choice))
for feedback in data.feedbacks
@feedbacks.push(new Feedback(feedback))

upvote : () ->
if @upvotes
@upvotes = @upvotes + 1
else
@upvotes = 1
$http({method: 'POST', url: '/polls/questions/' + @id + '/upvote'})
.success (data) =>
@upvotes = data.upvotes
$log.info("Succesfully upvoted")
.error (data) =>
$log.info("Failed to upvote.")

downvote : () ->
if @upvotes
@upvotes = @upvotes - 1
else
@upvotes = -1
$http({method: 'POST', url: '/polls/questions/' + @id + '/downvote'})
.success (data) =>
@upvotes = data.upvotes
$log.info("Succesfully downvoted")
.error (data) =>
$log.info("Failed to downvote.")

get : (questionId) ->
$http({method: 'GET', url: '/polls/questions/' + questionId + '/'})
Expand All @@ -41,6 +93,24 @@ services.factory('Question', (Choice, $http, $log) ->
$log.info("Succesfully fetched question")
.error (data) =>
$log.info("Failed to fetch question.")

voteOnChoice : (voteChoice, cb) ->
for choice in @choices
if choice.id == voteChoice
choice.votes+=1
@totalVotes+=1
choice.update(cb)
break

addFeedback: (feedbackText) ->
data = {'feedback_text' : feedbackText, 'question' : @id }
$http({method: 'POST', url: '/polls/feedbacks', data:data})
.success (data) =>
$log.info("Succesfully added feedback")
@feedbacks.push(new Feedback(data))
.error (data) =>
$log.info("Failed to add feedback")

return Question
)

Expand All @@ -53,6 +123,7 @@ services.factory('Questions', ($log, $http, Question) ->
questions['all'].length = 0
for question in data
questions['all'].push(new Question(question))
questions['all'] = questions['all'].sort((a,b) -> b.upvotes - a.upvotes )

fetch: ->
$http({method: 'GET', url: '/polls/questions'})
Expand Down
9 changes: 7 additions & 2 deletions djangular/polls/admin.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
from django.contrib import admin
from polls.models import Choice, Question
from polls.models import Choice, Question, Feedback


class ChoiceInline(admin.StackedInline):
model = Choice
extra = 3


class FeedbackInline(admin.StackedInline):
model = Feedback
extra = 1


class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['question_text']}),
('Date information', {'fields': ['pub_date'],
'classes': ['collapse']}),
]
inlines = [ChoiceInline]
inlines = [ChoiceInline, FeedbackInline]

admin.site.register(Question, QuestionAdmin)
25 changes: 25 additions & 0 deletions djangular/polls/models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from django.db import models
import datetime

class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
last_response_date = models.DateTimeField('last response date', null=True, blank=True)
upvotes = models.IntegerField(null=True, blank=True)

def __unicode__(self):
return self.question_text
Expand All @@ -16,3 +19,25 @@ class Choice(models.Model):
def __unicode__(self):
return self.choice_text

def save(self, *args, **kwargs):
''' On save, update timestamp on question '''
if self.votes > 0:
self.question.last_response_date = datetime.datetime.today()
self.question.save()
return super(Choice, self).save(*args, **kwargs)


class Feedback(models.Model):
question = models.ForeignKey(Question, related_name='feedbacks')
feedback_text = models.CharField(max_length=500)
pub_date = models.DateTimeField('date published')

def __unicode__(self):
return self.feedback_text

def save(self, *args, **kwargs):
''' On save, update timestamps '''
if not self.id:
self.pub_date = datetime.datetime.today()
return super(Feedback, self).save(*args, **kwargs)

18 changes: 15 additions & 3 deletions djangular/polls/serializers.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
from rest_framework import serializers

from .models import Question, Choice
from .models import Question, Choice, Feedback

class ChoiceSerializer(serializers.ModelSerializer):
question = serializers.PrimaryKeyRelatedField(required=False, read_only=True)

class Meta:
model = Choice
fields = ('choice_text', 'id', 'votes')
fields = ('choice_text', 'question', 'id', 'votes')

class FeedbackSerializer(serializers.ModelSerializer):
pub_date = serializers.DateTimeField(required=False)

class Meta:
model = Feedback
fields = ('feedback_text', 'question', 'id', 'pub_date')

class QuestionSerializer(serializers.ModelSerializer):
choices = ChoiceSerializer(many=True)
feedbacks = FeedbackSerializer(many=True)
last_response_date = serializers.DateTimeField(required=False)
upvotes = serializers.IntegerField(required=False)

class Meta:
model = Question
fields = ('question_text', 'choices', 'id')
# 'last_response_date'
fields = ('question_text', 'last_response_date', 'upvotes', 'choices', 'feedbacks', 'id')

9 changes: 8 additions & 1 deletion djangular/polls/urls.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
from django.conf.urls import patterns, url, include

from .views import QuestionList, ChoiceList, QuestionDetail, ChoiceUpdate
from .views import QuestionList, ChoiceList, QuestionDetail, ChoiceUpdate, FeedbackList, FeedbackUpdate, UpvoteApiView, DownvoteApiView


urlpatterns = patterns('polls.views',
url(r'^questions$', QuestionList.as_view(), name='questions_list'),
url(r'^questions/(?P<question_pk>[0-9]+)/$', QuestionDetail.as_view(),
name="questions_detail"),
url(r'^questions/(?P<question_pk>[0-9]+)/upvote$', UpvoteApiView.as_view(),
name="upvote"),
url(r'^questions/(?P<question_pk>[0-9]+)/downvote$', DownvoteApiView.as_view(),
name="downvote"),
url(r'^choices$', ChoiceList.as_view(), name='choices_list'),
url(r'^choices/(?P<choice_pk>[0-9]+)/$', ChoiceUpdate.as_view(),
name='choices_update'),
url(r'^feedbacks$', FeedbackList.as_view(), name='feedbacks_list'),
url(r'^feedbacks/(?P<feedback_pk>[0-9]+)/$', FeedbackUpdate.as_view(),
name='feedback_update'),
url(r'^$', 'index', name='questions_index'),
)
56 changes: 49 additions & 7 deletions djangular/polls/views.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,80 @@
from rest_framework import generics, permissions
from .models import Question, Choice
from .serializers import QuestionSerializer, ChoiceSerializer
from rest_framework import generics, permissions, views
from rest_framework.response import Response
from .models import Question, Choice, Feedback
from .serializers import QuestionSerializer, ChoiceSerializer, FeedbackSerializer
from django.shortcuts import render


class QuestionList(generics.ListCreateAPIView):
model = Question
queryset = Question.objects.all()
#model = Question
serializer_class = QuestionSerializer
permission_classes = [
permissions.AllowAny
]

class QuestionDetail(generics.RetrieveAPIView):
model = Question
queryset = Question.objects.all()
#model = Question
serializer_class = QuestionSerializer
lookup_url_kwarg = 'question_pk'
permission_classes = [
permissions.AllowAny
]

class ChoiceUpdate(generics.UpdateAPIView):
model = Choice
queryset = Choice.objects.all()
#model = Choice
serializer_class = ChoiceSerializer
lookup_url_kwarg = 'choice_pk'
permission_classes = [
permissions.AllowAny
]

class ChoiceList(generics.ListCreateAPIView):
model = Choice
queryset = Choice.objects.all()
#model = Choice
serializer_class = ChoiceSerializer
permission_classes = [
permissions.AllowAny
]

class FeedbackUpdate(generics.UpdateAPIView):
queryset = Feedback.objects.all()
serializer_class = FeedbackSerializer
lookup_url_kwarg = 'feedback_pk'
permission_classes = [
permissions.AllowAny
]

class FeedbackList(generics.ListCreateAPIView):
queryset = Feedback.objects.all()
serializer_class = FeedbackSerializer
permission_classes = [
permissions.AllowAny
]

class UpvoteApiView(views.APIView):

def post(self, request, *args, **kwargs):
question = Question.objects.get(id=kwargs['question_pk'])
if question.upvotes:
question.upvotes = question.upvotes+1
else:
question.upvotes = 1
question.save()
return Response({"question": question.id, "upvotes": question.upvotes, "success": True})

class DownvoteApiView(views.APIView):

def post(self, request, *args, **kwargs):
question = Question.objects.get(id=kwargs['question_pk'])
if question.upvotes:
question.upvotes = question.upvotes-1
else:
question.upvotes = -1
question.save()
return Response({"question": question.id, "upvotes": question.upvotes, "success": True})

def index(request):
return render(request, 'polls/index.html')
Loading