FEATURE: offer to unwatch categories when unwatching category
This commit is contained in:
parent
3e07658fb2
commit
1411eedad3
|
@ -2,6 +2,7 @@ import { setting } from 'discourse/lib/computed';
|
|||
import CanCheckEmails from 'discourse/mixins/can-check-emails';
|
||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||
import computed from "ember-addons/ember-computed-decorators";
|
||||
import { categoryBadgeHTML } from "discourse/helpers/category-link";
|
||||
|
||||
export default Ember.Controller.extend(CanCheckEmails, {
|
||||
|
||||
|
@ -134,6 +135,25 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
|||
this.set('saved', false);
|
||||
|
||||
const model = this.get('model');
|
||||
|
||||
|
||||
// watched status changes warn user
|
||||
const changedWatch = model.changedCategoryNotifications("watched");
|
||||
|
||||
if (changedWatch.remove.length > 0 && !this.get("warnedRemoveWatch")) {
|
||||
var categories = Discourse.Category.findByIds(changedWatch.remove).map((cat) => {
|
||||
return categoryBadgeHTML(cat);
|
||||
}).join(" ");
|
||||
bootbox.confirm(I18n.t('user.warn_unwatch.message', {categories: categories}),
|
||||
I18n.t('user.warn_unwatch.no_value', {count: changedWatch.remove.length}), I18n.t('user.warn_unwatch.yes_value'),
|
||||
(yes)=>{
|
||||
this.set('unwatchCategoryTopics', yes ? changedWatch.remove : false);
|
||||
this.send('save');
|
||||
});
|
||||
this.set("warnedRemoveWatch", true);
|
||||
return;
|
||||
}
|
||||
|
||||
const userFields = this.get('userFields');
|
||||
|
||||
// Update the user fields
|
||||
|
@ -148,12 +168,19 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
|||
|
||||
// Cook the bio for preview
|
||||
model.set('name', this.get('newNameInput'));
|
||||
return model.save().then(() => {
|
||||
var options = {};
|
||||
if (this.get('warnedRemoveWatch') && this.get('unwatchCategoryTopics')) {
|
||||
options["unwatchCategoryTopics"] = this.get("unwatchCategoryTopics");
|
||||
}
|
||||
|
||||
return model.save(options).then(() => {
|
||||
if (Discourse.User.currentProp('id') === model.get('id')) {
|
||||
Discourse.User.currentProp('name', model.get('name'));
|
||||
}
|
||||
model.set('bio_cooked', Discourse.Markdown.cook(Discourse.Markdown.sanitize(model.get('bio_raw'))));
|
||||
this.set('saved', true);
|
||||
this.set("unwatchTopics", false);
|
||||
this.set('warnedRemoveWatch', false);
|
||||
}).catch(popupAjaxError);
|
||||
},
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ const User = RestModel.extend({
|
|||
return Discourse.User.create(this.getProperties(Object.keys(this)));
|
||||
},
|
||||
|
||||
save() {
|
||||
save(options) {
|
||||
const data = this.getProperties(
|
||||
'bio_raw',
|
||||
'website',
|
||||
|
@ -177,8 +177,12 @@ const User = RestModel.extend({
|
|||
data[s] = this.get(`user_option.${s}`);
|
||||
});
|
||||
|
||||
var updatedState = {};
|
||||
|
||||
['muted','watched','tracked'].forEach(s => {
|
||||
let cats = this.get(s + 'Categories').map(c => c.get('id'));
|
||||
updatedState[s + '_category_ids'] = cats;
|
||||
|
||||
// HACK: denote lack of categories
|
||||
if (cats.length === 0) { cats = [-1]; }
|
||||
data[s + '_category_ids'] = cats;
|
||||
|
@ -188,6 +192,10 @@ const User = RestModel.extend({
|
|||
data['edit_history_public'] = this.get('user_option.edit_history_public');
|
||||
}
|
||||
|
||||
if (options && options.unwatchCategoryTopics) {
|
||||
data.unwatch_category_topics = options.unwatchCategoryTopics;
|
||||
}
|
||||
|
||||
// TODO: We can remove this when migrated fully to rest model.
|
||||
this.set('isSaving', true);
|
||||
return Discourse.ajax(`/users/${this.get('username_lower')}`, {
|
||||
|
@ -197,6 +205,7 @@ const User = RestModel.extend({
|
|||
this.set('bio_excerpt', result.user.bio_excerpt);
|
||||
const userProps = Em.getProperties(this.get('user_option'),'enable_quoting', 'external_links_in_new_tab', 'dynamic_favicon');
|
||||
Discourse.User.current().setProperties(userProps);
|
||||
this.setProperties(updatedState);
|
||||
}).finally(() => {
|
||||
this.set('isSaving', false);
|
||||
});
|
||||
|
@ -352,6 +361,16 @@ const User = RestModel.extend({
|
|||
this.set("watchedCategories", Discourse.Category.findByIds(this.watched_category_ids));
|
||||
},
|
||||
|
||||
changedCategoryNotifications: function(type) {
|
||||
const ids = this.get(type + "Categories").map(c => c.id);
|
||||
const oldIds = this.get(type + "_category_ids");
|
||||
|
||||
return {
|
||||
add: _.difference(ids, oldIds),
|
||||
remove: _.difference(oldIds, ids),
|
||||
}
|
||||
},
|
||||
|
||||
@computed("can_delete_account", "reply_count", "topic_count")
|
||||
canDeleteAccount(canDeleteAccount, replyCount, topicCount) {
|
||||
return !Discourse.SiteSettings.enable_sso && canDeleteAccount && ((replyCount || 0) + (topicCount || 0)) <= 1;
|
||||
|
|
|
@ -89,6 +89,10 @@ class UsersController < ApplicationController
|
|||
user = fetch_user_from_params
|
||||
guardian.ensure_can_edit!(user)
|
||||
|
||||
if params[:unwatch_category_topics]
|
||||
TopicUser.unwatch_categories!(user, params[:unwatch_category_topics])
|
||||
end
|
||||
|
||||
if params[:user_fields].present?
|
||||
params[:custom_fields] = {} unless params[:custom_fields].present?
|
||||
|
||||
|
|
|
@ -59,6 +59,32 @@ class TopicUser < ActiveRecord::Base
|
|||
topic_user.save
|
||||
end
|
||||
|
||||
def unwatch_categories!(user, category_ids)
|
||||
|
||||
track_threshold = user.user_option.auto_track_topics_after_msecs
|
||||
|
||||
sql = <<SQL
|
||||
UPDATE topic_users tu
|
||||
SET notification_level = CASE
|
||||
WHEN t.user_id = :user_id THEN :watching
|
||||
WHEN total_msecs_viewed > :track_threshold AND :track_threshold >= 0 THEN :tracking
|
||||
ELSE :regular
|
||||
end
|
||||
FROM topics t
|
||||
WHERE t.id = tu.topic_id AND tu.notification_level <> :muted AND category_id IN (:category_ids) AND tu.user_id = :user_id
|
||||
SQL
|
||||
|
||||
exec_sql(sql,
|
||||
watching: notification_levels[:watching],
|
||||
tracking: notification_levels[:tracking],
|
||||
regular: notification_levels[:regular],
|
||||
muted: notification_levels[:muted],
|
||||
category_ids: category_ids,
|
||||
user_id: user.id,
|
||||
track_threshold: track_threshold
|
||||
)
|
||||
end
|
||||
|
||||
# Find the information specific to a user in a forum topic
|
||||
def lookup_for(user, topics)
|
||||
# If the user isn't logged in, there's no last read posts
|
||||
|
|
|
@ -574,6 +574,13 @@ en:
|
|||
failed_to_move: "Failed to move selected messages (perhaps your network is down)"
|
||||
select_all: "Select All"
|
||||
|
||||
warn_unwatch:
|
||||
message: "Also stop watching previously watched topics in {{categories}}?"
|
||||
yes_value: "Yes, unwatch topics"
|
||||
no_value:
|
||||
one: "No, only unwatch category"
|
||||
other: "No, only unwatch categories"
|
||||
|
||||
change_password:
|
||||
success: "(email sent)"
|
||||
in_progress: "(sending email)"
|
||||
|
|
|
@ -2,6 +2,34 @@ require 'rails_helper'
|
|||
|
||||
describe TopicUser do
|
||||
|
||||
describe "#unwatch_categories!" do
|
||||
it "correctly unwatches categories" do
|
||||
|
||||
op_topic = Fabricate(:topic)
|
||||
another_topic = Fabricate(:topic)
|
||||
tracked_topic = Fabricate(:topic)
|
||||
|
||||
user = op_topic.user
|
||||
watching = TopicUser.notification_levels[:watching]
|
||||
regular = TopicUser.notification_levels[:regular]
|
||||
tracking = TopicUser.notification_levels[:tracking]
|
||||
|
||||
TopicUser.change(user.id, op_topic, notification_level: watching)
|
||||
TopicUser.change(user.id, another_topic, notification_level: watching)
|
||||
TopicUser.change(user.id, tracked_topic, notification_level: watching, total_msecs_viewed: SiteSetting.default_other_auto_track_topics_after_msecs + 1)
|
||||
|
||||
TopicUser.unwatch_categories!(user, [Fabricate(:category).id, Fabricate(:category).id])
|
||||
expect(TopicUser.get(another_topic, user).notification_level).to eq(watching)
|
||||
|
||||
TopicUser.unwatch_categories!(user, [op_topic.category_id])
|
||||
|
||||
expect(TopicUser.get(op_topic, user).notification_level).to eq(watching)
|
||||
expect(TopicUser.get(another_topic, user).notification_level).to eq(regular)
|
||||
expect(TopicUser.get(tracked_topic, user).notification_level).to eq(tracking)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe '#notification_levels' do
|
||||
context "verify enum sequence" do
|
||||
before do
|
||||
|
|
Loading…
Reference in New Issue