REFACTOR: setting component mixin (#14437)

* REFACTOR: setting component mixing

- drops jquery usage
- extract spit function
- uses @action
- removes get usage where possible
- uses helpers
- minor changes

Co-authored-by: Jarek Radosz <jradosz@gmail.com>
This commit is contained in:
Joffrey JAFFEUX
2021-09-27 10:43:26 +02:00
committed by GitHub
parent 37413f180a
commit 1abe807528
2 changed files with 150 additions and 149 deletions

View File

@@ -1,14 +1,18 @@
import { isNone } from "@ember/utils";
import { fmt, propertyNotEqual } from "discourse/lib/computed";
import { alias, oneWay } from "@ember/object/computed"; import { alias, oneWay } from "@ember/object/computed";
import I18n from "I18n"; import I18n from "I18n";
import Mixin from "@ember/object/mixin"; import Mixin from "@ember/object/mixin";
import { Promise } from "rsvp"; import { Promise } from "rsvp";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import { categoryLinkHTML } from "discourse/helpers/category-link"; import { categoryLinkHTML } from "discourse/helpers/category-link";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed, { bind } from "discourse-common/utils/decorators";
import { htmlSafe } from "@ember/template"; import { htmlSafe } from "@ember/template";
import { on } from "@ember/object/evented"; import { on } from "@ember/object/evented";
import showModal from "discourse/lib/show-modal"; import showModal from "discourse/lib/show-modal";
import { warn } from "@ember/debug"; import { warn } from "@ember/debug";
import { action } from "@ember/object";
import { splitString } from "discourse/lib/utilities";
const CUSTOM_TYPES = [ const CUSTOM_TYPES = [
"bool", "bool",
@@ -32,26 +36,20 @@ const CUSTOM_TYPES = [
const AUTO_REFRESH_ON_SAVE = ["logo", "logo_small", "large_icon"]; const AUTO_REFRESH_ON_SAVE = ["logo", "logo_small", "large_icon"];
function splitPipes(str) {
if (typeof str === "string") {
return str.split("|").filter(Boolean);
} else {
return [];
}
}
export default Mixin.create({ export default Mixin.create({
classNameBindings: [":row", ":setting", "overridden", "typeClass"], classNameBindings: [":row", ":setting", "overridden", "typeClass"],
content: alias("setting"), content: alias("setting"),
validationMessage: null, validationMessage: null,
isSecret: oneWay("setting.secret"), isSecret: oneWay("setting.secret"),
setting: null,
@discourseComputed("buffered.value", "setting.value") @discourseComputed("buffered.value", "setting.value")
dirty(bufferVal, settingVal) { dirty(bufferVal, settingVal) {
if (bufferVal === null || bufferVal === undefined) { if (isNone(bufferVal)) {
bufferVal = ""; bufferVal = "";
} }
if (settingVal === null || settingVal === undefined) {
if (isNone(settingVal)) {
settingVal = ""; settingVal = "";
} }
@@ -61,21 +59,17 @@ export default Mixin.create({
@discourseComputed("setting", "buffered.value") @discourseComputed("setting", "buffered.value")
preview(setting, value) { preview(setting, value) {
// A bit hacky, but allows us to use helpers // A bit hacky, but allows us to use helpers
if (setting.get("setting") === "category_style") { if (setting.setting === "category_style") {
let category = this.site.get("categories.firstObject"); const category = this.site.get("categories.firstObject");
if (category) { if (category) {
return categoryLinkHTML(category, { return categoryLinkHTML(category, { categoryStyle: value });
categoryStyle: value,
});
} }
} }
let preview = setting.get("preview");
const preview = setting.preview;
if (preview) { if (preview) {
return htmlSafe( const escapedValue = preview.replace(/\{\{value\}\}/g, value);
"<div class='preview'>" + return htmlSafe(`<div class='preview'>${escapedValue}</div>`);
preview.replace(/\{\{value\}\}/g, value) +
"</div>"
);
} }
}, },
@@ -103,61 +97,34 @@ export default Mixin.create({
return setting.type; return setting.type;
}, },
@discourseComputed("typeClass") componentName: fmt("typeClass", "site-settings/%@"),
componentName(typeClass) {
return "site-settings/" + typeClass;
},
@discourseComputed("setting.anyValue") @discourseComputed("setting.anyValue")
allowAny(anyValue) { allowAny(anyValue) {
return anyValue !== false; return anyValue !== false;
}, },
@discourseComputed("setting.default", "buffered.value") overridden: propertyNotEqual("setting.default", "buffered.value"),
overridden(settingDefault, bufferedValue) {
return settingDefault !== bufferedValue;
},
@discourseComputed("buffered.value") @discourseComputed("buffered.value")
bufferedValues: splitPipes, bufferedValues(value) {
return splitString(value, "|");
},
@discourseComputed("setting.defaultValues") @discourseComputed("setting.defaultValues")
defaultValues: splitPipes, defaultValues(value) {
return splitString(value, "|");
},
@discourseComputed("defaultValues", "bufferedValues") @discourseComputed("defaultValues", "bufferedValues")
defaultIsAvailable(defaultValues, bufferedValues) { defaultIsAvailable(defaultValues, bufferedValues) {
return ( return (
defaultValues &&
defaultValues.length > 0 && defaultValues.length > 0 &&
!defaultValues.every((value) => bufferedValues.includes(value)) !defaultValues.every((value) => bufferedValues.includes(value))
); );
}, },
_watchEnterKey: on("didInsertElement", function () { @action
$(this.element).on(
"keydown.setting-enter",
".input-setting-string",
(e) => {
if (e.key === "Enter") {
// enter key
this.send("save");
}
}
);
}),
_removeBindings: on("willDestroyElement", function () {
$(this.element).off("keydown.setting-enter");
}),
_save() {
warn("You should define a `_save` method", {
id: "discourse.setting-component.missing-save",
});
return Promise.resolve();
},
actions: {
update() { update() {
const defaultUserPreferences = [ const defaultUserPreferences = [
"default_email_digest_frequency", "default_email_digest_frequency",
@@ -204,26 +171,24 @@ export default Mixin.create({
if (count > 0) { if (count > 0) {
const controller = showModal("site-setting-default-categories", { const controller = showModal("site-setting-default-categories", {
model: { model: { count, key: key.replaceAll("_", " ") },
count: result.user_count,
key: key.replace(/_/g, " "),
},
admin: true, admin: true,
}); });
controller.set("onClose", () => { controller.set("onClose", () => {
this.updateExistingUsers = controller.updateExistingUsers; this.updateExistingUsers = controller.updateExistingUsers;
this.send("save"); this.save();
}); });
} else { } else {
this.send("save"); this.save();
} }
}); });
} else { } else {
this.send("save"); this.save();
} }
}, },
@action
save() { save() {
this._save() this._save()
.then(() => { .then(() => {
@@ -234,7 +199,7 @@ export default Mixin.create({
} }
}) })
.catch((e) => { .catch((e) => {
if (e.jqXHR.responseJSON && e.jqXHR.responseJSON.errors) { if (e.jqXHR?.responseJSON?.errors) {
this.set("validationMessage", e.jqXHR.responseJSON.errors[0]); this.set("validationMessage", e.jqXHR.responseJSON.errors[0]);
} else { } else {
this.set("validationMessage", I18n.t("generic_error")); this.set("validationMessage", I18n.t("generic_error"));
@@ -242,18 +207,22 @@ export default Mixin.create({
}); });
}, },
@action
cancel() { cancel() {
this.rollbackBuffer(); this.rollbackBuffer();
}, },
@action
resetDefault() { resetDefault() {
this.set("buffered.value", this.get("setting.default")); this.set("buffered.value", this.get("setting.default"));
}, },
@action
toggleSecret() { toggleSecret() {
this.toggleProperty("isSecret"); this.toggleProperty("isSecret");
}, },
@action
setDefaultValues() { setDefaultValues() {
this.set( this.set(
"buffered.value", "buffered.value",
@@ -261,5 +230,29 @@ export default Mixin.create({
); );
return false; return false;
}, },
@bind
_handleKeydown(event) {
if (
event.key === "Enter" &&
event.target.classList.contains("input-setting-string")
) {
this.save();
}
},
_watchEnterKey: on("didInsertElement", function () {
this.element.addEventListener("keydown", this._handleKeydown);
}),
_removeBindings: on("willDestroyElement", function () {
this.element.removeEventListener("keydown", this._handleKeydown);
}),
_save() {
warn("You should define a `_save` method", {
id: "discourse.setting-component.missing-save",
});
return Promise.resolve();
}, },
}); });

View File

@@ -7,6 +7,14 @@ import toMarkdown from "discourse/lib/to-markdown";
let _defaultHomepage; let _defaultHomepage;
export function splitString(str, separator = ",") {
if (typeof str === "string") {
return str.split(separator).filter(Boolean);
} else {
return [];
}
}
export function translateSize(size) { export function translateSize(size) {
switch (size) { switch (size) {
case "tiny": case "tiny":