thredded 0.14.4 → 0.15.1
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 +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
|