thredded 0.16.16 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +19 -7
- data/app/assets/javascripts/thredded/components/preview_area.es6 +3 -1
- data/app/controllers/concerns/thredded/render_preview.rb +6 -0
- data/app/controllers/thredded/application_controller.rb +5 -10
- data/app/controllers/thredded/topics_controller.rb +0 -6
- data/app/helpers/thredded/application_helper.rb +1 -1
- data/app/helpers/thredded/urls_helper.rb +1 -1
- data/app/models/concerns/thredded/post_common.rb +5 -4
- data/app/models/concerns/thredded/topic_common.rb +1 -1
- data/app/models/concerns/thredded/user_topic_read_state_common.rb +5 -5
- data/app/models/thredded/messageboard.rb +3 -4
- data/app/models/thredded/notifications_for_followed_topics.rb +1 -1
- data/app/models/thredded/post.rb +3 -2
- data/app/models/thredded/post_moderation_record.rb +8 -9
- data/app/models/thredded/private_post.rb +2 -2
- data/app/models/thredded/private_topic.rb +4 -2
- data/app/models/thredded/topic.rb +2 -2
- data/app/models/thredded/user_detail.rb +1 -1
- data/app/models/thredded/user_extender.rb +1 -1
- data/app/view_models/thredded/posts_page_view.rb +10 -9
- data/app/view_models/thredded/private_topics_page_view.rb +10 -6
- data/app/view_models/thredded/topic_posts_page_view.rb +16 -3
- data/app/view_models/thredded/topics_page_view.rb +9 -6
- data/app/views/layouts/thredded/application.html.erb +2 -2
- data/app/views/thredded/messageboards/_form.html.erb +3 -3
- data/app/views/thredded/posts_common/_content.html.erb +1 -1
- data/app/views/thredded/posts_common/actions/_quote.html.erb +1 -1
- data/app/views/thredded/shared/_page.html.erb +1 -1
- data/app/views/thredded/shared/nav/_standalone.html.erb +2 -2
- data/bin/create_migration_fixture +23 -0
- data/config/i18n-tasks.yml +5 -0
- data/config/locales/de.yml +2 -0
- data/config/locales/en.yml +3 -1
- data/config/locales/es.yml +2 -0
- data/config/locales/fr.yml +2 -0
- data/config/locales/it.yml +4 -2
- 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/upgrade_migrations/20180110200009_upgrade_thredded_v0_14_to_v0_15.rb +1 -1
- data/lib/generators/thredded/install/templates/initializer.rb +2 -2
- data/lib/thredded/arel_compat.rb +0 -41
- data/lib/thredded/base_migration.rb +1 -1
- data/lib/thredded/collection_to_strings_with_cache_renderer.rb +33 -31
- data/lib/thredded/compat.rb +35 -0
- data/lib/thredded/database_seeder.rb +11 -4
- data/lib/thredded/db_tools.rb +2 -4
- data/lib/thredded/email_transformer.rb +2 -2
- data/lib/thredded/version.rb +1 -1
- data/lib/thredded.rb +3 -23
- metadata +39 -27
- data/bin/rubocop +0 -18
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
# edit constants in lib/thredded/db_tools.rb
|
4
|
+
# git checkout v0.x.0 -b create-0.x-migration-fixture
|
5
|
+
# bundle
|
6
|
+
|
7
|
+
DIR=$(pwd)
|
8
|
+
|
9
|
+
cd spec/dummy && DB=sqlite3 rails db:environment:set RAILS_ENV=development
|
10
|
+
cd $DIR
|
11
|
+
DB=sqlite3 rake db:drop db:create db:migrate db:miniseed_dump
|
12
|
+
|
13
|
+
cd spec/dummy && DB=postgresql rails db:environment:set RAILS_ENV=development
|
14
|
+
cd $DIR
|
15
|
+
DB=postgresql rake db:drop db:create db:migrate db:miniseed_dump
|
16
|
+
|
17
|
+
cd spec/dummy && DB=mysql2 rails db:environment:set RAILS_ENV=development
|
18
|
+
cd $DIR
|
19
|
+
DB=mysql2 rake db:drop db:create db:migrate db:miniseed_dump
|
20
|
+
|
21
|
+
git add `pwd`/spec/migration/*.dump
|
22
|
+
|
23
|
+
git commit -em "add sample data for 0.8 base for migration spec"
|
data/config/i18n-tasks.yml
CHANGED
data/config/locales/de.yml
CHANGED
data/config/locales/en.yml
CHANGED
@@ -127,6 +127,8 @@ en:
|
|
127
127
|
moderation_users: Users
|
128
128
|
private_topics: Private Messages
|
129
129
|
settings: Notification Settings
|
130
|
+
sign_in: Sign In / Register
|
131
|
+
sign_out: Sign Out
|
130
132
|
unread_topics: Unread
|
131
133
|
null_user_name: Deleted user
|
132
134
|
posts:
|
@@ -262,7 +264,7 @@ en:
|
|
262
264
|
last_active_html: Last active %{time_ago}
|
263
265
|
posted_in_topic_html: Posted in %{topic_link}
|
264
266
|
posts_count:
|
265
|
-
one: Posted
|
267
|
+
one: Posted once
|
266
268
|
other: Posted %{count} times
|
267
269
|
recent_activity: :thredded.recent_activity
|
268
270
|
send_private_message: Send private message
|
data/config/locales/es.yml
CHANGED
data/config/locales/fr.yml
CHANGED
data/config/locales/it.yml
CHANGED
@@ -127,6 +127,8 @@ it:
|
|
127
127
|
moderation_users: Utenti
|
128
128
|
private_topics: Messaggi Privati
|
129
129
|
settings: Impostazioni Notifiche
|
130
|
+
sign_in: Entra
|
131
|
+
sign_out: Esci
|
130
132
|
unread_topics: Non letto
|
131
133
|
null_user_name: Utente cancellato
|
132
134
|
posts:
|
@@ -266,13 +268,13 @@ it:
|
|
266
268
|
last_active_html: Ultima attività %{time_ago}
|
267
269
|
posted_in_topic_html: Ha scritto in %{topic_link}
|
268
270
|
posts_count:
|
269
|
-
one: Ha commentato
|
271
|
+
one: Ha commentato una volta
|
270
272
|
other: Ha commentato %{count} volte
|
271
273
|
recent_activity: :thredded.recent_activity
|
272
274
|
send_private_message: Invia un messaggio privato
|
273
275
|
started_topic_html: Ha iniziato %{topic_link}
|
274
276
|
started_topics_count:
|
275
|
-
one: Ha iniziato
|
277
|
+
one: Ha iniziato una discussione
|
276
278
|
other: Ha iniziato %{count} discussioni
|
277
279
|
user_posted_in_topic_html: "%{user_link} ha commentato in %{topic_link}"
|
278
280
|
user_since_html: Utente da %{time_ago}
|
data/config/locales/pl.yml
CHANGED
data/config/locales/pt-BR.yml
CHANGED
data/config/locales/ru.yml
CHANGED
data/config/locales/zh-CN.yml
CHANGED
@@ -86,6 +86,6 @@ class UpgradeThreddedV014ToV015 < Thredded::BaseMigration
|
|
86
86
|
def remove_string_limit(table, column, type: :text, indices: [])
|
87
87
|
indices.each { |(_, options)| remove_index table, name: options[:name] }
|
88
88
|
change_column table, column, type, limit: nil
|
89
|
-
indices.each { |
|
89
|
+
indices.each { |(columns, options)| add_index table, columns, **options }
|
90
90
|
end
|
91
91
|
end
|
@@ -29,8 +29,8 @@ Thredded.user_path = ->(user) {
|
|
29
29
|
# This method is used by Thredded controllers and views to fetch the currently signed-in user
|
30
30
|
Thredded.current_user_method = :"current_#{Thredded.user_class_name.demodulize.underscore}"
|
31
31
|
|
32
|
-
# User avatar URL.
|
33
|
-
Thredded.avatar_url = ->(user) {
|
32
|
+
# User avatar URL. rails_gravatar gem is used by default:
|
33
|
+
Thredded.avatar_url = ->(user) { RailsGravatar.src(user.email, 156, 'mm') }
|
34
34
|
|
35
35
|
# ==> Permissions Configuration
|
36
36
|
# By default, thredded uses a simple permission model, where all the users can post to all message boards,
|
data/lib/thredded/arel_compat.rb
CHANGED
@@ -1,40 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
unless Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR >= 2 || Rails::VERSION::MAJOR > 5
|
4
|
-
require 'thredded/rails_lt_5_2_arel_case_node.rb'
|
5
|
-
end
|
6
|
-
|
7
3
|
module Thredded
|
8
4
|
module ArelCompat
|
9
5
|
module_function
|
10
6
|
|
11
|
-
# On Rails >= 5, this method simply returns `relation.pluck(*columns)`.
|
12
|
-
#
|
13
|
-
# Rails 4 `pluck` does not support Arel nodes and attributes. This method does.
|
14
|
-
#
|
15
|
-
# This is an external method because monkey-patching `pluck` would
|
16
|
-
# have compatibility issues, see:
|
17
|
-
#
|
18
|
-
# https://github.com/thredded/thredded/issues/842
|
19
|
-
# https://blog.newrelic.com/engineering/ruby-agent-module-prepend-alias-method-chains/
|
20
|
-
if Rails::VERSION::MAJOR > 4
|
21
|
-
def pluck(relation, *columns)
|
22
|
-
relation.pluck(*columns)
|
23
|
-
end
|
24
|
-
else
|
25
|
-
def pluck(relation, *columns)
|
26
|
-
relation.pluck(*columns.map do |n|
|
27
|
-
if n.is_a?(Arel::Node)
|
28
|
-
Arel.sql(n.to_sql)
|
29
|
-
elsif n.is_a?(Arel::Attributes::Attribute)
|
30
|
-
n.name
|
31
|
-
else
|
32
|
-
n
|
33
|
-
end
|
34
|
-
end)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
7
|
# @param [#connection] engine
|
39
8
|
# @param [Arel::Nodes::Node] a integer node
|
40
9
|
# @param [Arel::Nodes::Node] b integer node
|
@@ -46,15 +15,5 @@ module Thredded
|
|
46
15
|
Arel::Nodes::Division.new(a, b)
|
47
16
|
end
|
48
17
|
end
|
49
|
-
|
50
|
-
if Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR >= 2 || Rails::VERSION::MAJOR > 5
|
51
|
-
def true_value(_engine)
|
52
|
-
true
|
53
|
-
end
|
54
|
-
else
|
55
|
-
def true_value(engine)
|
56
|
-
engine.connection.adapter_name =~ /sqlite|mysql|mariadb/i ? 1 : true
|
57
|
-
end
|
58
|
-
end
|
59
18
|
end
|
60
19
|
end
|
@@ -22,9 +22,11 @@ module Thredded
|
|
22
22
|
def render_collection_to_strings_with_cache( # rubocop:disable Metrics/ParameterLists
|
23
23
|
view_context, collection:, partial:, expires_in:, render_threads: self.class.render_threads, locals: {}, **opts
|
24
24
|
)
|
25
|
-
template = @lookup_context.find_template(partial, [], true, locals, {})
|
25
|
+
template = @lookup_context.find_template(partial, [], true, locals.keys, {})
|
26
26
|
collection = collection.to_a
|
27
|
-
instrument(:collection,
|
27
|
+
ActiveSupport::Notifications.instrument(:collection,
|
28
|
+
identifier: template.identifier,
|
29
|
+
count: collection.size) do |instrumentation_payload|
|
28
30
|
return [] if collection.blank?
|
29
31
|
|
30
32
|
# Result is a hash with the key represents the
|
@@ -84,48 +86,48 @@ module Thredded
|
|
84
86
|
# https://github.com/rails/rails/blob/v6.0.2.1/actionview/lib/action_view/renderer/partial_renderer.rb#L379
|
85
87
|
# https://github.com/rails/rails/blob/v6.0.2.1/actionview/lib/action_view/renderer/partial_renderer.rb#L348-L356
|
86
88
|
opts[:locals] = opts[:locals].dup if opts[:locals]
|
87
|
-
|
89
|
+
ActiveRecord::Base.connection_pool.with_connection do
|
90
|
+
render_partials_serial(view_context.dup, slice, opts)
|
91
|
+
end
|
88
92
|
end
|
89
93
|
end.flat_map(&:value)
|
90
94
|
end
|
91
95
|
end
|
92
96
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
ActionView::PartialRenderer.collection_cache
|
97
|
+
if Thredded::Compat.rails_gte_61?
|
98
|
+
# @param [Array<Object>] collection
|
99
|
+
# @param [Hash] opts
|
100
|
+
# @param view_context
|
101
|
+
# @return [Array<String>]
|
102
|
+
def render_partials_serial(view_context, collection, opts)
|
103
|
+
# https://github.com/rails/rails/pull/38594
|
104
|
+
collection.map do |object|
|
105
|
+
renderer = ActionView::ObjectRenderer.new(@lookup_context, opts)
|
106
|
+
renderer.render_object_with_partial(object, opts[:partial], view_context, nil).body
|
107
|
+
end
|
105
108
|
end
|
106
109
|
else
|
107
|
-
def
|
108
|
-
|
110
|
+
def render_partials_serial(view_context, collection, opts)
|
111
|
+
partial_renderer = ActionView::PartialRenderer.new(@lookup_context)
|
112
|
+
collection.map { |object| render_partial(partial_renderer, view_context, **opts.merge(object: object)) }
|
109
113
|
end
|
110
114
|
end
|
111
115
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
view.fragment_cache_key(key)
|
119
|
-
end
|
120
|
-
else
|
121
|
-
def combined_fragment_cache_key(view, key)
|
122
|
-
view.controller.fragment_cache_key(key)
|
123
|
-
end
|
116
|
+
def collection_cache
|
117
|
+
ActionView::PartialRenderer.collection_cache
|
118
|
+
end
|
119
|
+
|
120
|
+
def combined_fragment_cache_key(view, key)
|
121
|
+
view.combined_fragment_cache_key(key)
|
124
122
|
end
|
125
123
|
|
126
|
-
if
|
124
|
+
if Thredded::Compat.rails_gte_60?
|
127
125
|
def cache_fragment_name(view, key, virtual_path:, digest_path:)
|
128
|
-
|
126
|
+
if Thredded::Compat.rails_gte_61?
|
127
|
+
view.cache_fragment_name(key, digest_path: digest_path)
|
128
|
+
else
|
129
|
+
view.cache_fragment_name(key, virtual_path: virtual_path, digest_path: digest_path)
|
130
|
+
end
|
129
131
|
end
|
130
132
|
|
131
133
|
def digest_path_from_template(view, template)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Thredded
|
4
|
+
module Compat
|
5
|
+
class << self
|
6
|
+
# @api private
|
7
|
+
def rails_gte_60?
|
8
|
+
@rails_gte_60 = (Rails.gem_version >= Gem::Version.new('6.0.0')) if @rails_gte_60.nil?
|
9
|
+
@rails_gte_60
|
10
|
+
end
|
11
|
+
|
12
|
+
# @api private
|
13
|
+
def rails_gte_61?
|
14
|
+
@rails_gte_61 = (Rails.gem_version >= Gem::Version.new('6.1.0')) if @rails_gte_61.nil?
|
15
|
+
@rails_gte_61
|
16
|
+
end
|
17
|
+
|
18
|
+
if Rails.gem_version >= Gem::Version.new('7.0.0')
|
19
|
+
# @api private
|
20
|
+
def association_preloader(records:, associations:, scope:)
|
21
|
+
ActiveRecord::Associations::Preloader.new(
|
22
|
+
records: records, associations: associations, scope: scope
|
23
|
+
).call
|
24
|
+
end
|
25
|
+
else
|
26
|
+
# @api private
|
27
|
+
def association_preloader(records:, associations:, scope:)
|
28
|
+
ActiveRecord::Associations::Preloader.new.preload(
|
29
|
+
records, associations, scope
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'factory_bot'
|
4
|
-
require_relative '../../spec/support/
|
4
|
+
require_relative '../../spec/support/system/fake_content'
|
5
5
|
|
6
6
|
# rubocop:disable HandleExceptions
|
7
7
|
begin
|
@@ -40,6 +40,7 @@ module Thredded
|
|
40
40
|
end
|
41
41
|
|
42
42
|
include LogTime
|
43
|
+
include Thredded::ApplicationHelper
|
43
44
|
|
44
45
|
SKIP_CALLBACKS = [
|
45
46
|
[Thredded::Post, :commit, :after, :update_parent_last_user_and_time_from_last_post, on: %i[create destroy]],
|
@@ -131,7 +132,13 @@ module Thredded
|
|
131
132
|
end
|
132
133
|
|
133
134
|
def fake_post_contents
|
134
|
-
@fake_post_contents ? @fake_post_contents.sample : FakeContent.post_content
|
135
|
+
with_mentions(@fake_post_contents ? @fake_post_contents.sample : FakeContent.post_content)
|
136
|
+
end
|
137
|
+
|
138
|
+
def with_mentions(post, mentions_count: rand(3))
|
139
|
+
return post if mentions_count.zero?
|
140
|
+
|
141
|
+
([post] + Array.new(mentions_count).map { user_mention(@users.sample) }).join(' ')
|
135
142
|
end
|
136
143
|
|
137
144
|
def first_user
|
@@ -255,9 +262,9 @@ module Thredded
|
|
255
262
|
|
256
263
|
delegate :log, to: :seeder
|
257
264
|
|
258
|
-
def find_or_create(*args)
|
265
|
+
def find_or_create(*args, **kwargs)
|
259
266
|
return @stored if @stored
|
260
|
-
@stored = (find || create(*args))
|
267
|
+
@stored = (find || create(*args, **kwargs))
|
261
268
|
end
|
262
269
|
|
263
270
|
def range_of_dates_in_order(up_to: Time.zone.now, count: 1)
|
data/lib/thredded/db_tools.rb
CHANGED
@@ -10,12 +10,10 @@ module Thredded
|
|
10
10
|
verbose_was = ActiveRecord::Migration.verbose
|
11
11
|
ActiveRecord::Migration.verbose = !quiet
|
12
12
|
migrate =
|
13
|
-
if
|
13
|
+
if Thredded::Compat.rails_gte_60?
|
14
14
|
-> { ActiveRecord::MigrationContext.new(paths, ActiveRecord::SchemaMigration).migrate(nil, &filter) }
|
15
|
-
|
15
|
+
else # Rails 5.2
|
16
16
|
-> { ActiveRecord::MigrationContext.new(paths).migrate(nil, &filter) }
|
17
|
-
else
|
18
|
-
-> { ActiveRecord::Migrator.migrate(paths, &filter) }
|
19
17
|
end
|
20
18
|
if quiet
|
21
19
|
silence_active_record(&migrate)
|
@@ -17,8 +17,8 @@ module Thredded
|
|
17
17
|
end
|
18
18
|
@transformers = [Onebox, Spoiler]
|
19
19
|
|
20
|
-
# @param
|
21
|
-
def self.call(doc)
|
20
|
+
# @param dom [Nokogiri::HTML::Document]
|
21
|
+
def self.call(doc, *)
|
22
22
|
transformers.each { |transformer| transformer.call(doc) }
|
23
23
|
end
|
24
24
|
end
|
data/lib/thredded/version.rb
CHANGED
data/lib/thredded.rb
CHANGED
@@ -9,7 +9,7 @@ require 'html/pipeline'
|
|
9
9
|
require 'html/pipeline/sanitization_filter'
|
10
10
|
require 'rinku'
|
11
11
|
require 'kaminari'
|
12
|
-
require '
|
12
|
+
require 'rails_gravatar'
|
13
13
|
require 'active_job'
|
14
14
|
require 'inline_svg'
|
15
15
|
|
@@ -32,6 +32,7 @@ require 'sprockets/es6'
|
|
32
32
|
require 'sassc-rails'
|
33
33
|
|
34
34
|
require 'thredded/version'
|
35
|
+
require 'thredded/compat'
|
35
36
|
require 'thredded/engine'
|
36
37
|
require 'thredded/errors'
|
37
38
|
|
@@ -48,15 +49,6 @@ require 'thredded/collection_to_strings_with_cache_renderer'
|
|
48
49
|
|
49
50
|
require 'thredded/webpack_assets'
|
50
51
|
|
51
|
-
if Rails::VERSION::MAJOR < 5
|
52
|
-
begin
|
53
|
-
require 'where-or'
|
54
|
-
rescue LoadError
|
55
|
-
$stderr.puts "\nthredded: Please add gem 'where-or' to your Gemfile"
|
56
|
-
exit 1 # rubocop:disable Rails/Exit
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
52
|
module Thredded # rubocop:disable Metrics/ModuleLength
|
61
53
|
class << self
|
62
54
|
#== User
|
@@ -252,22 +244,10 @@ module Thredded # rubocop:disable Metrics/ModuleLength
|
|
252
244
|
.includes(:postable)
|
253
245
|
)
|
254
246
|
end
|
255
|
-
|
256
|
-
# @api private
|
257
|
-
def rails_gte_51?
|
258
|
-
@rails_gte_51 = (Rails.gem_version >= Gem::Version.new('5.1.0')) if @rails_gte_51.nil?
|
259
|
-
@rails_gte_51
|
260
|
-
end
|
261
|
-
|
262
|
-
# @api private
|
263
|
-
def rails_supports_csp_nonce?
|
264
|
-
@rails_supports_csp_nonce = (Rails.gem_version >= Gem::Version.new('5.2.0')) if @rails_supports_csp_nonce.nil?
|
265
|
-
@rails_supports_csp_nonce
|
266
|
-
end
|
267
247
|
end
|
268
248
|
|
269
249
|
self.user_name_column = :name
|
270
|
-
self.avatar_url = ->(user) {
|
250
|
+
self.avatar_url = ->(user) { RailsGravatar.src(user.email, 156, 'mm') }
|
271
251
|
self.admin_column = :admin
|
272
252
|
|
273
253
|
self.content_visible_while_pending_moderation = true
|