thredded 0.2.2 → 0.3.0
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/CHANGELOG.mkdn +63 -0
- data/Procfile +1 -0
- data/README.mkdn +42 -20
- data/app/assets/images/thredded/private-messages.svg +4 -0
- data/app/assets/images/thredded/settings.svg +4 -0
- data/app/assets/javascripts/thredded.es6 +2 -10
- data/app/assets/javascripts/thredded/{currently_online.es6 → components/currently_online.es6} +0 -0
- data/app/assets/javascripts/thredded/{post_form.es6 → components/post_form.es6} +0 -0
- data/app/assets/javascripts/thredded/{time_stamps.es6 → components/time_stamps.es6} +0 -0
- data/app/assets/javascripts/thredded/{topic_form.es6 → components/topic_form.es6} +1 -1
- data/app/assets/javascripts/thredded/components/topics.es6 +37 -0
- data/app/assets/javascripts/thredded/components/user_preferences_form.es6 +45 -0
- data/app/assets/javascripts/thredded/components/users_select.es6 +56 -0
- data/app/assets/javascripts/thredded/dependencies.js +9 -0
- data/app/assets/javascripts/thredded/thredded.es6 +1 -0
- data/app/assets/stylesheets/thredded/_base.scss +3 -2
- data/app/assets/stylesheets/thredded/_thredded.scss +4 -1
- data/app/assets/stylesheets/thredded/base/_buttons.scss +2 -1
- data/app/assets/stylesheets/thredded/base/_forms.scss +23 -18
- data/app/assets/stylesheets/thredded/base/_grid.scss +1 -1
- data/app/assets/stylesheets/thredded/base/_nav.scss +21 -0
- data/app/assets/stylesheets/thredded/base/_tables.scss +5 -14
- data/app/assets/stylesheets/thredded/base/_typography.scss +9 -4
- data/app/assets/stylesheets/thredded/base/_variables.scss +28 -9
- data/app/assets/stylesheets/thredded/components/_alerts.scss +19 -0
- data/app/assets/stylesheets/thredded/components/_currently-online.scss +1 -1
- data/app/assets/stylesheets/thredded/components/_form-list.scss +2 -4
- data/app/assets/stylesheets/thredded/components/_icons.scss +3 -0
- data/app/assets/stylesheets/thredded/components/_messageboard.scss +4 -4
- data/app/assets/stylesheets/thredded/components/_pagination.scss +2 -2
- data/app/assets/stylesheets/thredded/components/_post-form.scss +3 -0
- data/app/assets/stylesheets/thredded/components/_post.scss +14 -4
- data/app/assets/stylesheets/thredded/components/_select2.scss +79 -9
- data/app/assets/stylesheets/thredded/components/_topic-header.scss +11 -1
- data/app/assets/stylesheets/thredded/components/_topics.scss +13 -11
- data/app/assets/stylesheets/thredded/layout/_main-container.scss +3 -3
- data/app/assets/stylesheets/thredded/layout/_main-navigation.scss +11 -17
- data/app/assets/stylesheets/thredded/layout/_navigation.scss +72 -0
- data/app/assets/stylesheets/thredded/layout/_search-navigation.scss +66 -0
- data/app/assets/stylesheets/thredded/layout/_user-navigation.scss +35 -61
- data/app/commands/thredded/at_notification_extractor.rb +1 -0
- data/app/commands/thredded/members_marked_notified.rb +1 -0
- data/app/commands/thredded/messageboard_destroyer.rb +7 -2
- data/app/commands/thredded/notify_mentioned_users.rb +8 -21
- data/app/commands/thredded/notify_private_topic_users.rb +3 -5
- data/app/controllers/thredded/application_controller.rb +76 -41
- data/app/controllers/thredded/autocomplete_users_controller.rb +46 -0
- data/app/controllers/thredded/messageboards_controller.rb +8 -5
- data/app/controllers/thredded/posts_controller.rb +20 -22
- data/app/controllers/thredded/preferences_controller.rb +19 -14
- data/app/controllers/thredded/private_topics_controller.rb +58 -23
- data/app/controllers/thredded/setups_controller.rb +1 -0
- data/app/controllers/thredded/theme_previews_controller.rb +24 -53
- data/app/controllers/thredded/topics_controller.rb +48 -77
- data/app/forms/thredded/private_topic_form.rb +1 -21
- data/app/forms/thredded/topic_form.rb +3 -7
- data/app/forms/thredded/user_preferences_form.rb +62 -0
- data/app/helpers/thredded/application_helper.rb +11 -12
- data/app/helpers/thredded/urls_helper.rb +103 -0
- data/app/jobs/thredded/activity_updater_job.rb +4 -3
- data/app/jobs/thredded/at_notifier_job.rb +1 -0
- data/app/jobs/thredded/notify_private_topic_users_job.rb +1 -0
- data/app/mailer_previews/thredded/base_mailer_preview.rb +101 -0
- data/app/mailer_previews/thredded/post_mailer_preview.rb +11 -0
- data/app/mailer_previews/thredded/private_post_mailer_preview.rb +11 -0
- data/app/mailer_previews/thredded/private_topic_mailer_preview.rb +15 -0
- data/app/mailers/thredded/base_mailer.rb +13 -0
- data/app/mailers/thredded/post_mailer.rb +4 -2
- data/app/mailers/thredded/private_post_mailer.rb +4 -2
- data/app/mailers/thredded/private_topic_mailer.rb +4 -2
- data/app/models/concerns/thredded/friendly_id_reserved_words_and_pagination.rb +16 -0
- data/app/models/concerns/thredded/post_common.rb +68 -63
- data/app/models/concerns/thredded/topic_common.rb +31 -8
- data/app/models/concerns/thredded/user_topic_read_state_common.rb +31 -0
- data/app/models/thredded/category.rb +1 -0
- data/app/models/thredded/messageboard.rb +24 -25
- data/app/models/thredded/messageboard_user.rb +1 -0
- data/app/models/thredded/null_preference.rb +1 -0
- data/app/models/thredded/null_user.rb +1 -6
- data/app/models/thredded/null_user_topic_read_state.rb +12 -0
- data/app/models/thredded/post.rb +6 -9
- data/app/models/thredded/post_notification.rb +1 -0
- data/app/models/thredded/private_post.rb +6 -2
- data/app/models/thredded/private_topic.rb +46 -32
- data/app/models/thredded/private_user.rb +3 -2
- data/app/models/thredded/stats.rb +1 -0
- data/app/models/thredded/topic.rb +40 -64
- data/app/models/thredded/topic_category.rb +1 -0
- data/app/models/thredded/user_detail.rb +2 -15
- data/app/models/thredded/user_extender.rb +29 -14
- data/app/models/thredded/user_messageboard_preference.rb +20 -0
- data/app/models/thredded/user_permissions/admin/if_admin_column_true.rb +1 -0
- data/app/models/thredded/user_permissions/admin/none.rb +1 -0
- data/app/models/thredded/user_permissions/message/readers_of_writeable_boards.rb +1 -0
- data/app/models/thredded/user_permissions/moderate/if_moderator_column_true.rb +1 -0
- data/app/models/thredded/user_permissions/moderate/none.rb +1 -0
- data/app/models/thredded/user_permissions/read/all.rb +1 -0
- data/app/models/thredded/user_permissions/write/all.rb +1 -0
- data/app/models/thredded/user_permissions/write/none.rb +1 -0
- data/app/models/thredded/user_preference.rb +7 -1
- data/app/models/thredded/user_private_topic_read_state.rb +12 -0
- data/app/models/thredded/user_topic_read_state.rb +12 -0
- data/app/policies/thredded/messageboard_policy.rb +27 -0
- data/app/policies/thredded/post_policy.rb +33 -0
- data/app/policies/thredded/private_post_policy.rb +29 -0
- data/app/policies/thredded/private_topic_policy.rb +23 -0
- data/app/policies/thredded/topic_policy.rb +32 -0
- data/app/view_models/thredded/base_topic_view.rb +56 -0
- data/app/view_models/thredded/post_view.rb +44 -0
- data/app/view_models/thredded/posts_page_view.rb +27 -0
- data/app/view_models/thredded/private_topic_view.rb +9 -0
- data/app/{decorators/thredded/topic_email_decorator.rb → view_models/thredded/topic_email_view.rb} +2 -1
- data/app/view_models/thredded/topic_view.rb +23 -0
- data/app/view_models/thredded/topics_page_view.rb +26 -0
- data/app/views/thredded/error_pages/forbidden.html.erb +6 -0
- data/app/views/thredded/error_pages/not_found.html.erb +6 -0
- data/app/views/thredded/messageboards/_messageboard.html.erb +13 -6
- data/app/views/thredded/messageboards/index.html.erb +2 -8
- data/app/views/thredded/messageboards/new.html.erb +8 -2
- data/app/views/thredded/post_mailer/at_notification.html.erb +3 -3
- data/app/views/thredded/post_mailer/at_notification.text.erb +1 -1
- data/app/views/thredded/posts/_content_field.html.erb +1 -1
- data/app/views/thredded/posts/_form.html.erb +5 -1
- data/app/views/thredded/posts/_post.html.erb +3 -1
- data/app/views/thredded/posts/edit.html.erb +7 -3
- data/app/views/thredded/posts_common/_form.html.erb +1 -1
- data/app/views/thredded/posts_common/_post.html.erb +14 -8
- data/app/views/thredded/preferences/_form.html.erb +37 -15
- data/app/views/thredded/preferences/_header.html.erb +1 -1
- data/app/views/thredded/preferences/edit.html.erb +4 -6
- data/app/views/thredded/private_post_mailer/at_notification.html.erb +6 -4
- data/app/views/thredded/private_posts/_form.html.erb +5 -1
- data/app/views/thredded/private_posts/_private_post.html.erb +3 -1
- data/app/views/thredded/private_topic_mailer/message_notification.html.erb +3 -7
- data/app/views/thredded/private_topic_mailer/message_notification.text.erb +1 -3
- data/app/views/thredded/private_topics/_breadcrumbs.html.erb +2 -2
- data/app/views/thredded/private_topics/_form.html.erb +15 -10
- data/app/views/thredded/private_topics/_header.html.erb +12 -0
- data/app/views/thredded/private_topics/_no_private_topics.html.erb +2 -2
- data/app/views/thredded/private_topics/_private_topic.html.erb +4 -6
- data/app/views/thredded/private_topics/edit.html.erb +32 -0
- data/app/views/thredded/private_topics/index.html.erb +5 -5
- data/app/views/thredded/private_topics/new.html.erb +1 -2
- data/app/views/thredded/private_topics/show.html.erb +12 -7
- data/app/views/thredded/search/_form.html.erb +9 -6
- data/app/views/thredded/shared/{_messageboard_topics_breadcrumbs.html.erb → _breadcrumbs.html.erb} +2 -2
- data/app/views/thredded/shared/_header.html.erb +2 -3
- data/app/views/thredded/shared/_nav.html.erb +20 -0
- data/app/views/thredded/shared/nav/_notification_preferences.html.erb +6 -0
- data/app/views/thredded/shared/nav/_private_topics.html.erb +11 -0
- data/app/views/thredded/shared/nav/_standalone.html.erb +12 -0
- data/app/views/thredded/theme_previews/_section_title.html.erb +2 -2
- data/app/views/thredded/theme_previews/show.html.erb +13 -17
- data/app/views/thredded/topics/_form.html.erb +8 -6
- data/app/views/thredded/topics/_header.html.erb +12 -0
- data/app/views/thredded/topics/_topic.html.erb +4 -8
- data/app/views/thredded/topics/_topic_form_admin_options.html.erb +1 -1
- data/app/views/thredded/topics/edit.html.erb +22 -18
- data/app/views/thredded/topics/index.html.erb +3 -3
- data/app/views/thredded/topics/new.html.erb +1 -1
- data/app/views/thredded/topics/search.html.erb +17 -5
- data/app/views/thredded/topics/show.html.erb +14 -11
- data/bin/rails +5 -0
- data/config.ru +3 -0
- data/config/i18n-tasks.yml +16 -0
- data/config/locales/en.yml +90 -0
- data/config/routes.rb +29 -15
- data/db/migrate/20160329231848_create_thredded.rb +29 -33
- data/db/seeds.rb +115 -0
- data/db/upgrade_migrations/20160410111522_upgrade_v0_2_to_v0_3.rb +59 -0
- data/heroku.gemfile +26 -0
- data/heroku.gemfile.lock +282 -0
- data/lib/generators/thredded/install/install_generator.rb +1 -0
- data/lib/generators/thredded/install/templates/initializer.rb +17 -0
- data/lib/html/pipeline/at_mention_filter.rb +2 -1
- data/lib/html/pipeline/bbcode_filter.rb +13 -4
- data/lib/tasks/thredded_tasks.rake +1 -0
- data/lib/thredded.rb +19 -17
- data/lib/thredded/at_users.rb +1 -0
- data/lib/thredded/engine.rb +14 -5
- data/lib/thredded/errors.rb +11 -11
- data/lib/thredded/main_app_route_delegator.rb +1 -0
- data/lib/thredded/search_parser.rb +2 -1
- data/lib/thredded/topics_search.rb +67 -0
- data/lib/thredded/version.rb +2 -1
- data/thredded.gemspec +12 -8
- metadata +146 -82
- data/app/assets/javascripts/thredded/users_select.es6 +0 -5
- data/app/assets/stylesheets/thredded/layout/_topic-navigation.scss +0 -53
- data/app/commands/thredded/user_reads_private_topic.rb +0 -22
- data/app/commands/thredded/user_resets_private_topic_to_unread.rb +0 -23
- data/app/decorators/thredded/base_topic_decorator.rb +0 -14
- data/app/decorators/thredded/base_user_topic_decorator.rb +0 -63
- data/app/decorators/thredded/messageboard_decorator.rb +0 -41
- data/app/decorators/thredded/post_decorator.rb +0 -40
- data/app/decorators/thredded/private_topic_decorator.rb +0 -23
- data/app/decorators/thredded/topic_decorator.rb +0 -25
- data/app/decorators/thredded/user_private_topic_decorator.rb +0 -13
- data/app/decorators/thredded/user_topic_decorator.rb +0 -37
- data/app/models/thredded/ability.rb +0 -60
- data/app/models/thredded/notification_preference.rb +0 -17
- data/app/models/thredded/null_topic.rb +0 -15
- data/app/models/thredded/null_topic_read.rb +0 -19
- data/app/models/thredded/user_topic_read.rb +0 -10
- data/app/views/thredded/shared/_notification_preferences.html.erb +0 -7
- data/app/views/thredded/shared/_top_nav.html.erb +0 -36
- data/app/views/thredded/shared/_topic_nav.html.erb +0 -22
- data/app/views/thredded/topics/_recent_topics_by_user.html.erb +0 -8
- data/app/views/thredded/topics/by_category.html.erb +0 -56
- data/app/views/thredded/topics_common/_header.html.erb +0 -6
- data/lib/thredded/messageboard_user_permissions.rb +0 -22
- data/lib/thredded/post_sql_builder.rb +0 -12
- data/lib/thredded/post_user_permissions.rb +0 -32
- data/lib/thredded/private_topic_user_permissions.rb +0 -26
- data/lib/thredded/search_sql_builder.rb +0 -21
- data/lib/thredded/seed_database.rb +0 -76
- data/lib/thredded/table_sql_builder.rb +0 -41
- data/lib/thredded/topic_sql_builder.rb +0 -11
- data/lib/thredded/topic_user_permissions.rb +0 -32
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Thredded
|
|
3
|
+
class UserPreferencesForm
|
|
4
|
+
include ActiveModel::Model
|
|
5
|
+
|
|
6
|
+
# @return [Thredded::Messageboard, nil]
|
|
7
|
+
attr_reader :messageboard
|
|
8
|
+
|
|
9
|
+
validate :validate_children
|
|
10
|
+
|
|
11
|
+
delegate :notify_on_mention, :notify_on_mention=,
|
|
12
|
+
:notify_on_message, :notify_on_message=,
|
|
13
|
+
to: :user_preference
|
|
14
|
+
|
|
15
|
+
delegate :notify_on_mention, :notify_on_mention=,
|
|
16
|
+
to: :user_messageboard_preference,
|
|
17
|
+
prefix: :messageboard
|
|
18
|
+
|
|
19
|
+
# @param user [Thredded.user_class]
|
|
20
|
+
# @param messageboard [Thredded::Messageboard, nil]
|
|
21
|
+
def initialize(user:, messageboard: nil, params: {})
|
|
22
|
+
@user = user
|
|
23
|
+
@messageboard = messageboard
|
|
24
|
+
super(params)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @return [Boolean]
|
|
28
|
+
def save
|
|
29
|
+
return false unless valid?
|
|
30
|
+
Thredded::UserPreference.transaction do
|
|
31
|
+
user_preference.save!
|
|
32
|
+
user_messageboard_preference.save! if messageboard
|
|
33
|
+
end
|
|
34
|
+
true
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
# @return [Thredded::UserPreference]
|
|
40
|
+
def user_preference
|
|
41
|
+
@user_preference ||= @user.thredded_user_preference
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @return [Thredded::UserMessageboardPreference, nil]
|
|
45
|
+
def user_messageboard_preference
|
|
46
|
+
return nil unless @messageboard
|
|
47
|
+
@user_messageboard_preference ||=
|
|
48
|
+
user_preference.messageboard_preferences.where(messageboard_id: @messageboard.id).first_or_initialize
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def validate_children
|
|
52
|
+
promote_errors(user_preference.errors) if user_preference.invalid?
|
|
53
|
+
promote_errors(user_messageboard_preference.errors, :messageboard) if messageboard && user_messageboard_preference.invalid?
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def promote_errors(child_errors, prefix = nil)
|
|
57
|
+
child_errors.each do |attribute, message|
|
|
58
|
+
errors.add([prefix, attribute].compact.join('_'), message)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Thredded
|
|
2
3
|
module ApplicationHelper
|
|
4
|
+
include ::Thredded::UrlsHelper
|
|
5
|
+
|
|
3
6
|
# Render the page container with the supplied block as content.
|
|
4
7
|
def thredded_page(&block)
|
|
5
8
|
# enable the host app to easily check whether a thredded view is being rendered:
|
|
@@ -8,12 +11,6 @@ module Thredded
|
|
|
8
11
|
render partial: 'thredded/shared/page'
|
|
9
12
|
end
|
|
10
13
|
|
|
11
|
-
# @param user [Thredded.user_class, Thredded::NullUser]
|
|
12
|
-
# @return [String] path to the user as specified by {Thredded.user_path}
|
|
13
|
-
def user_path(user)
|
|
14
|
-
Thredded.user_path(self, user)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
14
|
# @param user [Thredded.user_class, Thredded::NullUser]
|
|
18
15
|
# @return [String] html_safe link to the user
|
|
19
16
|
def user_link(user)
|
|
@@ -30,12 +27,14 @@ module Thredded
|
|
|
30
27
|
super(collection, args.reverse_merge(views_prefix: 'thredded'))
|
|
31
28
|
end
|
|
32
29
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
# @param topic [BaseTopicView]
|
|
31
|
+
# @return [Array<String>]
|
|
32
|
+
def topic_css_classes(topic)
|
|
33
|
+
[
|
|
34
|
+
*topic.states.map { |s| "thredded--topic-#{s}" },
|
|
35
|
+
*(topic.categories.map { |c| "thredded--topic-category-#{c.name}" } if topic.respond_to?(:categories)),
|
|
36
|
+
*('thredded--private-topic' if topic.is_a?(Thredded::PrivateTopicView))
|
|
37
|
+
]
|
|
39
38
|
end
|
|
40
39
|
end
|
|
41
40
|
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Thredded
|
|
3
|
+
module UrlsHelper
|
|
4
|
+
class << self
|
|
5
|
+
include Thredded::Engine.routes.url_helpers
|
|
6
|
+
include Thredded::UrlsHelper
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# @param user [Thredded.user_class, Thredded::NullUser]
|
|
10
|
+
# @return [String] path to the user as specified by {Thredded.user_path}
|
|
11
|
+
def user_path(user)
|
|
12
|
+
Thredded.user_path(self, user)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# @param topic [Topic, PrivateTopic, UserTopicDecorator, UserPrivateTopicDecorator]
|
|
16
|
+
# @return [String]
|
|
17
|
+
def topic_url(topic, params = {})
|
|
18
|
+
if params[:page] == 1
|
|
19
|
+
params = params.dup
|
|
20
|
+
params.delete(:page)
|
|
21
|
+
end
|
|
22
|
+
if topic.private?
|
|
23
|
+
private_topic_url(
|
|
24
|
+
topic.slug,
|
|
25
|
+
params)
|
|
26
|
+
else
|
|
27
|
+
messageboard_topic_url(
|
|
28
|
+
topic.messageboard.slug,
|
|
29
|
+
topic.slug,
|
|
30
|
+
params)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @param topic [Topic, PrivateTopic, UserTopicDecorator, UserPrivateTopicDecorator]
|
|
35
|
+
# @return [String] path to the latest unread page of the given topic.
|
|
36
|
+
def topic_path(topic, params = {})
|
|
37
|
+
topic_url(topic, params.merge(only_path: true))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @param post [Post, PrivatePost]
|
|
41
|
+
# @return [String] URL of the topic page with the post anchor.
|
|
42
|
+
def post_url(post, params = {})
|
|
43
|
+
params = params.dup
|
|
44
|
+
params[:anchor] ||= dom_id(post)
|
|
45
|
+
params[:page] ||= post.page
|
|
46
|
+
topic_url(post.postable, params)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @param post [Post, PrivatePost]
|
|
50
|
+
# @return [String] path to the topic page with the post anchor.
|
|
51
|
+
def post_path(post, params = {})
|
|
52
|
+
post_url(post, params.merge(only_path: true))
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @param post [Post, PrivatePost]
|
|
56
|
+
# @return [String] path to the Edit Post page.
|
|
57
|
+
def edit_post_path(post)
|
|
58
|
+
if post.private_topic_post?
|
|
59
|
+
edit_private_topic_private_post_path(post.postable, post)
|
|
60
|
+
else
|
|
61
|
+
edit_messageboard_topic_post_path(post.messageboard, post.postable, post)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# @param post [Post, PrivatePost]
|
|
66
|
+
# @return [String] path to the DELETE PATCH PUT POST endpoint.
|
|
67
|
+
def delete_post_path(post)
|
|
68
|
+
if post.private_topic_post?
|
|
69
|
+
private_topic_private_post_path(post.postable, post)
|
|
70
|
+
else
|
|
71
|
+
messageboard_topic_post_path(post.messageboard, post.postable, post)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# @param messageboard [Thredded::Messageboard, nil]
|
|
76
|
+
# @param params [Hash] additional params
|
|
77
|
+
# @return [String] the URL to the global or messageboard edit preferences page.
|
|
78
|
+
def edit_preferences_url(messageboard = nil, params = {})
|
|
79
|
+
if messageboard.try(:persisted?)
|
|
80
|
+
edit_messageboard_preferences_url(messageboard, params)
|
|
81
|
+
else
|
|
82
|
+
super(params)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# @param messageboard [Thredded::Messageboard, nil]
|
|
87
|
+
# @param params [Hash] additional params
|
|
88
|
+
# @return [String] the path to the global or messageboard edit preferences page.
|
|
89
|
+
def edit_preferences_path(messageboard = nil, params = {})
|
|
90
|
+
edit_preferences_url(messageboard, params.merge(only_path: true))
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# @param messageboard [Thredded::Messageboard, nil]
|
|
94
|
+
# @return [String] the path to the global or messageboard search.
|
|
95
|
+
def search_path(messageboard = nil)
|
|
96
|
+
if messageboard.try(:persisted?)
|
|
97
|
+
messageboard_search_path(messageboard)
|
|
98
|
+
else
|
|
99
|
+
messageboards_search_path
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Thredded
|
|
2
3
|
class ActivityUpdaterJob < ::ActiveJob::Base
|
|
3
4
|
queue_as :default
|
|
4
5
|
|
|
5
6
|
def perform(user_id, messageboard_id)
|
|
6
|
-
now = Time.
|
|
7
|
+
now = Time.current
|
|
7
8
|
|
|
8
|
-
user_detail = Thredded::UserDetail.
|
|
9
|
-
user_detail.
|
|
9
|
+
user_detail = Thredded::UserDetail.where(user_id: user_id).first_or_initialize
|
|
10
|
+
user_detail.update!(last_seen_at: now)
|
|
10
11
|
|
|
11
12
|
Thredded::MessageboardUser
|
|
12
13
|
.where(
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Thredded
|
|
3
|
+
# A base class for Thredded mailer previews.
|
|
4
|
+
# @abstract
|
|
5
|
+
class BaseMailerPreview
|
|
6
|
+
def self.preview_classes
|
|
7
|
+
RailsEmailPreview.find_preview_classes File.expand_path('..', File.dirname(__FILE__))
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
protected
|
|
11
|
+
|
|
12
|
+
def mock_content(mention_users: [])
|
|
13
|
+
<<-MARKDOWN
|
|
14
|
+
#{mention_users.map { |u| "@#{u}" } * ', '}, if we synthesize the driver, we can get to the HDD panel through the `1080p EXE` bus!
|
|
15
|
+
I'll program the **redundant** SMTP array, that should monitor the SMS microchip!
|
|
16
|
+
MARKDOWN
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def mock_topic(attr = {})
|
|
20
|
+
Topic.new(
|
|
21
|
+
attr.reverse_merge(
|
|
22
|
+
title: 'A test topic',
|
|
23
|
+
slug: 'a-test-topic',
|
|
24
|
+
created_at: 3.days.ago,
|
|
25
|
+
id: 1 + rand(1334),
|
|
26
|
+
last_user: mock_user,
|
|
27
|
+
locked: [false, true].sample,
|
|
28
|
+
messageboard: mock_messageboard,
|
|
29
|
+
posts_count: 1 + rand(42),
|
|
30
|
+
sticky: [false, true].sample,
|
|
31
|
+
updated_at: Time.zone.now,
|
|
32
|
+
user: mock_user,
|
|
33
|
+
))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def mock_post(attr = {})
|
|
37
|
+
topic = attr[:postable] || mock_topic
|
|
38
|
+
Post.new(
|
|
39
|
+
attr.reverse_merge(
|
|
40
|
+
content: 'A test post',
|
|
41
|
+
created_at: Time.zone.now,
|
|
42
|
+
id: 1 + rand(1334),
|
|
43
|
+
messageboard: topic.messageboard,
|
|
44
|
+
postable: topic,
|
|
45
|
+
updated_at: Time.zone.now,
|
|
46
|
+
user: topic.last_user,
|
|
47
|
+
))
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def mock_private_topic(attr = {})
|
|
51
|
+
PrivateTopic.new(
|
|
52
|
+
attr.reverse_merge(
|
|
53
|
+
title: 'A test private topic',
|
|
54
|
+
slug: 'a-test-private-topic',
|
|
55
|
+
created_at: 3.days.ago,
|
|
56
|
+
id: 1 + rand(1334),
|
|
57
|
+
last_user: mock_user,
|
|
58
|
+
posts_count: 1 + rand(42),
|
|
59
|
+
updated_at: Time.zone.now,
|
|
60
|
+
user: mock_user,
|
|
61
|
+
))
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def mock_private_post(attr = {})
|
|
65
|
+
private_topic = attr[:postable] || mock_private_topic
|
|
66
|
+
PrivatePost.new(
|
|
67
|
+
attr.reverse_merge(
|
|
68
|
+
content: 'A test private post',
|
|
69
|
+
created_at: Time.zone.now,
|
|
70
|
+
id: 1 + rand(1334),
|
|
71
|
+
postable: private_topic,
|
|
72
|
+
updated_at: Time.zone.now,
|
|
73
|
+
user: private_topic.last_user,
|
|
74
|
+
))
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def mock_messageboard(attr = {})
|
|
78
|
+
Messageboard.new(
|
|
79
|
+
attr.reverse_merge(
|
|
80
|
+
name: 'A test messageboard',
|
|
81
|
+
slug: 'a-test-messageboard',
|
|
82
|
+
description: 'Test messageboard description',
|
|
83
|
+
closed: false,
|
|
84
|
+
created_at: 1.month.ago,
|
|
85
|
+
id: 1 + rand(1334),
|
|
86
|
+
posts_count: rand(1337),
|
|
87
|
+
topics_count: rand(42),
|
|
88
|
+
updated_at: Time.zone.now,
|
|
89
|
+
))
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def mock_user(attr = {})
|
|
93
|
+
name = %w(Alice Bob).sample
|
|
94
|
+
Thredded.user_class.new(
|
|
95
|
+
attr.reverse_merge(
|
|
96
|
+
Thredded.user_name_column => name,
|
|
97
|
+
email: "#{name.downcase}@test.com",
|
|
98
|
+
))
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Thredded
|
|
3
|
+
# Previews for the PostMailer
|
|
4
|
+
class PostMailerPreview < BaseMailerPreview
|
|
5
|
+
def at_notification
|
|
6
|
+
PostMailer.at_notification(
|
|
7
|
+
mock_post(content: mock_content(mention_users: %w(glebm joel))),
|
|
8
|
+
%w(glebm@test.com joel@test.com))
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Thredded
|
|
3
|
+
# Previews for the PrivatePostMailer
|
|
4
|
+
class PrivatePostMailerPreview < BaseMailerPreview
|
|
5
|
+
def at_notification
|
|
6
|
+
PrivatePostMailer.at_notification(
|
|
7
|
+
mock_private_post(content: mock_content(mention_users: %w(glebm joel))),
|
|
8
|
+
%w(glebm@test.com joel@test.com))
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Thredded
|
|
3
|
+
# Previews for the PrivateTopicMailer
|
|
4
|
+
class PrivateTopicMailerPreview < BaseMailerPreview
|
|
5
|
+
def message_notification
|
|
6
|
+
PrivateTopicMailer.message_notification(
|
|
7
|
+
mock_private_topic.tap do |private_topic|
|
|
8
|
+
private_topic.posts = [
|
|
9
|
+
mock_private_post(content: mock_content(mention_users: ['glebm']), postable: private_topic)
|
|
10
|
+
]
|
|
11
|
+
end,
|
|
12
|
+
%w(glebm@test.com joel@test.com))
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -1,4 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Thredded
|
|
2
3
|
class BaseMailer < ActionMailer::Base
|
|
4
|
+
helper ::Thredded::UrlsHelper
|
|
5
|
+
|
|
6
|
+
protected
|
|
7
|
+
|
|
8
|
+
# Find a record by ID, or return the passed record.
|
|
9
|
+
# @param [Class<ActiveRecord::Base>] klass
|
|
10
|
+
# @param [Fixnum, String, klass] id_or_record
|
|
11
|
+
# @return [klass]
|
|
12
|
+
def find_record(klass, id_or_record)
|
|
13
|
+
# Check by name because in development the Class might have been reloaded after id was initialized
|
|
14
|
+
id_or_record.class.name == klass.name ? id_or_record : klass.find(id_or_record)
|
|
15
|
+
end
|
|
3
16
|
end
|
|
4
17
|
end
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_dependency 'thredded/topic_email_view'
|
|
1
3
|
module Thredded
|
|
2
4
|
class PostMailer < Thredded::BaseMailer
|
|
3
5
|
def at_notification(post_id, emails)
|
|
4
|
-
@post = Post
|
|
5
|
-
email_details =
|
|
6
|
+
@post = find_record Post, post_id
|
|
7
|
+
email_details = TopicEmailView.new(@post.postable)
|
|
6
8
|
headers['X-SMTPAPI'] = email_details.smtp_api_tag('at_notification')
|
|
7
9
|
|
|
8
10
|
mail from: email_details.no_reply,
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_dependency 'thredded/topic_email_view'
|
|
1
3
|
module Thredded
|
|
2
4
|
class PrivatePostMailer < Thredded::BaseMailer
|
|
3
5
|
def at_notification(post_id, emails)
|
|
4
|
-
@post = PrivatePost
|
|
5
|
-
email_details =
|
|
6
|
+
@post = find_record PrivatePost, post_id
|
|
7
|
+
email_details = TopicEmailView.new(@post.postable)
|
|
6
8
|
headers['X-SMTPAPI'] = email_details.smtp_api_tag('at_notification')
|
|
7
9
|
|
|
8
10
|
mail from: email_details.no_reply,
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_dependency 'thredded/topic_email_view'
|
|
1
3
|
module Thredded
|
|
2
4
|
class PrivateTopicMailer < Thredded::BaseMailer
|
|
3
5
|
def message_notification(private_topic_id, emails)
|
|
4
|
-
@topic = PrivateTopic
|
|
5
|
-
email_details =
|
|
6
|
+
@topic = find_record PrivateTopic, private_topic_id
|
|
7
|
+
email_details = TopicEmailView.new(@topic)
|
|
6
8
|
headers['X-SMTPAPI'] = email_details.smtp_api_tag('private_topic_mailer')
|
|
7
9
|
|
|
8
10
|
mail from: email_details.no_reply,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'set'
|
|
3
|
+
module Thredded
|
|
4
|
+
# Excludes pagination routes in addition to the given list of reserved words.
|
|
5
|
+
class FriendlyIdReservedWordsAndPagination
|
|
6
|
+
PAGINATION_PATTERN = /\Apage-\d+\z/i
|
|
7
|
+
|
|
8
|
+
def initialize(words = [])
|
|
9
|
+
@words = Set.new(words)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def include?(slug)
|
|
13
|
+
@words.include?(slug) || slug =~ PAGINATION_PATTERN
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|