thredded 0.7.0 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +119 -17
  3. data/app/assets/javascripts/thredded/components/currently_online.es6 +3 -3
  4. data/app/assets/javascripts/thredded/components/flash_messages.es6 +11 -0
  5. data/app/assets/javascripts/thredded/components/post_form.es6 +21 -4
  6. data/app/assets/javascripts/thredded/components/time_stamps.es6 +8 -6
  7. data/app/assets/javascripts/thredded/components/topic_form.es6 +14 -3
  8. data/app/assets/javascripts/thredded/components/topics.es6 +3 -3
  9. data/app/assets/javascripts/thredded/components/turboforms.es6 +15 -0
  10. data/app/assets/javascripts/thredded/components/user_preferences_form.es6 +47 -20
  11. data/app/assets/javascripts/thredded/components/users_select.es6 +25 -9
  12. data/app/assets/javascripts/thredded/core/hide_soft_keyboard.es6 +6 -0
  13. data/app/assets/javascripts/thredded/core/mention_autocompletion.es6 +54 -0
  14. data/app/assets/javascripts/thredded/core/on_page_load.es6 +46 -0
  15. data/app/assets/javascripts/thredded/dependencies.js +2 -1
  16. data/app/assets/javascripts/thredded/dependencies/jquery.js +1 -0
  17. data/app/assets/javascripts/thredded/thredded.es6 +1 -0
  18. data/app/assets/stylesheets/thredded/_thredded.scss +1 -0
  19. data/app/assets/stylesheets/thredded/base/_alerts.scss +5 -1
  20. data/app/assets/stylesheets/thredded/base/_grid.scss +8 -0
  21. data/app/assets/stylesheets/thredded/base/_nav.scss +0 -5
  22. data/app/assets/stylesheets/thredded/components/_following.scss +0 -3
  23. data/app/assets/stylesheets/thredded/components/_mention-autocomplete.scss +35 -0
  24. data/app/assets/stylesheets/thredded/components/_topic-header.scss +37 -17
  25. data/app/assets/stylesheets/thredded/components/_topics.scss +13 -0
  26. data/app/assets/stylesheets/thredded/layout/_main-navigation.scss +57 -14
  27. data/app/assets/stylesheets/thredded/layout/_moderation.scss +5 -0
  28. data/app/assets/stylesheets/thredded/layout/_navigation.scss +14 -17
  29. data/app/assets/stylesheets/thredded/layout/_search-navigation.scss +15 -3
  30. data/app/assets/stylesheets/thredded/layout/_user-navigation.scss +3 -11
  31. data/app/commands/thredded/at_notification_extractor.rb +2 -2
  32. data/app/commands/thredded/autofollow_mentioned_users.rb +2 -2
  33. data/app/commands/thredded/create_messageboard.rb +45 -0
  34. data/app/commands/thredded/notify_following_users.rb +10 -0
  35. data/app/controllers/thredded/autocomplete_users_controller.rb +2 -3
  36. data/app/controllers/thredded/messageboards_controller.rb +1 -24
  37. data/app/controllers/thredded/moderation_controller.rb +1 -1
  38. data/app/controllers/thredded/post_permalinks_controller.rb +1 -1
  39. data/app/controllers/thredded/preferences_controller.rb +4 -2
  40. data/app/controllers/thredded/private_post_permalinks_controller.rb +1 -1
  41. data/app/controllers/thredded/theme_previews_controller.rb +1 -1
  42. data/app/controllers/thredded/topics_controller.rb +0 -1
  43. data/app/forms/thredded/user_preferences_form.rb +4 -2
  44. data/app/helpers/thredded/application_helper.rb +5 -0
  45. data/app/helpers/thredded/nav_helper.rb +41 -0
  46. data/app/mailer_previews/thredded/base_mailer_preview.rb +0 -1
  47. data/app/mailers/thredded/post_mailer.rb +0 -1
  48. data/app/mailers/thredded/private_topic_mailer.rb +0 -1
  49. data/app/models/concerns/thredded/user_topic_read_state_common.rb +2 -2
  50. data/app/models/thredded/messageboard.rb +0 -1
  51. data/app/models/thredded/null_preference.rb +5 -1
  52. data/app/models/thredded/private_post.rb +2 -2
  53. data/app/policies/thredded/messageboard_group_policy.rb +1 -1
  54. data/app/view_hooks/thredded/all_view_hooks.rb +68 -0
  55. data/app/view_models/thredded/post_view.rb +3 -3
  56. data/app/view_models/thredded/topic_email_view.rb +0 -4
  57. data/app/view_models/thredded/topics_page_view.rb +12 -1
  58. data/app/views/layouts/thredded/application.html.erb +5 -2
  59. data/app/views/thredded/messageboard_groups/new.html.erb +3 -1
  60. data/app/views/thredded/messageboards/edit.html.erb +3 -1
  61. data/app/views/thredded/messageboards/new.html.erb +3 -1
  62. data/app/views/thredded/moderation/_users_search_form.html.erb +4 -1
  63. data/app/views/thredded/moderation/user.html.erb +34 -28
  64. data/app/views/thredded/posts_common/_form.html.erb +6 -1
  65. data/app/views/thredded/posts_common/form/_content_field.html.erb +5 -3
  66. data/app/views/thredded/preferences/_form.html.erb +30 -12
  67. data/app/views/thredded/private_topics/_form.html.erb +4 -3
  68. data/app/views/thredded/private_topics/index.html.erb +5 -5
  69. data/app/views/thredded/search/_form.html.erb +2 -1
  70. data/app/views/thredded/shared/_flash_messages.html.erb +1 -1
  71. data/app/views/thredded/shared/_page.html.erb +10 -1
  72. data/app/views/thredded/shared/nav/_moderation.html.erb +3 -2
  73. data/app/views/thredded/shared/nav/_notification_preferences.html.erb +5 -3
  74. data/app/views/thredded/shared/nav/_private_topics.html.erb +3 -2
  75. data/app/views/thredded/topics/_form.html.erb +6 -1
  76. data/app/views/thredded/topics/_header.html.erb +8 -5
  77. data/config/locales/en.yml +15 -7
  78. data/config/locales/pt-BR.yml +21 -13
  79. data/config/routes.rb +4 -2
  80. data/db/migrate/20160329231848_create_thredded.rb +5 -5
  81. data/db/upgrade_migrations/20161019150201_upgrade_v0_7_to_v0_8.rb +31 -0
  82. data/lib/generators/thredded/install/templates/initializer.rb +20 -8
  83. data/lib/tasks/thredded_tasks.rake +0 -7
  84. data/lib/thredded.rb +19 -5
  85. data/lib/thredded/content_formatter.rb +43 -8
  86. data/lib/thredded/database_seeder.rb +7 -1
  87. data/lib/thredded/engine.rb +2 -21
  88. data/lib/{html/pipeline → thredded/html_pipeline}/at_mention_filter.rb +4 -4
  89. data/lib/thredded/html_pipeline/autolink_filter.rb +14 -0
  90. data/lib/thredded/html_pipeline/kramdown_filter.rb +34 -0
  91. data/lib/thredded/version.rb +1 -1
  92. data/lib/thredded/view_hooks/config.rb +36 -0
  93. data/lib/thredded/view_hooks/renderer.rb +29 -0
  94. data/vendor/assets/javascripts/jquery.textcomplete.js +1488 -0
  95. metadata +65 -52
  96. data/app/commands/thredded/messageboard_destroyer.rb +0 -65
  97. data/lib/html/pipeline/bbcode_filter.rb +0 -33
  98. data/lib/thredded/main_app_route_delegator.rb +0 -25
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a4599cfd4cc1a0446216da0bb6c5bfcb19ad857d
4
- data.tar.gz: 24286dd248ea8aa78737a5ee708ae3af0b2d0ad0
3
+ metadata.gz: 0b5134ae28a842aa241f4de392cd1679bb84d8d3
4
+ data.tar.gz: 8481a216ec08609350f19c86d9b88a2f1560d857
5
5
  SHA512:
6
- metadata.gz: 0019fe0f00970082f29c57572ff07968de460d2a0cb9d8ab2590a668ef68a954078ac41f5d64a1e0125c4f6d0aabfd4a7465a96dae5685e0ce65f1b9cd0a8796
7
- data.tar.gz: e4fb202dee30cad34b4cc8ced571cd0c6968c7ab5989b7e4d7722916fe4eb382e9e0abaa7ef237ebad6e32c546f6bf315fa6853daa6da8647101f4061f6a5e06
6
+ metadata.gz: 2c039dfafa5e1b3e890694fd77581e1eb4795f3c5503c3ac4f41120e9c8398e551c04a3bde6b2d007aa2f636ca0315debeb71c91cd9e5cba61c06743de4f2199
7
+ data.tar.gz: a8fac9025ad895c6003513807d4e4d246d50b4c5ae3f5f414823b69e9673ea1e4c578e362bbf2d67d6f69de9cbc76ade42d493ddae931cfc39df9cfeed518392
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
- # Thredded [![Code Climate](https://codeclimate.com/github/thredded/thredded/badges/gpa.svg)](https://codeclimate.com/github/thredded/thredded) [![Travis-CI](https://api.travis-ci.org/thredded/thredded.svg?branch=master)](https://travis-ci.org/thredded/thredded/) [![Test Coverage](https://codeclimate.com/github/thredded/thredded/badges/coverage.svg)](https://codeclimate.com/github/thredded/thredded/coverage) [![Gitter](https://badges.gitter.im/thredded/thredded.svg)](https://gitter.im/thredded/thredded?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Stories in Ready](https://badge.waffle.io/thredded/thredded.svg?label=ready&title=waffle.io)](http://waffle.io/thredded/thredded)
1
+ # Thredded [![Code Climate](https://codeclimate.com/github/thredded/thredded/badges/gpa.svg)](https://codeclimate.com/github/thredded/thredded) [![Travis-CI](https://api.travis-ci.org/thredded/thredded.svg?branch=master)](https://travis-ci.org/thredded/thredded/) [![Test Coverage](https://codeclimate.com/github/thredded/thredded/badges/coverage.svg)](https://codeclimate.com/github/thredded/thredded/coverage) [![Inline docs](http://inch-ci.org/github/thredded/thredded.svg?branch=master)](http://inch-ci.org/github/thredded/thredded) [![Gitter](https://badges.gitter.im/thredded/thredded.svg)](https://gitter.im/thredded/thredded?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
2
2
 
3
3
  _Thredded_ is a Rails 4.2+ forum/messageboard engine. Its goal is to be as simple and feature rich as possible.
4
4
 
5
5
  Some of the features currently in Thredded:
6
6
 
7
- * Markdown post formatting with some BBCode support (by default).
7
+ * Markdown (default) or BBCode post formatting.
8
8
  * (Un)read posts tracking.
9
9
  * Email notifications, topic subscriptions, @-mentions, per-messageboard notification settings.
10
10
  * Private group messaging.
@@ -41,10 +41,28 @@ application and not an engine like Thredded.
41
41
 
42
42
  ## Installation
43
43
 
44
+ ### Creating a new Rails app with Thredded
45
+
46
+ Thredded provides an app generator that will generate a Rails app with Thredded, Devise, SimpleForm, RSpec,
47
+ PostgreSQL, and a basic theme and navigation that is configured to work out of the box.
48
+
49
+ ```sh
50
+ gem install thredded_create_app
51
+ thredded_create_app path/to/myapp
52
+ ```
53
+
54
+ See `thredded_create_app --help` and the [thredded_create_app repo] to learn about the various options.
55
+
56
+ Then, see the rest of this Readme for more information about using and customizing Thredded.
57
+
58
+ [thredded_create_app repo]: https://github.com/thredded/thredded_create_app
59
+
60
+ ### Adding Thredded to an existing Rails app
61
+
44
62
  Add the gem to your Gemfile:
45
63
 
46
64
  ```ruby
47
- gem 'thredded', '~> 0.7.0'
65
+ gem 'thredded', '~> 0.8.2'
48
66
  ```
49
67
 
50
68
  Add the Thredded [initializer] to your parent app by running the install generator.
@@ -114,14 +132,14 @@ to Thredded.
114
132
 
115
133
  ### Standalone layout
116
134
 
117
- By default, thredded renders in its own layout.
135
+ By default, thredded renders in its own (standalone) layout.
118
136
 
119
137
  When using the standalone thredded layout, the log in / sign out links will be rendered in the navigation.
120
138
  For these links (and only for these links), Thredded makes the assumption that you are using devise as your auth
121
139
  library. If you are using something different you need to override the partial at
122
140
  `app/views/thredded/shared/nav/_standalone.html.erb` and use the appropriate log in / sign out path URL helpers.
123
141
 
124
- You can override the partial by copying it into the app:
142
+ You can override the partial by copying it into your app:
125
143
 
126
144
  ```bash
127
145
  mkdir -p app/views/thredded/shared/nav && cp "$(bundle show thredded)/$_/_standalone.html.erb" "$_"
@@ -129,7 +147,19 @@ mkdir -p app/views/thredded/shared/nav && cp "$(bundle show thredded)/$_/_standa
129
147
 
130
148
  ### Application layout
131
149
 
132
- You can also use Thredded with the application layout by by setting `Thredded.layout` in the initializer.
150
+ You can also use Thredded with your application (or other) layout by by setting `Thredded.layout` in the initializer.
151
+
152
+ In this case, you will need to reference your paths/routes carefully and pull in thredded assets (styles and javascript):
153
+
154
+ #### Referencing your paths so that thredded views can find them
155
+
156
+ In your layout you will probably have links to other paths in your app (e.g. navigation links).
157
+ For any url helpers (like `users_path` or `projects_path` or whatever) will need to have `main_app.` prefixed to them so that they can be found from thredded (`main_app.users_path` will work from either thredded or your app).
158
+
159
+ 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:
160
+ See https://gist.github.com/timdiggins/bf6d09b28828a392198562c93554ad07.
161
+
162
+ #### Pulling in thredded assets (styles and javascript)
133
163
 
134
164
  In this case, you will also need to include Thredded styles and JavaScript into the application styles and JavaScript.
135
165
 
@@ -145,6 +175,14 @@ Include thredded JavaScripts in your `application.js`:
145
175
  //= require thredded
146
176
  ```
147
177
 
178
+ To use thredded with your application layout, you also need to ensure that your layout and thredded don't load different
179
+ versions of jQuery. By default, Thredded loads jQuery v3 (via `//= require jquery3` from [jquery-rails]),
180
+ but if you want to use jQuery v1 or v2, then you need to create a file at
181
+ `app/assets/javascripts/thredded/dependencies/jquery.js` which contains just `//= require jquery`
182
+ or `// require jquery2`. If you are not loading jQuery in your app, or if you are already using jQuery v3, then you don't need to do do this (You also don't need to worry about this if you are using the default ["Standalone" layout](#standalone-layout))
183
+
184
+ [jquery-rails]: https://github.com/rails/jquery-rails
185
+
148
186
  Thredded views also provide two `content_tag`s available to yield - `:thredded_page_title` and `:thredded_page_id`.
149
187
  The views within Thredded pass those up through to your layout if you would like to use them.
150
188
 
@@ -180,17 +218,31 @@ mkdir -p app/views/thredded/posts && cp "$(bundle show thredded)/$_/_post.html.e
180
218
  customizations are still compatible with the new version of thredded. This is difficult and error-prone.
181
219
  Whenever possible, use the styles and i18n to customize Thredded to your needs.
182
220
 
183
- #### Empty view partials included for customization
221
+ #### View hooks
222
+
223
+ Thredded provides view hooks to customize the UI before/after/replacing individual components.
184
224
 
185
- There are 2 empty view partials included in the gem that exist for the purpose of being overridden
186
- in the parent app *if desired*. They are:
225
+ View hooks allow you to render anything in the thredded view context.
226
+ For example, to render a partial after the post content textarea, add the snippet below to
227
+ the `config/initializers/thredded.rb` initializer:
187
228
 
188
- * `app/views/thredded/posts_common/form/_before_content.html.erb`
189
- * `app/views/thredded/posts_common/form/_after_content.html.erb`
229
+ ```ruby
230
+ Rails.application.config.to_prepare do
231
+ Thredded.view_hooks.post_form.content_text_area.config.before do |form:, **args|
232
+ # This is render in the Thredded view context, so all Thredded helpers and URLs are accessible here directly.
233
+ render 'my/partial', form: form
234
+ end
235
+ end
236
+ ```
237
+
238
+ You can use the post content textarea hook to add things like wysiwyg/wymean editors, buttons, help links, help copy,
239
+ further customization for the textarea, etc.
190
240
 
191
- And are rendered directly before, and directly after the textarea where users type their post
192
- contents. These exist in the case where a messageboard would like to add things like, wysiwyg/wymean
193
- editors, buttons, help links, help copy, further customization for the textarea, etc.
241
+ To see the complete list of view hooks and their arguments, run:
242
+
243
+ ```bash
244
+ grep view_hooks -R --include '*.html.erb' "$(bundle show thredded)"
245
+ ```
194
246
 
195
247
  ## Theming
196
248
 
@@ -442,11 +494,61 @@ rake dev:server
442
494
  To run the tests, just run `rspec`. The test suite will re-create the test database on every run, so there is no need to
443
495
  run tasks that maintain the test database.
444
496
 
445
- Run `rubocop` to ensure a consistent code style across the codebase.
446
-
447
- By default, SQLite is used in development and test. On Travis, the tests will run using SQLite, PostgreSQL, SQLite,
497
+ By default, SQLite is used in development and test. On Travis, the tests will run using SQLite, PostgreSQL, MySQL,
448
498
  and all the supported Rails versions.
449
499
 
500
+ ### Ruby
501
+
502
+ Thredded Ruby code formatting is ensured by [Rubocop](https://github.com/bbatsov/rubocop). Run `rubocop -a` to ensure a
503
+ consistent code style across the codebase.
504
+
505
+ Thredded is documented with [YARD](http://yardoc.org/) and you can use the
506
+ [inch gem](https://github.com/rrrene/inch) or the [Inch CI](http://inch-ci.org/github/thredded/thredded) to find code
507
+ that lacks documentation.
508
+
509
+ ### JavaScript
510
+
511
+ Currently, Thredded JavaScript is written in the subset of ES6 that does not
512
+ require Babel polyfills. We're waiting for the ES6/7 support on Rails to improve
513
+ before updating this to full Babel.
514
+
515
+ All Thredded JavaScript is compatible with the following Turbolinks options:
516
+
517
+ * No Turbolinks.
518
+ * Tubrolinks 5.
519
+ * Turbolinks Classic.
520
+ * Turbolinks Classic + jquery-turbolinks.
521
+
522
+ Thredded JavaScript is also compatible with being loaded from script elements with
523
+ `[async]` and/or `[defer]` attributes.
524
+
525
+ To achieve the above, all the Thredded code must register onload via
526
+ `Thredded.onPageLoad`, e.g.:
527
+
528
+ ```js
529
+ window.Thredded.onPageLoad(() => {
530
+ // Initialize widgets:
531
+ $('[data-thredded-select2]').select2();
532
+ });
533
+ ```
534
+
535
+ Additionally, all the thredded views must be wrapped in a `<%= thredded_page do %>` block.
536
+
537
+ On Turbolinks 5 onPageLoad will run on the same DOM when the page is restored
538
+ from history (because Turbolinks 5 caches a *clone* of the body node, so
539
+ the events are lost).
540
+
541
+ This means that all DOM modifications on `window.Thredded.onPageLoad` must be
542
+ idempotent, or they must be reverted on the `turbolinks:before-cache` event,
543
+ e.g.:
544
+
545
+ ```js
546
+ document.addEventListener('turbolinks:before-cache', () => {
547
+ // Destroy widgets:
548
+ $('[data-thredded-select2]').select2('destroy');
549
+ });
550
+ ```
551
+
450
552
  ### Testing with all the databases and Rails versions locally.
451
553
 
452
554
  You can also test the gem with all the supported databases and Rails versions locally.
@@ -1,4 +1,4 @@
1
- (function($) {
1
+ (($) => {
2
2
  const COMPONENT_SELECTOR = '[data-thredded-currently-online]';
3
3
 
4
4
  class ThreddedCurrentlyOnline {
@@ -16,8 +16,8 @@
16
16
  }
17
17
  }
18
18
 
19
- $(function() {
20
- var $nodes = $(COMPONENT_SELECTOR);
19
+ window.Thredded.onPageLoad(() => {
20
+ const $nodes = $(COMPONENT_SELECTOR);
21
21
  if ($nodes.length) {
22
22
  new ThreddedCurrentlyOnline().init($nodes);
23
23
  }
@@ -0,0 +1,11 @@
1
+ (($) => {
2
+ const COMPONENT_SELECTOR = '[data-thredded-flash-message]';
3
+
4
+ const destroy = () => {
5
+ $(COMPONENT_SELECTOR).remove();
6
+ };
7
+
8
+ document.addEventListener('turbolinks:before-cache', () => {
9
+ destroy()
10
+ });
11
+ })(jQuery);
@@ -1,4 +1,4 @@
1
- (function($) {
1
+ (($) => {
2
2
  const COMPONENT_SELECTOR = '[data-thredded-post-form]';
3
3
 
4
4
  class ThreddedPostForm {
@@ -7,14 +7,31 @@
7
7
  }
8
8
 
9
9
  init($nodes) {
10
- $nodes.find(this.textareaSelector).autosize();
10
+ let $textarea = $nodes.find(this.textareaSelector);
11
+ this.autosize($textarea);
12
+ new ThreddedMentionAutocompletion($).init($nodes);
13
+ }
14
+
15
+ autosize($textarea) {
16
+ $textarea.autosize()
17
+ }
18
+
19
+ destroy($nodes) {
20
+ $nodes.find(this.textareaSelector).trigger('autosize.destroy');
11
21
  }
12
22
  }
13
23
 
14
- $(function() {
15
- var $nodes = $(COMPONENT_SELECTOR);
24
+ window.Thredded.onPageLoad(() => {
25
+ const $nodes = $(COMPONENT_SELECTOR);
16
26
  if ($nodes.length) {
17
27
  new ThreddedPostForm().init($nodes);
18
28
  }
19
29
  });
30
+
31
+ document.addEventListener('turbolinks:before-cache', () => {
32
+ const $nodes = $(COMPONENT_SELECTOR);
33
+ if ($nodes.length) {
34
+ new ThreddedPostForm().destroy($nodes);
35
+ }
36
+ });
20
37
  })(jQuery);
@@ -1,8 +1,10 @@
1
- jQuery(function($) {
1
+ (($) => {
2
2
  const COMPONENT_SELECTOR = '#thredded--container abbr.timeago';
3
3
 
4
- var allowFutureWas = jQuery.timeago.settings.allowFuture;
5
- $.timeago.settings.allowFuture = true;
6
- $(COMPONENT_SELECTOR).timeago();
7
- $.timeago.settings.allowFuture = allowFutureWas;
8
- });
4
+ window.Thredded.onPageLoad(() => {
5
+ const allowFutureWas = jQuery.timeago.settings.allowFuture;
6
+ $.timeago.settings.allowFuture = true;
7
+ $(COMPONENT_SELECTOR).timeago();
8
+ $.timeago.settings.allowFuture = allowFutureWas;
9
+ });
10
+ })(jQuery);
@@ -1,4 +1,4 @@
1
- (function($) {
1
+ (($) => {
2
2
  const COMPONENT_SELECTOR = '[data-thredded-topic-form]';
3
3
  class ThreddedTopicForm {
4
4
  constructor() {
@@ -16,6 +16,7 @@
16
16
 
17
17
  init($nodes) {
18
18
  $nodes.find(this.textareaSelector).autosize();
19
+ new ThreddedMentionAutocompletion($).init($nodes);
19
20
  $nodes.filter(this.compactSelector).
20
21
  on('focus', this.titleSelector, e => {
21
22
  this.toggleExpanded(e.target, true);
@@ -42,14 +43,24 @@
42
43
  });
43
44
  }
44
45
 
46
+ destroy($nodes) {
47
+ $nodes.find(this.textareaSelector).trigger('autosize.destroy');
48
+ }
45
49
  }
46
50
 
47
- $(function() {
48
- var $nodes = $(COMPONENT_SELECTOR);
51
+ window.Thredded.onPageLoad(() => {
52
+ const $nodes = $(COMPONENT_SELECTOR);
49
53
  if ($nodes.length) {
50
54
  new ThreddedTopicForm().init($nodes);
51
55
  }
52
56
  });
57
+
58
+ document.addEventListener('turbolinks:before-cache', () => {
59
+ const $nodes = $(COMPONENT_SELECTOR);
60
+ if ($nodes.length) {
61
+ new ThreddedTopicForm().destroy($nodes);
62
+ }
63
+ });
53
64
  })(jQuery);
54
65
 
55
66
 
@@ -1,4 +1,4 @@
1
- (function($) {
1
+ (($) => {
2
2
  const COMPONENT_SELECTOR = '[data-thredded-topics]';
3
3
 
4
4
  const TOPIC_SELECTOR = 'article';
@@ -28,8 +28,8 @@
28
28
  }
29
29
  }
30
30
 
31
- $(function() {
32
- var $nodes = $(COMPONENT_SELECTOR);
31
+ window.Thredded.onPageLoad(() => {
32
+ const $nodes = $(COMPONENT_SELECTOR);
33
33
  if ($nodes.length) {
34
34
  new ThreddedTopics().init($nodes);
35
35
  }
@@ -0,0 +1,15 @@
1
+ // Submit GET forms with turbolinks
2
+ (function($) {
3
+ if (window.Turbolinks && window.Turbolinks.supported) {
4
+ window.Thredded.onPageLoad(() => {
5
+ $('[data-thredded-turboform]').on('submit', function(evt) {
6
+ evt.preventDefault();
7
+ Turbolinks.visit(this.action + (this.action.indexOf('?') === -1 ? '?' : '&') + $(this).serialize());
8
+
9
+ // On mobile the soft keyboard doesn't won't go away after the submit since we're submitting with
10
+ // Turbolinks. Hide it:
11
+ window.Thredded.hideSoftKeyboard();
12
+ });
13
+ });
14
+ }
15
+ })(jQuery);
@@ -1,40 +1,67 @@
1
- (function($) {
1
+ (($) => {
2
2
  const COMPONENT_SELECTOR = '[data-thredded-user-preferences-form]';
3
- const NOTIFY_ON_MENTION_SELECTOR = ':checkbox[name="user_preferences_form[notify_on_mention]"]';
4
- const MESSAGEBOARD_NOTIFY_ON_MENTION_SELECTOR = '[name="user_preferences_form[messageboard_notify_on_mention]"]';
3
+ const FOLLOW_TOPICS_ON_MENTION_SELECTOR = ':checkbox[name="user_preferences_form[follow_topics_on_mention]"]';
4
+ const MESSAGEBOARD_FOLLOW_TOPICS_ON_MENTION_SELECTOR = '[name="user_preferences_form[messageboard_follow_topics_on_mention]"]';
5
+ const FOLLOWED_TOPIC_EMAILS_SELECTOR = ':checkbox[name="user_preferences_form[followed_topic_emails]"]';
6
+ const MESSAGEBOARD_FOLLOWED_TOPIC_EMAILS_SELECTOR = ':checkbox[name="user_preferences_form[messageboard_followed_topic_emails]"]';
5
7
 
6
8
  class UserPreferencesForm {
7
9
  constructor(form) {
8
10
  this.$form = $(form);
9
- this.$notifyOnMention = this.$form.find(NOTIFY_ON_MENTION_SELECTOR);
10
- this.$messageboardNotifyOnMention = this.$form.find(MESSAGEBOARD_NOTIFY_ON_MENTION_SELECTOR);
11
+ this.$followTopicsOnMention = this.$form.find(FOLLOW_TOPICS_ON_MENTION_SELECTOR);
12
+ this.$messageboardFollowTopicsOnMention = this.$form.find(MESSAGEBOARD_FOLLOW_TOPICS_ON_MENTION_SELECTOR);
13
+ this.$followedTopicEmails = this.$form.find(FOLLOWED_TOPIC_EMAILS_SELECTOR);
14
+ this.$messageboardFollowedTopicEmails = this.$form.find(MESSAGEBOARD_FOLLOWED_TOPIC_EMAILS_SELECTOR);
11
15
 
12
- this.messageboardNotifyOnMentionCheckedWas = this.$messageboardNotifyOnMention.prop('checked');
13
- this.$messageboardNotifyOnMention.on('change', () => {
14
- this.rememberMessageboardNotifyOnMentionChecked();
16
+ this.messageboardFollowTopicsOnMentionCheckedWas = this.$messageboardFollowTopicsOnMention.prop('checked');
17
+ this.$messageboardFollowTopicsOnMention.on('change', () => {
18
+ this.rememberMessageboardAutofollowTopicsChecked();
15
19
  });
16
- this.rememberMessageboardNotifyOnMentionChecked();
20
+ this.rememberMessageboardAutofollowTopicsChecked();
17
21
 
18
- this.$notifyOnMention.on('change', () => {
19
- this.updateMessageboardNotifyOnMention();
22
+ this.$followTopicsOnMention.on('change', () => {
23
+ this.updateMessageboardAutofollowTopics();
20
24
  });
21
- this.updateMessageboardNotifyOnMention();
25
+ this.updateMessageboardAutofollowTopics();
26
+
27
+ this.messageboardFollowedTopicEmailsCheckedWas = this.$messageboardFollowedTopicEmails.prop('checked');
28
+ this.$messageboardFollowedTopicEmails.on('change', () => {
29
+ this.rememberMessageboardFollowedTopicEmailsChecked();
30
+ });
31
+ this.rememberMessageboardFollowedTopicEmailsChecked();
32
+
33
+ this.$followedTopicEmails.on('change', () => {
34
+ this.updateMessageboardFollowedTopicEmails();
35
+ });
36
+ this.updateMessageboardFollowedTopicEmails();
37
+ }
38
+
39
+ rememberMessageboardAutofollowTopicsChecked() {
40
+ this.messageboardFollowTopicsOnMentionCheckedWas =
41
+ this.$messageboardFollowTopicsOnMention.filter(':checkbox').prop('checked');
42
+ }
43
+
44
+ updateMessageboardAutofollowTopics() {
45
+ const enabled = this.$followTopicsOnMention.prop('checked');
46
+ this.$messageboardFollowTopicsOnMention
47
+ .prop('disabled', !enabled)
48
+ .filter(':checkbox').prop('checked', enabled ? this.messageboardFollowTopicsOnMentionCheckedWas : false);
22
49
  }
23
50
 
24
- rememberMessageboardNotifyOnMentionChecked() {
25
- this.messageboardNotifyOnMentionCheckedWas =
26
- this.$messageboardNotifyOnMention.filter(':checkbox').prop('checked');
51
+ rememberMessageboardFollowedTopicEmailsChecked() {
52
+ this.messageboardFollowedTopicEmailsCheckedWas =
53
+ this.$messageboardFollowedTopicEmails.filter(':checkbox').prop('checked');
27
54
  }
28
55
 
29
- updateMessageboardNotifyOnMention() {
30
- const enabled = this.$notifyOnMention.prop('checked');
31
- this.$messageboardNotifyOnMention
56
+ updateMessageboardFollowedTopicEmails() {
57
+ const enabled = this.$followedTopicEmails.prop('checked');
58
+ this.$messageboardFollowedTopicEmails
32
59
  .prop('disabled', !enabled)
33
- .filter(':checkbox').prop('checked', enabled ? this.messageboardNotifyOnMentionCheckedWas : false);
60
+ .filter(':checkbox').prop('checked', enabled ? this.messageboardFollowedTopicEmailsCheckedWas : false);
34
61
  }
35
62
  }
36
63
 
37
- $(function() {
64
+ window.Thredded.onPageLoad(() => {
38
65
  const $forms = $(COMPONENT_SELECTOR);
39
66
  if ($forms.length) {
40
67
  $forms.each(function() {