FEATURE: allow group membership to unmute categories and tags

For sites that are configured to mute some or all categories and tags
for users by default, groups can now be configured to set members'
notification level to normal from the group manage UI.
This commit is contained in:
Neil Lalonde
2020-08-13 17:20:23 -04:00
parent 18fb34bf2e
commit d65a839577
14 changed files with 124 additions and 59 deletions

View File

@ -6,9 +6,12 @@ export default Controller.extend({
"model.watchingCategories.[]",
"model.watchingFirstPostCategories.[]",
"model.trackingCategories.[]",
"model.regularCategories.[]",
"model.mutedCategories.[]"
)
selectedCategories(watching, watchingFirst, tracking, muted) {
return [].concat(watching, watchingFirst, tracking, muted).filter(t => t);
selectedCategories(watching, watchingFirst, tracking, regular, muted) {
return []
.concat(watching, watchingFirst, tracking, regular, muted)
.filter(t => t);
}
});

View File

@ -6,9 +6,12 @@ export default Controller.extend({
"model.watching_tags.[]",
"model.watching_first_post_tags.[]",
"model.tracking_tags.[]",
"model.regular_tags.[]",
"model.muted_tags.[]"
)
selectedTags(watching, watchingFirst, tracking, muted) {
return [].concat(watching, watchingFirst, tracking, muted).filter(t => t);
selectedTags(watching, watchingFirst, tracking, regular, muted) {
return []
.concat(watching, watchingFirst, tracking, regular, muted)
.filter(t => t);
}
});

View File

@ -200,6 +200,14 @@ const Group = RestModel.extend({
);
},
@observes("regular_category_ids")
_updateRegularCategories() {
this.set(
"regularCategories",
Category.findByIds(this.regular_category_ids)
);
},
@observes("muted_category_ids")
_updateMutedCategories() {
this.set("mutedCategories", Category.findByIds(this.muted_category_ids));
@ -240,25 +248,27 @@ const Group = RestModel.extend({
publish_read_state: this.publish_read_state
};
["muted", "watching", "tracking", "watching_first_post"].forEach(s => {
let prop =
s === "watching_first_post"
? "watchingFirstPostCategories"
: s + "Categories";
["muted", "regular", "watching", "tracking", "watching_first_post"].forEach(
s => {
let prop =
s === "watching_first_post"
? "watchingFirstPostCategories"
: s + "Categories";
let categories = this.get(prop);
let categories = this.get(prop);
if (categories) {
attrs[s + "_category_ids"] =
categories.length > 0 ? categories.map(c => c.get("id")) : [-1];
if (categories) {
attrs[s + "_category_ids"] =
categories.length > 0 ? categories.map(c => c.get("id")) : [-1];
}
let tags = this.get(s + "_tags");
if (tags) {
attrs[s + "_tags"] = tags.length > 0 ? tags : [""];
}
}
let tags = this.get(s + "_tags");
if (tags) {
attrs[s + "_tags"] = tags.length > 0 ? tags : [""];
}
});
);
if (this.flair_type === "icon") {
attrs["flair_icon"] = this.flair_icon;

View File

@ -5,11 +5,11 @@
</div>
<div class="control-group">
<label>{{d-icon "d-watching"}} {{i18n "user.watched_categories"}}</label>
<label>{{d-icon "d-watching"}} {{i18n "groups.notifications.watching.title"}}</label>
{{category-selector
categories=model.watchingCategories
blacklist=selectedCategories
blocklist=selectedCategories
onChange=(action (mut model.watchingCategories))
}}
@ -19,11 +19,11 @@
</div>
<div class="control-group">
<label>{{d-icon "d-tracking"}} {{i18n "user.tracked_categories"}}</label>
<label>{{d-icon "d-tracking"}} {{i18n "groups.notifications.tracking.title"}}</label>
{{category-selector
categories=model.trackingCategories
blacklist=selectedCategories
blocklist=selectedCategories
onChange=(action (mut model.trackingCategories))
}}
@ -33,11 +33,11 @@
</div>
<div class="control-group">
<label>{{d-icon "d-watching-first"}} {{i18n "user.watched_first_post_categories"}}</label>
<label>{{d-icon "d-watching-first"}} {{i18n "groups.notifications.watching_first_post.title"}}</label>
{{category-selector
categories=model.watchingFirstPostCategories
blacklist=selectedCategories
blocklist=selectedCategories
onChange=(action (mut model.watchingFirstPostCategories))
}}
@ -47,11 +47,25 @@
</div>
<div class="control-group">
<label>{{d-icon "d-muted"}} {{i18n "user.muted_categories"}}</label>
<label>{{d-icon "d-regular"}} {{i18n "groups.notifications.regular.title"}}</label>
{{category-selector
categories=model.regularCategories
blocklist=selectedCategories
onChange=(action (mut model.regularCategories))
}}
<div class="control-instructions">
{{i18n "groups.manage.categories.regular_categories_instructions"}}
</div>
</div>
<div class="control-group">
<label>{{d-icon "d-muted"}} {{i18n "groups.notifications.muted.title"}}</label>
{{category-selector
categories=model.mutedCategories
blacklist=selectedCategories
blocklist=selectedCategories
onChange=(action (mut model.mutedCategories))
}}

View File

@ -5,7 +5,7 @@
</div>
<div class="control-group">
<label>{{d-icon "d-watching"}} {{i18n "user.watched_tags"}}</label>
<label>{{d-icon "d-watching"}} {{i18n "groups.notifications.watching.title"}}</label>
{{tag-chooser
tags=model.watching_tags
@ -21,7 +21,7 @@
</div>
<div class="control-group">
<label>{{d-icon "d-tracking"}} {{i18n "user.tracked_tags"}}</label>
<label>{{d-icon "d-tracking"}} {{i18n "groups.notifications.tracking.title"}}</label>
{{tag-chooser
tags=model.tracking_tags
@ -37,7 +37,7 @@
</div>
<div class="control-group">
<label>{{d-icon "d-watching-first"}} {{i18n "user.watched_first_post_tags"}}</label>
<label>{{d-icon "d-watching-first"}} {{i18n "groups.notifications.watching_first_post.title"}}</label>
{{tag-chooser
tags=model.watching_first_post_tags
@ -53,7 +53,23 @@
</div>
<div class="control-group">
<label>{{d-icon "d-muted"}} {{i18n "user.muted_tags"}}</label>
<label>{{d-icon "d-regular"}} {{i18n "groups.notifications.regular.title"}}</label>
{{tag-chooser
tags=model.regular_tags
blacklist=selectedTags
allowCreate=false
everyTag=true
unlimitedTagCount=true
}}
<div class="control-instructions">
{{i18n "groups.manage.tags.regular_tags_instructions"}}
</div>
</div>
<div class="control-group">
<label>{{d-icon "d-muted"}} {{i18n "groups.notifications.muted.title"}}</label>
{{tag-chooser
tags=model.muted_tags

View File

@ -611,7 +611,7 @@ class GroupsController < ApplicationController
end
if !automatic || current_user.admin
[:muted, :tracking, :watching, :watching_first_post].each do |level|
[:muted, :regular, :tracking, :watching, :watching_first_post].each do |level|
permitted_params << { "#{level}_category_ids" => [] }
permitted_params << { "#{level}_tags" => [] }
end

View File

@ -765,7 +765,7 @@ class Group < ActiveRecord::Base
flair_icon.presence || flair_upload&.short_path
end
[:muted, :tracking, :watching, :watching_first_post].each do |level|
[:muted, :regular, :tracking, :watching, :watching_first_post].each do |level|
define_method("#{level}_category_ids=") do |category_ids|
@category_notifications ||= {}
@category_notifications[level] = category_ids

View File

@ -86,7 +86,7 @@ class GroupUser < ActiveRecord::Base
higher_level_category_ids = user_levels.values.flatten
[:muted, :tracking, :watching_first_post, :watching].each do |level|
[:muted, :regular, :tracking, :watching_first_post, :watching].each do |level|
level_num = NotificationLevels.all[level]
higher_level_category_ids -= (user_levels[level_num] || [])
if group_category_ids = group_levels[level_num]
@ -118,7 +118,7 @@ class GroupUser < ActiveRecord::Base
higher_level_tag_ids = user_levels.values.flatten
[:muted, :tracking, :watching_first_post, :watching].each do |level|
[:muted, :regular, :tracking, :watching_first_post, :watching].each do |level|
level_num = NotificationLevels.all[level]
higher_level_tag_ids -= (user_levels[level_num] || [])
if group_tag_ids = group_levels[level_num]

View File

@ -69,10 +69,12 @@ class BasicGroupSerializer < ApplicationSerializer
admin_or_owner_attributes :watching_category_ids,
:tracking_category_ids,
:watching_first_post_category_ids,
:regular_category_ids,
:muted_category_ids,
:watching_tags,
:watching_first_post_tags,
:tracking_tags,
:regular_tags,
:muted_tags
def include_display_name?
@ -121,7 +123,7 @@ class BasicGroupSerializer < ApplicationSerializer
scope.can_see_group_members?(object)
end
[:watching, :tracking, :watching_first_post, :muted].each do |level|
[:watching, :regular, :tracking, :watching_first_post, :muted].each do |level|
define_method("#{level}_category_ids") do
GroupCategoryNotificationDefault.lookup(object, level).pluck(:category_id)
end