thredded 0.9.3 → 0.9.4
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.
- checksums.yaml +4 -4
- data/README.md +5 -4
- data/app/assets/javascripts/thredded/components/post_form.es6 +5 -0
- data/app/assets/javascripts/thredded/components/preview_area.es6 +52 -0
- data/app/assets/javascripts/thredded/components/topic_form.es6 +3 -0
- data/app/assets/javascripts/thredded/core/debounce.es6 +32 -0
- data/app/assets/javascripts/thredded/core/hide_soft_keyboard.es6 +2 -1
- data/app/assets/javascripts/thredded/core/mention_autocompletion.es6 +2 -2
- data/app/assets/javascripts/thredded/core/on_page_load.es6 +2 -2
- data/app/assets/javascripts/thredded/core/thredded.es6 +1 -0
- data/app/assets/stylesheets/thredded/_thredded.scss +1 -0
- data/app/assets/stylesheets/thredded/components/_pagination.scss +10 -1
- data/app/assets/stylesheets/thredded/components/_preview_area.scss +11 -0
- data/app/controllers/concerns/thredded/new_private_topic_params.rb +24 -0
- data/app/controllers/concerns/thredded/new_topic_params.rb +18 -0
- data/app/controllers/concerns/thredded/render_preview.rb +15 -0
- data/app/controllers/thredded/post_previews_controller.rb +28 -0
- data/app/controllers/thredded/posts_controller.rb +2 -0
- data/app/controllers/thredded/private_post_previews_controller.rb +28 -0
- data/app/controllers/thredded/private_topic_previews_controller.rb +14 -0
- data/app/controllers/thredded/private_topics_controller.rb +2 -15
- data/app/controllers/thredded/topic_previews_controller.rb +14 -0
- data/app/controllers/thredded/topics_controller.rb +2 -13
- data/app/mailer_previews/thredded/private_topic_mailer_preview.rb +3 -1
- data/app/mailers/thredded/private_topic_mailer.rb +2 -1
- data/app/models/concerns/thredded/post_common.rb +12 -0
- data/app/models/thredded/post.rb +3 -5
- data/app/models/thredded/private_post.rb +8 -5
- data/app/notifiers/thredded/email_notifier.rb +1 -1
- data/app/view_hooks/thredded/all_view_hooks.rb +20 -0
- data/app/view_models/thredded/private_topic_view.rb +4 -0
- data/app/view_models/thredded/topic_view.rb +4 -0
- data/app/views/thredded/post_previews/preview.html.erb +1 -0
- data/app/views/thredded/post_previews/update.html.erb +1 -0
- data/app/views/thredded/posts/_form.html.erb +1 -0
- data/app/views/thredded/posts/edit.html.erb +2 -0
- data/app/views/thredded/posts_common/_form.html.erb +3 -2
- data/app/views/thredded/posts_common/form/_content.html.erb +7 -0
- data/app/views/thredded/posts_common/form/_preview_area.html.erb +16 -0
- data/app/views/thredded/private_post_previews/preview.html.erb +1 -0
- data/app/views/thredded/private_post_previews/update.html.erb +1 -0
- data/app/views/thredded/private_posts/_form.html.erb +2 -0
- data/app/views/thredded/private_topic_mailer/message_notification.html.erb +9 -5
- data/app/views/thredded/private_topic_mailer/message_notification.text.erb +4 -3
- data/app/views/thredded/private_topic_previews/preview.html.erb +1 -0
- data/app/views/thredded/private_topics/_form.html.erb +15 -8
- data/app/views/thredded/private_topics/index.html.erb +5 -4
- data/app/views/thredded/private_topics/new.html.erb +1 -0
- data/app/views/thredded/private_topics/show.html.erb +8 -2
- data/app/views/thredded/shared/preview.html.erb +10 -0
- data/app/views/thredded/theme_previews/show.html.erb +7 -0
- data/app/views/thredded/topic_previews/preview.html.erb +1 -0
- data/app/views/thredded/topics/_form.html.erb +4 -3
- data/app/views/thredded/topics/edit.html.erb +1 -1
- data/app/views/thredded/topics/index.html.erb +5 -4
- data/app/views/thredded/topics/new.html.erb +4 -3
- data/app/views/thredded/topics/search.html.erb +1 -1
- data/app/views/thredded/topics/show.html.erb +8 -1
- data/config/locales/en.yml +1 -0
- data/config/locales/es.yml +1 -0
- data/config/locales/pl.yml +187 -0
- data/config/locales/pt-BR.yml +1 -0
- data/config/routes.rb +14 -4
- data/lib/thredded/html_pipeline/at_mention_filter.rb +2 -2
- data/lib/thredded/version.rb +1 -1
- metadata +66 -4
- 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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3ff5d29c06fad4e64cf4fa4b1577d77785a29453
|
|
4
|
+
data.tar.gz: 2a6196cbbcff86edd7e418e9b0bdb6bd2bb7ce23
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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.
|
|
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
|
+
};
|
|
@@ -41,7 +41,7 @@ class ThreddedMentionAutocompletion {
|
|
|
41
41
|
},
|
|
42
42
|
replace ({name, match}) {
|
|
43
43
|
let prefix = match[1];
|
|
44
|
-
if (
|
|
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@)"?(
|
|
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 || {};
|
|
@@ -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,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
|
-
|
|
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
|
data/app/models/thredded/post.rb
CHANGED
|
@@ -42,11 +42,9 @@ module Thredded
|
|
|
42
42
|
false
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
# @return [ActiveRecord::Relation<Thredded.user_class>] users
|
|
46
|
-
def
|
|
47
|
-
|
|
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
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
.
|
|
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
|
|
|
@@ -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>
|