FIX: Liking a post shouldn't contract who liked it

This commit is contained in:
Robin Ward 2015-09-17 15:40:15 -04:00
parent 0aee7b8211
commit 4eaaf4198c
9 changed files with 96 additions and 66 deletions

View File

@ -1,6 +1,7 @@
import StringBuffer from 'discourse/mixins/string-buffer';
import { iconHTML } from 'discourse/helpers/fa-icon';
import { autoUpdatingRelativeAge } from 'discourse/lib/formatter';
import { on } from 'ember-addons/ember-computed-decorators';
export default Ember.Component.extend(StringBuffer, {
tagName: 'section',
@ -8,32 +9,44 @@ export default Ember.Component.extend(StringBuffer, {
actionsSummary: Em.computed.alias('post.actionsWithoutLikes'),
emptySummary: Em.computed.empty('actionsSummary'),
hidden: Em.computed.and('emptySummary', 'post.notDeleted'),
usersByType: null,
rerenderTriggers: ['actionsSummary.@each', 'actionsSummary.users.length', 'post.deleted'],
rerenderTriggers: ['actionsSummary.@each', 'post.deleted'],
@on('init')
initUsersByType() {
this.set('usersByType', {});
},
// This was creating way too many bound ifs and subviews in the handlebars version.
renderString(buffer) {
const usersByType = this.get('usersByType');
if (!this.get('emptySummary')) {
this.get('actionsSummary').forEach(function(c) {
const id = c.get('id');
const users = usersByType[id] || [];
buffer.push("<div class='post-action'>");
const renderActionIf = function(property, dataAttribute, text) {
if (!c.get(property)) { return; }
buffer.push(" <span class='action-link " + dataAttribute +"-action'><a href data-" + dataAttribute + "='" + c.get('id') + "'>" + text + "</a>.</span>");
const renderLink = (dataAttribute, text) => {
buffer.push(` <span class='action-link ${dataAttribute}-action'><a href data-${dataAttribute}='${id}'>${text}</a>.</span>`);
};
// TODO multi line expansion for flags
let iconsHtml = "";
if (c.get('usersExpanded')) {
if (users.length) {
let postUrl;
c.get('users').forEach(function(u) {
iconsHtml += "<a href=\"" + Discourse.getURL("/users/") + u.get('username_lower') + "\" data-user-card=\"" + u.get('username_lower') + "\">";
users.forEach(function(u) {
const username = u.get('username_lower');
iconsHtml += `<a href="${Discourse.getURL("/users")}${username}" data-user-card="${username}">`;
if (u.post_url) {
postUrl = postUrl || u.post_url;
}
iconsHtml += Discourse.Utilities.avatarImg({
size: 'small',
avatarTemplate: u.get('avatarTemplate'),
avatarTemplate: u.get('avatar_template'),
title: u.get('username')
});
iconsHtml += "</a>";
@ -45,9 +58,18 @@ export default Ember.Component.extend(StringBuffer, {
// TODO postUrl might be uninitialized? pick a good default
buffer.push(" " + I18n.t(key, { icons: iconsHtml, postUrl: postUrl}) + ".");
}
renderActionIf('usersCollapsed', 'who-acted', c.get('description'));
renderActionIf('can_undo', 'undo', I18n.t("post.actions.undo." + c.get('actionType.name_key')));
renderActionIf('can_defer_flags', 'defer-flags', I18n.t("post.actions.defer_flags", { count: c.count }));
if (users.length === 0) {
renderLink('who-acted', c.get('description'));
}
if (c.get('can_undo')) {
renderLink('undo', I18n.t("post.actions.undo." + c.get('actionType.name_key')));
}
if (c.get('can_defer_flags')) {
renderLink('defer-flags', I18n.t("post.actions.defer_flags", { count: c.count }));
}
buffer.push("</div>");
});
@ -79,8 +101,12 @@ export default Ember.Component.extend(StringBuffer, {
}
// User wants to know who actioned it
const usersByType = this.get('usersByType');
if (actionTypeId = $target.data('who-acted')) {
this.actionTypeById(actionTypeId).loadUsers(post);
this.actionTypeById(actionTypeId).loadUsers(post).then(users => {
usersByType[actionTypeId] = users;
this.rerender();
});
return false;
}

View File

@ -165,15 +165,12 @@ const PostMenuComponent = Ember.Component.extend(StringBuffer, {
},
clickLikeCount() {
const likeAction = this.get('post.likeAction');
if (likeAction) {
const users = likeAction.get('users');
if (users && users.length) {
users.clear();
} else {
likeAction.loadUsers(this.get('post'));
}
}
this.sendActionTarget('toggleWhoLiked');
},
sendActionTarget(action, arg) {
const target = this.get(`${action}Target`);
return target ? target.send(this.get(action), arg) : this.sendAction(action, arg);
},
clickReplies() {
@ -268,13 +265,13 @@ const PostMenuComponent = Ember.Component.extend(StringBuffer, {
self = this;
if (acted) {
this.sendAction('toggleLike', post);
this.sendActionTarget('toggleLike');
$likeButton.removeClass('has-like').addClass('like');
} else {
const scale = [1.0, 1.5];
animateHeart($heart, scale[0], scale[1], function() {
animateHeart($heart, scale[1], scale[0], function() {
self.sendAction('toggleLike', post);
self.sendActionTarget('toggleLike');
$likeButton.removeClass('like').addClass('has-like');
});
});

View File

@ -1,15 +1,14 @@
import StringBuffer from 'discourse/mixins/string-buffer';
export default Ember.Component.extend(StringBuffer, {
likedUsers: Ember.computed.alias('post.likeAction.users'),
rerenderTriggers: ['likedUsers.length'],
rerenderTriggers: ['users.length'],
renderString(buffer) {
const likedUsers = this.get('likedUsers');
if (likedUsers && likedUsers.length > 0) {
const users = this.get('users');
if (users && users.length > 0) {
buffer.push("<div class='who-liked'>");
let iconsHtml = "";
likedUsers.forEach(function(u) {
users.forEach(function(u) {
iconsHtml += "<a href=\"" + Discourse.getURL("/users/") + u.get('username_lower') + "\" data-user-card=\"" + u.get('username_lower') + "\">";
iconsHtml += Discourse.Utilities.avatarImg({
size: 'small',

View File

@ -144,13 +144,6 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
return false;
},
toggleLike(post) {
const likeAction = post.get('likeAction');
if (likeAction && likeAction.get('canToggle')) {
likeAction.toggle(post);
}
},
recoverPost(post) {
// Recovering the first post recovers the topic instead
if (post.get('post_number') === 1) {

View File

@ -27,7 +27,7 @@ const bindings = {
'home': {handler: 'goToFirstPost', anonymous: true},
'j': {handler: 'selectDown', anonymous: true},
'k': {handler: 'selectUp', anonymous: true},
'l': {postAction: 'toggleLike'},
'l': {click: '.topic-post.selected button[data-action="like"]'},
'm m': {click: 'div.notification-options li[data-id="0"] a'}, // mark topic as muted
'm r': {click: 'div.notification-options li[data-id="1"] a'}, // mark topic as regular
'm t': {click: 'div.notification-options li[data-id="2"] a'}, // mark topic as tracking

View File

@ -17,9 +17,6 @@ export default RestModel.extend({
}
}.property('count', 'acted', 'actionType'),
usersCollapsed: Em.computed.not('usersExpanded'),
usersExpanded: Em.computed.gt('users.length', 0),
canToggle: function() {
return this.get('can_undo') || this.get('can_act');
}.property('can_undo', 'can_act'),
@ -32,17 +29,15 @@ export default RestModel.extend({
can_act: true,
can_undo: false
});
if (this.get('usersExpanded')) {
this.get('users').removeObject(Discourse.User.current());
}
},
toggle: function(post) {
if (!this.get('acted')) {
this.act(post);
return true;
} else {
this.undo(post);
return false;
}
},
@ -66,14 +61,8 @@ export default RestModel.extend({
this.set('can_defer_flags',false);
}
// Add ourselves to the users who liked it if present
if (this.get('usersExpanded')) {
this.get('users').addObject(Discourse.User.current());
}
// Create our post action
const self = this;
return Discourse.ajax("/post_actions", {
type: 'POST',
data: {
@ -121,16 +110,11 @@ export default RestModel.extend({
});
},
loadUsers: function(post) {
const self = this;
Discourse.ajax("/post_actions/users", {
data: {
id: post.get('id'),
post_action_type_id: this.get('id')
}
loadUsers(post) {
return Discourse.ajax("/post_actions/users", {
data: { id: post.get('id'), post_action_type_id: this.get('id') }
}).then(function (result) {
const users = [];
self.set('users', users);
result.forEach(function(user) {
if (user.id === Discourse.User.currentProp('id')) {
users.pushObject(Discourse.User.current());
@ -138,6 +122,7 @@ export default RestModel.extend({
users.pushObject(Discourse.User.create(user));
}
});
return users;
});
}
});

View File

@ -104,16 +104,19 @@
recoverPost="recoverPost"
deletePost="deletePost"
toggleLike="toggleLike"
toggleLikeTarget=view
showFlags="showFlags"
editPost="editPost"
toggleBookmark="toggleBookmark"
toggleWiki="toggleWiki"
togglePostType="togglePostType"
rebakePost="rebakePost"
unhidePost="unhidePost"}}
unhidePost="unhidePost"
toggleWhoLiked="toggleWhoLiked"
toggleWhoLikedTarget=view}}
</div>
{{who-liked post=this}}
{{who-liked users=view.likedUsers}}
{{#if replies}}
<section class='embedded-posts bottom'>
{{#each reply in replies}}

View File

@ -1,5 +0,0 @@
import PostMenuComponent from 'discourse/components/post-menu';
Ember.warn("PostMenuView has been deprecated, use PostMenuComponent instead");
export default PostMenuComponent.extend();

View File

@ -1,7 +1,7 @@
import ScreenTrack from 'discourse/lib/screen-track';
import { number } from 'discourse/lib/formatter';
import DiscourseURL from 'discourse/lib/url';
import computed from 'ember-addons/ember-computed-decorators';
import { default as computed, on } from 'ember-addons/ember-computed-decorators';
import { fmt } from 'discourse/lib/computed';
const DAY = 60 * 50 * 1000;
@ -18,8 +18,13 @@ const PostView = Discourse.GroupedView.extend(Ember.Evented, {
'whisper'],
post: Ember.computed.alias('content'),
postElementId: fmt('post.post_number', 'post_%@'),
likedUsers: null,
@on('init')
initLikedUsers() {
this.set('likedUsers', []);
},
@computed('post.post_type')
whisper(postType) {
@ -197,6 +202,33 @@ const PostView = Discourse.GroupedView.extend(Ember.Evented, {
},
actions: {
toggleLike() {
const currentUser = this.get('controller.currentUser');
const post = this.get('post');
const likeAction = post.get('likeAction');
if (likeAction && likeAction.get('canToggle')) {
const users = this.get('likedUsers');
if (likeAction.toggle(post) && users.length) {
users.addObject(currentUser);
} else {
users.removeObject(currentUser);
}
}
},
toggleWhoLiked() {
const post = this.get('post');
const likeAction = post.get('likeAction');
if (likeAction) {
const users = this.get('likedUsers');
if (users.length) {
users.clear();
} else {
likeAction.loadUsers(post).then(newUsers => this.set('likedUsers', newUsers));
}
}
},
// Toggle the replies this post is a reply to
toggleReplyHistory(post) {
const replyHistory = post.get('replyHistory'),