Merge pull request #4477 from cpradio/watching-state-on-reply
FEATURE: Add notification level user preference when replying to a topic
This commit is contained in:
commit
ea1f0683c8
|
@ -3,6 +3,7 @@ import CanCheckEmails from 'discourse/mixins/can-check-emails';
|
||||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||||
import computed from "ember-addons/ember-computed-decorators";
|
import computed from "ember-addons/ember-computed-decorators";
|
||||||
import { cook } from 'discourse/lib/text';
|
import { cook } from 'discourse/lib/text';
|
||||||
|
import { NotificationLevels } from 'discourse/lib/notification-levels';
|
||||||
|
|
||||||
export default Ember.Controller.extend(CanCheckEmails, {
|
export default Ember.Controller.extend(CanCheckEmails, {
|
||||||
|
|
||||||
|
@ -110,6 +111,10 @@ export default Ember.Controller.extend(CanCheckEmails, {
|
||||||
{ name: I18n.t('user.auto_track_options.after_5_minutes'), value: 300000 },
|
{ name: I18n.t('user.auto_track_options.after_5_minutes'), value: 300000 },
|
||||||
{ name: I18n.t('user.auto_track_options.after_10_minutes'), value: 600000 }],
|
{ name: I18n.t('user.auto_track_options.after_10_minutes'), value: 600000 }],
|
||||||
|
|
||||||
|
notificationLevelsForReplying: [{ name: I18n.t('topic.notifications.watching.title'), value: NotificationLevels.WATCHING },
|
||||||
|
{ name: I18n.t('topic.notifications.tracking.title'), value: NotificationLevels.TRACKING }],
|
||||||
|
|
||||||
|
|
||||||
considerNewTopicOptions: [{ name: I18n.t('user.new_topic_duration.not_viewed'), value: -1 },
|
considerNewTopicOptions: [{ name: I18n.t('user.new_topic_duration.not_viewed'), value: -1 },
|
||||||
{ name: I18n.t('user.new_topic_duration.after_1_day'), value: 60 * 24 },
|
{ name: I18n.t('user.new_topic_duration.after_1_day'), value: 60 * 24 },
|
||||||
{ name: I18n.t('user.new_topic_duration.after_2_days'), value: 60 * 48 },
|
{ name: I18n.t('user.new_topic_duration.after_2_days'), value: 60 * 48 },
|
||||||
|
|
|
@ -222,6 +222,7 @@ const User = RestModel.extend({
|
||||||
'digest_after_minutes',
|
'digest_after_minutes',
|
||||||
'new_topic_duration_minutes',
|
'new_topic_duration_minutes',
|
||||||
'auto_track_topics_after_msecs',
|
'auto_track_topics_after_msecs',
|
||||||
|
'notification_level_when_replying',
|
||||||
'like_notification_frequency',
|
'like_notification_frequency',
|
||||||
'include_tl0_in_digests'
|
'include_tl0_in_digests'
|
||||||
].forEach(s => {
|
].forEach(s => {
|
||||||
|
|
|
@ -234,6 +234,11 @@
|
||||||
{{combo-box valueAttribute="value" content=autoTrackDurations value=model.user_option.auto_track_topics_after_msecs}}
|
{{combo-box valueAttribute="value" content=autoTrackDurations value=model.user_option.auto_track_topics_after_msecs}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="controls controls-dropdown">
|
||||||
|
<label>{{i18n 'user.notification_level_when_replying'}}</label>
|
||||||
|
{{combo-box valueAttribute="value" content=notificationLevelsForReplying value=model.user_option.notification_level_when_replying}}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="controls controls-dropdown">
|
<div class="controls controls-dropdown">
|
||||||
<label>{{i18n 'user.like_notification_frequency.title'}}</label>
|
<label>{{i18n 'user.like_notification_frequency.title'}}</label>
|
||||||
{{combo-box valueAttribute="value" content=likeNotificationFrequencies value=model.user_option.like_notification_frequency}}
|
{{combo-box valueAttribute="value" content=likeNotificationFrequencies value=model.user_option.like_notification_frequency}}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
require_dependency 'enum_site_setting'
|
||||||
|
require_dependency 'notification_levels'
|
||||||
|
|
||||||
|
class NotificationLevelWhenReplyingSiteSetting < EnumSiteSetting
|
||||||
|
|
||||||
|
def self.valid_value?(val)
|
||||||
|
val.to_i.to_s == val.to_s &&
|
||||||
|
values.any? { |v| v[:value] == val.to_i }
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.notification_levels
|
||||||
|
NotificationLevels.topic_levels
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.values
|
||||||
|
@values ||= [
|
||||||
|
{ name: 'topic.notifications.watching.title', value: notification_levels[:watching] },
|
||||||
|
{ name: 'topic.notifications.tracking.title', value: notification_levels[:tracking] }
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.translate_names?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -37,24 +37,24 @@ class TopicUser < ActiveRecord::Base
|
||||||
auto_track_tag: 12)
|
auto_track_tag: 12)
|
||||||
end
|
end
|
||||||
|
|
||||||
def auto_track(user_id, topic_id, reason)
|
def auto_notification(user_id, topic_id, reason, notification_level)
|
||||||
if TopicUser.where(user_id: user_id, topic_id: topic_id, notifications_reason_id: nil).exists?
|
if TopicUser.where(user_id: user_id, topic_id: topic_id, notifications_reason_id: nil).exists?
|
||||||
change(user_id, topic_id,
|
change(user_id, topic_id,
|
||||||
notification_level: notification_levels[:tracking],
|
notification_level: notification_level,
|
||||||
notifications_reason_id: reason
|
notifications_reason_id: reason
|
||||||
)
|
)
|
||||||
|
|
||||||
MessageBus.publish("/topic/#{topic_id}", {
|
MessageBus.publish("/topic/#{topic_id}", {
|
||||||
notification_level_change: notification_levels[:tracking],
|
notification_level_change: notification_level,
|
||||||
notifications_reason_id: reason
|
notifications_reason_id: reason
|
||||||
}, user_ids: [user_id])
|
}, user_ids: [user_id])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def auto_watch(user_id, topic_id)
|
def auto_notification_for_staging(user_id, topic_id, reason)
|
||||||
topic_user = TopicUser.find_or_initialize_by(user_id: user_id, topic_id: topic_id)
|
topic_user = TopicUser.find_or_initialize_by(user_id: user_id, topic_id: topic_id)
|
||||||
topic_user.notification_level = notification_levels[:watching]
|
topic_user.notification_level = notification_levels[:watching]
|
||||||
topic_user.notifications_reason_id = notification_reasons[:auto_watch]
|
topic_user.notifications_reason_id = reason
|
||||||
topic_user.save
|
topic_user.save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ class UserOption < ActiveRecord::Base
|
||||||
|
|
||||||
self.new_topic_duration_minutes = SiteSetting.default_other_new_topic_duration_minutes
|
self.new_topic_duration_minutes = SiteSetting.default_other_new_topic_duration_minutes
|
||||||
self.auto_track_topics_after_msecs = SiteSetting.default_other_auto_track_topics_after_msecs
|
self.auto_track_topics_after_msecs = SiteSetting.default_other_auto_track_topics_after_msecs
|
||||||
|
self.notification_level_when_replying = SiteSetting.default_other_notification_level_when_replying
|
||||||
|
|
||||||
self.like_notification_frequency = SiteSetting.default_other_like_notification_frequency
|
self.like_notification_frequency = SiteSetting.default_other_like_notification_frequency
|
||||||
|
|
||||||
|
@ -129,26 +130,27 @@ end
|
||||||
#
|
#
|
||||||
# Table name: user_options
|
# Table name: user_options
|
||||||
#
|
#
|
||||||
# user_id :integer not null, primary key
|
# user_id :integer not null, primary key
|
||||||
# email_always :boolean default(FALSE), not null
|
# email_always :boolean default(FALSE), not null
|
||||||
# mailing_list_mode :boolean default(FALSE), not null
|
# mailing_list_mode :boolean default(FALSE), not null
|
||||||
# email_digests :boolean
|
# email_digests :boolean
|
||||||
# email_direct :boolean default(TRUE), not null
|
# email_direct :boolean default(TRUE), not null
|
||||||
# email_private_messages :boolean default(TRUE), not null
|
# email_private_messages :boolean default(TRUE), not null
|
||||||
# external_links_in_new_tab :boolean default(FALSE), not null
|
# external_links_in_new_tab :boolean default(FALSE), not null
|
||||||
# enable_quoting :boolean default(TRUE), not null
|
# enable_quoting :boolean default(TRUE), not null
|
||||||
# dynamic_favicon :boolean default(FALSE), not null
|
# dynamic_favicon :boolean default(FALSE), not null
|
||||||
# disable_jump_reply :boolean default(FALSE), not null
|
# disable_jump_reply :boolean default(FALSE), not null
|
||||||
# automatically_unpin_topics :boolean default(TRUE), not null
|
# automatically_unpin_topics :boolean default(TRUE), not null
|
||||||
# digest_after_minutes :integer
|
# digest_after_minutes :integer
|
||||||
# auto_track_topics_after_msecs :integer
|
# auto_track_topics_after_msecs :integer
|
||||||
# new_topic_duration_minutes :integer
|
# notification_level_when_replying :integer
|
||||||
# last_redirected_to_top_at :datetime
|
# new_topic_duration_minutes :integer
|
||||||
# email_previous_replies :integer default(2), not null
|
# last_redirected_to_top_at :datetime
|
||||||
# email_in_reply_to :boolean default(TRUE), not null
|
# email_previous_replies :integer default(2), not null
|
||||||
# like_notification_frequency :integer default(1), not null
|
# email_in_reply_to :boolean default(TRUE), not null
|
||||||
# include_tl0_in_digests :boolean default(FALSE)
|
# like_notification_frequency :integer default(1), not null
|
||||||
# mailing_list_mode_frequency :integer default(0), not null
|
# include_tl0_in_digests :boolean default(FALSE)
|
||||||
|
# mailing_list_mode_frequency :integer default(0), not null
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
|
|
@ -13,6 +13,7 @@ class UserOptionSerializer < ApplicationSerializer
|
||||||
:digest_after_minutes,
|
:digest_after_minutes,
|
||||||
:automatically_unpin_topics,
|
:automatically_unpin_topics,
|
||||||
:auto_track_topics_after_msecs,
|
:auto_track_topics_after_msecs,
|
||||||
|
:notification_level_when_replying,
|
||||||
:new_topic_duration_minutes,
|
:new_topic_duration_minutes,
|
||||||
:email_previous_replies,
|
:email_previous_replies,
|
||||||
:email_in_reply_to,
|
:email_in_reply_to,
|
||||||
|
@ -24,6 +25,10 @@ class UserOptionSerializer < ApplicationSerializer
|
||||||
object.auto_track_topics_after_msecs || SiteSetting.default_other_auto_track_topics_after_msecs
|
object.auto_track_topics_after_msecs || SiteSetting.default_other_auto_track_topics_after_msecs
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def notification_level_when_replying
|
||||||
|
object.notification_level_when_replying || SiteSetting.default_other_notification_level_when_replying
|
||||||
|
end
|
||||||
|
|
||||||
def new_topic_duration_minutes
|
def new_topic_duration_minutes
|
||||||
object.new_topic_duration_minutes || SiteSetting.default_other_new_topic_duration_minutes
|
object.new_topic_duration_minutes || SiteSetting.default_other_new_topic_duration_minutes
|
||||||
end
|
end
|
||||||
|
|
|
@ -29,6 +29,7 @@ class UserUpdater
|
||||||
:digest_after_minutes,
|
:digest_after_minutes,
|
||||||
:new_topic_duration_minutes,
|
:new_topic_duration_minutes,
|
||||||
:auto_track_topics_after_msecs,
|
:auto_track_topics_after_msecs,
|
||||||
|
:notification_level_when_replying,
|
||||||
:email_previous_replies,
|
:email_previous_replies,
|
||||||
:email_in_reply_to,
|
:email_in_reply_to,
|
||||||
:like_notification_frequency,
|
:like_notification_frequency,
|
||||||
|
|
|
@ -740,6 +740,8 @@ en:
|
||||||
after_5_minutes: "after 5 minutes"
|
after_5_minutes: "after 5 minutes"
|
||||||
after_10_minutes: "after 10 minutes"
|
after_10_minutes: "after 10 minutes"
|
||||||
|
|
||||||
|
notification_level_when_replying: "When I post in a topic, set that topic to"
|
||||||
|
|
||||||
invited:
|
invited:
|
||||||
search: "type to search invites..."
|
search: "type to search invites..."
|
||||||
title: "Invites"
|
title: "Invites"
|
||||||
|
|
|
@ -1368,6 +1368,7 @@ en:
|
||||||
|
|
||||||
default_other_new_topic_duration_minutes: "Global default condition for which a topic is considered new."
|
default_other_new_topic_duration_minutes: "Global default condition for which a topic is considered new."
|
||||||
default_other_auto_track_topics_after_msecs: "Global default time before a topic is automatically tracked."
|
default_other_auto_track_topics_after_msecs: "Global default time before a topic is automatically tracked."
|
||||||
|
default_other_notification_level_when_replying: "Global default notification level when the user replies to a topic."
|
||||||
default_other_external_links_in_new_tab: "Open external links in a new tab by default."
|
default_other_external_links_in_new_tab: "Open external links in a new tab by default."
|
||||||
default_other_enable_quoting: "Enable quote reply for highlighted text by default."
|
default_other_enable_quoting: "Enable quote reply for highlighted text by default."
|
||||||
default_other_dynamic_favicon: "Show new/updated topic count on browser icon by default."
|
default_other_dynamic_favicon: "Show new/updated topic count on browser icon by default."
|
||||||
|
|
|
@ -1250,6 +1250,9 @@ user_preferences:
|
||||||
default_other_auto_track_topics_after_msecs:
|
default_other_auto_track_topics_after_msecs:
|
||||||
enum: 'AutoTrackDurationSiteSetting'
|
enum: 'AutoTrackDurationSiteSetting'
|
||||||
default: 240000
|
default: 240000
|
||||||
|
default_other_notification_level_when_replying:
|
||||||
|
enum: 'NotificationLevelWhenReplyingSiteSetting'
|
||||||
|
default: 2
|
||||||
default_other_external_links_in_new_tab: false
|
default_other_external_links_in_new_tab: false
|
||||||
default_other_enable_quoting: true
|
default_other_enable_quoting: true
|
||||||
default_other_dynamic_favicon: false
|
default_other_dynamic_favicon: false
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddNotificationLevelWhenReplying < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :user_options, :notification_level_when_replying, :integer
|
||||||
|
end
|
||||||
|
end
|
|
@ -452,9 +452,11 @@ class PostCreator
|
||||||
end
|
end
|
||||||
|
|
||||||
if @user.staged
|
if @user.staged
|
||||||
TopicUser.auto_watch(@user.id, @topic.id)
|
TopicUser.auto_notification_for_staging(@user.id, @topic.id, TopicUser.notification_reasons[:auto_watch])
|
||||||
|
elsif @user.user_option.notification_level_when_replying === NotificationLevels.topic_levels[:watching]
|
||||||
|
TopicUser.auto_notification(@user.id, @topic.id, TopicUser.notification_reasons[:created_post], NotificationLevels.topic_levels[:watching])
|
||||||
else
|
else
|
||||||
TopicUser.auto_track(@user.id, @topic.id, TopicUser.notification_reasons[:created_post])
|
TopicUser.auto_notification(@user.id, @topic.id, TopicUser.notification_reasons[:created_post], NotificationLevels.topic_levels[:tracking])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -798,6 +798,42 @@ describe PostCreator do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "topic tracking" do
|
||||||
|
it "automatically watches topic based on preference" do
|
||||||
|
user.user_option.notification_level_when_replying = 3
|
||||||
|
|
||||||
|
admin = Fabricate(:admin)
|
||||||
|
topic = PostCreator.create(admin,
|
||||||
|
title: "this is the title of a topic created by an admin for watching notification",
|
||||||
|
raw: "this is the content of a topic created by an admin for keeping a watching notification state on a topic ;)"
|
||||||
|
)
|
||||||
|
|
||||||
|
post = PostCreator.create(user,
|
||||||
|
topic_id: topic.topic_id,
|
||||||
|
raw: "this is a reply to set the tracking state to watching ;)"
|
||||||
|
)
|
||||||
|
topic_user = TopicUser.find_by(user_id: user.id, topic_id: post.topic_id)
|
||||||
|
expect(topic_user.notification_level).to eq(TopicUser.notification_levels[:watching])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "topic notification level remains tracking based on preference" do
|
||||||
|
user.user_option.notification_level_when_replying = 2
|
||||||
|
|
||||||
|
admin = Fabricate(:admin)
|
||||||
|
topic = PostCreator.create(admin,
|
||||||
|
title: "this is the title of a topic created by an admin for tracking notification",
|
||||||
|
raw: "this is the content of a topic created by an admin for keeping a tracking notification state on a topic ;)"
|
||||||
|
)
|
||||||
|
|
||||||
|
post = PostCreator.create(user,
|
||||||
|
topic_id: topic.topic_id,
|
||||||
|
raw: "this is a reply to set the tracking state to tracking ;)"
|
||||||
|
)
|
||||||
|
topic_user = TopicUser.find_by(user_id: user.id, topic_id: post.topic_id)
|
||||||
|
expect(topic_user.notification_level).to eq(TopicUser.notification_levels[:tracking])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#create!' do
|
describe '#create!' do
|
||||||
it "should return the post if it was successfully created" do
|
it "should return the post if it was successfully created" do
|
||||||
title = "This is a valid title"
|
title = "This is a valid title"
|
||||||
|
|
|
@ -1246,6 +1246,7 @@ describe User do
|
||||||
|
|
||||||
SiteSetting.default_other_new_topic_duration_minutes = -1 # not viewed
|
SiteSetting.default_other_new_topic_duration_minutes = -1 # not viewed
|
||||||
SiteSetting.default_other_auto_track_topics_after_msecs = 0 # immediately
|
SiteSetting.default_other_auto_track_topics_after_msecs = 0 # immediately
|
||||||
|
SiteSetting.default_other_notification_level_when_replying = 3 # immediately
|
||||||
SiteSetting.default_other_external_links_in_new_tab = true
|
SiteSetting.default_other_external_links_in_new_tab = true
|
||||||
SiteSetting.default_other_enable_quoting = false
|
SiteSetting.default_other_enable_quoting = false
|
||||||
SiteSetting.default_other_dynamic_favicon = true
|
SiteSetting.default_other_dynamic_favicon = true
|
||||||
|
@ -1273,6 +1274,7 @@ describe User do
|
||||||
expect(options.email_direct).to eq(false)
|
expect(options.email_direct).to eq(false)
|
||||||
expect(options.new_topic_duration_minutes).to eq(-1)
|
expect(options.new_topic_duration_minutes).to eq(-1)
|
||||||
expect(options.auto_track_topics_after_msecs).to eq(0)
|
expect(options.auto_track_topics_after_msecs).to eq(0)
|
||||||
|
expect(options.notification_level_when_replying).to eq(3)
|
||||||
|
|
||||||
expect(CategoryUser.lookup(user, :watching).pluck(:category_id)).to eq([1])
|
expect(CategoryUser.lookup(user, :watching).pluck(:category_id)).to eq([1])
|
||||||
expect(CategoryUser.lookup(user, :tracking).pluck(:category_id)).to eq([2])
|
expect(CategoryUser.lookup(user, :tracking).pluck(:category_id)).to eq([2])
|
||||||
|
|
|
@ -19,6 +19,7 @@ describe UserSerializer do
|
||||||
it "serializes options correctly" do
|
it "serializes options correctly" do
|
||||||
# so we serialize more stuff
|
# so we serialize more stuff
|
||||||
SiteSetting.default_other_auto_track_topics_after_msecs = 0
|
SiteSetting.default_other_auto_track_topics_after_msecs = 0
|
||||||
|
SiteSetting.default_other_notification_level_when_replying = 3
|
||||||
SiteSetting.default_other_new_topic_duration_minutes = 60*24
|
SiteSetting.default_other_new_topic_duration_minutes = 60*24
|
||||||
|
|
||||||
user = Fabricate.build(:user,
|
user = Fabricate.build(:user,
|
||||||
|
@ -32,6 +33,7 @@ describe UserSerializer do
|
||||||
expect(json[:user_option][:dynamic_favicon]).to eq(true)
|
expect(json[:user_option][:dynamic_favicon]).to eq(true)
|
||||||
expect(json[:user_option][:new_topic_duration_minutes]).to eq(60*24)
|
expect(json[:user_option][:new_topic_duration_minutes]).to eq(60*24)
|
||||||
expect(json[:user_option][:auto_track_topics_after_msecs]).to eq(0)
|
expect(json[:user_option][:auto_track_topics_after_msecs]).to eq(0)
|
||||||
|
expect(json[:user_option][:notification_level_when_replying]).to eq(3)
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -71,6 +71,7 @@ describe UserUpdater do
|
||||||
digest_after_minutes: "45",
|
digest_after_minutes: "45",
|
||||||
new_topic_duration_minutes: 100,
|
new_topic_duration_minutes: 100,
|
||||||
auto_track_topics_after_msecs: 101,
|
auto_track_topics_after_msecs: 101,
|
||||||
|
notification_level_when_replying: 3,
|
||||||
email_in_reply_to: false
|
email_in_reply_to: false
|
||||||
)
|
)
|
||||||
expect(val).to be_truthy
|
expect(val).to be_truthy
|
||||||
|
@ -83,6 +84,7 @@ describe UserUpdater do
|
||||||
expect(user.user_option.digest_after_minutes).to eq 45
|
expect(user.user_option.digest_after_minutes).to eq 45
|
||||||
expect(user.user_option.new_topic_duration_minutes).to eq 100
|
expect(user.user_option.new_topic_duration_minutes).to eq 100
|
||||||
expect(user.user_option.auto_track_topics_after_msecs).to eq 101
|
expect(user.user_option.auto_track_topics_after_msecs).to eq 101
|
||||||
|
expect(user.user_option.notification_level_when_replying).to eq 3
|
||||||
expect(user.user_option.email_in_reply_to).to eq false
|
expect(user.user_option.email_in_reply_to).to eq false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue