Allow user to enable / disable notifications for a post from stream #5350

This commit is contained in:
Marco Colli 2014-12-29 13:30:58 +01:00
parent ccd7561072
commit eccab62e32
14 changed files with 165 additions and 6 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -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,22 @@ app.views.StreamPost = app.views.Post.extend({
});
},
createParticipation: function (evt) {
that = this;
$.post("/posts/" + this.model.get("id") + "/participation", {}, function () {
that.model.set({participation: true});
that.render();
});
},
destroyParticipation: function (evt) {
that = this;
$.post("/posts/" + this.model.get("id") + "/participation", { _method: "delete" }, function () {
that.model.set({participation: false});
that.render();
});
},
focusCommentTextarea: function(evt){
evt.preventDefault();
this.$(".new_comment_form_wrapper").removeClass("hidden");

View file

@ -279,6 +279,22 @@ ul.as-selections {
width: 14px;
}
}
.create_participation {
display: inline-block;
.icons-create-participation {
height: 14px;
width: 14px;
background: image-url("icons/create_participation.png") center;
}
}
.destroy_participation {
display: inline-block;
.icons-destroy-participation {
height: 14px;
width: 14px;
background: image-url("icons/destroy_participation.png") center;
}
}
.delete {
display: inline-block;
.icons-deletelabel {

View file

@ -16,6 +16,15 @@
<a href="#" rel="nofollow" class="block_user" title="{{t "ignore"}}">
<div class="icons-ignoreuser control_icon"></div>
</a>
{{#if participation}}
<a href="#" rel="nofollow" class="destroy_participation" title="{{t "stream.disable_post_notifications"}}">
<div class="icons-destroy-participation control_icon"></div>
</a>
{{else}}
<a href="#" rel="nofollow" class="create_participation" title="{{t "stream.enable_post_notifications"}}">
<div class="icons-create-participation control_icon"></div>
</a>
{{/if}}
<a href="#" rel="nofollow" class="delete hide_post" title="{{t "stream.hide"}}">
<div class="icons-deletelabel delete control_icon"/>
</a>

View file

@ -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 => :no_content
else
render :nothing => true, :status => :unprocessable_entity
end
end
end

View file

@ -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

View file

@ -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

View file

@ -162,6 +162,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:

View file

@ -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

View file

@ -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

View file

@ -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