UX: Move links from gutter to below posts

This commit is contained in:
Robin Ward 2016-05-16 14:31:52 -04:00
parent e9ba6e4e99
commit 4a7567b485
No known key found for this signature in database
GPG Key ID: 0E091E2B4ED1B83D
9 changed files with 137 additions and 182 deletions

View File

@ -1,72 +0,0 @@
import { iconNode } from 'discourse/helpers/fa-icon';
import { createWidget } from 'discourse/widgets/widget';
import { h } from 'virtual-dom';
import RawHtml from 'discourse/widgets/raw-html';
const MAX_GUTTER_LINKS = 5;
export default createWidget('post-gutter', {
tagName: 'div.gutter',
buildKey: (attrs) => `post-gutter-${attrs.id}`,
defaultState() {
return { collapsed: true };
},
html(attrs, state) {
const links = this.attrs.links || [];
const result = [];
let toShow = links.length;
if (state.collapsed && toShow > MAX_GUTTER_LINKS) { toShow = MAX_GUTTER_LINKS; }
const seenTitles = {};
let titleCount = 0;
links.forEach(function(l) {
let title = l.title;
if (title && !seenTitles[title]) {
seenTitles[title] = true;
titleCount++;
if (result.length < toShow) {
const linkBody = [new RawHtml({html: `<span>${Discourse.Emoji.unescape(Handlebars.Utils.escapeExpression(title))}</span>`})];
if (l.clicks) {
linkBody.push(h('span.badge.badge-notification.clicks', l.clicks.toString()));
}
const className = l.reflection ? 'inbound' : 'outbound';
const link = h('a.track-link', {className, attributes: {href: l.url}}, linkBody);
result.push(h('li', link));
}
}
});
if (state.collapsed) {
const remaining = titleCount - MAX_GUTTER_LINKS;
if (remaining > 0) {
result.push(h('li', h('a.toggle-more', I18n.t('post.more_links', {count: remaining}))));
}
}
if (attrs.canReplyAsNewTopic) {
result.push(h('a.reply-new', [iconNode('plus'), I18n.t('post.reply_as_new_topic')]));
}
return h('ul.post-links', result);
},
click(e) {
const $target = $(e.target);
if ($target.hasClass('toggle-more')) {
this.sendWidgetAction('showAll');
} else if ($target.closest('.reply-new').length) {
this.sendWidgetAction('newTopicAction');
}
return true;
},
showAll() {
this.state.collapsed = false;
}
});

View File

@ -0,0 +1,65 @@
import { iconNode } from 'discourse/helpers/fa-icon';
import { createWidget } from 'discourse/widgets/widget';
import { h } from 'virtual-dom';
import RawHtml from 'discourse/widgets/raw-html';
export default createWidget('post-links', {
tagName: 'div.post-links-container',
buildKey: (attrs) => `post-links-${attrs.id}`,
defaultState() {
return { collapsed: true };
},
html(attrs, state) {
const links = this.attrs.links || [];
const result = [];
if (links.length) {
if (state.collapsed) {
return this.attach('link', {
labelCount: `post_links.title`,
count: links.length,
action: 'expandLinks',
className: 'expand-links'
});
}
const seenTitles = {};
let titleCount = 0;
links.forEach(function(l) {
let title = l.title;
if (title && !seenTitles[title]) {
seenTitles[title] = true;
titleCount++;
const linkBody = [new RawHtml({html: `<span>${Discourse.Emoji.unescape(Handlebars.Utils.escapeExpression(title))}</span>`})];
if (l.clicks) {
linkBody.push(h('span.badge.badge-notification.clicks', l.clicks.toString()));
}
result.push(h('li',
h('a.track-link', {
className: l.reflection ? 'inbound' : 'outbound',
attributes: {href: l.url}
}, [linkBody, iconNode(l.reflection ? 'arrow-left' : 'arrow-right')])
));
}
});
}
if (attrs.canReplyAsNewTopic) {
result.push(h('li', this.attach('link', {
className: 'reply-new',
contents: () => [I18n.t('post.reply_as_new_topic'), iconNode('plus')],
action: 'newTopicAction'
})));
}
return h('ul.post-links', result);
},
expandLinks() {
this.state.collapsed = false;
}
});

View File

@ -306,6 +306,7 @@ createWidget('post-body', {
if (attrs.showTopicMap) {
result.push(this.attach('topic-map', attrs));
}
result.push(this.attach('post-links', attrs));
return result;
}
@ -341,9 +342,7 @@ createWidget('post-article', {
rows.push(h('div.row', h('section.embedded-posts.top.topic-body.offset2', replies)));
}
rows.push(h('div.row', [this.attach('post-avatar', attrs),
this.attach('post-body', attrs),
this.attach('post-gutter', attrs)]));
rows.push(h('div.row', [this.attach('post-avatar', attrs), this.attach('post-body', attrs)]));
return rows;
},

View File

@ -1,5 +1,4 @@
#topic-title {
.title-wrapper {
float: left;
width: 90%;
@ -79,3 +78,49 @@
}
}
}
.post-links-container {
@include unselectable;
clear: both;
text-align: right;
margin-top: 1em;
.expand-links {
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 50%));
}
.track-link {
padding-left: 10px;
display: inline-block;
overflow: hidden;
}
ul {
list-style: none;
li {
margin-bottom: 0.5em;
a[href] {
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 50%));
}
i {
font-size: 0.857em;
margin-left: 0.5em;
}
}
}
a.reply-new {
i {
background: $secondary;
border-radius: 20px;
transition: all linear .15s;
}
&:hover {
color: $tertiary;
i {
background: dark-light-diff($tertiary, $secondary, 85%, -65%);
}
}
}
}

View File

@ -47,25 +47,6 @@ h1 .topic-statuses .topic-status i {
}
}
.topic-post {
.gutter {
.reply-new {
.discourse-no-touch & {
opacity:0;
transition: opacity 0.7s ease-in-out;
}
.discourse-touch & {opacity: 1;}
}
}
&:hover .gutter, .selected .gutter {
.reply-new,
.track-link {
opacity:1;
}
}
}
section.post-menu-area {
position: relative;
}
@ -637,51 +618,6 @@ blockquote {
}
.gutter {
margin-top: 13px;
width: 100%;
box-sizing: border-box;
z-index: 1;
padding-left: 757px;
ul {margin: 0;}
li {margin-bottom: 10px;}
i {font-size: 0.857em;}
.reply-new {
padding-left: 27px;
display: inline-block;
overflow:hidden;
}
.track-link {
padding-left: 10px;
display: inline-block;
overflow: hidden;
}
.post-links {
list-style-type: none;
position: relative;
line-height: 18px;
word-wrap: break-word;
a i {
position: relative;
margin-right: 7px;
margin-top: -2px;
margin-left: -17px;
}
a.toggle-more {
display: block;
text-align: right;
}
}
}
// variables are used to calculate the width of .gap
$topic-body-width: 690px;
$topic-body-width-padding: 11px;
@ -925,17 +861,17 @@ a.attachment:before {
}
.private_message .gutter, .deleted-topic .gutter,.read_restricted .gutter {
position: relative;
position: relative;
}
.deleted-topic .gutter:before {
display: block;
position: absolute;
left: 767px;
color: rgba(dark-light-diff($primary, $secondary, 90%, -65%) , .8);
font: 6.429em/1 FontAwesome;
content: "\f014";
z-index: -5;
display: block;
position: absolute;
left: 767px;
color: rgba(dark-light-diff($primary, $secondary, 90%, -65%) , .8);
font: 6.429em/1 FontAwesome;
content: "\f014";
z-index: -5;
}
.topic-meta-data {
@ -1003,7 +939,7 @@ and (max-width : 870px) {
.gutter {
display: none;
}
}
.topic-avatar {
width: 45px;

View File

@ -8,6 +8,7 @@
margin-top: 10px;
}
}
.post-menu-area {
margin-bottom: 10px;
margin-top: 20px;
@ -53,8 +54,6 @@
margin-bottom: 2px;
}
.private-message-glyph { display: none; }
}
.private-message-glyph {
@ -64,26 +63,6 @@
}
.private_message #topic-title .private-message-glyph { display: inline; }
a.reply-new {
margin-top: 3px;
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 50%));
i {
margin-right: 3px;
background: $secondary;
padding: 1.5px 3px;
border-radius: 20px;
transition: all linear .15s;
margin-left: -20px;
}
}
a:hover.reply-new {
color: $tertiary;
i {
background: dark-light-diff($tertiary, $secondary, 85%, -65%);
}
}
.topic-error {
padding: 18px;
width: 60%;

View File

@ -143,10 +143,6 @@ button {
}
}
.reply-new {
display: none;
}
.post-actions {
/* overriding display: here was causing hidden element to take up space */
}

View File

@ -1815,6 +1815,10 @@ en:
clicks:
one: "1 click"
other: "%{count} clicks"
post_links:
title:
one: "1 post link"
other: "%{count} post links"
topic_statuses:
warning:

View File

@ -1,9 +1,9 @@
import { moduleForWidget, widgetTest } from 'helpers/widget-test';
moduleForWidget('post-gutter');
moduleForWidget('post-links');
widgetTest("duplicate links", {
template: '{{mount-widget widget="post-gutter" args=args}}',
template: '{{mount-widget widget="post-links" args=args}}',
setup() {
this.set('args', {
id: 2,
@ -14,12 +14,15 @@ widgetTest("duplicate links", {
});
},
test(assert) {
assert.equal(this.$('.post-links a.track-link').length, 1, 'it hides the dupe link');
click('.expand-links');
andThen(() => {
assert.equal(this.$('.post-links a.track-link').length, 1, 'it hides the dupe link');
});
}
});
widgetTest("collapsed links", {
template: '{{mount-widget widget="post-gutter" args=args}}',
template: '{{mount-widget widget="post-links" args=args}}',
setup() {
this.set('args', {
id: 1,
@ -35,8 +38,8 @@ widgetTest("collapsed links", {
});
},
test(assert) {
assert.equal(this.$('.post-links a.track-link').length, 5, 'collapses by default');
click('a.toggle-more');
assert.ok(this.$('.expand-links').length, 'collapsed by default');
click('a.expand-links');
andThen(() => {
assert.equal(this.$('.post-links a.track-link').length, 7);
});
@ -44,7 +47,7 @@ widgetTest("collapsed links", {
});
widgetTest("reply as new topic", {
template: '{{mount-widget widget="post-gutter" args=args newTopicAction="newTopicAction"}}',
template: '{{mount-widget widget="post-links" args=args newTopicAction="newTopicAction"}}',
setup() {
this.set('args', { canReplyAsNewTopic: true });
this.on('newTopicAction', () => this.newTopicTriggered = true);