DEV: Do not skip pages when loading polls (#13649)
In some conditions, pages were skipped. This was implemented in the past inf490a8d
, but then reverted in04ec543
, because sometimes it was stuck reloading the first page. The code that loads more results was simplified and a lot of duplicate code was removed. The logic to remove users who changed their vote was also introduced again, but just for the regular polls.
This commit is contained in:
parent
a1e5a6bbe0
commit
573a71fdd9
|
@ -32,16 +32,6 @@ function infoTextHtml(text) {
|
|||
});
|
||||
}
|
||||
|
||||
function _fetchVoters(data) {
|
||||
return ajax("/polls/voters.json", { data }).catch((error) => {
|
||||
if (error) {
|
||||
popupAjaxError(error);
|
||||
} else {
|
||||
bootbox.alert(I18n.t("poll.error_while_fetching_voters"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function checkUserGroups(user, poll) {
|
||||
const pollGroups =
|
||||
poll && poll.groups && poll.groups.split(",").map((g) => g.toLowerCase());
|
||||
|
@ -125,14 +115,6 @@ createWidget("discourse-poll-voters", {
|
|||
tagName: "ul.poll-voters-list",
|
||||
buildKey: (attrs) => `poll-voters-${attrs.optionId}`,
|
||||
|
||||
defaultState() {
|
||||
return {
|
||||
loaded: "new",
|
||||
voters: [],
|
||||
page: 1,
|
||||
};
|
||||
},
|
||||
|
||||
html(attrs) {
|
||||
const contents = attrs.voters.map((user) =>
|
||||
h("li", [
|
||||
|
@ -156,50 +138,13 @@ createWidget("discourse-poll-standard-results", {
|
|||
tagName: "ul.results",
|
||||
buildKey: (attrs) => `poll-standard-results-${attrs.id}`,
|
||||
|
||||
defaultState() {
|
||||
return { loaded: false };
|
||||
},
|
||||
|
||||
fetchVoters(optionId) {
|
||||
const { attrs, state } = this;
|
||||
|
||||
if (!state.page) {
|
||||
state.page = {};
|
||||
}
|
||||
|
||||
if (!state.page[optionId]) {
|
||||
state.page[optionId] = 1;
|
||||
}
|
||||
|
||||
return _fetchVoters({
|
||||
post_id: attrs.post.id,
|
||||
poll_name: attrs.poll.name,
|
||||
option_id: optionId,
|
||||
page: state.page[optionId] + 1,
|
||||
limit: FETCH_VOTERS_COUNT,
|
||||
}).then((result) => {
|
||||
if (!state.voters[optionId]) {
|
||||
state.voters[optionId] = [];
|
||||
}
|
||||
|
||||
if (result.voters[optionId] && result.voters[optionId].length > 0) {
|
||||
state.voters[optionId] = [
|
||||
...new Set([...state.voters[optionId], ...result.voters[optionId]]),
|
||||
];
|
||||
state.page[optionId]++;
|
||||
}
|
||||
|
||||
this.scheduleRerender();
|
||||
});
|
||||
},
|
||||
|
||||
html(attrs, state) {
|
||||
html(attrs) {
|
||||
const { poll } = attrs;
|
||||
const options = poll.get("options");
|
||||
const options = poll.options;
|
||||
|
||||
if (options) {
|
||||
const voters = poll.get("voters");
|
||||
const isPublic = poll.get("public");
|
||||
const voters = poll.voters;
|
||||
const isPublic = poll.public;
|
||||
|
||||
const ordered = [...options].sort((a, b) => {
|
||||
if (a.votes < b.votes) {
|
||||
|
@ -215,11 +160,6 @@ createWidget("discourse-poll-standard-results", {
|
|||
}
|
||||
});
|
||||
|
||||
if (isPublic && !state.loaded) {
|
||||
state.voters = poll.get("preloaded_voters");
|
||||
state.loaded = true;
|
||||
}
|
||||
|
||||
const percentages =
|
||||
voters === 0
|
||||
? Array(ordered.length).fill(0)
|
||||
|
@ -253,9 +193,9 @@ createWidget("discourse-poll-standard-results", {
|
|||
this.attach("discourse-poll-voters", {
|
||||
postId: attrs.post.id,
|
||||
optionId: option.id,
|
||||
pollName: poll.get("name"),
|
||||
pollName: poll.name,
|
||||
totalVotes: option.votes,
|
||||
voters: (state.voters && state.voters[option.id]) || [],
|
||||
voters: (attrs.voters && attrs.voters[option.id]) || [],
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -269,45 +209,14 @@ createWidget("discourse-poll-standard-results", {
|
|||
createWidget("discourse-poll-number-results", {
|
||||
buildKey: (attrs) => `poll-number-results-${attrs.id}`,
|
||||
|
||||
defaultState() {
|
||||
return { loaded: false };
|
||||
},
|
||||
|
||||
fetchVoters(optionId) {
|
||||
const { attrs, state } = this;
|
||||
|
||||
if (!state.page) {
|
||||
state.page = 1;
|
||||
}
|
||||
|
||||
return _fetchVoters({
|
||||
post_id: attrs.post.id,
|
||||
poll_name: attrs.poll.name,
|
||||
option_id: optionId,
|
||||
page: state.page + 1,
|
||||
limit: FETCH_VOTERS_COUNT,
|
||||
}).then((result) => {
|
||||
if (!state.voters) {
|
||||
state.voters = [];
|
||||
}
|
||||
|
||||
if (result.voters && result.voters.length > 0) {
|
||||
state.voters = [...new Set([...state.voters, ...result.voters])];
|
||||
state.page++;
|
||||
}
|
||||
|
||||
this.scheduleRerender();
|
||||
});
|
||||
},
|
||||
|
||||
html(attrs, state) {
|
||||
html(attrs) {
|
||||
const { poll } = attrs;
|
||||
|
||||
const totalScore = poll.get("options").reduce((total, o) => {
|
||||
const totalScore = poll.options.reduce((total, o) => {
|
||||
return total + parseInt(o.html, 10) * parseInt(o.votes, 10);
|
||||
}, 0);
|
||||
|
||||
const voters = poll.get("voters");
|
||||
const voters = poll.voters;
|
||||
const average = voters === 0 ? 0 : round(totalScore / voters, -2);
|
||||
const averageRating = I18n.t("poll.average_rating", { average });
|
||||
const contents = [
|
||||
|
@ -317,19 +226,14 @@ createWidget("discourse-poll-number-results", {
|
|||
),
|
||||
];
|
||||
|
||||
if (poll.get("public")) {
|
||||
if (!state.loaded) {
|
||||
state.voters = poll.get("preloaded_voters");
|
||||
state.loaded = true;
|
||||
}
|
||||
|
||||
if (poll.public) {
|
||||
contents.push(
|
||||
this.attach("discourse-poll-voters", {
|
||||
totalVotes: poll.get("voters"),
|
||||
voters: state.voters || [],
|
||||
totalVotes: poll.voters,
|
||||
voters: attrs.voters || [],
|
||||
postId: attrs.post.id,
|
||||
pollName: poll.get("name"),
|
||||
pollType: poll.get("type"),
|
||||
pollName: poll.name,
|
||||
pollType: poll.type,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -340,10 +244,15 @@ createWidget("discourse-poll-number-results", {
|
|||
|
||||
createWidget("discourse-poll-container", {
|
||||
tagName: "div.poll-container",
|
||||
buildKey: (attrs) => `poll-container-${attrs.id}`,
|
||||
|
||||
html(attrs) {
|
||||
defaultState() {
|
||||
return { voters: [] };
|
||||
},
|
||||
|
||||
html(attrs, state) {
|
||||
const { poll } = attrs;
|
||||
const options = poll.get("options");
|
||||
const options = poll.options;
|
||||
|
||||
if (attrs.showResults) {
|
||||
const contents = [];
|
||||
|
@ -352,12 +261,21 @@ createWidget("discourse-poll-container", {
|
|||
contents.push(new RawHtml({ html: attrs.titleHTML }));
|
||||
}
|
||||
|
||||
const type = poll.get("type") === "number" ? "number" : "standard";
|
||||
if (poll.public) {
|
||||
state.voters = poll.preloaded_voters;
|
||||
}
|
||||
|
||||
const type = poll.type === "number" ? "number" : "standard";
|
||||
const resultsWidget =
|
||||
type === "number" || attrs.poll.chart_type !== PIE_CHART_TYPE
|
||||
? `discourse-poll-${type}-results`
|
||||
: "discourse-poll-pie-chart";
|
||||
contents.push(this.attach(resultsWidget, attrs));
|
||||
contents.push(
|
||||
this.attach(
|
||||
resultsWidget,
|
||||
Object.assign({}, attrs, { voters: state.voters })
|
||||
)
|
||||
);
|
||||
|
||||
return contents;
|
||||
} else if (options) {
|
||||
|
@ -392,6 +310,71 @@ createWidget("discourse-poll-container", {
|
|||
return contents;
|
||||
}
|
||||
},
|
||||
|
||||
fetchVoters(optionId) {
|
||||
const { attrs, state } = this;
|
||||
let votersCount;
|
||||
|
||||
if (optionId) {
|
||||
if (!state.voters) {
|
||||
state.voters = {};
|
||||
}
|
||||
|
||||
if (!state.voters[optionId]) {
|
||||
state.voters[optionId] = [];
|
||||
}
|
||||
|
||||
votersCount = state.voters[optionId].length;
|
||||
} else {
|
||||
if (!state.voters) {
|
||||
state.voters = [];
|
||||
}
|
||||
|
||||
votersCount = state.voters.length;
|
||||
}
|
||||
|
||||
return ajax("/polls/voters.json", {
|
||||
data: {
|
||||
post_id: attrs.post.id,
|
||||
poll_name: attrs.poll.name,
|
||||
option_id: optionId,
|
||||
page: Math.floor(votersCount / FETCH_VOTERS_COUNT) + 1,
|
||||
limit: FETCH_VOTERS_COUNT,
|
||||
},
|
||||
})
|
||||
.then((result) => {
|
||||
const voters = optionId ? state.voters[optionId] : state.voters;
|
||||
const newVoters = optionId ? result.voters[optionId] : result.voters;
|
||||
|
||||
const votersSet = new Set(voters.map((voter) => voter.username));
|
||||
newVoters.forEach((voter) => {
|
||||
if (!votersSet.has(voter.username)) {
|
||||
votersSet.add(voter.username);
|
||||
voters.push(voter);
|
||||
}
|
||||
});
|
||||
|
||||
// remove users who changed their vote
|
||||
if (attrs.poll.type === "regular") {
|
||||
Object.keys(state.voters).forEach((otherOptionId) => {
|
||||
if (optionId !== otherOptionId) {
|
||||
state.voters[otherOptionId] = state.voters[otherOptionId].filter(
|
||||
(voter) => !votersSet.has(voter.username)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.scheduleRerender();
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error) {
|
||||
popupAjaxError(error);
|
||||
} else {
|
||||
bootbox.alert(I18n.t("poll.error_while_fetching_voters"));
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
createWidget("discourse-poll-info", {
|
||||
|
@ -422,7 +405,7 @@ createWidget("discourse-poll-info", {
|
|||
|
||||
html(attrs) {
|
||||
const { poll } = attrs;
|
||||
const count = poll.get("voters");
|
||||
const count = poll.voters;
|
||||
const contents = [
|
||||
h("p", [
|
||||
h("span.info-number", count.toString()),
|
||||
|
@ -432,7 +415,7 @@ createWidget("discourse-poll-info", {
|
|||
|
||||
if (attrs.isMultiple) {
|
||||
if (attrs.showResults || attrs.isClosed) {
|
||||
const totalVotes = poll.get("options").reduce((total, o) => {
|
||||
const totalVotes = poll.options.reduce((total, o) => {
|
||||
return total + parseInt(o.votes, 10);
|
||||
}, 0);
|
||||
|
||||
|
@ -449,7 +432,7 @@ createWidget("discourse-poll-info", {
|
|||
const help = this.multipleHelpText(
|
||||
attrs.min,
|
||||
attrs.max,
|
||||
poll.get("options.length")
|
||||
poll.options.length
|
||||
);
|
||||
if (help) {
|
||||
contents.push(infoTextHtml(help));
|
||||
|
@ -600,9 +583,9 @@ createWidget("discourse-poll-buttons", {
|
|||
})
|
||||
);
|
||||
} else {
|
||||
if (poll.get("results") === "on_vote" && !attrs.hasVoted && !isMe) {
|
||||
if (poll.results === "on_vote" && !attrs.hasVoted && !isMe) {
|
||||
contents.push(infoTextHtml(I18n.t("poll.results.vote.title")));
|
||||
} else if (poll.get("results") === "on_close" && !closed) {
|
||||
} else if (poll.results === "on_close" && !closed) {
|
||||
contents.push(infoTextHtml(I18n.t("poll.results.closed.title")));
|
||||
} else if (poll.results === "staff_only" && !isStaff) {
|
||||
contents.push(infoTextHtml(I18n.t("poll.results.staff.title")));
|
||||
|
@ -613,7 +596,7 @@ createWidget("discourse-poll-buttons", {
|
|||
label: "poll.show-results.label",
|
||||
title: "poll.show-results.title",
|
||||
icon: "far-eye",
|
||||
disabled: poll.get("voters") === 0,
|
||||
disabled: poll.voters === 0,
|
||||
action: "toggleResults",
|
||||
})
|
||||
);
|
||||
|
@ -645,8 +628,8 @@ createWidget("discourse-poll-buttons", {
|
|||
);
|
||||
}
|
||||
|
||||
if (poll.get("close")) {
|
||||
const closeDate = moment(poll.get("close"));
|
||||
if (poll.close) {
|
||||
const closeDate = moment(poll.close);
|
||||
if (closeDate.isValid()) {
|
||||
const title = closeDate.format("LLL");
|
||||
let label;
|
||||
|
@ -669,7 +652,7 @@ createWidget("discourse-poll-buttons", {
|
|||
|
||||
if (
|
||||
this.currentUser &&
|
||||
(this.currentUser.get("id") === post.get("user_id") || isStaff) &&
|
||||
(this.currentUser.id === post.user_id || isStaff) &&
|
||||
!topicArchived
|
||||
) {
|
||||
if (closed) {
|
||||
|
@ -712,19 +695,17 @@ export default createWidget("discourse-poll", {
|
|||
}
|
||||
return {
|
||||
class: cssClasses,
|
||||
"data-poll-name": attrs.poll.get("name"),
|
||||
"data-poll-type": attrs.poll.get("type"),
|
||||
"data-poll-name": attrs.poll.name,
|
||||
"data-poll-type": attrs.poll.type,
|
||||
};
|
||||
},
|
||||
|
||||
defaultState(attrs) {
|
||||
const { post, poll } = attrs;
|
||||
const { poll } = attrs;
|
||||
const staffOnly = attrs.poll.results === "staff_only";
|
||||
|
||||
const showResults =
|
||||
(post.get("topic.archived") && !staffOnly) ||
|
||||
(this.isClosed() && !staffOnly) ||
|
||||
(poll.results !== "on_close" && this.hasVoted() && !staffOnly);
|
||||
poll.results !== "on_close" && this.hasVoted() && !staffOnly;
|
||||
|
||||
return { loading: false, showResults };
|
||||
},
|
||||
|
@ -755,7 +736,7 @@ export default createWidget("discourse-poll", {
|
|||
},
|
||||
|
||||
min() {
|
||||
let min = parseInt(this.attrs.poll.get("min"), 10);
|
||||
let min = parseInt(this.attrs.poll.min, 10);
|
||||
if (isNaN(min) || min < 0) {
|
||||
min = 0;
|
||||
}
|
||||
|
@ -763,8 +744,8 @@ export default createWidget("discourse-poll", {
|
|||
},
|
||||
|
||||
max() {
|
||||
let max = parseInt(this.attrs.poll.get("max"), 10);
|
||||
const numOptions = this.attrs.poll.get("options.length");
|
||||
let max = parseInt(this.attrs.poll.max, 10);
|
||||
const numOptions = this.attrs.poll.options.length;
|
||||
if (isNaN(max) || max > numOptions) {
|
||||
max = numOptions;
|
||||
}
|
||||
|
@ -773,17 +754,17 @@ export default createWidget("discourse-poll", {
|
|||
|
||||
isAutomaticallyClosed() {
|
||||
const { poll } = this.attrs;
|
||||
return poll.get("close") && moment.utc(poll.get("close")) <= moment();
|
||||
return poll.close && moment.utc(poll.close) <= moment();
|
||||
},
|
||||
|
||||
isClosed() {
|
||||
const { poll } = this.attrs;
|
||||
return poll.get("status") === "closed" || this.isAutomaticallyClosed();
|
||||
return poll.status === "closed" || this.isAutomaticallyClosed();
|
||||
},
|
||||
|
||||
isMultiple() {
|
||||
const { poll } = this.attrs;
|
||||
return poll.get("type") === "multiple";
|
||||
return poll.type === "multiple";
|
||||
},
|
||||
|
||||
hasVoted() {
|
||||
|
@ -829,14 +810,14 @@ export default createWidget("discourse-poll", {
|
|||
ajax("/polls/toggle_status", {
|
||||
type: "PUT",
|
||||
data: {
|
||||
post_id: post.get("id"),
|
||||
poll_name: poll.get("name"),
|
||||
post_id: post.id,
|
||||
poll_name: poll.name,
|
||||
status,
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
poll.set("status", status);
|
||||
if (poll.get("results") === "on_close") {
|
||||
if (poll.results === "on_close") {
|
||||
state.showResults = status === "closed";
|
||||
}
|
||||
this.scheduleRerender();
|
||||
|
@ -955,7 +936,7 @@ export default createWidget("discourse-poll", {
|
|||
type: "PUT",
|
||||
data: {
|
||||
post_id: attrs.post.id,
|
||||
poll_name: attrs.poll.get("name"),
|
||||
poll_name: attrs.poll.name,
|
||||
options: attrs.vote,
|
||||
},
|
||||
})
|
||||
|
@ -963,11 +944,11 @@ export default createWidget("discourse-poll", {
|
|||
attrs.poll.setProperties(poll);
|
||||
this.appEvents.trigger("poll:voted", poll, attrs.post, attrs.vote);
|
||||
|
||||
if (attrs.poll.get("results") !== "on_close") {
|
||||
if (attrs.poll.results !== "on_close") {
|
||||
state.showResults = true;
|
||||
}
|
||||
if (attrs.poll.results === "staff_only") {
|
||||
if (this.currentUser && this.currentUser.get("staff")) {
|
||||
if (this.currentUser && this.currentUser.staff) {
|
||||
state.showResults = true;
|
||||
} else {
|
||||
state.showResults = false;
|
||||
|
|
|
@ -2,7 +2,7 @@ import {
|
|||
acceptance,
|
||||
publishToMessageBus,
|
||||
} from "discourse/tests/helpers/qunit-helpers";
|
||||
import { skip } from "qunit";
|
||||
import { test } from "qunit";
|
||||
import { clearPopupMenuOptionsCallback } from "discourse/controllers/composer";
|
||||
import { visit } from "@ember/test-helpers";
|
||||
|
||||
|
@ -553,13 +553,17 @@ acceptance("Poll results", function (needs) {
|
|||
});
|
||||
});
|
||||
|
||||
skip("can load more voters", async function (assert) {
|
||||
test("can load more voters", async function (assert) {
|
||||
await visit("/t/-/load-more-poll-voters");
|
||||
|
||||
assert.equal(
|
||||
find(".poll-container .results li:nth-child(1) .poll-voters li").length,
|
||||
1
|
||||
);
|
||||
assert.equal(
|
||||
find(".poll-container .results li:nth-child(2) .poll-voters li").length,
|
||||
0
|
||||
);
|
||||
|
||||
publishToMessageBus("/polls/134", {
|
||||
post_id: "156",
|
||||
|
@ -579,10 +583,10 @@ acceptance("Poll results", function (needs) {
|
|||
{
|
||||
id: "d8c22ff912e03740d9bc19e133e581e0",
|
||||
html: 'Option <span class="hashtag">#2</span>',
|
||||
votes: 1,
|
||||
votes: 2,
|
||||
},
|
||||
],
|
||||
voters: 2,
|
||||
voters: 3,
|
||||
preloaded_voters: {
|
||||
db753fe0bc4e72869ac1ad8765341764: [
|
||||
{
|
||||
|
@ -611,14 +615,25 @@ acceptance("Poll results", function (needs) {
|
|||
});
|
||||
await visit("/t/-/load-more-poll-voters");
|
||||
|
||||
await click(".poll-voters-toggle-expand a");
|
||||
assert.equal(
|
||||
find(".poll-container .results li:nth-child(1) .poll-voters li").length,
|
||||
0
|
||||
1
|
||||
);
|
||||
assert.equal(
|
||||
find(".poll-container .results li:nth-child(2) .poll-voters li").length,
|
||||
1
|
||||
);
|
||||
|
||||
await click(".poll-voters-toggle-expand a");
|
||||
await visit("/t/-/load-more-poll-voters");
|
||||
|
||||
assert.equal(
|
||||
find(".poll-container .results li:nth-child(1) .poll-voters li").length,
|
||||
2
|
||||
);
|
||||
assert.equal(
|
||||
find(".poll-container .results li:nth-child(2) .poll-voters li").length,
|
||||
0
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue