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:
Sam 2016-10-11 10:05:37 +11:00 committed by GitHub
commit ea1f0683c8
17 changed files with 127 additions and 27 deletions

View File

@ -3,6 +3,7 @@ import CanCheckEmails from 'discourse/mixins/can-check-emails';
import { popupAjaxError } from 'discourse/lib/ajax-error';
import computed from "ember-addons/ember-computed-decorators";
import { cook } from 'discourse/lib/text';
import { NotificationLevels } from 'discourse/lib/notification-levels';
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_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 },
{ 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 },

View File

@ -222,6 +222,7 @@ const User = RestModel.extend({
'digest_after_minutes',
'new_topic_duration_minutes',
'auto_track_topics_after_msecs',
'notification_level_when_replying',
'like_notification_frequency',
'include_tl0_in_digests'
].forEach(s => {

View File

@ -234,6 +234,11 @@
{{combo-box valueAttribute="value" content=autoTrackDurations value=model.user_option.auto_track_topics_after_msecs}}
</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">
<label>{{i18n 'user.like_notification_frequency.title'}}</label>
{{combo-box valueAttribute="value" content=likeNotificationFrequencies value=model.user_option.like_notification_frequency}}

View File

@ -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

View File

@ -37,24 +37,24 @@ class TopicUser < ActiveRecord::Base
auto_track_tag: 12)
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?
change(user_id, topic_id,
notification_level: notification_levels[:tracking],
notification_level: notification_level,
notifications_reason_id: reason
)
MessageBus.publish("/topic/#{topic_id}", {
notification_level_change: notification_levels[:tracking],
notification_level_change: notification_level,
notifications_reason_id: reason
}, user_ids: [user_id])
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.notification_level = notification_levels[:watching]
topic_user.notifications_reason_id = notification_reasons[:auto_watch]
topic_user.notifications_reason_id = reason
topic_user.save
end

View File

@ -38,6 +38,7 @@ class UserOption < ActiveRecord::Base
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.notification_level_when_replying = SiteSetting.default_other_notification_level_when_replying
self.like_notification_frequency = SiteSetting.default_other_like_notification_frequency
@ -129,26 +130,27 @@ end
#
# Table name: user_options
#
# user_id :integer not null, primary key
# email_always :boolean default(FALSE), not null
# mailing_list_mode :boolean default(FALSE), not null
# email_digests :boolean
# email_direct :boolean default(TRUE), not null
# email_private_messages :boolean default(TRUE), not null
# external_links_in_new_tab :boolean default(FALSE), not null
# enable_quoting :boolean default(TRUE), not null
# dynamic_favicon :boolean default(FALSE), not null
# disable_jump_reply :boolean default(FALSE), not null
# automatically_unpin_topics :boolean default(TRUE), not null
# digest_after_minutes :integer
# auto_track_topics_after_msecs :integer
# new_topic_duration_minutes :integer
# last_redirected_to_top_at :datetime
# email_previous_replies :integer default(2), not null
# email_in_reply_to :boolean default(TRUE), not null
# like_notification_frequency :integer default(1), not null
# include_tl0_in_digests :boolean default(FALSE)
# mailing_list_mode_frequency :integer default(0), not null
# user_id :integer not null, primary key
# email_always :boolean default(FALSE), not null
# mailing_list_mode :boolean default(FALSE), not null
# email_digests :boolean
# email_direct :boolean default(TRUE), not null
# email_private_messages :boolean default(TRUE), not null
# external_links_in_new_tab :boolean default(FALSE), not null
# enable_quoting :boolean default(TRUE), not null
# dynamic_favicon :boolean default(FALSE), not null
# disable_jump_reply :boolean default(FALSE), not null
# automatically_unpin_topics :boolean default(TRUE), not null
# digest_after_minutes :integer
# auto_track_topics_after_msecs :integer
# notification_level_when_replying :integer
# new_topic_duration_minutes :integer
# last_redirected_to_top_at :datetime
# email_previous_replies :integer default(2), not null
# email_in_reply_to :boolean default(TRUE), not null
# like_notification_frequency :integer default(1), not null
# include_tl0_in_digests :boolean default(FALSE)
# mailing_list_mode_frequency :integer default(0), not null
#
# Indexes
#

View File

@ -13,6 +13,7 @@ class UserOptionSerializer < ApplicationSerializer
:digest_after_minutes,
:automatically_unpin_topics,
:auto_track_topics_after_msecs,
:notification_level_when_replying,
:new_topic_duration_minutes,
:email_previous_replies,
: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
end
def notification_level_when_replying
object.notification_level_when_replying || SiteSetting.default_other_notification_level_when_replying
end
def new_topic_duration_minutes
object.new_topic_duration_minutes || SiteSetting.default_other_new_topic_duration_minutes
end

View File

@ -29,6 +29,7 @@ class UserUpdater
:digest_after_minutes,
:new_topic_duration_minutes,
:auto_track_topics_after_msecs,
:notification_level_when_replying,
:email_previous_replies,
:email_in_reply_to,
:like_notification_frequency,

View File

@ -740,6 +740,8 @@ en:
after_5_minutes: "after 5 minutes"
after_10_minutes: "after 10 minutes"
notification_level_when_replying: "When I post in a topic, set that topic to"
invited:
search: "type to search invites..."
title: "Invites"

View File

@ -1368,6 +1368,7 @@ en:
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_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_enable_quoting: "Enable quote reply for highlighted text by default."
default_other_dynamic_favicon: "Show new/updated topic count on browser icon by default."

View File

@ -1250,6 +1250,9 @@ user_preferences:
default_other_auto_track_topics_after_msecs:
enum: 'AutoTrackDurationSiteSetting'
default: 240000
default_other_notification_level_when_replying:
enum: 'NotificationLevelWhenReplyingSiteSetting'
default: 2
default_other_external_links_in_new_tab: false
default_other_enable_quoting: true
default_other_dynamic_favicon: false

View File

@ -0,0 +1,5 @@
class AddNotificationLevelWhenReplying < ActiveRecord::Migration
def change
add_column :user_options, :notification_level_when_replying, :integer
end
end

View File

@ -452,9 +452,11 @@ class PostCreator
end
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
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

View File

@ -798,6 +798,42 @@ describe PostCreator do
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
it "should return the post if it was successfully created" do
title = "This is a valid title"

View File

@ -1246,6 +1246,7 @@ describe User do
SiteSetting.default_other_new_topic_duration_minutes = -1 # not viewed
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_enable_quoting = false
SiteSetting.default_other_dynamic_favicon = true
@ -1273,6 +1274,7 @@ describe User do
expect(options.email_direct).to eq(false)
expect(options.new_topic_duration_minutes).to eq(-1)
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, :tracking).pluck(:category_id)).to eq([2])

View File

@ -19,6 +19,7 @@ describe UserSerializer do
it "serializes options correctly" do
# so we serialize more stuff
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
user = Fabricate.build(:user,
@ -32,6 +33,7 @@ describe UserSerializer do
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][:auto_track_topics_after_msecs]).to eq(0)
expect(json[:user_option][:notification_level_when_replying]).to eq(3)
end
end

View File

@ -71,6 +71,7 @@ describe UserUpdater do
digest_after_minutes: "45",
new_topic_duration_minutes: 100,
auto_track_topics_after_msecs: 101,
notification_level_when_replying: 3,
email_in_reply_to: false
)
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.new_topic_duration_minutes).to eq 100
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
end