mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
Merge pull request #4522 from fantasticfears/featured-link
FEATURE: Allow posting a link with the topic
This commit is contained in:
@@ -13,7 +13,8 @@ export default Ember.Component.extend({
|
||||
'composer.canEditTitle:edit-title',
|
||||
'composer.createdPost:created-post',
|
||||
'composer.creatingTopic:topic',
|
||||
'composer.whisper:composing-whisper'],
|
||||
'composer.whisper:composing-whisper',
|
||||
'composer.showComposerEditor::topic-featured-link-only'],
|
||||
|
||||
@computed('composer.composeState')
|
||||
composeState(composeState) {
|
||||
@@ -27,7 +28,7 @@ export default Ember.Component.extend({
|
||||
this.appEvents.trigger("composer:resized");
|
||||
},
|
||||
|
||||
@observes('composeState', 'composer.action')
|
||||
@observes('composeState', 'composer.action', 'composer.canEditTopicFeaturedLink')
|
||||
resize() {
|
||||
Ember.run.scheduleOnce('afterRender', () => {
|
||||
if (!this.element || this.isDestroying || this.isDestroyed) { return; }
|
||||
|
||||
@@ -21,6 +21,9 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
if (this.site.mobileView) { this.set("viewMode", "inline"); }
|
||||
}.on("init"),
|
||||
|
||||
previousFeaturedLink: Em.computed.alias('model.featured_link_changes.previous'),
|
||||
currentFeaturedLink: Em.computed.alias('model.featured_link_changes.current'),
|
||||
|
||||
previousTagChanges: customTagArray('model.tags_changes.previous'),
|
||||
currentTagChanges: customTagArray('model.tags_changes.current'),
|
||||
|
||||
|
||||
@@ -160,6 +160,14 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
||||
return post => this.postSelected(post);
|
||||
}.property(),
|
||||
|
||||
@computed('model.isPrivateMessage', 'model.category.id')
|
||||
canEditTopicFeaturedLink(isPrivateMessage, categoryId) {
|
||||
if (!this.siteSettings.topic_featured_link_enabled || isPrivateMessage) { return false; }
|
||||
|
||||
const categoryIds = this.site.get('topic_featured_link_allowed_category_ids');
|
||||
return categoryIds === undefined || !categoryIds.length || categoryIds.indexOf(categoryId) !== -1;
|
||||
},
|
||||
|
||||
@computed('model.isPrivateMessage')
|
||||
canEditTags(isPrivateMessage) {
|
||||
return !isPrivateMessage && this.site.get('can_tag_topics');
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { registerUnbound } from 'discourse-common/lib/helpers';
|
||||
import renderTopicFeaturedLink from 'discourse/lib/render-topic-featured-link';
|
||||
|
||||
export default registerUnbound('topic-featured-link', function(topic, params) {
|
||||
return new Handlebars.SafeString(renderTopicFeaturedLink(topic, params));
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
import { extractDomainFromUrl } from 'discourse/lib/utilities';
|
||||
import { h } from 'virtual-dom';
|
||||
|
||||
const _decorators = [];
|
||||
|
||||
export function addFeaturedLinkMetaDecorator(decorator) {
|
||||
_decorators.push(decorator);
|
||||
}
|
||||
|
||||
function extractLinkMeta(topic) {
|
||||
const href = topic.featured_link, target = Discourse.SiteSettings.open_topic_featured_link_in_external_window ? '_blank' : '';
|
||||
if (!href) { return; }
|
||||
|
||||
let domain = extractDomainFromUrl(href);
|
||||
if (!domain) { return; }
|
||||
|
||||
// www appears frequently, so we truncate it
|
||||
if (domain && domain.substr(0, 4) === 'www.') {
|
||||
domain = domain.substring(4);
|
||||
}
|
||||
|
||||
const meta = { target, href, domain, rel: 'nofollow' };
|
||||
if (_decorators.length) {
|
||||
_decorators.forEach(cb => cb(meta));
|
||||
}
|
||||
return meta;
|
||||
}
|
||||
|
||||
export default function renderTopicFeaturedLink(topic) {
|
||||
const meta = extractLinkMeta(topic);
|
||||
if (meta) {
|
||||
return `<a class="topic-featured-link" rel="${meta.rel}" target="${meta.target}" href="${meta.href}">${meta.domain}</a>`;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
export function topicFeaturedLinkNode(topic) {
|
||||
const meta = extractLinkMeta(topic);
|
||||
if (meta) {
|
||||
return h('a.topic-featured-link', {
|
||||
attributes: { href: meta.href, rel: meta.rel, target: meta.target }
|
||||
}, meta.domain);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,6 +169,18 @@ const Category = RestModel.extend({
|
||||
@computed("id")
|
||||
isUncategorizedCategory(id) {
|
||||
return id === Discourse.Site.currentProp("uncategorized_category_id");
|
||||
},
|
||||
|
||||
@computed('custom_fields.topic_featured_link_allowed')
|
||||
topicFeaturedLinkAllowed: {
|
||||
get(allowed) {
|
||||
return allowed === "true";
|
||||
},
|
||||
set(value) {
|
||||
value = value ? "true" : "false";
|
||||
this.set("custom_fields.topic_featured_link_allowed", value);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -32,13 +32,15 @@ const CLOSED = 'closed',
|
||||
target_usernames: 'targetUsernames',
|
||||
typing_duration_msecs: 'typingTime',
|
||||
composer_open_duration_msecs: 'composerTime',
|
||||
tags: 'tags'
|
||||
tags: 'tags',
|
||||
featured_link: 'featuredLink'
|
||||
},
|
||||
|
||||
_edit_topic_serializer = {
|
||||
title: 'topic.title',
|
||||
categoryId: 'topic.category.id',
|
||||
tags: 'topic.tags'
|
||||
tags: 'topic.tags',
|
||||
featuredLink: 'topic.featured_link'
|
||||
};
|
||||
|
||||
const Composer = RestModel.extend({
|
||||
@@ -136,6 +138,14 @@ const Composer = RestModel.extend({
|
||||
canEditTitle: Em.computed.or('creatingTopic', 'creatingPrivateMessage', 'editingFirstPost'),
|
||||
canCategorize: Em.computed.and('canEditTitle', 'notCreatingPrivateMessage'),
|
||||
|
||||
@computed('canEditTitle', 'creatingPrivateMessage', 'categoryId')
|
||||
canEditTopicFeaturedLink(canEditTitle, creatingPrivateMessage, categoryId) {
|
||||
if (!this.siteSettings.topic_featured_link_enabled || !canEditTitle || creatingPrivateMessage) { return false; }
|
||||
|
||||
const categoryIds = this.site.get('topic_featured_link_allowed_category_ids');
|
||||
return categoryIds === undefined || !categoryIds.length || categoryIds.indexOf(categoryId) !== -1;
|
||||
},
|
||||
|
||||
// Determine the appropriate title for this action
|
||||
actionTitle: function() {
|
||||
const topic = this.get('topic');
|
||||
@@ -180,6 +190,10 @@ const Composer = RestModel.extend({
|
||||
|
||||
}.property('action', 'post', 'topic', 'topic.title'),
|
||||
|
||||
@computed('canEditTopicFeaturedLink')
|
||||
showComposerEditor(canEditTopicFeaturedLink) {
|
||||
return canEditTopicFeaturedLink ? !this.siteSettings.topic_featured_link_onebox : true;
|
||||
},
|
||||
|
||||
// whether to disable the post button
|
||||
cantSubmitPost: function() {
|
||||
@@ -269,11 +283,12 @@ const Composer = RestModel.extend({
|
||||
}
|
||||
}.property('privateMessage'),
|
||||
|
||||
missingReplyCharacters: function() {
|
||||
const postType = this.get('post.post_type');
|
||||
if (postType === this.site.get('post_types.small_action')) { return 0; }
|
||||
return this.get('minimumPostLength') - this.get('replyLength');
|
||||
}.property('minimumPostLength', 'replyLength'),
|
||||
@computed('minimumPostLength', 'replyLength', 'canEditTopicFeaturedLink')
|
||||
missingReplyCharacters(minimumPostLength, replyLength, canEditTopicFeaturedLink) {
|
||||
if (this.get('post.post_type') === this.site.get('post_types.small_action') ||
|
||||
canEditTopicFeaturedLink && this.siteSettings.topic_featured_link_onebox) { return 0; }
|
||||
return minimumPostLength - replyLength;
|
||||
},
|
||||
|
||||
/**
|
||||
Minimum number of characters for a post body to be valid.
|
||||
@@ -492,6 +507,14 @@ const Composer = RestModel.extend({
|
||||
|
||||
save(opts) {
|
||||
if (!this.get('cantSubmitPost')) {
|
||||
|
||||
// change category may result in some effect for topic featured link
|
||||
if (this.get('canEditTopicFeaturedLink')) {
|
||||
if (this.siteSettings.topic_featured_link_onebox) { this.set('reply', null); }
|
||||
} else {
|
||||
this.set('featuredLink', null);
|
||||
}
|
||||
|
||||
return this.get('editingPost') ? this.editPost(opts) : this.createPost(opts);
|
||||
}
|
||||
},
|
||||
@@ -512,7 +535,8 @@ const Composer = RestModel.extend({
|
||||
stagedPost: false,
|
||||
typingTime: 0,
|
||||
composerOpened: null,
|
||||
composerTotalOpened: 0
|
||||
composerTotalOpened: 0,
|
||||
featuredLink: null
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -19,6 +19,17 @@
|
||||
</label>
|
||||
</section>
|
||||
|
||||
{{#if siteSettings.topic_featured_link_enabled}}
|
||||
<section class='field'>
|
||||
<div class="allowed-topic-featured-link-category">
|
||||
<label class="checkbox-label">
|
||||
{{input type="checkbox" checked=category.topicFeaturedLinkAllowed}}
|
||||
{{i18n 'category.topic_featured_link_allowed'}}
|
||||
</label>
|
||||
</div>
|
||||
</section>
|
||||
{{/if}}
|
||||
|
||||
<section class="field">
|
||||
<label>
|
||||
{{i18n "category.sort_order"}}
|
||||
|
||||
@@ -2,12 +2,16 @@
|
||||
{{bound-category-link topic.category.parentCategory}}
|
||||
{{/if}}
|
||||
{{bound-category-link topic.category hideParent=true}}
|
||||
{{#if siteSettings.tagging_enabled}}
|
||||
<div class="list-tags">
|
||||
{{#each topic.tags as |t|}}
|
||||
{{discourse-tag t}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="topic-header-extra">
|
||||
{{#if siteSettings.tagging_enabled}}
|
||||
<div class="list-tags">
|
||||
{{#each topic.tags as |t|}}
|
||||
{{discourse-tag t}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if siteSettings.topic_featured_link_enabled}}
|
||||
{{topic-featured-link topic}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{plugin-outlet "topic-category"}}
|
||||
|
||||
@@ -80,9 +80,13 @@
|
||||
{{/if}}
|
||||
{{render "additional-composer-buttons" model}}
|
||||
{{/if}}
|
||||
{{#if model.canEditTopicFeaturedLink}}
|
||||
<div class="topic-featured-link-input">
|
||||
{{text-field tabindex="4" type="url" value=model.featuredLink id='topic-featured-link' placeholderKey="composer.topic_featured_link_placeholder"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet "composer-fields"}}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
<td class='main-link clearfix' colspan="{{titleColSpan}}">
|
||||
{{raw "topic-status" topic=topic}}
|
||||
{{topic-link topic}}
|
||||
{{#if topic.featured_link}}
|
||||
{{topic-featured-link topic}}
|
||||
{{/if}}
|
||||
{{plugin-outlet "topic-list-after-title"}}
|
||||
{{#if showTopicPostBadges}}
|
||||
{{raw "topic-post-badges" unread=topic.unread newPosts=topic.displayNewPosts unseen=topic.unseen url=topic.lastUnreadUrl}}
|
||||
|
||||
@@ -86,6 +86,13 @@
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if model.featured_link_changes}}
|
||||
<div class='row'>
|
||||
{{model.featured_link_changes.previous}}
|
||||
→
|
||||
{{model.featured_link_changes.current}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet "post-revisions"}}
|
||||
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
{{category-chooser valueAttribute="id" value=buffered.category_id}}
|
||||
{{/if}}
|
||||
|
||||
{{#if canEditTopicFeaturedLink}}
|
||||
{{text-field type="url" value=buffered.featured_link id='topic-featured-link' placeholderKey="composer.topic_featured_link_placeholder"}}
|
||||
{{/if}}
|
||||
{{#if canEditTags}}
|
||||
<br>
|
||||
{{tag-chooser tags=buffered.tags categoryId=buffered.category_id}}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { iconNode } from 'discourse/helpers/fa-icon-node';
|
||||
import DiscourseURL from 'discourse/lib/url';
|
||||
import RawHtml from 'discourse/widgets/raw-html';
|
||||
import { tagNode } from 'discourse/lib/render-tag';
|
||||
import { topicFeaturedLinkNode } from 'discourse/lib/render-topic-featured-link';
|
||||
|
||||
export default createWidget('header-topic-info', {
|
||||
tagName: 'div.extra-info-wrapper',
|
||||
@@ -44,12 +45,19 @@ export default createWidget('header-topic-info', {
|
||||
title.push(this.attach('category-link', { category }));
|
||||
}
|
||||
|
||||
const extra = [];
|
||||
if (this.siteSettings.tagging_enabled) {
|
||||
const tags = topic.get('tags') || [];
|
||||
if (tags.length) {
|
||||
title.push(h('div.list-tags', tags.map(tagNode)));
|
||||
extra.push(h('div.list-tags', tags.map(tagNode)));
|
||||
}
|
||||
}
|
||||
if (this.siteSettings.topic_featured_link_enabled) {
|
||||
extra.push(topicFeaturedLinkNode(attrs.topic));
|
||||
}
|
||||
if (extra) {
|
||||
title.push(h('div.topic-header-extra', extra));
|
||||
}
|
||||
}
|
||||
|
||||
const contents = h('div.title-wrapper', title);
|
||||
|
||||
Reference in New Issue
Block a user