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.
Files changed (220) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.mkdn +63 -0
  3. data/Procfile +1 -0
  4. data/README.mkdn +42 -20
  5. data/app/assets/images/thredded/private-messages.svg +4 -0
  6. data/app/assets/images/thredded/settings.svg +4 -0
  7. data/app/assets/javascripts/thredded.es6 +2 -10
  8. data/app/assets/javascripts/thredded/{currently_online.es6 → components/currently_online.es6} +0 -0
  9. data/app/assets/javascripts/thredded/{post_form.es6 → components/post_form.es6} +0 -0
  10. data/app/assets/javascripts/thredded/{time_stamps.es6 → components/time_stamps.es6} +0 -0
  11. data/app/assets/javascripts/thredded/{topic_form.es6 → components/topic_form.es6} +1 -1
  12. data/app/assets/javascripts/thredded/components/topics.es6 +37 -0
  13. data/app/assets/javascripts/thredded/components/user_preferences_form.es6 +45 -0
  14. data/app/assets/javascripts/thredded/components/users_select.es6 +56 -0
  15. data/app/assets/javascripts/thredded/dependencies.js +9 -0
  16. data/app/assets/javascripts/thredded/thredded.es6 +1 -0
  17. data/app/assets/stylesheets/thredded/_base.scss +3 -2
  18. data/app/assets/stylesheets/thredded/_thredded.scss +4 -1
  19. data/app/assets/stylesheets/thredded/base/_buttons.scss +2 -1
  20. data/app/assets/stylesheets/thredded/base/_forms.scss +23 -18
  21. data/app/assets/stylesheets/thredded/base/_grid.scss +1 -1
  22. data/app/assets/stylesheets/thredded/base/_nav.scss +21 -0
  23. data/app/assets/stylesheets/thredded/base/_tables.scss +5 -14
  24. data/app/assets/stylesheets/thredded/base/_typography.scss +9 -4
  25. data/app/assets/stylesheets/thredded/base/_variables.scss +28 -9
  26. data/app/assets/stylesheets/thredded/components/_alerts.scss +19 -0
  27. data/app/assets/stylesheets/thredded/components/_currently-online.scss +1 -1
  28. data/app/assets/stylesheets/thredded/components/_form-list.scss +2 -4
  29. data/app/assets/stylesheets/thredded/components/_icons.scss +3 -0
  30. data/app/assets/stylesheets/thredded/components/_messageboard.scss +4 -4
  31. data/app/assets/stylesheets/thredded/components/_pagination.scss +2 -2
  32. data/app/assets/stylesheets/thredded/components/_post-form.scss +3 -0
  33. data/app/assets/stylesheets/thredded/components/_post.scss +14 -4
  34. data/app/assets/stylesheets/thredded/components/_select2.scss +79 -9
  35. data/app/assets/stylesheets/thredded/components/_topic-header.scss +11 -1
  36. data/app/assets/stylesheets/thredded/components/_topics.scss +13 -11
  37. data/app/assets/stylesheets/thredded/layout/_main-container.scss +3 -3
  38. data/app/assets/stylesheets/thredded/layout/_main-navigation.scss +11 -17
  39. data/app/assets/stylesheets/thredded/layout/_navigation.scss +72 -0
  40. data/app/assets/stylesheets/thredded/layout/_search-navigation.scss +66 -0
  41. data/app/assets/stylesheets/thredded/layout/_user-navigation.scss +35 -61
  42. data/app/commands/thredded/at_notification_extractor.rb +1 -0
  43. data/app/commands/thredded/members_marked_notified.rb +1 -0
  44. data/app/commands/thredded/messageboard_destroyer.rb +7 -2
  45. data/app/commands/thredded/notify_mentioned_users.rb +8 -21
  46. data/app/commands/thredded/notify_private_topic_users.rb +3 -5
  47. data/app/controllers/thredded/application_controller.rb +76 -41
  48. data/app/controllers/thredded/autocomplete_users_controller.rb +46 -0
  49. data/app/controllers/thredded/messageboards_controller.rb +8 -5
  50. data/app/controllers/thredded/posts_controller.rb +20 -22
  51. data/app/controllers/thredded/preferences_controller.rb +19 -14
  52. data/app/controllers/thredded/private_topics_controller.rb +58 -23
  53. data/app/controllers/thredded/setups_controller.rb +1 -0
  54. data/app/controllers/thredded/theme_previews_controller.rb +24 -53
  55. data/app/controllers/thredded/topics_controller.rb +48 -77
  56. data/app/forms/thredded/private_topic_form.rb +1 -21
  57. data/app/forms/thredded/topic_form.rb +3 -7
  58. data/app/forms/thredded/user_preferences_form.rb +62 -0
  59. data/app/helpers/thredded/application_helper.rb +11 -12
  60. data/app/helpers/thredded/urls_helper.rb +103 -0
  61. data/app/jobs/thredded/activity_updater_job.rb +4 -3
  62. data/app/jobs/thredded/at_notifier_job.rb +1 -0
  63. data/app/jobs/thredded/notify_private_topic_users_job.rb +1 -0
  64. data/app/mailer_previews/thredded/base_mailer_preview.rb +101 -0
  65. data/app/mailer_previews/thredded/post_mailer_preview.rb +11 -0
  66. data/app/mailer_previews/thredded/private_post_mailer_preview.rb +11 -0
  67. data/app/mailer_previews/thredded/private_topic_mailer_preview.rb +15 -0
  68. data/app/mailers/thredded/base_mailer.rb +13 -0
  69. data/app/mailers/thredded/post_mailer.rb +4 -2
  70. data/app/mailers/thredded/private_post_mailer.rb +4 -2
  71. data/app/mailers/thredded/private_topic_mailer.rb +4 -2
  72. data/app/models/concerns/thredded/friendly_id_reserved_words_and_pagination.rb +16 -0
  73. data/app/models/concerns/thredded/post_common.rb +68 -63
  74. data/app/models/concerns/thredded/topic_common.rb +31 -8
  75. data/app/models/concerns/thredded/user_topic_read_state_common.rb +31 -0
  76. data/app/models/thredded/category.rb +1 -0
  77. data/app/models/thredded/messageboard.rb +24 -25
  78. data/app/models/thredded/messageboard_user.rb +1 -0
  79. data/app/models/thredded/null_preference.rb +1 -0
  80. data/app/models/thredded/null_user.rb +1 -6
  81. data/app/models/thredded/null_user_topic_read_state.rb +12 -0
  82. data/app/models/thredded/post.rb +6 -9
  83. data/app/models/thredded/post_notification.rb +1 -0
  84. data/app/models/thredded/private_post.rb +6 -2
  85. data/app/models/thredded/private_topic.rb +46 -32
  86. data/app/models/thredded/private_user.rb +3 -2
  87. data/app/models/thredded/stats.rb +1 -0
  88. data/app/models/thredded/topic.rb +40 -64
  89. data/app/models/thredded/topic_category.rb +1 -0
  90. data/app/models/thredded/user_detail.rb +2 -15
  91. data/app/models/thredded/user_extender.rb +29 -14
  92. data/app/models/thredded/user_messageboard_preference.rb +20 -0
  93. data/app/models/thredded/user_permissions/admin/if_admin_column_true.rb +1 -0
  94. data/app/models/thredded/user_permissions/admin/none.rb +1 -0
  95. data/app/models/thredded/user_permissions/message/readers_of_writeable_boards.rb +1 -0
  96. data/app/models/thredded/user_permissions/moderate/if_moderator_column_true.rb +1 -0
  97. data/app/models/thredded/user_permissions/moderate/none.rb +1 -0
  98. data/app/models/thredded/user_permissions/read/all.rb +1 -0
  99. data/app/models/thredded/user_permissions/write/all.rb +1 -0
  100. data/app/models/thredded/user_permissions/write/none.rb +1 -0
  101. data/app/models/thredded/user_preference.rb +7 -1
  102. data/app/models/thredded/user_private_topic_read_state.rb +12 -0
  103. data/app/models/thredded/user_topic_read_state.rb +12 -0
  104. data/app/policies/thredded/messageboard_policy.rb +27 -0
  105. data/app/policies/thredded/post_policy.rb +33 -0
  106. data/app/policies/thredded/private_post_policy.rb +29 -0
  107. data/app/policies/thredded/private_topic_policy.rb +23 -0
  108. data/app/policies/thredded/topic_policy.rb +32 -0
  109. data/app/view_models/thredded/base_topic_view.rb +56 -0
  110. data/app/view_models/thredded/post_view.rb +44 -0
  111. data/app/view_models/thredded/posts_page_view.rb +27 -0
  112. data/app/view_models/thredded/private_topic_view.rb +9 -0
  113. data/app/{decorators/thredded/topic_email_decorator.rb → view_models/thredded/topic_email_view.rb} +2 -1
  114. data/app/view_models/thredded/topic_view.rb +23 -0
  115. data/app/view_models/thredded/topics_page_view.rb +26 -0
  116. data/app/views/thredded/error_pages/forbidden.html.erb +6 -0
  117. data/app/views/thredded/error_pages/not_found.html.erb +6 -0
  118. data/app/views/thredded/messageboards/_messageboard.html.erb +13 -6
  119. data/app/views/thredded/messageboards/index.html.erb +2 -8
  120. data/app/views/thredded/messageboards/new.html.erb +8 -2
  121. data/app/views/thredded/post_mailer/at_notification.html.erb +3 -3
  122. data/app/views/thredded/post_mailer/at_notification.text.erb +1 -1
  123. data/app/views/thredded/posts/_content_field.html.erb +1 -1
  124. data/app/views/thredded/posts/_form.html.erb +5 -1
  125. data/app/views/thredded/posts/_post.html.erb +3 -1
  126. data/app/views/thredded/posts/edit.html.erb +7 -3
  127. data/app/views/thredded/posts_common/_form.html.erb +1 -1
  128. data/app/views/thredded/posts_common/_post.html.erb +14 -8
  129. data/app/views/thredded/preferences/_form.html.erb +37 -15
  130. data/app/views/thredded/preferences/_header.html.erb +1 -1
  131. data/app/views/thredded/preferences/edit.html.erb +4 -6
  132. data/app/views/thredded/private_post_mailer/at_notification.html.erb +6 -4
  133. data/app/views/thredded/private_posts/_form.html.erb +5 -1
  134. data/app/views/thredded/private_posts/_private_post.html.erb +3 -1
  135. data/app/views/thredded/private_topic_mailer/message_notification.html.erb +3 -7
  136. data/app/views/thredded/private_topic_mailer/message_notification.text.erb +1 -3
  137. data/app/views/thredded/private_topics/_breadcrumbs.html.erb +2 -2
  138. data/app/views/thredded/private_topics/_form.html.erb +15 -10
  139. data/app/views/thredded/private_topics/_header.html.erb +12 -0
  140. data/app/views/thredded/private_topics/_no_private_topics.html.erb +2 -2
  141. data/app/views/thredded/private_topics/_private_topic.html.erb +4 -6
  142. data/app/views/thredded/private_topics/edit.html.erb +32 -0
  143. data/app/views/thredded/private_topics/index.html.erb +5 -5
  144. data/app/views/thredded/private_topics/new.html.erb +1 -2
  145. data/app/views/thredded/private_topics/show.html.erb +12 -7
  146. data/app/views/thredded/search/_form.html.erb +9 -6
  147. data/app/views/thredded/shared/{_messageboard_topics_breadcrumbs.html.erb → _breadcrumbs.html.erb} +2 -2
  148. data/app/views/thredded/shared/_header.html.erb +2 -3
  149. data/app/views/thredded/shared/_nav.html.erb +20 -0
  150. data/app/views/thredded/shared/nav/_notification_preferences.html.erb +6 -0
  151. data/app/views/thredded/shared/nav/_private_topics.html.erb +11 -0
  152. data/app/views/thredded/shared/nav/_standalone.html.erb +12 -0
  153. data/app/views/thredded/theme_previews/_section_title.html.erb +2 -2
  154. data/app/views/thredded/theme_previews/show.html.erb +13 -17
  155. data/app/views/thredded/topics/_form.html.erb +8 -6
  156. data/app/views/thredded/topics/_header.html.erb +12 -0
  157. data/app/views/thredded/topics/_topic.html.erb +4 -8
  158. data/app/views/thredded/topics/_topic_form_admin_options.html.erb +1 -1
  159. data/app/views/thredded/topics/edit.html.erb +22 -18
  160. data/app/views/thredded/topics/index.html.erb +3 -3
  161. data/app/views/thredded/topics/new.html.erb +1 -1
  162. data/app/views/thredded/topics/search.html.erb +17 -5
  163. data/app/views/thredded/topics/show.html.erb +14 -11
  164. data/bin/rails +5 -0
  165. data/config.ru +3 -0
  166. data/config/i18n-tasks.yml +16 -0
  167. data/config/locales/en.yml +90 -0
  168. data/config/routes.rb +29 -15
  169. data/db/migrate/20160329231848_create_thredded.rb +29 -33
  170. data/db/seeds.rb +115 -0
  171. data/db/upgrade_migrations/20160410111522_upgrade_v0_2_to_v0_3.rb +59 -0
  172. data/heroku.gemfile +26 -0
  173. data/heroku.gemfile.lock +282 -0
  174. data/lib/generators/thredded/install/install_generator.rb +1 -0
  175. data/lib/generators/thredded/install/templates/initializer.rb +17 -0
  176. data/lib/html/pipeline/at_mention_filter.rb +2 -1
  177. data/lib/html/pipeline/bbcode_filter.rb +13 -4
  178. data/lib/tasks/thredded_tasks.rake +1 -0
  179. data/lib/thredded.rb +19 -17
  180. data/lib/thredded/at_users.rb +1 -0
  181. data/lib/thredded/engine.rb +14 -5
  182. data/lib/thredded/errors.rb +11 -11
  183. data/lib/thredded/main_app_route_delegator.rb +1 -0
  184. data/lib/thredded/search_parser.rb +2 -1
  185. data/lib/thredded/topics_search.rb +67 -0
  186. data/lib/thredded/version.rb +2 -1
  187. data/thredded.gemspec +12 -8
  188. metadata +146 -82
  189. data/app/assets/javascripts/thredded/users_select.es6 +0 -5
  190. data/app/assets/stylesheets/thredded/layout/_topic-navigation.scss +0 -53
  191. data/app/commands/thredded/user_reads_private_topic.rb +0 -22
  192. data/app/commands/thredded/user_resets_private_topic_to_unread.rb +0 -23
  193. data/app/decorators/thredded/base_topic_decorator.rb +0 -14
  194. data/app/decorators/thredded/base_user_topic_decorator.rb +0 -63
  195. data/app/decorators/thredded/messageboard_decorator.rb +0 -41
  196. data/app/decorators/thredded/post_decorator.rb +0 -40
  197. data/app/decorators/thredded/private_topic_decorator.rb +0 -23
  198. data/app/decorators/thredded/topic_decorator.rb +0 -25
  199. data/app/decorators/thredded/user_private_topic_decorator.rb +0 -13
  200. data/app/decorators/thredded/user_topic_decorator.rb +0 -37
  201. data/app/models/thredded/ability.rb +0 -60
  202. data/app/models/thredded/notification_preference.rb +0 -17
  203. data/app/models/thredded/null_topic.rb +0 -15
  204. data/app/models/thredded/null_topic_read.rb +0 -19
  205. data/app/models/thredded/user_topic_read.rb +0 -10
  206. data/app/views/thredded/shared/_notification_preferences.html.erb +0 -7
  207. data/app/views/thredded/shared/_top_nav.html.erb +0 -36
  208. data/app/views/thredded/shared/_topic_nav.html.erb +0 -22
  209. data/app/views/thredded/topics/_recent_topics_by_user.html.erb +0 -8
  210. data/app/views/thredded/topics/by_category.html.erb +0 -56
  211. data/app/views/thredded/topics_common/_header.html.erb +0 -6
  212. data/lib/thredded/messageboard_user_permissions.rb +0 -22
  213. data/lib/thredded/post_sql_builder.rb +0 -12
  214. data/lib/thredded/post_user_permissions.rb +0 -32
  215. data/lib/thredded/private_topic_user_permissions.rb +0 -26
  216. data/lib/thredded/search_sql_builder.rb +0 -21
  217. data/lib/thredded/seed_database.rb +0 -76
  218. data/lib/thredded/table_sql_builder.rb +0 -41
  219. data/lib/thredded/topic_sql_builder.rb +0 -11
  220. data/lib/thredded/topic_user_permissions.rb +0 -32
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ class UserTopicReadState < ActiveRecord::Base
4
+ include UserTopicReadStateCommon
5
+ belongs_to :user,
6
+ class_name: Thredded.user_class,
7
+ inverse_of: :thredded_topic_read_states
8
+ belongs_to :postable,
9
+ class_name: 'Thredded::Topic',
10
+ inverse_of: :user_read_states
11
+ end
12
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ class MessageboardPolicy
4
+ # @param user [Thredded.user_class]
5
+ # @param messageboard [Thredded::Messageboard]
6
+ def initialize(user, messageboard)
7
+ @user = user
8
+ @messageboard = messageboard
9
+ end
10
+
11
+ def create?
12
+ @user.thredded_admin?
13
+ end
14
+
15
+ def read?
16
+ @user.thredded_admin? || @user.thredded_can_read_messageboards.include?(@messageboard)
17
+ end
18
+
19
+ def post?
20
+ @user.thredded_admin? || @user.thredded_can_write_messageboards.include?(@messageboard)
21
+ end
22
+
23
+ def moderate?
24
+ @user.thredded_admin? || @user.thredded_can_moderate_messageboards.include?(@messageboard)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ class PostPolicy
4
+ # @param user [Thredded.user_class]
5
+ # @param post [Thredded::Post]
6
+ def initialize(user, post)
7
+ @user = user
8
+ @post = post
9
+ end
10
+
11
+ def create?
12
+ @user.thredded_admin? || !@post.postable.locked? && messageboard_policy.post?
13
+ end
14
+
15
+ def update?
16
+ @user.thredded_admin? || own_post? || messageboard_policy.moderate?
17
+ end
18
+
19
+ def destroy?
20
+ @post.postable.first_post != @post && update?
21
+ end
22
+
23
+ private
24
+
25
+ def messageboard_policy
26
+ @messageboard_policy ||= MessageboardPolicy.new(@user, @post.messageboard)
27
+ end
28
+
29
+ def own_post?
30
+ @user.id == @post.user_id
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ class PrivatePostPolicy
4
+ # @param user [Thredded.user_class]
5
+ # @param post [Thredded::PrivatePost]
6
+ def initialize(user, post)
7
+ @user = user
8
+ @post = post
9
+ end
10
+
11
+ def create?
12
+ @user.thredded_admin? || @post.postable.users.include?(@user)
13
+ end
14
+
15
+ def update?
16
+ @user.thredded_admin? || own_post?
17
+ end
18
+
19
+ def destroy?
20
+ @post.postable.first_post != @post && update?
21
+ end
22
+
23
+ private
24
+
25
+ def own_post?
26
+ @user.id == @post.user_id
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ class PrivateTopicPolicy
4
+ # @param user [Thredded.user_class]
5
+ # @param private_topic [Thredded::PrivateTopic]
6
+ def initialize(user, private_topic)
7
+ @private_topic = private_topic
8
+ @user = user
9
+ end
10
+
11
+ def create?
12
+ !@user.thredded_anonymous?
13
+ end
14
+
15
+ def read?
16
+ @private_topic.users.include?(@user)
17
+ end
18
+
19
+ def update?
20
+ @user.id == @private_topic.user_id
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ class TopicPolicy
4
+ # @param user [Thredded.user_class]
5
+ # @param topic [Thredded::Topic]
6
+ def initialize(user, topic)
7
+ @user = user
8
+ @topic = topic
9
+ @messageboard_user_permission = MessageboardPolicy.new(user, topic.messageboard)
10
+ end
11
+
12
+ def create?
13
+ @messageboard_user_permission.post?
14
+ end
15
+
16
+ def read?
17
+ @messageboard_user_permission.read?
18
+ end
19
+
20
+ def update?
21
+ @user.thredded_admin? || @topic.user_id == @user.id || moderate?
22
+ end
23
+
24
+ def destroy?
25
+ @user.thredded_admin?
26
+ end
27
+
28
+ def moderate?
29
+ @messageboard_user_permission.moderate?
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+ require_dependency 'thredded/urls_helper'
3
+ module Thredded
4
+ # A view model for TopicCommon.
5
+ class BaseTopicView
6
+ delegate :title,
7
+ :posts_count,
8
+ :updated_at,
9
+ :created_at,
10
+ :user,
11
+ :last_user,
12
+ :to_model,
13
+ to: :@topic
14
+
15
+ delegate :read?,
16
+ to: :@read_state
17
+
18
+ # @param topic [TopicCommon]
19
+ # @param read_state [UserTopicReadStateCommon, nil]
20
+ # @param policy [#destroy?]
21
+ def initialize(topic, read_state, policy)
22
+ @read_state = read_state || Thredded::NullUserTopicReadState.new
23
+ @topic = topic
24
+ @policy = policy
25
+ end
26
+
27
+ def states
28
+ [@read_state.read? ? :read : :unread]
29
+ end
30
+
31
+ def can_update?
32
+ @policy.update?
33
+ end
34
+
35
+ def can_destroy?
36
+ @policy.destroy?
37
+ end
38
+
39
+ def path
40
+ Thredded::UrlsHelper.topic_path(@topic, page: @read_state.page)
41
+ end
42
+
43
+ def self.inherited(subclass)
44
+ subclass.extend ClassMethods
45
+ end
46
+
47
+ module ClassMethods
48
+ def from_user(topic, user)
49
+ read_state = if user && !user.thredded_anonymous?
50
+ topic.association(:user_read_states).klass.where(user_id: user.id, postable_id: topic.id).first
51
+ end
52
+ new(topic, read_state, Pundit.policy!(user, topic))
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+ require_dependency 'thredded/urls_helper'
3
+ module Thredded
4
+ # A view model for PostCommon.
5
+ class PostView
6
+ delegate :filtered_content,
7
+ :avatar_url,
8
+ :created_at,
9
+ :user,
10
+ :to_model,
11
+ to: :@post
12
+
13
+ # @param post [Thredded::PostCommon]
14
+ # @param policy [#update? #destroy?]
15
+ def initialize(post, policy)
16
+ @post = post
17
+ @policy = policy
18
+ end
19
+
20
+ def can_update?
21
+ @can_update ||= @policy.update?
22
+ end
23
+
24
+ def can_destroy?
25
+ @can_destroy ||= @policy.destroy?
26
+ end
27
+
28
+ def edit_path
29
+ Thredded::UrlsHelper.edit_post_path(@post)
30
+ end
31
+
32
+ def destroy_path
33
+ Thredded::UrlsHelper.delete_post_path(@post)
34
+ end
35
+
36
+ def cache_key
37
+ [
38
+ @post,
39
+ @post.user,
40
+ [can_update?, can_destroy?].map { |p| p ? '+' : '-' } * ''
41
+ ]
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+ require_dependency 'thredded/post_view'
3
+ require_dependency 'thredded/topic_view'
4
+ require_dependency 'thredded/private_topic_view'
5
+ module Thredded
6
+ # A view model for a page of PostViews.
7
+ class PostsPageView
8
+ delegate :to_ary,
9
+ to: :@topic_views
10
+ delegate :total_pages,
11
+ :current_page,
12
+ :limit_value,
13
+ to: :@topics_page_scope
14
+
15
+ # @return [Thredded::BaseTopicView]
16
+ attr_reader :topic
17
+
18
+ # @param user [Thredded.user_class] the user who is viewing the posts page
19
+ # @param topic [Thredded::TopicCommon]
20
+ # @param posts_page_scope [ActiveRecord::Relation<Thredded::PostCommon>]
21
+ def initialize(user, topic, posts_page_scope)
22
+ @topics_page_scope = posts_page_scope
23
+ @topic_views = posts_page_scope.map { |post| PostView.new(post, Pundit.policy!(user, post)) }
24
+ @topic = "#{posts_page_scope.reflect_on_association(:postable).klass}View".constantize.from_user(topic, user)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ # A view model for PrivateTopic.
4
+ class PrivateTopicView < BaseTopicView
5
+ def edit_path
6
+ Thredded::UrlsHelper.edit_private_topic_path(@topic)
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  module Thredded
2
- class TopicEmailDecorator
3
+ class TopicEmailView
3
4
  # @param [Thredded::TopicCommon] topic
4
5
  def initialize(topic)
5
6
  @topic = topic
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ # A view model for Topic.
4
+ class TopicView < BaseTopicView
5
+ delegate :categories,
6
+ to: :@topic
7
+
8
+ def states
9
+ super + [
10
+ (:locked if @topic.locked?),
11
+ (:sticky if @topic.sticky?),
12
+ ].compact
13
+ end
14
+
15
+ def edit_path
16
+ Thredded::UrlsHelper.edit_messageboard_topic_path(@topic.messageboard, @topic)
17
+ end
18
+
19
+ def destroy_path
20
+ Thredded::UrlsHelper.messageboard_topic_path(@topic.messageboard, @topic)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ require_dependency 'thredded/topic_view'
3
+ require_dependency 'thredded/private_topic_view'
4
+ module Thredded
5
+ # A view model for a page of BaseTopicViews.
6
+ class TopicsPageView
7
+ delegate :to_ary,
8
+ :blank?,
9
+ :empty?,
10
+ to: :@topic_views
11
+ delegate :total_pages,
12
+ :current_page,
13
+ :limit_value,
14
+ to: :@topics_page_scope
15
+
16
+ # @param user [Thredded.user_class] the user who is viewing the posts page
17
+ # @param topics_page_scope [ActiveRecord::Relation<Thredded::Topic>]
18
+ def initialize(user, topics_page_scope)
19
+ @topics_page_scope = topics_page_scope
20
+ topic_view_class = "#{topics_page_scope.klass}View".constantize
21
+ @topic_views = @topics_page_scope.with_read_states(user).map do |(topic, read_state)|
22
+ topic_view_class.new(topic, read_state, Pundit.policy!(user, topic))
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,6 @@
1
+ <% content_for :thredded_page_title, @message %>
2
+ <% content_for :thredded_page_id, 'thredded--error-forbidden' %>
3
+ <% content_for :thredded_breadcrumbs, render('thredded/shared/breadcrumbs') %>
4
+ <%= thredded_page do %>
5
+ <p class="thredded--alert thredded--alert-warning"><%= @message %></p>
6
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <% content_for :thredded_page_title, @message %>
2
+ <% content_for :thredded_page_id, 'thredded--error-not-found' %>
3
+ <% content_for :thredded_breadcrumbs, render('thredded/shared/breadcrumbs') %>
4
+ <%= thredded_page do %>
5
+ <p class="thredded--alert thredded--alert-danger"><%= @message %></p>
6
+ <% end %>
@@ -1,15 +1,22 @@
1
- <% if current_ability.can? :read, messageboard.original %>
1
+ <% if policy(messageboard).read? %>
2
2
  <%= link_to messageboard_topics_path(messageboard), class: 'thredded--messageboard' do %>
3
3
  <header>
4
4
  <h2 class="thredded--messageboard--title"><%= messageboard.name %></h2>
5
- <h3 class="thredded--messageboard--meta"><%= messageboard.meta %></h3>
5
+ <h3 class="thredded--messageboard--meta">
6
+ <%= t 'thredded.messageboard.topics_and_posts_counts',
7
+ topics_count: number_to_human(messageboard.topics_count).downcase,
8
+ posts_count: number_to_human(messageboard.posts_count).downcase %>
9
+ </h3>
6
10
  </header>
7
11
 
8
12
  <p class="thredded--messageboard--description"><%= messageboard.description %></p>
9
13
 
10
- <p class="thredded--messageboard--byline">
11
- Updated <%= time_ago messageboard.latest_topic.updated_at %>
12
- <cite>by <%= messageboard.latest_user %></cite>
13
- </p>
14
+ <% if messageboard.latest_topic %>
15
+ <p class="thredded--messageboard--byline">
16
+ <%= t 'thredded.messageboard.last_updated_by_html',
17
+ time_ago: time_ago(messageboard.latest_topic.updated_at),
18
+ user: messageboard.latest_user %>
19
+ </p>
20
+ <% end %>
14
21
  <% end %>
15
22
  <% end %>
@@ -1,18 +1,12 @@
1
1
  <% content_for :thredded_page_title, 'Messageboards' %>
2
2
  <% content_for :thredded_page_id, 'thredded--messageboards-index' %>
3
- <% content_for :thredded_breadcrumbs do %>
4
- <ul class="thredded--navigation-breadcrumbs">
5
- <li>
6
- <%= link_to 'All Message Boards', messageboards_path %>
7
- </li>
8
- </ul>
9
- <% end %>
3
+ <% content_for :thredded_breadcrumbs, render('thredded/shared/breadcrumbs') %>
10
4
  <%= thredded_page do %>
11
5
  <section class="thredded--main-section thredded--messageboards">
12
6
  <%= render @messageboards %>
13
7
  </section>
14
8
 
15
- <% if current_ability.can? :create, Thredded::Messageboard %>
9
+ <% if policy(Thredded::Messageboard.new).create? %>
16
10
  <div class="thredded--messageboard--create">
17
11
  <a class="thredded--button" href="<%= new_messageboard_path %>">Create a New Messageboard</a>
18
12
  </div>
@@ -1,11 +1,17 @@
1
1
  <% content_for :thredded_page_title, 'Create a New Messageboard' %>
2
2
  <% content_for :thredded_page_id, 'thredded--messageboards-new' %>
3
+ <% content_for :thredded_breadcrumbs do %>
4
+ <ul class="thredded--navigation-breadcrumbs">
5
+ <li>Create a New Messageboard</li>
6
+ </ul>
7
+ <% end %>
8
+
3
9
  <%= thredded_page do %>
4
- <%= form_for @messageboard, class: 'thredded--form' do |f| %>
10
+ <%= form_for @messageboard, html: { class: 'thredded--form' } do |f| %>
5
11
  <ul class="thredded--form-list">
6
12
  <li>
7
13
  <%= f.label :name %>
8
- <%= f.text_field :name %>
14
+ <%= f.text_field :name, required: true %>
9
15
  </li>
10
16
  <li>
11
17
  <%= f.label :description %>