Add custom post icons to PluginAPI

This commit is contained in:
Robin Ward 2016-02-12 16:57:24 -05:00
parent 9b8871d7dd
commit f9722f8598
6 changed files with 74 additions and 81 deletions

View File

@ -161,7 +161,9 @@ function methodMissing() {
"and your plugin needs to be updated."); "and your plugin needs to be updated.");
}; };
['reopen', 'registerButton'].forEach(function(m) { RemovedObject.prototype[m] = methodMissing; }); Discourse.RemovedObject = RemovedObject;
['reopen', 'registerButton', 'on', 'off'].forEach(function(m) { RemovedObject.prototype[m] = methodMissing; });
['discourse/views/post', 'discourse/components/post-menu'].forEach(function(moduleName) { ['discourse/views/post', 'discourse/components/post-menu'].forEach(function(moduleName) {
define(moduleName, [], function() { return new RemovedObject(moduleName); }); define(moduleName, [], function() { return new RemovedObject(moduleName); });

View File

@ -1,77 +1,2 @@
import { setting } from 'discourse/lib/computed'; const removed = new Discourse.RemovedObject('discourse/components/poster-name');
export default removed;
const PosterNameComponent = Em.Component.extend({
classNames: ['names', 'trigger-user-card'],
displayNameOnPosts: setting('display_name_on_posts'),
// sanitize name for comparison
sanitizeName(name){
return name.toLowerCase().replace(/[\s_-]/g,'');
},
render(buffer) {
const post = this.get('post');
if (post) {
const username = post.get('username'),
primaryGroupName = post.get('primary_group_name'),
url = post.get('usernameUrl');
var linkClass = 'username',
name = post.get('name');
if (post.get('staff')) { linkClass += ' staff'; }
if (post.get('admin')) { linkClass += ' admin'; }
if (post.get('moderator')) { linkClass += ' moderator'; }
if (post.get('new_user')) { linkClass += ' new-user'; }
if (!Em.isEmpty(primaryGroupName)) {
linkClass += ' ' + primaryGroupName;
}
// Main link
buffer.push("<span class='" + linkClass + "'><a href='" + url + "' data-auto-route='true' data-user-card='" + username + "'>" + username + "</a>");
// Add a glyph if we have one
const glyph = this.posterGlyph(post);
if (!Em.isEmpty(glyph)) {
buffer.push(glyph);
}
buffer.push("</span>");
// Are we showing full names?
if (name && this.get('displayNameOnPosts') && (this.sanitizeName(name) !== this.sanitizeName(username))) {
name = Discourse.Utilities.escapeExpression(name);
buffer.push("<span class='full-name'><a href='" + url + "' data-auto-route='true' data-user-card='" + username + "'>" + name + "</a></span>");
}
// User titles
let title = post.get('user_title');
if (!Em.isEmpty(title)) {
title = Discourse.Utilities.escapeExpression(title);
buffer.push('<span class="user-title">');
if (Em.isEmpty(primaryGroupName)) {
buffer.push(title);
} else {
buffer.push("<a href='/groups/" + post.get('primary_group_name') + "' class='user-group'>" + title + "</a>");
}
buffer.push("</span>");
}
PosterNameComponent.trigger('renderedName', buffer, post);
}
},
// Overwrite this to give a user a custom font awesome glyph.
posterGlyph(post) {
if(post.get('moderator')) {
const desc = I18n.t('user.moderator_tooltip');
return '<i class="fa fa-shield" title="' + desc + '" alt="' + desc + '"></i>';
}
}
});
// Support for event triggering
PosterNameComponent.reopenClass(Em.Evented);
export default PosterNameComponent;

View File

@ -1,5 +1,6 @@
import { addDecorator } from 'discourse/widgets/post-cooked'; import { addDecorator } from 'discourse/widgets/post-cooked';
import ComposerEditor from 'discourse/components/composer-editor'; import ComposerEditor from 'discourse/components/composer-editor';
import { addPosterIcon } from 'discourse/widgets/poster-name';
let _decorateId = 0; let _decorateId = 0;
function decorate(klass, evt, cb) { function decorate(klass, evt, cb) {
@ -18,21 +19,61 @@ class PluginApi {
this.container = container; this.container = container;
} }
/**
* decorateCooked(callback)
*
* Used for decorating the `cooked` content of a post after it is rendered using
* jQuery.
*
* `callback` will be called when it is time to decorate with a jQuery selector.
*
* For example, to add a yellow background to all posts you could do this:
*
* ```
* api.decorateCooked($elem => $elem.css({ backgroundColor: 'yellow' }));
* ```
**/
decorateCooked(cb) { decorateCooked(cb) {
addDecorator(cb); addDecorator(cb);
decorate(ComposerEditor, 'previewRefreshed', cb); decorate(ComposerEditor, 'previewRefreshed', cb);
decorate(this.container.lookupFactory('view:user-stream'), 'didInsertElement', cb); decorate(this.container.lookupFactory('view:user-stream'), 'didInsertElement', cb);
} }
/**
* addPosterIcon(callback)
*
* This function can be used to add an icon with a link that will be displayed
* beside a poster's name. The `callback` is called with the post's user custom
* fields, and will render an icon if it receives an object back.
*
* The returned object can have the following attributes:
*
* icon (required) the font awesome icon to render
* className (optional) a css class to apply to the icon
* url (optional) where to link the icon
* title (optional) the tooltip title for the icon on hover
*
* ```
* api.addPosterIcon(cfs => {
* if (cfs.customer) {
* return { icon: 'user', className: 'customer', title: 'customer' };
* }
* });
* ```
**/
addPosterIcon(cb) {
addPosterIcon(cb);
}
} }
let _pluginv01; let _pluginv01;
export function getPluginApi(version) { export function getPluginApi(version) {
if (version === "0.1") { if (version === "0.1") {
if (!_pluginv01) { if (!_pluginv01) {
_pluginv01 = new PluginApi(version, Discourse.__container__); _pluginv01 = new PluginApi(version, Discourse.__container__);
} }
return _pluginv01; return _pluginv01;
} else {
throw `Plugin API v${version} is not supported`;
} }
} }

View File

@ -96,6 +96,7 @@ export default function transformPost(currentUser, site, post, prevPost, nextPos
postAtts.linkCounts = post.link_counts; postAtts.linkCounts = post.link_counts;
postAtts.actionCode = post.action_code; postAtts.actionCode = post.action_code;
postAtts.actionCodeWho = post.action_code_who; postAtts.actionCodeWho = post.action_code_who;
postAtts.userCustomFields = post.user_custom_fields;
const showPMMap = topic.archetype === 'private_message' && post.post_number === 1; const showPMMap = topic.archetype === 'private_message' && post.post_number === 1;
if (showPMMap) { if (showPMMap) {

View File

@ -29,7 +29,7 @@
{{#link-to 'user' user}} {{#link-to 'user' user}}
{{avatar user imageSize="extra_large"}} {{avatar user imageSize="extra_large"}}
<div class="details clearfix"> <div class="details clearfix">
{{poster-name post=user}} <div class='username'>{{user.username}}</div>
</div> </div>
{{/link-to}} {{/link-to}}
<div class='earned'> <div class='earned'>

View File

@ -6,6 +6,11 @@ function sanitizeName(name){
return name.toLowerCase().replace(/[\s_-]/g,''); return name.toLowerCase().replace(/[\s_-]/g,'');
} }
const _callbacks = [];
export function addPosterIcon(cb) {
_callbacks.push(cb);
}
export default createWidget('poster-name', { export default createWidget('poster-name', {
tagName: 'div.names.trigger-user-card', tagName: 'div.names.trigger-user-card',
@ -56,6 +61,25 @@ export default createWidget('poster-name', {
contents.push(h('span.user-title', titleContents)); contents.push(h('span.user-title', titleContents));
} }
const cfs = attrs.userCustomFields;
if (cfs) {
_callbacks.forEach(cb => {
const result = cb(cfs);
if (result) {
let iconBody = iconNode(result.icon);
if (result.url) {
iconBody = h('a', { attributes: { href: result.url } }, iconBody);
}
contents.push(h('span',
{ className: result.className,
attributes: { title: result.title }
},
iconBody));
}
});
}
return contents; return contents;
} }
}); });