design for poll participation implemented, saving works as well

This commit is contained in:
Jannik Streek 2014-03-24 19:43:52 +01:00
parent 04199837b3
commit d0a77ce6b3
18 changed files with 197 additions and 13 deletions

View file

@ -0,0 +1,5 @@
app.models.PollParticipation = Backbone.Model.extend({
url : function(){
"/poll_participations"
}
});

View file

@ -13,7 +13,8 @@ app.models.StatusMessage = app.models.Post.extend({
status_message : _.clone(this.attributes),
aspect_ids : this.get("aspect_ids"),
photos : this.photos && this.photos.pluck("id"),
services : this.get("services")
services : this.get("services"),
poll : this.get("poll")
}
}
});

View file

@ -0,0 +1,50 @@
app.views.Poll = app.views.Base.extend({
templateName : "poll",
events : {
"click .submit" : "vote"
},
initialize : function(options) {
this.poll = this.model.attributes.poll;
this.progressBarFactor = 3;
//this.model.bind('remove', this.remove, this);
},
postRenderTemplate : function() {
if(this.poll) {
this.setProgressBar();
}
},
setProgressBar : function() {
var answers = this.poll.poll_answers;
for(index = 0; index < answers.length; ++index) {
var percentage = 0;
if(this.poll.participation_count != 0) {
percentage = answers[index].vote_count / this.poll.participation_count * 100;
}
var input = this.$("input[value="+answers[index].id+"]");
var progressBar = $(input).parent().find(".poll_progress_bar");
var width = percentage * this.progressBarFactor;
progressBar.css("width", width + "px");
}
//
},
vote : function(evt){
var result = parseInt($(evt.target).parent().find("input[name=vote]:checked").val());
var pollParticipation = new app.models.PollParticipation();
pollParticipation.save({
"poll_answer_id" : result,
"poll_id" : this.poll.poll_id,
},{
url : "/posts/"+this.poll.post_id+"/poll_participations",
success : function() {
console.log(success);
//todo remove radios+input
}
});
}
});

View file

@ -192,7 +192,7 @@ app.views.Publisher = Backbone.View.extend({
var clone = this.el_poll_answer.clone();
var answer = clone.find('.poll_answer_input');
//answer.attr("name", "poll_answer_" + this.option_counter);
answer.val("");
var placeholder = answer.attr("placeholder");
var expression = /[^0-9]+/;

View file

@ -9,6 +9,7 @@ app.views.StreamPost = app.views.Post.extend({
".post-content" : "postContentView",
".oembed" : "oEmbedView",
".opengraph" : "openGraphView",
".poll" : "pollView",
".status-message-location" : "postLocationStreamView"
},
@ -31,6 +32,7 @@ app.views.StreamPost = app.views.Post.extend({
this.commentStreamView = new app.views.CommentStream({model : this.model});
this.oEmbedView = new app.views.OEmbed({model : this.model});
this.openGraphView = new app.views.OpenGraph({model : this.model});
this.pollView = new app.views.Poll({model : this.model});
},

View file

@ -10,6 +10,7 @@
@import 'header'
@import 'footer'
@import 'opengraph'
@import 'poll'
@import 'help'
@import 'profile'
@import 'publisher_blueprint'

View file

@ -0,0 +1,43 @@
.poll_form {
display: block;
margin: 10px 0px 10px 0px;
border-top: solid 1px $border-grey;
border-bottom: solid 1px $border-grey;
padding: 10px 0px 5px 0px;
overflow: hidden;
width: 100%;
}
.poll_form input[type="radio"] {
display:inline !important;
}
.poll_result {
width:100%px;
display:inline;
}
.poll_progress_bar {
position:absolute;
width:100px;
height:15px;
top:-10px;
z-index:-1;
background-color:#3f8fba;
}
.poll_statistic{
float:right;
}
.poll_progress_bar_wrapper {
position: relative;
width: 0;
height: 0;
display:inline-block;
}
.poll_answer_entry{
display:inline;
width:100%;
}

View file

@ -0,0 +1,19 @@
{{#if poll}}
<div class="poll_form">
<p class="poll_statistic">{{t "poll.result" votes=poll.participation_count}}</p>
<strong>{{poll.question}}</strong><br/>
{{#poll.poll_answers}}
<div class="poll_answer_entry">
<input type="radio" name="vote" value="{{id}}"/>
<div class="poll_result">
<div class="poll_progress_bar_wrapper">
<div class="poll_progress_bar"> </div>
</div>
{{answer}}
</div>
</div>
<br/>
{{/poll.poll_answers}}
<input type="submit" class="button submit" style="float:right;" value="{{t "poll.vote"}}"/>
</div>
{{/if}}

View file

@ -18,4 +18,5 @@
{{{text}}}
<div class="oembed"></div>
<div class="opengraph"></div>
<div class="poll"></div>
</div>

View file

@ -0,0 +1,30 @@
class PollParticipationsController < ApplicationController
include ApplicationHelper
before_filter :authenticate_user!
def create
answer = PollAnswer.find(params[:poll_answer_id])
poll_participation = current_user.participate_in_poll!(target, answer) if target rescue ActiveRecord::RecordInvalid
if poll_participation
respond_to do |format|
format.html { redirect_to :back }
format.mobile { redirect_to stream_path }
format.json { render :nothing => true, :status => 201 }
end
else
respond_to do |format|
format.html { redirect_to :back }
format.mobile { redirect_to stream_path }
format.json { render :nothing => true, :status => 403 }
end
end
end
private
def target
@target ||= if params[:post_id]
current_user.find_visible_shareable_by_id(Post, params[:post_id]) || raise(ActiveRecord::RecordNotFound.new)
end
end
end

View file

@ -49,16 +49,18 @@ class StatusMessagesController < ApplicationController
@status_message = current_user.build_post(:status_message, params[:status_message])
@status_message.build_location(:address => params[:location_address], :coordinates => params[:location_coords]) if params[:location_address].present?
@status_message.build_poll(:question => params[:poll_question]) if params[:poll_question].present?
poll_answers = params[:poll_answers]
if params[:poll_answers].instance_of? String
poll_answers = [params[:poll_answers]]
end
poll_answers.each do |poll_answer|
@status_message.poll.poll_answers.build(:answer => poll_answer)
if params[:poll_question].present?
@status_message.build_poll(:question => params[:poll_question])
poll_answers = params[:poll_answers]
if params[:poll_answers].instance_of? String
poll_answers = [params[:poll_answers]]
end
poll_answers.each do |poll_answer|
@status_message.poll.poll_answers.build(:answer => poll_answer)
end
end
@status_message.attach_photos_by_ids(params[:photos])
if @status_message.save
@ -88,7 +90,7 @@ class StatusMessagesController < ApplicationController
respond_to do |format|
format.html { redirect_to :back }
format.mobile { redirect_to stream_path }
format.json { render {:nothing => true} , :status => 403 }
format.json { render :nothing => true, :status => 403 }
end
end
end

View file

@ -14,8 +14,26 @@ class Poll < ActiveRecord::Base
validate :enough_poll_answers
#TODO check if user has the right to vote
self.include_root_in_json = false
def enough_poll_answers
errors.add(:poll_answers, I18n.t("activerecord.errors.models.poll.attributes.poll_answers.not_enough_poll_answers")) if poll_answers.size < 2
end
def as_json(options={})
{
:poll_id => self.id,
:post_id => self.status_message.id,
:question => self.question,
:poll_answers => self.poll_answers,
:participation_count => self.participation_count
#TODO already participated?
}
end
def participation_count
poll_answers.sum("vote_count")
end
end

View file

@ -8,6 +8,8 @@ class PollAnswer < ActiveRecord::Base
xml_attr :answer
self.include_root_in_json = false
def update_vote_counter
self.vote_count = self.vote_count + 1
self.save!

View file

@ -72,6 +72,9 @@ class Post < ActiveRecord::Base
def address
end
def poll
end
def self.excluding_blocks(user)
people = user.blocks.map{|b| b.person_id}
scope = scoped

View file

@ -35,6 +35,7 @@ class PostPresenter
:root => root,
:title => title,
:address => @post.address,
:poll => @post.poll,
:interactions => {
:likes => [user_like].compact,

View file

@ -172,3 +172,7 @@ en:
reshared: "Reshared"
comment: "Comment"
home: "HOME"
poll:
vote: "Vote"
result: "<%=votes%> votes so far"

View file

@ -31,11 +31,15 @@ Diaspora::Application.routes.draw do
get :interactions
end
resources :poll_participations, :only => [:create]
resources :likes, :only => [:create, :destroy, :index ]
resources :participations, :only => [:create, :destroy, :index]
resources :comments, :only => [:new, :create, :destroy, :index]
end
get 'p/:id' => 'posts#show', :as => 'short_post'
get 'posts/:id/iframe' => 'posts#iframe', :as => 'iframe'

View file

@ -11,8 +11,6 @@ module Federated
FEDERATION_LOGGER.info("user:#{@user.id} dispatching #{relayable.class}:#{relayable.guid}")
Postzord::Dispatcher.defer_build_and_post(@user, relayable)
relayable
else
false
end
end