diff --git a/app/assets/javascripts/app/views/single-post-viewer/single_post_interaction_counts.js b/app/assets/javascripts/app/views/single-post-viewer/single_post_interaction_counts.js
index 42348627c..abc4f5d9e 100644
--- a/app/assets/javascripts/app/views/single-post-viewer/single_post_interaction_counts.js
+++ b/app/assets/javascripts/app/views/single-post-viewer/single_post_interaction_counts.js
@@ -4,8 +4,15 @@ app.views.SinglePostInteractionCounts = app.views.Base.extend({
templateName: "single-post-viewer/single-post-interaction-counts",
tooltipSelector: ".avatar.micro",
+ events: {
+ "click #show-all-likes": "showAllLikes",
+ "click #show-all-reshares": "showAllReshares"
+ },
+
initialize: function() {
this.model.interactions.on("change", this.render, this);
+ this.model.interactions.likes.on("change", this.render, this);
+ this.model.interactions.reshares.on("change", this.render, this);
},
presenter: function() {
@@ -15,8 +22,28 @@ app.views.SinglePostInteractionCounts = app.views.Base.extend({
reshares: interactions.reshares.toJSON(),
commentsCount: interactions.commentsCount(),
likesCount: interactions.likesCount(),
- resharesCount: interactions.resharesCount()
+ resharesCount: interactions.resharesCount(),
+ showMoreLikes: interactions.likes.length < interactions.likesCount(),
+ showMoreReshares: interactions.reshares.length < interactions.resharesCount()
};
+ },
+
+ _showAll: function(interactionType, models) {
+ this.$("#show-all-" + interactionType).addClass("hidden");
+ this.$("#" + interactionType + " .loader").removeClass("hidden");
+ models.fetch({success: function() {
+ models.trigger("change");
+ }});
+ },
+
+ showAllLikes: function(evt) {
+ evt.preventDefault();
+ this._showAll("likes", this.model.interactions.likes);
+ },
+
+ showAllReshares: function(evt) {
+ evt.preventDefault();
+ this._showAll("reshares", this.model.interactions.reshares);
}
});
// @license-end
diff --git a/app/assets/stylesheets/single-post-view.scss b/app/assets/stylesheets/single-post-view.scss
index 0593436d3..ceaabc4fa 100644
--- a/app/assets/stylesheets/single-post-view.scss
+++ b/app/assets/stylesheets/single-post-view.scss
@@ -157,5 +157,11 @@
.author-name:hover {
text-decoration: none;
}
+
+ .loader {
+ height: $line-height-computed;
+ vertical-align: text-bottom;
+ width: $line-height-computed;
+ }
}
}
diff --git a/app/assets/templates/single-post-viewer/single-post-interaction-counts_tpl.jst.hbs b/app/assets/templates/single-post-viewer/single-post-interaction-counts_tpl.jst.hbs
index 221274487..dcf8cdd31 100644
--- a/app/assets/templates/single-post-viewer/single-post-interaction-counts_tpl.jst.hbs
+++ b/app/assets/templates/single-post-viewer/single-post-interaction-counts_tpl.jst.hbs
@@ -10,6 +10,12 @@
{{{personImage this "small" "micro"}}}
{{/linkToAuthor}}
{{/each}}
+ {{#if showMoreReshares}}
+
+ {{t "show_all"}}
+ {{/if}}
{{/if}}
@@ -25,6 +31,12 @@
{{{personImage this "small" "micro"}}}
{{/linkToAuthor}}
{{/each}}
+ {{#if showMoreLikes}}
+
+ {{t "show_all"}}
+ {{/if}}
{{/if}}
diff --git a/config/locales/javascript/javascript.en.yml b/config/locales/javascript/javascript.en.yml
index 7c5071762..8f4ed6953 100644
--- a/config/locales/javascript/javascript.en.yml
+++ b/config/locales/javascript/javascript.en.yml
@@ -28,6 +28,7 @@ en:
comma: ","
edit: "Edit"
no_results: "No results found"
+ show_all: "Show all"
admins:
dashboard:
diff --git a/spec/javascripts/app/views/single-post-view/single_post_interaction_counts_spec.js b/spec/javascripts/app/views/single-post-view/single_post_interaction_counts_spec.js
index 35abf7afe..0ff6959bc 100644
--- a/spec/javascripts/app/views/single-post-view/single_post_interaction_counts_spec.js
+++ b/spec/javascripts/app/views/single-post-view/single_post_interaction_counts_spec.js
@@ -1,6 +1,6 @@
describe("app.views.SinglePostInteractionCounts", function() {
beforeEach(function() {
- this.post = factory.post();
+ this.post = factory.postWithInteractions();
this.view = new app.views.SinglePostInteractionCounts({model: this.post});
});
@@ -12,5 +12,151 @@ describe("app.views.SinglePostInteractionCounts", function() {
this.post.interactions.trigger("change");
expect(app.views.SinglePostInteractionCounts.prototype.render).toHaveBeenCalled();
});
+
+ it("calls render when the likes change", function() {
+ spyOn(app.views.SinglePostInteractionCounts.prototype, "render");
+ this.view.initialize();
+ expect(app.views.SinglePostInteractionCounts.prototype.render).not.toHaveBeenCalled();
+ this.post.interactions.likes.trigger("change");
+ expect(app.views.SinglePostInteractionCounts.prototype.render).toHaveBeenCalled();
+ });
+
+ it("calls render when the reshares change", function() {
+ spyOn(app.views.SinglePostInteractionCounts.prototype, "render");
+ this.view.initialize();
+ expect(app.views.SinglePostInteractionCounts.prototype.render).not.toHaveBeenCalled();
+ this.post.interactions.reshares.trigger("change");
+ expect(app.views.SinglePostInteractionCounts.prototype.render).toHaveBeenCalled();
+ });
+ });
+
+ describe("render", function() {
+ it("doesn't show a #show-all-likes link if there are no additional likes", function() {
+ this.view.render();
+ expect(this.view.$("#show-all-likes").length).toBe(0);
+ });
+
+ it("shows a #show-all-likes link if there are additional likes", function() {
+ this.view.model.interactions.set("likes_count", this.view.model.interactions.likes.length + 1);
+ this.view.render();
+ expect(this.view.$("#show-all-likes").length).toBe(1);
+ });
+
+ it("doesn't show a #show-all-reshares link if there are no additional reshares", function() {
+ this.view.render();
+ expect(this.view.$("#show-all-reshares").length).toBe(0);
+ });
+
+ it("shows a #show-all-reshares link if there are additional reshares", function() {
+ this.view.model.interactions.set("reshares_count", this.view.model.interactions.reshares.length + 1);
+ this.view.render();
+ expect(this.view.$("#show-all-reshares").length).toBe(1);
+ });
+ });
+
+ describe("showAllLikes", function() {
+ it("is called when clicking #show-all-likes", function() {
+ spyOn(this.view, "showAllLikes");
+ this.view.delegateEvents();
+ this.view.model.interactions.set("likes_count", this.view.model.interactions.likes.length + 1);
+ this.view.render();
+ expect(this.view.showAllLikes).not.toHaveBeenCalled();
+ this.view.$("#show-all-likes").click();
+ expect(this.view.showAllLikes).toHaveBeenCalled();
+ });
+
+ it("calls _showAll", function() {
+ spyOn(this.view, "_showAll");
+ this.view.showAllLikes($.Event());
+ expect(this.view._showAll).toHaveBeenCalledWith("likes", this.view.model.interactions.likes);
+ });
+ });
+
+ describe("showAllReshares", function() {
+ it("is called when clicking #show-all-reshares", function() {
+ spyOn(this.view, "showAllReshares");
+ this.view.delegateEvents();
+ this.view.model.interactions.set("reshares_count", this.view.model.interactions.reshares.length + 1);
+ this.view.render();
+ expect(this.view.showAllReshares).not.toHaveBeenCalled();
+ this.view.$("#show-all-reshares").click();
+ expect(this.view.showAllReshares).toHaveBeenCalled();
+ });
+
+ it("calls _showAll", function() {
+ spyOn(this.view, "_showAll");
+ this.view.showAllReshares($.Event());
+ expect(this.view._showAll).toHaveBeenCalledWith("reshares", this.view.model.interactions.reshares);
+ });
+ });
+
+ describe("_showAll", function() {
+ beforeEach(function() {
+ this.view.model.interactions.set("likes_count", this.view.model.interactions.likes.length + 1);
+ this.view.model.interactions.set("reshares_count", this.view.model.interactions.reshares.length + 1);
+ this.view.render();
+ });
+
+ context("with likes", function() {
+ it("hides the #show-all-likes link", function() {
+ expect(this.view.$("#show-all-likes")).not.toHaveClass("hidden");
+ expect(this.view.$("#show-all-reshares")).not.toHaveClass("hidden");
+ this.view._showAll("likes", this.view.model.interactions.likes);
+ expect(this.view.$("#show-all-likes")).toHaveClass("hidden");
+ expect(this.view.$("#show-all-reshares")).not.toHaveClass("hidden");
+ });
+
+ it("shows the likes loader", function() {
+ expect(this.view.$("#likes .loader")).toHaveClass("hidden");
+ expect(this.view.$("#reshares .loader")).toHaveClass("hidden");
+ this.view._showAll("likes", this.view.model.interactions.likes);
+ expect(this.view.$("#likes .loader")).not.toHaveClass("hidden");
+ expect(this.view.$("#reshares .loader")).toHaveClass("hidden");
+ });
+
+ it("calls #fetch on the model", function() {
+ spyOn(this.view.model.interactions.likes, "fetch");
+ this.view._showAll("likes", this.view.model.interactions.likes);
+ expect(this.view.model.interactions.likes.fetch).toHaveBeenCalled();
+ });
+
+ it("triggers 'change' after a successfull fetch", function() {
+ spyOn(this.view.model.interactions.likes, "trigger");
+ this.view._showAll("likes", this.view.model.interactions.likes);
+ jasmine.Ajax.requests.mostRecent().respondWith({status: 200, responseText: "{\"id\": 1}"});
+ expect(this.view.model.interactions.likes.trigger).toHaveBeenCalledWith("change");
+ });
+ });
+
+ context("with reshares", function() {
+ it("hides the #show-all-reshares link", function() {
+ expect(this.view.$("#show-all-likes")).not.toHaveClass("hidden");
+ expect(this.view.$("#show-all-reshares")).not.toHaveClass("hidden");
+ this.view._showAll("reshares", this.view.model.interactions.reshares);
+ expect(this.view.$("#show-all-likes")).not.toHaveClass("hidden");
+ expect(this.view.$("#show-all-reshares")).toHaveClass("hidden");
+ });
+
+ it("shows the reshares loader", function() {
+ expect(this.view.$("#likes .loader")).toHaveClass("hidden");
+ expect(this.view.$("#reshares .loader")).toHaveClass("hidden");
+ this.view._showAll("reshares", this.view.model.interactions.reshares);
+ expect(this.view.$("#likes .loader")).toHaveClass("hidden");
+ expect(this.view.$("#reshares .loader")).not.toHaveClass("hidden");
+ });
+
+ it("calls #fetch on the model", function() {
+ spyOn(this.view.model.interactions.reshares, "fetch");
+ this.view._showAll("reshares", this.view.model.interactions.reshares);
+ expect(this.view.model.interactions.reshares.fetch).toHaveBeenCalled();
+ });
+
+ it("triggers 'change' after a successfull fetch", function() {
+ spyOn(this.view.model.interactions.reshares, "trigger");
+ this.view._showAll("reshares", this.view.model.interactions.reshares);
+ jasmine.Ajax.requests.mostRecent().respondWith({status: 200, responseText: "{\"id\": 1}"});
+ expect(this.view.model.interactions.reshares.trigger).toHaveBeenCalledWith("change");
+ });
+ });
});
});
diff --git a/spec/javascripts/jasmine_helpers/factory.js b/spec/javascripts/jasmine_helpers/factory.js
index 551fe87bc..ba97e5b71 100644
--- a/spec/javascripts/jasmine_helpers/factory.js
+++ b/spec/javascripts/jasmine_helpers/factory.js
@@ -21,6 +21,16 @@ var factory = {
return _.extend(defaultAttrs, overrides);
},
+ reshare: function(overrides) {
+ var defaultAttrs = {
+ "created_at": "2012-01-04T00:55:30Z",
+ "author": this.author(),
+ "guid": this.guid(),
+ "id": this.id.next()
+ };
+ return _.extend(defaultAttrs, overrides);
+ },
+
aspectMembershipAttrs: function(overrides) {
var id = this.id.next();
var defaultAttrs = {
@@ -207,6 +217,24 @@ var factory = {
return new app.models.Post(_.extend(defaultAttrs, overrides));
},
+ postWithInteractions: function(overrides) {
+ var likes = _.range(10).map(function() { return factory.like(); });
+ var reshares = _.range(15).map(function() { return factory.reshare(); });
+ var comments = _.range(20).map(function() { return factory.comment(); });
+ var defaultAttrs = _.extend(factory.postAttrs(), {
+ "author": this.author(),
+ "interactions": {
+ "reshares_count": 15,
+ "likes_count": 10,
+ "comments_count": 20,
+ "comments": comments,
+ "likes": likes,
+ "reshares": reshares
+ }
+ });
+ return new app.models.Post(_.extend(defaultAttrs, overrides));
+ },
+
statusMessage : function(overrides){
//intentionally doesn't have an author to mirror creation process, maybe we should change the creation process
return new app.models.StatusMessage(_.extend(factory.postAttrs(), overrides));