FIX: Can't change notification level of categories set to regular (#18801)

This commit fixes a bug on the client site where we would include the
`regular_category_ids` field when trying to update the notification levels of
categories for a user. The `regulary_category_ids` field should only be
included when the `mute_all_categories_by_default` is enabled
This commit is contained in:
Alan Guo Xiang Tan 2022-11-01 07:15:53 +08:00 committed by GitHub
parent d1c5529aad
commit 02304cae83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 116 additions and 20 deletions

View File

@ -4,26 +4,41 @@ import { or } from "@ember/object/computed";
import { popupAjaxError } from "discourse/lib/ajax-error";
export default Controller.extend({
init() {
this._super(...arguments);
this.saveAttrNames = [
"muted_category_ids",
"regular_category_ids",
@discourseComputed("siteSettings.mute_all_categories_by_default")
saveAttrNames(muteAllCategoriesByDefault) {
return [
"watched_category_ids",
"tracked_category_ids",
"watched_first_post_category_ids",
muteAllCategoriesByDefault
? "regular_category_ids"
: "muted_category_ids",
];
},
@discourseComputed(
"siteSettings.mute_all_categories_by_default",
"model.watchedCategories",
"model.watchedFirstPostCategories",
"model.trackedCategories",
"model.mutedCategories"
"model.mutedCategories",
"model.regularCategories"
)
selectedCategories(watched, watchedFirst, tracked, muted) {
return [].concat(watched, watchedFirst, tracked, muted).filter((t) => t);
selectedCategories(
muteAllCategoriesByDefault,
watched,
watchedFirst,
tracked,
muted,
regular
) {
let categories = [].concat(watched, watchedFirst, tracked);
categories = categories.concat(
muteAllCategoriesByDefault ? regular : muted
);
return categories.filter((t) => t);
},
@discourseComputed

View File

@ -398,22 +398,28 @@ const User = RestModel.extend({
let updatedState = {};
["muted", "regular", "watched", "tracked", "watched_first_post"].forEach(
(s) => {
if (fields === undefined || fields.includes(s + "_category_ids")) {
(categoryNotificationLevel) => {
if (
fields === undefined ||
fields.includes(`${categoryNotificationLevel}_category_ids`)
) {
let prop =
s === "watched_first_post"
categoryNotificationLevel === "watched_first_post"
? "watchedFirstPostCategories"
: s + "Categories";
: `${categoryNotificationLevel}Categories`;
let cats = this.get(prop);
if (cats) {
let cat_ids = cats.map((c) => c.get("id"));
updatedState[s + "_category_ids"] = cat_ids;
updatedState[`${categoryNotificationLevel}_category_ids`] = cat_ids;
// HACK: denote lack of categories
if (cats.length === 0) {
cat_ids = [-1];
}
data[s + "_category_ids"] = cat_ids;
data[`${categoryNotificationLevel}_category_ids`] = cat_ids;
}
}
}

View File

@ -1,7 +1,7 @@
<div class="control-group category-notifications">
<label class="control-label">{{i18n "user.categories_settings"}}</label>
<div class="controls tracking-controls">
<div class="controls tracking-controls tracking-controls--watched-categories">
<label>{{d-icon "d-watching"}} {{i18n "user.watched_categories"}}</label>
{{#if this.canSee}}
<a class="show-tracking" href={{this.model.watchingTopicsPath}}>{{i18n "user.tracked_topics_link"}}</a>
@ -10,7 +10,7 @@
</div>
<div class="instructions">{{i18n "user.watched_categories_instructions"}}</div>
<div class="controls tracking-controls">
<div class="controls tracking-controls tracking-controls--tracked-categories">
<label>{{d-icon "d-tracking"}} {{i18n "user.tracked_categories"}}</label>
{{#if this.canSee}}
<a class="show-tracking" href={{this.model.trackingTopicsPath}}>{{i18n "user.tracked_topics_link"}}</a>
@ -19,20 +19,20 @@
</div>
<div class="instructions">{{i18n "user.tracked_categories_instructions"}}</div>
<div class="controls tracking-controls">
<div class="controls tracking-controls tracking-controls--watched-first-categories">
<label>{{d-icon "d-watching-first"}} {{i18n "user.watched_first_post_categories"}}</label>
<CategorySelector @categories={{this.model.watchedFirstPostCategories}} @blockedCategories={{this.selectedCategories}} @onChange={{action (mut this.model.watchedFirstPostCategories)}} />
</div>
<div class="instructions">{{i18n "user.watched_first_post_categories_instructions"}}</div>
{{#if this.siteSettings.mute_all_categories_by_default}}
<div class="controls tracking-controls">
<div class="controls tracking-controls tracking-controls--regular-categories">
<label>{{d-icon "d-regular"}} {{i18n "user.regular_categories"}}</label>
<CategorySelector @categories={{this.model.regularCategories}} @blockedCategories={{this.selectedCategories}} @onChange={{action (mut this.model.regularCategories)}} />
</div>
<div class="instructions">{{i18n "user.regular_categories_instructions"}}</div>
{{else}}
<div class="controls tracking-controls">
<div class="controls tracking-controls tracking-controls--muted-categories">
<label>{{d-icon "d-muted"}} {{i18n "user.muted_categories"}}</label>
{{#if this.canSee}}
<a class="show-tracking" href={{this.model.mutedTopicsPath}}>{{i18n "user.tracked_topics_link"}}</a>

View File

@ -0,0 +1,75 @@
import { test } from "qunit";
import { click, visit } from "@ember/test-helpers";
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
import selectKit from "discourse/tests/helpers/select-kit-helper";
acceptance("User Preferences - Categories", function (needs) {
needs.user();
let putRequestData;
needs.pretender((server, helper) => {
server.put("/u/eviltrout.json", (request) => {
putRequestData = helper.parsePostData(request.requestBody);
return helper.response({ user: {} });
});
});
needs.hooks.afterEach(() => {
putRequestData = null;
});
test("tracking category which is set to regular notification level for user when mute_all_categories_by_default site setting is enabled", async function (assert) {
this.siteSettings.mute_all_categories_by_default = true;
await visit("/u/eviltrout/preferences/categories");
const trackedCategoriesSelector = selectKit(
".tracking-controls--tracked-categories .category-selector"
);
await trackedCategoriesSelector.expand();
assert.notOk(
trackedCategoriesSelector.rowByValue("4").exists(),
"category that is set to regular is not available for selection"
);
const regularCategoriesSelector = selectKit(
".tracking-controls--regular-categories .category-selector"
);
await regularCategoriesSelector.expand();
await regularCategoriesSelector.deselectItemByValue("4");
await trackedCategoriesSelector.expand();
await trackedCategoriesSelector.selectRowByValue("4");
await click(".save-changes");
assert.deepEqual(putRequestData, {
"regular_category_ids[]": ["-1"],
"tracked_category_ids[]": ["4"],
"watched_category_ids[]": ["3"],
"watched_first_post_category_ids[]": ["-1"],
});
});
test("tracking category which is set to regular notification level for user when mute_all_categories_by_default site setting is disabled", async function (assert) {
await visit("/u/eviltrout/preferences/categories");
const categorySelector = selectKit(
".tracking-controls--tracked-categories .category-selector"
);
await categorySelector.expand();
// User has `regular_category_ids` set to [4] in fixtures
await categorySelector.selectRowByValue(4);
await click(".save-changes");
assert.deepEqual(putRequestData, {
"muted_category_ids[]": ["-1"],
"tracked_category_ids[]": ["4"],
"watched_category_ids[]": ["3"],
"watched_first_post_category_ids[]": ["-1"],
});
});
});