diff --git a/Changelog.md b/Changelog.md index c0aba9a85..1a7c2d134 100644 --- a/Changelog.md +++ b/Changelog.md @@ -177,6 +177,7 @@ diaspora.yml file**. The existing settings from 0.4.x and before will not work a * Give admins the ability to lock & unlock accounts [#5643](https://github.com/diaspora/diaspora/pull/5643) * Add reshares to the stream view immediately [#5699](https://github.com/diaspora/diaspora/pull/5699) * Start help section for the chat [#5665](https://github.com/diaspora/diaspora/pull/5665) +* Expose participation controls in the stream view [#5511](https://github.com/diaspora/diaspora/pull/5511) # 0.4.1.2 diff --git a/app/assets/images/icons-s71323e8d98.png b/app/assets/images/icons-s71323e8d98.png deleted file mode 100644 index 026503b9a..000000000 Binary files a/app/assets/images/icons-s71323e8d98.png and /dev/null differ diff --git a/app/assets/images/icons-sbcb16d92c7.png b/app/assets/images/icons-sbcb16d92c7.png new file mode 100644 index 000000000..8ddc17847 Binary files /dev/null and b/app/assets/images/icons-sbcb16d92c7.png differ diff --git a/app/assets/images/icons/create_participation.png b/app/assets/images/icons/create_participation.png new file mode 100644 index 000000000..7496495b9 Binary files /dev/null and b/app/assets/images/icons/create_participation.png differ diff --git a/app/assets/images/icons/destroy_participation.png b/app/assets/images/icons/destroy_participation.png new file mode 100644 index 000000000..f13d187a6 Binary files /dev/null and b/app/assets/images/icons/destroy_participation.png differ diff --git a/app/assets/javascripts/app/views/stream_post_views.js b/app/assets/javascripts/app/views/stream_post_views.js index da34f8bd8..5a317bdd4 100644 --- a/app/assets/javascripts/app/views/stream_post_views.js +++ b/app/assets/javascripts/app/views/stream_post_views.js @@ -23,10 +23,13 @@ app.views.StreamPost = app.views.Post.extend({ "click .remove_post": "destroyModel", "click .hide_post": "hidePost", "click .post_report": "report", - "click .block_user": "blockUser" + "click .block_user": "blockUser", + + "click .create_participation": "createParticipation", + "click .destroy_participation": "destroyParticipation" }, - tooltipSelector : ".timeago, .post_scope, .block_user, .delete", + tooltipSelector : ".timeago, .post_scope, .block_user, .delete, .create_participation, .destroy_participation", initialize : function(){ var personId = this.model.get('author').id; @@ -113,6 +116,24 @@ app.views.StreamPost = app.views.Post.extend({ }); }, + createParticipation: function (evt) { + if(evt) { evt.preventDefault(); } + that = this; + $.post(Routes.post_participation_path(this.model.get("id")), {}, function () { + that.model.set({participation: true}); + that.render(); + }); + }, + + destroyParticipation: function (evt) { + if(evt) { evt.preventDefault(); } + that = this; + $.post(Routes.post_participation_path(this.model.get("id")), { _method: "delete" }, function () { + that.model.set({participation: false}); + that.render(); + }); + }, + focusCommentTextarea: function(evt){ evt.preventDefault(); this.$(".new_comment_form_wrapper").removeClass("hidden"); diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss index a3e81c602..65f0771cd 100644 --- a/app/assets/stylesheets/application.css.scss +++ b/app/assets/stylesheets/application.css.scss @@ -279,6 +279,20 @@ ul.as-selections { width: 14px; } } + .create_participation { + display: inline-block; + .icons-create_participation { + height: 14px; + width: 14px; + } + } + .destroy_participation { + display: inline-block; + .icons-destroy_participation { + height: 14px; + width: 14px; + } + } .delete { display: inline-block; .icons-deletelabel { diff --git a/app/assets/templates/stream-element_tpl.jst.hbs b/app/assets/templates/stream-element_tpl.jst.hbs index 9a6952808..4ed0daeb9 100644 --- a/app/assets/templates/stream-element_tpl.jst.hbs +++ b/app/assets/templates/stream-element_tpl.jst.hbs @@ -16,6 +16,15 @@
+ {{#if participation}} + +
+
+ {{else}} + +
+
+ {{/if}}
@@ -26,7 +35,7 @@ {{/unless}}
{{/if}} - +
{{#with author}} {{name}} diff --git a/app/controllers/participations_controller.rb b/app/controllers/participations_controller.rb new file mode 100644 index 000000000..95e8a2c03 --- /dev/null +++ b/app/controllers/participations_controller.rb @@ -0,0 +1,23 @@ +class ParticipationsController < ApplicationController + before_action :authenticate_user! + + def create + post = current_user.find_visible_shareable_by_id(Post, params[:post_id]) + if post + current_user.participate! post + render nothing: true, status: :created + else + render nothing: true, status: :forbidden + end + end + + def destroy + participation = current_user.participations.find_by target_id: params[:post_id] + if participation + participation.destroy + render nothing: true, status: :ok + else + render nothing: true, status: :unprocessable_entity + end + end +end diff --git a/app/models/comment.rb b/app/models/comment.rb index b71fcaa22..aa86daedb 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -60,7 +60,7 @@ class Comment < ActiveRecord::Base def notification_type(user, person) if self.post.author == user.person return Notifications::CommentOnPost - elsif self.post.comments.where(:author_id => user.person.id) != [] && self.author_id != user.person.id + elsif user.participations.where(:target_id => self.post).exists? && self.author_id != user.person.id return Notifications::AlsoCommented else return false diff --git a/app/presenters/post_presenter.rb b/app/presenters/post_presenter.rb index ff3877bf7..766961e96 100644 --- a/app/presenters/post_presenter.rb +++ b/app/presenters/post_presenter.rb @@ -41,13 +41,14 @@ class PostPresenter :address => @post.address, :poll => @post.poll(), :already_participated_in_poll => already_participated_in_poll, + :participation => participate?, :interactions => { :likes => [user_like].compact, :reshares => [user_reshare].compact, :comments_count => @post.comments_count, :likes_count => @post.likes_count, - :reshares_count => @post.reshares_count, + :reshares_count => @post.reshares_count } } end @@ -86,6 +87,10 @@ class PostPresenter end end + def participate? + user_signed_in? && @current_user.participations.where(:target_id => @post).exists? + end + end class PostInteractionPresenter diff --git a/config/locales/javascript/javascript.en.yml b/config/locales/javascript/javascript.en.yml index 09f19b739..03d7e5337 100644 --- a/config/locales/javascript/javascript.en.yml +++ b/config/locales/javascript/javascript.en.yml @@ -166,6 +166,8 @@ en: hide_nsfw_posts: "Hide #nsfw posts" follow: "Follow" unfollow: "Unfollow" + enable_post_notifications: "Enable notifications for this post" + disable_post_notifications: "Disable notifications for this post" via: "via <%= provider %>" likes: diff --git a/config/routes.rb b/config/routes.rb index 8eed61639..e31d8409d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -36,7 +36,7 @@ Diaspora::Application.routes.draw do resources :poll_participations, :only => [:create] resources :likes, :only => [:create, :destroy, :index ] - resources :participations, :only => [:create, :destroy, :index] + resource :participation, :only => [:create, :destroy] resources :comments, :only => [:new, :create, :destroy, :index] end diff --git a/spec/controllers/participations_controller_spec.rb b/spec/controllers/participations_controller_spec.rb new file mode 100644 index 000000000..f9de58b39 --- /dev/null +++ b/spec/controllers/participations_controller_spec.rb @@ -0,0 +1,79 @@ +require 'spec_helper' + +describe ParticipationsController, :type => :controller do + before do + allow(@controller).to receive(:current_user).and_return(alice) + sign_in :user, alice + end + + describe '#create' do + let(:stranger) { FactoryGirl.create(:user) } + + shared_examples 'on a visible post' do + it 'creates the participation' do + post :create, post_id: @post.id + expect(alice.participations.where(:target_id => @post.id)).to exist + expect(response.code).to eq('201') + end + end + + context 'on my own post' do + before do + aspect_to_post = alice.aspects.where(:name => 'generic').first + @post = alice.post :status_message, :text => 'something', :to => aspect_to_post + end + + it_behaves_like 'on a visible post' + end + + context 'on a post from a contact' do + before do + aspect_to_post = bob.aspects.where(:name => 'generic').first + @post = bob.post :status_message, :text => 'something', :to => aspect_to_post + end + + it_behaves_like 'on a visible post' + end + + context 'on a public post from a stranger' do + before do + @post = stranger.post :status_message, :text => 'something', :public => true, :to => 'all' + end + + it_behaves_like 'on a visible post' + end + + context 'on a non visible post' do + before do + @post = stranger.post :status_message, :text => 'something', :public => false, :to => 'all' + end + + it 'should not create the participation' do + post :create, post_id: @post.id + expect(alice.participations.where(:target_id => @post.id)).not_to exist + expect(response.code).to eq('403') + end + end + end + + describe '#destroy' do + let(:post) { FactoryGirl.create(:status_message) } + + context 'on a post you partecipate to' do + before { alice.participate! post } + + it 'should remove participation' do + delete :destroy, post_id: post.id + expect(alice.participations.where(:target_id => post.id)).not_to exist + expect(response.code).to eq('204') + end + end + + context 'on a post you do not partecipate to' do + it 'says it is an unprocessable request' do + delete :destroy, post_id: post.id + expect(response.code).to eq('422') + end + end + end +end diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb index efc7eacdc..2e2a91205 100644 --- a/spec/models/comment_spec.rb +++ b/spec/models/comment_spec.rb @@ -12,11 +12,17 @@ describe Comment, :type => :model do end describe 'comment#notification_type' do + let (:comment) { alice.comment!(@status, "why so formal?") } + it "returns 'comment_on_post' if the comment is on a post you own" do - comment = alice.comment!(@status, "why so formal?") expect(comment.notification_type(bob, alice.person)).to eq(Notifications::CommentOnPost) end + it "returns 'also_commented' if the comment is on a post you participate to" do + eve.participate! @status + expect(comment.notification_type(eve, alice.person)).to eq(Notifications::AlsoCommented) + end + it 'returns false if the comment is not on a post you own and no one "also_commented"' do comment = alice.comment!(@status, "I simply felt like issuing a greeting. Do step off.") expect(comment.notification_type(eve, alice.person)).to be false