FEATURE: set notification levels when added to a group (#10378)

* FEATURE: set notification levels when added to a group

This feature allows admins and group owners to define default
category and tag tracking levels that will be applied to user
preferences automatically at the time when users are added to the
group. Users are free to change those preferences afterwards.
When removed from a group, the user's notification preferences aren't
changed.
This commit is contained in:
Neil Lalonde
2020-08-06 12:27:27 -04:00
committed by GitHub
parent cd4f251891
commit 1ca81fbb95
27 changed files with 937 additions and 8 deletions

View File

@@ -0,0 +1,14 @@
import discourseComputed from "discourse-common/utils/decorators";
import Controller from "@ember/controller";
export default Controller.extend({
@discourseComputed(
"model.watchingCategories.[]",
"model.watchingFirstPostCategories.[]",
"model.trackingCategories.[]",
"model.mutedCategories.[]"
)
selectedCategories(watching, watchingFirst, tracking, muted) {
return [].concat(watching, watchingFirst, tracking, muted).filter(t => t);
}
});

View File

@@ -0,0 +1,14 @@
import discourseComputed from "discourse-common/utils/decorators";
import Controller from "@ember/controller";
export default Controller.extend({
@discourseComputed(
"model.watching_tags.[]",
"model.watching_first_post_tags.[]",
"model.tracking_tags.[]",
"model.muted_tags.[]"
)
selectedTags(watching, watchingFirst, tracking, muted) {
return [].concat(watching, watchingFirst, tracking, muted).filter(t => t);
}
});

View File

@@ -13,6 +13,14 @@ export default Controller.extend({
route: "group.manage.interaction",
title: "groups.manage.interaction.title"
},
{
route: "group.manage.categories",
title: "groups.manage.categories.title"
},
{
route: "group.manage.tags",
title: "groups.manage.tags.title"
},
{ route: "group.manage.logs", title: "groups.manage.logs.title" }
];

View File

@@ -176,6 +176,35 @@ const Group = RestModel.extend({
}
},
@observes("watching_category_ids")
_updateWatchingCategories() {
this.set(
"watchingCategories",
Category.findByIds(this.watching_category_ids)
);
},
@observes("tracking_category_ids")
_updateTrackingCategories() {
this.set(
"trackingCategories",
Category.findByIds(this.tracking_category_ids)
);
},
@observes("watching_first_post_category_ids")
_updateWatchingFirstPostCategories() {
this.set(
"watchingFirstPostCategories",
Category.findByIds(this.watching_first_post_category_ids)
);
},
@observes("muted_category_ids")
_updateMutedCategories() {
this.set("mutedCategories", Category.findByIds(this.muted_category_ids));
},
asJSON() {
const attrs = {
name: this.name,
@@ -211,6 +240,26 @@ 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";
let categories = this.get(prop);
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 : [""];
}
});
if (this.flair_type === "icon") {
attrs["flair_icon"] = this.flair_icon;
} else if (this.flair_type === "image") {

View File

@@ -94,6 +94,8 @@ export default function() {
this.route("interaction");
this.route("email");
this.route("members");
this.route("categories");
this.route("tags");
this.route("logs");
});

View File

@@ -0,0 +1,10 @@
import I18n from "I18n";
import DiscourseRoute from "discourse/routes/discourse";
export default DiscourseRoute.extend({
showFooter: true,
titleToken() {
return I18n.t("groups.manage.categories.title");
}
});

View File

@@ -0,0 +1,10 @@
import I18n from "I18n";
import DiscourseRoute from "discourse/routes/discourse";
export default DiscourseRoute.extend({
showFooter: true,
titleToken() {
return I18n.t("groups.manage.tags.title");
}
});

View File

@@ -0,0 +1,64 @@
<form class="groups-form form-vertical groups-notifications-form">
<div class="control-group">
<label class="control-label">{{i18n "groups.manage.categories.long_title"}}</label>
<div>{{i18n "groups.manage.categories.description"}}</div>
</div>
<div class="control-group">
<label>{{d-icon "d-watching"}} {{i18n "user.watched_categories"}}</label>
{{category-selector
categories=model.watchingCategories
blacklist=selectedCategories
onChange=(action (mut model.watchingCategories))
}}
<div class="control-instructions">
{{i18n "groups.manage.categories.watched_categories_instructions"}}
</div>
</div>
<div class="control-group">
<label>{{d-icon "d-tracking"}} {{i18n "user.tracked_categories"}}</label>
{{category-selector
categories=model.trackingCategories
blacklist=selectedCategories
onChange=(action (mut model.trackingCategories))
}}
<div class="control-instructions">
{{i18n "groups.manage.categories.tracked_categories_instructions"}}
</div>
</div>
<div class="control-group">
<label>{{d-icon "d-watching-first"}} {{i18n "user.watched_first_post_categories"}}</label>
{{category-selector
categories=model.watchingFirstPostCategories
blacklist=selectedCategories
onChange=(action (mut model.watchingFirstPostCategories))
}}
<div class="control-instructions">
{{i18n "groups.manage.categories.watching_first_post_categories_instructions"}}
</div>
</div>
<div class="control-group">
<label>{{d-icon "d-muted"}} {{i18n "user.muted_categories"}}</label>
{{category-selector
categories=model.mutedCategories
blacklist=selectedCategories
onChange=(action (mut model.mutedCategories))
}}
<div class="control-instructions">
{{i18n "groups.manage.categories.muted_categories_instructions"}}
</div>
</div>
{{group-manage-save-button model=model}}
</form>

View File

@@ -0,0 +1,72 @@
<form class="groups-form form-vertical groups-notifications-form">
<div class="control-group">
<label class="control-label">{{i18n "groups.manage.tags.long_title"}}</label>
<div>{{i18n "groups.manage.tags.description"}}</div>
</div>
<div class="control-group">
<label>{{d-icon "d-watching"}} {{i18n "user.watched_tags"}}</label>
{{tag-chooser
tags=model.watching_tags
blacklist=selectedTags
allowCreate=false
everyTag=true
unlimitedTagCount=true
}}
<div class="control-instructions">
{{i18n "groups.manage.tags.watched_tags_instructions"}}
</div>
</div>
<div class="control-group">
<label>{{d-icon "d-tracking"}} {{i18n "user.tracked_tags"}}</label>
{{tag-chooser
tags=model.tracking_tags
blacklist=selectedTags
allowCreate=false
everyTag=true
unlimitedTagCount=true
}}
<div class="control-instructions">
{{i18n "groups.manage.tags.tracked_tags_instructions"}}
</div>
</div>
<div class="control-group">
<label>{{d-icon "d-watching-first"}} {{i18n "user.watched_first_post_tags"}}</label>
{{tag-chooser
tags=model.watching_first_post_tags
blacklist=selectedTags
allowCreate=false
everyTag=true
unlimitedTagCount=true
}}
<div class="control-instructions">
{{i18n "groups.manage.tags.watching_first_post_tags_instructions"}}
</div>
</div>
<div class="control-group">
<label>{{d-icon "d-muted"}} {{i18n "user.muted_tags"}}</label>
{{tag-chooser
tags=model.muted_tags
blacklist=selectedTags
allowCreate=false
everyTag=true
unlimitedTagCount=true
}}
<div class="control-instructions">
{{i18n "groups.manage.tags.muted_tags_instructions"}}
</div>
</div>
{{group-manage-save-button model=model}}
</form>