Move post controls to a separate view

This commit is contained in:
Steffen van Bergerem 2016-08-30 16:21:10 +02:00 committed by Dennis Schubert
parent 68045cec8c
commit 8faedd574d
No known key found for this signature in database
GPG key ID: 5A0304BEA7966D7E
5 changed files with 317 additions and 100 deletions

View file

@ -0,0 +1,78 @@
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
app.views.PostControls = app.views.Base.extend({
templateName: "post-controls",
className: "control-icons",
events: {
"click .remove_post": "destroyModel",
"click .hide_post": "hidePost",
"click .post_report": "report",
"click .block_user": "blockUser",
"click .create_participation": "createParticipation",
"click .destroy_participation": "destroyParticipation"
},
tooltipSelector: [".post_report",
".block_user",
".delete",
".create_participation",
".destroy_participation"].join(", "),
initialize: function(opts) {
this.model.bind("change", this.render, this);
this.post = opts.post;
},
presenter: function() {
return _.extend(this.defaultPresenter(), {
authorIsCurrentUser: app.currentUser.isAuthorOf(this.model)
});
},
blockUser: function(evt) {
if (evt) { evt.preventDefault(); }
if (!confirm(Diaspora.I18n.t("ignore_user"))) { return; }
this.model.blockAuthor().fail(function() {
app.flashMessages.error(Diaspora.I18n.t("ignore_failed"));
});
},
hidePost: function(evt) {
if (evt) { evt.preventDefault(); }
if (!confirm(Diaspora.I18n.t("confirm_dialog"))) { return; }
var self = this;
$.ajax({
url: Routes.shareVisibility(42),
type: "PUT",
data: {
/* eslint-disable camelcase */
post_id: this.model.id
/* eslint-enable camelcase */
}
}).done(function() {
self.post.remove();
}).fail(function() {
app.flashMessages.error(Diaspora.I18n.t("hide_post_failed"));
});
},
createParticipation: function(evt) {
if (evt) { evt.preventDefault(); }
var that = this;
$.post(Routes.postParticipation(this.model.get("id")), {}, function() {
that.model.set({participation: true});
});
},
destroyParticipation: function(evt) {
if (evt) { evt.preventDefault(); }
var that = this;
$.post(Routes.postParticipation(this.model.get("id")), {_method: "delete"}, function() {
that.model.set({participation: false});
});
}
});
// @license-end

View file

@ -6,9 +6,10 @@ app.views.StreamPost = app.views.Post.extend({
subviews : {
".feedback": "feedbackView",
".comments": "commentStreamView",
".likes": "likesInfoView",
".reshares": "resharesInfoView",
".comments" : "commentStreamView",
".post-controls": "postControlsView",
".post-content": "postContentView",
".oembed": "oEmbedView",
".opengraph": "openGraphView",
@ -19,24 +20,11 @@ app.views.StreamPost = app.views.Post.extend({
events: {
"click .focus_comment_textarea": "focusCommentTextarea",
"click .show_nsfw_post": "removeNsfwShield",
"click .toggle_nsfw_state": "toggleNsfwState",
"click .remove_post": "destroyModel",
"click .hide_post": "hidePost",
"click .post_report": "report",
"click .block_user": "blockUser",
"click .create_participation": "createParticipation",
"click .destroy_participation": "destroyParticipation"
"click .toggle_nsfw_state": "toggleNsfwState"
},
tooltipSelector : [".timeago",
".post_scope",
".post_report",
".block_user",
".delete",
".create_participation",
".destroy_participation",
".permalink"].join(", "),
initialize : function(){
@ -51,6 +39,9 @@ app.views.StreamPost = app.views.Post.extend({
this.pollView = new app.views.Poll({model : this.model});
},
postControlsView: function() {
return new app.views.PostControls({model: this.model, post: this});
},
likesInfoView : function(){
return new app.views.LikesInfo({model : this.model});
@ -87,60 +78,12 @@ app.views.StreamPost = app.views.Post.extend({
app.currentUser.toggleNsfwState();
},
blockUser: function(evt){
if(evt) { evt.preventDefault(); }
if(!confirm(Diaspora.I18n.t("ignore_user"))) { return }
this.model.blockAuthor()
.fail(function() {
app.flashMessages.error(Diaspora.I18n.t("ignore_failed"));
});
},
remove : function() {
$(this.el).slideUp(400, _.bind(function(){this.$el.remove()}, this));
app.stream.remove(this.model);
return this;
},
hidePost : function(evt) {
if(evt) { evt.preventDefault(); }
if(!confirm(Diaspora.I18n.t("confirm_dialog"))) { return }
var self = this;
$.ajax({
url : "/share_visibilities/42",
type : "PUT",
data : {
post_id : this.model.id
}
}).done(function() {
self.remove();
})
.fail(function() {
app.flashMessages.error(Diaspora.I18n.t("hide_post_failed"));
});
},
createParticipation: function (evt) {
if(evt) { evt.preventDefault(); }
var that = this;
$.post(Routes.postParticipation(this.model.get("id")), {}, function () {
that.model.set({participation: true});
that.render();
});
},
destroyParticipation: function (evt) {
if(evt) { evt.preventDefault(); }
var that = this;
$.post(Routes.postParticipation(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");
@ -148,6 +91,5 @@ app.views.StreamPost = app.views.Post.extend({
return this;
}
});
// @license-end

View file

@ -0,0 +1,24 @@
{{#if authorIsCurrentUser}}
<a href="#" rel="nofollow" class="delete remove_post" title="{{t "delete"}}">
<i class="entypo-trash"></i>
</a>
{{else}}
<a href="#" rel="nofollow" data-type="Post" class="post_report" title="{{t "report.name"}}">
<i class="entypo-warning"></i>
</a>
<a href="#" rel="nofollow" class="block_user" title="{{t "ignore"}}">
<i class="entypo-block"></i>
</a>
{{#if participation}}
<a href="#" rel="nofollow" class="destroy_participation" title="{{t "stream.disable_post_notifications"}}">
<i class="entypo-bell"></i>
</a>
{{else}}
<a href="#" rel="nofollow" class="create_participation" title="{{t "stream.enable_post_notifications"}}">
<i class="entypo-bell"></i>
</a>
{{/if}}
<a href="#" rel="nofollow" class="delete hide_post" title="{{t "stream.hide"}}">
<i class="entypo-cross"></i>
</a>
{{/if}}

View file

@ -7,34 +7,7 @@
<div class="bd">
{{#if loggedIn}}
<div class="control-icons">
{{#unless preview}}
{{#if authorIsCurrentUser}}
<a href="#" rel="nofollow" class="delete remove_post" title="{{t "delete"}}">
<i class="entypo-trash"></i>
</a>
{{else}}
<a href="#" rel="nofollow" data-type="Post" class="post_report" title="{{t "report.name"}}">
<i class="entypo-warning"></i>
</a>
<a href="#" rel="nofollow" class="block_user" title="{{t "ignore"}}">
<i class="entypo-block"></i>
</a>
{{#if participation}}
<a href="#" rel="nofollow" class="destroy_participation" title="{{t "stream.disable_post_notifications"}}">
<i class="entypo-bell"></i>
</a>
{{else}}
<a href="#" rel="nofollow" class="create_participation" title="{{t "stream.enable_post_notifications"}}">
<i class="entypo-bell"></i>
</a>
{{/if}}
<a href="#" rel="nofollow" class="delete hide_post" title="{{t "stream.hide"}}">
<i class="entypo-cross"></i>
</a>
{{/if}}
{{/unless}}
</div>
<div class="post-controls"></div>
{{/if}}
<div>

View file

@ -0,0 +1,200 @@
describe("app.views.PostControls", function() {
describe("render", function() {
beforeEach(function() {
this.model = factory.post();
this.view = new app.views.PostControls({model: this.model});
});
context("in a post of the current user", function() {
beforeEach(function() {
app.currentUser = new app.models.User(this.model.attributes.author);
this.view.render();
});
it("shows a delete button", function() {
expect(this.view.$(".delete.remove_post").length).toBe(1);
});
it("doesn't show a report button", function() {
expect(this.view.$(".post_report").length).toBe(0);
});
it("doesn't show an ignore button", function() {
expect(this.view.$(".block_user").length).toBe(0);
});
it("doesn't show participation buttons", function() {
expect(this.view.$(".create_participation").length).toBe(0);
expect(this.view.$(".destroy_participation").length).toBe(0);
});
it("doesn't show a hide button", function() {
expect(this.view.$(".delete.hide_post").length).toBe(0);
});
});
context("in a post of another user", function() {
beforeEach(function() {
this.view.render();
});
it("doesn't show a delete button", function() {
expect(this.view.$(".delete.remove_post").length).toBe(0);
});
it("shows a report button", function() {
expect(this.view.$(".post_report").length).toBe(1);
});
it("shows an ignore button", function() {
expect(this.view.$(".block_user").length).toBe(1);
});
it("shows a create participation button", function() {
expect(this.view.$(".create_participation").length).toBe(1);
expect(this.view.$(".destroy_participation").length).toBe(0);
});
it("shows a destroy participation button if the user participated", function() {
this.model.set({participation: true});
this.view.render();
expect(this.view.$(".create_participation").length).toBe(0);
expect(this.view.$(".destroy_participation").length).toBe(1);
});
it("shows a hide button", function() {
expect(this.view.$(".delete.hide_post").length).toBe(1);
});
});
});
describe("events", function() {
beforeEach(function() {
this.model = factory.post();
});
it("calls destroyModel when removing a post", function() {
spyOn(app.views.PostControls.prototype, "destroyModel");
app.currentUser = new app.models.User(this.model.attributes.author);
this.view = new app.views.PostControls({model: this.model});
this.view.render();
this.view.$(".remove_post.delete").click();
expect(app.views.PostControls.prototype.destroyModel).toHaveBeenCalled();
});
it("calls hidePost when hiding a post", function() {
spyOn(app.views.PostControls.prototype, "hidePost");
this.view = new app.views.PostControls({model: this.model});
this.view.render();
this.view.$(".hide_post.delete").click();
expect(app.views.PostControls.prototype.hidePost).toHaveBeenCalled();
});
it("calls report when reporting a post", function() {
spyOn(app.views.PostControls.prototype, "report");
this.view = new app.views.PostControls({model: this.model});
this.view.render();
this.view.$(".post_report").click();
expect(app.views.PostControls.prototype.report).toHaveBeenCalled();
});
it("calls blockUser when blocking the user", function() {
spyOn(app.views.PostControls.prototype, "blockUser");
this.view = new app.views.PostControls({model: this.model});
this.view.render();
this.view.$(".block_user").click();
expect(app.views.PostControls.prototype.blockUser).toHaveBeenCalled();
});
it("calls createParticipation when creating a participation", function() {
spyOn(app.views.PostControls.prototype, "createParticipation");
this.view = new app.views.PostControls({model: this.model});
this.view.render();
this.view.$(".create_participation").click();
expect(app.views.PostControls.prototype.createParticipation).toHaveBeenCalled();
});
it("calls destroyParticipation when destroying a participation", function() {
spyOn(app.views.PostControls.prototype, "destroyParticipation");
this.model.set({participation: true});
this.view = new app.views.PostControls({model: this.model});
this.view.render();
this.view.$(".destroy_participation").click();
expect(app.views.PostControls.prototype.destroyParticipation).toHaveBeenCalled();
});
});
describe("initialize", function() {
it("rerenders the view when the model has been changed", function() {
spyOn(app.views.PostControls.prototype, "render");
this.model = factory.post();
this.view = new app.views.PostControls({model: this.model});
expect(app.views.PostControls.prototype.render).not.toHaveBeenCalled();
this.model.trigger("change");
expect(app.views.PostControls.prototype.render).toHaveBeenCalled();
});
});
describe("blockUser", function() {
beforeEach(function() {
spyOn(window, "confirm").and.returnValue(true);
this.model = factory.post();
this.view = new app.views.PostControls({model: this.model});
this.view.render();
});
it("asks for a confirmation", function() {
this.view.blockUser();
expect(window.confirm).toHaveBeenCalledWith(Diaspora.I18n.t("ignore_user"));
});
it("calls blockAuthor", function() {
spyOn(this.model, "blockAuthor").and.callThrough();
this.view.blockUser();
expect(this.model.blockAuthor).toHaveBeenCalled();
});
it("shows a flash message when errors occur", function() {
spyOn(app.flashMessages, "error");
this.view.blockUser();
jasmine.Ajax.requests.mostRecent().respondWith({status: 422});
expect(app.flashMessages.error).toHaveBeenCalledWith(Diaspora.I18n.t("ignore_failed"));
});
});
describe("hidePost", function() {
beforeEach(function() {
spyOn(window, "confirm").and.returnValue(true);
this.postView = {remove: function() { return; }};
this.model = factory.post();
this.view = new app.views.PostControls({model: this.model, post: this.postView});
this.view.render();
});
it("asks for a confirmation", function() {
this.view.hidePost();
expect(window.confirm).toHaveBeenCalledWith(Diaspora.I18n.t("confirm_dialog"));
});
it("sends an ajax request with the correct post id", function() {
this.view.hidePost();
expect(jasmine.Ajax.requests.mostRecent().url).toBe(Routes.shareVisibility(42));
expect(jasmine.Ajax.requests.mostRecent().data().post_id).toEqual(["" + this.model.get("id")]);
expect(jasmine.Ajax.requests.mostRecent().method).toBe("PUT");
});
it("removes the post on success", function() {
spyOn(this.view.post, "remove");
this.view.hidePost();
jasmine.Ajax.requests.mostRecent().respondWith({status: 204});
expect(this.view.post.remove).toHaveBeenCalled();
});
it("shows a flash message when errors occur", function() {
spyOn(app.flashMessages, "error");
this.view.hidePost();
jasmine.Ajax.requests.mostRecent().respondWith({status: 422});
expect(app.flashMessages.error).toHaveBeenCalledWith(Diaspora.I18n.t("hide_post_failed"));
});
});
});