Skip to content

Commit ee1a1c7

Browse files
committed
DEV: Add preferences-save-attributes value transformer
Previously, plugins needed to use `modifyClass` to extend the `saveAttrNames` list in preference controllers. This approach is not ideal as it overrides controller methods and can be fragile. This commit introduces a `preferences-save-attributes` value transformer that provides a supported way for plugins to add custom fields to any preference page's save list. The transformer passes a `page` context parameter so plugins can target specific preference pages: ```javascript api.registerValueTransformer( "preferences-save-attributes", ({ value: attrs, context }) => { if (context.page === "interface") { attrs.push("my_custom_field"); } return attrs; } ); Available pages: account, emails, interface, navigation-menu, notifications, profile, tags, tracking, users.
1 parent 96d7e6b commit ee1a1c7

File tree

12 files changed

+171
-88
lines changed

12 files changed

+171
-88
lines changed

frontend/discourse/app/controllers/preferences/account.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { propertyNotEqual, setting } from "discourse/lib/computed";
1111
import discourseComputed from "discourse/lib/decorators";
1212
import { exportUserArchive } from "discourse/lib/export-csv";
1313
import getURL from "discourse/lib/get-url";
14+
import { applyValueTransformer } from "discourse/lib/transformer";
1415
import DiscourseURL from "discourse/lib/url";
1516
import { findAll } from "discourse/models/login-method";
1617
import { i18n } from "discourse-i18n";
@@ -40,17 +41,17 @@ export default class AccountController extends Controller {
4041

4142
init() {
4243
super.init(...arguments);
43-
44-
this.saveAttrNames = [
45-
"name",
46-
"title",
47-
"primary_group_id",
48-
"flair_group_id",
49-
"status",
50-
];
5144
this.set("revoking", {});
5245
}
5346

47+
get saveAttrNames() {
48+
return applyValueTransformer(
49+
"preferences-save-attributes",
50+
["name", "title", "primary_group_id", "flair_group_id", "status"],
51+
{ page: "account" }
52+
);
53+
}
54+
5455
reset() {
5556
this.set("passwordProgress", null);
5657
}

frontend/discourse/app/controllers/preferences/emails.js

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { action } from "@ember/object";
33
import { equal } from "@ember/object/computed";
44
import { popupAjaxError } from "discourse/lib/ajax-error";
55
import discourseComputed from "discourse/lib/decorators";
6+
import { applyValueTransformer } from "discourse/lib/transformer";
67
import { i18n } from "discourse-i18n";
78

89
const EMAIL_LEVELS = {
@@ -20,18 +21,6 @@ export default class EmailsController extends Controller {
2021
@equal("model.user_option.email_level", EMAIL_LEVELS.ONLY_WHEN_AWAY)
2122
emailLevelAway;
2223

23-
saveAttrNames = [
24-
"email_level",
25-
"email_messages_level",
26-
"mailing_list_mode",
27-
"mailing_list_mode_frequency",
28-
"email_digests",
29-
"email_in_reply_to",
30-
"email_previous_replies",
31-
"digest_after_minutes",
32-
"include_tl0_in_digests",
33-
];
34-
3524
previousRepliesOptions = [
3625
{ name: i18n("user.email_previous_replies.always"), value: 0 },
3726
{ name: i18n("user.email_previous_replies.unless_emailed"), value: 1 },
@@ -56,6 +45,24 @@ export default class EmailsController extends Controller {
5645
{ name: i18n("user.email_digests.every_six_months"), value: 259200 },
5746
];
5847

48+
get saveAttrNames() {
49+
return applyValueTransformer(
50+
"preferences-save-attributes",
51+
[
52+
"email_level",
53+
"email_messages_level",
54+
"mailing_list_mode",
55+
"mailing_list_mode_frequency",
56+
"email_digests",
57+
"email_in_reply_to",
58+
"email_previous_replies",
59+
"digest_after_minutes",
60+
"include_tl0_in_digests",
61+
],
62+
{ page: "emails" }
63+
);
64+
}
65+
5966
@discourseComputed()
6067
frequencyEstimate() {
6168
let estimate = this.get("model.mailing_list_posts_per_day");

frontend/discourse/app/controllers/preferences/interface.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
listThemes,
1818
setLocalTheme,
1919
} from "discourse/lib/theme-selector";
20+
import { applyValueTransformer } from "discourse/lib/transformer";
2021
import { setDefaultHomepage } from "discourse/lib/utilities";
2122
import { AUTO_DELETE_PREFERENCES } from "discourse/models/bookmark";
2223
import { i18n } from "discourse-i18n";
@@ -86,7 +87,9 @@ export default class InterfaceController extends Controller {
8687
attrs.push("theme_ids");
8788
}
8889

89-
return attrs;
90+
return applyValueTransformer("preferences-save-attributes", attrs, {
91+
page: "interface",
92+
});
9093
}
9194

9295
@discourseComputed()

frontend/discourse/app/controllers/preferences/navigation-menu.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,21 @@ import { tracked } from "@glimmer/tracking";
22
import Controller from "@ember/controller";
33
import { action } from "@ember/object";
44
import { popupAjaxError } from "discourse/lib/ajax-error";
5+
import { applyValueTransformer } from "discourse/lib/transformer";
56
import { i18n } from "discourse-i18n";
67

78
export default class extends Controller {
89
@tracked saved = false;
910

1011
subpageTitle = i18n("user.preferences_nav.navigation_menu");
1112

12-
saveAttrNames = [
13-
"sidebar_link_to_filtered_list",
14-
"sidebar_show_count_of_new_items",
15-
];
13+
get saveAttrNames() {
14+
return applyValueTransformer(
15+
"preferences-save-attributes",
16+
["sidebar_link_to_filtered_list", "sidebar_show_count_of_new_items"],
17+
{ page: "navigation-menu" }
18+
);
19+
}
1620

1721
@action
1822
save() {

frontend/discourse/app/controllers/preferences/notifications.js

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,38 @@
11
import Controller from "@ember/controller";
22
import { action } from "@ember/object";
33
import { popupAjaxError } from "discourse/lib/ajax-error";
4+
import { applyValueTransformer } from "discourse/lib/transformer";
45
import { i18n } from "discourse-i18n";
56

67
export default class NotificationsController extends Controller {
78
subpageTitle = i18n("user.preferences_nav.notifications");
89

9-
init() {
10-
super.init(...arguments);
10+
likeNotificationFrequencies = [
11+
{ name: i18n("user.like_notification_frequency.always"), value: 0 },
12+
{
13+
name: i18n("user.like_notification_frequency.first_time_and_daily"),
14+
value: 1,
15+
},
16+
{ name: i18n("user.like_notification_frequency.first_time"), value: 2 },
17+
{ name: i18n("user.like_notification_frequency.never"), value: 3 },
18+
];
1119

12-
this.saveAttrNames = [
13-
"allow_private_messages",
14-
"auto_track_topics_after_msecs",
15-
"enable_allowed_pm_users",
16-
"like_notification_frequency",
17-
"muted_usernames",
18-
"new_topic_duration_minutes",
19-
"notification_level_when_replying",
20-
"notify_on_linked_posts",
21-
"user_notification_schedule",
22-
];
23-
24-
this.likeNotificationFrequencies = [
25-
{ name: i18n("user.like_notification_frequency.always"), value: 0 },
26-
{
27-
name: i18n("user.like_notification_frequency.first_time_and_daily"),
28-
value: 1,
29-
},
30-
{ name: i18n("user.like_notification_frequency.first_time"), value: 2 },
31-
{ name: i18n("user.like_notification_frequency.never"), value: 3 },
32-
];
20+
get saveAttrNames() {
21+
return applyValueTransformer(
22+
"preferences-save-attributes",
23+
[
24+
"allow_private_messages",
25+
"auto_track_topics_after_msecs",
26+
"enable_allowed_pm_users",
27+
"like_notification_frequency",
28+
"muted_usernames",
29+
"new_topic_duration_minutes",
30+
"notification_level_when_replying",
31+
"notify_on_linked_posts",
32+
"user_notification_schedule",
33+
],
34+
{ page: "notifications" }
35+
);
3336
}
3437

3538
@action

frontend/discourse/app/controllers/preferences/profile.js

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import FeatureTopicOnProfileModal from "discourse/components/modal/feature-topic
77
import { ajax } from "discourse/lib/ajax";
88
import { popupAjaxError } from "discourse/lib/ajax-error";
99
import discourseComputed from "discourse/lib/decorators";
10+
import { applyValueTransformer } from "discourse/lib/transformer";
1011
import { i18n } from "discourse-i18n";
1112

1213
export default class ProfileController extends Controller {
@@ -22,25 +23,31 @@ export default class ProfileController extends Controller {
2223
@readOnly("model.can_upload_user_card_background")
2324
canUploadUserCardBackground;
2425

25-
saveAttrNames = [
26-
"bio_raw",
27-
"website",
28-
"location",
29-
"custom_fields",
30-
"user_fields",
31-
"profile_background_upload_url",
32-
"card_background_upload_url",
33-
"date_of_birth",
34-
"timezone",
35-
"default_calendar",
36-
"hide_profile",
37-
];
38-
3926
calendarOptions = [
4027
{ name: i18n("download_calendar.google"), value: "google" },
4128
{ name: i18n("download_calendar.ics"), value: "ics" },
4229
];
4330

31+
get saveAttrNames() {
32+
return applyValueTransformer(
33+
"preferences-save-attributes",
34+
[
35+
"bio_raw",
36+
"website",
37+
"location",
38+
"custom_fields",
39+
"user_fields",
40+
"profile_background_upload_url",
41+
"card_background_upload_url",
42+
"date_of_birth",
43+
"timezone",
44+
"default_calendar",
45+
"hide_profile",
46+
],
47+
{ page: "profile" }
48+
);
49+
}
50+
4451
@discourseComputed("[email protected]")
4552
userFields() {
4653
let siteUserFields = this.site.user_fields;

frontend/discourse/app/controllers/preferences/tags.js

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,21 @@ import Controller from "@ember/controller";
22
import { action } from "@ember/object";
33
import { popupAjaxError } from "discourse/lib/ajax-error";
44
import discourseComputed from "discourse/lib/decorators";
5+
import { applyValueTransformer } from "discourse/lib/transformer";
56

67
export default class TagsController extends Controller {
7-
saveAttrNames = [
8-
"muted_tags",
9-
"tracked_tags",
10-
"watched_tags",
11-
"watching_first_post_tags",
12-
];
8+
get saveAttrNames() {
9+
return applyValueTransformer(
10+
"preferences-save-attributes",
11+
[
12+
"muted_tags",
13+
"tracked_tags",
14+
"watched_tags",
15+
"watching_first_post_tags",
16+
],
17+
{ page: "tags" }
18+
);
19+
}
1320

1421
@discourseComputed(
1522
"model.watched_tags.[]",

frontend/discourse/app/controllers/preferences/tracking.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { action, computed } from "@ember/object";
44
import { service } from "@ember/service";
55
import { popupAjaxError } from "discourse/lib/ajax-error";
66
import { NotificationLevels } from "discourse/lib/notification-levels";
7+
import { applyValueTransformer } from "discourse/lib/transformer";
78
import { i18n } from "discourse-i18n";
89

910
export default class extends Controller {
@@ -185,7 +186,9 @@ export default class extends Controller {
185186
attrs.push(...this.customAttrNames);
186187
}
187188

188-
return attrs;
189+
return applyValueTransformer("preferences-save-attributes", attrs, {
190+
page: "tracking",
191+
});
189192
}
190193

191194
@action

frontend/discourse/app/controllers/preferences/users.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { popupAjaxError } from "discourse/lib/ajax-error";
55
import { uniqueItemsFromArray } from "discourse/lib/array-tools";
66
import discourseComputed from "discourse/lib/decorators";
77
import { makeArray } from "discourse/lib/helpers";
8+
import { applyValueTransformer } from "discourse/lib/transformer";
89
import { i18n } from "discourse-i18n";
910

1011
export default class UsersController extends Controller {
@@ -16,15 +17,17 @@ export default class UsersController extends Controller {
1617

1718
subpageTitle = i18n("user.preferences_nav.users");
1819

19-
init() {
20-
super.init(...arguments);
21-
22-
this.saveAttrNames = [
23-
"allow_private_messages",
24-
"muted_usernames",
25-
"allowed_pm_usernames",
26-
"enable_allowed_pm_users",
27-
];
20+
get saveAttrNames() {
21+
return applyValueTransformer(
22+
"preferences-save-attributes",
23+
[
24+
"allow_private_messages",
25+
"muted_usernames",
26+
"allowed_pm_usernames",
27+
"enable_allowed_pm_users",
28+
],
29+
{ page: "users" }
30+
);
2831
}
2932

3033
@computed("model.muted_usernames")

frontend/discourse/app/lib/transformer/registry.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ export const VALUE_TRANSFORMERS = Object.freeze([
7373
"poster-name-class",
7474
"poster-name-icons",
7575
"poster-name-user-title",
76+
"preferences-save-attributes",
7677
"quote-params",
7778
"small-user-attrs",
7879
"tag-separator",

0 commit comments

Comments
 (0)