diff --git a/app/assets/javascripts/admin/addon/mixins/setting-component.js b/app/assets/javascripts/admin/addon/mixins/setting-component.js
index b55c0455931..9585168210e 100644
--- a/app/assets/javascripts/admin/addon/mixins/setting-component.js
+++ b/app/assets/javascripts/admin/addon/mixins/setting-component.js
@@ -1,14 +1,18 @@
+import { isNone } from "@ember/utils";
+import { fmt, propertyNotEqual } from "discourse/lib/computed";
import { alias, oneWay } from "@ember/object/computed";
import I18n from "I18n";
import Mixin from "@ember/object/mixin";
import { Promise } from "rsvp";
import { ajax } from "discourse/lib/ajax";
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 { on } from "@ember/object/evented";
import showModal from "discourse/lib/show-modal";
import { warn } from "@ember/debug";
+import { action } from "@ember/object";
+import { splitString } from "discourse/lib/utilities";
const CUSTOM_TYPES = [
"bool",
@@ -32,26 +36,20 @@ const CUSTOM_TYPES = [
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({
classNameBindings: [":row", ":setting", "overridden", "typeClass"],
content: alias("setting"),
validationMessage: null,
isSecret: oneWay("setting.secret"),
+ setting: null,
@discourseComputed("buffered.value", "setting.value")
dirty(bufferVal, settingVal) {
- if (bufferVal === null || bufferVal === undefined) {
+ if (isNone(bufferVal)) {
bufferVal = "";
}
- if (settingVal === null || settingVal === undefined) {
+
+ if (isNone(settingVal)) {
settingVal = "";
}
@@ -61,21 +59,17 @@ export default Mixin.create({
@discourseComputed("setting", "buffered.value")
preview(setting, value) {
// A bit hacky, but allows us to use helpers
- if (setting.get("setting") === "category_style") {
- let category = this.site.get("categories.firstObject");
+ if (setting.setting === "category_style") {
+ const category = this.site.get("categories.firstObject");
if (category) {
- return categoryLinkHTML(category, {
- categoryStyle: value,
- });
+ return categoryLinkHTML(category, { categoryStyle: value });
}
}
- let preview = setting.get("preview");
+
+ const preview = setting.preview;
if (preview) {
- return htmlSafe(
- "
" +
- preview.replace(/\{\{value\}\}/g, value) +
- "
"
- );
+ const escapedValue = preview.replace(/\{\{value\}\}/g, value);
+ return htmlSafe(`${escapedValue}
`);
}
},
@@ -103,51 +97,156 @@ export default Mixin.create({
return setting.type;
},
- @discourseComputed("typeClass")
- componentName(typeClass) {
- return "site-settings/" + typeClass;
- },
+ componentName: fmt("typeClass", "site-settings/%@"),
@discourseComputed("setting.anyValue")
allowAny(anyValue) {
return anyValue !== false;
},
- @discourseComputed("setting.default", "buffered.value")
- overridden(settingDefault, bufferedValue) {
- return settingDefault !== bufferedValue;
- },
+ overridden: propertyNotEqual("setting.default", "buffered.value"),
@discourseComputed("buffered.value")
- bufferedValues: splitPipes,
+ bufferedValues(value) {
+ return splitString(value, "|");
+ },
@discourseComputed("setting.defaultValues")
- defaultValues: splitPipes,
+ defaultValues(value) {
+ return splitString(value, "|");
+ },
@discourseComputed("defaultValues", "bufferedValues")
defaultIsAvailable(defaultValues, bufferedValues) {
return (
- defaultValues &&
defaultValues.length > 0 &&
!defaultValues.every((value) => bufferedValues.includes(value))
);
},
- _watchEnterKey: on("didInsertElement", function () {
- $(this.element).on(
- "keydown.setting-enter",
- ".input-setting-string",
- (e) => {
- if (e.key === "Enter") {
- // enter key
- this.send("save");
+ @action
+ update() {
+ const defaultUserPreferences = [
+ "default_email_digest_frequency",
+ "default_include_tl0_in_digests",
+ "default_email_level",
+ "default_email_messages_level",
+ "default_email_mailing_list_mode",
+ "default_email_mailing_list_mode_frequency",
+ "default_email_previous_replies",
+ "default_email_in_reply_to",
+ "default_other_new_topic_duration_minutes",
+ "default_other_auto_track_topics_after_msecs",
+ "default_other_notification_level_when_replying",
+ "default_other_external_links_in_new_tab",
+ "default_other_enable_quoting",
+ "default_other_enable_defer",
+ "default_other_dynamic_favicon",
+ "default_other_like_notification_frequency",
+ "default_other_skip_new_user_tips",
+ "default_topics_automatic_unpin",
+ "default_categories_watching",
+ "default_categories_tracking",
+ "default_categories_muted",
+ "default_categories_watching_first_post",
+ "default_categories_regular",
+ "default_tags_watching",
+ "default_tags_tracking",
+ "default_tags_muted",
+ "default_tags_watching_first_post",
+ "default_text_size",
+ "default_title_count_mode",
+ ];
+ const key = this.buffered.get("setting");
+
+ if (defaultUserPreferences.includes(key)) {
+ const data = {};
+ data[key] = this.buffered.get("value");
+
+ ajax(`/admin/site_settings/${key}/user_count.json`, {
+ type: "PUT",
+ data,
+ }).then((result) => {
+ const count = result.user_count;
+
+ if (count > 0) {
+ const controller = showModal("site-setting-default-categories", {
+ model: { count, key: key.replaceAll("_", " ") },
+ admin: true,
+ });
+
+ controller.set("onClose", () => {
+ this.updateExistingUsers = controller.updateExistingUsers;
+ this.save();
+ });
+ } else {
+ this.save();
}
- }
+ });
+ } else {
+ this.save();
+ }
+ },
+
+ @action
+ save() {
+ this._save()
+ .then(() => {
+ this.set("validationMessage", null);
+ this.commitBuffer();
+ if (AUTO_REFRESH_ON_SAVE.includes(this.setting.setting)) {
+ this.afterSave();
+ }
+ })
+ .catch((e) => {
+ if (e.jqXHR?.responseJSON?.errors) {
+ this.set("validationMessage", e.jqXHR.responseJSON.errors[0]);
+ } else {
+ this.set("validationMessage", I18n.t("generic_error"));
+ }
+ });
+ },
+
+ @action
+ cancel() {
+ this.rollbackBuffer();
+ },
+
+ @action
+ resetDefault() {
+ this.set("buffered.value", this.get("setting.default"));
+ },
+
+ @action
+ toggleSecret() {
+ this.toggleProperty("isSecret");
+ },
+
+ @action
+ setDefaultValues() {
+ this.set(
+ "buffered.value",
+ this.bufferedValues.concat(this.defaultValues).uniq().join("|")
);
+ 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).off("keydown.setting-enter");
+ this.element.removeEventListener("keydown", this._handleKeydown);
}),
_save() {
@@ -156,110 +255,4 @@ export default Mixin.create({
});
return Promise.resolve();
},
-
- actions: {
- update() {
- const defaultUserPreferences = [
- "default_email_digest_frequency",
- "default_include_tl0_in_digests",
- "default_email_level",
- "default_email_messages_level",
- "default_email_mailing_list_mode",
- "default_email_mailing_list_mode_frequency",
- "default_email_previous_replies",
- "default_email_in_reply_to",
- "default_other_new_topic_duration_minutes",
- "default_other_auto_track_topics_after_msecs",
- "default_other_notification_level_when_replying",
- "default_other_external_links_in_new_tab",
- "default_other_enable_quoting",
- "default_other_enable_defer",
- "default_other_dynamic_favicon",
- "default_other_like_notification_frequency",
- "default_other_skip_new_user_tips",
- "default_topics_automatic_unpin",
- "default_categories_watching",
- "default_categories_tracking",
- "default_categories_muted",
- "default_categories_watching_first_post",
- "default_categories_regular",
- "default_tags_watching",
- "default_tags_tracking",
- "default_tags_muted",
- "default_tags_watching_first_post",
- "default_text_size",
- "default_title_count_mode",
- ];
- const key = this.buffered.get("setting");
-
- if (defaultUserPreferences.includes(key)) {
- const data = {};
- data[key] = this.buffered.get("value");
-
- ajax(`/admin/site_settings/${key}/user_count.json`, {
- type: "PUT",
- data,
- }).then((result) => {
- const count = result.user_count;
-
- if (count > 0) {
- const controller = showModal("site-setting-default-categories", {
- model: {
- count: result.user_count,
- key: key.replace(/_/g, " "),
- },
- admin: true,
- });
-
- controller.set("onClose", () => {
- this.updateExistingUsers = controller.updateExistingUsers;
- this.send("save");
- });
- } else {
- this.send("save");
- }
- });
- } else {
- this.send("save");
- }
- },
-
- save() {
- this._save()
- .then(() => {
- this.set("validationMessage", null);
- this.commitBuffer();
- if (AUTO_REFRESH_ON_SAVE.includes(this.setting.setting)) {
- this.afterSave();
- }
- })
- .catch((e) => {
- if (e.jqXHR.responseJSON && e.jqXHR.responseJSON.errors) {
- this.set("validationMessage", e.jqXHR.responseJSON.errors[0]);
- } else {
- this.set("validationMessage", I18n.t("generic_error"));
- }
- });
- },
-
- cancel() {
- this.rollbackBuffer();
- },
-
- resetDefault() {
- this.set("buffered.value", this.get("setting.default"));
- },
-
- toggleSecret() {
- this.toggleProperty("isSecret");
- },
-
- setDefaultValues() {
- this.set(
- "buffered.value",
- this.bufferedValues.concat(this.defaultValues).uniq().join("|")
- );
- return false;
- },
- },
});
diff --git a/app/assets/javascripts/discourse/app/lib/utilities.js b/app/assets/javascripts/discourse/app/lib/utilities.js
index e9cdaaf3f02..178fa1e6e25 100644
--- a/app/assets/javascripts/discourse/app/lib/utilities.js
+++ b/app/assets/javascripts/discourse/app/lib/utilities.js
@@ -7,6 +7,14 @@ import toMarkdown from "discourse/lib/to-markdown";
let _defaultHomepage;
+export function splitString(str, separator = ",") {
+ if (typeof str === "string") {
+ return str.split(separator).filter(Boolean);
+ } else {
+ return [];
+ }
+}
+
export function translateSize(size) {
switch (size) {
case "tiny":