Update Polls plugin to work with new Plugin API
This commit is contained in:
parent
f6aa1ac37a
commit
6935925f10
|
@ -2,6 +2,12 @@ import { diff, patch } from 'virtual-dom';
|
|||
import { WidgetClickHook } from 'discourse/widgets/click-hook';
|
||||
import { renderedKey } from 'discourse/widgets/widget';
|
||||
|
||||
const _cleanCallbacks = {};
|
||||
export function addWidgetCleanCallback(widgetName, fn) {
|
||||
_cleanCallbacks[widgetName] = _cleanCallbacks[widgetName] || [];
|
||||
_cleanCallbacks[widgetName].push(fn);
|
||||
}
|
||||
|
||||
export default Ember.Component.extend({
|
||||
_tree: null,
|
||||
_rootNode: null,
|
||||
|
@ -22,6 +28,13 @@ export default Ember.Component.extend({
|
|||
this._timeout = Ember.run.scheduleOnce('render', this, this.rerenderWidget);
|
||||
},
|
||||
|
||||
willClearRender() {
|
||||
const callbacks = _cleanCallbacks[this.get('widget')];
|
||||
if (callbacks) {
|
||||
callbacks.forEach(cb => cb());
|
||||
}
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
Ember.run.cancel(this._timeout);
|
||||
},
|
||||
|
|
|
@ -4,6 +4,7 @@ import { addPosterIcon } from 'discourse/widgets/poster-name';
|
|||
import { addButton } from 'discourse/widgets/post-menu';
|
||||
import { includeAttributes } from 'discourse/lib/transform-post';
|
||||
import { addToolbarCallback } from 'discourse/components/d-editor';
|
||||
import { addWidgetCleanCallback } from 'discourse/components/mount-widget';
|
||||
|
||||
let _decorateId = 0;
|
||||
function decorate(klass, evt, cb) {
|
||||
|
@ -29,23 +30,31 @@ class PluginApi {
|
|||
}
|
||||
|
||||
/**
|
||||
* decorateCooked(callback)
|
||||
* decorateCooked(callback, options)
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Use `options.onlyStream` if you only want to decorate posts within a topic,
|
||||
* and not in other places like the user stream.
|
||||
*
|
||||
* 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);
|
||||
decorateCooked(callback, opts) {
|
||||
opts = opts || {};
|
||||
|
||||
addDecorator(callback);
|
||||
|
||||
if (!opts.onlyStream) {
|
||||
decorate(ComposerEditor, 'previewRefreshed', callback);
|
||||
decorate(this.container.lookupFactory('view:user-stream'), 'didInsertElement', callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,6 +100,10 @@ class PluginApi {
|
|||
addToolbarCallback(callback);
|
||||
}
|
||||
|
||||
cleanupStream(fn) {
|
||||
addWidgetCleanCallback('post-stream', fn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let _pluginv01;
|
||||
|
|
|
@ -10,10 +10,11 @@ export function addDecorator(cb) {
|
|||
|
||||
export default class PostCooked {
|
||||
|
||||
constructor(attrs) {
|
||||
constructor(attrs, getModel) {
|
||||
this.attrs = attrs;
|
||||
this.expanding = false;
|
||||
this._highlighted = false;
|
||||
this.getModel = getModel;
|
||||
}
|
||||
|
||||
update(prev) {
|
||||
|
@ -29,7 +30,7 @@ export default class PostCooked {
|
|||
this._fixImageSizes($html);
|
||||
this._applySearchHighlight($html);
|
||||
|
||||
_decorators.forEach(cb => cb($html));
|
||||
_decorators.forEach(cb => cb($html, this.getModel));
|
||||
return $html[0];
|
||||
}
|
||||
|
||||
|
|
|
@ -221,6 +221,17 @@ createWidget('expand-post-button', {
|
|||
}
|
||||
});
|
||||
|
||||
class DecoratorHelper {
|
||||
constructor(widget) {
|
||||
this.container = widget.container;
|
||||
this._widget = widget;
|
||||
}
|
||||
|
||||
getModel() {
|
||||
return this._widget.findAncestorModel();
|
||||
}
|
||||
}
|
||||
|
||||
createWidget('post-contents', {
|
||||
buildKey: attrs => `post-contents-${attrs.id}`,
|
||||
|
||||
|
@ -240,7 +251,7 @@ createWidget('post-contents', {
|
|||
},
|
||||
|
||||
html(attrs, state) {
|
||||
const result = [new PostCooked(attrs)];
|
||||
const result = [new PostCooked(attrs, new DecoratorHelper(this))];
|
||||
|
||||
if (attrs.cooked_hidden) {
|
||||
result.push(this.attach('expand-hidden', attrs));
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
import PostView from "discourse/views/post";
|
||||
import TopicController from "discourse/controllers/topic";
|
||||
import Post from "discourse/models/post";
|
||||
|
||||
import { on } from "ember-addons/ember-computed-decorators";
|
||||
import { withPluginApi } from 'discourse/lib/plugin-api';
|
||||
|
||||
function createPollView(container, post, poll, vote) {
|
||||
const controller = container.lookup("controller:poll", { singleton: false }),
|
||||
view = container.lookup("view:poll");
|
||||
const controller = container.lookup("controller:poll", { singleton: false });
|
||||
const view = container.lookup("view:poll");
|
||||
|
||||
controller.set("vote", vote);
|
||||
controller.setProperties({ model: poll, post });
|
||||
|
@ -15,12 +11,32 @@ function createPollView(container, post, poll, vote) {
|
|||
return view;
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "extend-for-poll",
|
||||
let _pollViews;
|
||||
|
||||
initialize(container) {
|
||||
function initializePolls(api) {
|
||||
|
||||
const TopicController = api.container.lookupFactory('controller:topic');
|
||||
TopicController.reopen({
|
||||
subscribe(){
|
||||
this._super();
|
||||
this.messageBus.subscribe("/polls/" + this.get("model.id"), msg => {
|
||||
const post = this.get('model.postStream').findLoadedPost(msg.post_id);
|
||||
if (post) {
|
||||
post.set('polls', msg.polls);
|
||||
}
|
||||
});
|
||||
},
|
||||
unsubscribe(){
|
||||
this.messageBus.unsubscribe('/polls/*');
|
||||
this._super();
|
||||
}
|
||||
});
|
||||
|
||||
const Post = api.container.lookupFactory('model:post');
|
||||
Post.reopen({
|
||||
_polls: null,
|
||||
pollsObject: null,
|
||||
|
||||
// we need a proper ember object so it is bindable
|
||||
pollsChanged: function(){
|
||||
const polls = this.get("polls");
|
||||
|
@ -39,64 +55,51 @@ export default {
|
|||
}.observes("polls")
|
||||
});
|
||||
|
||||
TopicController.reopen({
|
||||
subscribe(){
|
||||
this._super();
|
||||
this.messageBus.subscribe("/polls/" + this.get("model.id"), msg => {
|
||||
const post = this.get('model.postStream').findLoadedPost(msg.post_id);
|
||||
if (post) {
|
||||
post.set('polls', msg.polls);
|
||||
function cleanUpPollViews() {
|
||||
if (_pollViews) {
|
||||
Object.keys(_pollViews).forEach(pollName => _pollViews[pollName].destroy());
|
||||
}
|
||||
});
|
||||
},
|
||||
unsubscribe(){
|
||||
this.messageBus.unsubscribe('/polls/*');
|
||||
this._super();
|
||||
_pollViews = null;
|
||||
}
|
||||
});
|
||||
|
||||
// overwrite polls
|
||||
PostView.reopen({
|
||||
function createPollViews($elem, helper) {
|
||||
const $polls = $('.poll', $elem);
|
||||
if (!$polls.length) { return; }
|
||||
|
||||
@on("postViewInserted", "postViewUpdated")
|
||||
_createPollViews($post) {
|
||||
const post = this.get("post"),
|
||||
votes = post.get("polls_votes") || {};
|
||||
const post = helper.getModel();
|
||||
const votes = post.get('polls_votes') || {};
|
||||
|
||||
post.pollsChanged();
|
||||
const polls = post.get("pollsObject");
|
||||
|
||||
// don't even bother when there's no poll
|
||||
const polls = post.get("pollsObject");
|
||||
if (!polls) { return; }
|
||||
|
||||
// TODO inject cleanly into
|
||||
cleanUpPollViews();
|
||||
const postPollViews = {};
|
||||
|
||||
// clean-up if needed
|
||||
this._cleanUpPollViews();
|
||||
$polls.each((idx, pollElem) => {
|
||||
const $div = $("<div>");
|
||||
const $poll = $(pollElem);
|
||||
|
||||
const pollViews = {};
|
||||
|
||||
// iterate over all polls
|
||||
$(".poll", $post).each(function() {
|
||||
const $div = $("<div>"),
|
||||
$poll = $(this),
|
||||
pollName = $poll.data("poll-name"),
|
||||
pollView = createPollView(container, post, polls[pollName], votes[pollName]);
|
||||
const pollName = $poll.data("poll-name");
|
||||
const pollView = createPollView(helper.container, post, polls[pollName], votes[pollName]);
|
||||
|
||||
$poll.replaceWith($div);
|
||||
Em.run.next(() => pollView.renderer.replaceIn(pollView, $div[0]));
|
||||
pollViews[pollName] = pollView;
|
||||
postPollViews[pollName] = pollView;
|
||||
});
|
||||
|
||||
this.set("pollViews", pollViews);
|
||||
},
|
||||
_pollViews = postPollViews;
|
||||
}
|
||||
|
||||
@on("willClearRender")
|
||||
_cleanUpPollViews() {
|
||||
if (this.get("pollViews")) {
|
||||
_.forEach(this.get("pollViews"), v => v.destroy());
|
||||
}
|
||||
}
|
||||
});
|
||||
api.decorateCooked(createPollViews, { onlyStream: true });
|
||||
api.cleanupStream(cleanUpPollViews);
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "extend-for-poll",
|
||||
|
||||
initialize() {
|
||||
withPluginApi('0.1', initializePolls);
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue