thredded 0.11.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
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 %>