From f9722f8598985278961dc0d0619124459a02ff9b Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Fri, 12 Feb 2016 16:57:24 -0500 Subject: [PATCH] Add custom post icons to PluginAPI --- app/assets/javascripts/discourse.js | 4 +- .../discourse/components/poster-name.js.es6 | 79 +------------------ .../discourse/lib/plugin-api.js.es6 | 45 ++++++++++- .../discourse/lib/transform-post.js.es6 | 1 + .../discourse/templates/badges/show.hbs | 2 +- .../discourse/widgets/poster-name.js.es6 | 24 ++++++ 6 files changed, 74 insertions(+), 81 deletions(-) diff --git a/app/assets/javascripts/discourse.js b/app/assets/javascripts/discourse.js index 553d70fb45c..ab0a429832b 100644 --- a/app/assets/javascripts/discourse.js +++ b/app/assets/javascripts/discourse.js @@ -161,7 +161,9 @@ function methodMissing() { "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) { define(moduleName, [], function() { return new RemovedObject(moduleName); }); diff --git a/app/assets/javascripts/discourse/components/poster-name.js.es6 b/app/assets/javascripts/discourse/components/poster-name.js.es6 index 7f213f7c00e..15ca5404049 100644 --- a/app/assets/javascripts/discourse/components/poster-name.js.es6 +++ b/app/assets/javascripts/discourse/components/poster-name.js.es6 @@ -1,77 +1,2 @@ -import { setting } from 'discourse/lib/computed'; - -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("" + username + ""); - - // Add a glyph if we have one - const glyph = this.posterGlyph(post); - if (!Em.isEmpty(glyph)) { - buffer.push(glyph); - } - buffer.push(""); - - // Are we showing full names? - if (name && this.get('displayNameOnPosts') && (this.sanitizeName(name) !== this.sanitizeName(username))) { - name = Discourse.Utilities.escapeExpression(name); - buffer.push("" + name + ""); - } - - // User titles - let title = post.get('user_title'); - if (!Em.isEmpty(title)) { - - title = Discourse.Utilities.escapeExpression(title); - buffer.push(''); - if (Em.isEmpty(primaryGroupName)) { - buffer.push(title); - } else { - buffer.push("" + title + ""); - } - buffer.push(""); - } - - 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 ''; - } - } -}); - -// Support for event triggering -PosterNameComponent.reopenClass(Em.Evented); - -export default PosterNameComponent; +const removed = new Discourse.RemovedObject('discourse/components/poster-name'); +export default removed; diff --git a/app/assets/javascripts/discourse/lib/plugin-api.js.es6 b/app/assets/javascripts/discourse/lib/plugin-api.js.es6 index c65b6a241fd..156f74a317e 100644 --- a/app/assets/javascripts/discourse/lib/plugin-api.js.es6 +++ b/app/assets/javascripts/discourse/lib/plugin-api.js.es6 @@ -1,5 +1,6 @@ import { addDecorator } from 'discourse/widgets/post-cooked'; import ComposerEditor from 'discourse/components/composer-editor'; +import { addPosterIcon } from 'discourse/widgets/poster-name'; let _decorateId = 0; function decorate(klass, evt, cb) { @@ -18,21 +19,61 @@ class PluginApi { 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) { addDecorator(cb); decorate(ComposerEditor, 'previewRefreshed', 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; - export function getPluginApi(version) { if (version === "0.1") { if (!_pluginv01) { _pluginv01 = new PluginApi(version, Discourse.__container__); } return _pluginv01; + } else { + throw `Plugin API v${version} is not supported`; } } - diff --git a/app/assets/javascripts/discourse/lib/transform-post.js.es6 b/app/assets/javascripts/discourse/lib/transform-post.js.es6 index 7cb39896975..cad1e263302 100644 --- a/app/assets/javascripts/discourse/lib/transform-post.js.es6 +++ b/app/assets/javascripts/discourse/lib/transform-post.js.es6 @@ -96,6 +96,7 @@ export default function transformPost(currentUser, site, post, prevPost, nextPos postAtts.linkCounts = post.link_counts; postAtts.actionCode = post.action_code; postAtts.actionCodeWho = post.action_code_who; + postAtts.userCustomFields = post.user_custom_fields; const showPMMap = topic.archetype === 'private_message' && post.post_number === 1; if (showPMMap) { diff --git a/app/assets/javascripts/discourse/templates/badges/show.hbs b/app/assets/javascripts/discourse/templates/badges/show.hbs index 7cfada24304..e41eb32ef1d 100644 --- a/app/assets/javascripts/discourse/templates/badges/show.hbs +++ b/app/assets/javascripts/discourse/templates/badges/show.hbs @@ -29,7 +29,7 @@ {{#link-to 'user' user}} {{avatar user imageSize="extra_large"}}
- {{poster-name post=user}} +
{{user.username}}
{{/link-to}}
diff --git a/app/assets/javascripts/discourse/widgets/poster-name.js.es6 b/app/assets/javascripts/discourse/widgets/poster-name.js.es6 index 3c91a68d5cd..e8e7923b99a 100644 --- a/app/assets/javascripts/discourse/widgets/poster-name.js.es6 +++ b/app/assets/javascripts/discourse/widgets/poster-name.js.es6 @@ -6,6 +6,11 @@ function sanitizeName(name){ return name.toLowerCase().replace(/[\s_-]/g,''); } +const _callbacks = []; +export function addPosterIcon(cb) { + _callbacks.push(cb); +} + export default createWidget('poster-name', { tagName: 'div.names.trigger-user-card', @@ -56,6 +61,25 @@ export default createWidget('poster-name', { 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; } });