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.
- checksums.yaml +4 -4
- data/README.md +2 -5
- data/app/assets/javascripts/thredded/components/post_form.es6 +4 -4
- data/app/assets/javascripts/thredded/components/quote_post.es6 +45 -0
- data/app/assets/javascripts/thredded/components/topic_form.es6 +4 -4
- data/app/assets/javascripts/thredded/core/on_page_load.es6 +8 -0
- data/app/assets/javascripts/thredded/dependencies.js +1 -1
- data/app/assets/stylesheets/thredded/_email.scss +2 -3
- data/app/assets/stylesheets/thredded/components/_preferences.scss +17 -4
- data/app/controllers/concerns/thredded/new_post_params.rb +20 -0
- data/app/controllers/concerns/thredded/new_private_post_params.rb +20 -0
- data/app/controllers/thredded/posts_controller.rb +22 -13
- data/app/controllers/thredded/preferences_controller.rb +1 -0
- data/app/controllers/thredded/private_posts_controller.rb +24 -12
- data/app/controllers/thredded/private_topics_controller.rb +4 -1
- data/app/controllers/thredded/theme_previews_controller.rb +4 -2
- data/app/controllers/thredded/topics_controller.rb +13 -2
- data/app/forms/thredded/post_form.rb +52 -0
- data/app/forms/thredded/private_post_form.rb +48 -0
- data/app/forms/thredded/private_topic_form.rb +8 -0
- data/app/forms/thredded/topic_form.rb +8 -0
- data/app/forms/thredded/user_preferences_form.rb +7 -1
- data/app/helpers/thredded/urls_helper.rb +18 -0
- data/app/models/thredded/topic.rb +3 -3
- data/app/policies/thredded/private_topic_policy.rb +1 -1
- data/app/view_models/thredded/messageboard_group_view.rb +1 -1
- data/app/view_models/thredded/post_view.rb +19 -3
- data/app/view_models/thredded/private_topic_view.rb +0 -4
- data/app/view_models/thredded/topic_view.rb +0 -4
- data/app/views/thredded/posts/_form.html.erb +0 -2
- data/app/views/thredded/posts/edit.html.erb +2 -5
- data/app/views/thredded/posts/new.html.erb +15 -0
- data/app/views/thredded/posts_common/_actions.html.erb +3 -0
- data/app/views/thredded/posts_common/_form.html.erb +5 -3
- data/app/views/thredded/posts_common/_header.html.erb +3 -1
- data/app/views/thredded/posts_common/actions/_quote.html.erb +4 -0
- data/app/views/thredded/preferences/_form.html.erb +3 -5
- data/app/views/thredded/preferences/_messageboards_nav.html.erb +8 -0
- data/app/views/thredded/preferences/_messageboards_nav_item.html.erb +2 -0
- data/app/views/thredded/preferences/edit.html.erb +13 -3
- data/app/views/thredded/private_posts/_form.html.erb +0 -2
- data/app/views/thredded/private_posts/edit.html.erb +2 -4
- data/app/views/thredded/private_posts/new.html.erb +11 -0
- data/app/views/thredded/private_topics/_form.html.erb +2 -2
- data/app/views/thredded/private_topics/index.html.erb +1 -2
- data/app/views/thredded/private_topics/new.html.erb +0 -1
- data/app/views/thredded/private_topics/show.html.erb +5 -3
- data/app/views/thredded/shared/_nav.html.erb +1 -7
- data/app/views/thredded/shared/nav/_standalone.html.erb +3 -3
- data/app/views/thredded/shared/nav/_standalone_profile.html.erb +3 -0
- data/app/views/thredded/theme_previews/show.html.erb +3 -17
- data/app/views/thredded/topics/_form.html.erb +3 -2
- data/app/views/thredded/topics/index.html.erb +0 -2
- data/app/views/thredded/topics/new.html.erb +0 -2
- data/app/views/thredded/topics/show.html.erb +1 -3
- data/config/locales/en.yml +4 -3
- data/config/locales/es.yml +4 -3
- data/config/locales/pl.yml +4 -3
- data/config/locales/pt-BR.yml +4 -3
- data/config/locales/ru.yml +12 -7
- data/config/routes.rb +2 -0
- data/db/migrate/20160329231848_create_thredded.rb +1 -1
- data/db/upgrade_migrations/20170420163138_upgrade_thredded_v0_11_to_v0_12.rb +25 -0
- data/lib/thredded.rb +0 -1
- data/lib/thredded/content_formatter.rb +11 -0
- data/lib/thredded/version.rb +1 -1
- data/vendor/assets/javascripts/autosize.js +290 -0
- metadata +15 -17
- data/app/views/thredded/preferences/_header.html.erb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9da3f257731b6397128563a35788225046e8a589
|
4
|
+
data.tar.gz: fc0b9d0117acd6de8c6d21fa1d3ff629e3e463e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d811130638a892c28e07b2065f05b0c8e6edd8d2aabea59691dd0f5653424818978fd4bb2d0676875aa85110e9b58bacda911efc60c26ce4dd5bb53fefa306c6
|
7
|
+
data.tar.gz: b78b12a3e681153c4b82363b6334a5c09648e86910f17f8d997e4f53dac0cd84555a3141c83d7da20f885b4b532a385913703ad6ff8a36982cc7c4ecc91636d1
|
data/README.md
CHANGED
@@ -99,7 +99,7 @@ Then, see the rest of this Readme for more information about using and customizi
|
|
99
99
|
Add the gem to your Gemfile:
|
100
100
|
|
101
101
|
```ruby
|
102
|
-
gem 'thredded', '~> 0.
|
102
|
+
gem 'thredded', '~> 0.12.0'
|
103
103
|
```
|
104
104
|
|
105
105
|
Add the Thredded [initializer] to your parent app by running the install generator.
|
@@ -151,7 +151,7 @@ But then compare this with the previous version to decide what to keep.
|
|
151
151
|
2) To upgrade the database (in this example from v0.10 to v0.11):
|
152
152
|
|
153
153
|
```console
|
154
|
-
# Note that for guaranteed best results you will want to run this with the gem checked out with v0.
|
154
|
+
# Note that for guaranteed best results you will want to run this with the gem checked out with v0.11
|
155
155
|
cp `bundle show thredded`/db/upgrade_migrations/20170312131417_upgrade_thredded_v0_10_to_v0_11.rb db/migrate
|
156
156
|
rake db:migrate
|
157
157
|
```
|
@@ -193,9 +193,6 @@ In your layout you will probably have links to other paths in your app (e.g. nav
|
|
193
193
|
For any url helpers (like `users_path` or `projects_path` or whatever) will need to have `main_app.`
|
194
194
|
prefixed to them so that they can be found from thredded (`main_app.users_path` will work from both thredded and your app).
|
195
195
|
|
196
|
-
However if you don't want to update your layouts and partials, you can define methods automatically to delegate to the main_app's routes:
|
197
|
-
See https://gist.github.com/timdiggins/bf6d09b28828a392198562c93554ad07.
|
198
|
-
|
199
196
|
#### Add Thredded styles
|
200
197
|
|
201
198
|
In this case, you will also need to include Thredded styles and JavaScript into the application styles and JavaScript.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
//= require ./preview_area
|
2
2
|
|
3
|
-
((
|
3
|
+
(($, autosize) => {
|
4
4
|
const COMPONENT_SELECTOR = '[data-thredded-post-form]';
|
5
5
|
|
6
6
|
class ThreddedPostForm {
|
@@ -18,11 +18,11 @@
|
|
18
18
|
}
|
19
19
|
|
20
20
|
autosize($textarea) {
|
21
|
-
$textarea
|
21
|
+
autosize($textarea)
|
22
22
|
}
|
23
23
|
|
24
24
|
destroy($nodes) {
|
25
|
-
$nodes.find(this.textareaSelector)
|
25
|
+
autosize.destroy($nodes.find(this.textareaSelector));
|
26
26
|
}
|
27
27
|
}
|
28
28
|
|
@@ -39,4 +39,4 @@
|
|
39
39
|
new ThreddedPostForm().destroy($nodes);
|
40
40
|
}
|
41
41
|
});
|
42
|
-
})(jQuery);
|
42
|
+
})(jQuery, window.autosize);
|
@@ -0,0 +1,45 @@
|
|
1
|
+
(function() {
|
2
|
+
window.Thredded.onPageLoad(() => {
|
3
|
+
Array.prototype.forEach.call(document.querySelectorAll('[data-thredded-quote-post]'), (el) => {
|
4
|
+
el.addEventListener('click', onClick);
|
5
|
+
});
|
6
|
+
});
|
7
|
+
|
8
|
+
function onClick(evt) {
|
9
|
+
// Handle only left clicks with no modifier keys
|
10
|
+
if (evt.button !== 0 || evt.ctrlKey || evt.altKey || evt.metaKey || evt.shiftKey) return;
|
11
|
+
evt.preventDefault();
|
12
|
+
const target = document.getElementById('post_content');
|
13
|
+
target.scrollIntoView();
|
14
|
+
target.value = '...';
|
15
|
+
fetchReply(evt.target.getAttribute('data-thredded-quote-post'), (replyText) => {
|
16
|
+
if (!target.ownerDocument.body.contains(target)) return;
|
17
|
+
target.focus();
|
18
|
+
target.value = replyText;
|
19
|
+
|
20
|
+
const autosizeUpdateEvent = document.createEvent('Event');
|
21
|
+
autosizeUpdateEvent.initEvent('autosize:update', true, false);
|
22
|
+
target.dispatchEvent(autosizeUpdateEvent);
|
23
|
+
// Scroll into view again as the size might have changed.
|
24
|
+
target.scrollIntoView();
|
25
|
+
}, (errorMessage) => {
|
26
|
+
target.value = errorMessage;
|
27
|
+
});
|
28
|
+
}
|
29
|
+
|
30
|
+
function fetchReply(url, onSuccess, onError) {
|
31
|
+
const request = new XMLHttpRequest();
|
32
|
+
request.open('GET', url, /* async */ true);
|
33
|
+
request.onload = () => {
|
34
|
+
if (request.status >= 200 && request.status < 400) {
|
35
|
+
onSuccess(request.responseText);
|
36
|
+
} else {
|
37
|
+
onError(`Error (${request.status}): ${request.statusText} ${request.responseText}`);
|
38
|
+
}
|
39
|
+
};
|
40
|
+
request.onerror = () => {
|
41
|
+
onError('Network Error');
|
42
|
+
};
|
43
|
+
request.send();
|
44
|
+
}
|
45
|
+
})();
|
@@ -1,4 +1,4 @@
|
|
1
|
-
((
|
1
|
+
(($, autosize) => {
|
2
2
|
const COMPONENT_SELECTOR = '[data-thredded-topic-form]';
|
3
3
|
class ThreddedTopicForm {
|
4
4
|
constructor() {
|
@@ -15,7 +15,7 @@
|
|
15
15
|
}
|
16
16
|
|
17
17
|
init($nodes) {
|
18
|
-
$nodes.find(this.textareaSelector)
|
18
|
+
autosize($nodes.find(this.textareaSelector));
|
19
19
|
$nodes.each(function() {
|
20
20
|
new ThreddedPreviewArea($(this));
|
21
21
|
});
|
@@ -47,7 +47,7 @@
|
|
47
47
|
}
|
48
48
|
|
49
49
|
destroy($nodes) {
|
50
|
-
$nodes.find(this.textareaSelector)
|
50
|
+
autosize.destroy($nodes.find(this.textareaSelector));
|
51
51
|
}
|
52
52
|
}
|
53
53
|
|
@@ -64,6 +64,6 @@
|
|
64
64
|
new ThreddedTopicForm().destroy($nodes);
|
65
65
|
}
|
66
66
|
});
|
67
|
-
})(jQuery);
|
67
|
+
})(jQuery, window.autosize);
|
68
68
|
|
69
69
|
|
@@ -26,6 +26,14 @@
|
|
26
26
|
};
|
27
27
|
|
28
28
|
if (isTurbolinks5) {
|
29
|
+
// In Turbolinks 5.0.1, turbolinks:load may have already fired (before DOMContentLoaded).
|
30
|
+
// If so, add our own DOMContentLoaded listener:
|
31
|
+
// See: https://github.com/turbolinks/turbolinks/commit/69d353ea73d10ee6b25c2866fc5706879ba403e3
|
32
|
+
if (window.Turbolinks.controller.lastRenderedLocation) {
|
33
|
+
document.addEventListener('DOMContentLoaded', () => {
|
34
|
+
triggerOnPageLoad();
|
35
|
+
});
|
36
|
+
}
|
29
37
|
document.addEventListener('turbolinks:load', () => {
|
30
38
|
triggerOnPageLoad();
|
31
39
|
});
|
@@ -21,14 +21,13 @@
|
|
21
21
|
margin: 0;
|
22
22
|
|
23
23
|
&--author {
|
24
|
-
margin-bottom:
|
24
|
+
margin-bottom: 2px;
|
25
25
|
}
|
26
26
|
|
27
27
|
.thredded--post--content {
|
28
28
|
font-size: inherit;
|
29
|
-
border-left: solid 5px $thredded-blockquote-border-color;
|
30
29
|
margin: 0 0 0.75rem;
|
31
|
-
padding:
|
30
|
+
padding-left: 0;
|
32
31
|
|
33
32
|
.onebox-wrapper-table {
|
34
33
|
width: 100%;
|
@@ -1,6 +1,19 @@
|
|
1
|
-
.thredded--preferences
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
.thredded--preferences--title {
|
2
|
+
@extend %thredded--heading;
|
3
|
+
font-size: 1.5rem; // 24px
|
4
|
+
}
|
5
|
+
|
6
|
+
.thredded--preferences--form {
|
7
|
+
padding-bottom: $thredded-base-spacing;
|
8
|
+
}
|
9
|
+
|
10
|
+
.thredded--preferences--messageboards-nav {
|
11
|
+
border-top: $thredded-base-border;
|
12
|
+
padding-top: $thredded-base-spacing;
|
13
|
+
}
|
14
|
+
|
15
|
+
.thredded--preferences--messageboards-nav--item {
|
16
|
+
&.thredded--messageboard {
|
17
|
+
padding: $thredded-small-spacing;
|
5
18
|
}
|
6
19
|
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Thredded
|
3
|
+
# @api private
|
4
|
+
module NewPostParams
|
5
|
+
protected
|
6
|
+
|
7
|
+
def new_post_params
|
8
|
+
params.fetch(:post, {})
|
9
|
+
.permit(:content, :quote_post_id)
|
10
|
+
.merge(ip: request.remote_ip).tap do |p|
|
11
|
+
quote_id = p.delete(:quote_post_id)
|
12
|
+
if quote_id
|
13
|
+
post = Post.find(quote_id)
|
14
|
+
authorize_reading post
|
15
|
+
p[:quote_post] = post
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Thredded
|
3
|
+
# @api private
|
4
|
+
module NewPrivatePostParams
|
5
|
+
protected
|
6
|
+
|
7
|
+
def new_private_post_params
|
8
|
+
params.fetch(:post, {})
|
9
|
+
.permit(:content, :quote_private_post_id)
|
10
|
+
.merge(ip: request.remote_ip).tap do |p|
|
11
|
+
quote_id = p.delete(:quote_private_post_id)
|
12
|
+
if quote_id
|
13
|
+
post = PrivatePost.find(quote_id)
|
14
|
+
authorize_reading post
|
15
|
+
p[:quote_post] = post
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -3,29 +3,39 @@ module Thredded
|
|
3
3
|
# A controller for managing {Post}s.
|
4
4
|
class PostsController < Thredded::ApplicationController
|
5
5
|
include ActionView::RecordIdentifier
|
6
|
+
include Thredded::NewPostParams
|
6
7
|
|
7
8
|
helper_method :topic
|
8
9
|
after_action :update_user_activity
|
9
10
|
|
10
11
|
after_action :verify_authorized
|
11
12
|
|
12
|
-
def
|
13
|
-
|
14
|
-
authorize_creating post
|
15
|
-
|
13
|
+
def new
|
14
|
+
@post_form = PostForm.new(user: thredded_current_user, topic: parent_topic, post_params: new_post_params)
|
15
|
+
authorize_creating @post_form.post
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
+
def create
|
19
|
+
@post_form = PostForm.new(user: thredded_current_user, topic: parent_topic, post_params: new_post_params)
|
20
|
+
authorize_creating @post_form.post
|
21
|
+
|
22
|
+
if @post_form.save
|
23
|
+
redirect_to post_path(@post_form.post, user: thredded_current_user)
|
24
|
+
else
|
25
|
+
render :new
|
26
|
+
end
|
18
27
|
end
|
19
28
|
|
20
29
|
def edit
|
21
|
-
|
30
|
+
@post_form = PostForm.for_persisted(post)
|
31
|
+
authorize @post_form.post, :update?
|
22
32
|
return redirect_to(canonical_topic_params) unless params_match?(canonical_topic_params)
|
23
33
|
render
|
24
34
|
end
|
25
35
|
|
26
36
|
def update
|
27
37
|
authorize post, :update?
|
28
|
-
post.update_attributes(
|
38
|
+
post.update_attributes(new_post_params)
|
29
39
|
|
30
40
|
redirect_to post_path(post, user: thredded_current_user)
|
31
41
|
end
|
@@ -45,6 +55,11 @@ module Thredded
|
|
45
55
|
after_mark_as_unread # customization hook
|
46
56
|
end
|
47
57
|
|
58
|
+
def quote
|
59
|
+
authorize_reading post
|
60
|
+
render plain: Thredded::ContentFormatter.quote_content(post.content)
|
61
|
+
end
|
62
|
+
|
48
63
|
private
|
49
64
|
|
50
65
|
def canonical_topic_params
|
@@ -59,12 +74,6 @@ module Thredded
|
|
59
74
|
post.postable
|
60
75
|
end
|
61
76
|
|
62
|
-
def post_params
|
63
|
-
params.require(:post)
|
64
|
-
.permit(:content)
|
65
|
-
.merge(user: thredded_current_user, ip: request.remote_ip, messageboard: messageboard)
|
66
|
-
end
|
67
|
-
|
68
77
|
def parent_topic
|
69
78
|
Topic
|
70
79
|
.where(messageboard: messageboard)
|
@@ -3,22 +3,35 @@ module Thredded
|
|
3
3
|
# A controller for managing {PrivatePost}s.
|
4
4
|
class PrivatePostsController < Thredded::ApplicationController
|
5
5
|
include ActionView::RecordIdentifier
|
6
|
+
include NewPrivatePostParams
|
6
7
|
|
7
8
|
helper_method :topic
|
8
9
|
after_action :update_user_activity
|
9
10
|
|
10
11
|
after_action :verify_authorized
|
11
12
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
def new
|
14
|
+
@post_form = PrivatePostForm.new(
|
15
|
+
user: thredded_current_user, topic: parent_topic, post_params: new_private_post_params
|
16
|
+
)
|
17
|
+
authorize_creating @post_form.post
|
18
|
+
end
|
16
19
|
|
17
|
-
|
20
|
+
def create
|
21
|
+
@post_form = PrivatePostForm.new(
|
22
|
+
user: thredded_current_user, topic: parent_topic, post_params: new_private_post_params
|
23
|
+
)
|
24
|
+
authorize_creating @post_form.post
|
25
|
+
if @post_form.save
|
26
|
+
redirect_to post_path(@post_form.post, user: thredded_current_user)
|
27
|
+
else
|
28
|
+
render :new
|
29
|
+
end
|
18
30
|
end
|
19
31
|
|
20
32
|
def edit
|
21
|
-
|
33
|
+
@post_form = PrivatePostForm.for_persisted(post)
|
34
|
+
authorize @post_form.post, :update?
|
22
35
|
return redirect_to(canonical_topic_params) unless params_match?(canonical_topic_params)
|
23
36
|
render
|
24
37
|
end
|
@@ -45,6 +58,11 @@ module Thredded
|
|
45
58
|
after_mark_as_unread # customization hook
|
46
59
|
end
|
47
60
|
|
61
|
+
def quote
|
62
|
+
authorize_reading post
|
63
|
+
render plain: Thredded::ContentFormatter.quote_content(post.content)
|
64
|
+
end
|
65
|
+
|
48
66
|
private
|
49
67
|
|
50
68
|
def canonical_topic_params
|
@@ -59,12 +77,6 @@ module Thredded
|
|
59
77
|
post.postable
|
60
78
|
end
|
61
79
|
|
62
|
-
def post_params
|
63
|
-
params.require(:post)
|
64
|
-
.permit(:content)
|
65
|
-
.merge(user: thredded_current_user, ip: request.remote_ip)
|
66
|
-
end
|
67
|
-
|
68
80
|
def parent_topic
|
69
81
|
PrivateTopic
|
70
82
|
.includes(:private_users)
|
@@ -2,6 +2,7 @@
|
|
2
2
|
module Thredded
|
3
3
|
class PrivateTopicsController < Thredded::ApplicationController
|
4
4
|
include Thredded::NewPrivateTopicParams
|
5
|
+
include Thredded::NewPrivatePostParams
|
5
6
|
|
6
7
|
before_action :thredded_require_login!
|
7
8
|
|
@@ -37,7 +38,9 @@ module Thredded
|
|
37
38
|
)
|
38
39
|
end
|
39
40
|
|
40
|
-
@
|
41
|
+
@new_post = Thredded::PrivatePostForm.new(
|
42
|
+
user: thredded_current_user, topic: private_topic, post_params: new_private_post_params
|
43
|
+
)
|
41
44
|
end
|
42
45
|
|
43
46
|
def new
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module Thredded
|
3
3
|
class ThemePreviewsController < Thredded::ApplicationController
|
4
|
-
def show
|
4
|
+
def show # rubocop:disable Metrics/MethodLength
|
5
5
|
@messageboard = Messageboard.first
|
6
6
|
fail Thredded::Errors::DatabaseEmpty unless @messageboard
|
7
7
|
@user = if thredded_current_user.thredded_anonymous?
|
@@ -16,7 +16,8 @@ module Thredded
|
|
16
16
|
@topic = TopicView.from_user(topic, @user)
|
17
17
|
@posts = TopicPostsPageView.new(@user, topic, topic.posts.page(1).limit(3))
|
18
18
|
@post = topic.posts.build(id: 1337, postable: topic, content: 'Hello world', user: @user)
|
19
|
-
@
|
19
|
+
@post_form = PostForm.for_persisted(@post)
|
20
|
+
@new_post = PostForm.new(user: @user, topic: topic)
|
20
21
|
@new_topic = TopicForm.new(user: @user, messageboard: @messageboard)
|
21
22
|
@new_private_topic = PrivateTopicForm.new(user: @user)
|
22
23
|
private_topic = PrivateTopic.new(id: 1337, title: 'Hello', user: @user, last_user: @user, users: [@user])
|
@@ -25,6 +26,7 @@ module Thredded
|
|
25
26
|
@private_post = private_topic.posts.build(
|
26
27
|
id: 1337, postable: private_topic, content: 'A private hello world', user: @user
|
27
28
|
)
|
29
|
+
@private_post_form = PrivatePostForm.for_persisted(@private_post)
|
28
30
|
@preferences = UserPreferencesForm.new(user: @user, messageboard: @messageboard)
|
29
31
|
end
|
30
32
|
end
|