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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 267a7718fa00308d076699e3970f2e3d74946f28
4
- data.tar.gz: 40e40286c2af13e04f3af5b72b376d5a3e3a8209
3
+ metadata.gz: 9da3f257731b6397128563a35788225046e8a589
4
+ data.tar.gz: fc0b9d0117acd6de8c6d21fa1d3ff629e3e463e3
5
5
  SHA512:
6
- metadata.gz: 0b2074d057c58a048c9cb3bba55de02e95099f604a95fc75b843cd0c48fb71a81d04b8c2d18a89e0e0a71e193039cacec83aa27eb0d9ea9f09b75e85efe6fb5d
7
- data.tar.gz: 2ebee2bec698ce19036b4845ff4ca1ec04ecf0c5848d71ad5f67593fac08e979997cae369739cfdbc04fcbf6a71295372eee7da8df881f6085ce0eb62bb3e043
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.11.1'
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.10.0
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.autosize()
21
+ autosize($textarea)
22
22
  }
23
23
 
24
24
  destroy($nodes) {
25
- $nodes.find(this.textareaSelector).trigger('autosize.destroy');
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).autosize();
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).trigger('autosize.destroy');
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
  });
@@ -2,7 +2,7 @@
2
2
  // Require jquery.timeago instead of rails-timeago so that we can control the initialization.
3
3
  //= require jquery.timeago
4
4
  //= require jquery_ujs
5
- //= require jquery.autosize
5
+ //= require autosize
6
6
  //= require jquery.textcomplete
7
7
  //= require select2
8
8
 
@@ -21,14 +21,13 @@
21
21
  margin: 0;
22
22
 
23
23
  &--author {
24
- margin-bottom: 1em;
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: ($thredded-small-spacing / 2) $thredded-small-spacing;
30
+ padding-left: 0;
32
31
 
33
32
  .onebox-wrapper-table {
34
33
  width: 100%;
@@ -1,6 +1,19 @@
1
- .thredded--preferences-header {
2
- &--title {
3
- @extend %thredded--heading;
4
- font-size: 1.5rem; // 24px
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 create
13
- post = parent_topic.posts.build(post_params)
14
- authorize_creating post
15
- post.save!
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
- redirect_to post_path(post, user: thredded_current_user)
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
- authorize post, :update?
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(post_params.except(:user, :ip))
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)
@@ -21,6 +21,7 @@ module Thredded
21
21
  @preferences = UserPreferencesForm.new(
22
22
  user: thredded_current_user,
23
23
  messageboard: messageboard_or_nil,
24
+ messageboards: policy_scope(Messageboard.all),
24
25
  params: preferences_params
25
26
  )
26
27
  end
@@ -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 create
13
- post = parent_topic.posts.build(post_params)
14
- authorize_creating post
15
- post.save!
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
- redirect_to post_path(post, user: thredded_current_user)
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
- authorize post, :update?
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
- @post = private_topic.posts.build
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
- @new_post = @messageboard.posts.build(postable: topic)
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