UX: tweak location of like count

UX: clean up fade logic so it meshes with new like style
EXTENSIBILITY: add hook for insertion of custom HTML for buttons
UX: stop suppressing share for anon, like expander is not suppressed
 old behavior is inconsistent


also reimplements like count expander as a proper button,
adds a nice label for it
This commit is contained in:
Sam 2015-07-08 15:10:53 +10:00
parent 73fc612cbc
commit 2bd6e201f9
7 changed files with 113 additions and 62 deletions

View File

@ -29,9 +29,12 @@ function animateHeart($elem, start, end, complete) {
Button.prototype.render = function(buffer) { Button.prototype.render = function(buffer) {
const opts = this.opts; const opts = this.opts;
const label = I18n.t(this.label); const label = I18n.t(this.label, opts.labelOptions);
if (opts.prefixHTML) {
buffer.push(opts.prefixHTML);
}
buffer.push("<button aria-label=\"" + label +"\" " + "title=\"" + label + "\""); buffer.push("<button aria-label=\"" + label +"\" " + "title=\"" + label + "\"");
if (opts.disabled) { buffer.push(" disabled"); } if (opts.disabled) { buffer.push(" disabled"); }
if (opts.className) { buffer.push(" class=\"" + opts.className + "\""); } if (opts.className) { buffer.push(" class=\"" + opts.className + "\""); }
if (opts.shareUrl) { buffer.push(" data-share-url=\"" + opts.shareUrl + "\""); } if (opts.shareUrl) { buffer.push(" data-share-url=\"" + opts.shareUrl + "\""); }
@ -76,7 +79,6 @@ const PostMenuComponent = Ember.Component.extend(StringBuffer, {
const post = this.get('post'); const post = this.get('post');
buffer.push("<nav class='post-controls'>"); buffer.push("<nav class='post-controls'>");
this.renderLikes(post, buffer);
this.renderReplies(post, buffer); this.renderReplies(post, buffer);
this.renderButtons(post, buffer); this.renderButtons(post, buffer);
this.renderAdminPopup(post, buffer); this.renderAdminPopup(post, buffer);
@ -89,7 +91,7 @@ const PostMenuComponent = Ember.Component.extend(StringBuffer, {
action = $target.data('action') || $target.parent().data('action'); action = $target.data('action') || $target.parent().data('action');
if (!action) return; if (!action) return;
const handler = this["click" + action.capitalize()]; const handler = this["click" + action.replace(/[\+-]/, "").capitalize()];
if (!handler) return; if (!handler) return;
handler.call(this, this.get('post')); handler.call(this, this.get('post'));
@ -100,8 +102,7 @@ const PostMenuComponent = Ember.Component.extend(StringBuffer, {
if (!post.get('showRepliesBelow')) return; if (!post.get('showRepliesBelow')) return;
const replyCount = post.get('reply_count'); const replyCount = post.get('reply_count');
buffer.push("<button class='show-replies' data-action='replies'>"); buffer.push("<button class='show-replies highlight-action' data-action='replies'>");
buffer.push("<span class='badge-posts'>" + replyCount + "</span>");
buffer.push(I18n.t("post.has_replies", { count: replyCount })); buffer.push(I18n.t("post.has_replies", { count: replyCount }));
const icon = (this.get('post.replies.length') > 0) ? 'chevron-up' : 'chevron-down'; const icon = (this.get('post.replies.length') > 0) ? 'chevron-up' : 'chevron-down';
@ -140,7 +141,7 @@ const PostMenuComponent = Ember.Component.extend(StringBuffer, {
const yours = post.get('yours'); const yours = post.get('yours');
this.siteSettings.post_menu.split("|").forEach(function(i) { this.siteSettings.post_menu.split("|").forEach(function(i) {
const creator = self["buttonFor" + i.replace(/\+/, '').capitalize()]; const creator = self["buttonFor" + i.replace(/[\+-]/, '').capitalize()];
if (creator) { if (creator) {
const button = creator.call(self, post); const button = creator.call(self, post);
if (button) { if (button) {
@ -176,7 +177,7 @@ const PostMenuComponent = Ember.Component.extend(StringBuffer, {
buffer.push("</div>"); buffer.push("</div>");
}, },
clickLikes() { clickLikecount() {
const likeAction = this.get('post.actionByName.like'); const likeAction = this.get('post.actionByName.like');
if (likeAction) { if (likeAction) {
const users = likeAction.get('users'); const users = likeAction.get('users');
@ -246,12 +247,30 @@ const PostMenuComponent = Ember.Component.extend(StringBuffer, {
const likeAction = this.get('likeAction'); const likeAction = this.get('likeAction');
if (!likeAction) { return; } if (!likeAction) { return; }
const className = likeAction.get('acted') ? 'has-like' : 'like'; const className = likeAction.get('acted') ? 'has-like fade-out' : 'like';
var opts = {className: className};
if (likeAction.get('canToggle')) { if (likeAction.get('canToggle')) {
const descKey = likeAction.get('acted') ? 'post.controls.undo_like' : 'post.controls.like'; const descKey = likeAction.get('acted') ? 'post.controls.undo_like' : 'post.controls.like';
return new Button('like', descKey, 'heart', {className: className}); return new Button('like', descKey, 'heart', opts);
} else if (likeAction.get('acted')) { } else if (likeAction.get('acted')) {
return new Button('like', 'post.controls.has_liked', 'heart', {className: className, disabled: true}); opts.disabled = true;
return new Button('like', 'post.controls.has_liked', 'heart', opts);
}
},
buttonForLikecount() {
var likeCount = this.get('post.like_count') || 0;
if (likeCount > 0) {
const likedPost = !!this.get('likeAction.acted');
const label = likedPost ? 'post.has_likes_title_you' : 'post.has_likes_title';
return new Button('like-count', label, undefined, {
className: 'like-count highlight-action',
innerHTML: I18n.t("post.has_likes", { count: likeCount }),
labelOptions: {count: likedPost ? (likeCount-1) : likeCount}
});
} }
}, },
@ -300,7 +319,6 @@ const PostMenuComponent = Ember.Component.extend(StringBuffer, {
// Share button // Share button
buttonForShare(post) { buttonForShare(post) {
if (!Discourse.User.current()) return;
const options = { const options = {
shareUrl: post.get('shareUrl'), shareUrl: post.get('shareUrl'),
postNumber: post.get('post_number') postNumber: post.get('post_number')
@ -311,7 +329,7 @@ const PostMenuComponent = Ember.Component.extend(StringBuffer, {
// Reply button // Reply button
buttonForReply() { buttonForReply() {
if (!this.get('canCreatePost')) return; if (!this.get('canCreatePost')) return;
const options = {className: 'create'}; const options = {className: 'create fade-out'};
if(!Discourse.Mobile.mobileView) { if(!Discourse.Mobile.mobileView) {
options.textLabel = 'topic.reply.title'; options.textLabel = 'topic.reply.title';

View File

@ -7,7 +7,8 @@ export default Ember.Component.extend(StringBuffer, {
renderString(buffer) { renderString(buffer) {
const likedUsers = this.get('likedUsers'); const likedUsers = this.get('likedUsers');
if (likedUsers) { if (likedUsers && likedUsers.length > 0) {
buffer.push("<i class='fa fa-heart'></i>");
let iconsHtml = ""; let iconsHtml = "";
likedUsers.forEach(function(u) { likedUsers.forEach(function(u) {
iconsHtml += "<a href=\"" + Discourse.getURL("/users/") + u.get('username_lower') + "\" data-user-card=\"" + u.get('username_lower') + "\">"; iconsHtml += "<a href=\"" + Discourse.getURL("/users/") + u.get('username_lower') + "\" data-user-card=\"" + u.get('username_lower') + "\">";

View File

@ -239,5 +239,15 @@ blockquote > *:last-child {
margin: 0 0.25em 0.5em 0; margin: 0 0.25em 0.5em 0;
display: inline-block; display: inline-block;
} }
.fa-heart {
font-size: 20px;
margin-right: 5px;
display: inline-block;
vertical-align: middle;
color: $love;
}
} }

View File

@ -29,15 +29,15 @@ h1 .topic-statuses .topic-status i {
border-top: none; border-top: none;
} }
.reply-to-tab { .reply-to-tab {
z-index: 400; z-index: 400;
font-size: 0.929em; font-size: 0.929em;
float: right; float: right;
margin: 1px 25px 0 0; margin: 1px 25px 0 0;
color: scale-color($primary, $lightness: 50%); color: scale-color($primary, $lightness: 50%);
} }
.gutter { .gutter {
.reply-new { .reply-new {
.discourse-no-touch & { .discourse-no-touch & {
opacity:0; opacity:0;
@ -45,27 +45,27 @@ h1 .topic-statuses .topic-status i {
} }
.discourse-touch & {opacity: 1;} .discourse-touch & {opacity: 1;}
} }
} }
div.actions, .post-actions { .actions .fade-out {
.discourse-no-touch & { .discourse-no-touch & {
opacity: 0.2; opacity: 0.7;
transition: opacity 0.7s ease-in-out; transition: opacity 0.7s ease-in-out;
} }
.discourse-touch & {opacity: 1;} .discourse-touch & {opacity: 1;}
} }
&:hover div.actions, &:hover .post-actions { &:hover .actions .fade-out, .selected .actions .fade-out {
opacity: 1; opacity: 1;
} }
&:hover .gutter { &:hover .gutter, .selected .gutter {
.reply-new, .reply-new,
.track-link { .track-link {
opacity:1; opacity:1;
} }
} }
} }
section.post-menu-area { section.post-menu-area {
@ -73,10 +73,25 @@ section.post-menu-area {
} }
nav.post-controls { nav.post-controls {
.like-count {
font-size: inherit;
margin-right: -5px;
}
padding: 0; padding: 0;
button { .highlight-action {
color: scale-color($primary, $lightness: 60%); color: scale-color($primary, $lightness: 60%);
}
a, button {
color: scale-color($primary, $lightness: 75%);
margin-right: 2px; margin-right: 2px;
display: inline-block;
}
a.toggle-likes {
padding: 8px 0;
margin-right: -3px;
} }
span.badge-posts { span.badge-posts {
@ -95,8 +110,8 @@ nav.post-controls {
} }
} }
.show-replies, .show-likes { .show-replies {
margin-left: 0; margin-left: -10px;
font-size: inherit; font-size: inherit;
span.badge-posts {color: scale-color($primary, $lightness: 60%);} span.badge-posts {color: scale-color($primary, $lightness: 60%);}
&:hover { &:hover {
@ -258,7 +273,6 @@ nav.post-controls {
} }
} }
&.bottom { &.bottom {
margin-top: -11px;
.row { .row {
padding-top: 7px; padding-top: 7px;
} }

View File

@ -27,20 +27,18 @@ span.badge-posts {
display: none; display: none;
} }
.show-likes {
padding-left: 0;
padding-right: 0;
font-size: inherit;
span.badge-posts {color: scale-color($primary, $lightness: 60%);}
i {
display: none;
}
}
nav.post-controls { nav.post-controls {
clear: both; clear: both;
} }
.who-liked {
margin-left: 20px;
}
button.like-count {
padding: 8px 4px;
}
button { button {
border: none; border: none;
font-size: 1.214em; font-size: 1.214em;

View File

@ -1231,11 +1231,20 @@ en:
unread: "Post is unread" unread: "Post is unread"
has_replies: has_replies:
one: "Reply" one: "{{count}} Reply"
other: "Replies" other: "{{count}} Replies"
has_likes: has_likes:
one: "Like" one: "{{count}} Like"
other: "Likes" other: "{{count}} Likes"
has_likes_title:
one: "1 person liked this post"
other: "{{count}} people liked this post"
has_likes_title_you:
zero: "you liked this post"
one: "you and 1 other person liked this post"
other: "you and {{count}} other people liked this post"
errors: errors:
create: "Sorry, there was an error creating your post. Please try again." create: "Sorry, there was an error creating your post. Please try again."

View File

@ -107,8 +107,9 @@ basic:
post_menu: post_menu:
client: true client: true
type: list type: list
default: 'like|share|flag|edit|bookmark|delete|admin|reply' default: 'like-count|like|share|flag|edit|bookmark|delete|admin|reply'
choices: choices:
- like-count
- like - like
- edit - edit
- flag - flag