UX: Move links from gutter to below posts
This commit is contained in:
parent
e9ba6e4e99
commit
4a7567b485
|
@ -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;
|
||||
}
|
||||
});
|
|
@ -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;
|
||||
}
|
||||
});
|
|
@ -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;
|
||||
},
|
||||
|
||||
|
|
|
@ -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%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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%;
|
||||
|
|
|
@ -143,10 +143,6 @@ button {
|
|||
}
|
||||
}
|
||||
|
||||
.reply-new {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.post-actions {
|
||||
/* overriding display: here was causing hidden element to take up space */
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
Loading…
Reference in New Issue