DEV: Clean up settings component (#20485)

Async, modern syntax, no `on()` component hooks, const extraction, sorted props, template tweaks, and a small filtering bugfix (filtering could throw errors after saving a category-selection setting)
This commit is contained in:
Jarek Radosz 2023-03-01 10:12:39 +01:00 committed by GitHub
parent 3dbaaf1268
commit 007cce62e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 112 additions and 108 deletions

View File

@ -1,7 +1,8 @@
<div class="setting-label"> <div class="setting-label">
<h3> <h3>
{{this.settingName}}
{{#if this.staffLogFilter}} {{#if this.staffLogFilter}}
{{this.settingName}}
<LinkTo <LinkTo
@route="adminLogs.staffActionLogs" @route="adminLogs.staffActionLogs"
@query={{hash filters=this.staffLogFilter force_refresh=true}} @query={{hash filters=this.staffLogFilter force_refresh=true}}
@ -11,17 +12,18 @@
{{d-icon "history"}} {{d-icon "history"}}
</span> </span>
</LinkTo> </LinkTo>
{{else}}
{{this.settingName}}
{{/if}} {{/if}}
</h3> </h3>
{{#if this.defaultIsAvailable}} {{#if this.defaultIsAvailable}}
<a <DButton
href class="btn-link"
onClick={{action "setDefaultValues"}} @action={{this.setDefaultValues}}
>{{this.setting.setDefaultValuesLabel}}</a> @translatedLabel={{this.setting.setDefaultValuesLabel}}
/>
{{/if}} {{/if}}
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{component {{component
this.componentName this.componentName
@ -33,18 +35,20 @@
allowAny=this.allowAny allowAny=this.allowAny
}} }}
</div> </div>
{{#if this.dirty}} {{#if this.dirty}}
<div class="setting-controls"> <div class="setting-controls">
<DButton @class="ok" @action={{action "update"}} @icon="check" /> <DButton class="ok" @action={{this.update}} @icon="check" />
<DButton @class="cancel" @action={{action "cancel"}} @icon="times" /> <DButton class="cancel" @action={{this.cancel}} @icon="times" />
</div> </div>
{{else if this.setting.overridden}} {{else if this.setting.overridden}}
{{#if this.setting.secret}} {{#if this.setting.secret}}
<DButton @action={{action "toggleSecret"}} @icon="far-eye-slash" /> <DButton @action={{this.toggleSecret}} @icon="far-eye-slash" />
{{/if}} {{/if}}
<DButton <DButton
@class="btn-default undo" class="btn-default undo"
@action={{action "resetDefault"}} @action={{this.resetDefault}}
@icon="undo" @icon="undo"
@label="admin.settings.reset" @label="admin.settings.reset"
/> />

View File

@ -14,7 +14,7 @@ export default Controller.extend({
filterContentNow(category) { filterContentNow(category) {
// If we have no content, don't bother filtering anything // If we have no content, don't bother filtering anything
if (!!isEmpty(this.allSiteSettings)) { if (isEmpty(this.allSiteSettings)) {
return; return;
} }
@ -73,7 +73,7 @@ export default Controller.extend({
setting.includes(filter) || setting.includes(filter) ||
setting.replace(/_/g, " ").includes(filter) || setting.replace(/_/g, " ").includes(filter) ||
item.get("description").toLowerCase().includes(filter) || item.get("description").toLowerCase().includes(filter) ||
(item.get("value") || "").toLowerCase().includes(filter) (item.get("value") || "").toString().toLowerCase().includes(filter)
); );
} else { } else {
return true; return true;

View File

@ -3,12 +3,10 @@ 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 { 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, { bind } 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 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 { action } from "@ember/object";
@ -37,13 +35,61 @@ const CUSTOM_TYPES = [
const AUTO_REFRESH_ON_SAVE = ["logo", "logo_small", "large_icon"]; const AUTO_REFRESH_ON_SAVE = ["logo", "logo_small", "large_icon"];
const DEFAULT_USER_PREFERENCES = [
"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_hide_profile_and_presence",
"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_normal",
"default_tags_watching",
"default_tags_tracking",
"default_tags_muted",
"default_tags_watching_first_post",
"default_text_size",
"default_title_count_mode",
"default_sidebar_categories",
"default_sidebar_tags",
];
export default Mixin.create({ export default Mixin.create({
classNameBindings: [":row", ":setting", "overridden", "typeClass"],
content: alias("setting"),
validationMessage: null,
isSecret: oneWay("setting.secret"),
setting: null,
attributeBindings: ["setting.setting:data-setting"], attributeBindings: ["setting.setting:data-setting"],
classNameBindings: [":row", ":setting", "overridden", "typeClass"],
validationMessage: null,
setting: null,
content: alias("setting"),
isSecret: oneWay("setting.secret"),
componentName: fmt("typeClass", "site-settings/%@"),
overridden: propertyNotEqual("setting.default", "buffered.value"),
didInsertElement() {
this._super(...arguments);
this.element.addEventListener("keydown", this._handleKeydown);
},
willDestroyElement() {
this._super(...arguments);
this.element.removeEventListener("keydown", this._handleKeydown);
},
@discourseComputed("buffered.value", "setting.value") @discourseComputed("buffered.value", "setting.value")
dirty(bufferVal, settingVal) { dirty(bufferVal, settingVal) {
@ -99,15 +145,11 @@ export default Mixin.create({
return setting.type; return setting.type;
}, },
componentName: fmt("typeClass", "site-settings/%@"),
@discourseComputed("setting.anyValue") @discourseComputed("setting.anyValue")
allowAny(anyValue) { allowAny(anyValue) {
return anyValue !== false; return anyValue !== false;
}, },
overridden: propertyNotEqual("setting.default", "buffered.value"),
@discourseComputed("buffered.value") @discourseComputed("buffered.value")
bufferedValues(value) { bufferedValues(value) {
return splitString(value, "|"); return splitString(value, "|");
@ -127,90 +169,57 @@ export default Mixin.create({
}, },
@action @action
update() { async 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_hide_profile_and_presence",
"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_normal",
"default_tags_watching",
"default_tags_tracking",
"default_tags_muted",
"default_tags_watching_first_post",
"default_text_size",
"default_title_count_mode",
"default_sidebar_categories",
"default_sidebar_tags",
];
const key = this.buffered.get("setting"); const key = this.buffered.get("setting");
if (defaultUserPreferences.includes(key)) { if (!DEFAULT_USER_PREFERENCES.includes(key)) {
const data = {}; await this.save();
data[key] = this.buffered.get("value"); return;
}
ajax(`/admin/site_settings/${key}/user_count.json`, { const data = {
type: "PUT", [key]: this.buffered.get("value"),
data, };
}).then((result) => {
const count = result.user_count;
if (count > 0) { const result = await ajax(`/admin/site_settings/${key}/user_count.json`, {
const controller = showModal("site-setting-default-categories", { type: "PUT",
model: { count, key: key.replaceAll("_", " ") }, data,
admin: true, });
});
controller.set("onClose", () => { const count = result.user_count;
this.updateExistingUsers = controller.updateExistingUsers;
this.save(); if (count > 0) {
}); const controller = showModal("site-setting-default-categories", {
} else { model: { count, key: key.replaceAll("_", " ") },
this.save(); admin: true,
} });
controller.set("onClose", () => {
this.updateExistingUsers = controller.updateExistingUsers;
this.save();
}); });
} else { } else {
this.save(); await this.save();
} }
}, },
@action @action
save() { async save() {
this._save() try {
.then(() => { await this._save();
this.set("validationMessage", null);
this.commitBuffer(); this.set("validationMessage", null);
if (AUTO_REFRESH_ON_SAVE.includes(this.setting.setting)) { this.commitBuffer();
this.afterSave(); if (AUTO_REFRESH_ON_SAVE.includes(this.setting.setting)) {
} this.afterSave();
}) }
.catch((e) => { } catch (e) {
if (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"));
} }
}); }
}, },
@action @action
@ -247,18 +256,9 @@ export default Mixin.create({
} }
}, },
_watchEnterKey: on("didInsertElement", function () { async _save() {
this.element.addEventListener("keydown", this._handleKeydown);
}),
_removeBindings: on("willDestroyElement", function () {
this.element.removeEventListener("keydown", this._handleKeydown);
}),
_save() {
warn("You should define a `_save` method", { warn("You should define a `_save` method", {
id: "discourse.setting-component.missing-save", id: "discourse.setting-component.missing-save",
}); });
return Promise.resolve();
}, },
}); });