mirror of
https://github.com/discourse/discourse.git
synced 2025-05-29 21:27:58 +08:00
Adds primary user group as a class to quote (#5285)
* Adds primary user group as a class to quote This feature addition will add the class `group-PRIMARY_USER_GROUP` to the quote `aside`. `PRIMARY_USER_GROUP` will be the primary user group of the user being quoted. This is similar to the class that is added to a `topic-post`. * Remove trailing whitespace * Fix avatar in test * Address PR comments * Fix trailing whitespace
This commit is contained in:
@ -75,6 +75,19 @@ export default Ember.Component.extend({
|
|||||||
return tinyAvatar(quotedPost.get('avatar_template'));
|
return tinyAvatar(quotedPost.get('avatar_template'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
lookupPrimaryUserGroupByPostNumber: (postNumber, topicId) => {
|
||||||
|
const topic = this.get('topic');
|
||||||
|
if (!topic) { return; }
|
||||||
|
|
||||||
|
const posts = topic.get('postStream.posts');
|
||||||
|
if (posts && topicId === topic.get('id')) {
|
||||||
|
const quotedPost = posts.findBy("post_number", postNumber);
|
||||||
|
if (quotedPost) {
|
||||||
|
return quotedPost.primary_group_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -9,7 +9,7 @@ const rule = {
|
|||||||
let options = state.md.options.discourse;
|
let options = state.md.options.discourse;
|
||||||
|
|
||||||
let quoteInfo = attrs['_default'];
|
let quoteInfo = attrs['_default'];
|
||||||
let username, postNumber, topicId, avatarImg, full;
|
let username, postNumber, topicId, avatarImg, primaryGroupName, full;
|
||||||
|
|
||||||
if (quoteInfo) {
|
if (quoteInfo) {
|
||||||
let split = quoteInfo.split(/\,\s*/);
|
let split = quoteInfo.split(/\,\s*/);
|
||||||
@ -34,9 +34,30 @@ const rule = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.lookupAvatarByPostNumber) {
|
||||||
|
// client-side, we can retrieve the avatar from the post
|
||||||
|
avatarImg = options.lookupAvatarByPostNumber(postNumber, topicId);
|
||||||
|
} else if (options.lookupAvatar) {
|
||||||
|
// server-side, we need to lookup the avatar from the username
|
||||||
|
avatarImg = options.lookupAvatar(username);
|
||||||
|
}
|
||||||
|
|
||||||
let token = state.push('bbcode_open', 'aside', 1);
|
if (options.lookupPrimaryUserGroupByPostNumber) {
|
||||||
token.attrs = [['class', 'quote']];
|
// client-side, we can retrieve the primary user group from the post
|
||||||
|
primaryGroupName = options.lookupPrimaryUserGroupByPostNumber(postNumber, topicId);
|
||||||
|
} else if (options.lookupPrimaryUserGroup) {
|
||||||
|
// server-side, we need to lookup the primary user group from the username
|
||||||
|
primaryGroupName = options.lookupPrimaryUserGroup(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
let token = state.push('bbcode_open', 'aside', 1);
|
||||||
|
token.attrs = [];
|
||||||
|
|
||||||
|
if (primaryGroupName && primaryGroupName.length !== 0) {
|
||||||
|
token.attrs.push(['class', `quote group-${primaryGroupName}`]);
|
||||||
|
} else {
|
||||||
|
token.attrs.push(['class', 'quote']);
|
||||||
|
}
|
||||||
|
|
||||||
if (postNumber) {
|
if (postNumber) {
|
||||||
token.attrs.push(['data-post', postNumber]);
|
token.attrs.push(['data-post', postNumber]);
|
||||||
@ -50,14 +71,6 @@ const rule = {
|
|||||||
token.attrs.push(['data-full', 'true']);
|
token.attrs.push(['data-full', 'true']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.lookupAvatarByPostNumber) {
|
|
||||||
// client-side, we can retrieve the avatar from the post
|
|
||||||
avatarImg = options.lookupAvatarByPostNumber(postNumber, topicId);
|
|
||||||
} else if (options.lookupAvatar) {
|
|
||||||
// server-side, we need to lookup the avatar from the username
|
|
||||||
avatarImg = options.lookupAvatar(username);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (username) {
|
if (username) {
|
||||||
let offTopicQuote = options.topicId &&
|
let offTopicQuote = options.topicId &&
|
||||||
postNumber &&
|
postNumber &&
|
||||||
@ -132,4 +145,11 @@ export function setup(helper) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
helper.whiteList(['img[class=avatar]']);
|
helper.whiteList(['img[class=avatar]']);
|
||||||
|
helper.whiteList({
|
||||||
|
custom(tag, name, value) {
|
||||||
|
if (tag === 'aside' && name === 'class') {
|
||||||
|
return !!/^quote group\-(.+)$/.exec(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ export function buildOptions(state) {
|
|||||||
siteSettings,
|
siteSettings,
|
||||||
getURL,
|
getURL,
|
||||||
lookupAvatar,
|
lookupAvatar,
|
||||||
|
lookupPrimaryUserGroup,
|
||||||
getTopicInfo,
|
getTopicInfo,
|
||||||
topicId,
|
topicId,
|
||||||
categoryHashtagLookup,
|
categoryHashtagLookup,
|
||||||
@ -19,6 +20,7 @@ export function buildOptions(state) {
|
|||||||
getCurrentUser,
|
getCurrentUser,
|
||||||
currentUser,
|
currentUser,
|
||||||
lookupAvatarByPostNumber,
|
lookupAvatarByPostNumber,
|
||||||
|
lookupPrimaryUserGroupByPostNumber,
|
||||||
emojiUnicodeReplacer,
|
emojiUnicodeReplacer,
|
||||||
lookupInlineOnebox,
|
lookupInlineOnebox,
|
||||||
lookupImageUrls,
|
lookupImageUrls,
|
||||||
@ -50,6 +52,7 @@ export function buildOptions(state) {
|
|||||||
getURL,
|
getURL,
|
||||||
features,
|
features,
|
||||||
lookupAvatar,
|
lookupAvatar,
|
||||||
|
lookupPrimaryUserGroup,
|
||||||
getTopicInfo,
|
getTopicInfo,
|
||||||
topicId,
|
topicId,
|
||||||
categoryHashtagLookup,
|
categoryHashtagLookup,
|
||||||
@ -57,6 +60,7 @@ export function buildOptions(state) {
|
|||||||
getCurrentUser,
|
getCurrentUser,
|
||||||
currentUser,
|
currentUser,
|
||||||
lookupAvatarByPostNumber,
|
lookupAvatarByPostNumber,
|
||||||
|
lookupPrimaryUserGroupByPostNumber,
|
||||||
mentionLookup,
|
mentionLookup,
|
||||||
emojiUnicodeReplacer,
|
emojiUnicodeReplacer,
|
||||||
lookupInlineOnebox,
|
lookupInlineOnebox,
|
||||||
|
@ -158,6 +158,7 @@ module PrettyText
|
|||||||
__optInput.getURL = __getURL;
|
__optInput.getURL = __getURL;
|
||||||
__optInput.getCurrentUser = __getCurrentUser;
|
__optInput.getCurrentUser = __getCurrentUser;
|
||||||
__optInput.lookupAvatar = __lookupAvatar;
|
__optInput.lookupAvatar = __lookupAvatar;
|
||||||
|
__optInput.lookupPrimaryUserGroup = __lookupPrimaryUserGroup;
|
||||||
__optInput.getTopicInfo = __getTopicInfo;
|
__optInput.getTopicInfo = __getTopicInfo;
|
||||||
__optInput.categoryHashtagLookup = __categoryLookup;
|
__optInput.categoryHashtagLookup = __categoryLookup;
|
||||||
__optInput.mentionLookup = __mentionLookup;
|
__optInput.mentionLookup = __mentionLookup;
|
||||||
|
@ -25,6 +25,14 @@ module PrettyText
|
|||||||
UrlHelper.schemaless(UrlHelper.absolute(user.avatar_template))
|
UrlHelper.schemaless(UrlHelper.absolute(user.avatar_template))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def lookup_primary_user_group(username)
|
||||||
|
return "" unless username
|
||||||
|
user = User.find_by(username_lower: username.downcase)
|
||||||
|
return "" unless user.present?
|
||||||
|
|
||||||
|
user.primary_group.try(:name) || ""
|
||||||
|
end
|
||||||
|
|
||||||
def mention_lookup(name)
|
def mention_lookup(name)
|
||||||
return false if name.blank?
|
return false if name.blank?
|
||||||
return "group" if Group.exists?(name: name)
|
return "group" if Group.exists?(name: name)
|
||||||
|
@ -73,6 +73,10 @@ function __lookupAvatar(p) {
|
|||||||
return __utils.avatarImg({size: "tiny", avatarTemplate: __helpers.avatar_template(p) }, __getURL);
|
return __utils.avatarImg({size: "tiny", avatarTemplate: __helpers.avatar_template(p) }, __getURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function __lookupPrimaryUserGroup(p) {
|
||||||
|
return __helpers.lookup_primary_user_group(p);
|
||||||
|
}
|
||||||
|
|
||||||
function __getCurrentUser(userId) {
|
function __getCurrentUser(userId) {
|
||||||
return __helpers.get_current_user(userId);
|
return __helpers.get_current_user(userId);
|
||||||
}
|
}
|
||||||
|
@ -113,6 +113,34 @@ describe PrettyText do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "with primary user group" do
|
||||||
|
let(:default_avatar) { "//test.localhost/uploads/default/avatars/42d/57c/46ce7ee487/{size}.png" }
|
||||||
|
let(:group) { Fabricate(:group) }
|
||||||
|
let!(:user) { Fabricate(:user, primary_group: group) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
User.stubs(:default_template).returns(default_avatar)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "adds primary group class to referenced users quote" do
|
||||||
|
|
||||||
|
topic = Fabricate(:topic, title: "this is a test topic")
|
||||||
|
expected = <<~HTML
|
||||||
|
<aside class="quote group-#{group.name}" data-topic="#{topic.id}" data-post="2">
|
||||||
|
<div class="title">
|
||||||
|
<div class="quote-controls"></div>
|
||||||
|
<img alt class='avatar' height='20' src='//test.localhost/uploads/default/avatars/42d/57c/46ce7ee487/40.png' width='20'><a href='http://test.localhost/t/this-is-a-test-topic/#{topic.id}/2'>This is a test topic</a>
|
||||||
|
</div>
|
||||||
|
<blockquote>
|
||||||
|
<p>ddd</p>
|
||||||
|
</blockquote>
|
||||||
|
</aside>
|
||||||
|
HTML
|
||||||
|
|
||||||
|
expect(cook("[quote=\"#{user.username}, post:2, topic:#{topic.id}\"]\nddd\n[/quote]", topic_id: 1)).to eq(n(expected))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it "can handle inline block bbcode" do
|
it "can handle inline block bbcode" do
|
||||||
cooked = PrettyText.cook("[quote]te **s** t[/quote]")
|
cooked = PrettyText.cook("[quote]te **s** t[/quote]")
|
||||||
|
|
||||||
|
@ -244,7 +244,6 @@ QUnit.test("Quotes", assert => {
|
|||||||
</aside>`,
|
</aside>`,
|
||||||
"works with multiple lines");
|
"works with multiple lines");
|
||||||
|
|
||||||
|
|
||||||
assert.cookedOptions("[quote=\"bob, post:1\"]\nmy quote\n[/quote]",
|
assert.cookedOptions("[quote=\"bob, post:1\"]\nmy quote\n[/quote]",
|
||||||
{ topicId: 2, lookupAvatar: function() { } },
|
{ topicId: 2, lookupAvatar: function() { } },
|
||||||
`<aside class=\"quote\" data-post=\"1\">
|
`<aside class=\"quote\" data-post=\"1\">
|
||||||
@ -270,6 +269,16 @@ QUnit.test("Quotes", assert => {
|
|||||||
</aside>`,
|
</aside>`,
|
||||||
"handles nested quotes properly");
|
"handles nested quotes properly");
|
||||||
|
|
||||||
|
assert.cookedOptions(`[quote="bob, post:1, topic:1"]\ntest quote\n[/quote]`, { lookupPrimaryUserGroupByPostNumber: () => "aUserGroup" },
|
||||||
|
`<aside class="quote group-aUserGroup" data-post="1" data-topic="1">
|
||||||
|
<div class="title">
|
||||||
|
<div class="quote-controls"></div>
|
||||||
|
bob:</div>
|
||||||
|
<blockquote>
|
||||||
|
<p>test quote</p>
|
||||||
|
</blockquote>
|
||||||
|
</aside>`,
|
||||||
|
"quote has group class");
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test("Mentions", assert => {
|
QUnit.test("Mentions", assert => {
|
||||||
|
Reference in New Issue
Block a user