Skip to content

Commit

Permalink
Adds support for seeing results of voting
Browse files Browse the repository at this point in the history
Also changes voting to round 2
  • Loading branch information
beerlington committed Mar 23, 2014
1 parent 1c204d3 commit 1f4eabf
Show file tree
Hide file tree
Showing 21 changed files with 189 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Proposals.VotingResultsController = Ember.Controller.extend()

5 changes: 5 additions & 0 deletions app/assets/javascripts/models/result.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Proposals.Result = DS.Model.extend
proposal: DS.belongsTo('proposal')
voteCount: DS.attr('number')
title: DS.attr('string')
userName: DS.attr('string')
1 change: 1 addition & 0 deletions app/assets/javascripts/models/round.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ Proposals.Round = DS.Model.extend
text: DS.attr('string')
totalVotes: DS.attr('number')
isAnonymous: DS.attr('boolean')
isCompleted: DS.attr('boolean')
isCurrentRound: DS.attr('boolean')
name: DS.attr('string')
4 changes: 4 additions & 0 deletions app/assets/javascripts/router.js.coffee
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
Proposals.Router.map ()->
@resource('voting_round', path: '/round/:round')
@resource('voting_results', path: '/results/:round')
@resource('proposals', ->
@route('show', path: ':proposal_id')
)

Proposals.Router.reopen
rootURL: '/voting/'
Expand Down
10 changes: 10 additions & 0 deletions app/assets/javascripts/routes/voting_results_route.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Proposals.VotingResultsRoute = Ember.Route.extend
model: (params) ->
Ember.RSVP.hash(
round: @store.find('round', params.round)
results: @store.find('result', round: params.round)
)

setupController: (controller, model) ->
controller.set('round', model.round)
controller.set('results', model.results)
2 changes: 1 addition & 1 deletion app/assets/javascripts/routes/voting_round_route.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Proposals.VotingRoundRoute = Ember.Route.extend
model: (params) ->
Ember.RSVP.hash(
round: @store.find('round', params.round)
proposals: @store.find('proposal')
proposals: @store.find('proposal', round: params.round)
)

setupController: (controller, model) ->
Expand Down
17 changes: 12 additions & 5 deletions app/assets/javascripts/templates/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@
<div class="small-12 medium-6 columns">
<h2>{{round.text}}</h2>

{{#if round.isCurrentRound}}
<p>Voting is now open for {{round.text}}. {{link-to "Cast your vote." "voting_round" round.id}}</p>
{{else}}
<p>Voting is closed for {{round.text}}.</p>
{{/if}}
<p>
{{#if round.isCurrentRound}}
Voting is now open for {{round.text}}. {{link-to "Cast your vote." "voting_round" round.id}}</p>
{{else}}
Voting is closed for {{round.text}}.
{{/if}}

{{#if round.isCompleted}}
{{link-to 'View results' 'voting_results' round.id}}
{{/if}}
</p>


<h3>Your votes for {{round.text}}</h3>
<ol>
Expand Down
44 changes: 44 additions & 0 deletions app/assets/javascripts/templates/proposals/show.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<div class="voting">
<div class="proposal-show">
<h1>{{title}}</h1>

{{#if userName}}
<div class="user-info content">
<h2>Submitter info</h2>
<dl>
<dt>Name</dt>
<dd>{{userName}}</dd>
{{#if twitter}}
<dt><i class="fi-social-twitter"></i></dt>
<dd>{{format-twitter twitter}}</dd>
{{/if}}
{{#if github}}
<dt><i class="fi-social-github"></i></dt>
<dd>{{format-github github}}</dd>
{{/if}}
</dl>

<div class="bio">
{{unbound format-markdown userBio}}
</div>
</div>
{{/if}}

<div class="content">
<h2>Abstract</h2>
{{format-markdown abstract}}
</div>

<div class="content">
<h2>Notes</h2>
{{format-markdown notes}}
</div>

{{#if pitch}}
<div class="content">
<h2>Pitch</h2>
{{format-markdown pitch}}
</div>
{{/if}}
</div>
</div>
17 changes: 17 additions & 0 deletions app/assets/javascripts/templates/voting_results.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<div class="voting">
<div class="results">
<h1>Voting Results for {{round.text}}</h1>

<ol>
{{#each results}}
<li>
[<span class="count">{{voteCount}} votes</span>]
{{link-to title 'proposals.show' id className="title"}}
{{#if userName}}by <span class="username">{{userName}}</span>{{/if}}
</li>
{{else}}
Loading...
{{/each}}
</ol>
</div>
</div>
12 changes: 12 additions & 0 deletions app/assets/stylesheets/style.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,15 @@ textarea {
.filters {
@include sub-nav();
}

.results {
.username {
font-weight: bold;
}
}

.proposal-show {
.content {
@include grid-column(12);
}
}
5 changes: 5 additions & 0 deletions app/controllers/api/proposals_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,10 @@ def index
current_votes: current_votes,
current_hidden_votes: current_hidden_votes
end

def show
proposal = Proposal.find(params[:id])
respond_with proposal, serializer: ProposalSerializer
end
end
end
22 changes: 22 additions & 0 deletions app/controllers/api/results_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module Api
class ResultsController < ApplicationController
respond_to :json
before_filter :require_voter!, :verify_round_complete

def index
respond_with Vote.results_for_round(round)
end

private

def round
Round.detect { |round| round.to_i == params[:round].to_i }
end

def verify_round_complete
unless round.completed?
render json: {}, status: :unauthorized
end
end
end
end
4 changes: 4 additions & 0 deletions app/enums/round.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
class Round < ClassyEnum::Base
include ActiveModel::Serialization

def completed?
self < Rails.configuration.current_round
end
end

class Round::One < Round
Expand Down
22 changes: 22 additions & 0 deletions app/models/vote.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,26 @@ class Vote < ActiveRecord::Base
belongs_to :proposal

classy_enum_attr :round

# Only show proposals with more than this many votes in results
MIN_VOTE_THRESHOLD = 1

def self.results_for_round(round)
votes = where(round: round).includes(proposal: :user).group_by(&:proposal)

votes.map {|proposal, votes|
{
id: proposal.id,
title: proposal.title,
user_name: anonymous? ? nil : proposal.user_name,
vote_count: votes.count
}
}.select {|result|
result[:vote_count] > MIN_VOTE_THRESHOLD
}.sort {|a,b| b[:vote_count] <=> a[:vote_count] }
end

def self.anonymous?
Rails.configuration.current_round.anonymous?
end
end
3 changes: 0 additions & 3 deletions app/serializers/proposal_list_serializer.rb

This file was deleted.

16 changes: 10 additions & 6 deletions app/serializers/proposal_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ class ProposalSerializer < ActiveModel::Serializer
has_one :hidden_vote

def vote
return if options[:current_votes].nil?

vote = options[:current_votes].detect { |vote| vote.proposal_id == object.id }
return if vote.nil?
VoteSerializer.new(vote)
end

def hidden_vote
return if options[:current_hidden_votes].nil?

vote = options[:current_hidden_votes].detect { |vote| vote.proposal_id == object.id }
return if vote.nil?
HiddenVoteSerializer.new(vote)
Expand All @@ -28,28 +32,28 @@ def visible
end

def pitch
object.pitch unless anonymous_round?
object.pitch unless anonymous?
end

def user_name
object.user_name unless anonymous_round?
object.user_name unless anonymous?
end

def user_bio
object.user_bio unless anonymous_round?
object.user_bio unless anonymous?
end

def twitter
object.user.twitter unless anonymous_round?
object.user.twitter unless anonymous?
end

def github
object.user.github unless anonymous_round?
object.user.github unless anonymous?
end

private

def anonymous_round?
def anonymous?
Rails.configuration.current_round.anonymous?
end
end
7 changes: 6 additions & 1 deletion app/serializers/round_serializer.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
class RoundSerializer < ActiveModel::Serializer
root false

attributes :id, :text, :total_votes, :is_anonymous, :is_current_round, :name
attributes :id, :text, :total_votes, :is_anonymous, :is_current_round, :name,
:is_completed

def name
object.to_s
Expand All @@ -15,6 +16,10 @@ def is_anonymous
object.anonymous?
end

def is_completed
object.completed?
end

def is_current_round
object == Rails.configuration.current_round
end
Expand Down
2 changes: 1 addition & 1 deletion app/serializers/voting_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ class VotingSerializer < ActiveModel::Serializer

embed :ids, include: true
attributes :id, :round
has_one :proposal, serializer: ProposalListSerializer
has_one :proposal, serializer: ProposalSerializer

def round
object.round.to_s
Expand Down
2 changes: 1 addition & 1 deletion config/initializers/current_round.rb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Rails.application.config.current_round = Round::One.new
Rails.application.config.current_round = Round::Two.new
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
get '/rounds' => 'rounds#index'
get '/rounds/:id' => 'rounds#show'
get '/proposals' => 'proposals#index'
get '/proposals/:id' => 'proposals#show'
get '/votes' => 'votes#index'
post '/votes' => 'votes#create'
delete '/votes/:id' => 'votes#destroy'
post '/hidden_votes' => 'hidden_votes#create'
delete '/hidden_votes/:id' => 'hidden_votes#destroy'
get '/results' => 'results#index'
end

# Ember app root
Expand Down
8 changes: 8 additions & 0 deletions test/integration/voting_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ class VotingTest < ActionDispatch::IntegrationTest

@user = users(:voter)
login_user @user

# These tests assume the current round is 1
@prev_round = Rails.configuration.current_round
Rails.configuration.current_round = Round::One.new
end

teardown do
Rails.configuration.current_round = @prev_round
end

test 'Voter votes for proposals in round 1' do
Expand Down

0 comments on commit 1f4eabf

Please sign in to comment.