discourse/plugins/poll/assets/javascripts/initializers/extend-for-poll.js.es6
Jarek Radosz cd4f251891
FEATURE: Poll breakdown 2.0 (#10345)
The poll breakdown modal replaces the grouped pie charts feature.

Includes:

* MODAL: Untangle `onSelectPanel`
Previously modal-tab component would call on click the onSelectPanel callback with itself (modal-tab) as `this` which severely limited its usefulness. Now showModal binds the callback to its controller.

"The PR includes a fix/change to d-modal (b7f6ec6) that hasn't been extracted to a separate PR because it's not currently possible to test a change like this in abstract, i.e. with dynamically created controllers/components in tests. The percentage/count toggle test for the poll breakdown feature is essentially a test for that d-modal modification."
2020-08-06 17:57:06 +02:00

133 lines
3.4 KiB
JavaScript

import EmberObject from "@ember/object";
import { withPluginApi } from "discourse/lib/plugin-api";
import WidgetGlue from "discourse/widgets/glue";
import { getRegister } from "discourse-common/lib/get-owner";
import { observes } from "discourse-common/utils/decorators";
function initializePolls(api) {
const register = getRegister(api);
api.modifyClass("controller:topic", {
subscribe() {
this._super(...arguments);
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(...arguments);
}
});
let _glued = [];
let _interval = null;
function rerender() {
_glued.forEach(g => g.queueRerender());
}
api.modifyClass("model:post", {
_polls: null,
pollsObject: null,
// we need a proper ember object so it is bindable
@observes("polls")
pollsChanged() {
const polls = this.polls;
if (polls) {
this._polls = this._polls || {};
polls.forEach(p => {
const existing = this._polls[p.name];
if (existing) {
this._polls[p.name].setProperties(p);
} else {
this._polls[p.name] = EmberObject.create(p);
}
});
this.set("pollsObject", this._polls);
rerender();
}
}
});
function attachPolls($elem, helper) {
const $polls = $(".poll", $elem);
if (!$polls.length || !helper) {
return;
}
let post = helper.getModel();
api.preventCloak(post.id);
post.pollsChanged();
const polls = post.pollsObject || {};
const votes = post.polls_votes || {};
_interval = _interval || setInterval(rerender, 30000);
$polls.each((idx, pollElem) => {
const $poll = $(pollElem);
const pollName = $poll.data("poll-name");
let poll = polls[pollName];
let vote = votes[pollName] || [];
const quotedId = $poll.parent(".expanded-quote").data("post-id");
if (quotedId) {
const quotedPost = post.quoted[quotedId];
if (quotedPost) {
post = EmberObject.create(quotedPost);
poll = EmberObject.create(
quotedPost.polls.find(p => p.name === pollName)
);
vote = quotedPost.polls_votes || {};
vote = vote[pollName] || [];
}
}
if (poll) {
const attrs = {
id: `${pollName}-${post.id}`,
post,
poll,
vote,
groupableUserFields: (
api.container.lookup("site-settings:main")
.poll_groupable_user_fields || ""
)
.split("|")
.filter(Boolean)
};
const glue = new WidgetGlue("discourse-poll", register, attrs);
glue.appendTo(pollElem);
_glued.push(glue);
}
});
}
function cleanUpPolls() {
if (_interval) {
clearInterval(_interval);
_interval = null;
}
_glued.forEach(g => g.cleanUp());
_glued = [];
}
api.includePostAttributes("polls", "polls_votes");
api.decorateCooked(attachPolls, { onlyStream: true, id: "discourse-poll" });
api.cleanupStream(cleanUpPolls);
}
export default {
name: "extend-for-poll",
initialize() {
withPluginApi("0.8.7", initializePolls);
}
};