mirror of
https://github.com/codeninjasllc/discourse.git
synced 2025-05-03 17:35:09 -04:00
Ability to mount ember views into vdom
It's slow but can be used as a last resort for old plugins.
This commit is contained in:
parent
0af9e7b572
commit
54904133a0
4 changed files with 76 additions and 11 deletions
app/assets/javascripts/discourse
|
@ -18,6 +18,7 @@ export default Ember.Component.extend({
|
||||||
init() {
|
init() {
|
||||||
this._super();
|
this._super();
|
||||||
this._widgetClass = this.container.lookupFactory(`widget:${this.get('widget')}`);
|
this._widgetClass = this.container.lookupFactory(`widget:${this.get('widget')}`);
|
||||||
|
this._connected = [];
|
||||||
},
|
},
|
||||||
|
|
||||||
didInsertElement() {
|
didInsertElement() {
|
||||||
|
@ -33,6 +34,9 @@ export default Ember.Component.extend({
|
||||||
if (callbacks) {
|
if (callbacks) {
|
||||||
callbacks.forEach(cb => cb());
|
callbacks.forEach(cb => cb());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._connected.forEach(v => v.destroy());
|
||||||
|
this._connected.length = 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
willDestroyElement() {
|
willDestroyElement() {
|
||||||
|
|
|
@ -84,7 +84,9 @@ class PluginApi {
|
||||||
* ```
|
* ```
|
||||||
**/
|
**/
|
||||||
addPosterIcon(cb) {
|
addPosterIcon(cb) {
|
||||||
decorateWidget('poster-name:after', (h, attrs) => {
|
decorateWidget('poster-name:after', dec => {
|
||||||
|
const attrs = dec.attrs;
|
||||||
|
|
||||||
const result = cb(attrs.userCustomFields || {}, attrs);
|
const result = cb(attrs.userCustomFields || {}, attrs);
|
||||||
if (result) {
|
if (result) {
|
||||||
let iconBody;
|
let iconBody;
|
||||||
|
@ -94,7 +96,7 @@ class PluginApi {
|
||||||
} else if (result.emoji) {
|
} else if (result.emoji) {
|
||||||
iconBody = result.emoji.split('|').map(emoji => {
|
iconBody = result.emoji.split('|').map(emoji => {
|
||||||
const src = Discourse.Emoji.urlFor(emoji);
|
const src = Discourse.Emoji.urlFor(emoji);
|
||||||
return h('img', { className: 'emoji', attributes: { src } });
|
return dec.h('img', { className: 'emoji', attributes: { src } });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,13 +105,13 @@ class PluginApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.url) {
|
if (result.url) {
|
||||||
iconBody = h('a', { attributes: { href: result.url } }, iconBody);
|
iconBody = dec.h('a', { attributes: { href: result.url } }, iconBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return h('span',
|
return dec.h('span',
|
||||||
{ className: result.className, attributes: { title: result.title } },
|
{ className: result.className, attributes: { title: result.title } },
|
||||||
iconBody);
|
iconBody);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
39
app/assets/javascripts/discourse/widgets/connector.js.es6
Normal file
39
app/assets/javascripts/discourse/widgets/connector.js.es6
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
export default class Connector {
|
||||||
|
|
||||||
|
constructor(widget, opts) {
|
||||||
|
this.widget = widget;
|
||||||
|
this.opts = opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
const $elem = $(`<div class='widget-connector'></div>`);
|
||||||
|
const elem = $elem[0];
|
||||||
|
|
||||||
|
const { opts, widget } = this;
|
||||||
|
Ember.run.next(() => {
|
||||||
|
|
||||||
|
const mounted = widget._findView();
|
||||||
|
|
||||||
|
let context;
|
||||||
|
if (opts.context === 'model') {
|
||||||
|
const model = widget.findAncestorModel();
|
||||||
|
context = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
const view = Ember.View.create({
|
||||||
|
container: widget.container,
|
||||||
|
templateName: opts.templateName,
|
||||||
|
context
|
||||||
|
});
|
||||||
|
mounted._connected.push(view);
|
||||||
|
|
||||||
|
view.renderer.replaceIn(view, $elem[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
update() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
Connector.prototype.type = 'Widget';
|
|
@ -1,5 +1,6 @@
|
||||||
import { WidgetClickHook, WidgetClickOutsideHook } from 'discourse/widgets/click-hook';
|
import { WidgetClickHook, WidgetClickOutsideHook } from 'discourse/widgets/click-hook';
|
||||||
import { h } from 'virtual-dom';
|
import { h } from 'virtual-dom';
|
||||||
|
import Connector from 'discourse/widgets/connector';
|
||||||
|
|
||||||
function emptyContent() { }
|
function emptyContent() { }
|
||||||
|
|
||||||
|
@ -16,14 +17,33 @@ export function renderedKey(key) {
|
||||||
|
|
||||||
const _decorators = {};
|
const _decorators = {};
|
||||||
|
|
||||||
|
class DecoratorHelper {
|
||||||
|
constructor(container, attrs, state) {
|
||||||
|
this.container = container;
|
||||||
|
this.attrs = attrs;
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(details) {
|
||||||
|
return new Connector(this.container, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DecoratorHelper.prototype.h = h;
|
||||||
|
|
||||||
export function decorateWidget(widgetName, cb) {
|
export function decorateWidget(widgetName, cb) {
|
||||||
_decorators[widgetName] = _decorators[widgetName] || [];
|
_decorators[widgetName] = _decorators[widgetName] || [];
|
||||||
_decorators[widgetName].push(cb);
|
_decorators[widgetName].push(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyDecorators(name, type, attrs, state) {
|
function applyDecorators(widget, type, attrs, state) {
|
||||||
const decorators = _decorators[`${name}:${type}`] || [];
|
const decorators = _decorators[`${widget.name}:${type}`] || [];
|
||||||
return decorators.map(d => d(h, attrs, state));
|
|
||||||
|
if (decorators.length) {
|
||||||
|
const helper = new DecoratorHelper(widget, attrs, state);
|
||||||
|
return decorators.map(d => d(helper));
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawWidget(builder, attrs, state) {
|
function drawWidget(builder, attrs, state) {
|
||||||
|
@ -58,8 +78,8 @@ function drawWidget(builder, attrs, state) {
|
||||||
|
|
||||||
let contents = this.html(attrs, state);
|
let contents = this.html(attrs, state);
|
||||||
if (this.name) {
|
if (this.name) {
|
||||||
const beforeContents = applyDecorators(this.name, 'before', attrs, state) || [];
|
const beforeContents = applyDecorators(this, 'before', attrs, state) || [];
|
||||||
const afterContents = applyDecorators(this.name, 'after', attrs, state) || [];
|
const afterContents = applyDecorators(this, 'after', attrs, state) || [];
|
||||||
contents = beforeContents.concat(contents).concat(afterContents);
|
contents = beforeContents.concat(contents).concat(afterContents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue