thredded 0.11.1 → 0.12.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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -5
  3. data/app/assets/javascripts/thredded/components/post_form.es6 +4 -4
  4. data/app/assets/javascripts/thredded/components/quote_post.es6 +45 -0
  5. data/app/assets/javascripts/thredded/components/topic_form.es6 +4 -4
  6. data/app/assets/javascripts/thredded/core/on_page_load.es6 +8 -0
  7. data/app/assets/javascripts/thredded/dependencies.js +1 -1
  8. data/app/assets/stylesheets/thredded/_email.scss +2 -3
  9. data/app/assets/stylesheets/thredded/components/_preferences.scss +17 -4
  10. data/app/controllers/concerns/thredded/new_post_params.rb +20 -0
  11. data/app/controllers/concerns/thredded/new_private_post_params.rb +20 -0
  12. data/app/controllers/thredded/posts_controller.rb +22 -13
  13. data/app/controllers/thredded/preferences_controller.rb +1 -0
  14. data/app/controllers/thredded/private_posts_controller.rb +24 -12
  15. data/app/controllers/thredded/private_topics_controller.rb +4 -1
  16. data/app/controllers/thredded/theme_previews_controller.rb +4 -2
  17. data/app/controllers/thredded/topics_controller.rb +13 -2
  18. data/app/forms/thredded/post_form.rb +52 -0
  19. data/app/forms/thredded/private_post_form.rb +48 -0
  20. data/app/forms/thredded/private_topic_form.rb +8 -0
  21. data/app/forms/thredded/topic_form.rb +8 -0
  22. data/app/forms/thredded/user_preferences_form.rb +7 -1
  23. data/app/helpers/thredded/urls_helper.rb +18 -0
  24. data/app/models/thredded/topic.rb +3 -3
  25. data/app/policies/thredded/private_topic_policy.rb +1 -1
  26. data/app/view_models/thredded/messageboard_group_view.rb +1 -1
  27. data/app/view_models/thredded/post_view.rb +19 -3
  28. data/app/view_models/thredded/private_topic_view.rb +0 -4
  29. data/app/view_models/thredded/topic_view.rb +0 -4
  30. data/app/views/thredded/posts/_form.html.erb +0 -2
  31. data/app/views/thredded/posts/edit.html.erb +2 -5
  32. data/app/views/thredded/posts/new.html.erb +15 -0
  33. data/app/views/thredded/posts_common/_actions.html.erb +3 -0
  34. data/app/views/thredded/posts_common/_form.html.erb +5 -3
  35. data/app/views/thredded/posts_common/_header.html.erb +3 -1
  36. data/app/views/thredded/posts_common/actions/_quote.html.erb +4 -0
  37. data/app/views/thredded/preferences/_form.html.erb +3 -5
  38. data/app/views/thredded/preferences/_messageboards_nav.html.erb +8 -0
  39. data/app/views/thredded/preferences/_messageboards_nav_item.html.erb +2 -0
  40. data/app/views/thredded/preferences/edit.html.erb +13 -3
  41. data/app/views/thredded/private_posts/_form.html.erb +0 -2
  42. data/app/views/thredded/private_posts/edit.html.erb +2 -4
  43. data/app/views/thredded/private_posts/new.html.erb +11 -0
  44. data/app/views/thredded/private_topics/_form.html.erb +2 -2
  45. data/app/views/thredded/private_topics/index.html.erb +1 -2
  46. data/app/views/thredded/private_topics/new.html.erb +0 -1
  47. data/app/views/thredded/private_topics/show.html.erb +5 -3
  48. data/app/views/thredded/shared/_nav.html.erb +1 -7
  49. data/app/views/thredded/shared/nav/_standalone.html.erb +3 -3
  50. data/app/views/thredded/shared/nav/_standalone_profile.html.erb +3 -0
  51. data/app/views/thredded/theme_previews/show.html.erb +3 -17
  52. data/app/views/thredded/topics/_form.html.erb +3 -2
  53. data/app/views/thredded/topics/index.html.erb +0 -2
  54. data/app/views/thredded/topics/new.html.erb +0 -2
  55. data/app/views/thredded/topics/show.html.erb +1 -3
  56. data/config/locales/en.yml +4 -3
  57. data/config/locales/es.yml +4 -3
  58. data/config/locales/pl.yml +4 -3
  59. data/config/locales/pt-BR.yml +4 -3
  60. data/config/locales/ru.yml +12 -7
  61. data/config/routes.rb +2 -0
  62. data/db/migrate/20160329231848_create_thredded.rb +1 -1
  63. data/db/upgrade_migrations/20170420163138_upgrade_thredded_v0_11_to_v0_12.rb +25 -0
  64. data/lib/thredded.rb +0 -1
  65. data/lib/thredded/content_formatter.rb +11 -0
  66. data/lib/thredded/version.rb +1 -1
  67. data/vendor/assets/javascripts/autosize.js +290 -0
  68. metadata +15 -17
  69. data/app/views/thredded/preferences/_header.html.erb +0 -1
@@ -2,9 +2,14 @@
2
2
  module Thredded
3
3
  class TopicsController < Thredded::ApplicationController # rubocop:disable Metrics/ClassLength
4
4
  include Thredded::NewTopicParams
5
+ include Thredded::NewPostParams
5
6
 
6
7
  before_action :thredded_require_login!,
7
8
  only: %i(edit new update create destroy follow unfollow)
9
+
10
+ before_action :use_topic_messageboard,
11
+ only: %i(show edit update destroy follow unfollow)
12
+
8
13
  after_action :update_user_activity
9
14
 
10
15
  after_action :verify_authorized, except: %i(search)
@@ -43,7 +48,7 @@ module Thredded
43
48
  )
44
49
  end
45
50
 
46
- @new_post = messageboard.posts.build(postable: topic)
51
+ @new_post = Thredded::PostForm.new(user: thredded_current_user, topic: topic, post_params: new_post_params)
47
52
  end
48
53
 
49
54
  def search
@@ -172,7 +177,13 @@ module Thredded
172
177
  # @return [Thredded::Topic]
173
178
  # @raise [Thredded::Errors::TopicNotFound] if the topic with the given slug does not exist.
174
179
  def topic
175
- @topic ||= messageboard.topics.friendly_find!(params[:id])
180
+ @topic ||= Thredded::Topic.friendly_find!(params[:id])
181
+ end
182
+
183
+ # Use the topic's messageboard instead of the one specified in the URL,
184
+ # to account for `params[:messageboard_id]` pointing to the wrong messageboard
185
+ def use_topic_messageboard
186
+ @messageboard = topic.messageboard
176
187
  end
177
188
 
178
189
  def topic_params
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ class PostForm
4
+ attr_reader :post, :topic
5
+ delegate :id,
6
+ :persisted?,
7
+ :content,
8
+ :content=,
9
+ to: :@post
10
+
11
+ # @param user [Thredded.user_class]
12
+ # @param topic [Topic]
13
+ # @param post [PrivatePost]
14
+ # @param post_params [Hash]
15
+ def initialize(user:, topic:, post: nil, post_params: {})
16
+ @messageboard = topic.messageboard
17
+ @topic = topic
18
+ @post = post ? post : topic.posts.build
19
+
20
+ if post_params.include?(:quote_post)
21
+ post_params[:content] =
22
+ Thredded::ContentFormatter.quote_content(post_params.delete(:quote_post).content)
23
+ end
24
+ @post.attributes = post_params.merge(
25
+ user: (user unless user.thredded_anonymous?),
26
+ messageboard: topic.messageboard
27
+ )
28
+ end
29
+
30
+ def self.for_persisted(post)
31
+ new(user: post.user, topic: post.postable, post: post)
32
+ end
33
+
34
+ def submit_path
35
+ Thredded::UrlsHelper.url_for([@messageboard, @topic, @post, only_path: true])
36
+ end
37
+
38
+ def preview_path
39
+ if @post.persisted?
40
+ Thredded::UrlsHelper.messageboard_topic_post_preview_path(@messageboard, @topic, @post)
41
+ else
42
+ Thredded::UrlsHelper.preview_new_messageboard_topic_post_path(@messageboard, @topic)
43
+ end
44
+ end
45
+
46
+ def save
47
+ return false unless @post.valid?
48
+ @post.save!
49
+ true
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ class PrivatePostForm
4
+ attr_reader :post, :topic
5
+ delegate :id,
6
+ :persisted?,
7
+ :content,
8
+ :content=,
9
+ to: :@post
10
+
11
+ # @param user [Thredded.user_class]
12
+ # @param topic [PrivateTopic]
13
+ # @param post [Post]
14
+ # @param post_params [Hash]
15
+ def initialize(user:, topic:, post: nil, post_params: {})
16
+ @topic = topic
17
+ @post = post ? post : topic.posts.build
18
+
19
+ if post_params.include?(:quote_post)
20
+ post_params[:content] =
21
+ Thredded::ContentFormatter.quote_content(post_params.delete(:quote_post).content)
22
+ end
23
+ @post.attributes = post_params.merge(user: (user unless user.thredded_anonymous?))
24
+ end
25
+
26
+ def self.for_persisted(post)
27
+ new(user: post.user, topic: post.postable, post: post)
28
+ end
29
+
30
+ def submit_path
31
+ Thredded::UrlsHelper.url_for([@topic, @post, only_path: true])
32
+ end
33
+
34
+ def preview_path
35
+ if @post.persisted?
36
+ Thredded::UrlsHelper.private_topic_private_post_preview_path(@topic, @post)
37
+ else
38
+ Thredded::UrlsHelper.preview_new_private_topic_private_post_path(@topic)
39
+ end
40
+ end
41
+
42
+ def save
43
+ return false unless @post.valid?
44
+ @post.save!
45
+ true
46
+ end
47
+ end
48
+ end
@@ -60,6 +60,14 @@ module Thredded
60
60
  )
61
61
  end
62
62
 
63
+ def submit_path
64
+ Thredded::UrlsHelper.url_for([private_topic, only_path: true])
65
+ end
66
+
67
+ def preview_path
68
+ Thredded::UrlsHelper.preview_new_private_topic_path
69
+ end
70
+
63
71
  private
64
72
 
65
73
  def topic_categories
@@ -55,6 +55,14 @@ module Thredded
55
55
  )
56
56
  end
57
57
 
58
+ def submit_path
59
+ Thredded::UrlsHelper.url_for([messageboard, topic, only_path: true])
60
+ end
61
+
62
+ def preview_path
63
+ Thredded::UrlsHelper.preview_new_messageboard_topic_path(messageboard)
64
+ end
65
+
58
66
  private
59
67
 
60
68
  # @return [Thredded.user_class, nil] return a user or nil if the user is a NullUser
@@ -22,9 +22,11 @@ module Thredded
22
22
 
23
23
  # @param user [Thredded.user_class]
24
24
  # @param messageboard [Thredded::Messageboard, nil]
25
- def initialize(user:, messageboard: nil, params: {})
25
+ # @param messageboards [ActiveRecord::Relation<Thredded::Messageboard>]
26
+ def initialize(user:, messageboard: nil, messageboards: nil, params: {})
26
27
  @user = user
27
28
  @messageboard = messageboard
29
+ @messageboards = messageboards
28
30
  super(params)
29
31
  end
30
32
 
@@ -46,6 +48,10 @@ module Thredded
46
48
  true
47
49
  end
48
50
 
51
+ def messageboard_groups
52
+ @messageboard_groups ||= MessageboardGroupView.grouped(@messageboards)
53
+ end
54
+
49
55
  def notifications_for_private_topics
50
56
  for_every_notifier(user_preference.notifications_for_private_topics)
51
57
  end
@@ -104,6 +104,14 @@ module Thredded
104
104
  end
105
105
  end
106
106
 
107
+ def quote_post_path(post)
108
+ if post.private_topic_post?
109
+ quote_private_topic_private_post_path(post.postable, post)
110
+ else
111
+ quote_messageboard_topic_post_path(post.messageboard, post.postable, post)
112
+ end
113
+ end
114
+
107
115
  def mark_unread_path(post, _params = {})
108
116
  if post.private_topic_post?
109
117
  mark_as_unread_private_topic_private_post_path(post.postable, post)
@@ -111,5 +119,15 @@ module Thredded
111
119
  mark_as_unread_messageboard_topic_post_path(post.messageboard, post.postable, post)
112
120
  end
113
121
  end
122
+
123
+ # @param post [Post, PrivatePost]
124
+ # @return [String] post permalink path
125
+ def permalink_path(post)
126
+ if post.private_topic_post?
127
+ private_post_permalink_path(post)
128
+ else
129
+ post_permalink_path(post)
130
+ end
131
+ end
114
132
  end
115
133
  end
@@ -22,8 +22,7 @@ module Thredded
22
22
 
23
23
  extend FriendlyId
24
24
  friendly_id :slug_candidates,
25
- use: [:history, :reserved, :scoped],
26
- scope: :messageboard,
25
+ use: %i(history reserved),
27
26
  # Avoid route conflicts
28
27
  reserved_words: ::Thredded::FriendlyIdReservedWordsAndPagination.new(%w(topics))
29
28
 
@@ -153,7 +152,8 @@ module Thredded
153
152
  def slug_candidates
154
153
  [
155
154
  :title,
156
- [:title, '-topic'],
155
+ [:title, '-', messageboard.try(:name)],
156
+ [:title, '-', messageboard.try(:name), '-topic']
157
157
  ]
158
158
  end
159
159
 
@@ -17,7 +17,7 @@ module Thredded
17
17
  end
18
18
 
19
19
  def update?
20
- @user.id == @private_topic.user_id
20
+ !@user.thredded_anonymous? && @user.id == @private_topic.user_id
21
21
  end
22
22
  end
23
23
  end
@@ -5,7 +5,7 @@ module Thredded
5
5
  delegate :name, to: :@group, allow_nil: true
6
6
  attr_reader :group, :messageboards
7
7
 
8
- # @param messageboard_scope [ActiveRecord::Relation]
8
+ # @param messageboard_scope [ActiveRecord::Relation<Thredded::Messageboard>]
9
9
  # @return [Array<MessageboardGroupView>]
10
10
  def self.grouped(messageboard_scope)
11
11
  messageboard_scope.preload(last_topic: [:last_user])
@@ -14,14 +14,18 @@ module Thredded
14
14
  to: :@post
15
15
 
16
16
  # @param post [Thredded::PostCommon]
17
- # @param policy [#update? #destroy?]
18
- # @param policy [Thredded::TopicView]
17
+ # @param policy [#create? #update? #destroy? #moderate?]
18
+ # @param topic_view [Thredded::TopicView]
19
19
  def initialize(post, policy, topic_view: nil)
20
20
  @post = post
21
21
  @policy = policy
22
22
  @topic_view = topic_view
23
23
  end
24
24
 
25
+ def can_reply?
26
+ @can_reply ||= @policy.create?
27
+ end
28
+
25
29
  def can_update?
26
30
  @can_update ||= @policy.update?
27
31
  end
@@ -34,6 +38,18 @@ module Thredded
34
38
  @can_moderate ||= @policy.moderate?
35
39
  end
36
40
 
41
+ def quote_url_params
42
+ if @post.private_topic_post?
43
+ { post: { quote_private_post_id: @post.id } }
44
+ else
45
+ { post: { quote_post_id: @post.id } }
46
+ end.update(anchor: 'post_content')
47
+ end
48
+
49
+ def quote_path
50
+ Thredded::UrlsHelper.quote_post_path(@post)
51
+ end
52
+
37
53
  def edit_path
38
54
  Thredded::UrlsHelper.edit_post_path(@post)
39
55
  end
@@ -47,7 +63,7 @@ module Thredded
47
63
  end
48
64
 
49
65
  def permalink_path
50
- Thredded::UrlsHelper.post_permalink_path(@post.id)
66
+ Thredded::UrlsHelper.permalink_path(@post)
51
67
  end
52
68
 
53
69
  # This cache key is used only for caching the content.
@@ -15,9 +15,5 @@ module Thredded
15
15
  end
16
16
  new(topic, read_state, Pundit.policy!(user, topic))
17
17
  end
18
-
19
- def new_post_preview_path
20
- Thredded::UrlsHelper.preview_new_private_topic_private_post_path(@topic)
21
- end
22
18
  end
23
19
  end
@@ -63,9 +63,5 @@ module Thredded
63
63
  def messageboard_path
64
64
  Thredded::UrlsHelper.messageboard_topics_path(@topic.messageboard)
65
65
  end
66
-
67
- def new_post_preview_path
68
- Thredded::UrlsHelper.preview_new_messageboard_topic_post_path(@topic.messageboard, @topic)
69
- end
70
66
  end
71
67
  end
@@ -1,7 +1,5 @@
1
1
  <%= render 'thredded/posts_common/form',
2
- topic: topic,
3
2
  post: post,
4
- preview_url: preview_url,
5
3
  content_label: t('thredded.posts.form.content_label'),
6
4
  button_text: button_text,
7
5
  button_submitting_text: local_assigns.key?(:button_submitting_text) ? button_submitting_text : nil %>
@@ -2,17 +2,14 @@
2
2
  <% content_for :thredded_page_id, 'thredded--edit-post' %>
3
3
  <% content_for :thredded_breadcrumbs do %>
4
4
  <ul class="thredded--navigation-breadcrumbs">
5
- <li><%= link_to t('thredded.nav.edit_post'), edit_post_path(@post) %></li>
5
+ <li><%= link_to t('thredded.nav.edit_post'), edit_post_path(@post_form.post) %></li>
6
6
  </ul>
7
7
  <% end %>
8
8
 
9
9
  <%= thredded_page do %>
10
10
  <section class="thredded--main-section">
11
11
  <%= render 'thredded/posts/form',
12
- messageboard: messageboard,
13
- topic: topic,
14
- post: @post,
15
- preview_url: messageboard_topic_post_preview_path(messageboard, @post.postable, @post),
12
+ post: @post_form,
16
13
  button_text: t('thredded.posts.form.update_btn'),
17
14
  button_submitting_text: t('thredded.posts.form.update_btn_submitting')%>
18
15
  </section>
@@ -0,0 +1,15 @@
1
+ <% content_for :thredded_page_title, @post_form.topic.title %>
2
+ <% content_for :thredded_page_id, 'thredded--topic--new-post' %>
3
+ <% content_for :thredded_breadcrumbs, render('thredded/shared/breadcrumbs') %>
4
+
5
+ <%= thredded_page do %>
6
+ <section class="thredded--main-section">
7
+ <div class="thredded--post-form--wrapper">
8
+ <h3 class="thredded--post-form--title"><%= t('thredded.posts.form.title_label') %></h3>
9
+ <%= render 'thredded/posts/form',
10
+ post: @post_form,
11
+ button_text: t('thredded.posts.form.create_btn'),
12
+ button_submitting_text: t('thredded.posts.form.create_btn_submitting') %>
13
+ </div>
14
+ </section>
15
+ <% end %>
@@ -1,5 +1,8 @@
1
1
  <% actions = capture do %>
2
2
  <%= view_hooks.post_common.actions.render self, post: post do %>
3
+ <% if post.can_reply? %>
4
+ <%= render 'thredded/posts_common/actions/quote', post: post %>
5
+ <% end %>
3
6
  <% if post.can_update? %>
4
7
  <%= render 'thredded/posts_common/actions/edit', post: post %>
5
8
  <% end %>
@@ -1,5 +1,7 @@
1
- <%# locals: messageboard, topic, post, preview_url, content_label, button_text, button_submitting_text. %>
2
- <%= form_for (post.private_topic_post? ? [topic, post] : [messageboard, topic, post]), as: :post,
1
+ <%# locals: post, content_label, button_text, button_submitting_text. %>
2
+ <%= form_for post,
3
+ url: post.submit_path,
4
+ as: :post,
3
5
  html: {
4
6
  class: 'thredded--form thredded--post-form',
5
7
  'data-thredded-post-form' => true,
@@ -8,7 +10,7 @@
8
10
  } do |form| %>
9
11
  <ul class="thredded--form-list">
10
12
  <%= render 'thredded/posts_common/form/content',
11
- form: form, content_label: content_label, preview_url: preview_url %>
13
+ form: form, content_label: content_label, preview_url: post.preview_path %>
12
14
  <li>
13
15
  <% button_submitting_text ||=
14
16
  post.persisted? ? t('thredded.form.update_btn_submitting') : t('thredded.form.create_btn_submitting') %>
@@ -2,5 +2,7 @@
2
2
  <header>
3
3
  <%= image_tag post.avatar_url, class: 'thredded--post--avatar' if post.user %>
4
4
  <h2 class="thredded--post--user"><%= user_link post.user %></h2>
5
- <p class="thredded--post--created-at"><%= time_ago post.created_at %></p>
5
+ <a href="<%= post.permalink_path %>" rel="nofollow" class="thredded--link thredded--post--created-at">
6
+ <%= time_ago post.created_at %>
7
+ </a>
6
8
  </header>
@@ -0,0 +1,4 @@
1
+ <%= link_to t('thredded.posts.quote_btn'), url_for(post.quote_url_params),
2
+ 'data-thredded-quote-post' => post.quote_path,
3
+ class: 'thredded--post--quote thredded--post--dropdown--actions--item',
4
+ rel: 'nofollow' %>
@@ -3,8 +3,6 @@
3
3
  class: 'thredded--form thredded--notification-preferences-form',
4
4
  'data-thredded-user-preferences-form' => true
5
5
  }) do |f| %>
6
-
7
- <h3><%= t 'thredded.preferences.form.global_preferences_label' %></h3>
8
6
  <ul class="thredded--form-list">
9
7
  <li>
10
8
  <%= f.label :auto_follow_topics do %>
@@ -52,9 +50,9 @@
52
50
  <% end %>
53
51
  </ul>
54
52
  <% if preferences.messageboard %>
55
- <h3>
56
- <%= t 'thredded.preferences.form.messageboard_preferences_label_html', messageboard: messageboard.name %>
57
- </h3>
53
+ <h2 class="thredded--preferences--title">
54
+ <%= t 'thredded.preferences.messageboard_preferences_title_html', messageboard: messageboard.name %>
55
+ </h2>
58
56
  <ul class="thredded--form-list" data-thredded-user-preferences-form-messageboard-fields>
59
57
  <li>
60
58
  <%= f.label :messageboard_auto_follow_topics do %>