thredded 0.3.2 → 0.4.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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.mkdn +22 -2
  3. data/README.mkdn +17 -5
  4. data/app/assets/stylesheets/thredded/base/_typography.scss +9 -0
  5. data/app/assets/stylesheets/thredded/base/_variables.scss +4 -0
  6. data/app/assets/stylesheets/thredded/components/_messageboard.scss +13 -1
  7. data/app/assets/stylesheets/thredded/components/_post.scss +15 -1
  8. data/app/assets/stylesheets/thredded/layout/_search-navigation.scss +1 -1
  9. data/app/controllers/thredded/application_controller.rb +1 -1
  10. data/app/controllers/thredded/messageboard_groups_controller.rb +29 -0
  11. data/app/controllers/thredded/messageboards_controller.rb +24 -10
  12. data/app/controllers/thredded/post_permalinks_controller.rb +10 -0
  13. data/app/controllers/thredded/private_post_permalinks_controller.rb +11 -0
  14. data/app/controllers/thredded/private_topics_controller.rb +2 -1
  15. data/app/controllers/thredded/theme_previews_controller.rb +3 -2
  16. data/app/controllers/thredded/topics_controller.rb +14 -7
  17. data/app/forms/thredded/private_topic_form.rb +4 -2
  18. data/app/helpers/thredded/application_helper.rb +1 -1
  19. data/app/helpers/thredded/urls_helper.rb +5 -3
  20. data/app/mailer_previews/thredded/base_mailer_preview.rb +12 -6
  21. data/app/mailer_previews/thredded/post_mailer_preview.rb +2 -1
  22. data/app/mailer_previews/thredded/private_post_mailer_preview.rb +2 -1
  23. data/app/mailer_previews/thredded/private_topic_mailer_preview.rb +2 -1
  24. data/app/models/concerns/thredded/post_common.rb +6 -5
  25. data/app/models/thredded/messageboard.rb +18 -1
  26. data/app/models/thredded/messageboard_group.rb +11 -0
  27. data/app/models/thredded/null_user.rb +2 -6
  28. data/app/policies/thredded/messageboard_group_policy.rb +15 -0
  29. data/app/policies/thredded/messageboard_policy.rb +4 -0
  30. data/app/policies/thredded/post_policy.rb +5 -0
  31. data/app/policies/thredded/private_post_policy.rb +5 -0
  32. data/app/view_models/thredded/messageboard_group_view.rb +14 -0
  33. data/app/views/thredded/messageboard_groups/new.html.erb +20 -0
  34. data/app/views/thredded/messageboards/_form.html.erb +19 -0
  35. data/app/views/thredded/messageboards/edit.html.erb +11 -0
  36. data/app/views/thredded/messageboards/index.html.erb +14 -6
  37. data/app/views/thredded/messageboards/new.html.erb +3 -16
  38. data/app/views/thredded/post_mailer/at_notification.html.erb +1 -1
  39. data/app/views/thredded/post_mailer/at_notification.text.erb +1 -1
  40. data/app/views/thredded/posts_common/_form.html.erb +1 -1
  41. data/app/views/thredded/posts_common/form/_after_content.html.erb +0 -0
  42. data/app/views/thredded/posts_common/form/_before_content.html.erb +0 -0
  43. data/app/views/thredded/posts_common/form/_content_field.html.erb +6 -0
  44. data/app/views/thredded/private_post_mailer/at_notification.html.erb +1 -1
  45. data/app/views/thredded/private_topics/_form.html.erb +1 -1
  46. data/app/views/thredded/topics/_form.html.erb +1 -1
  47. data/app/views/thredded/topics/index.html.erb +8 -0
  48. data/app/views/thredded/users/_link.html.erb +1 -1
  49. data/config/locales/en.yml +11 -0
  50. data/config/locales/pt-BR.yml +15 -3
  51. data/config/routes.rb +12 -1
  52. data/db/migrate/20160329231848_create_thredded.rb +8 -0
  53. data/db/seeds.rb +10 -5
  54. data/db/upgrade_migrations/20160429222452_upgrade_v0_3_to_v0_4.rb +14 -0
  55. data/heroku.gemfile +1 -1
  56. data/heroku.gemfile.lock +43 -43
  57. data/lib/generators/thredded/install/USAGE +1 -6
  58. data/lib/generators/thredded/install/install_generator.rb +0 -5
  59. data/lib/thredded/engine.rb +8 -0
  60. data/lib/thredded/version.rb +1 -1
  61. data/thredded.gemspec +1 -1
  62. metadata +17 -6
  63. data/app/controllers/thredded/setups_controller.rb +0 -54
  64. data/app/views/thredded/posts/_content_field.html.erb +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a5b1a2f3452e32092928cdeaa8ccb705e9f2a7d8
4
- data.tar.gz: ff7a72e796b7dd7b20d0becc114ec3734ead905b
3
+ metadata.gz: 8023f4374b36ef9c88f7619b9768b5be2c4bca46
4
+ data.tar.gz: 9d18f2e394e2bbf3e4469735cd48ca5f0003bfd2
5
5
  SHA512:
6
- metadata.gz: 9d4db4b55939ec62cc509a46ba8fe1e67c1f919ed826637e2202adf52ed1da8b67d6b4e58943b3d4fff8cef6ed5f7420fdab39a1464cb8eebca5c316be2e79e6
7
- data.tar.gz: 6b6a9c0faa439d62c8bd53fdc7937efbd51261416e9506f0b67b1eeb659e79b706594f7c06438d447c18bdaa4780a711ed0ffd100a6ddd5941fc9604ea3c462a
6
+ metadata.gz: 8144322f3774be32136e270fdf52733062d53917882e2759a1b122280332904df9fd558085d17a4b565dea5a4f5c17dc8019a81b16b022cd471518a64b3880d1
7
+ data.tar.gz: 41d7acb3dfbe5a619cb6abb47ee313ab04e6697867ec2c09566f7a6fadf85c32547b99729c844d57a9b2248738e9d455edcaf38588693f1e9d77bb24631c1f46
data/CHANGELOG.mkdn CHANGED
@@ -1,6 +1,26 @@
1
- # MASTER
1
+ # 0.4.0 - 2016-05-21
2
2
 
3
- ## 0.3.2 - 2016-05-04
3
+ **NB:** If updating to this version from 0.3.x, you will need to copy and run [this migration](https://github.com/thredded/thredded/blob/559fc205b9ee405abfe3968b981254f01f928027/db/upgrade_migrations/20160429222452_upgrade_v0_3_to_v0_4.rb).
4
+
5
+ ## Fixed
6
+
7
+ * Results from messageboards that cannot be read by the user no longer appear in the search results. [77293c](https://github.com/thredded/thredded/commit/77293c88980ec97f178d9a47405fdf915cd36ccc)
8
+ * Word-wrap is no longer a hard one (wraps in the middle of a word), and now wraps in a more
9
+ acceptable spot - after words, at hyphens, etc.
10
+ * Mailers now use permalinks to posts that always redirect to the correct page number. [#301](https://github.com/thredded/thredded/pull/301)
11
+
12
+ ## Added
13
+
14
+ * Messageboard groups ([#261](https://github.com/thredded/thredded/issues/261)) and editing ([#303](https://github.com/thredded/thredded/pull/303)).
15
+ * Spoiler(s) tag for post contents [5c8102a](https://github.com/thredded/thredded/commit/5c8102) `[spoiler]vader is luke's father[spoiler]`
16
+ * Styled blockquote tags.
17
+ * Empty partials before and after post textareas (for customization and extensibility) [#293](https://github.com/thredded/thredded/pull/293)
18
+ * New topic form page now allows pre-filling the fields from URL parameters. [#297](https://github.com/thredded/thredded/issues/297)
19
+ * Date format fix for dates older than 1 week. [9d71ba](https://github.com/thredded/thredded/commit/9d71ba2f1ddeac761e084e872a4b0a84ab62e35c)
20
+
21
+ See the full list of changes here: https://github.com/thredded/thredded/compare/v0.3.2...v0.4.0.
22
+
23
+ # 0.3.2 - 2016-05-04
4
24
 
5
25
  * Main app routes are delegated correctly when using the standalone layout. [8a2ff56](https://github.com/thredded/thredded/commit/8a2ff56f73afe0d6e8e8ecede9666b8d65817fa3)
6
26
  * Posts now have `word-break: break-all` applied to prevent overly long string form breaking the layout. [#267](https://github.com/thredded/thredded/issues/267)
data/README.mkdn CHANGED
@@ -37,18 +37,17 @@ dependencies other than the database and, if configured in the parent applicatio
37
37
  backend dependency such as Redis. Currently only MRI Ruby 2.2+ is supported. We would love to
38
38
  support JRuby and Rubinius as well.
39
39
 
40
- If you're looking for variations on a theme - see [Forem] and [Discourse]. Forem is also an engine,
41
- while Discourse is a full app.
40
+ If you're looking for variations on a theme - see [Discourse]. However, It is a full rails
41
+ application and not an engine like Thredded.
42
42
 
43
43
  [Discourse]: http://www.discourse.org/
44
- [Forem]: https://github.com/rubysherpas/forem
45
44
 
46
45
  ## Installation
47
46
 
48
47
  Add the gem to your Gemfile:
49
48
 
50
49
  ```ruby
51
- gem 'thredded', '~> 0.3.2'
50
+ gem 'thredded', '~> 0.4.0'
52
51
  ```
53
52
 
54
53
  Add the Thredded [initializer] to your parent app by running the install generator.
@@ -89,10 +88,11 @@ DbTextSearch::CaseInsensitive.add_index(
89
88
 
90
89
  ### Migrating from Forem
91
90
 
92
- Using [Forem]? Thredded provides [a migration][forem-to-thredded] to copy all your existing forums from Forem over
91
+ Are you currently using [Forem]? Thredded provides [a migration][forem-to-thredded] to copy all of your existing data from Forem over
93
92
  to Thredded.
94
93
 
95
94
  [forem-to-thredded]: https://github.com/thredded/thredded/wiki/Migrate-from-Forem
95
+ [Forem]: https://github.com/rubysherpas/forem
96
96
 
97
97
  ## Views and other assets
98
98
 
@@ -147,6 +147,18 @@ mkdir -p app/views/thredded/posts && cp "$(bundle show thredded)/$_/_post.html.e
147
147
  customizations are still compatible with the new version of thredded. This is difficult and error-prone.
148
148
  Whenever possible, use the styles and i18n to customize Thredded to your needs.
149
149
 
150
+ #### Empty view partials included for customization
151
+
152
+ There are 2 empty view partials included in the gem that exist for the purpose of being overridden
153
+ in the parent app *if desired*. They are:
154
+
155
+ * `app/views/thredded/posts_common/form/_before_content.html.erb`
156
+ * `app/views/thredded/posts_common/form/_after_content.html.erb`
157
+
158
+ And are rendered directly before, and directly after the textarea where users type their post
159
+ contents. These exist in the case where a messageboard would like to add things like, wysiwyg/wymean
160
+ editors, buttons, help links, help copy, further customization for the textarea, etc.
161
+
150
162
  ## Theming
151
163
 
152
164
  The engine comes by default with a light and effective implementation of the
@@ -39,3 +39,12 @@
39
39
  fill: currentColor;
40
40
  }
41
41
 
42
+ %thredded--blockquote {
43
+ margin: 0 0 0.75rem;
44
+ border-left: solid 5px $thredded-blockquote-border-color;
45
+ padding: 1rem;
46
+
47
+ p:last-of-type {
48
+ margin-bottom: 0;
49
+ }
50
+ }
@@ -31,6 +31,9 @@ $thredded-nav-color: $thredded-text-color !default;
31
31
  $thredded-nav-hover-color: $thredded-action-color !default;
32
32
  $thredded-nav-current-color: $thredded-action-color !default;
33
33
  $thredded-secondary-nav-color: $thredded-secondary-text-color !default;
34
+ $thredded-spoiler-hidden-color: $thredded-light-gray !default;
35
+ $thredded-spoiler-shown-color: black !default;
36
+
34
37
 
35
38
  // Colors of alerts and flash messages
36
39
  $thredded-alert-danger-background: #fbe3e4 !default;
@@ -45,6 +48,7 @@ $thredded-alert-warning-color: #8a6d3b !default;
45
48
  // Borders
46
49
  $thredded-base-border-color: $thredded-light-gray !default;
47
50
  $thredded-base-border: 1px solid $thredded-base-border-color !default;
51
+ $thredded-blockquote-border-color: $thredded-light-gray !default;
48
52
 
49
53
  // Form inputs
50
54
  $thredded-form-background: $thredded-background-color !default;
@@ -50,6 +50,18 @@
50
50
  margin-bottom: 0;
51
51
  }
52
52
 
53
- &--messageboard--create {
53
+ &--messageboards--actions {
54
54
  text-align: center;
55
+ a {
56
+ display: block;
57
+ margin-top: $thredded-small-spacing;
58
+ }
59
+ @include thredded-media-tablet-and-up {
60
+ a {
61
+ display: inline-block;
62
+ }
63
+ a + a {
64
+ margin-left: $thredded-small-spacing;
65
+ }
66
+ }
55
67
  }
@@ -57,7 +57,7 @@
57
57
  &--post--content {
58
58
  font-size: 1.063rem; // 17px
59
59
  line-height: 1.65;
60
- word-break: break-all;
60
+ word-break: break-word;
61
61
  a {
62
62
  @extend %thredded--link;
63
63
  }
@@ -74,4 +74,18 @@
74
74
  table {
75
75
  @extend %thredded--table;
76
76
  }
77
+ blockquote {
78
+ @extend %thredded--blockquote;
79
+ }
80
+
81
+ &--spoiler {
82
+ color: $thredded-spoiler-hidden-color;
83
+ background-color: $thredded-spoiler-hidden-color;
84
+ cursor: pointer;
85
+
86
+ &:hover,
87
+ &:focus {
88
+ color: $thredded-spoiler-shown-color;
89
+ }
90
+ }
77
91
  }
@@ -23,7 +23,7 @@
23
23
  border-color: transparent;
24
24
  font-size: $thredded-font-size-small;
25
25
  line-height: 1rem;
26
- min-width: 12.8125rem;
26
+ min-width: 13rem;
27
27
  text-align: right;
28
28
  width: auto;
29
29
  padding: 0.90625rem $padding-x 0.8125rem $padding-x;
@@ -95,7 +95,7 @@ module Thredded
95
95
  end
96
96
 
97
97
  def update_user_activity
98
- return if messageboard.nil?
98
+ return if messageboard.nil? || !signed_in?
99
99
 
100
100
  Thredded::ActivityUpdaterJob.perform_later(
101
101
  thredded_current_user.id,
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Thredded
4
+ class MessageboardGroupsController < Thredded::ApplicationController
5
+ def new
6
+ @messageboard_group = MessageboardGroup.new
7
+ authorize @messageboard_group, :create?
8
+ end
9
+
10
+ def create
11
+ @messageboard_group = MessageboardGroup.new(messageboard_group_params)
12
+ authorize @messageboard_group, :create?
13
+
14
+ if @messageboard_group.save
15
+ redirect_to root_path
16
+ else
17
+ render action: :new
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def messageboard_group_params
24
+ params
25
+ .require(:messageboard_group)
26
+ .permit(:name)
27
+ end
28
+ end
29
+ end
@@ -1,42 +1,56 @@
1
1
  # frozen_string_literal: true
2
2
  module Thredded
3
3
  class MessageboardsController < Thredded::ApplicationController
4
+ before_action :thredded_require_login!, only: [:new, :create, :edit, :update]
5
+
4
6
  def index
5
- @messageboards = thredded_current_user.thredded_can_read_messageboards
7
+ @groups = thredded_current_user
8
+ .thredded_can_read_messageboards
9
+ .preload(:group).group_by(&:group)
10
+ .map { |(group, messageboards)| MessageboardGroupView.new(group, messageboards) }
6
11
  end
7
12
 
8
13
  def new
9
14
  @messageboard = Messageboard.new
15
+ @messageboard_group = MessageboardGroup.all
10
16
  authorize_creating @messageboard
11
17
  end
12
18
 
13
19
  def create
14
20
  @messageboard = Messageboard.new(messageboard_params)
15
21
  authorize_creating @messageboard
16
-
17
- if signed_in? && @messageboard.save
22
+ if @messageboard.save
18
23
  Topic.transaction do
19
24
  @topic = Topic.create!(topic_params)
20
25
  @post = Post.create!(post_params)
21
26
  end
22
-
23
27
  redirect_to root_path
24
28
  else
25
- show_sign_in_error unless signed_in?
26
- render action: :new
29
+ render :new
27
30
  end
28
31
  end
29
32
 
30
- private
33
+ def edit
34
+ @messageboard = Messageboard.friendly.find(params[:id])
35
+ authorize @messageboard, :update?
36
+ end
31
37
 
32
- def show_sign_in_error
33
- flash.now[:error] = 'You are not signed in. Sign in or create an account before creating your messageboard.'
38
+ def update
39
+ @messageboard = Messageboard.friendly.find(params[:id])
40
+ authorize @messageboard, :update?
41
+ if @messageboard.update(messageboard_params)
42
+ redirect_to messageboard_topics_path(@messageboard), notice: I18n.t('thredded.messageboard.updated_notice')
43
+ else
44
+ render :new
45
+ end
34
46
  end
35
47
 
48
+ private
49
+
36
50
  def messageboard_params
37
51
  params
38
52
  .require(:messageboard)
39
- .permit(:description, :name, :posting_permission, :security)
53
+ .permit(:name, :description, :messageboard_group_id)
40
54
  end
41
55
 
42
56
  def topic_params
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ class PostPermalinksController < ApplicationController
4
+ def show
5
+ post = Post.find(params[:id])
6
+ authorize post, :read?
7
+ redirect_to post_url(post), status: :found
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ class PrivatePostPermalinksController < ApplicationController
4
+ before_action :thredded_require_login!
5
+ def show
6
+ private_post = PrivatePost.find(params[:id])
7
+ authorize private_post, :read?
8
+ redirect_to post_url(private_post), status: :found
9
+ end
10
+ end
11
+ end
@@ -13,7 +13,8 @@ module Thredded
13
13
  .for_user(thredded_current_user)
14
14
  .order_recently_updated_first
15
15
  .includes(:last_user, :user)
16
- .page(params[:page]))
16
+ .page(params[:page])
17
+ )
17
18
 
18
19
  PrivateTopicForm.new(user: thredded_current_user).tap do |form|
19
20
  @new_private_topic = form if policy(form.private_topic).create?
@@ -23,8 +23,9 @@ module Thredded
23
23
  @private_topic = PrivateTopicView.from_user(private_topic, @user)
24
24
  @private_posts = PostsPageView.new(@user, private_topic, private_topic.posts.page(1).limit(3))
25
25
  @private_post = private_topic.posts.build(
26
- id: 1337, postable: private_topic, content: 'A private hello world', user: @user)
27
- @preferences = UserPreferencesForm.new(user: @user, messageboard: @messageboard)
26
+ id: 1337, postable: private_topic, content: 'A private hello world', user: @user
27
+ )
28
+ @preferences = UserPreferencesForm.new(user: @user, messageboard: @messageboard)
28
29
  end
29
30
  end
30
31
  end
@@ -15,7 +15,8 @@ module Thredded
15
15
  messageboard.topics
16
16
  .order_sticky_first.order_recently_updated_first
17
17
  .includes(:categories, :last_user, :user)
18
- .page(current_page))
18
+ .page(current_page)
19
+ )
19
20
  TopicForm.new(messageboard: messageboard, user: thredded_current_user).tap do |form|
20
21
  @new_topic = form if policy(form.topic).create?
21
22
  end
@@ -36,17 +37,23 @@ module Thredded
36
37
 
37
38
  def search
38
39
  @query = params[:q].to_s
40
+ topics_scope = if messageboard_or_nil
41
+ messageboard.topics
42
+ else
43
+ Topic.where(messageboard_id: thredded_current_user.thredded_can_read_messageboards.pluck(:id))
44
+ end
39
45
  @topics = Thredded::TopicsPageView.new(
40
46
  thredded_current_user,
41
- (messageboard_or_nil ? messageboard.topics : Topic)
47
+ topics_scope
42
48
  .search_query(@query)
43
49
  .order_recently_updated_first
44
50
  .includes(:categories, :last_user, :user)
45
- .page(current_page))
51
+ .page(current_page)
52
+ )
46
53
  end
47
54
 
48
55
  def new
49
- @new_topic = TopicForm.new(messageboard: messageboard, user: thredded_current_user)
56
+ @new_topic = TopicForm.new(new_topic_params)
50
57
  authorize_creating @new_topic.topic
51
58
  end
52
59
 
@@ -58,7 +65,8 @@ module Thredded
58
65
  @category.topics
59
66
  .unstuck
60
67
  .order_recently_updated_first
61
- .page(current_page))
68
+ .page(current_page)
69
+ )
62
70
  render :index
63
71
  end
64
72
 
@@ -103,12 +111,11 @@ module Thredded
103
111
  params
104
112
  .require(:topic)
105
113
  .permit(:title, :locked, :sticky, category_ids: [])
106
- .merge(user: thredded_current_user)
107
114
  end
108
115
 
109
116
  def new_topic_params
110
117
  params
111
- .require(:topic)
118
+ .fetch(:topic, {})
112
119
  .permit(:title, :locked, :sticky, :content, category_ids: [])
113
120
  .merge(
114
121
  messageboard: messageboard,
@@ -49,13 +49,15 @@ module Thredded
49
49
  title: title,
50
50
  users: private_users,
51
51
  user: non_null_user,
52
- last_user: non_null_user)
52
+ last_user: non_null_user
53
+ )
53
54
  end
54
55
 
55
56
  def post
56
57
  @post ||= private_topic.posts.build(
57
58
  content: content,
58
- user: non_null_user)
59
+ user: non_null_user
60
+ )
59
61
  end
60
62
 
61
63
  private
@@ -20,7 +20,7 @@ module Thredded
20
20
  # @param datetime [DateTime]
21
21
  # @return [String] html_safe datetime presentation
22
22
  def time_ago(datetime)
23
- timeago_tag datetime, lang: I18n.locale.to_s.downcase, date_only: false, nojs: true
23
+ timeago_tag datetime, lang: I18n.locale.to_s.downcase, format: :short, nojs: true
24
24
  end
25
25
 
26
26
  def paginate(collection, args = {})
@@ -22,12 +22,14 @@ module Thredded
22
22
  if topic.private?
23
23
  private_topic_url(
24
24
  topic.slug,
25
- params)
25
+ params
26
+ )
26
27
  else
27
28
  messageboard_topic_url(
28
29
  topic.messageboard.slug,
29
30
  topic.slug,
30
- params)
31
+ params
32
+ )
31
33
  end
32
34
  end
33
35
 
@@ -41,7 +43,7 @@ module Thredded
41
43
  # @return [String] URL of the topic page with the post anchor.
42
44
  def post_url(post, params = {})
43
45
  params = params.dup
44
- params[:anchor] ||= dom_id(post)
46
+ params[:anchor] ||= ActionView::RecordIdentifier.dom_id(post)
45
47
  params[:page] ||= post.page
46
48
  topic_url(post.postable, params)
47
49
  end
@@ -30,7 +30,8 @@ MARKDOWN
30
30
  sticky: [false, true].sample,
31
31
  updated_at: Time.zone.now,
32
32
  user: mock_user,
33
- ))
33
+ )
34
+ )
34
35
  end
35
36
 
36
37
  def mock_post(attr = {})
@@ -44,7 +45,8 @@ MARKDOWN
44
45
  postable: topic,
45
46
  updated_at: Time.zone.now,
46
47
  user: topic.last_user,
47
- ))
48
+ )
49
+ )
48
50
  end
49
51
 
50
52
  def mock_private_topic(attr = {})
@@ -58,7 +60,8 @@ MARKDOWN
58
60
  posts_count: 1 + rand(42),
59
61
  updated_at: Time.zone.now,
60
62
  user: mock_user,
61
- ))
63
+ )
64
+ )
62
65
  end
63
66
 
64
67
  def mock_private_post(attr = {})
@@ -71,7 +74,8 @@ MARKDOWN
71
74
  postable: private_topic,
72
75
  updated_at: Time.zone.now,
73
76
  user: private_topic.last_user,
74
- ))
77
+ )
78
+ )
75
79
  end
76
80
 
77
81
  def mock_messageboard(attr = {})
@@ -86,7 +90,8 @@ MARKDOWN
86
90
  posts_count: rand(1337),
87
91
  topics_count: rand(42),
88
92
  updated_at: Time.zone.now,
89
- ))
93
+ )
94
+ )
90
95
  end
91
96
 
92
97
  def mock_user(attr = {})
@@ -95,7 +100,8 @@ MARKDOWN
95
100
  attr.reverse_merge(
96
101
  Thredded.user_name_column => name,
97
102
  email: "#{name.downcase}@test.com",
98
- ))
103
+ )
104
+ )
99
105
  end
100
106
  end
101
107
  end
@@ -5,7 +5,8 @@ module Thredded
5
5
  def at_notification
6
6
  PostMailer.at_notification(
7
7
  mock_post(content: mock_content(mention_users: %w(glebm joel))),
8
- %w(glebm@test.com joel@test.com))
8
+ %w(glebm@test.com joel@test.com)
9
+ )
9
10
  end
10
11
  end
11
12
  end
@@ -5,7 +5,8 @@ module Thredded
5
5
  def at_notification
6
6
  PrivatePostMailer.at_notification(
7
7
  mock_private_post(content: mock_content(mention_users: %w(glebm joel))),
8
- %w(glebm@test.com joel@test.com))
8
+ %w(glebm@test.com joel@test.com)
9
+ )
9
10
  end
10
11
  end
11
12
  end
@@ -9,7 +9,8 @@ module Thredded
9
9
  mock_private_post(content: mock_content(mention_users: ['glebm']), postable: private_topic)
10
10
  ]
11
11
  end,
12
- %w(glebm@test.com joel@test.com))
12
+ %w(glebm@test.com joel@test.com)
13
+ )
13
14
  end
14
15
  end
15
16
  end
@@ -17,21 +17,22 @@ module Thredded
17
17
  end
18
18
  ].freeze
19
19
 
20
- WHITELIST_ELEMENTS = HTML::Pipeline::SanitizationFilter::WHITELIST[:elements] + [
21
- 'iframe',
22
- ].freeze
20
+ WHITELIST_ELEMENTS = HTML::Pipeline::SanitizationFilter::WHITELIST[:elements] + %w(
21
+ iframe span
22
+ ).freeze
23
23
 
24
24
  WHITELIST = HTML::Pipeline::SanitizationFilter::WHITELIST.deep_merge(
25
25
  elements: WHITELIST_ELEMENTS,
26
26
  transformers: WHITELIST_TRANSFORMERS,
27
27
  attributes: {
28
28
  'a' => %w(href rel),
29
- 'iframe' => %w(src width height frameborder allowfullscreen sandbox seamless)
29
+ 'iframe' => %w(src width height frameborder allowfullscreen sandbox seamless),
30
+ 'span' => %w(class),
30
31
  },
31
32
  add_attributes: {
32
33
  'iframe' => {
33
34
  'seamless' => 'seamless',
34
- 'sandbox' => 'allow-forms allow-scripts'
35
+ 'sandbox' => 'allow-forms allow-scripts',
35
36
  }
36
37
  }
37
38
  ).freeze
@@ -6,7 +6,16 @@ module Thredded
6
6
  use: [:slugged, :reserved],
7
7
  # Avoid route conflicts
8
8
  reserved_words: ::Thredded::FriendlyIdReservedWordsAndPagination.new(
9
- %w(messageboards preferences private-topics autocomplete-users theme-preview)
9
+ %w(
10
+ admin
11
+ autocomplete-users
12
+ messageboards
13
+ posts
14
+ preferences
15
+ private-posts
16
+ private-topics
17
+ theme-preview
18
+ )
10
19
  )
11
20
 
12
21
  validates :name, uniqueness: true, length: { maximum: 60 }, presence: true
@@ -33,8 +42,16 @@ module Thredded
33
42
  through: :recently_active_user_details,
34
43
  source: :user
35
44
 
45
+ belongs_to :group,
46
+ inverse_of: :messageboards,
47
+ foreign_key: :messageboard_group_id,
48
+ class_name: 'Thredded::MessageboardGroup'
49
+
36
50
  default_scope { where(closed: false).order(topics_count: :desc) }
37
51
 
52
+ scope :top_level_messageboards, -> { where(group: nil) }
53
+ scope :by_messageboard_group, ->(group) { where(group: group.id) }
54
+
38
55
  def latest_user
39
56
  latest_topic.last_user
40
57
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ class MessageboardGroup < ActiveRecord::Base
4
+ has_many :messageboards,
5
+ inverse_of: :group,
6
+ foreign_key: :messageboard_group_id,
7
+ dependent: :nullify
8
+
9
+ validates :name, presence: true
10
+ end
11
+ end
@@ -12,15 +12,11 @@ module Thredded
12
12
  end
13
13
 
14
14
  def id
15
- 0
16
- end
17
-
18
- def member_of?(_)
19
- false
15
+ nil
20
16
  end
21
17
 
22
18
  def name
23
- 'Anonymous User'
19
+ I18n.t('thredded.null_user_name')
24
20
  end
25
21
 
26
22
  def to_s
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ class MessageboardGroupPolicy
4
+ # @param user [Thredded.user_class]
5
+ # @param messageboard_group [Thredded::MessageboardGroup]
6
+ def initialize(user, group)
7
+ @user = user
8
+ @group = group
9
+ end
10
+
11
+ def create?
12
+ @user.thredded_admin?
13
+ end
14
+ end
15
+ end