thredded 0.8.4 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +48 -9
- data/app/assets/images/thredded/breadcrumb-chevron.svg +1 -1
- data/app/assets/images/thredded/follow.svg +1 -1
- data/app/assets/images/thredded/moderation.svg +1 -4
- data/app/assets/images/thredded/private-messages.svg +1 -4
- data/app/assets/images/thredded/settings.svg +1 -4
- data/app/assets/images/thredded/unfollow.svg +1 -1
- data/app/assets/javascripts/thredded/components/time_stamps.es6 +1 -1
- data/app/assets/javascripts/thredded/components/user_preferences_form.es6 +26 -49
- data/app/assets/javascripts/thredded/dependencies.js +2 -1
- data/app/assets/stylesheets/thredded/base/_grid.scss +4 -4
- data/app/assets/stylesheets/thredded/base/_typography.scss +18 -0
- data/app/assets/stylesheets/thredded/components/_base.scss +4 -0
- data/app/assets/stylesheets/thredded/components/_currently-online.scss +4 -0
- data/app/assets/stylesheets/thredded/components/_form-list.scss +5 -0
- data/app/assets/stylesheets/thredded/components/_messageboard.scss +3 -0
- data/app/assets/stylesheets/thredded/components/_post-form.scss +7 -4
- data/app/assets/stylesheets/thredded/components/_post.scss +3 -0
- data/app/assets/stylesheets/thredded/components/_topic-delete.scss +3 -0
- data/app/assets/stylesheets/thredded/components/_topic-header.scss +20 -0
- data/app/assets/stylesheets/thredded/components/_topics.scss +13 -1
- data/app/assets/stylesheets/thredded/layout/_main-navigation.scss +1 -1
- data/app/assets/stylesheets/thredded/layout/_navigation.scss +3 -1
- data/app/assets/stylesheets/thredded/layout/_search-navigation.scss +4 -0
- data/app/assets/stylesheets/thredded/layout/_user-navigation.scss +3 -0
- data/app/commands/thredded/at_notification_extractor.rb +1 -2
- data/app/commands/thredded/autofollow_mentioned_users.rb +0 -1
- data/app/commands/thredded/notify_following_users.rb +20 -11
- data/app/commands/thredded/notify_private_topic_users.rb +12 -28
- data/app/controllers/thredded/application_controller.rb +8 -4
- data/app/controllers/thredded/messageboards_controller.rb +2 -2
- data/app/controllers/thredded/moderation_controller.rb +12 -13
- data/app/controllers/thredded/posts_controller.rb +1 -1
- data/app/controllers/thredded/preferences_controller.rb +11 -7
- data/app/controllers/thredded/private_topics_controller.rb +13 -9
- data/app/controllers/thredded/topics_controller.rb +20 -12
- data/app/forms/thredded/user_preferences_form.rb +23 -4
- data/app/helpers/thredded/application_helper.rb +11 -1
- data/app/mailers/thredded/post_mailer.rb +2 -3
- data/app/mailers/thredded/private_topic_mailer.rb +2 -3
- data/app/models/concerns/thredded/content_moderation_state.rb +1 -1
- data/app/models/concerns/thredded/notifier_preference.rb +18 -0
- data/app/models/concerns/thredded/post_common.rb +5 -1
- data/{lib → app/models/concerns}/thredded/search_parser.rb +0 -0
- data/app/models/concerns/thredded/topic_common.rb +3 -3
- data/{lib → app/models/concerns}/thredded/topics_search.rb +2 -3
- data/app/models/thredded/messageboard.rb +11 -0
- data/app/models/thredded/messageboard_notifications_for_followed_topics.rb +29 -0
- data/app/models/thredded/notifications_for_followed_topics.rb +22 -0
- data/app/models/thredded/notifications_for_private_topics.rb +21 -0
- data/app/models/thredded/post.rb +5 -3
- data/app/models/thredded/post_moderation_record.rb +1 -1
- data/app/models/thredded/private_post.rb +1 -1
- data/app/models/thredded/private_topic.rb +8 -4
- data/app/models/thredded/stats.rb +1 -1
- data/app/models/thredded/topic.rb +10 -7
- data/app/models/thredded/user_detail.rb +1 -1
- data/app/models/thredded/user_extender.rb +3 -1
- data/app/models/thredded/user_preference.rb +16 -5
- data/app/models/thredded/user_private_topic_read_state.rb +1 -1
- data/app/models/thredded/user_topic_read_state.rb +1 -1
- data/app/notifiers/thredded/base_notifier.rb +28 -0
- data/app/notifiers/thredded/email_notifier.rb +34 -0
- data/app/policies/thredded/post_policy.rb +3 -4
- data/app/policies/thredded/private_post_policy.rb +2 -3
- data/app/policies/thredded/topic_policy.rb +1 -2
- data/app/view_hooks/thredded/all_view_hooks.rb +0 -3
- data/app/view_models/thredded/base_topic_view.rb +0 -1
- data/app/view_models/thredded/post_view.rb +0 -1
- data/app/view_models/thredded/posts_page_view.rb +1 -4
- data/app/view_models/thredded/private_topic_view.rb +3 -1
- data/app/view_models/thredded/private_topics_page_view.rb +8 -3
- data/app/view_models/thredded/topic_posts_page_view.rb +1 -2
- data/app/view_models/thredded/topic_view.rb +3 -3
- data/app/view_models/thredded/topics_page_view.rb +0 -1
- data/app/views/thredded/messageboard_groups/new.html.erb +5 -1
- data/app/views/thredded/messageboards/_form.html.erb +7 -2
- data/app/views/thredded/posts/_form.html.erb +2 -1
- data/app/views/thredded/posts/edit.html.erb +3 -2
- data/app/views/thredded/posts_common/_form.html.erb +6 -2
- data/app/views/thredded/preferences/_form.html.erb +41 -29
- data/app/views/thredded/private_posts/_form.html.erb +1 -0
- data/app/views/thredded/private_topics/_form.html.erb +3 -2
- data/app/views/thredded/private_topics/_header.html.erb +4 -0
- data/app/views/thredded/private_topics/_no_private_topics.html.erb +1 -1
- data/app/views/thredded/private_topics/_private_topic.html.erb +5 -2
- data/app/views/thredded/private_topics/edit.html.erb +2 -1
- data/app/views/thredded/private_topics/header/_participant.html.erb +1 -0
- data/app/views/thredded/private_topics/index.html.erb +6 -5
- data/app/views/thredded/private_topics/new.html.erb +0 -1
- data/app/views/thredded/private_topics/private_topic/_participant.html.erb +1 -0
- data/app/views/thredded/private_topics/show.html.erb +1 -3
- data/app/views/thredded/topics/_form.html.erb +1 -1
- data/app/views/thredded/topics/show.html.erb +4 -5
- data/config/locales/en.yml +22 -9
- data/config/locales/pt-BR.yml +22 -10
- data/config/routes.rb +1 -1
- data/db/migrate/20160329231848_create_thredded.rb +23 -3
- data/db/upgrade_migrations/20160410111522_upgrade_v0_2_to_v0_3.rb +1 -1
- data/db/upgrade_migrations/20161113161801_upgrade_v0_8_to_v0_9.rb +56 -0
- data/lib/generators/thredded/install/templates/initializer.rb +28 -0
- data/lib/thredded.rb +32 -8
- data/lib/thredded/content_formatter.rb +3 -2
- data/lib/thredded/database_seeder.rb +11 -8
- data/lib/thredded/db_tools.rb +82 -0
- data/lib/thredded/html_pipeline/wrap_iframes_filter.rb +12 -0
- data/lib/thredded/version.rb +1 -1
- metadata +18 -8
- data/app/models/thredded/null_preference.rb +0 -16
|
@@ -9,12 +9,12 @@ module Thredded
|
|
|
9
9
|
validate :validate_children
|
|
10
10
|
|
|
11
11
|
delegate :follow_topics_on_mention, :follow_topics_on_mention=,
|
|
12
|
-
:
|
|
13
|
-
:
|
|
12
|
+
:messageboard_notifications_for_followed_topics_attributes=,
|
|
13
|
+
:notifications_for_followed_topics_attributes=,
|
|
14
|
+
:notifications_for_private_topics_attributes=,
|
|
14
15
|
to: :user_preference
|
|
15
16
|
|
|
16
17
|
delegate :follow_topics_on_mention, :follow_topics_on_mention=,
|
|
17
|
-
:followed_topic_emails, :followed_topic_emails=,
|
|
18
18
|
to: :user_messageboard_preference,
|
|
19
19
|
prefix: :messageboard
|
|
20
20
|
|
|
@@ -36,6 +36,25 @@ module Thredded
|
|
|
36
36
|
true
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
+
def notifications_for_private_topics
|
|
40
|
+
for_every_notifier(user_preference.notifications_for_private_topics)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def notifications_for_followed_topics
|
|
44
|
+
for_every_notifier(user_preference.notifications_for_followed_topics)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def messageboard_notifications_for_followed_topics
|
|
48
|
+
return nil unless messageboard
|
|
49
|
+
for_every_notifier(user_preference.messageboard_notifications_for_followed_topics.for_messageboard(messageboard))
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def for_every_notifier(prefs)
|
|
53
|
+
Thredded.notifiers.map do |notifier|
|
|
54
|
+
prefs.find { |n| n.notifier_key == notifier.key } || prefs.build(notifier_key: notifier.key)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
39
58
|
private
|
|
40
59
|
|
|
41
60
|
# @return [Thredded::UserPreference]
|
|
@@ -52,7 +71,7 @@ module Thredded
|
|
|
52
71
|
|
|
53
72
|
def validate_children
|
|
54
73
|
promote_errors(user_preference.errors) if user_preference.invalid?
|
|
55
|
-
if messageboard && user_messageboard_preference.invalid?
|
|
74
|
+
if messageboard && user_messageboard_preference.invalid? # rubocop:disable Style/GuardClause
|
|
56
75
|
promote_errors(user_messageboard_preference.errors, :messageboard)
|
|
57
76
|
end
|
|
58
77
|
end
|
|
@@ -52,11 +52,21 @@ module Thredded
|
|
|
52
52
|
def time_ago(datetime, default: '-')
|
|
53
53
|
timeago_tag datetime,
|
|
54
54
|
lang: I18n.locale.to_s.downcase,
|
|
55
|
-
format: ->
|
|
55
|
+
format: ->(t, _opts) { t.year == Time.current.year ? :short : :long },
|
|
56
56
|
nojs: true,
|
|
57
|
+
date_only: false,
|
|
57
58
|
default: default
|
|
58
59
|
end
|
|
59
60
|
|
|
61
|
+
# Override the default timeago_tag_content from rails-timeago
|
|
62
|
+
def timeago_tag_content(time, time_options = {})
|
|
63
|
+
if time_options[:nojs] && (time_options[:limit].nil? || time_options[:limit] < time)
|
|
64
|
+
t 'thredded.time_ago', time: time_ago_in_words(time)
|
|
65
|
+
else
|
|
66
|
+
I18n.l time.to_date, format: time_options[:format]
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
60
70
|
def paginate(collection, args = {})
|
|
61
71
|
super(collection, args.reverse_merge(views_prefix: 'thredded'))
|
|
62
72
|
end
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
require_dependency 'thredded/topic_email_view'
|
|
3
2
|
module Thredded
|
|
4
3
|
class PostMailer < Thredded::BaseMailer
|
|
5
4
|
def post_notification(post_id, emails)
|
|
6
|
-
@post = find_record Post, post_id
|
|
7
|
-
email_details = TopicEmailView.new(@post.postable)
|
|
5
|
+
@post = find_record Thredded::Post, post_id
|
|
6
|
+
email_details = Thredded::TopicEmailView.new(@post.postable)
|
|
8
7
|
headers['X-SMTPAPI'] = email_details.smtp_api_tag('post_notification')
|
|
9
8
|
|
|
10
9
|
mail from: email_details.no_reply,
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
require_dependency 'thredded/topic_email_view'
|
|
3
2
|
module Thredded
|
|
4
3
|
class PrivateTopicMailer < Thredded::BaseMailer
|
|
5
4
|
def message_notification(private_topic_id, emails)
|
|
6
|
-
@topic = find_record PrivateTopic, private_topic_id
|
|
7
|
-
email_details = TopicEmailView.new(@topic)
|
|
5
|
+
@topic = find_record Thredded::PrivateTopic, private_topic_id
|
|
6
|
+
email_details = Thredded::TopicEmailView.new(@topic)
|
|
8
7
|
headers['X-SMTPAPI'] = email_details.smtp_api_tag('private_topic_mailer')
|
|
9
8
|
|
|
10
9
|
mail from: email_details.no_reply,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Thredded
|
|
3
|
+
module NotifierPreference
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
delegate :human_name, to: :notifier, prefix: true
|
|
8
|
+
|
|
9
|
+
def self.detect_or_default(prefs, notifier)
|
|
10
|
+
(prefs && prefs.find { |pref| pref.notifier_key == notifier.key }) || default(notifier)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def notifier
|
|
15
|
+
@notifier ||= Thredded.notifiers.find { |notifier| notifier.key == notifier_key }
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -28,10 +28,14 @@ module Thredded
|
|
|
28
28
|
|
|
29
29
|
# @param view_context [Object] the context of the rendering view.
|
|
30
30
|
# @return [String] formatted and sanitized html-safe post content.
|
|
31
|
-
def filtered_content(view_context, users_provider: ->
|
|
31
|
+
def filtered_content(view_context, users_provider: ->(names) { readers_from_user_names(names) })
|
|
32
32
|
Thredded::ContentFormatter.new(view_context, users_provider: users_provider).format_content(content)
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
def first_post_in_topic?
|
|
36
|
+
postable.first_post == self
|
|
37
|
+
end
|
|
38
|
+
|
|
35
39
|
private
|
|
36
40
|
|
|
37
41
|
def ensure_user_detail
|
|
File without changes
|
|
@@ -10,7 +10,7 @@ module Thredded
|
|
|
10
10
|
foreign_key: 'last_user_id'
|
|
11
11
|
|
|
12
12
|
scope :order_recently_posted_first, -> { order(last_post_at: :desc, id: :desc) }
|
|
13
|
-
scope :on_page, ->
|
|
13
|
+
scope :on_page, ->(page_num) { page(page_num) }
|
|
14
14
|
|
|
15
15
|
validates :hash_id, presence: true, uniqueness: true
|
|
16
16
|
validates :posts_count, numericality: true
|
|
@@ -25,11 +25,11 @@ module Thredded
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def user
|
|
28
|
-
super || NullUser.new
|
|
28
|
+
super || Thredded::NullUser.new
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def last_user
|
|
32
|
-
super || NullUser.new
|
|
32
|
+
super || Thredded::NullUser.new
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def private?
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
require 'thredded/search_parser'
|
|
3
2
|
module Thredded
|
|
4
3
|
class TopicsSearch
|
|
5
4
|
def initialize(query, scope)
|
|
6
|
-
@terms = SearchParser.new(query).parse
|
|
5
|
+
@terms = Thredded::SearchParser.new(query).parse
|
|
7
6
|
@scope = scope
|
|
8
7
|
|
|
9
8
|
@search_categories = @search_users = @search_text = nil
|
|
@@ -12,7 +11,7 @@ module Thredded
|
|
|
12
11
|
# @return [ActiveRecord::Relation<Thredded::Topic>]
|
|
13
12
|
def search
|
|
14
13
|
if categories.present?
|
|
15
|
-
@scope = @scope.joins(:topic_categories).merge(TopicCategory.where(category_id: categories))
|
|
14
|
+
@scope = @scope.joins(:topic_categories).merge(Thredded::TopicCategory.where(category_id: categories))
|
|
16
15
|
end
|
|
17
16
|
if text.present? || users.present?
|
|
18
17
|
[search_topics, search_posts].compact.reduce(:union)
|
|
@@ -81,6 +81,17 @@ module Thredded
|
|
|
81
81
|
order(topics_count: :desc)
|
|
82
82
|
}
|
|
83
83
|
# rubocop:enable Style/Lambda
|
|
84
|
+
|
|
85
|
+
# Finds the messageboard by its slug or ID, or raises Thredded::Errors::MessageboardNotFound.
|
|
86
|
+
# @param slug_or_id [String]
|
|
87
|
+
# @return [Thredded::Messageboard]
|
|
88
|
+
# @raise [Thredded::Errors::MessageboardNotFound] if the messageboard with the given slug does not exist.
|
|
89
|
+
def self.friendly_find!(slug_or_id)
|
|
90
|
+
friendly.find(slug_or_id)
|
|
91
|
+
rescue ActiveRecord::RecordNotFound
|
|
92
|
+
raise Thredded::Errors::MessageboardNotFound
|
|
93
|
+
end
|
|
94
|
+
|
|
84
95
|
def last_user
|
|
85
96
|
last_topic.try(:last_user)
|
|
86
97
|
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Thredded
|
|
3
|
+
class MessageboardNotificationsForFollowedTopics < ActiveRecord::Base
|
|
4
|
+
belongs_to :user_preference,
|
|
5
|
+
primary_key: :user_id,
|
|
6
|
+
foreign_key: :user_id,
|
|
7
|
+
inverse_of: :messageboard_notifications_for_followed_topics
|
|
8
|
+
belongs_to :user,
|
|
9
|
+
class_name: Thredded.user_class,
|
|
10
|
+
inverse_of: :thredded_user_messageboard_preferences
|
|
11
|
+
belongs_to :messageboard
|
|
12
|
+
scope :for_messageboard, ->(messageboard) { where(messageboard_id: messageboard.id) }
|
|
13
|
+
|
|
14
|
+
validates :user_id, presence: true
|
|
15
|
+
validates :messageboard_id, presence: true
|
|
16
|
+
|
|
17
|
+
def self.in(messageboard)
|
|
18
|
+
where(messageboard_id: messageboard.id)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
include Thredded::NotifierPreference
|
|
22
|
+
|
|
23
|
+
def self.default(_notifier)
|
|
24
|
+
# could be moved to `notifier.defaults(:notifications_for_followed_topics)` or
|
|
25
|
+
# `notifier.defaults(:messageboard_notifications_for_followed_topics)`
|
|
26
|
+
Thredded::BaseNotifier::NotificationsDefault.new(true)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Thredded
|
|
3
|
+
class NotificationsForFollowedTopics < ActiveRecord::Base
|
|
4
|
+
belongs_to :user,
|
|
5
|
+
class_name: Thredded.user_class,
|
|
6
|
+
inverse_of: :thredded_notifications_for_followed_topics
|
|
7
|
+
belongs_to :messageboard # or is global
|
|
8
|
+
belongs_to :user_preference,
|
|
9
|
+
primary_key: :user_id,
|
|
10
|
+
foreign_key: :user_id,
|
|
11
|
+
inverse_of: :notifications_for_followed_topics
|
|
12
|
+
|
|
13
|
+
validates :user_id, presence: true
|
|
14
|
+
|
|
15
|
+
include Thredded::NotifierPreference
|
|
16
|
+
|
|
17
|
+
def self.default(_notifier)
|
|
18
|
+
# could be moved to `notifier.defaults(:notifications_for_followed_topics)`
|
|
19
|
+
Thredded::BaseNotifier::NotificationsDefault.new(true)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Thredded
|
|
3
|
+
class NotificationsForPrivateTopics < ActiveRecord::Base
|
|
4
|
+
belongs_to :user,
|
|
5
|
+
class_name: Thredded.user_class,
|
|
6
|
+
inverse_of: :thredded_notifications_for_private_topics
|
|
7
|
+
belongs_to :user_preference,
|
|
8
|
+
primary_key: :user_id,
|
|
9
|
+
foreign_key: :user_id,
|
|
10
|
+
inverse_of: :notifications_for_private_topics
|
|
11
|
+
|
|
12
|
+
validates :user_id, presence: true
|
|
13
|
+
|
|
14
|
+
include Thredded::NotifierPreference
|
|
15
|
+
|
|
16
|
+
def self.default(_notifier)
|
|
17
|
+
# could be moved to `notifier.defaults(:notifications_for_private_topics)`
|
|
18
|
+
Thredded::BaseNotifier::NotificationsDefault.new(true)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/app/models/thredded/post.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module Thredded
|
|
3
3
|
class Post < ActiveRecord::Base
|
|
4
|
-
include PostCommon
|
|
5
|
-
include ContentModerationState
|
|
4
|
+
include Thredded::PostCommon
|
|
5
|
+
include Thredded::ContentModerationState
|
|
6
6
|
|
|
7
7
|
belongs_to :user,
|
|
8
8
|
class_name: Thredded.user_class,
|
|
@@ -54,7 +54,9 @@ module Thredded
|
|
|
54
54
|
def auto_follow_and_notify
|
|
55
55
|
return unless user
|
|
56
56
|
# need to do this in-process so that it appears to them immediately
|
|
57
|
-
|
|
57
|
+
if first_post_in_topic? ? Thredded.auto_follow_when_creating_topic : Thredded.auto_follow_when_posting_in_topic
|
|
58
|
+
UserTopicFollow.create_unless_exists(user.id, postable_id, :posted)
|
|
59
|
+
end
|
|
58
60
|
# everything else can happen later
|
|
59
61
|
AutoFollowAndNotifyJob.perform_later(id)
|
|
60
62
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module Thredded
|
|
3
3
|
class PostModerationRecord < ActiveRecord::Base
|
|
4
|
-
include ModerationState
|
|
4
|
+
include Thredded::ModerationState
|
|
5
5
|
# Rails 4 doesn't support enum _prefix
|
|
6
6
|
if Rails::VERSION::MAJOR >= 5
|
|
7
7
|
enum previous_moderation_state: moderation_states, _prefix: :previous
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module Thredded
|
|
3
3
|
class PrivateTopic < ActiveRecord::Base
|
|
4
|
-
include TopicCommon
|
|
4
|
+
include Thredded::TopicCommon
|
|
5
5
|
|
|
6
|
-
scope :for_user, ->
|
|
6
|
+
scope :for_user, ->(user) { joins(:private_users).merge(PrivateUser.where(user_id: user.id)) }
|
|
7
7
|
|
|
8
8
|
extend FriendlyId
|
|
9
9
|
friendly_id :slug_candidates,
|
|
@@ -48,8 +48,12 @@ module Thredded
|
|
|
48
48
|
|
|
49
49
|
before_validation :ensure_user_in_private_users
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
# Finds the topic by its slug or ID, or raises Thredded::Errors::PrivateTopicNotFound.
|
|
52
|
+
# @param slug_or_id [String]
|
|
53
|
+
# @return [Thredded::PrivateTopic]
|
|
54
|
+
# @raise [Thredded::Errors::PrivateTopicNotFound] if the topic with the given slug does not exist.
|
|
55
|
+
def self.friendly_find!(slug_or_id)
|
|
56
|
+
friendly.find(slug_or_id)
|
|
53
57
|
rescue ActiveRecord::RecordNotFound
|
|
54
58
|
raise Thredded::Errors::PrivateTopicNotFound
|
|
55
59
|
end
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
require 'thredded/topics_search'
|
|
3
2
|
module Thredded
|
|
4
3
|
class Topic < ActiveRecord::Base
|
|
5
|
-
include TopicCommon
|
|
6
|
-
include ContentModerationState
|
|
4
|
+
include Thredded::TopicCommon
|
|
5
|
+
include Thredded::ContentModerationState
|
|
7
6
|
|
|
8
|
-
scope :for_messageboard, ->
|
|
7
|
+
scope :for_messageboard, ->(messageboard) { where(messageboard_id: messageboard.id) }
|
|
9
8
|
|
|
10
9
|
scope :stuck, -> { where(sticky: true) }
|
|
11
10
|
scope :unstuck, -> { where(sticky: false) }
|
|
12
11
|
|
|
13
12
|
# Using `search_query` instead of `search` to avoid conflict with Ransack.
|
|
14
|
-
scope :search_query, ->
|
|
13
|
+
scope :search_query, ->(query) { ::Thredded::TopicsSearch.new(query, self).search }
|
|
15
14
|
|
|
16
15
|
scope :order_sticky_first, -> { order(sticky: :desc) }
|
|
17
16
|
|
|
@@ -77,8 +76,12 @@ module Thredded
|
|
|
77
76
|
after_commit :update_messageboard_last_topic, on: :update, if: -> { previous_changes.include?('moderation_state') }
|
|
78
77
|
after_update :update_last_user_and_time_from_last_post!, if: -> { previous_changes.include?('moderation_state') }
|
|
79
78
|
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
# Finds the topic by its slug or ID, or raises Thredded::Errors::TopicNotFound.
|
|
80
|
+
# @param slug_or_id [String]
|
|
81
|
+
# @return [Thredded::Topic]
|
|
82
|
+
# @raise [Thredded::Errors::TopicNotFound] if the topic with the given slug does not exist.
|
|
83
|
+
def self.friendly_find!(slug_or_id)
|
|
84
|
+
friendly.find(slug_or_id)
|
|
82
85
|
rescue ActiveRecord::RecordNotFound
|
|
83
86
|
raise Thredded::Errors::TopicNotFound
|
|
84
87
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module Thredded
|
|
3
3
|
class UserDetail < ActiveRecord::Base
|
|
4
|
-
include ModerationState
|
|
4
|
+
include Thredded::ModerationState
|
|
5
5
|
|
|
6
6
|
belongs_to :user, class_name: Thredded.user_class, inverse_of: :thredded_user_detail
|
|
7
7
|
validates :user_id, presence: true, uniqueness: true
|
|
@@ -9,7 +9,7 @@ module Thredded
|
|
|
9
9
|
include ::Thredded::UserPermissions::Moderate::IfModeratorColumnTrue
|
|
10
10
|
include ::Thredded::UserPermissions::Admin::IfAdminColumnTrue
|
|
11
11
|
|
|
12
|
-
included do
|
|
12
|
+
included do # rubocop:disable Metrics/BlockLength
|
|
13
13
|
with_options dependent: :nullify, foreign_key: 'user_id', inverse_of: :user do |opt|
|
|
14
14
|
opt.has_many :thredded_posts, class_name: 'Thredded::Post'
|
|
15
15
|
opt.has_many :thredded_topics, class_name: 'Thredded::Topic'
|
|
@@ -24,6 +24,8 @@ module Thredded
|
|
|
24
24
|
|
|
25
25
|
with_options dependent: :destroy, foreign_key: 'user_id', inverse_of: :user do |opt|
|
|
26
26
|
opt.has_many :thredded_user_messageboard_preferences, class_name: 'Thredded::UserMessageboardPreference'
|
|
27
|
+
opt.has_many :thredded_notifications_for_followed_topics, class_name: 'Thredded::NotificationsForFollowedTopics'
|
|
28
|
+
opt.has_many :thredded_notifications_for_private_topics, class_name: 'Thredded::NotificationsForPrivateTopics'
|
|
27
29
|
opt.has_many :thredded_private_users, class_name: 'Thredded::PrivateUser'
|
|
28
30
|
opt.has_many :thredded_topic_read_states, class_name: 'Thredded::UserTopicReadState'
|
|
29
31
|
opt.has_many :thredded_private_topic_read_states, class_name: 'Thredded::UserPrivateTopicReadState'
|
|
@@ -2,11 +2,22 @@
|
|
|
2
2
|
module Thredded
|
|
3
3
|
class UserPreference < ActiveRecord::Base
|
|
4
4
|
belongs_to :user, class_name: Thredded.user_class, inverse_of: :thredded_user_preference
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
|
|
6
|
+
with_options(inverse_of: :user_preference, primary_key: :user_id, foreign_key: :user_id,
|
|
7
|
+
dependent: :destroy) do |opt|
|
|
8
|
+
opt.has_many :messageboard_preferences,
|
|
9
|
+
class_name: 'Thredded::UserMessageboardPreference'
|
|
10
|
+
opt.has_many :messageboard_notifications_for_followed_topics,
|
|
11
|
+
class_name: 'Thredded::MessageboardNotificationsForFollowedTopics'
|
|
12
|
+
opt.has_many :notifications_for_followed_topics,
|
|
13
|
+
class_name: 'Thredded::NotificationsForFollowedTopics'
|
|
14
|
+
opt.has_many :notifications_for_private_topics,
|
|
15
|
+
class_name: 'Thredded::NotificationsForPrivateTopics'
|
|
16
|
+
end
|
|
10
17
|
validates :user_id, presence: true
|
|
18
|
+
|
|
19
|
+
accepts_nested_attributes_for :notifications_for_followed_topics,
|
|
20
|
+
:notifications_for_private_topics,
|
|
21
|
+
:messageboard_notifications_for_followed_topics
|
|
11
22
|
end
|
|
12
23
|
end
|