diff --git a/app/assets/javascripts/app/views/publisher_view.js b/app/assets/javascripts/app/views/publisher_view.js index 791992ef2b9094ae58f0e3a9353e95e5f8ccbd9f..10f01896bf5f471df3f8dab91999b09aefb6bb09 100644 --- a/app/assets/javascripts/app/views/publisher_view.js +++ b/app/assets/javascripts/app/views/publisher_view.js @@ -183,8 +183,8 @@ app.views.Publisher = Backbone.View.extend({ addPollAnswer: function(){ var clone = this.el_poll_answer.clone(); - var count_of_answers = this.el_poll_answer.size()+1; - clone.attr("name", "poll_answer_"+count_of_answers) + var count_of_answers = $('.poll_answer_input').size()+1; + clone.children('.poll_answer_input').attr("name", "poll_answer_"+count_of_answers); this.el_poll_answer.last().after(clone); }, diff --git a/app/assets/stylesheets/publisher_blueprint.css.scss b/app/assets/stylesheets/publisher_blueprint.css.scss index 68a6f617f63e4f6242d17b84000635cf1a2cb6f6..8799176605949a3a149735256875b90c5f4ce03e 100644 --- a/app/assets/stylesheets/publisher_blueprint.css.scss +++ b/app/assets/stylesheets/publisher_blueprint.css.scss @@ -322,12 +322,10 @@ #poll_creator_wrapper { display:none; + border: 1px solid $border-dark-grey; + padding:5px; } .remove_poll_answer { - display:inline-block; + display:inline; } - -.poll_answer_input { - display:inline-block !important; -} \ No newline at end of file diff --git a/app/models/poll.rb b/app/models/poll.rb index 15d770cc45efeed719369ffbf617e91df852e6fb..896908b5005545d8339e0886512995ca7fbdcfc8 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -1,7 +1,15 @@ class Poll < ActiveRecord::Base - attr_accessible :question - + include Diaspora::Federated::Base + include Diaspora::Guid + attr_accessible :question, :poll_answers belongs_to :status_message - belongs_to :author, :class_name => :person, :foreign_key => :author_id - #has_many :poll_answers + has_many :poll_answers + has_many :poll_participations + + delegate :author, :author_id, :subscribers, to: :status_message + + #forward subscribers request to status message, because a poll is just attached to a status message and is not sharable itself + #def subscribers(user) + # status_message.subscribers(user) + #end end diff --git a/app/models/poll_answer.rb b/app/models/poll_answer.rb new file mode 100644 index 0000000000000000000000000000000000000000..7893a8b25bd2f22ef528327aaf7dfdcbb6fd4da8 --- /dev/null +++ b/app/models/poll_answer.rb @@ -0,0 +1,10 @@ +class PollAnswer < ActiveRecord::Base + + include Diaspora::Federated::Base + include Diaspora::Guid + + belongs_to :poll + has_many :poll_participations + + xml_attr :answer +end diff --git a/app/models/poll_participation.rb b/app/models/poll_participation.rb new file mode 100644 index 0000000000000000000000000000000000000000..a5990f12e56442b50a424ecfac7ae7e511e9806f --- /dev/null +++ b/app/models/poll_participation.rb @@ -0,0 +1,55 @@ +class PollParticipation < ActiveRecord::Base + + include Diaspora::Federated::Base + + include Diaspora::Guid + include Diaspora::Relayable + belongs_to :poll + belongs_to :poll_answer + belongs_to :author, :class_name => 'Person', :foreign_key => :author_id + xml_attr :diaspora_handle + xml_attr :poll_answer_guid + + def parent_class + Poll + end + + def parent + self.poll + end + + def poll_answer_guid + poll_answer.guid + end + + def poll_answer_guid= new_poll_answer_guid + self.poll_answer = PollAnswer.where(:guid => new_poll_answer_guid).first + end + + def parent= parent + self.poll = parent + end + + def diaspora_handle + self.author.diaspora_handle + end + + def diaspora_handle= nh + self.author = Webfinger.new(nh).fetch + end + + class Generator < Federated::Generator + def self.federated_class + PollParticipation + end + + def initialize(person, target, poll_answer) + @poll_answer = poll_answer + super(person, target) + end + + def relayable_options + {:poll => @target.poll, :poll_answer => @poll_answer} + end + end +end diff --git a/app/models/status_message.rb b/app/models/status_message.rb index 352e646b2d4a03395933b53f6a7552497d86a07e..aa79c69f7624b951139e4a28d778c3d070f79126 100644 --- a/app/models/status_message.rb +++ b/app/models/status_message.rb @@ -20,6 +20,7 @@ class StatusMessage < Post xml_attr :raw_message xml_attr :photos, :as => [Photo] xml_attr :location, :as => Location + xml_attr :poll, :as => Poll has_many :photos, :dependent => :destroy, :foreign_key => :status_message_guid, :primary_key => :guid diff --git a/app/models/user/social_actions.rb b/app/models/user/social_actions.rb index 6bb547f40e38aec49d8f010824dcfcc2260bdb84..ccc30b4841a8cee0394e24ab4901b901f3ddb93d 100644 --- a/app/models/user/social_actions.rb +++ b/app/models/user/social_actions.rb @@ -13,6 +13,11 @@ module User::SocialActions Like::Generator.new(self, target).create!(opts) end + def participate_in_poll!(target, answer, opts={}) + find_or_create_participation!(target) + PollParticipation::Generator.new(self, target, answer).create!(opts) + end + def reshare!(target, opts={}) find_or_create_participation!(target) reshare = build_post(:reshare, :root_guid => target.guid) diff --git a/app/views/publisher/_publisher_blueprint.html.haml b/app/views/publisher/_publisher_blueprint.html.haml index 0d4357cc00c2b3d93d6fea55183a1434b203dc98..b5eb1936f9a96b61bfa9ddba40027328a97fb100 100644 --- a/app/views/publisher/_publisher_blueprint.html.haml +++ b/app/views/publisher/_publisher_blueprint.html.haml @@ -36,14 +36,14 @@ = image_tag 'icons/camera.png', :alt => t('shared.publisher.upload_photos').titleize, :class => 'publisher_image' = hidden_field :location, :coords #location_container + %br #poll_creator_wrapper = 'Poll creation' %br - %br - %input{:id => 'poll_question', :placeholder => 'Question', :name => 'poll_question'} - %div{:class => 'poll_answer'} - %input{:class => 'poll_answer_input', :placeholder => 'Answer', :name => 'poll_answer_1'} - %a{:class => 'remove_poll_answer'} + %input{:id => 'poll_question', :placeholder => 'Question', :name => 'poll_question', :class => 'span-12'} + %div{:class => 'poll_answer span-12'} + %input{:class => 'poll_answer_input span-8', :placeholder => 'Answer', :name => 'poll_answer_1'} + %a{:class => 'remove_poll_answer span-3'} = t('shared.publisher.poll.remove_poll_answer') %div{:id => 'add_poll_answer', :class => 'button creation'} = t('shared.publisher.poll.add_poll_answer') diff --git a/db/migrate/20140308154022_create_polls.rb b/db/migrate/20140308154022_create_polls.rb index 4fd4479745e359a333f9d55db3f53b327e66e020..52188cdc655d1e6e555e769fd301ea6382b28f2c 100644 --- a/db/migrate/20140308154022_create_polls.rb +++ b/db/migrate/20140308154022_create_polls.rb @@ -4,6 +4,7 @@ class CreatePolls < ActiveRecord::Migration t.string :question, :null => false t.belongs_to :status_message, :null => false t.boolean :status + t.string :guid t.timestamps end add_index :polls, :status_message_id @@ -11,6 +12,7 @@ class CreatePolls < ActiveRecord::Migration create_table :poll_answers do |t| t.string :answer, :null => false t.belongs_to :poll, :null => false + t.string :guid end add_index :poll_answers, :poll_id @@ -18,7 +20,9 @@ class CreatePolls < ActiveRecord::Migration t.belongs_to :poll_answer, :null => false t.belongs_to :author, :null => false t.belongs_to :poll, :null => false - t.datetime :time + t.string :guid + t.text :author_signature + t.text :parent_author_signature t.timestamps end diff --git a/db/schema.rb b/db/schema.rb index fe5a33e0482d1f956e31b1f36bb6e26188d7c89a..91253852f12faecece65dae13f512756bfa4e2de 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -286,17 +286,20 @@ ActiveRecord::Schema.define(:version => 20140308154022) do create_table "poll_answers", :force => true do |t| t.string "answer", :null => false t.integer "poll_id", :null => false + t.string "guid" end add_index "poll_answers", ["poll_id"], :name => "index_poll_answers_on_poll_id" create_table "poll_participations", :force => true do |t| - t.integer "poll_answer_id", :null => false - t.integer "author_id", :null => false - t.integer "poll_id", :null => false - t.datetime "time" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.integer "poll_answer_id", :null => false + t.integer "author_id", :null => false + t.integer "poll_id", :null => false + t.string "guid" + t.text "author_signature" + t.text "parent_author_signature" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end add_index "poll_participations", ["poll_id"], :name => "index_poll_participations_on_poll_id" @@ -305,6 +308,7 @@ ActiveRecord::Schema.define(:version => 20140308154022) do t.string "question", :null => false t.integer "status_message_id", :null => false t.boolean "status" + t.string "guid" t.datetime "created_at", :null => false t.datetime "updated_at", :null => false end diff --git a/lib/diaspora/parser.rb b/lib/diaspora/parser.rb index 1d2c5009248908d48388bf3e974c339cb9cee4b4..5665d74afd892d0b58df271f17f3f20fc199b456 100644 --- a/lib/diaspora/parser.rb +++ b/lib/diaspora/parser.rb @@ -5,6 +5,7 @@ module Diaspora module Parser def self.from_xml(xml) + puts xml doc = Nokogiri::XML(xml) { |cfg| cfg.noblanks } return unless body = doc.xpath("/XML/post").children.first class_name = body.name.gsub('-', '/') diff --git a/spec/models/poll_answer_spec.rb b/spec/models/poll_answer_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..b49465034e697803f2f877b7bf9576e9562d3166 --- /dev/null +++ b/spec/models/poll_answer_spec.rb @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe PollAnswer do +before :do + describe 'validation' do + it 'should ...' do + + end + end +end \ No newline at end of file diff --git a/spec/models/poll_participation_spec.rb b/spec/models/poll_participation_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..ee25b378a65eda281a3fd9a276a0fec691ec2f3e --- /dev/null +++ b/spec/models/poll_participation_spec.rb @@ -0,0 +1,78 @@ +require 'spec_helper' +require Rails.root.join("spec", "shared_behaviors", "relayable") + +describe PollParticipation do + + before do + @alices_aspect = alice.aspects.first + @status = bob.post(:status_message, :text => "hello", :to => bob.aspects.first.id) + end + + describe 'xml' do + before do + @poll_participant = FactoryGirl.create(:user) + @poll_participant_aspect = @poll_participant.aspects.create(:name => "bruisers") + connect_users(alice, @alices_aspect, @poll_participant, @poll_participant_aspect) + @poll = Poll.new(:question => "hi") + @poll.poll_answers.build(:answer => "a") + @poll.poll_answers.build(:answer => "b") + @post = alice.post :status_message, :text => "hello", :to => @alices_aspect.id + @post.poll = @poll + @poll_participation = @poll_participant.participate_in_poll!(@post, @poll.poll_answers.first) + @xml = @poll_participation.to_xml.to_s + end + + it 'serializes the sender handle' do + @xml.include?(@poll_participation.diaspora_handle).should be_true + end + + it 'serializes the poll_guid' do + @xml.should include(@poll.guid) + end + + it 'serializes the poll_answer_guid' do + @xml.should include(@poll_participation.poll_answer.guid) + end + + describe 'marshalling' do + before do + @marshalled_poll_participation = PollParticipation.from_xml(@xml) + end + + it 'marshals the author' do + @marshalled_poll_participation.author.should == @poll_participant.person + end + + it 'marshals the answer' do + @marshalled_poll_participation.poll_answer.should == @poll_participation.poll_answer + end + + it 'marshals the poll' do + @marshalled_poll_participation.poll.should == @poll + end + end + end + + # describe 'it is relayable' do + # before do + # @poll = Poll.new + # @poll_answer = PollAnswer.new(:answer => '1') + # @poll_answer2 = PollAnswer.new(:answer => '1') + # @poll.answers << [poll_answer, poll_answer2] + # @status.poll = @poll + + # @local_luke, @local_leia, @remote_raphael = set_up_friends + # @remote_parent = FactoryGirl.build(:status_message, :author => @remote_raphael) + # @local_parent = @local_luke.post :status_message, :text => "hi", :to => @local_luke.aspects.first + + # @object_by_parent_author = @local_luke.vote!(@local_parent, @poll_answer) + # @object_by_recipient = @local_leia.vote!(@local_parent, @poll_answer) + # @dup_object_by_parent_author = @object_by_parent_author.dup + + # @object_on_remote_parent = @local_luke.comment!(@remote_parent, "Yeah, it was great") + # end + + # let(:build_object) { alice.build_poll_participation(:poll => @poll, :poll_answer => @poll_answer) } + # it_should_behave_like 'it is relayable' + # end +end diff --git a/spec/models/poll_spec.rb b/spec/models/poll_spec.rb index 8f2cabf75796f108ed698211b5bd29ccca6e9be1..ab5641fc7b5d713170f75132a7690234a735fbb2 100644 --- a/spec/models/poll_spec.rb +++ b/spec/models/poll_spec.rb @@ -1,5 +1,22 @@ require 'spec_helper' describe Poll do - pending "add some examples to (or delete) #{__FILE__}" -end + before do + @poll = Poll.new(:question => "What do you think about apples?") + end + + describe 'validation' do + it 'should create no poll when it has less than two answers' do + @poll.poll_answers << PollAnswer.new(:answer => '1') + @poll.should_not be_valid + end + + it 'should create a poll when it has more than two answers' do + @poll.poll_answers << PollAnswer.new(:answer => '1') + @poll.poll_answers << PollAnswer.new(:answer => '2') + @poll.should be_valid + end + end + + #TODO test if delegation of subscribers works +end \ No newline at end of file diff --git a/spec/models/status_message_spec.rb b/spec/models/status_message_spec.rb index 7ee8b4bc5ca2aeb58312daf5f8a3585659d614ac..c68a821476f173f7b08f1afd60c0323503e89120 100644 --- a/spec/models/status_message_spec.rb +++ b/spec/models/status_message_spec.rb @@ -350,6 +350,31 @@ STR end end end + + context 'with a poll' do + before do + @message.poll = Poll.new(coordinates: "1, 2").tap(&:save) + @xml = @message.to_xml.to_s + end + + it 'serializes the location' do + @xml.should include "location" + @xml.should include "lat" + @xml.should include "lng" + end + + describe ".from_xml" do + before do + @marshalled = StatusMessage.from_xml(@xml) + end + + it 'marshals the location' do + @marshalled.location.should be_present + end + end + end + + end describe '#after_dispatch' do diff --git a/spec/models/user/social_actions_spec.rb b/spec/models/user/social_actions_spec.rb index 33c99e6756e6642df91f31eaa734e7da80b417b0..6ab83e4c566cb4e6143ea3a379ec16c8ed400992 100644 --- a/spec/models/user/social_actions_spec.rb +++ b/spec/models/user/social_actions_spec.rb @@ -83,4 +83,14 @@ describe User::SocialActions do @status.reload.likes.should == likes end end + + describe 'User#participate_in_poll!' do + before do + @bobs_aspect = bob.aspects.where(:name => "generic").first + poll = Poll.new(:poll_answers => [PollAnswer.new(:answer => "1"), PollAnswer.new(:answer => "2")]) + @status = bob.post(:status_message, :text => "hello", :to => @bobs_aspect.id, :poll => poll) + end + it "sets the poll answer id" do + alice.participate_in_poll!(@status, 1).poll_answer.answer.should == "1" + end end \ No newline at end of file