thredded 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -4
  3. data/app/assets/javascripts/thredded/components/post_form.es6 +5 -0
  4. data/app/assets/javascripts/thredded/components/preview_area.es6 +52 -0
  5. data/app/assets/javascripts/thredded/components/topic_form.es6 +3 -0
  6. data/app/assets/javascripts/thredded/core/debounce.es6 +32 -0
  7. data/app/assets/javascripts/thredded/core/hide_soft_keyboard.es6 +2 -1
  8. data/app/assets/javascripts/thredded/core/mention_autocompletion.es6 +2 -2
  9. data/app/assets/javascripts/thredded/core/on_page_load.es6 +2 -2
  10. data/app/assets/javascripts/thredded/core/thredded.es6 +1 -0
  11. data/app/assets/stylesheets/thredded/_thredded.scss +1 -0
  12. data/app/assets/stylesheets/thredded/components/_pagination.scss +10 -1
  13. data/app/assets/stylesheets/thredded/components/_preview_area.scss +11 -0
  14. data/app/controllers/concerns/thredded/new_private_topic_params.rb +24 -0
  15. data/app/controllers/concerns/thredded/new_topic_params.rb +18 -0
  16. data/app/controllers/concerns/thredded/render_preview.rb +15 -0
  17. data/app/controllers/thredded/post_previews_controller.rb +28 -0
  18. data/app/controllers/thredded/posts_controller.rb +2 -0
  19. data/app/controllers/thredded/private_post_previews_controller.rb +28 -0
  20. data/app/controllers/thredded/private_topic_previews_controller.rb +14 -0
  21. data/app/controllers/thredded/private_topics_controller.rb +2 -15
  22. data/app/controllers/thredded/topic_previews_controller.rb +14 -0
  23. data/app/controllers/thredded/topics_controller.rb +2 -13
  24. data/app/mailer_previews/thredded/private_topic_mailer_preview.rb +3 -1
  25. data/app/mailers/thredded/private_topic_mailer.rb +2 -1
  26. data/app/models/concerns/thredded/post_common.rb +12 -0
  27. data/app/models/thredded/post.rb +3 -5
  28. data/app/models/thredded/private_post.rb +8 -5
  29. data/app/notifiers/thredded/email_notifier.rb +1 -1
  30. data/app/view_hooks/thredded/all_view_hooks.rb +20 -0
  31. data/app/view_models/thredded/private_topic_view.rb +4 -0
  32. data/app/view_models/thredded/topic_view.rb +4 -0
  33. data/app/views/thredded/post_previews/preview.html.erb +1 -0
  34. data/app/views/thredded/post_previews/update.html.erb +1 -0
  35. data/app/views/thredded/posts/_form.html.erb +1 -0
  36. data/app/views/thredded/posts/edit.html.erb +2 -0
  37. data/app/views/thredded/posts_common/_form.html.erb +3 -2
  38. data/app/views/thredded/posts_common/form/_content.html.erb +7 -0
  39. data/app/views/thredded/posts_common/form/_preview_area.html.erb +16 -0
  40. data/app/views/thredded/private_post_previews/preview.html.erb +1 -0
  41. data/app/views/thredded/private_post_previews/update.html.erb +1 -0
  42. data/app/views/thredded/private_posts/_form.html.erb +2 -0
  43. data/app/views/thredded/private_topic_mailer/message_notification.html.erb +9 -5
  44. data/app/views/thredded/private_topic_mailer/message_notification.text.erb +4 -3
  45. data/app/views/thredded/private_topic_previews/preview.html.erb +1 -0
  46. data/app/views/thredded/private_topics/_form.html.erb +15 -8
  47. data/app/views/thredded/private_topics/index.html.erb +5 -4
  48. data/app/views/thredded/private_topics/new.html.erb +1 -0
  49. data/app/views/thredded/private_topics/show.html.erb +8 -2
  50. data/app/views/thredded/shared/preview.html.erb +10 -0
  51. data/app/views/thredded/theme_previews/show.html.erb +7 -0
  52. data/app/views/thredded/topic_previews/preview.html.erb +1 -0
  53. data/app/views/thredded/topics/_form.html.erb +4 -3
  54. data/app/views/thredded/topics/edit.html.erb +1 -1
  55. data/app/views/thredded/topics/index.html.erb +5 -4
  56. data/app/views/thredded/topics/new.html.erb +4 -3
  57. data/app/views/thredded/topics/search.html.erb +1 -1
  58. data/app/views/thredded/topics/show.html.erb +8 -1
  59. data/config/locales/en.yml +1 -0
  60. data/config/locales/es.yml +1 -0
  61. data/config/locales/pl.yml +187 -0
  62. data/config/locales/pt-BR.yml +1 -0
  63. data/config/routes.rb +14 -4
  64. data/lib/thredded/html_pipeline/at_mention_filter.rb +2 -2
  65. data/lib/thredded/version.rb +1 -1
  66. metadata +66 -4
  67. data/app/views/thredded/topics/menu/_new_topic.html.erb +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0a49cf4f5b1bb361db1653f027efaf34c1de3dc6
4
- data.tar.gz: f1cabfe3e1c3d3c20a25242447fe0cbddf813f7e
3
+ metadata.gz: 3ff5d29c06fad4e64cf4fa4b1577d77785a29453
4
+ data.tar.gz: 2a6196cbbcff86edd7e418e9b0bdb6bd2bb7ce23
5
5
  SHA512:
6
- metadata.gz: b85be66c122e1eec83513d29ff3c7934f6000b8437623458719367f9bea60ca3aa34b30cd2eb9ff05e414f088d4d203cf456e1653f962c01e791b1a3cb2b70ef
7
- data.tar.gz: 065b6e28bf583efa655c1ffca1c65857708ae85a60699a8010e1a4eec0477ea9583c4573f5ba7579ced0343877b442d87dc121fe77692607fcb3499a98d85862
6
+ metadata.gz: 944f979a29481faaf886de134b5d2e1ee7dee38d26597292d630c10406a9910e6b064a9b23ba1a26b31a65548a23a7a4cb3e3ed539e84830d8fdc150492e5e86
7
+ data.tar.gz: d87c3e1584e457bbd771114d548fdf143c90d8adb12f1c4393c7b41f1cb594b68bf6ed3cb05e48827ce3df04db7d5a9f9463f853e4896f51032576c9f989d702
data/README.md CHANGED
@@ -56,7 +56,7 @@ Then, see the rest of this Readme for more information about using and customizi
56
56
  Add the gem to your Gemfile:
57
57
 
58
58
  ```ruby
59
- gem 'thredded', '~> 0.9.3'
59
+ gem 'thredded', '~> 0.9.4'
60
60
  ```
61
61
 
62
62
  Add the Thredded [initializer] to your parent app by running the install generator.
@@ -323,7 +323,7 @@ You can also turn off the email notifier totally, or add other notifiers (e.g. P
323
323
 
324
324
  ## I18n
325
325
 
326
- Thredded is mostly internationalized. It is currently available in English, Brazilian Portuguese, and Spanish.
326
+ Thredded is mostly internationalized. It is currently available in English, Brazilian Portuguese, Polish, and Spanish.
327
327
  We welcome PRs adding support for new languages.
328
328
 
329
329
  If you use thredded in languages other than English, you probably want to add `rails-i18n` to your Gemfile.
@@ -511,8 +511,9 @@ change_column_default :thredded_user_details, :moderation_state, 1 # approved
511
511
 
512
512
  The following official plugins are available for Thredded:
513
513
 
514
- * [BBCode](https://github.com/thredded/thredded-bbcode) formatting for posts, e.g. `[b]for bold[/b]`.
515
- * [Code Syntax Highlighting](https://github.com/thredded/thredded-markdown_coderay) using Coderay.
514
+ * [BBCode](https://github.com/thredded/thredded-bbcode) formatting for posts, e.g. `[b]for bold[/b]`. Can be used alongside Markdown.
515
+ * [Code Syntax Highlighting in Markdown](https://github.com/thredded/thredded-markdown_coderay) using Coderay.
516
+ * [TeX math via KaTeX in Markdown](https://github.com/thredded/thredded-markdown_katex), fast, accessible, JS-free math rendering.
516
517
 
517
518
  Thredded is built for extensibility, and writing plugins for it is easy. If you plan on extending Thredded functionality
518
519
  in a way others may benefit from, please consider making it a plugin.
@@ -1,3 +1,5 @@
1
+ //= require ./preview_area
2
+
1
3
  (($) => {
2
4
  const COMPONENT_SELECTOR = '[data-thredded-post-form]';
3
5
 
@@ -9,6 +11,9 @@
9
11
  init($nodes) {
10
12
  let $textarea = $nodes.find(this.textareaSelector);
11
13
  this.autosize($textarea);
14
+ $nodes.each(function() {
15
+ new ThreddedPreviewArea($(this));
16
+ });
12
17
  new ThreddedMentionAutocompletion($).init($nodes);
13
18
  }
14
19
 
@@ -0,0 +1,52 @@
1
+ //= require ./preview_area
2
+
3
+ (function($) {
4
+ const PREVIEW_AREA_SELECTOR = '[data-thredded-preview-area]';
5
+ const PREVIEW_AREA_POST_SELECTOR = '[data-thredded-preview-area-post]';
6
+
7
+ class ThreddedPreviewArea {
8
+
9
+ constructor($form) {
10
+ const $preview = $form.find(PREVIEW_AREA_SELECTOR);
11
+ if (!$preview.length) return;
12
+ this.$form = $form;
13
+ const $textarea = $form.find('textarea');
14
+ this.textarea = $textarea.get(0);
15
+ this.preview = $preview.get(0);
16
+ this.previewPost = $form.find(PREVIEW_AREA_POST_SELECTOR).get(0);
17
+ this.previewUrl = this.preview.getAttribute('data-thredded-preview-url');
18
+
19
+ const onChange = Thredded.debounce(() => {
20
+ this.updatePreview()
21
+ }, 200, false);
22
+
23
+ this.textarea.addEventListener('input', onChange, false);
24
+ // Listen to the jQuery change event as that's what is triggered by plugins such as jQuery.textcomplete.
25
+ $textarea.on('change', onChange);
26
+
27
+ this.requestId = 0;
28
+ }
29
+
30
+ updatePreview() {
31
+ this.requestId++;
32
+ const requestId = this.requestId;
33
+ $.ajax({
34
+ type: this.$form.attr('method'),
35
+ url: this.previewUrl,
36
+ data: this.$form.serialize(),
37
+ }).done((data) => {
38
+ if (requestId == this.requestId) {
39
+ // Ignore older responses received out-of-order
40
+ this.onPreviewResponse(data);
41
+ }
42
+ });
43
+ }
44
+
45
+ onPreviewResponse(data) {
46
+ this.preview.style.display = 'block';
47
+ this.previewPost.innerHTML = data;
48
+ }
49
+ }
50
+
51
+ window.ThreddedPreviewArea = ThreddedPreviewArea;
52
+ })(jQuery);
@@ -16,6 +16,9 @@
16
16
 
17
17
  init($nodes) {
18
18
  $nodes.find(this.textareaSelector).autosize();
19
+ $nodes.each(function() {
20
+ new ThreddedPreviewArea($(this));
21
+ });
19
22
  new ThreddedMentionAutocompletion($).init($nodes);
20
23
  $nodes.filter(this.compactSelector).
21
24
  on('focus', this.titleSelector, e => {
@@ -0,0 +1,32 @@
1
+ //= require ./thredded
2
+
3
+ /**
4
+ * Return a function, that, as long as it continues to be invoked, will
5
+ * not be triggered. The function will be called after it stops being
6
+ * called for `wait` milliseconds. If `immediate` is passed, trigger the
7
+ * function on the leading edge, instead of the trailing.
8
+ * Based on https://john-dugan.com/javascript-debounce/.
9
+ *
10
+ * @param {Function} func
11
+ * @param {Number} wait in milliseconds
12
+ * @param {Boolean} immediate
13
+ * @returns {Function}
14
+ */
15
+ window.Thredded.debounce = function(func, wait, immediate) {
16
+ let timeoutId = null;
17
+ return function() {
18
+ const context = this, args = arguments;
19
+ const later = function() {
20
+ timeoutId = null;
21
+ if (!immediate) {
22
+ func.apply(context, args);
23
+ }
24
+ };
25
+ const callNow = immediate && !timeoutId;
26
+ clearTimeout(timeoutId);
27
+ timeoutId = setTimeout(later, wait || 200);
28
+ if (callNow) {
29
+ func.apply(context, args);
30
+ }
31
+ };
32
+ };
@@ -1,4 +1,5 @@
1
- window.Thredded = window.Thredded || {};
1
+ //= require ./thredded
2
+
2
3
  window.Thredded.hideSoftKeyboard = () => {
3
4
  const activeElement = document.activeElement;
4
5
  if (!activeElement || !activeElement.blur) return;
@@ -41,7 +41,7 @@ class ThreddedMentionAutocompletion {
41
41
  },
42
42
  replace ({name, match}) {
43
43
  let prefix = match[1];
44
- if (name.indexOf(" ") > -1) {
44
+ if (/[. ]/.test(name)) {
45
45
  return `${prefix}"${name}" `
46
46
  } else {
47
47
  return `${prefix}${name} `
@@ -51,4 +51,4 @@ class ThreddedMentionAutocompletion {
51
51
  }
52
52
  }
53
53
 
54
- ThreddedMentionAutocompletion.MATCH_RE = /(^@|\s@)"?((?:\w| )+)$/;
54
+ ThreddedMentionAutocompletion.MATCH_RE = /(^@|\s@)"?([\w. ]+)$/;
@@ -1,3 +1,5 @@
1
+ //= require ./thredded
2
+
1
3
  (() => {
2
4
  const isTurbolinks = 'Turbolinks' in window && window.Turbolinks.supported;
3
5
  const isTurbolinks5 = isTurbolinks && 'clearCache' in window.Turbolinks;
@@ -11,8 +13,6 @@
11
13
  onPageLoadFiredOnce = true;
12
14
  };
13
15
 
14
- window.Thredded = window.Thredded || {};
15
-
16
16
  // Fires the callback on DOMContentLoaded or a Turbolinks page load.
17
17
  // If called from an async script on the first page load, and the DOMContentLoad event
18
18
  // has already fired, will execute the callback immediately.
@@ -0,0 +1 @@
1
+ window.Thredded = window.Thredded || {};
@@ -30,3 +30,4 @@
30
30
  @import "components/topic-delete";
31
31
  @import "components/topic-header";
32
32
  @import "components/topics";
33
+ @import "components/preview_area";
@@ -1,6 +1,5 @@
1
1
  .thredded--pagination {
2
2
  border-top: $thredded-base-border;
3
- margin-top: $thredded-base-spacing;
4
3
  padding-top: $thredded-base-spacing;
5
4
  text-align: center;
6
5
 
@@ -24,3 +23,13 @@
24
23
  }
25
24
  }
26
25
  }
26
+
27
+ .thredded--pagination-top > .thredded--pagination {
28
+ border-bottom: $thredded-base-border;
29
+ margin-bottom: $thredded-base-spacing;
30
+ padding-bottom: $thredded-base-spacing;
31
+ }
32
+
33
+ .thredded--pagination-bottom > .thredded--pagination {
34
+ margin-top: $thredded-base-spacing;
35
+ }
@@ -0,0 +1,11 @@
1
+ .thredded--preview-area {
2
+ display: none;
3
+
4
+ &--title {
5
+ @extend %thredded--heading;
6
+ }
7
+
8
+ &--post {
9
+ margin-bottom: $thredded-base-spacing;
10
+ }
11
+ }
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ # @api private
4
+ module NewPrivateTopicParams
5
+ protected
6
+
7
+ def new_private_topic_params
8
+ params
9
+ .require(:private_topic)
10
+ .permit(:title, :content, :user_ids, user_ids: [])
11
+ .merge(
12
+ user: thredded_current_user,
13
+ ip: request.remote_ip
14
+ ).tap { |p| adapt_user_ids! p }
15
+ end
16
+
17
+ private
18
+
19
+ # select2 returns a string of IDs joined with commas.
20
+ def adapt_user_ids!(p)
21
+ p[:user_ids] = p[:user_ids].split(',') if p[:user_ids].is_a?(String)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ # @api private
4
+ module NewTopicParams
5
+ protected
6
+
7
+ def new_topic_params
8
+ params
9
+ .fetch(:topic, {})
10
+ .permit(:title, :locked, :sticky, :content, category_ids: [])
11
+ .merge(
12
+ messageboard: messageboard,
13
+ user: thredded_current_user,
14
+ ip: request.remote_ip,
15
+ )
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ module RenderPreview
4
+ protected
5
+
6
+ def render_preview
7
+ if request.xhr?
8
+ render layout: false
9
+ else
10
+ @preview_content = render_to_string(layout: false)
11
+ render template: 'thredded/shared/preview'
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ class PostPreviewsController < Thredded::ApplicationController
4
+ include Thredded::RenderPreview
5
+
6
+ # Preview a new post
7
+ def preview
8
+ @post = Post.new(post_params)
9
+ @post.postable = Topic.friendly_find!(params[:topic_id])
10
+ render_preview
11
+ end
12
+
13
+ # Preview an update to an existing post
14
+ def update
15
+ @post = Post.find(params[:post_id])
16
+ @post.assign_attributes(post_params)
17
+ render_preview
18
+ end
19
+
20
+ private
21
+
22
+ def post_params
23
+ params.require(:post)
24
+ .permit(:content)
25
+ .merge(user: thredded_current_user, messageboard: messageboard)
26
+ end
27
+ end
28
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  module Thredded
3
+ # This currently handles both {Post}s and {PrivatePost}s.
4
+ # TODO: split up the PrivatePost functionality into a separate controller.
3
5
  class PostsController < Thredded::ApplicationController
4
6
  include ActionView::RecordIdentifier
5
7
 
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ class PrivatePostPreviewsController < Thredded::ApplicationController
4
+ include Thredded::RenderPreview
5
+
6
+ # Preview a new post
7
+ def preview
8
+ @private_post = PrivatePost.new(private_post_params)
9
+ @private_post.postable = PrivateTopic.friendly_find!(params[:private_topic_id])
10
+ render_preview
11
+ end
12
+
13
+ # Preview an update to an existing post
14
+ def update
15
+ @private_post = PrivatePost.find(params[:private_post_id])
16
+ @private_post.assign_attributes(private_post_params)
17
+ render_preview
18
+ end
19
+
20
+ private
21
+
22
+ def private_post_params
23
+ params.require(:post)
24
+ .permit(:content)
25
+ .merge(user: thredded_current_user)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ class PrivateTopicPreviewsController < Thredded::ApplicationController
4
+ include Thredded::NewPrivateTopicParams
5
+ include Thredded::RenderPreview
6
+
7
+ def preview
8
+ form = PrivateTopicForm.new(new_private_topic_params)
9
+ @private_post = form.post
10
+ @private_post.postable = form.private_topic
11
+ render_preview
12
+ end
13
+ end
14
+ end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  module Thredded
3
3
  class PrivateTopicsController < Thredded::ApplicationController
4
+ include Thredded::NewPrivateTopicParams
5
+
4
6
  before_action :thredded_require_login!
5
7
 
6
8
  def index
@@ -85,20 +87,5 @@ module Thredded
85
87
  .require(:private_topic)
86
88
  .permit(:title)
87
89
  end
88
-
89
- def new_private_topic_params
90
- params
91
- .require(:private_topic)
92
- .permit(:title, :content, :user_ids, user_ids: [])
93
- .merge(
94
- user: thredded_current_user,
95
- ip: request.remote_ip
96
- ).tap { |p| adapt_user_ids! p }
97
- end
98
-
99
- # select2 returns a string of IDs joined with commas.
100
- def adapt_user_ids!(p)
101
- p[:user_ids] = p[:user_ids].split(',') if p[:user_ids].is_a?(String)
102
- end
103
90
  end
104
91
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ module Thredded
3
+ class TopicPreviewsController < Thredded::ApplicationController
4
+ include Thredded::NewTopicParams
5
+ include Thredded::RenderPreview
6
+
7
+ def preview
8
+ form = TopicForm.new(new_topic_params)
9
+ @post = form.post
10
+ @post.postable = form.topic
11
+ render_preview
12
+ end
13
+ end
14
+ end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
- # rubocop:disable Metrics/ClassLength
3
2
  module Thredded
4
3
  class TopicsController < Thredded::ApplicationController
4
+ include Thredded::NewTopicParams
5
+
5
6
  before_action :thredded_require_login!,
6
7
  only: %i(edit new update create destroy follow unfollow)
7
8
  after_action :update_user_activity
@@ -147,20 +148,8 @@ module Thredded
147
148
  .permit(:title, :locked, :sticky, category_ids: [])
148
149
  end
149
150
 
150
- def new_topic_params
151
- params
152
- .fetch(:topic, {})
153
- .permit(:title, :locked, :sticky, :content, category_ids: [])
154
- .merge(
155
- messageboard: messageboard,
156
- user: thredded_current_user,
157
- ip: request.remote_ip,
158
- )
159
- end
160
-
161
151
  def current_page
162
152
  (params[:page] || 1).to_i
163
153
  end
164
154
  end
165
155
  end
166
- # rubocop:enable Metrics/ClassLength
@@ -3,10 +3,12 @@ module Thredded
3
3
  # Previews for the PrivateTopicMailer
4
4
  class PrivateTopicMailerPreview < BaseMailerPreview
5
5
  def message_notification
6
+ post = mock_private_post(content: mock_content(mention_users: ['glebm']))
6
7
  PrivateTopicMailer.message_notification(
7
8
  mock_private_topic(posts: [
8
- mock_private_post(content: mock_content(mention_users: ['glebm']))
9
+ post
9
10
  ]),
11
+ post,
10
12
  %w(glebm@test.com joel@test.com)
11
13
  )
12
14
  end
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
  module Thredded
3
3
  class PrivateTopicMailer < Thredded::BaseMailer
4
- def message_notification(private_topic_id, emails)
4
+ def message_notification(private_topic_id, post_id, emails)
5
5
  @topic = find_record Thredded::PrivateTopic, private_topic_id
6
+ @post = find_record Thredded::PrivatePost, post_id
6
7
  email_details = Thredded::TopicEmailView.new(@topic)
7
8
  headers['X-SMTPAPI'] = email_details.smtp_api_tag('private_topic_mailer')
8
9
 
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
  module Thredded
3
+ # @abstract Classes that include this module are expected to implement {#readers}.
4
+ # @!method readers
5
+ # @abstract
6
+ # @return [ActiveRecord::Relation<Thredded.user_class>] users from that can read this post.
3
7
  module PostCommon
4
8
  extend ActiveSupport::Concern
5
9
 
@@ -36,6 +40,14 @@ module Thredded
36
40
  postable.first_post == self
37
41
  end
38
42
 
43
+ # @return [ActiveRecord::Relation<Thredded.user_class>] users from the list of user names that can read this post.
44
+ # @api private
45
+ def readers_from_user_names(user_names)
46
+ DbTextSearch::CaseInsensitive
47
+ .new(readers, Thredded.user_name_column)
48
+ .in(user_names)
49
+ end
50
+
39
51
  private
40
52
 
41
53
  def ensure_user_detail
@@ -42,11 +42,9 @@ module Thredded
42
42
  false
43
43
  end
44
44
 
45
- # @return [ActiveRecord::Relation<Thredded.user_class>] users from the list of user names that can read this post.
46
- def readers_from_user_names(user_names)
47
- DbTextSearch::CaseInsensitive
48
- .new(Thredded.user_class.thredded_messageboards_readers([messageboard]), Thredded.user_name_column)
49
- .in(user_names)
45
+ # @return [ActiveRecord::Relation<Thredded.user_class>] users that can read this post.
46
+ def readers
47
+ Thredded.user_class.thredded_messageboards_readers([messageboard])
50
48
  end
51
49
 
52
50
  private
@@ -27,11 +27,14 @@ module Thredded
27
27
  true
28
28
  end
29
29
 
30
- # @return [ActiveRecord::Relation<Thredded.user_class>] users from the list of user names that can read this post.
31
- def readers_from_user_names(user_names)
32
- DbTextSearch::CaseInsensitive
33
- .new(postable.users, Thredded.user_name_column)
34
- .in(user_names)
30
+ # @return [ActiveRecord::Relation<Thredded.user_class>] users that can read this post.
31
+ def readers
32
+ collection_proxy = postable.users
33
+ if persisted?
34
+ collection_proxy.scope
35
+ else
36
+ Thredded.user_class.where(id: collection_proxy.to_a.map(&:id))
37
+ end
35
38
  end
36
39
 
37
40
  private
@@ -18,7 +18,7 @@ module Thredded
18
18
  users = exclude_previously_notified(post, users)
19
19
  return unless users.present?
20
20
  PrivateTopicMailer
21
- .message_notification(post.postable.id, users.map(&:email))
21
+ .message_notification(post.postable.id, post.id, users.map(&:email))
22
22
  .deliver_now
23
23
  MembersMarkedNotified.new(post, users).run
24
24
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  module Thredded
3
3
  class AllViewHooks
4
+ # @return [PostsCommon]
5
+ attr_reader :posts_common
4
6
  # @return [PostForm]
5
7
  attr_reader :post_form
6
8
  # @return [ModerationUserPage]
@@ -19,16 +21,34 @@ module Thredded
19
21
  end
20
22
 
21
23
  def initialize
24
+ @posts_common = PostsCommon.new
22
25
  @post_form = PostForm.new
23
26
  @moderation_user_page = ModerationUserPage.new
24
27
  end
25
28
 
29
+ # View hooks for collections of public or private posts.
30
+ class PostsCommon
31
+ # @return [Thredded::AllViewHooks::ViewHook]
32
+ attr_reader :pagination_top
33
+ # @return [Thredded::AllViewHooks::ViewHook]
34
+ attr_reader :pagination_bottom
35
+
36
+ def initialize
37
+ @pagination_top = ViewHook.new
38
+ @pagination_bottom = ViewHook.new
39
+ end
40
+ end
41
+
26
42
  class PostForm
27
43
  # @return [Thredded::AllViewHooks::ViewHook]
28
44
  attr_reader :content_text_area
29
45
 
46
+ # @return [Thredded::AllViewHooks::ViewHook]
47
+ attr_reader :preview_area
48
+
30
49
  def initialize
31
50
  @content_text_area = ViewHook.new
51
+ @preview_area = ViewHook.new
32
52
  end
33
53
  end
34
54
 
@@ -15,5 +15,9 @@ 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
18
22
  end
19
23
  end
@@ -63,5 +63,9 @@ 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
66
70
  end
67
71
  end
@@ -0,0 +1 @@
1
+ <%= @post.filtered_content(self) %>
@@ -0,0 +1 @@
1
+ <%= @post.filtered_content(self) %>
@@ -1,6 +1,7 @@
1
1
  <%= render 'thredded/posts_common/form',
2
2
  topic: topic,
3
3
  post: post,
4
+ preview_url: preview_url,
4
5
  content_label: t('thredded.posts.form.content_label'),
5
6
  button_text: button_text,
6
7
  button_submitting_text: local_assigns.key?(:button_submitting_text) ? button_submitting_text : nil %>
@@ -12,6 +12,8 @@
12
12
  messageboard: (messageboard unless @post.private_topic_post?),
13
13
  topic: topic,
14
14
  post: @post,
15
+ preview_url: (@post.private_topic_post? ? private_topic_private_post_preview_path(@post.postable, @post)
16
+ : messageboard_topic_post_preview_path(messageboard, @post.postable, @post)),
15
17
  button_text: t('thredded.posts.form.update_btn'),
16
18
  button_submitting_text: t('thredded.posts.form.update_btn_submitting')%>
17
19
  </section>