Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

DEV: Add page-aware plugin APIs for saving user preferences#36757

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
ZogStriP merged 2 commits intomainfromdev-add-page-specific-saving-to-plugin-api
Dec 18, 2025
Merged
Show file tree
Hide file tree
Changes from1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 103 additions & 2 deletionsfrontend/discourse/app/lib/plugin-api.gjs
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2081,12 +2081,113 @@ class _PluginApi {
addAdvancedSearchOptions(options);
}

addSaveableUserField(fieldName) {
/**
* Registers a user field that can be saved via the user preferences API.
* User fields are admin-defined profile fields stored in the user_fields table.
*
* @param {string} fieldName - The name of the user field to save
* @param {Object} [options] - Optional configuration
* @param {string} [options.page] - The preferences page where this field should be saved.
* Valid pages: "account", "emails", "interface", "navigation-menu", "notifications",
* "profile", "tags", "tracking", "users"
*
* @example
* // Register a user field that will be saved on the emails preferences page
* api.addSaveableUserField("newsletter_subscribe", { page: "emails" });
*/
addSaveableUserField(fieldName, options = {}) {
addSaveableUserField(fieldName);

if (options.page) {
this.registerValueTransformer(
"preferences-save-attributes",
({ value: attrs, context }) => {
if (context.page === options.page) {
attrs.push(fieldName);
}
return attrs;
}
);
}
}

addSaveableUserOptionField(fieldName) {
/**
* Registers a user option that can be saved via the user preferences API.
* User options are preference settings stored in the user_options table.
*
* @param {string} fieldName - The name of the user option to save
* @param {Object} [options] - Optional configuration
* @param {string} [options.page] - The preferences page where this option should be saved.
* Valid pages: "account", "emails", "interface", "navigation-menu", "notifications",
* "profile", "tags", "tracking", "users"
*
* @example
* // Register a user option that will be saved on the emails preferences page
* api.addSaveableUserOption("chat_email_frequency", { page: "emails" });
*
* @example
* // Register a user option without specifying a page (for use with custom preference pages)
* api.addSaveableUserOption("my_custom_setting");
*/
addSaveableUserOption(fieldName, options = {}) {
addSaveableUserOptionField(fieldName);

if (options.page) {
this.registerValueTransformer(
"preferences-save-attributes",
({ value: attrs, context }) => {
if (context.page === options.page) {
attrs.push(fieldName);
}
return attrs;
}
);
}
}

/**
* @deprecated Use `addSaveableUserOption` instead
*/
addSaveableUserOptionField(fieldName, options = {}) {
this.addSaveableUserOption(fieldName, options);
}

/**
* Ensures custom_fields are saved on a specific preferences page.
* Custom fields are stored in the user_custom_fields table.
*
* Unlike `addSaveableUserOption` and `addSaveableUserField` which track
* individual field names, this method ensures the entire `custom_fields`
* object is included in the save payload. Multiple plugins can safely
* call this for the same page - `custom_fields` will only be added once.
*
* @param {Object} options - Configuration options
* @param {string} options.page - The preferences page where custom_fields should be saved.
* Valid pages: "account", "emails", "interface", "navigation-menu", "notifications",
* "profile", "tags", "tracking", "users"
*
* @example
* // Ensure custom_fields are saved on the notifications preferences page
* api.addSaveableCustomFields({ page: "notifications" });
*/
addSaveableCustomFields(options = {}) {
if (!options.page) {
// eslint-disable-next-line no-console
console.warn(
"addSaveableCustomFields requires a `page` option to specify which preferences page should save custom_fields"
);
return;
}

this.registerValueTransformer(
"preferences-save-attributes",
({ value: attrs, context }) => {
if (context.page === options.page && !attrs.includes("custom_fields")) {
attrs.push("custom_fields");
}
return attrs;
}
);
}

/**
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,26 @@
import{withPluginApi}from"discourse/lib/plugin-api";

constCHAT_ENABLED_FIELD="chat_enabled";
constONLY_CHAT_PUSH_NOTIFICATIONS_FIELD="only_chat_push_notifications";
constIGNORE_CHANNEL_WIDE_MENTION="ignore_channel_wide_mention";
constSHOW_THREAD_TITLE_PROMPTS="show_thread_title_prompts";
constCHAT_SOUND="chat_sound";
constCHAT_EMAIL_FREQUENCY="chat_email_frequency";
constCHAT_HEADER_INDICATOR_PREFERENCE="chat_header_indicator_preference";
constCHAT_SEPARATE_SIDEBAR_MODE="chat_separate_sidebar_mode";
constCHAT_SEND_SHORTCUT="chat_send_shortcut";
constCHAT_QUICK_REACTION_TYPE="chat_quick_reaction_type";
constCHAT_QUICK_REACTIONS_CUSTOM="chat_quick_reactions_custom";

exportdefault{
name:"chat-user-options",

initialize(container){
withPluginApi((api)=>{
constsiteSettings=container.lookup("service:site-settings");
if(siteSettings.chat_enabled){
api.addSaveableUserOptionField(CHAT_ENABLED_FIELD);
api.addSaveableUserOptionField(ONLY_CHAT_PUSH_NOTIFICATIONS_FIELD);
api.addSaveableUserOptionField(IGNORE_CHANNEL_WIDE_MENTION);
api.addSaveableUserOptionField(SHOW_THREAD_TITLE_PROMPTS);
api.addSaveableUserOptionField(CHAT_SOUND);
api.addSaveableUserOptionField(CHAT_EMAIL_FREQUENCY);
api.addSaveableUserOptionField(CHAT_HEADER_INDICATOR_PREFERENCE);
api.addSaveableUserOptionField(CHAT_SEPARATE_SIDEBAR_MODE);
api.addSaveableUserOptionField(CHAT_SEND_SHORTCUT);
api.addSaveableUserOptionField(CHAT_QUICK_REACTION_TYPE);
api.addSaveableUserOptionField(CHAT_QUICK_REACTIONS_CUSTOM);
const{ chat_enabled}=container.lookup("service:site-settings");

if(chat_enabled){
// Chat settings
api.addSaveableUserOption("chat_enabled");
api.addSaveableUserOption("chat_header_indicator_preference");
api.addSaveableUserOption("chat_quick_reaction_type");
api.addSaveableUserOption("chat_quick_reactions_custom");
api.addSaveableUserOption("chat_send_shortcut");
api.addSaveableUserOption("chat_separate_sidebar_mode");
api.addSaveableUserOption("chat_sound");
api.addSaveableUserOption("ignore_channel_wide_mention");
api.addSaveableUserOption("only_chat_push_notifications");
api.addSaveableUserOption("show_thread_title_prompts");
// Email settings
api.addSaveableUserOption("chat_email_frequency",{page:"emails"});
}
});
},
Expand Down
View file
Open in desktop

This file was deleted.

View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
import { click, visit } from "@ember/test-helpers";
import { test } from "qunit";
import {
acceptance,
updateCurrentUser,
} from "discourse/tests/helpers/qunit-helpers";
import selectKit from "discourse/tests/helpers/select-kit-helper";

acceptance("Chat | Email Preferences", function (needs) {
needs.user();
needs.settings({
chat_enabled: true,
});

let savedData;
needs.pretender((server, helper) => {
server.put("/u/eviltrout.json", (request) => {
savedData = helper.parsePostData(request.requestBody);
return helper.response({ user: {} });
});
});

test("saves chat_email_frequency when saving email preferences", async function (assert) {
updateCurrentUser({
user_option: {
chat_email_frequency: "when_away",
},
});

await visit("/u/eviltrout/preferences/emails");

const dropdown = selectKit("#user_chat_email_frequency");
await dropdown.expand();
await dropdown.selectRowByValue("never");

await click(".save-changes");

assert.strictEqual(
savedData.chat_email_frequency,
"never",
"chat_email_frequency is included in saved data"
);
});
});
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
import { apiInitializer } from "discourse/lib/api";

const FIELD_NAME = "ai_search_discoveries";

export default apiInitializer((api) => {
const currentUser = api.getCurrentUser();
const settings = api.container.lookup("service:site-settings");
Expand All@@ -13,17 +11,7 @@ export default apiInitializer((api) => {
return;
}

api.addSaveableUserOptionField(FIELD_NAME);

api.registerValueTransformer(
"preferences-save-attributes",
({ value: attrs, context }) => {
if (context.page === "interface") {
attrs.push(FIELD_NAME);
}
return attrs;
}
);
api.addSaveableUserOption("ai_search_discoveries", { page: "interface" });

const discobotDiscoveries = api.container.lookup(
"service:discobot-discoveries"
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,13 +7,6 @@ import { i18n } from "discourse-i18n";
exportdefaultclassNotificationLevelWhenAssignedextendsComponent {
@service siteSettings;

constructor(owner,args) {
super(...arguments);
if (this.siteSettings.assign_enabled) {
args.outletArgs.customAttrNames.push("notification_level_when_assigned");
}
}

getnotificationLevelsWhenAssigned() {
// The order matches the "notification level when replying" user preference
return [
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
import { action } from "@ember/object";
import { getOwner } from "@ember/owner";
import { htmlSafe } from "@ember/template";
import { renderAvatar } from "discourse/helpers/user-avatar";
Expand DownExpand Up@@ -528,17 +527,7 @@ function initialize(api) {
"group-plus"
);

api.modifyClass(
"controller:preferences/notifications",
(Superclass) =>
class extends Superclass {
@action
save() {
this.saveAttrNames.push("custom_fields");
super.save(...arguments);
}
}
);
api.addSaveableCustomFields({ page: "notifications" });

api.addKeyboardShortcut("g a", "", { path: "/my/activity/assigned" });
}
Expand DownExpand Up@@ -706,7 +695,9 @@ export default {

api.addUserSearchOption("assignableGroups");

api.addSaveableUserOptionField("notification_level_when_assigned");
api.addSaveableUserOption("notification_level_when_assigned", {
page: "tracking",
});

api.addBulkActionButton({
id: "assign-topics",
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,17 @@
import EmailsController from "discourse/controllers/preferences/emails";
import { withPluginApi } from "discourse/lib/plugin-api";

const SEND_EMAIL_NOTIFICATIONS_FIELD = "policy_email_frequency";

export default {
name: "policy-user-options",

initialize(container) {
withPluginApi((api) => {
const siteSettings = container.lookup("service:site-settings");
if (siteSettings.policy_enabled) {
api.addSaveableUserOptionField(SEND_EMAIL_NOTIFICATIONS_FIELD);
}
});
const { policy_enabled } = container.lookup("service:site-settings");

EmailsController.reopen({
init() {
this._super(...arguments);
this.saveAttrNames.push(SEND_EMAIL_NOTIFICATIONS_FIELD);
},
if (policy_enabled){
api.addSaveableUserOption("policy_email_frequency", {
page: "emails",
});
}
});
},
};
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,6 +3,10 @@ import { test } from "qunit";
import { cloneJSON } from "discourse/lib/object";
import postFixtures from "discourse/tests/fixtures/post";
import topicFixtures from "discourse/tests/fixtures/topic";
import pretender, {
parsePostData,
response,
} from "discourse/tests/helpers/create-pretender";
import {
acceptance,
updateCurrentUser,
Expand DownExpand Up@@ -63,8 +67,26 @@ acceptance("Discourse Policy - post", function (needs) {
});

test("edit email preferences", async function (assert) {
let savedData;
pretender.put("/u/eviltrout.json", (request) => {
savedData = parsePostData(request.requestBody);
return response({ user: {} });
});

await visit(`/u/eviltrout/preferences/emails`);
assert.dom("#user_policy_email_frequency").exists();

const dropdown = selectKit("#user_policy_email_frequency");
await dropdown.expand();
await dropdown.selectRowByValue("never");

await click(".save-changes");

assert.strictEqual(
savedData.policy_email_frequency,
"never",
"policy_email_frequency is included in saved data"
);
});

test("edit policy - staff", async function (assert) {
Expand Down
Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp