thredded 0.14.4 → 0.15.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -2
- data/app/assets/javascripts/thredded/components/preview_area.es6 +3 -0
- data/app/assets/javascripts/thredded/components/spoilers.es6 +37 -0
- data/app/assets/stylesheets/thredded/_email.scss +25 -0
- data/app/assets/stylesheets/thredded/_thredded.scss +1 -0
- data/app/assets/stylesheets/thredded/base/_typography.scss +1 -1
- data/app/assets/stylesheets/thredded/base/_variables.scss +2 -3
- data/app/assets/stylesheets/thredded/components/_post.scss +0 -11
- data/app/assets/stylesheets/thredded/components/_spoiler.scss +41 -0
- data/app/commands/thredded/mark_all_read.rb +1 -7
- data/app/controllers/concerns/thredded/new_post_params.rb +1 -1
- data/app/controllers/concerns/thredded/new_private_post_params.rb +1 -1
- data/app/controllers/concerns/thredded/new_private_topic_params.rb +1 -2
- data/app/controllers/concerns/thredded/new_topic_params.rb +0 -1
- data/app/controllers/thredded/application_controller.rb +10 -0
- data/app/controllers/thredded/posts_controller.rb +1 -2
- data/app/controllers/thredded/private_posts_controller.rb +1 -2
- data/app/controllers/thredded/private_topics_controller.rb +10 -12
- data/app/controllers/thredded/topics_controller.rb +14 -17
- data/app/forms/thredded/edit_topic_form.rb +2 -1
- data/app/forms/thredded/post_form.rb +3 -1
- data/app/forms/thredded/private_post_form.rb +3 -1
- data/app/forms/thredded/private_topic_form.rb +1 -0
- data/app/jobs/thredded/activity_updater_job.rb +18 -8
- data/app/jobs/thredded/auto_follow_and_notify_job.rb +2 -1
- data/app/models/concerns/thredded/post_common.rb +3 -4
- data/app/models/concerns/thredded/topic_common.rb +7 -0
- data/app/models/concerns/thredded/user_topic_read_state_common.rb +62 -5
- data/app/models/thredded/null_user_topic_read_state.rb +8 -0
- data/app/policies/thredded/private_post_policy.rb +16 -0
- data/app/view_hooks/thredded/all_view_hooks.rb +3 -0
- data/app/view_models/thredded/base_topic_view.rb +5 -1
- data/app/view_models/thredded/post_view.rb +13 -1
- data/app/view_models/thredded/posts_page_view.rb +1 -1
- data/app/view_models/thredded/topic_posts_page_view.rb +13 -1
- data/app/views/thredded/posts/_post.html.erb +1 -0
- data/app/views/thredded/posts/edit.html.erb +1 -0
- data/app/views/thredded/posts_common/_before_first_unread_post.html.erb +7 -0
- data/app/views/thredded/posts_common/form/_after_content.html.erb +8 -0
- data/app/views/thredded/posts_common/form/_before_content.html.erb +8 -0
- data/app/views/thredded/private_posts/_private_post.html.erb +2 -1
- data/app/views/thredded/private_posts/edit.html.erb +1 -0
- data/app/views/thredded/private_topics/_form.html.erb +1 -0
- data/app/views/thredded/private_topics/edit.html.erb +2 -1
- data/app/views/thredded/shared/_field_errors.html.erb +3 -0
- data/app/views/thredded/shared/_nav.html.erb +1 -1
- data/app/views/thredded/shared/_page.html.erb +1 -1
- data/app/views/thredded/topics/_form.html.erb +1 -0
- data/app/views/thredded/topics/edit.html.erb +2 -1
- data/config/locales/de.yml +2 -0
- data/config/locales/en.yml +2 -0
- data/config/locales/es.yml +2 -0
- data/config/locales/fr.yml +2 -0
- data/config/locales/it.yml +2 -0
- data/config/locales/pl.yml +2 -0
- data/config/locales/pt-BR.yml +2 -0
- data/config/locales/ru.yml +2 -0
- data/config/locales/zh-CN.yml +2 -0
- data/db/migrate/20160329231848_create_thredded.rb +37 -23
- data/db/upgrade_migrations/{20170811090735_upgrade_thredded_v0_13_to_v_014.rb → 20170811090735_upgrade_thredded_v0_13_to_v0_14.rb} +0 -0
- data/db/upgrade_migrations/20180110200009_upgrade_thredded_v0_14_to_v0_15.rb +91 -0
- data/lib/generators/thredded/install/templates/initializer.rb +16 -7
- data/lib/thredded.rb +143 -125
- data/lib/thredded/arel_compat.rb +57 -0
- data/lib/thredded/base_migration.rb +10 -0
- data/lib/thredded/collection_to_strings_with_cache_renderer.rb +35 -9
- data/lib/thredded/content_formatter.rb +27 -18
- data/lib/thredded/database_seeder.rb +218 -64
- data/lib/thredded/email_transformer.rb +5 -2
- data/lib/thredded/email_transformer/spoiler.rb +25 -0
- data/lib/thredded/formatting_demo_content.rb +12 -0
- data/lib/thredded/html_pipeline/onebox_filter.rb +3 -38
- data/lib/thredded/html_pipeline/spoiler_tag_filter.rb +128 -0
- data/lib/thredded/html_pipeline/utils.rb +47 -0
- data/lib/thredded/rails_lt_5_2_arel_case_node.rb +119 -0
- data/lib/thredded/version.rb +1 -1
- metadata +17 -21
@@ -2,7 +2,7 @@
|
|
2
2
|
<%= render 'thredded/shared/header' %>
|
3
3
|
<%= render 'thredded/shared/flash_messages' %>
|
4
4
|
<%= yield :thredded_page_content %>
|
5
|
-
<%= render 'thredded/shared/currently_online' %>
|
5
|
+
<%= render 'thredded/shared/currently_online' if Thredded.currently_online_enabled %>
|
6
6
|
<%- end %>
|
7
7
|
|
8
8
|
<%# If thredded JS is loaded via an [async] script, the JS may
|
@@ -10,6 +10,7 @@
|
|
10
10
|
<li class="title">
|
11
11
|
<%= form.label :title, t('thredded.topics.form.title_label') %>
|
12
12
|
<%= form.text_field :title, placeholder: placeholder, required: true %>
|
13
|
+
<%= render 'thredded/shared/field_errors', messages: form.object.errors[:title] if form.object.errors.include?(:title) %>
|
13
14
|
</li>
|
14
15
|
|
15
16
|
<% if form.object.category_options.any? %>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<ul class="thredded--navigation-breadcrumbs">
|
5
5
|
<li><%= link_to t('thredded.nav.all_messageboards'), messageboards_path %></li>
|
6
6
|
<li><%= link_to messageboard.name, @edit_topic.messageboard_path %></li>
|
7
|
-
<li><%= link_to @edit_topic.title, @edit_topic.path %></li>
|
7
|
+
<li><%= link_to @edit_topic.title_was || @edit_topic.title, @edit_topic.path %></li>
|
8
8
|
<li><%= link_to t('thredded.nav.edit_topic'), @edit_topic.edit_path %></li>
|
9
9
|
</ul>
|
10
10
|
<% end %>
|
@@ -22,6 +22,7 @@
|
|
22
22
|
placeholder: t('thredded.topics.form.title_placeholder'),
|
23
23
|
autofocus: true,
|
24
24
|
required: true %>
|
25
|
+
<%= render 'thredded/shared/field_errors', messages: form.object.errors[:title] if form.object.errors.include?(:title) %>
|
25
26
|
</li>
|
26
27
|
|
27
28
|
<% if form.object.category_options.any? %>
|
data/config/locales/de.yml
CHANGED
@@ -132,6 +132,8 @@ de:
|
|
132
132
|
update_btn_submitting: :thredded.form.update_btn_submitting
|
133
133
|
pending_moderation_notice: Dein Beitrag wird veröffentlicht, sobald ein Moderator ihn angeschaut hat.
|
134
134
|
quote_btn: Zitat
|
135
|
+
spoiler_summary: Spoiler - klicken um zu zeigen.
|
136
|
+
spoiler_summary_for_email: 'Spoiler - Wählen Sie den Inhalt unten, um zu sehen:'
|
135
137
|
preferences:
|
136
138
|
edit:
|
137
139
|
page_title: :thredded.nav.settings
|
data/config/locales/en.yml
CHANGED
@@ -131,6 +131,8 @@ en:
|
|
131
131
|
update_btn_submitting: :thredded.form.update_btn_submitting
|
132
132
|
pending_moderation_notice: Your post will be published when it has been reviewed by a moderator.
|
133
133
|
quote_btn: Quote
|
134
|
+
spoiler_summary: Spoiler - click to show.
|
135
|
+
spoiler_summary_for_email: 'Spoiler - select the contents below to see:'
|
134
136
|
preferences:
|
135
137
|
edit:
|
136
138
|
page_title: :thredded.nav.settings
|
data/config/locales/es.yml
CHANGED
@@ -133,6 +133,8 @@ es:
|
|
133
133
|
update_btn_submitting: :thredded.form.update_btn_submitting
|
134
134
|
pending_moderation_notice: Tu post será publicado cuando haya sido revisado por un moderador.
|
135
135
|
quote_btn: Citar
|
136
|
+
spoiler_summary: 'Spoiler: haz clic para mostrar.'
|
137
|
+
spoiler_summary_for_email: 'Spoiler: selecciona el contenido a continuación para ver:'
|
136
138
|
preferences:
|
137
139
|
edit:
|
138
140
|
page_title: :thredded.nav.settings
|
data/config/locales/fr.yml
CHANGED
@@ -131,6 +131,8 @@ fr:
|
|
131
131
|
update_btn_submitting: :thredded.form.update_btn_submitting
|
132
132
|
pending_moderation_notice: Votre commentaire sera publié dès qu'il aura été validé par un modérateur.
|
133
133
|
quote_btn: Citer
|
134
|
+
spoiler_summary: Spoiler - cliquez pour afficher.
|
135
|
+
spoiler_summary_for_email: 'Spoiler - sélectionnez le contenu ci-dessous pour voir:'
|
134
136
|
preferences:
|
135
137
|
edit:
|
136
138
|
page_title: :thredded.nav.settings
|
data/config/locales/it.yml
CHANGED
@@ -131,6 +131,8 @@ it:
|
|
131
131
|
update_btn_submitting: :thredded.form.update_btn_submitting
|
132
132
|
pending_moderation_notice: Il tuo messaggio sarà pubblicato dopo essere stato controllato da un moderatore.
|
133
133
|
quote_btn: Citazione
|
134
|
+
spoiler_summary: Spoiler - clicca per mostrare.
|
135
|
+
spoiler_summary_for_email: 'Spoiler: seleziona i contenuti sotto per vedere:'
|
134
136
|
preferences:
|
135
137
|
edit:
|
136
138
|
page_title: :thredded.nav.settings
|
data/config/locales/pl.yml
CHANGED
@@ -131,6 +131,8 @@ pl:
|
|
131
131
|
update_btn_submitting: :thredded.form.update_btn_submitting
|
132
132
|
pending_moderation_notice: Twój post zostanie zamieszczony po zweryfikowaniu go przez moderatora.
|
133
133
|
quote_btn: Zacytować
|
134
|
+
spoiler_summary: Spoiler - kliknij, aby pokazać.
|
135
|
+
spoiler_summary_for_email: 'Spoiler - wybierz zawartość poniżej, aby zobaczyć:'
|
134
136
|
preferences:
|
135
137
|
edit:
|
136
138
|
page_title: :thredded.nav.settings
|
data/config/locales/pt-BR.yml
CHANGED
@@ -133,6 +133,8 @@ pt-BR:
|
|
133
133
|
update_btn_submitting: :thredded.form.update_btn_submitting
|
134
134
|
pending_moderation_notice: O envio da mensagem será publicada quando foi revisado por um moderador.
|
135
135
|
quote_btn: Citar
|
136
|
+
spoiler_summary: Spoiler - clique para mostrar.
|
137
|
+
spoiler_summary_for_email: 'Spoiler - selecione o conteúdo abaixo para ver:'
|
136
138
|
preferences:
|
137
139
|
edit:
|
138
140
|
page_title: :thredded.nav.settings
|
data/config/locales/ru.yml
CHANGED
@@ -129,6 +129,8 @@ ru:
|
|
129
129
|
update_btn_submitting: :thredded.form.update_btn_submitting
|
130
130
|
pending_moderation_notice: Ваш пост будет опубликован, когда будет одобрен модератором.
|
131
131
|
quote_btn: Цитировать
|
132
|
+
spoiler_summary: Спойлер - нажмите, чтобы показать.
|
133
|
+
spoiler_summary_for_email: 'Спойлер - выделите содержимое ниже, чтобы увидеть:'
|
132
134
|
preferences:
|
133
135
|
edit:
|
134
136
|
page_title: :thredded.nav.settings
|
data/config/locales/zh-CN.yml
CHANGED
@@ -126,6 +126,8 @@ zh-CN:
|
|
126
126
|
update_btn_submitting: :thredded.form.update_btn_submitting
|
127
127
|
pending_moderation_notice: 你的回复将在审核之后公开发表
|
128
128
|
quote_btn: 引用
|
129
|
+
spoiler_summary: 剧透 - 点击显示。
|
130
|
+
spoiler_summary_for_email: 扰流板 - 选择下面的内容来查看:
|
129
131
|
preferences:
|
130
132
|
edit:
|
131
133
|
page_title: :thredded.nav.settings
|
@@ -25,18 +25,23 @@ class CreateThredded < Thredded::BaseMigration
|
|
25
25
|
|
26
26
|
create_table :thredded_categories do |t|
|
27
27
|
t.references :messageboard, null: false, index: false
|
28
|
-
t.
|
29
|
-
t.
|
28
|
+
t.text :name, null: false
|
29
|
+
t.text :description
|
30
30
|
t.timestamps null: false
|
31
|
-
t.
|
32
|
-
t.index %i[messageboard_id slug],
|
31
|
+
t.text :slug, null: false
|
32
|
+
t.index %i[messageboard_id slug],
|
33
|
+
name: :index_thredded_categories_on_messageboard_id_and_slug,
|
34
|
+
unique: true,
|
35
|
+
length: { slug: max_key_length }
|
33
36
|
t.index [:messageboard_id], name: :index_thredded_categories_on_messageboard_id
|
34
37
|
end
|
35
|
-
DbTextSearch::CaseInsensitive.add_index connection, :thredded_categories, :name,
|
38
|
+
DbTextSearch::CaseInsensitive.add_index connection, :thredded_categories, :name,
|
39
|
+
name: :thredded_categories_name_ci,
|
40
|
+
**(max_key_length ? { length: max_key_length } : {})
|
36
41
|
|
37
42
|
create_table :thredded_messageboards do |t|
|
38
|
-
t.
|
39
|
-
t.
|
43
|
+
t.text :name, null: false
|
44
|
+
t.text :slug
|
40
45
|
t.text :description
|
41
46
|
t.integer :topics_count, default: 0
|
42
47
|
t.integer :posts_count, default: 0
|
@@ -46,14 +51,16 @@ class CreateThredded < Thredded::BaseMigration
|
|
46
51
|
t.timestamps null: false
|
47
52
|
t.boolean :locked, null: false, default: false
|
48
53
|
t.index [:messageboard_group_id], name: :index_thredded_messageboards_on_messageboard_group_id
|
49
|
-
t.index [:slug],
|
54
|
+
t.index [:slug],
|
55
|
+
name: :index_thredded_messageboards_on_slug,
|
56
|
+
unique: true,
|
57
|
+
length: { slug: max_key_length }
|
50
58
|
end
|
51
59
|
|
52
60
|
create_table :thredded_posts do |t|
|
53
61
|
t.references :user, type: user_id_type, index: false
|
54
62
|
t.text :content, limit: 65_535
|
55
|
-
t.string :
|
56
|
-
t.string :source, limit: 255, default: 'web'
|
63
|
+
t.string :source, limit: 191, default: 'web'
|
57
64
|
t.references :postable, null: false, index: false
|
58
65
|
t.references :messageboard, null: false, index: false
|
59
66
|
t.integer :moderation_state, null: false
|
@@ -63,7 +70,7 @@ class CreateThredded < Thredded::BaseMigration
|
|
63
70
|
name: :index_thredded_posts_for_display
|
64
71
|
t.index [:messageboard_id], name: :index_thredded_posts_on_messageboard_id
|
65
72
|
t.index [:postable_id], name: :index_thredded_posts_on_postable_id
|
66
|
-
t.index [
|
73
|
+
t.index %i[postable_id created_at], name: :index_thredded_posts_on_postable_id_and_created_at
|
67
74
|
t.index [:user_id], name: :index_thredded_posts_on_user_id
|
68
75
|
end
|
69
76
|
DbTextSearch::FullText.add_index connection, :thredded_posts, :content, name: :thredded_posts_content_fts
|
@@ -72,21 +79,25 @@ class CreateThredded < Thredded::BaseMigration
|
|
72
79
|
t.references :user, type: user_id_type, index: false
|
73
80
|
t.text :content, limit: 65_535
|
74
81
|
t.references :postable, null: false, index: false
|
75
|
-
t.string :ip, limit: 255
|
76
82
|
t.timestamps null: false
|
83
|
+
t.index %i[postable_id created_at], name: :index_thredded_private_posts_on_postable_id_and_created_at
|
77
84
|
end
|
78
85
|
|
79
86
|
create_table :thredded_private_topics do |t|
|
80
87
|
t.references :user, type: user_id_type, index: false
|
81
88
|
t.references :last_user, index: false
|
82
|
-
t.
|
83
|
-
t.
|
89
|
+
t.text :title, null: false
|
90
|
+
t.text :slug, null: false
|
84
91
|
t.integer :posts_count, default: 0
|
85
|
-
t.string :hash_id, limit:
|
92
|
+
t.string :hash_id, limit: 20, null: false
|
86
93
|
t.datetime :last_post_at
|
87
94
|
t.timestamps null: false
|
95
|
+
t.index [:last_post_at], name: :index_thredded_private_topics_on_last_post_at
|
88
96
|
t.index [:hash_id], name: :index_thredded_private_topics_on_hash_id
|
89
|
-
t.index [:slug],
|
97
|
+
t.index [:slug],
|
98
|
+
name: :index_thredded_private_topics_on_slug,
|
99
|
+
unique: true,
|
100
|
+
length: { slug: max_key_length }
|
90
101
|
end
|
91
102
|
|
92
103
|
create_table :thredded_private_users do |t|
|
@@ -107,22 +118,25 @@ class CreateThredded < Thredded::BaseMigration
|
|
107
118
|
create_table :thredded_topics do |t|
|
108
119
|
t.references :user, type: user_id_type, index: false
|
109
120
|
t.references :last_user, index: false
|
110
|
-
t.
|
111
|
-
t.
|
121
|
+
t.text :title, null: false
|
122
|
+
t.text :slug, null: false
|
112
123
|
t.references :messageboard, null: false, index: false
|
113
124
|
t.integer :posts_count, default: 0, null: false
|
114
125
|
t.boolean :sticky, default: false, null: false
|
115
126
|
t.boolean :locked, default: false, null: false
|
116
|
-
t.string :hash_id, limit:
|
117
|
-
t.string :type, limit: 191
|
127
|
+
t.string :hash_id, limit: 20, null: false
|
118
128
|
t.integer :moderation_state, null: false
|
119
129
|
t.datetime :last_post_at
|
120
130
|
t.timestamps null: false
|
121
131
|
t.index %i[moderation_state sticky updated_at],
|
122
132
|
order: { sticky: :desc, updated_at: :desc },
|
123
133
|
name: :index_thredded_topics_for_display
|
134
|
+
t.index [:last_post_at], name: :index_thredded_topics_on_last_post_at
|
124
135
|
t.index [:hash_id], name: :index_thredded_topics_on_hash_id
|
125
|
-
t.index [:slug],
|
136
|
+
t.index [:slug],
|
137
|
+
name: :index_thredded_topics_on_slug,
|
138
|
+
unique: true,
|
139
|
+
length: { slug: max_key_length }
|
126
140
|
t.index [:messageboard_id], name: :index_thredded_topics_on_messageboard_id
|
127
141
|
t.index [:user_id], name: :index_thredded_topics_on_user_id
|
128
142
|
end
|
@@ -149,7 +163,8 @@ class CreateThredded < Thredded::BaseMigration
|
|
149
163
|
t.references :thredded_messageboard, null: false, index: false
|
150
164
|
t.datetime :last_seen_at, null: false
|
151
165
|
t.index %i[thredded_messageboard_id thredded_user_detail_id],
|
152
|
-
name: :index_thredded_messageboard_users_primary
|
166
|
+
name: :index_thredded_messageboard_users_primary,
|
167
|
+
unique: true
|
153
168
|
t.index %i[thredded_messageboard_id last_seen_at],
|
154
169
|
name: :index_thredded_messageboard_users_for_recently_active
|
155
170
|
end
|
@@ -182,7 +197,6 @@ class CreateThredded < Thredded::BaseMigration
|
|
182
197
|
create_table table_name do |t|
|
183
198
|
t.references :user, type: user_id_type, null: false, index: false
|
184
199
|
t.references :postable, null: false, index: false
|
185
|
-
t.integer :page, default: 1, null: false
|
186
200
|
t.timestamp :read_at, null: false
|
187
201
|
t.index %i[user_id postable_id], name: :"#{table_name}_user_postable", unique: true
|
188
202
|
end
|
File without changes
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thredded/base_migration'
|
4
|
+
|
5
|
+
class UpgradeThreddedV014ToV015 < Thredded::BaseMigration
|
6
|
+
def change # rubocop:disable Metrics/MethodLength
|
7
|
+
# Work around race condition on last_seen_at update
|
8
|
+
# https://github.com/thredded/thredded/pull/674
|
9
|
+
remove_index :thredded_messageboard_users,
|
10
|
+
name: :index_thredded_messageboard_users_primary
|
11
|
+
add_index :thredded_messageboard_users,
|
12
|
+
%i[thredded_messageboard_id thredded_user_detail_id],
|
13
|
+
name: :index_thredded_messageboard_users_primary,
|
14
|
+
unique: true
|
15
|
+
|
16
|
+
# Remove database string length limits.
|
17
|
+
# https://github.com/thredded/thredded/pull/703
|
18
|
+
remove_index :thredded_categories, name: :thredded_categories_name_ci
|
19
|
+
remove_string_limit :thredded_categories, :name
|
20
|
+
DbTextSearch::CaseInsensitive.add_index connection, :thredded_categories, :name,
|
21
|
+
name: :thredded_categories_name_ci,
|
22
|
+
**(max_key_length ? { length: max_key_length } : {})
|
23
|
+
remove_string_limit :thredded_categories, :description
|
24
|
+
remove_string_limit :thredded_categories, :slug,
|
25
|
+
indices: [
|
26
|
+
[%i[messageboard_id slug],
|
27
|
+
name: :index_thredded_categories_on_messageboard_id_and_slug,
|
28
|
+
unique: true,
|
29
|
+
length: { slug: max_key_length }]
|
30
|
+
]
|
31
|
+
|
32
|
+
remove_string_limit :thredded_messageboards, :name
|
33
|
+
remove_string_limit :thredded_messageboards, :slug,
|
34
|
+
indices: [
|
35
|
+
[%i[slug],
|
36
|
+
name: :index_thredded_messageboards_on_slug,
|
37
|
+
unique: true,
|
38
|
+
length: { slug: max_key_length }]
|
39
|
+
]
|
40
|
+
|
41
|
+
change_column :thredded_posts, :ip, :string, limit: 45
|
42
|
+
change_column :thredded_posts, :source, :string, limit: 191
|
43
|
+
|
44
|
+
remove_string_limit :thredded_private_topics, :title
|
45
|
+
remove_string_limit :thredded_private_topics, :slug,
|
46
|
+
indices: [
|
47
|
+
[%i[slug],
|
48
|
+
name: :index_thredded_private_topics_on_slug,
|
49
|
+
unique: true,
|
50
|
+
length: { slug: max_key_length }]
|
51
|
+
]
|
52
|
+
change_column :thredded_private_topics, :hash_id, :string, limit: 20
|
53
|
+
|
54
|
+
remove_string_limit :thredded_topics, :title
|
55
|
+
remove_string_limit :thredded_topics, :slug,
|
56
|
+
indices: [
|
57
|
+
[%i[slug],
|
58
|
+
name: :index_thredded_topics_on_slug,
|
59
|
+
unique: true,
|
60
|
+
length: { slug: max_key_length }]
|
61
|
+
]
|
62
|
+
change_column :thredded_topics, :hash_id, :string, limit: 20
|
63
|
+
remove_column :thredded_topics, :type
|
64
|
+
|
65
|
+
# Remove IP tracking column from posts
|
66
|
+
# https://github.com/thredded/thredded/pull/705
|
67
|
+
remove_column :thredded_posts, :ip
|
68
|
+
remove_column :thredded_private_posts, :ip
|
69
|
+
|
70
|
+
# Jump to first unread post
|
71
|
+
# https://github.com/thredded/thredded/pull/695
|
72
|
+
remove_column :thredded_user_topic_read_states, :page
|
73
|
+
remove_column :thredded_user_private_topic_read_states, :page
|
74
|
+
add_index :thredded_topics, [:last_post_at], name: :index_thredded_topics_on_last_post_at
|
75
|
+
add_index :thredded_private_topics, [:last_post_at], name: :index_thredded_private_topics_on_last_post_at
|
76
|
+
add_index :thredded_posts, %i[postable_id created_at], name: :index_thredded_posts_on_postable_id_and_created_at
|
77
|
+
add_index :thredded_private_posts, %i[postable_id created_at],
|
78
|
+
name: :index_thredded_private_posts_on_postable_id_and_created_at
|
79
|
+
|
80
|
+
# Cleanup
|
81
|
+
remove_index :thredded_posts, name: :index_thredded_posts_on_postable_id_and_created_at
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def remove_string_limit(table, column, type: :text, indices: [])
|
87
|
+
indices.each { |(_, options)| remove_index table, name: options[:name] }
|
88
|
+
change_column table, column, type, limit: nil
|
89
|
+
indices.each { |args| add_index table, *args }
|
90
|
+
end
|
91
|
+
end
|
@@ -51,13 +51,10 @@ Thredded.admin_column = :admin
|
|
51
51
|
# Whether posts and topics pending moderation are visible to regular users.
|
52
52
|
Thredded.content_visible_while_pending_moderation = true
|
53
53
|
|
54
|
-
# Whether users that are following a topic are listed on topic page.
|
55
|
-
Thredded.show_topic_followers = false
|
56
|
-
|
57
54
|
# This model can be customized further by overriding a handful of methods on the User model.
|
58
55
|
# For more information, see app/models/thredded/user_extender.rb.
|
59
56
|
|
60
|
-
# ==>
|
57
|
+
# ==> UI configuration
|
61
58
|
|
62
59
|
# How to calculate the position of messageboards in a list:
|
63
60
|
# :position (default) set the position manually (new messageboards go to the bottom, by creation timestamp)
|
@@ -65,6 +62,18 @@ Thredded.show_topic_followers = false
|
|
65
62
|
# :topics_count_desc most topics first
|
66
63
|
Thredded.messageboards_order = :position
|
67
64
|
|
65
|
+
# Whether users that are following a topic are listed on the topic page.
|
66
|
+
Thredded.show_topic_followers = false
|
67
|
+
|
68
|
+
# Whether the list of users who are currently online is displayed.
|
69
|
+
Thredded.currently_online_enabled = true
|
70
|
+
|
71
|
+
# Whether private messaging functionality is enabled.
|
72
|
+
Thredded.private_messaging_enabled = true
|
73
|
+
|
74
|
+
# The layout for rendering Thredded views.
|
75
|
+
Thredded.layout = 'thredded/application'
|
76
|
+
|
68
77
|
# ==> Email Configuration
|
69
78
|
# Email "From:" field will use the following
|
70
79
|
# Thredded.email_from = 'no-reply@example.com'
|
@@ -75,9 +84,9 @@ Thredded.messageboards_order = :position
|
|
75
84
|
# The parent mailer for all Thredded mailers
|
76
85
|
# Thredded.parent_mailer = 'ActionMailer::Base'
|
77
86
|
|
78
|
-
# ==>
|
79
|
-
#
|
80
|
-
Thredded.
|
87
|
+
# ==> Model configuration
|
88
|
+
# The range of valid topic title lengths. Default:
|
89
|
+
# Thredded.topic_title_length_range = (1..200)
|
81
90
|
|
82
91
|
# ==> URLs
|
83
92
|
# How Thredded generates URL slugs from text.
|
data/lib/thredded.rb
CHANGED
@@ -16,11 +16,13 @@ require 'inline_svg'
|
|
16
16
|
# Require these explictly to make sure they are not reloaded.
|
17
17
|
# This allows for configuring them by accessing class methods in the initializer.
|
18
18
|
require 'thredded/formatting_demo_content'
|
19
|
+
require 'thredded/html_pipeline/utils'
|
19
20
|
require 'thredded/html_pipeline/at_mention_filter'
|
20
21
|
require 'thredded/html_pipeline/autolink_filter'
|
21
22
|
require 'thredded/html_pipeline/kramdown_filter'
|
22
23
|
require 'thredded/html_pipeline/onebox_filter'
|
23
24
|
require 'thredded/html_pipeline/wrap_iframes_filter'
|
25
|
+
require 'thredded/html_pipeline/spoiler_tag_filter'
|
24
26
|
|
25
27
|
# Asset compilation
|
26
28
|
require 'autoprefixer-rails'
|
@@ -39,152 +41,168 @@ require 'thredded/content_formatter'
|
|
39
41
|
require 'thredded/email_transformer'
|
40
42
|
require 'thredded/base_notifier'
|
41
43
|
|
44
|
+
require 'thredded/arel_compat'
|
42
45
|
require 'thredded/collection_to_strings_with_cache_renderer'
|
43
46
|
|
44
47
|
module Thredded
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
:user_path
|
57
|
-
|
58
|
-
# @return [Symbol] The name of the method used by Thredded controllers and views to fetch the currently signed-in user
|
59
|
-
mattr_accessor :current_user_method
|
60
|
-
|
61
|
-
# @return [Symbol] The name of the moderator flag column on the users table for the default permissions model
|
62
|
-
mattr_accessor :moderator_column
|
63
|
-
|
64
|
-
# @return [Symbol] The name of the admin flag column on the users table for the default permissions model
|
65
|
-
mattr_accessor :admin_column
|
66
|
-
|
67
|
-
# @return [Boolean] Whether posts that are pending moderation are visible to regular users.
|
68
|
-
mattr_accessor :content_visible_while_pending_moderation
|
69
|
-
|
70
|
-
# @return [Array] The notifiers, by default just the EmailNotifier
|
71
|
-
mattr_accessor :notifiers
|
72
|
-
|
73
|
-
# @return [Boolean] Whether users that are following a topic are listed on topic page.
|
74
|
-
mattr_accessor :show_topic_followers
|
75
|
-
|
76
|
-
# @return [Symbol] The name of the method used by Thredded to display users
|
77
|
-
mattr_accessor :user_display_name_method
|
78
|
-
|
79
|
-
# @return [String] The name of the parent mailer class for Thredded mailers.
|
80
|
-
mattr_accessor :parent_mailer
|
81
|
-
self.parent_mailer = 'ActionMailer::Base'
|
48
|
+
class << self
|
49
|
+
attr_accessor \
|
50
|
+
:autocomplete_min_length,
|
51
|
+
:active_user_threshold,
|
52
|
+
:avatar_url,
|
53
|
+
:email_from,
|
54
|
+
:email_outgoing_prefix,
|
55
|
+
:layout,
|
56
|
+
:messageboards_order,
|
57
|
+
:routes_id_constraint,
|
58
|
+
:user_name_column
|
82
59
|
|
83
|
-
|
84
|
-
|
85
|
-
self.slugifier = ->(input) { input.parameterize }
|
60
|
+
# A lambda that generates a URL path to the user page for the given user.
|
61
|
+
attr_writer :user_path
|
86
62
|
|
87
|
-
|
88
|
-
|
89
|
-
self.auto_follow_when_creating_topic = true
|
63
|
+
# @return [Symbol] The name of the method used by Thredded controllers and views to get the currently signed-in user
|
64
|
+
attr_accessor :current_user_method
|
90
65
|
|
91
|
-
|
92
|
-
|
93
|
-
self.auto_follow_when_posting_in_topic = true
|
66
|
+
# @return [Symbol] The name of the moderator flag column on the users table for the default permissions model
|
67
|
+
attr_accessor :moderator_column
|
94
68
|
|
95
|
-
|
96
|
-
|
69
|
+
# @return [Symbol] The name of the admin flag column on the users table for the default permissions model
|
70
|
+
attr_accessor :admin_column
|
97
71
|
|
98
|
-
|
99
|
-
|
100
|
-
self.avatar_url = ->(user) { Gravatar.src(user.email, 156, 'mm') }
|
101
|
-
self.layout = 'thredded/application'
|
102
|
-
self.moderator_column = :admin
|
103
|
-
self.user_name_column = :name
|
104
|
-
self.content_visible_while_pending_moderation = true
|
105
|
-
self.show_topic_followers = false
|
106
|
-
self.messageboards_order = :position
|
107
|
-
self.autocomplete_min_length = 2
|
108
|
-
self.routes_id_constraint = /[1-9]\d*/
|
72
|
+
# @return [Boolean] Whether posts that are pending moderation are visible to regular users.
|
73
|
+
attr_accessor :content_visible_while_pending_moderation
|
109
74
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
75
|
+
# @return [Boolean] Whether users that are following a topic are listed on the topic page.
|
76
|
+
attr_accessor :show_topic_followers
|
77
|
+
|
78
|
+
# @return [Symbol] The name of the method used by Thredded to display users
|
79
|
+
attr_writer :user_display_name_method
|
80
|
+
|
81
|
+
# @return [String] The name of the parent mailer class for Thredded mailers.
|
82
|
+
attr_accessor :parent_mailer
|
83
|
+
|
84
|
+
# @return [Proc] The proc that Thredded uses to generate URL slugs from text.
|
85
|
+
attr_accessor :slugifier
|
86
|
+
|
87
|
+
# @return [Boolean] Whether the user should get subscribed to a new topic they've created.
|
88
|
+
attr_accessor :auto_follow_when_creating_topic
|
89
|
+
|
90
|
+
# @return [Boolean] Whether the user should get subscribed to a topic after posting in it.
|
91
|
+
attr_accessor :auto_follow_when_posting_in_topic
|
92
|
+
|
93
|
+
# @return [String] The name of the user class
|
94
|
+
attr_reader :user_class_name
|
95
|
+
|
96
|
+
# @return [Range<Integer>] The range of valid topic title lengths.
|
97
|
+
attr_accessor :topic_title_length_range
|
98
|
+
|
99
|
+
# @return [Boolean] Whether the list of users who are currently online is displayed.
|
100
|
+
attr_accessor :currently_online_enabled
|
101
|
+
|
102
|
+
# @return [Boolean] Whether the private messaging functionality is enabled.
|
103
|
+
attr_accessor :private_messaging_enabled
|
104
|
+
|
105
|
+
# @return [Thredded::AllViewHooks] View hooks configuration.
|
106
|
+
def view_hooks
|
107
|
+
instance = Thredded::AllViewHooks.instance
|
108
|
+
unless instance
|
109
|
+
fail '`Thredded.view_hooks` must be configured in a `Rails.application.config.to_prepare` block!'
|
110
|
+
end
|
111
|
+
instance
|
115
112
|
end
|
116
|
-
instance
|
117
|
-
end
|
118
113
|
|
119
|
-
|
120
|
-
|
121
|
-
|
114
|
+
# @return [Array] The notifiers, by default just the EmailNotifier
|
115
|
+
def notifiers
|
116
|
+
@notifiers ||= [Thredded::EmailNotifier.new]
|
117
|
+
end
|
122
118
|
|
123
|
-
|
124
|
-
notifiers
|
125
|
-
|
126
|
-
|
119
|
+
# @param [Array] notifiers
|
120
|
+
def notifiers=(notifiers)
|
121
|
+
notifiers.each { |notifier| Thredded::BaseNotifier.validate_notifier(notifier) }
|
122
|
+
@notifiers = notifiers
|
123
|
+
end
|
127
124
|
|
128
|
-
|
129
|
-
|
130
|
-
|
125
|
+
# @return [Symbol] The name of the method used by Thredded to display users
|
126
|
+
def user_display_name_method
|
127
|
+
@user_display_name_method || user_name_column
|
128
|
+
end
|
131
129
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
130
|
+
# @param value [:position, :topics_count_desc, :last_post_at_desc]
|
131
|
+
def messageboards_order=(value)
|
132
|
+
case value
|
133
|
+
when :position, :topics_count_desc, :last_post_at_desc
|
134
|
+
@messageboards_order = value
|
135
|
+
else
|
136
|
+
fail ArgumentError, "Unexpected value for Thredded.messageboards_order: #{value}"
|
137
|
+
end
|
139
138
|
end
|
140
|
-
end
|
141
139
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
140
|
+
# @param user_class_name [String]
|
141
|
+
def user_class=(user_class_name)
|
142
|
+
unless user_class_name.is_a?(String)
|
143
|
+
fail "Thredded.user_class must be set to a String, got #{user_class_name.inspect}"
|
144
|
+
end
|
145
|
+
@user_class_name = user_class_name
|
146
146
|
end
|
147
|
-
@@user_class_name = user_class_name # rubocop:disable Style/ClassVars
|
148
|
-
end
|
149
147
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
148
|
+
# @return [Class<Thredded::UserExtender>] the user class from the host application.
|
149
|
+
def user_class
|
150
|
+
# This is nil before the initializer is installed.
|
151
|
+
return nil if @user_class_name.nil?
|
152
|
+
@user_class_name.constantize
|
153
|
+
end
|
156
154
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
155
|
+
# @param view_context [Object] context to execute the lambda in.
|
156
|
+
# @param user [Thredded.user_class]
|
157
|
+
# @return [String] path to the user evaluated in the specified context.
|
158
|
+
def user_path(view_context, user)
|
159
|
+
view_context.instance_exec(user, &@user_path)
|
160
|
+
end
|
163
161
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
162
|
+
# Whether the layout is a thredded layout as opposed to the application layout.
|
163
|
+
def standalone_layout?
|
164
|
+
layout.is_a?(String) && layout.start_with?('thredded/')
|
165
|
+
end
|
168
166
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
167
|
+
# Returns a view for the given posts' scope, applying read permission filters to the scope.
|
168
|
+
# Can be used in main_app, e.g. for showing the recent user posts on the profile page.
|
169
|
+
#
|
170
|
+
# @param scope [ActiveRecord::Relation<Thredded::Post>] the posts scope for which to return the view.
|
171
|
+
# @param current_user [Thredded.user_class, nil] the user viewing the posts.
|
172
|
+
# @return [PostsPageView]
|
173
|
+
def posts_page_view(scope:, current_user:)
|
174
|
+
current_user ||= Thredded::NullUser.new
|
175
|
+
Thredded::PostsPageView.new(
|
176
|
+
current_user,
|
177
|
+
Pundit.policy_scope!(current_user, scope)
|
178
|
+
.where(messageboard_id: Pundit.policy_scope!(current_user, Thredded::Messageboard.all).pluck(:id))
|
179
|
+
.includes(:postable)
|
180
|
+
)
|
181
|
+
end
|
184
182
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
183
|
+
# @api private
|
184
|
+
def rails_gte_51?
|
185
|
+
@rails_gte_51 = (Rails.gem_version >= Gem::Version.new('5.1.0')) if @rails_gte_51.nil?
|
186
|
+
@rails_gte_51
|
187
|
+
end
|
189
188
|
end
|
189
|
+
|
190
|
+
self.active_user_threshold = 5.minutes
|
191
|
+
self.admin_column = :admin
|
192
|
+
self.auto_follow_when_creating_topic = true
|
193
|
+
self.auto_follow_when_posting_in_topic = true
|
194
|
+
self.autocomplete_min_length = 2
|
195
|
+
self.avatar_url = ->(user) { Gravatar.src(user.email, 156, 'mm') }
|
196
|
+
self.content_visible_while_pending_moderation = true
|
197
|
+
self.layout = 'thredded/application'
|
198
|
+
self.messageboards_order = :position
|
199
|
+
self.moderator_column = :admin
|
200
|
+
self.parent_mailer = 'ActionMailer::Base'
|
201
|
+
self.routes_id_constraint = /[1-9]\d*/
|
202
|
+
self.show_topic_followers = false
|
203
|
+
self.slugifier = ->(input) { input.parameterize }
|
204
|
+
self.topic_title_length_range = (1..200)
|
205
|
+
self.user_name_column = :name
|
206
|
+
self.private_messaging_enabled = true
|
207
|
+
self.currently_online_enabled = true
|
190
208
|
end
|