mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
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:
@@ -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,51 +97,156 @@ 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(
|
update() {
|
||||||
"keydown.setting-enter",
|
const defaultUserPreferences = [
|
||||||
".input-setting-string",
|
"default_email_digest_frequency",
|
||||||
(e) => {
|
"default_include_tl0_in_digests",
|
||||||
if (e.key === "Enter") {
|
"default_email_level",
|
||||||
// enter key
|
"default_email_messages_level",
|
||||||
this.send("save");
|
"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 () {
|
_removeBindings: on("willDestroyElement", function () {
|
||||||
$(this.element).off("keydown.setting-enter");
|
this.element.removeEventListener("keydown", this._handleKeydown);
|
||||||
}),
|
}),
|
||||||
|
|
||||||
_save() {
|
_save() {
|
||||||
@@ -156,110 +255,4 @@ export default Mixin.create({
|
|||||||
});
|
});
|
||||||
return Promise.resolve();
|
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;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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":
|
||||||
|
|||||||
Reference in New Issue
Block a user