2019-10-23 13:06:54 -04:00
|
|
|
import Controller from "@ember/controller";
|
2021-04-12 12:48:01 -04:00
|
|
|
import EmberObject, { action } from "@ember/object";
|
|
|
|
import { gt, or } from "@ember/object/computed";
|
|
|
|
import { next } from "@ember/runloop";
|
|
|
|
import discourseComputed, { observes } from "discourse-common/utils/decorators";
|
|
|
|
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
2020-08-06 11:57:06 -04:00
|
|
|
import I18n from "I18n";
|
2016-06-13 06:21:14 -04:00
|
|
|
|
2019-11-25 12:51:01 -05:00
|
|
|
export const BAR_CHART_TYPE = "bar";
|
|
|
|
export const PIE_CHART_TYPE = "pie";
|
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
export const REGULAR_POLL_TYPE = "regular";
|
|
|
|
export const NUMBER_POLL_TYPE = "number";
|
|
|
|
export const MULTIPLE_POLL_TYPE = "multiple";
|
|
|
|
|
|
|
|
const ALWAYS_POLL_RESULT = "always";
|
|
|
|
const VOTE_POLL_RESULT = "on_vote";
|
|
|
|
const CLOSED_POLL_RESULT = "on_close";
|
|
|
|
const STAFF_POLL_RESULT = "staff_only";
|
|
|
|
|
|
|
|
export default Controller.extend(ModalFunctionality, {
|
|
|
|
showAdvanced: false,
|
|
|
|
|
|
|
|
pollType: REGULAR_POLL_TYPE,
|
|
|
|
pollTitle: "",
|
|
|
|
pollOptions: null,
|
2021-04-23 09:54:53 -04:00
|
|
|
pollOptionsText: null,
|
2021-04-12 12:48:01 -04:00
|
|
|
pollMin: 1,
|
|
|
|
pollMax: 2,
|
|
|
|
pollStep: 1,
|
|
|
|
pollGroups: null,
|
|
|
|
pollAutoClose: null,
|
|
|
|
pollResult: ALWAYS_POLL_RESULT,
|
|
|
|
chartType: BAR_CHART_TYPE,
|
|
|
|
publicPoll: null,
|
|
|
|
|
|
|
|
onShow() {
|
|
|
|
this.setProperties({
|
|
|
|
showAdvanced: false,
|
|
|
|
pollType: REGULAR_POLL_TYPE,
|
|
|
|
pollTitle: null,
|
|
|
|
pollOptions: [EmberObject.create({ value: "" })],
|
2021-04-23 09:54:53 -04:00
|
|
|
pollOptionsText: "",
|
2021-04-12 12:48:01 -04:00
|
|
|
pollMin: 1,
|
|
|
|
pollMax: 2,
|
|
|
|
pollStep: 1,
|
|
|
|
pollGroups: null,
|
|
|
|
pollAutoClose: null,
|
|
|
|
pollResult: ALWAYS_POLL_RESULT,
|
|
|
|
chartType: BAR_CHART_TYPE,
|
|
|
|
publicPoll: false,
|
|
|
|
});
|
2019-11-25 12:51:01 -05:00
|
|
|
},
|
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
@discourseComputed
|
|
|
|
pollResults() {
|
|
|
|
const options = [
|
2018-11-19 08:50:00 -05:00
|
|
|
{
|
|
|
|
name: I18n.t("poll.ui_builder.poll_result.always"),
|
2021-04-12 12:48:01 -04:00
|
|
|
value: ALWAYS_POLL_RESULT,
|
2018-11-19 08:50:00 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: I18n.t("poll.ui_builder.poll_result.vote"),
|
2021-04-12 12:48:01 -04:00
|
|
|
value: VOTE_POLL_RESULT,
|
2018-11-19 08:50:00 -05:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: I18n.t("poll.ui_builder.poll_result.closed"),
|
2021-04-12 12:48:01 -04:00
|
|
|
value: CLOSED_POLL_RESULT,
|
2018-11-19 08:50:00 -05:00
|
|
|
},
|
|
|
|
];
|
2021-04-12 12:48:01 -04:00
|
|
|
|
2020-02-03 08:22:14 -05:00
|
|
|
if (this.get("currentUser.staff")) {
|
2019-12-17 16:43:15 -05:00
|
|
|
options.push({
|
|
|
|
name: I18n.t("poll.ui_builder.poll_result.staff"),
|
2021-04-12 12:48:01 -04:00
|
|
|
value: STAFF_POLL_RESULT,
|
2019-12-17 16:43:15 -05:00
|
|
|
});
|
|
|
|
}
|
2018-11-19 08:50:00 -05:00
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
return options;
|
2020-01-28 07:30:04 -05:00
|
|
|
},
|
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
@discourseComputed("pollType")
|
|
|
|
isRegular(pollType) {
|
|
|
|
return pollType === REGULAR_POLL_TYPE;
|
2017-04-04 23:15:39 -04:00
|
|
|
},
|
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
@discourseComputed("pollType")
|
|
|
|
isNumber(pollType) {
|
|
|
|
return pollType === NUMBER_POLL_TYPE;
|
2016-06-13 06:21:14 -04:00
|
|
|
},
|
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
@discourseComputed("pollType")
|
|
|
|
isMultiple(pollType) {
|
|
|
|
return pollType === MULTIPLE_POLL_TYPE;
|
2016-06-13 06:21:14 -04:00
|
|
|
},
|
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
showNumber: or("showAdvanced", "isNumber"),
|
2016-06-13 06:21:14 -04:00
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
@discourseComputed("pollOptions.@each.value")
|
2016-06-13 06:21:14 -04:00
|
|
|
pollOptionsCount(pollOptions) {
|
2021-06-09 10:58:55 -04:00
|
|
|
return (pollOptions || []).filter((option) => option.value.length > 0)
|
|
|
|
.length;
|
2016-06-13 06:21:14 -04:00
|
|
|
},
|
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
@discourseComputed("site.groups")
|
|
|
|
siteGroups(groups) {
|
|
|
|
// prevents group "everyone" to be listed
|
|
|
|
return groups.filter((g) => g.id !== 0);
|
2016-06-13 06:21:14 -04:00
|
|
|
},
|
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
@discourseComputed("chartType", "pollType")
|
|
|
|
isPie(chartType, pollType) {
|
|
|
|
return pollType !== NUMBER_POLL_TYPE && chartType === PIE_CHART_TYPE;
|
2016-06-13 06:21:14 -04:00
|
|
|
},
|
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
canRemoveOption: gt("pollOptions.length", 1),
|
2016-06-13 06:21:14 -04:00
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
@observes("pollType", "pollOptionsCount")
|
|
|
|
_setPollMinMax() {
|
|
|
|
if (this.isMultiple) {
|
|
|
|
if (
|
2021-04-22 14:36:32 -04:00
|
|
|
this.pollMin <= 0 ||
|
2021-04-12 12:48:01 -04:00
|
|
|
this.pollMin >= this.pollMax ||
|
|
|
|
this.pollMin >= this.pollOptionsCount
|
|
|
|
) {
|
|
|
|
this.set("pollMin", this.pollOptionsCount > 0 ? 1 : 0);
|
2017-11-30 11:04:41 -05:00
|
|
|
}
|
2016-06-13 06:21:14 -04:00
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
if (
|
2021-04-22 14:36:32 -04:00
|
|
|
this.pollMax <= 0 ||
|
2021-04-12 12:48:01 -04:00
|
|
|
this.pollMin >= this.pollMax ||
|
|
|
|
this.pollMax > this.pollOptionsCount
|
|
|
|
) {
|
2021-04-22 14:36:32 -04:00
|
|
|
this.set("pollMax", this.pollOptionsCount);
|
2021-04-12 12:48:01 -04:00
|
|
|
}
|
|
|
|
} else if (this.isNumber) {
|
|
|
|
this.set("pollMax", this.siteSettings.poll_maximum_options);
|
2020-09-22 10:28:28 -04:00
|
|
|
}
|
2016-06-13 06:21:14 -04:00
|
|
|
},
|
|
|
|
|
2020-02-03 08:22:14 -05:00
|
|
|
@discourseComputed(
|
2018-06-15 12:42:20 -04:00
|
|
|
"pollType",
|
2018-11-19 08:50:00 -05:00
|
|
|
"pollResult",
|
2018-06-15 12:42:20 -04:00
|
|
|
"publicPoll",
|
2020-10-02 03:21:24 -04:00
|
|
|
"pollTitle",
|
2021-04-12 12:48:01 -04:00
|
|
|
"pollOptions.@each.value",
|
2018-06-15 12:42:20 -04:00
|
|
|
"pollMin",
|
|
|
|
"pollMax",
|
|
|
|
"pollStep",
|
2020-01-28 07:30:04 -05:00
|
|
|
"pollGroups",
|
2021-04-12 12:48:01 -04:00
|
|
|
"pollAutoClose",
|
|
|
|
"chartType"
|
2018-06-15 12:42:20 -04:00
|
|
|
)
|
|
|
|
pollOutput(
|
|
|
|
pollType,
|
2018-11-19 08:50:00 -05:00
|
|
|
pollResult,
|
2018-06-15 12:42:20 -04:00
|
|
|
publicPoll,
|
2020-10-02 03:21:24 -04:00
|
|
|
pollTitle,
|
2018-06-15 12:42:20 -04:00
|
|
|
pollOptions,
|
|
|
|
pollMin,
|
|
|
|
pollMax,
|
|
|
|
pollStep,
|
2020-01-28 07:30:04 -05:00
|
|
|
pollGroups,
|
2021-04-12 12:48:01 -04:00
|
|
|
pollAutoClose,
|
|
|
|
chartType
|
2018-06-15 12:42:20 -04:00
|
|
|
) {
|
|
|
|
let pollHeader = "[poll";
|
|
|
|
let output = "";
|
|
|
|
|
2019-05-27 04:15:39 -04:00
|
|
|
const match = this.toolbarEvent
|
2018-06-15 12:42:20 -04:00
|
|
|
.getText()
|
|
|
|
.match(/\[poll(\s+name=[^\s\]]+)*.*\]/gim);
|
2016-07-05 10:14:59 -04:00
|
|
|
|
|
|
|
if (match) {
|
|
|
|
pollHeader += ` name=poll${match.length + 1}`;
|
2018-06-15 12:42:20 -04:00
|
|
|
}
|
2016-07-05 10:14:59 -04:00
|
|
|
|
2017-11-30 11:04:41 -05:00
|
|
|
let step = pollStep;
|
2018-06-15 12:42:20 -04:00
|
|
|
if (step < 1) {
|
|
|
|
step = 1;
|
|
|
|
}
|
2017-11-30 11:04:41 -05:00
|
|
|
|
2020-09-22 10:28:28 -04:00
|
|
|
if (pollType) {
|
|
|
|
pollHeader += ` type=${pollType}`;
|
|
|
|
}
|
|
|
|
if (pollResult) {
|
|
|
|
pollHeader += ` results=${pollResult}`;
|
|
|
|
}
|
2021-04-12 12:48:01 -04:00
|
|
|
if (pollMin && pollType !== REGULAR_POLL_TYPE) {
|
2020-09-22 10:28:28 -04:00
|
|
|
pollHeader += ` min=${pollMin}`;
|
|
|
|
}
|
2021-04-12 12:48:01 -04:00
|
|
|
if (pollMax && pollType !== REGULAR_POLL_TYPE) {
|
2020-09-22 10:28:28 -04:00
|
|
|
pollHeader += ` max=${pollMax}`;
|
|
|
|
}
|
2021-04-12 12:48:01 -04:00
|
|
|
if (pollType === NUMBER_POLL_TYPE) {
|
2020-09-22 10:28:28 -04:00
|
|
|
pollHeader += ` step=${step}`;
|
|
|
|
}
|
|
|
|
if (publicPoll) {
|
|
|
|
pollHeader += ` public=true`;
|
|
|
|
}
|
2021-04-12 12:48:01 -04:00
|
|
|
if (chartType && pollType !== NUMBER_POLL_TYPE) {
|
2019-11-25 12:51:01 -05:00
|
|
|
pollHeader += ` chartType=${chartType}`;
|
2020-09-22 10:28:28 -04:00
|
|
|
}
|
2020-06-12 07:52:32 -04:00
|
|
|
if (pollGroups && pollGroups.length > 0) {
|
|
|
|
pollHeader += ` groups=${pollGroups}`;
|
|
|
|
}
|
2021-04-12 12:48:01 -04:00
|
|
|
if (pollAutoClose) {
|
|
|
|
pollHeader += ` close=${pollAutoClose.toISOString()}`;
|
2018-06-12 09:31:09 -04:00
|
|
|
}
|
2018-05-02 20:12:19 -04:00
|
|
|
|
2018-06-15 12:42:20 -04:00
|
|
|
pollHeader += "]";
|
2016-06-13 06:21:14 -04:00
|
|
|
output += `${pollHeader}\n`;
|
|
|
|
|
2020-10-02 03:21:24 -04:00
|
|
|
if (pollTitle) {
|
|
|
|
output += `# ${pollTitle.trim()}\n`;
|
|
|
|
}
|
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
if (pollOptions.length > 0 && pollType !== NUMBER_POLL_TYPE) {
|
|
|
|
pollOptions.forEach((option) => {
|
|
|
|
if (option.value.length > 0) {
|
|
|
|
output += `* ${option.value.trim()}\n`;
|
2020-09-22 10:28:28 -04:00
|
|
|
}
|
2016-07-14 03:10:31 -04:00
|
|
|
});
|
2016-06-13 06:21:14 -04:00
|
|
|
}
|
|
|
|
|
2019-10-16 21:40:42 -04:00
|
|
|
output += "[/poll]\n";
|
2016-06-13 06:21:14 -04:00
|
|
|
return output;
|
|
|
|
},
|
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
@discourseComputed("isNumber", "pollOptionsCount")
|
|
|
|
minNumOfOptionsValidation(isNumber, pollOptionsCount) {
|
2017-03-14 12:34:30 -04:00
|
|
|
let options = { ok: true };
|
|
|
|
|
2021-04-22 14:36:32 -04:00
|
|
|
if (!isNumber) {
|
|
|
|
if (pollOptionsCount < 1) {
|
|
|
|
return EmberObject.create({
|
|
|
|
failed: true,
|
|
|
|
reason: I18n.t("poll.ui_builder.help.options_min_count"),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pollOptionsCount > this.siteSettings.poll_maximum_options) {
|
|
|
|
return EmberObject.create({
|
|
|
|
failed: true,
|
|
|
|
reason: I18n.t("poll.ui_builder.help.options_max_count", {
|
|
|
|
count: this.siteSettings.poll_maximum_options,
|
|
|
|
}),
|
|
|
|
});
|
|
|
|
}
|
2017-03-14 12:34:30 -04:00
|
|
|
}
|
|
|
|
|
2019-11-11 15:48:33 -05:00
|
|
|
return EmberObject.create(options);
|
2016-06-13 06:21:14 -04:00
|
|
|
},
|
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
@discourseComputed("pollOptions.@each.value")
|
|
|
|
showMinNumOfOptionsValidation(pollOptions) {
|
|
|
|
return pollOptions.length !== 1 || pollOptions[0].value !== "";
|
|
|
|
},
|
2017-11-30 11:04:41 -05:00
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
@discourseComputed(
|
|
|
|
"isMultiple",
|
|
|
|
"pollOptionsCount",
|
|
|
|
"isNumber",
|
|
|
|
"pollMin",
|
2021-04-22 14:36:32 -04:00
|
|
|
"pollMax",
|
|
|
|
"pollStep"
|
2021-04-12 12:48:01 -04:00
|
|
|
)
|
|
|
|
minMaxValueValidation(
|
|
|
|
isMultiple,
|
|
|
|
pollOptionsCount,
|
|
|
|
isNumber,
|
|
|
|
pollMin,
|
2021-04-22 14:36:32 -04:00
|
|
|
pollMax,
|
|
|
|
pollStep
|
2021-04-12 12:48:01 -04:00
|
|
|
) {
|
|
|
|
pollMin = parseInt(pollMin, 10) || 0;
|
|
|
|
pollMax = parseInt(pollMax, 10) || 0;
|
2021-04-22 14:36:32 -04:00
|
|
|
pollStep = parseInt(pollStep, 10) || 0;
|
2021-04-12 12:48:01 -04:00
|
|
|
|
2021-04-22 14:36:32 -04:00
|
|
|
if (pollMin < 0) {
|
|
|
|
return EmberObject.create({
|
|
|
|
failed: true,
|
|
|
|
reason: I18n.t("poll.ui_builder.help.invalid_min_value"),
|
|
|
|
});
|
|
|
|
}
|
2021-04-12 12:48:01 -04:00
|
|
|
|
2021-04-22 14:36:32 -04:00
|
|
|
if (pollMax < 0 || (isMultiple && pollMax > pollOptionsCount)) {
|
|
|
|
return EmberObject.create({
|
|
|
|
failed: true,
|
|
|
|
reason: I18n.t("poll.ui_builder.help.invalid_max_value"),
|
|
|
|
});
|
2017-11-30 11:04:41 -05:00
|
|
|
}
|
|
|
|
|
2021-04-22 14:36:32 -04:00
|
|
|
if (pollMin > pollMax) {
|
|
|
|
return EmberObject.create({
|
|
|
|
failed: true,
|
|
|
|
reason: I18n.t("poll.ui_builder.help.invalid_values"),
|
|
|
|
});
|
|
|
|
}
|
2017-11-30 11:04:41 -05:00
|
|
|
|
2021-04-22 14:36:32 -04:00
|
|
|
if (isNumber) {
|
|
|
|
if (pollStep < 1) {
|
|
|
|
return EmberObject.create({
|
|
|
|
failed: true,
|
|
|
|
reason: I18n.t("poll.ui_builder.help.min_step_value"),
|
|
|
|
});
|
|
|
|
}
|
2016-06-13 06:21:14 -04:00
|
|
|
|
2021-04-22 14:36:32 -04:00
|
|
|
const optionsCount = (pollMax - pollMin + 1) / pollStep;
|
|
|
|
|
|
|
|
if (optionsCount < 1) {
|
|
|
|
return EmberObject.create({
|
|
|
|
failed: true,
|
|
|
|
reason: I18n.t("poll.ui_builder.help.options_min_count"),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (optionsCount > this.siteSettings.poll_maximum_options) {
|
|
|
|
return EmberObject.create({
|
|
|
|
failed: true,
|
|
|
|
reason: I18n.t("poll.ui_builder.help.options_max_count", {
|
|
|
|
count: this.siteSettings.poll_maximum_options,
|
|
|
|
}),
|
|
|
|
});
|
|
|
|
}
|
2016-06-13 06:21:14 -04:00
|
|
|
}
|
|
|
|
|
2021-04-22 14:36:32 -04:00
|
|
|
return EmberObject.create({ ok: true });
|
2016-06-13 06:21:14 -04:00
|
|
|
},
|
|
|
|
|
2021-04-22 14:36:32 -04:00
|
|
|
@discourseComputed("minMaxValueValidation", "minNumOfOptionsValidation")
|
|
|
|
disableInsert(minMaxValueValidation, minNumOfOptionsValidation) {
|
|
|
|
return !minMaxValueValidation.ok || !minNumOfOptionsValidation.ok;
|
2021-04-12 12:48:01 -04:00
|
|
|
},
|
|
|
|
|
2020-08-31 16:34:14 -04:00
|
|
|
_comboboxOptions(startIndex, endIndex) {
|
|
|
|
return [...Array(endIndex - startIndex).keys()].map((number) => ({
|
|
|
|
value: number + startIndex,
|
|
|
|
name: number + startIndex,
|
|
|
|
}));
|
2016-06-13 06:21:14 -04:00
|
|
|
},
|
|
|
|
|
2021-04-23 09:54:53 -04:00
|
|
|
@action
|
|
|
|
onOptionsTextChange(e) {
|
|
|
|
let idx = 0;
|
|
|
|
this.set(
|
|
|
|
"pollOptions",
|
|
|
|
e.target.value
|
|
|
|
.split("\n")
|
|
|
|
.map((value) => EmberObject.create({ idx: idx++, value }))
|
|
|
|
);
|
|
|
|
},
|
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
@action
|
|
|
|
insertPoll() {
|
|
|
|
this.toolbarEvent.addText(this.pollOutput);
|
|
|
|
this.send("closeModal");
|
|
|
|
},
|
|
|
|
|
|
|
|
@action
|
|
|
|
toggleAdvanced() {
|
|
|
|
this.toggleProperty("showAdvanced");
|
2021-04-23 09:54:53 -04:00
|
|
|
if (this.showAdvanced) {
|
|
|
|
this.set(
|
|
|
|
"pollOptionsText",
|
|
|
|
this.pollOptions.map((x) => x.value).join("\n")
|
|
|
|
);
|
|
|
|
}
|
2021-04-12 12:48:01 -04:00
|
|
|
},
|
|
|
|
|
|
|
|
@action
|
|
|
|
addOption(beforeOption, value, e) {
|
|
|
|
if (value !== "") {
|
|
|
|
const idx = this.pollOptions.indexOf(beforeOption) + 1;
|
|
|
|
const option = EmberObject.create({ value: "" });
|
|
|
|
this.pollOptions.insertAt(idx, option);
|
|
|
|
|
|
|
|
let lastOptionIdx = 0;
|
|
|
|
this.pollOptions.forEach((o) => o.set("idx", lastOptionIdx++));
|
|
|
|
|
|
|
|
next(() => {
|
|
|
|
const pollOptions = document.getElementsByClassName("poll-options");
|
|
|
|
if (pollOptions) {
|
|
|
|
const inputs = pollOptions[0].getElementsByTagName("input");
|
|
|
|
if (option.idx < inputs.length) {
|
|
|
|
inputs[option.idx].focus();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (e) {
|
|
|
|
e.preventDefault();
|
|
|
|
}
|
2016-06-13 06:21:14 -04:00
|
|
|
},
|
|
|
|
|
2021-04-12 12:48:01 -04:00
|
|
|
@action
|
|
|
|
removeOption(option) {
|
|
|
|
this.pollOptions.removeObject(option);
|
2016-06-13 06:21:14 -04:00
|
|
|
},
|
DEV: Remove usage of {{action}} modifiers - Take 2 (#18476)
This PR enables the [`no-action-modifiers`](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-action-modifiers.md) template lint rule and removes all usages of the `{{action}}` modifier in core.
In general, instances of `{{action "x"}}` have been replaced with `{{on "click" (action "x")}}`.
In many cases, such as for `a` elements, we also need to prevent default event handling to avoid unwanted side effects. While the `{{action}}` modifier internally calls `event.preventDefault()`, we need to handle these cases more explicitly. For this purpose, this PR also adds the [ember-event-helpers](https://github.com/buschtoens/ember-event-helpers) dependency so we can use the `prevent-default` handler. For instance:
```
<a href {{on "click" (prevent-default (action "x"))}}>Do X</a>
```
Note that `action` has not in general been refactored away as a helper yet. In general, all event handlers should be methods on the corresponding component and referenced directly (e.g. `{{on "click" this.doSomething}}`). However, the `action` helper is used extensively throughout the codebase and often references methods in the `actions` hash on controllers or routes. Thus this refactor will also be extensive and probably deserves a separate PR.
Note: This work was done to complement #17767 by minimizing the potential impact of the `action` modifier override, which uses private API and arguably should be replaced with an AST transform.
This is a followup to #18333, which had to be reverted because it did not account for the default treatment of modifier keys by the {{action}} modifier.
Commits:
* Enable `no-action-modifiers` template lint rule
* Replace {{action "x"}} with {{on "click" (action "x")}}
* Remove unnecessary action helper usage
* Remove ctl+click tests for user-menu
These tests now break in Chrome when used with addEventListener. As per the comment, they can probably be safely removed.
* Prevent default event handlers to avoid unwanted side effects
Uses `event.preventDefault()` in event handlers to prevent default event handling. This had been done automatically by the `action` modifier, but is not always desirable or necessary.
* Restore UserCardContents#showUser action to avoid regression
By keeping the `showUser` action, we can avoid a breaking change for plugins that rely upon it, while not interfering with the `showUser` argument that's been passed.
* Revert EditCategoryTab#selectTab -> EditCategoryTab#select
Avoid potential breaking change in themes / plugins
* Restore GroupCardContents#showGroup action to avoid regression
By keeping the `showGroup` action, we can avoid a breaking change for plugins that rely upon it, while not interfering with the `showGroup` argument that's been passed.
* Restore SecondFactorAddTotp#showSecondFactorKey action to avoid regression
By keeping the `showSecondFactorKey` action, we can avoid a breaking change for plugins that rely upon it, while not interfering with the `showSecondFactorKey` property that's maintained on the controller.
* Refactor away from `actions` hash in ChooseMessage component
* Modernize EmojiPicker#onCategorySelection usage
* Modernize SearchResultEntry#logClick usage
* Modernize Discovery::Categories#showInserted usage
* Modernize Preferences::Account#resendConfirmationEmail usage
* Modernize MultiSelect::SelectedCategory#onSelectedNameClick usage
* Favor fn over action in SelectedChoice component
* Modernize WizardStep event handlers
* Favor fn over action usage in buttons
* Restore Login#forgotPassword action to avoid possible regression
* Introduce modKeysPressed utility
Returns an array of modifier keys that are pressed during a given `MouseEvent` or `KeyboardEvent`.
* Don't interfere with click events on links with `href` values when modifier keys are pressed
2022-10-05 08:08:54 -04:00
|
|
|
|
|
|
|
@action
|
|
|
|
updatePollType(pollType, event) {
|
|
|
|
event?.preventDefault();
|
2022-10-11 06:20:18 -04:00
|
|
|
this.set("pollType", pollType);
|
DEV: Remove usage of {{action}} modifiers - Take 2 (#18476)
This PR enables the [`no-action-modifiers`](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-action-modifiers.md) template lint rule and removes all usages of the `{{action}}` modifier in core.
In general, instances of `{{action "x"}}` have been replaced with `{{on "click" (action "x")}}`.
In many cases, such as for `a` elements, we also need to prevent default event handling to avoid unwanted side effects. While the `{{action}}` modifier internally calls `event.preventDefault()`, we need to handle these cases more explicitly. For this purpose, this PR also adds the [ember-event-helpers](https://github.com/buschtoens/ember-event-helpers) dependency so we can use the `prevent-default` handler. For instance:
```
<a href {{on "click" (prevent-default (action "x"))}}>Do X</a>
```
Note that `action` has not in general been refactored away as a helper yet. In general, all event handlers should be methods on the corresponding component and referenced directly (e.g. `{{on "click" this.doSomething}}`). However, the `action` helper is used extensively throughout the codebase and often references methods in the `actions` hash on controllers or routes. Thus this refactor will also be extensive and probably deserves a separate PR.
Note: This work was done to complement #17767 by minimizing the potential impact of the `action` modifier override, which uses private API and arguably should be replaced with an AST transform.
This is a followup to #18333, which had to be reverted because it did not account for the default treatment of modifier keys by the {{action}} modifier.
Commits:
* Enable `no-action-modifiers` template lint rule
* Replace {{action "x"}} with {{on "click" (action "x")}}
* Remove unnecessary action helper usage
* Remove ctl+click tests for user-menu
These tests now break in Chrome when used with addEventListener. As per the comment, they can probably be safely removed.
* Prevent default event handlers to avoid unwanted side effects
Uses `event.preventDefault()` in event handlers to prevent default event handling. This had been done automatically by the `action` modifier, but is not always desirable or necessary.
* Restore UserCardContents#showUser action to avoid regression
By keeping the `showUser` action, we can avoid a breaking change for plugins that rely upon it, while not interfering with the `showUser` argument that's been passed.
* Revert EditCategoryTab#selectTab -> EditCategoryTab#select
Avoid potential breaking change in themes / plugins
* Restore GroupCardContents#showGroup action to avoid regression
By keeping the `showGroup` action, we can avoid a breaking change for plugins that rely upon it, while not interfering with the `showGroup` argument that's been passed.
* Restore SecondFactorAddTotp#showSecondFactorKey action to avoid regression
By keeping the `showSecondFactorKey` action, we can avoid a breaking change for plugins that rely upon it, while not interfering with the `showSecondFactorKey` property that's maintained on the controller.
* Refactor away from `actions` hash in ChooseMessage component
* Modernize EmojiPicker#onCategorySelection usage
* Modernize SearchResultEntry#logClick usage
* Modernize Discovery::Categories#showInserted usage
* Modernize Preferences::Account#resendConfirmationEmail usage
* Modernize MultiSelect::SelectedCategory#onSelectedNameClick usage
* Favor fn over action in SelectedChoice component
* Modernize WizardStep event handlers
* Favor fn over action usage in buttons
* Restore Login#forgotPassword action to avoid possible regression
* Introduce modKeysPressed utility
Returns an array of modifier keys that are pressed during a given `MouseEvent` or `KeyboardEvent`.
* Don't interfere with click events on links with `href` values when modifier keys are pressed
2022-10-05 08:08:54 -04:00
|
|
|
},
|
2016-06-13 06:21:14 -04:00
|
|
|
});
|