Plugin Outlets need their arguments to be explicit
This commit is contained in:
parent
a808bcb0b8
commit
2efe4900cf
|
@ -23,7 +23,7 @@
|
|||
{{nav-item route='admin.backups' label='admin.backups.title'}}
|
||||
{{/if}}
|
||||
{{nav-item route='adminPlugins' label='admin.plugins.title'}}
|
||||
{{plugin-outlet "admin-menu" tagName="li"}}
|
||||
{{plugin-outlet name="admin-menu" connectorTagName="li"}}
|
||||
</ul>
|
||||
|
||||
<div class='boxed white admin-content'>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{{plugin-outlet "admin-dashboard-top"}}
|
||||
{{plugin-outlet name="admin-dashboard-top"}}
|
||||
|
||||
{{#conditional-loading-spinner condition=loading}}
|
||||
<div class="dashboard-left">
|
||||
|
|
|
@ -121,7 +121,7 @@
|
|||
{{#if siteSettings.email_in}}
|
||||
<label for="incoming_email">{{i18n 'admin.groups.incoming_email'}}</label>
|
||||
{{text-field name="incoming_email" value=model.incoming_email placeholderKey="admin.groups.incoming_email_placeholder"}}
|
||||
{{plugin-outlet "group-email-in"}}
|
||||
{{plugin-outlet name="group-email-in" args=(hash model=model)}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
|
||||
|
|
|
@ -137,12 +137,21 @@ export function buildResolver(baseName) {
|
|||
return this._super(parsedName);
|
||||
},
|
||||
|
||||
findConnectorTemplate(parsedName) {
|
||||
const full = parsedName.fullNameWithoutType.replace('components/', '');
|
||||
if (full.indexOf('connectors') === 0) {
|
||||
return Ember.TEMPLATES[`javascripts/${full}`];
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
resolveTemplate(parsedName) {
|
||||
return this.findPluginMobileTemplate(parsedName) ||
|
||||
this.findPluginTemplate(parsedName) ||
|
||||
this.findMobileTemplate(parsedName) ||
|
||||
this.findTemplate(parsedName) ||
|
||||
this.findLoadingTemplate(parsedName) ||
|
||||
this.findConnectorTemplate(parsedName) ||
|
||||
Ember.TEMPLATES.not_found;
|
||||
},
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
export default Ember.Component.extend({
|
||||
|
||||
init() {
|
||||
this._super();
|
||||
|
||||
const connector = this.get('connector');
|
||||
this.set('layoutName', connector.templateName);
|
||||
|
||||
const args = this.get('args') || {};
|
||||
Object.keys(args).forEach(key => this.set(key, args[key]));
|
||||
},
|
||||
|
||||
send(name, ...args) {
|
||||
const connectorClass = this.get('connector.connectorClass');
|
||||
const action = connectorClass.actions[name];
|
||||
return action ? action.call(this, ...args) : this._super(name, ...args);
|
||||
}
|
||||
|
||||
});
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
A plugin outlet is an extension point for templates where other templates can
|
||||
be inserted by plugins.
|
||||
|
||||
## Usage
|
||||
|
||||
If your handlebars template has:
|
||||
|
||||
```handlebars
|
||||
{{plugin-outlet name="evil-trout"}}
|
||||
```
|
||||
|
||||
Then any handlebars files you create in the `connectors/evil-trout` directory
|
||||
will automatically be appended. For example:
|
||||
|
||||
plugins/hello/assets/javascripts/discourse/templates/connectors/evil-trout/hello.hbs
|
||||
|
||||
With the contents:
|
||||
|
||||
```handlebars
|
||||
<b>Hello World</b>
|
||||
```
|
||||
|
||||
Will insert <b>Hello World</b> at that point in the template.
|
||||
|
||||
## Disabling
|
||||
|
||||
If a plugin returns a disabled status, the outlets will not be wired up for it.
|
||||
The list of disabled plugins is returned via the `Site` singleton.
|
||||
|
||||
**/
|
||||
import { connectorsFor } from 'discourse/lib/plugin-connectors';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
tagName: 'span',
|
||||
connectors: null,
|
||||
|
||||
init() {
|
||||
this._super();
|
||||
const name = this.get('name');
|
||||
|
||||
if (name) {
|
||||
const args = this.get('args');
|
||||
const connectors = connectorsFor(name).filter(con => {
|
||||
return con.connectorClass.shouldRender(args);
|
||||
});
|
||||
|
||||
this.set('connectors', connectors);
|
||||
}
|
||||
}
|
||||
});
|
|
@ -1,141 +0,0 @@
|
|||
/**
|
||||
A plugin outlet is an extension point for templates where other templates can
|
||||
be inserted by plugins.
|
||||
|
||||
## Usage
|
||||
|
||||
If your handlebars template has:
|
||||
|
||||
```handlebars
|
||||
{{plugin-outlet "evil-trout"}}
|
||||
```
|
||||
|
||||
Then any handlebars files you create in the `connectors/evil-trout` directory
|
||||
will automatically be appended. For example:
|
||||
|
||||
plugins/hello/assets/javascripts/discourse/templates/connectors/evil-trout/hello.hbs
|
||||
|
||||
With the contents:
|
||||
|
||||
```handlebars
|
||||
<b>Hello World</b>
|
||||
```
|
||||
|
||||
Will insert <b>Hello World</b> at that point in the template.
|
||||
|
||||
## Disabling
|
||||
|
||||
If a plugin returns a disabled status, the outlets will not be wired up for it.
|
||||
The list of disabled plugins is returned via the `Site` singleton.
|
||||
|
||||
**/
|
||||
let _connectorCache, _templateCache;
|
||||
|
||||
function findOutlets(collection, callback) {
|
||||
const disabledPlugins = Discourse.Site.currentProp('disabled_plugins') || [];
|
||||
|
||||
Object.keys(collection).forEach(function(res) {
|
||||
if (res.indexOf("/connectors/") !== -1) {
|
||||
// Skip any disabled plugins
|
||||
for (let i=0; i<disabledPlugins.length; i++) {
|
||||
if (res.indexOf("/" + disabledPlugins[i] + "/") !== -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const segments = res.split("/");
|
||||
let outletName = segments[segments.length-2];
|
||||
const uniqueName = segments[segments.length-1];
|
||||
|
||||
callback(outletName, res, uniqueName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function clearCache() {
|
||||
_templateCache = null;
|
||||
_connectorCache = null;
|
||||
}
|
||||
|
||||
function buildConnectorCache() {
|
||||
_connectorCache = {};
|
||||
_templateCache = [];
|
||||
|
||||
findOutlets(Ember.TEMPLATES, function(outletName, resource, uniqueName) {
|
||||
_connectorCache[outletName] = _connectorCache[outletName] || [];
|
||||
|
||||
_connectorCache[outletName].push({
|
||||
templateName: resource.replace('javascripts/', ''),
|
||||
template: Ember.TEMPLATES[resource],
|
||||
classNames: `${outletName}-outlet ${uniqueName}`
|
||||
});
|
||||
});
|
||||
|
||||
Object.keys(_connectorCache).forEach(outletName => {
|
||||
const connector = _connectorCache[outletName];
|
||||
(connector || []).forEach(s => {
|
||||
_templateCache.push(s.template);
|
||||
s.templateId = parseInt(_templateCache.length - 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// unbound version of outlets, only has a template
|
||||
Handlebars.registerHelper('plugin-outlet', function(name) {
|
||||
if (!_connectorCache) { buildConnectorCache(); }
|
||||
|
||||
const connector = _connectorCache[name];
|
||||
if (connector && connector.length) {
|
||||
const output = connector.map(c => c.template({context: this}));
|
||||
return new Handlebars.SafeString(output.join(""));
|
||||
}
|
||||
});
|
||||
|
||||
export default Ember.Helper.helper(function() {
|
||||
});
|
||||
|
||||
// const { registerKeyword } = Ember.__loader.require("ember-htmlbars/keywords");
|
||||
// const { internal } = Ember.__loader.require('htmlbars-runtime');
|
||||
//
|
||||
// registerKeyword('plugin-outlet', {
|
||||
// setupState(state, env, scope, params) {
|
||||
// if (!_connectorCache) { buildConnectorCache(); }
|
||||
// return { outletName: env.hooks.getValue(params[0]) };
|
||||
// },
|
||||
//
|
||||
// render(renderNode, env, scope, params, hash, template, inverse, visitor) {
|
||||
// let state = renderNode.getState();
|
||||
// if (!state.outletName) { return true; }
|
||||
// const connector = _connectorCache[state.outletName];
|
||||
// if (!connector || connector.length === 0) { return true; }
|
||||
//
|
||||
// const listTemplate = Ember.TEMPLATES['outlet-list'];
|
||||
// listTemplate.raw.locals = ['templateId', 'outletClasses', 'tagName'];
|
||||
//
|
||||
// internal.hostBlock(renderNode, env, scope, listTemplate.raw, null, null, visitor, function(options) {
|
||||
// connector.forEach(source => {
|
||||
// const tid = source.templateId;
|
||||
// options.templates.template.yieldItem(`d-outlet-${tid}`, [
|
||||
// tid,
|
||||
// source.classNames,
|
||||
// hash.tagName || 'div'
|
||||
// ]);
|
||||
// });
|
||||
// });
|
||||
// return true;
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// registerKeyword('connector', function(morph, env, scope, params, hash, template, inverse, visitor) {
|
||||
// template = _templateCache[parseInt(env.hooks.getValue(hash.templateId))];
|
||||
//
|
||||
// env.hooks.component(morph,
|
||||
// env,
|
||||
// scope,
|
||||
// 'connector-container',
|
||||
// params,
|
||||
// hash,
|
||||
// { default: template.raw, inverse },
|
||||
// visitor);
|
||||
// return true;
|
||||
// });
|
|
@ -0,0 +1,9 @@
|
|||
import { connectorsFor } from 'discourse/lib/plugin-connectors';
|
||||
|
||||
Handlebars.registerHelper('raw-plugin-outlet', function(args) {
|
||||
const connectors = connectorsFor(args.hash.name);
|
||||
if (connectors.length) {
|
||||
const output = connectors.map(c => c.template({context: this}));
|
||||
return new Handlebars.SafeString(output.join(""));
|
||||
}
|
||||
});
|
|
@ -0,0 +1,67 @@
|
|||
let _connectorCache;
|
||||
let _extraConnectorClasses = {};
|
||||
|
||||
export function resetExtraClasses() {
|
||||
_extraConnectorClasses = {};
|
||||
}
|
||||
|
||||
// Note: In plugins, define a class by path and it will be wired up automatically
|
||||
// eg: discourse/connectors/<OUTLET NAME>/<CONNECTOR NAME>.js.es6
|
||||
export function extraConnectorClass(name, obj) {
|
||||
_extraConnectorClasses[name] = obj;
|
||||
}
|
||||
|
||||
const DefaultConnectorClass = {
|
||||
actions: {},
|
||||
shouldRender: () => true
|
||||
};
|
||||
|
||||
function findOutlets(collection, callback) {
|
||||
const disabledPlugins = Discourse.Site.currentProp('disabled_plugins') || [];
|
||||
|
||||
Object.keys(collection).forEach(function(res) {
|
||||
if (res.indexOf("/connectors/") !== -1) {
|
||||
// Skip any disabled plugins
|
||||
for (let i=0; i<disabledPlugins.length; i++) {
|
||||
if (res.indexOf("/" + disabledPlugins[i] + "/") !== -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const segments = res.split("/");
|
||||
let outletName = segments[segments.length-2];
|
||||
const uniqueName = segments[segments.length-1];
|
||||
|
||||
callback(outletName, res, uniqueName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function clearCache() {
|
||||
_connectorCache = null;
|
||||
}
|
||||
|
||||
function buildConnectorCache() {
|
||||
_connectorCache = {};
|
||||
|
||||
findOutlets(Ember.TEMPLATES, function(outletName, resource, uniqueName) {
|
||||
_connectorCache[outletName] = _connectorCache[outletName] || [];
|
||||
|
||||
const foundClass = _extraConnectorClasses[`${outletName}/${uniqueName}`];
|
||||
const connectorClass = foundClass ?
|
||||
jQuery.extend({}, DefaultConnectorClass, foundClass) :
|
||||
DefaultConnectorClass;
|
||||
|
||||
_connectorCache[outletName].push({
|
||||
templateName: resource.replace('javascripts/', ''),
|
||||
template: Ember.TEMPLATES[resource],
|
||||
classNames: `${outletName}-outlet ${uniqueName}`,
|
||||
connectorClass
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function connectorsFor(outletName) {
|
||||
if (!_connectorCache) { buildConnectorCache(); }
|
||||
return _connectorCache[outletName] || [];
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
{{plugin-outlet "above-site-header"}}
|
||||
{{plugin-outlet name="above-site-header"}}
|
||||
{{site-header canSignUp=canSignUp
|
||||
showCreateAccount=(action "appRouteAction" "showCreateAccount")
|
||||
showLogin=(action "appRouteAction" "showLogin")
|
||||
|
@ -6,7 +6,7 @@
|
|||
toggleMobileView=(action "appRouteAction" "toggleMobileView")
|
||||
toggleAnonymous=(action "appRouteAction" "toggleAnonymous")
|
||||
logout=(action "appRouteAction" "logout")}}
|
||||
{{plugin-outlet "below-site-header"}}
|
||||
{{plugin-outlet name="below-site-header"}}
|
||||
|
||||
<div id="main-outlet" class="wrap">
|
||||
<div class="container">
|
||||
|
@ -20,11 +20,11 @@
|
|||
{{outlet "user-card"}}
|
||||
</div>
|
||||
|
||||
{{plugin-outlet "above-footer"}}
|
||||
{{plugin-outlet name="above-footer"}}
|
||||
{{#if showFooter}}
|
||||
{{custom-html "footer"}}
|
||||
{{/if}}
|
||||
{{plugin-outlet "below-footer"}}
|
||||
{{plugin-outlet name="below-footer"}}
|
||||
|
||||
{{outlet "modal"}}
|
||||
{{topic-entrance}}
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
{{tag-drop firstCategory=firstCategory secondCategory=secondCategory tagId=tagId}}
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet "bread-crumbs-right" tagName="li"}}
|
||||
{{plugin-outlet name="bread-crumbs-right" connectorTagName="li"}}
|
||||
|
||||
<div class='clear'></div>
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
</label>
|
||||
</section>
|
||||
|
||||
{{plugin-outlet "category-email-in"}}
|
||||
{{plugin-outlet name="category-email-in" args=(hash category=category)}}
|
||||
{{/if}}
|
||||
|
||||
{{#if showPositionInput}}
|
||||
|
@ -82,4 +82,4 @@
|
|||
</section>
|
||||
{{/unless}}
|
||||
|
||||
{{plugin-outlet "category-custom-settings"}}
|
||||
{{plugin-outlet name="category-custom-settings" args=(hash category=category)}}
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
{{navigation-item content=navItem filterMode=filterMode}}
|
||||
{{/each}}
|
||||
{{custom-html "extraNavItem"}}
|
||||
{{plugin-outlet "extra-nav-item" tagName="li"}}
|
||||
{{plugin-outlet name="extra-nav-item" connectorTagName="li"}}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{{#each connectors as |c|}}
|
||||
{{plugin-connector connector=c args=args class=c.classNames tagName=connectorTagName}}
|
||||
{{/each}}
|
|
@ -6,7 +6,7 @@
|
|||
<a href={{item.postUrl}}>{{{item.title}}}</a>
|
||||
</span>
|
||||
<div class="category">{{category-link item.category}}</div>
|
||||
{{plugin-outlet "user-stream-item-header"}}
|
||||
{{plugin-outlet name="user-stream-item-header" args=(hash item=item)}}
|
||||
</div>
|
||||
|
||||
{{#if actionDescription}}
|
||||
|
|
|
@ -14,4 +14,4 @@
|
|||
{{topic-featured-link topic}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{plugin-outlet "topic-category"}}
|
||||
{{plugin-outlet name="topic-category" args=(hash topic=topic category=topic.category)}}
|
||||
|
|
|
@ -66,8 +66,12 @@
|
|||
title="topic.reply.help"}}
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet "after-topic-footer-main-buttons" tagName="span"}}
|
||||
{{plugin-outlet name="after-topic-footer-main-buttons"
|
||||
args=(hash topic=topic)
|
||||
connectorTagName="span"}}
|
||||
|
||||
{{pinned-button topic=topic}}
|
||||
{{topic-notifications-button topic=topic}}
|
||||
{{plugin-outlet "after-topic-footer-buttons" tagName="span"}}
|
||||
{{plugin-outlet name="after-topic-footer-buttons"
|
||||
args=(hash topic=topic)
|
||||
connectorTagName="span"}}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<h2>{{user.title}}</h2>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet "user-card-post-names"}}
|
||||
{{plugin-outlet name="user-card-post-names" args=(hash user=user)}}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
@ -85,7 +85,7 @@
|
|||
</span>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet "user-card-location-and-website"}}
|
||||
{{plugin-outlet name="user-card-location-and-website" args=(hash user=user)}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
|
@ -95,7 +95,7 @@
|
|||
<h3><span class='desc'>{{i18n 'last_post'}}</span> {{format-date user.last_posted_at leaveAgo="true"}}</h3>
|
||||
{{/if}}
|
||||
<h3><span class='desc'>{{i18n 'joined'}}</span> {{format-date user.created_at leaveAgo="true"}}</h3>
|
||||
{{plugin-outlet "user-card-metadata"}}
|
||||
{{plugin-outlet name="user-card-metadata" args=(hash user=user)}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
{{#if model.viewOpen}}
|
||||
<div class='control-row reply-area'>
|
||||
<div class='composer-fields'>
|
||||
{{plugin-outlet "composer-open"}}
|
||||
{{plugin-outlet name="composer-open" args=(hash model=model)}}
|
||||
|
||||
<div class='reply-to'>
|
||||
{{{model.actionTitle}}}
|
||||
|
@ -81,7 +81,7 @@
|
|||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{plugin-outlet "composer-fields"}}
|
||||
{{plugin-outlet name="composer-fields" args=(hash model=model)}}
|
||||
</div>
|
||||
|
||||
{{composer-editor topic=topic
|
||||
|
@ -103,7 +103,7 @@
|
|||
|
||||
{{#if currentUser}}
|
||||
<div class='submit-panel'>
|
||||
{{plugin-outlet "composer-fields-below"}}
|
||||
{{plugin-outlet name="composer-fields-below" args=(hash model=model)}}
|
||||
{{#if canEditTags}}
|
||||
{{tag-chooser tags=model.tags tabIndex="4" categoryId=model.categoryId}}
|
||||
{{/if}}
|
||||
|
|
|
@ -21,11 +21,11 @@
|
|||
<div class="row">
|
||||
<div class="full-width">
|
||||
<div id="list-area">
|
||||
{{plugin-outlet "discovery-list-container-top"}}
|
||||
{{plugin-outlet name="discovery-list-container-top"}}
|
||||
{{outlet "list-container"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{plugin-outlet "discovery-below"}}
|
||||
{{plugin-outlet name="discovery-below"}}
|
||||
|
|
|
@ -94,7 +94,7 @@
|
|||
{{#each result.topic.tags as |tag|}}
|
||||
{{discourse-tag tag}}
|
||||
{{/each}}
|
||||
{{plugin-outlet "full-page-search-category"}}
|
||||
{{plugin-outlet name="full-page-search-category" args=(hash result=result)}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
{{#if topic.featured_link}}
|
||||
{{topic-featured-link topic}}
|
||||
{{/if}}
|
||||
{{plugin-outlet "topic-list-after-title"}}
|
||||
{{raw-plugin-outlet name="topic-list-after-title"}}
|
||||
{{#if showTopicPostBadges}}
|
||||
{{raw "topic-post-badges" unread=topic.unread newPosts=topic.displayNewPosts unseen=topic.unseen url=topic.lastUnreadUrl}}
|
||||
{{/if}}
|
||||
|
@ -21,7 +21,7 @@
|
|||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{plugin-outlet "topic-list-tags"}}
|
||||
{{raw-plugin-outlet name="topic-list-tags"}}
|
||||
{{#if expandPinned}}
|
||||
{{raw "list/topic-excerpt" topic=topic}}
|
||||
{{/if}}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet "topic-list-tags"}}
|
||||
{{raw-plugin-outlet name="topic-list-tags"}}
|
||||
|
||||
<div class="pull-right">
|
||||
<div class='num activity last'>
|
||||
|
|
|
@ -52,7 +52,11 @@
|
|||
</tr>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet "create-account-before-password"}}
|
||||
{{plugin-outlet name="create-account-before-password"
|
||||
args=(hash accountName=accountName
|
||||
accountUsername=accountUsername
|
||||
accountPassword=accountPassword
|
||||
userFields=userFields)}}
|
||||
|
||||
{{#if passwordRequired}}
|
||||
<tr class="input">
|
||||
|
|
|
@ -94,7 +94,7 @@
|
|||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet "post-revisions"}}
|
||||
{{plugin-outlet name="post-revisions" args=(hash model=model)}}
|
||||
|
||||
{{#links-redirect class="row"}}
|
||||
{{{bodyDiff}}}
|
||||
|
|
|
@ -248,7 +248,7 @@
|
|||
{{preference-checkbox labelKey="user.enable_quoting" checked=model.user_option.enable_quoting}}
|
||||
{{preference-checkbox labelKey="user.dynamic_favicon" checked=model.user_option.dynamic_favicon}}
|
||||
{{preference-checkbox labelKey="user.disable_jump_reply" checked=model.user_option.disable_jump_reply}}
|
||||
{{plugin-outlet "user-custom-preferences"}}
|
||||
{{plugin-outlet name="user-custom-preferences" args=(hash model=model)}}
|
||||
</div>
|
||||
|
||||
<div class="control-group category">
|
||||
|
@ -350,7 +350,7 @@
|
|||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet "user-custom-controls"}}
|
||||
{{plugin-outlet name="user-custom-controls" args=(hash model=model)}}
|
||||
|
||||
<div class="control-group save-button">
|
||||
<div class="controls">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{{#d-section bodyClass=bodyClass class="container"}}
|
||||
{{#watch-read action="markFaqRead" path=model.path}}
|
||||
<div class='contents clearfix body-page'>
|
||||
{{plugin-outlet "above-static"}}
|
||||
{{plugin-outlet name="above-static"}}
|
||||
{{{model.html}}}
|
||||
|
||||
{{#if showSignupButton}}
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{{plugin-outlet "discovery-list-container-top"}}
|
||||
{{plugin-outlet name="discovery-list-container-top"}}
|
||||
|
||||
<footer class='topic-list-bottom'>
|
||||
{{conditional-loading-spinner condition=loading}}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet "topic-above-post-stream"}}
|
||||
{{plugin-outlet name="topic-above-post-stream" args=(hash model=model)}}
|
||||
|
||||
{{#if model.postStream.loaded}}
|
||||
{{#if model.postStream.firstPostPresent}}
|
||||
|
@ -30,7 +30,7 @@
|
|||
{{tag-chooser tags=buffered.tags categoryId=buffered.category_id}}
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet "edit-topic"}}
|
||||
{{plugin-outlet name="edit-topic" args=(hash model=model buffered=buffered)}}
|
||||
|
||||
{{d-button action="finishedEditingTopic" class="btn-primary btn-small submit-edit" icon="check"}}
|
||||
{{d-button action="cancelEditingTopic" class="btn-small cancel-edit" icon="times"}}
|
||||
|
@ -59,7 +59,7 @@
|
|||
{{/unless}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{plugin-outlet "topic-title"}}
|
||||
{{plugin-outlet name="topic-title" args=(hash model=model)}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
@ -125,7 +125,7 @@
|
|||
<div class="posts-wrapper">
|
||||
{{conditional-loading-spinner condition=model.postStream.loadingAbove}}
|
||||
|
||||
{{plugin-outlet "topic-above-posts"}}
|
||||
{{plugin-outlet name="topic-above-posts" args=(hash model=model)}}
|
||||
|
||||
{{#unless model.postStream.loadingFilter}}
|
||||
{{scrolling-post-stream
|
||||
|
@ -221,7 +221,7 @@
|
|||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet "topic-above-suggested"}}
|
||||
{{plugin-outlet name="topic-above-suggested" args=(hash model=model)}}
|
||||
|
||||
{{#if model.details.suggested_topics.length}}
|
||||
<div id="suggested-topics">
|
||||
|
|
|
@ -47,7 +47,9 @@
|
|||
{{#if currentUser.staff}}
|
||||
<li><a href={{model.adminPath}} class="btn">{{fa-icon "wrench"}}{{i18n 'admin.user.show_admin_profile'}}</a></li>
|
||||
{{/if}}
|
||||
{{plugin-outlet "user-profile-controls" tagName="li"}}
|
||||
{{plugin-outlet name="user-profile-controls"
|
||||
connectorTagName="li"
|
||||
args=(hash model=model)}}
|
||||
|
||||
{{#if collapsedInfo}}
|
||||
{{#if viewingSelf}}
|
||||
|
@ -75,7 +77,7 @@
|
|||
<span title={{model.website}}>{{model.website_name}}</span>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{plugin-outlet "user-location-and-website"}}
|
||||
{{plugin-outlet name="user-location-and-website" args=(hash model=model)}}
|
||||
</h3>
|
||||
|
||||
<div class='bio'>
|
||||
|
@ -102,12 +104,13 @@
|
|||
{{/if}}
|
||||
{{/each}}
|
||||
|
||||
{{plugin-outlet "user-profile-public-fields"}}
|
||||
{{plugin-outlet name="user-profile-public-fields"
|
||||
args=(hash publicUserFields=publicUserFields
|
||||
model=model)}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet "user-profile-primary"}}
|
||||
|
||||
{{plugin-outlet name="user-profile-primary" args=(hash model=model)}}
|
||||
</div>
|
||||
</div>
|
||||
<div style='clear: both'></div>
|
||||
|
@ -153,7 +156,7 @@
|
|||
{{d-button action="adminDelete" icon="exclamation-triangle" label="user.admin_delete" class="btn-danger"}}
|
||||
{{/if}}
|
||||
</dl>
|
||||
{{plugin-outlet "user-profile-secondary"}}
|
||||
{{plugin-outlet name="user-profile-secondary" args=(hash model=model)}}
|
||||
</div>
|
||||
{{/unless}}
|
||||
</section>
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
{{plugin-outlet "user-activity-bottom" tagName='li'}}
|
||||
{{plugin-outlet name="user-activity-bottom"
|
||||
connectorTagName='li'
|
||||
args=(hash model=model)}}
|
||||
{{/mobile-nav}}
|
||||
|
||||
{{#if viewingSelf}}
|
||||
|
|
|
@ -37,7 +37,9 @@
|
|||
<li>
|
||||
{{user-stat value=model.likes_received label="user.summary.likes_received"}}
|
||||
</li>
|
||||
{{plugin-outlet "user-summary-stat" tagName="li"}}
|
||||
{{plugin-outlet name="user-summary-stat"
|
||||
connectorTagName="li"
|
||||
args=(hash model=model)}}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
import { acceptance } from "helpers/qunit-helpers";
|
||||
import { extraConnectorClass } from 'discourse/lib/plugin-connectors';
|
||||
|
||||
const PREFIX = "javascripts/single-test/connectors";
|
||||
acceptance("Plugin Outlet - Connector Class", {
|
||||
setup() {
|
||||
extraConnectorClass('user-profile-primary/hello', {
|
||||
actions: {
|
||||
sayHello() {
|
||||
this.set('hello', 'hello!');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
extraConnectorClass('user-profile-primary/dont-render', {
|
||||
shouldRender(args) {
|
||||
return args.model.get('username') !== 'eviltrout';
|
||||
}
|
||||
});
|
||||
|
||||
Ember.TEMPLATES[`${PREFIX}/user-profile-primary/hello`] = Ember.HTMLBars.compile(
|
||||
`<span class='hello-username'>{{model.username}}</span>
|
||||
<button class='say-hello' {{action "sayHello"}}></button>
|
||||
<span class='hello-result'>{{hello}}</span>`
|
||||
);
|
||||
Ember.TEMPLATES[`${PREFIX}/user-profile-primary/dont-render`] = Ember.HTMLBars.compile(
|
||||
`I'm not rendered!`
|
||||
);
|
||||
},
|
||||
|
||||
teardown() {
|
||||
delete Ember.TEMPLATES[`${PREFIX}/user-profile-primary/hello`];
|
||||
delete Ember.TEMPLATES[`${PREFIX}/user-profile-primary/dont-render`];
|
||||
}
|
||||
});
|
||||
|
||||
test("Renders a template into the outlet", assert => {
|
||||
visit("/users/eviltrout");
|
||||
andThen(() => {
|
||||
assert.ok(find('.user-profile-primary-outlet.hello').length === 1, 'it has class names');
|
||||
assert.ok(!find('.user-profile-primary-outlet.dont-render').length, "doesn't render");
|
||||
});
|
||||
click('.say-hello');
|
||||
andThen(() => {
|
||||
assert.equal(find('.hello-result').text(), 'hello!', 'actions delegate properly');
|
||||
});
|
||||
});
|
|
@ -1,5 +1,5 @@
|
|||
import { acceptance } from "helpers/qunit-helpers";
|
||||
import { clearCache } from 'discourse/helpers/plugin-outlet';
|
||||
import { clearCache } from 'discourse/lib/plugin-connectors';
|
||||
|
||||
const HELLO = 'javascripts/multi-test/connectors/user-profile-primary/hello';
|
||||
const GOODBYE = 'javascripts/multi-test/connectors/user-profile-primary/goodbye';
|
||||
|
|
|
@ -4,9 +4,7 @@ const CONNECTOR = 'javascripts/single-test/connectors/user-profile-primary/hello
|
|||
acceptance("Plugin Outlet - Single Template", {
|
||||
setup() {
|
||||
Ember.TEMPLATES[CONNECTOR] = Ember.HTMLBars.compile(
|
||||
`<span class='hello-username'>{{model.username}}</span>
|
||||
<button class='hello-check-email' {{action "checkEmail" model}}></button>
|
||||
<span class='hello-email'>{{model.email}}</span>`
|
||||
`<span class='hello-username'>{{model.username}}</span>`
|
||||
);
|
||||
},
|
||||
|
||||
|
@ -21,8 +19,4 @@ test("Renders a template into the outlet", assert => {
|
|||
assert.ok(find('.user-profile-primary-outlet.hello').length === 1, 'it has class names');
|
||||
assert.equal(find('.hello-username').text(), 'eviltrout', 'it renders into the outlet');
|
||||
});
|
||||
click('.hello-check-email');
|
||||
andThen(() => {
|
||||
assert.equal(find('.hello-email').text(), 'eviltrout@example.com', 'actions delegate properly');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,9 +5,10 @@ import siteFixtures from 'fixtures/site-fixtures';
|
|||
import HeaderComponent from 'discourse/components/site-header';
|
||||
import { forceMobile, resetMobile } from 'discourse/lib/mobile';
|
||||
import { resetPluginApi } from 'discourse/lib/plugin-api';
|
||||
import { clearCache as clearOutletCache } from 'discourse/helpers/plugin-outlet';
|
||||
import { clearCache as clearOutletCache, resetExtraClasses } from 'discourse/lib/plugin-connectors';
|
||||
import { clearHTMLCache } from 'discourse/helpers/custom-html';
|
||||
|
||||
|
||||
function currentUser() {
|
||||
return Discourse.User.create(sessionFixtures['/session/current.json'].current_user);
|
||||
}
|
||||
|
@ -44,6 +45,7 @@ function acceptance(name, options) {
|
|||
// For now don't do scrolling stuff in Test Mode
|
||||
HeaderComponent.reopen({examineDockHeader: Ember.K});
|
||||
|
||||
resetExtraClasses();
|
||||
const siteJson = siteFixtures['site.json'].site;
|
||||
if (options) {
|
||||
if (options.setup) {
|
||||
|
@ -80,6 +82,7 @@ function acceptance(name, options) {
|
|||
Discourse.User.resetCurrent();
|
||||
Discourse.Site.resetCurrent(Discourse.Site.create(jQuery.extend(true, {}, fixtures['site.json'].site)));
|
||||
|
||||
resetExtraClasses();
|
||||
clearOutletCache();
|
||||
clearHTMLCache();
|
||||
resetPluginApi();
|
||||
|
|
Loading…
Reference in New Issue