biovision-comment 0.8.190926.0 → 0.12.200627.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/biovision/comment/comments.scss +11 -0
- data/app/controllers/admin/comments_controller.rb +3 -2
- data/app/controllers/comments_controller.rb +13 -7
- data/app/helpers/comments_helper.rb +2 -1
- data/app/mailers/comment_mailer.rb +20 -2
- data/app/models/comment.rb +23 -6
- data/app/models/concerns/commentable_item.rb +1 -1
- data/app/services/biovision/components/comments_component.rb +80 -9
- data/app/services/comment_handler.rb +1 -2
- data/app/views/admin/comments/entity/_in_list.html.erb +3 -3
- data/app/views/admin/comments/show.html.erb +1 -1
- data/app/views/comment_mailer/comment_reply.html.erb +18 -0
- data/app/views/comment_mailer/entry_reply.html.erb +18 -0
- data/app/views/comments/_comment.html.erb +7 -0
- data/app/views/comments/_form.html.erb +6 -2
- data/config/locales/comments-ru.yml +13 -2
- data/db/{migrate → amends}/20190203090909_add_fields_to_comments.rb +0 -0
- data/db/{migrate → amends}/20190428212121_add_approved_to_comments.rb +0 -0
- data/db/{migrate → amends}/20190428212122_create_comments_component.rb +4 -2
- data/db/{migrate → amends}/20190628101010_add_data_to_comments.rb +0 -0
- data/db/migrate/20170914000001_create_comments.rb +15 -5
- data/db/migrate/20191017202020_add_search_index_to_comments.rb +16 -0
- data/db/migrate/20200208090909_convert_comments_vote_data.rb +27 -0
- data/lib/biovision/comment/version.rb +1 -1
- metadata +11 -51
- data/app/services/comments_manager.rb +0 -16
- data/app/views/comment_mailer/entry_reply.text.erb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fcfc0b5b350911016a52aca91b97a22d97fcb9b56db8f9eb9c896461b44bfb4f
|
4
|
+
data.tar.gz: 7fa54e4a1fdab7e2af536625e4997cfa5b8af28d50857193cb09dbd6757014e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 28ea2988dac507f37e3b434944e73ac81ad4b66277b15b4e15a7b8c6a81b50a4c56d4beeef240baa7cf707e1bf09bcb43b8e3dc02deb3d0ab0205982daa2cd3c
|
7
|
+
data.tar.gz: 9aa0e6476f9b048c132f5ba7232918b9e9fc990578b75557a6a0beda636fc46724dfd56220dc7300bbec44a176ed9e98769de96ea721e38b765ce1bb3733f162
|
@@ -82,6 +82,7 @@ $row-background-odd: #fafafa !default;
|
|
82
82
|
|
83
83
|
.comment-wrapper {
|
84
84
|
display: flex;
|
85
|
+
flex-wrap: wrap;
|
85
86
|
}
|
86
87
|
|
87
88
|
.vote-block {
|
@@ -152,6 +153,16 @@ $row-background-odd: #fafafa !default;
|
|
152
153
|
.children {
|
153
154
|
margin-left: var(--spacer-xs, .8rem);
|
154
155
|
}
|
156
|
+
|
157
|
+
.approval-buttons {
|
158
|
+
padding: var(--spacer-xs);
|
159
|
+
text-align: center;
|
160
|
+
width: 100%;
|
161
|
+
|
162
|
+
button {
|
163
|
+
cursor: pointer;
|
164
|
+
}
|
165
|
+
}
|
155
166
|
}
|
156
167
|
|
157
168
|
.comment-form {
|
@@ -19,6 +19,7 @@ class Admin::CommentsController < AdminController
|
|
19
19
|
# put /admin/comments/:id/approve
|
20
20
|
def approve
|
21
21
|
@entity.update(approved: true)
|
22
|
+
component_handler.class.notify(@entity)
|
22
23
|
|
23
24
|
head :no_content
|
24
25
|
end
|
@@ -31,8 +32,8 @@ class Admin::CommentsController < AdminController
|
|
31
32
|
|
32
33
|
protected
|
33
34
|
|
34
|
-
def
|
35
|
-
Biovision::Components::CommentsComponent
|
35
|
+
def component_class
|
36
|
+
Biovision::Components::CommentsComponent
|
36
37
|
end
|
37
38
|
|
38
39
|
def restrict_access
|
@@ -51,8 +51,8 @@ class CommentsController < ApplicationController
|
|
51
51
|
|
52
52
|
private
|
53
53
|
|
54
|
-
def
|
55
|
-
Biovision::Components::CommentsComponent
|
54
|
+
def component_class
|
55
|
+
Biovision::Components::CommentsComponent
|
56
56
|
end
|
57
57
|
|
58
58
|
def restrict_access
|
@@ -65,9 +65,11 @@ class CommentsController < ApplicationController
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def create_comment
|
68
|
-
|
68
|
+
verify_captcha_and_create
|
69
69
|
if @entity.valid?
|
70
|
-
|
70
|
+
unless @entity.approved?
|
71
|
+
flash[:notice] = t('comments.create.premoderation')
|
72
|
+
end
|
71
73
|
next_page = param_from_request(:return_url)
|
72
74
|
form_processed_ok(next_page.match?(%r{\A/[^/]}) ? next_page : root_path)
|
73
75
|
else
|
@@ -89,8 +91,12 @@ class CommentsController < ApplicationController
|
|
89
91
|
params.require(:comment).permit(permitted).merge(owner_for_entity(true))
|
90
92
|
end
|
91
93
|
|
92
|
-
|
93
|
-
|
94
|
-
|
94
|
+
protected
|
95
|
+
|
96
|
+
def verify_captcha_and_create
|
97
|
+
entity = Comment.new(creation_parameters)
|
98
|
+
verify_recaptcha(model: entity) if component_handler.use_captcha?
|
99
|
+
|
100
|
+
@entity = component_handler.create_comment(entity)
|
95
101
|
end
|
96
102
|
end
|
@@ -15,6 +15,7 @@ module CommentsHelper
|
|
15
15
|
def comment_link(entity, text = entity.commentable_name, options = {})
|
16
16
|
anchor = options.key?(:anchor)
|
17
17
|
options.delete(:anchor)
|
18
|
-
|
18
|
+
path = Biovision::Components::CommentsComponent.commentable_path(entity, anchor)
|
19
|
+
link_to(text, path, options)
|
19
20
|
end
|
20
21
|
end
|
@@ -1,8 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Mailer for sending comment notifications
|
1
4
|
class CommentMailer < ApplicationMailer
|
2
|
-
# @param [Integer]
|
5
|
+
# @param [Integer] comment_id
|
3
6
|
def entry_reply(comment_id)
|
4
7
|
@comment = Comment.find_by(id: comment_id)
|
5
8
|
|
6
|
-
|
9
|
+
return if @comment.nil?
|
10
|
+
|
11
|
+
user = @comment.commentable.user
|
12
|
+
|
13
|
+
mail(to: user.email) if user.can_receive_letters?
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param [Integer] comment_id
|
17
|
+
def comment_reply(comment_id)
|
18
|
+
@comment = Comment.find_by(id: comment_id)
|
19
|
+
|
20
|
+
return if @comment.nil?
|
21
|
+
|
22
|
+
user = @comment.parent.user
|
23
|
+
|
24
|
+
mail(to: user.email) if user.can_receive_letters?
|
7
25
|
end
|
8
26
|
end
|
data/app/models/comment.rb
CHANGED
@@ -11,6 +11,7 @@
|
|
11
11
|
# commentable_id [Integer]
|
12
12
|
# commentable_type [String]
|
13
13
|
# created_at [DateTime]
|
14
|
+
# data [JSON]
|
14
15
|
# deleted [Boolean]
|
15
16
|
# downvote_count [Integer]
|
16
17
|
# ip [Inet], optional
|
@@ -50,6 +51,7 @@ class Comment < ApplicationRecord
|
|
50
51
|
scope :chronological, -> { order 'id asc' }
|
51
52
|
scope :approved, -> { where(approved: true) }
|
52
53
|
scope :visible, -> { approved.where(deleted: false, visible: true, spam: false) }
|
54
|
+
scope :search, ->(q) { where("to_tsvector('russian', body) @@ phraseto_tsquery('russian', ?)", q.to_s) unless q.blank? }
|
53
55
|
scope :list_for_administration, -> { recent }
|
54
56
|
scope :list_for_visitors, -> { visible.chronological }
|
55
57
|
scope :list_for_visitors_recent, -> { visible.recent }
|
@@ -110,12 +112,18 @@ class Comment < ApplicationRecord
|
|
110
112
|
end
|
111
113
|
|
112
114
|
def notify_entry_owner?
|
115
|
+
return false unless commentable.respond_to?(:user)
|
116
|
+
|
113
117
|
entry_owner = commentable.user
|
114
|
-
if entry_owner.
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
118
|
+
return false if entry_owner.nil? || owned_by?(entry_owner)
|
119
|
+
|
120
|
+
!entry_owner.nil?
|
121
|
+
end
|
122
|
+
|
123
|
+
def notify_parent_owner?
|
124
|
+
return false if parent.nil?
|
125
|
+
|
126
|
+
!parent.owned_by?(user)
|
119
127
|
end
|
120
128
|
|
121
129
|
def text_for_link
|
@@ -127,7 +135,9 @@ class Comment < ApplicationRecord
|
|
127
135
|
end
|
128
136
|
|
129
137
|
def commentable_title
|
130
|
-
if commentable.respond_to?(:title)
|
138
|
+
if commentable.respond_to?(:title!)
|
139
|
+
commentable.title!
|
140
|
+
elsif commentable.respond_to?(:title)
|
131
141
|
commentable.title
|
132
142
|
else
|
133
143
|
commentable_name
|
@@ -138,6 +148,13 @@ class Comment < ApplicationRecord
|
|
138
148
|
user.nil? ? author_name : user.profile_name
|
139
149
|
end
|
140
150
|
|
151
|
+
# @param [Integer] word_count
|
152
|
+
def preview(word_count = 50)
|
153
|
+
words = body.split(/\s+/)
|
154
|
+
ellipsis = words.count > word_count ? '…' : ''
|
155
|
+
words.first(word_count).join(' ') + ellipsis
|
156
|
+
end
|
157
|
+
|
141
158
|
private
|
142
159
|
|
143
160
|
def commentable_is_commentable
|
@@ -10,28 +10,73 @@ module Biovision
|
|
10
10
|
%w[moderator]
|
11
11
|
end
|
12
12
|
|
13
|
+
# @param [Comment] comment
|
14
|
+
# @param [TrueClass|FalseClass] anchor
|
15
|
+
def self.commentable_path(comment, anchor = false)
|
16
|
+
method_name = "#{comment.commentable_type}_path".downcase.to_sym
|
17
|
+
if comment.commentable.respond_to?(:url)
|
18
|
+
result = comment.commentable.url
|
19
|
+
anchor ? "#{result}#comment-#{comment.id}" : result
|
20
|
+
else
|
21
|
+
"##{method_name}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [Comment] comment
|
26
|
+
def self.notify(comment)
|
27
|
+
return if comment.data['notified']
|
28
|
+
|
29
|
+
if comment.parent.nil?
|
30
|
+
if comment.notify_entry_owner?
|
31
|
+
CommentMailer.entry_reply(comment.id).deliver_later
|
32
|
+
end
|
33
|
+
elsif comment.notify_parent_owner?
|
34
|
+
CommentMailer.comment_reply(comment.id).deliver_later
|
35
|
+
end
|
36
|
+
|
37
|
+
comment.data['notified'] = true
|
38
|
+
comment.save
|
39
|
+
end
|
40
|
+
|
13
41
|
def use_parameters?
|
14
42
|
false
|
15
43
|
end
|
16
44
|
|
17
|
-
# @param [Hash]
|
18
|
-
def create_comment(
|
19
|
-
@comment = ::Comment.new(
|
45
|
+
# @param [Hash|Comment] data
|
46
|
+
def create_comment(data)
|
47
|
+
@comment = data.is_a?(::Comment) ? data : ::Comment.new(data)
|
48
|
+
limit_comment_body
|
20
49
|
@comment.approved = approval_flag if settings['premoderation']
|
21
|
-
|
50
|
+
trap_spam if settings['trap_spam']
|
51
|
+
@comment.save unless ignore?
|
52
|
+
self.class.notify(@comment) if @comment.approved?
|
53
|
+
|
22
54
|
@comment
|
23
55
|
end
|
24
56
|
|
57
|
+
def use_captcha?
|
58
|
+
return false unless settings['recaptcha']
|
59
|
+
return false unless Gem.loaded_specs.key?('recaptcha')
|
60
|
+
return true if user.nil?
|
61
|
+
|
62
|
+
gate = settings['auto_approve_threshold'].to_i
|
63
|
+
positive = ::Comment.where(user: user, approved: true).count
|
64
|
+
negative = ::Comment.where(user: user, approved: false).count
|
65
|
+
positive - negative < gate
|
66
|
+
end
|
67
|
+
|
25
68
|
protected
|
26
69
|
|
27
70
|
# @param [Hash] data
|
28
71
|
# @return [Hash]
|
29
72
|
def normalize_settings(data)
|
30
73
|
result = {}
|
31
|
-
flags
|
74
|
+
flags = %w[premoderation trap_spam recaptcha ignore_spam]
|
32
75
|
flags.each { |f| result[f] = data[f].to_i == 1 }
|
33
|
-
numbers = %w[auto_approve_threshold]
|
76
|
+
numbers = %w[auto_approve_threshold body_limit spam_link_threshold]
|
34
77
|
numbers.each { |f| result[f] = data[f].to_i }
|
78
|
+
strings = %w[spam_pattern]
|
79
|
+
strings.each { |f| result[f] = data[f].to_s }
|
35
80
|
|
36
81
|
result
|
37
82
|
end
|
@@ -40,15 +85,41 @@ module Biovision
|
|
40
85
|
threshold = settings['auto_approve_threshold']
|
41
86
|
if @comment.user.nil?
|
42
87
|
criteria = {
|
43
|
-
user_id: nil
|
44
|
-
ip: @comment.ip,
|
45
|
-
agent_id: @comment.agent_id
|
88
|
+
agent_id: @comment.agent_id, ip: @comment.ip, user_id: nil
|
46
89
|
}
|
47
90
|
::Comment.approved.where(criteria).count >= threshold
|
48
91
|
else
|
49
92
|
::Comment.approved.owned_by(@comment.user).count >= threshold
|
50
93
|
end
|
51
94
|
end
|
95
|
+
|
96
|
+
def trap_spam
|
97
|
+
@comment.approved = !spam?
|
98
|
+
end
|
99
|
+
|
100
|
+
def spam?
|
101
|
+
pattern = settings['spam_pattern']
|
102
|
+
return false if pattern.blank?
|
103
|
+
|
104
|
+
threshold = settings['spam_link_threshold'].to_i
|
105
|
+
|
106
|
+
@comment.body.scan(Regexp.new(pattern, 'i')).length > threshold
|
107
|
+
rescue RegexpError => e
|
108
|
+
Rails.logger.warn(e)
|
109
|
+
false
|
110
|
+
end
|
111
|
+
|
112
|
+
def ignore?
|
113
|
+
settings['ignore_spam'] && spam?
|
114
|
+
end
|
115
|
+
|
116
|
+
def limit_comment_body
|
117
|
+
body_limit = @component.settings['body_limit'].to_i
|
118
|
+
body_limit = 5000 if body_limit < 1
|
119
|
+
body_limit -= 1
|
120
|
+
|
121
|
+
@comment.body = @comment.body.to_s[0..body_limit]
|
122
|
+
end
|
52
123
|
end
|
53
124
|
end
|
54
125
|
end
|
@@ -6,9 +6,8 @@ class CommentHandler
|
|
6
6
|
|
7
7
|
# @param [User] user
|
8
8
|
def initialize(user = nil)
|
9
|
-
slug = Biovision::Components::CommentsComponent::SLUG
|
10
9
|
@user = user
|
11
|
-
@handler = Biovision::Components::
|
10
|
+
@handler = Biovision::Components::CommentsComponent[user]
|
12
11
|
end
|
13
12
|
|
14
13
|
# Get list of comments for entity
|
@@ -12,13 +12,13 @@
|
|
12
12
|
|
13
13
|
<div class="info">
|
14
14
|
<%= entity.commentable_name %>
|
15
|
-
(
|
15
|
+
(<cite><%= entity.commentable_title %></cite>)<br/>
|
16
16
|
<%= admin_user_link(entity.user) %>,
|
17
17
|
<%= time_tag entity.created_at %>
|
18
18
|
</div>
|
19
19
|
|
20
20
|
<div class="secondary info">
|
21
|
-
|
21
|
+
<p><%= entity.preview %></p>
|
22
22
|
</div>
|
23
23
|
|
24
24
|
<% unless entity.approved? %>
|
@@ -31,7 +31,7 @@
|
|
31
31
|
<ul class="actions">
|
32
32
|
<li><%= edit_icon(edit_comment_path(id: entity.id)) %></li>
|
33
33
|
<% unless entity.deleted? %>
|
34
|
-
<li><%= world_icon(
|
34
|
+
<li><%= world_icon(Biovision::Components::CommentsComponent.commentable_path(entity, true)) %></li>
|
35
35
|
<li class="danger"><%= destroy_icon(entity) %></li>
|
36
36
|
<% end %>
|
37
37
|
</ul>
|
@@ -14,7 +14,7 @@
|
|
14
14
|
<ul class="actions">
|
15
15
|
<li><%= back_icon(admin_comments_path) %></li>
|
16
16
|
<% unless @entity.deleted? %>
|
17
|
-
<li><%= world_icon(
|
17
|
+
<li><%= world_icon(Biovision::Components::CommentsComponent.commentable_path(@entity, true)) %></li>
|
18
18
|
<% end %>
|
19
19
|
<% unless @entity.locked? %>
|
20
20
|
<li><%= edit_icon edit_comment_path(id: @entity.id) %></li>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<%
|
2
|
+
relative_path = Biovision::Components::CommentsComponent.commentable_path(@comment, true)
|
3
|
+
protocol = ActionMailer::Base.default_url_options[:protocol] || 'http'
|
4
|
+
url = "#{protocol}://" + ActionMailer::Base.default_url_options[:host] + relative_path
|
5
|
+
%>
|
6
|
+
<p>Здравствуйте, <%= @comment.parent.user.name_for_letter %>.</p>
|
7
|
+
|
8
|
+
<p>
|
9
|
+
На ваш <%= link_to('комментарий', url) %> к записи
|
10
|
+
«<%= @comment.commentable_title %>» оставили ответ.
|
11
|
+
</p>
|
12
|
+
|
13
|
+
<figure style="margin-left:0;border-left:2px solid #777777;padding:10px">
|
14
|
+
<figcaption style="font-weight:700"><%= @comment.profile_name %>:</figcaption>
|
15
|
+
<blockquote>
|
16
|
+
<%= simple_format(@comment.body) %>
|
17
|
+
</blockquote>
|
18
|
+
</figure>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<%
|
2
|
+
relative_path = Biovision::Components::CommentsComponent.commentable_path(@comment)
|
3
|
+
protocol = ActionMailer::Base.default_url_options[:protocol] || 'http'
|
4
|
+
url = "#{protocol}://" + ActionMailer::Base.default_url_options[:host] + relative_path
|
5
|
+
%>
|
6
|
+
<p>Здравствуйте, <%= @comment.commentable.user.name_for_letter %>.</p>
|
7
|
+
|
8
|
+
<p>
|
9
|
+
На вашу запись «<%= link_to(@comment.commentable_title, url) %>»
|
10
|
+
оставили комментарий.
|
11
|
+
</p>
|
12
|
+
|
13
|
+
<figure style="margin-left:0;border-left:2px solid #777777;padding:10px">
|
14
|
+
<figcaption style="font-weight:700"><%= @comment.profile_name %>:</figcaption>
|
15
|
+
<blockquote>
|
16
|
+
<%= simple_format(@comment.body) %>
|
17
|
+
</blockquote>
|
18
|
+
</figure>
|
@@ -39,6 +39,13 @@
|
|
39
39
|
<div class="body" itemprop="about">
|
40
40
|
<%= simple_format(comment.body) %>
|
41
41
|
</div>
|
42
|
+
|
43
|
+
<% if handler.allow?('moderator') && !comment.approved? %>
|
44
|
+
<div class="approval-buttons">
|
45
|
+
<button class="js-approve-comment button-primary" data-url="<%= approve_admin_comment_path(id: comment.id) %>" type="button"><%= t('admin.comments.entity.in_list.approve') %></button>
|
46
|
+
<button class="js-delete-comment button-destroy" data-url="<%= admin_comment_path(id: comment.id) %>" type="button"><%= t(:delete) %></button>
|
47
|
+
</div>
|
48
|
+
<% end %>
|
42
49
|
</div>
|
43
50
|
|
44
51
|
<% if show_container %>
|
@@ -59,6 +59,10 @@
|
|
59
59
|
<% end %>
|
60
60
|
|
61
61
|
<div class="required">
|
62
|
+
<%
|
63
|
+
body_limit = BiovisionComponent['comments'].settings['body_limit'].to_i
|
64
|
+
body_limit = 5000 if body_limit < 1
|
65
|
+
%>
|
62
66
|
<%= f.label :body %>
|
63
67
|
<%=
|
64
68
|
f.text_area(
|
@@ -67,7 +71,7 @@
|
|
67
71
|
required: true,
|
68
72
|
cols: 60,
|
69
73
|
rows: 5,
|
70
|
-
maxlength:
|
74
|
+
maxlength: 5000,
|
71
75
|
class: 'auto-expand',
|
72
76
|
data: {
|
73
77
|
min_rows: 5,
|
@@ -77,7 +81,7 @@
|
|
77
81
|
)
|
78
82
|
%>
|
79
83
|
<div class="check-result-error hidden" data-field="body"></div>
|
80
|
-
<div class="guideline"><%= t('.guidelines.body') %></div>
|
84
|
+
<div class="guideline"><%= t('.guidelines.body', limit: body_limit) %></div>
|
81
85
|
</div>
|
82
86
|
</div>
|
83
87
|
|
@@ -86,8 +86,13 @@ ru:
|
|
86
86
|
guidelines:
|
87
87
|
author_name: "Максимум 100 символов, обязательное поле."
|
88
88
|
author_email: "Не показывается публично. Максимум 100 символов, обязательное поле."
|
89
|
-
body: "Максимум
|
89
|
+
body: "Максимум %{limit} символов."
|
90
90
|
disclaimer: "Отправляя комментарий, вы принимаете пользовательское соглашение и даёте своё согласие на обработку ваших персональных данных."
|
91
|
+
comment_mailer:
|
92
|
+
entry_reply:
|
93
|
+
subject: "Новый комментарий к вашей записи"
|
94
|
+
comment_reply:
|
95
|
+
subject: "Новый ответ на ваш комментарий"
|
91
96
|
biovision:
|
92
97
|
components:
|
93
98
|
comments:
|
@@ -95,5 +100,11 @@ ru:
|
|
95
100
|
privileges:
|
96
101
|
moderator: "Модератор"
|
97
102
|
settings:
|
98
|
-
premoderation: "Премодерация"
|
99
103
|
auto_approve_threshold: "Порог автоматического одобрения"
|
104
|
+
body_limit: "Максимальная длина"
|
105
|
+
ignore_spam: "Игнорировать спам"
|
106
|
+
premoderation: "Премодерация"
|
107
|
+
spam_link_threshold: "Порог попаданий шаблона для пометки как спам"
|
108
|
+
spam_pattern: "RegEx для ловли спама"
|
109
|
+
trap_spam: "Отлавливать спам"
|
110
|
+
recaptcha: "Использовать reCaptcha"
|
File without changes
|
File without changes
|
@@ -3,14 +3,16 @@
|
|
3
3
|
# Create row for comments component in components table
|
4
4
|
class CreateCommentsComponent < ActiveRecord::Migration[5.2]
|
5
5
|
def up
|
6
|
-
slug = Biovision::Components::CommentsComponent
|
6
|
+
slug = Biovision::Components::CommentsComponent.slug
|
7
7
|
return if BiovisionComponent.exists?(slug: slug)
|
8
8
|
|
9
9
|
BiovisionComponent.create!(
|
10
10
|
slug: slug,
|
11
11
|
settings: {
|
12
|
+
auto_approve_threshold: 3,
|
12
13
|
premoderation: false,
|
13
|
-
|
14
|
+
spam_link_threshold: 0,
|
15
|
+
trap_spam: true
|
14
16
|
}
|
15
17
|
)
|
16
18
|
end
|
File without changes
|
@@ -16,6 +16,7 @@ class CreateComments < ActiveRecord::Migration[5.0]
|
|
16
16
|
def create_comments_table
|
17
17
|
create_table :comments, comment: 'Comment for commentable item' do |t|
|
18
18
|
t.timestamps
|
19
|
+
t.uuid :uuid
|
19
20
|
t.integer :parent_id
|
20
21
|
t.references :user, foreign_key: { on_update: :cascade, on_delete: :cascade }
|
21
22
|
t.references :agent, foreign_key: { on_update: :cascade, on_delete: :nullify }
|
@@ -25,9 +26,6 @@ class CreateComments < ActiveRecord::Migration[5.0]
|
|
25
26
|
t.boolean :deleted, default: false, null: false
|
26
27
|
t.boolean :spam, default: false, null: false
|
27
28
|
t.boolean :approved, default: true, null: false
|
28
|
-
t.integer :upvote_count, default: 0, null: false
|
29
|
-
t.integer :downvote_count, default: 0, null: false
|
30
|
-
t.integer :vote_result, default: 0, null: false
|
31
29
|
t.integer :commentable_id, null: false
|
32
30
|
t.string :commentable_type, null: false
|
33
31
|
t.string :author_name
|
@@ -36,20 +34,32 @@ class CreateComments < ActiveRecord::Migration[5.0]
|
|
36
34
|
t.jsonb :data, default: {}, null: false
|
37
35
|
end
|
38
36
|
|
37
|
+
add_index :comments, :uuid, unique: true
|
39
38
|
add_index :comments, :data, using: :gin
|
40
39
|
add_index :comments, %i[commentable_id commentable_type]
|
40
|
+
add_index :comments, %i[approved agent_id ip]
|
41
41
|
add_foreign_key :comments, :comments, column: :parent_id, on_update: :cascade, on_delete: :cascade
|
42
|
+
|
43
|
+
execute %(
|
44
|
+
create index if not exists
|
45
|
+
comments_search_idx on comments
|
46
|
+
using gin(to_tsvector('russian', body));
|
47
|
+
)
|
42
48
|
end
|
43
49
|
|
44
50
|
def create_component_record
|
45
|
-
slug = Biovision::Components::CommentsComponent
|
51
|
+
slug = Biovision::Components::CommentsComponent.slug
|
46
52
|
return if BiovisionComponent.exists?(slug: slug)
|
47
53
|
|
48
54
|
BiovisionComponent.create!(
|
49
55
|
slug: slug,
|
50
56
|
settings: {
|
57
|
+
auto_approve_threshold: 3,
|
58
|
+
body_limit: 5000,
|
51
59
|
premoderation: false,
|
52
|
-
|
60
|
+
spam_link_threshold: 0,
|
61
|
+
trap_spam: true,
|
62
|
+
spam_pattern: 'https?://[a-z0-9]+'
|
53
63
|
}
|
54
64
|
)
|
55
65
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Add full-text search for comments
|
4
|
+
class AddSearchIndexToComments < ActiveRecord::Migration[5.2]
|
5
|
+
def up
|
6
|
+
execute %(
|
7
|
+
create index if not exists
|
8
|
+
comments_search_idx on comments
|
9
|
+
using gin(to_tsvector('russian', body));
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
def down
|
14
|
+
execute %(drop index if exists comments_search_idx)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Move vote component fields into data
|
4
|
+
class ConvertCommentsVoteData < ActiveRecord::Migration[5.2]
|
5
|
+
def up
|
6
|
+
return unless column_exists?(:comments, :vote_result)
|
7
|
+
|
8
|
+
add_column :comments, :uuid, :uuid
|
9
|
+
|
10
|
+
Comment.order('id asc').each do |comment|
|
11
|
+
comment.data['votes'] = {
|
12
|
+
up: comment.upvote_count,
|
13
|
+
down: comment.downvote_count,
|
14
|
+
total: comment.vote_result
|
15
|
+
}
|
16
|
+
comment.save!
|
17
|
+
end
|
18
|
+
|
19
|
+
remove_column :comments, :upvote_count
|
20
|
+
remove_column :comments, :downvote_count
|
21
|
+
remove_column :comments, :vote_result
|
22
|
+
end
|
23
|
+
|
24
|
+
def down
|
25
|
+
# No rollback needed
|
26
|
+
end
|
27
|
+
end
|
metadata
CHANGED
@@ -1,43 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: biovision-comment
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.200627.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maxim Khan-Magomedov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-06-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: rails
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '5.2'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '5.2'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: rails-i18n
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '5.0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '5.0'
|
41
13
|
- !ruby/object:Gem::Dependency
|
42
14
|
name: biovision-base
|
43
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,20 +24,6 @@ dependencies:
|
|
52
24
|
- - ">="
|
53
25
|
- !ruby/object:Gem::Version
|
54
26
|
version: '0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: kaminari
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :runtime
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
27
|
- !ruby/object:Gem::Dependency
|
70
28
|
name: database_cleaner
|
71
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,14 +108,14 @@ files:
|
|
150
108
|
- app/models/concerns/commentable_item.rb
|
151
109
|
- app/services/biovision/components/comments_component.rb
|
152
110
|
- app/services/comment_handler.rb
|
153
|
-
- app/services/comments_manager.rb
|
154
111
|
- app/views/admin/comments/_comment.html.erb
|
155
112
|
- app/views/admin/comments/_nav_item.html.erb
|
156
113
|
- app/views/admin/comments/entity/_in_list.html.erb
|
157
114
|
- app/views/admin/comments/index.html.erb
|
158
115
|
- app/views/admin/comments/show.html.erb
|
159
116
|
- app/views/admin/components/links/_comments.html.erb
|
160
|
-
- app/views/comment_mailer/
|
117
|
+
- app/views/comment_mailer/comment_reply.html.erb
|
118
|
+
- app/views/comment_mailer/entry_reply.html.erb
|
161
119
|
- app/views/comments/_comment.html.erb
|
162
120
|
- app/views/comments/_form.html.erb
|
163
121
|
- app/views/comments/_list.html.erb
|
@@ -168,11 +126,13 @@ files:
|
|
168
126
|
- app/views/layouts/biovision/comment/application.html.erb
|
169
127
|
- config/locales/comments-ru.yml
|
170
128
|
- config/routes.rb
|
129
|
+
- db/amends/20190203090909_add_fields_to_comments.rb
|
130
|
+
- db/amends/20190428212121_add_approved_to_comments.rb
|
131
|
+
- db/amends/20190428212122_create_comments_component.rb
|
132
|
+
- db/amends/20190628101010_add_data_to_comments.rb
|
171
133
|
- db/migrate/20170914000001_create_comments.rb
|
172
|
-
- db/migrate/
|
173
|
-
- db/migrate/
|
174
|
-
- db/migrate/20190428212122_create_comments_component.rb
|
175
|
-
- db/migrate/20190628101010_add_data_to_comments.rb
|
134
|
+
- db/migrate/20191017202020_add_search_index_to_comments.rb
|
135
|
+
- db/migrate/20200208090909_convert_comments_vote_data.rb
|
176
136
|
- lib/biovision/comment.rb
|
177
137
|
- lib/biovision/comment/engine.rb
|
178
138
|
- lib/biovision/comment/version.rb
|
@@ -196,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
196
156
|
- !ruby/object:Gem::Version
|
197
157
|
version: '0'
|
198
158
|
requirements: []
|
199
|
-
rubygems_version: 3.
|
159
|
+
rubygems_version: 3.1.4
|
200
160
|
signing_key:
|
201
161
|
specification_version: 4
|
202
162
|
summary: Commenting for biovision-based applications
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Tool for handling comments
|
4
|
-
class CommentsManager
|
5
|
-
# @param [Comment] comment
|
6
|
-
# @param [TrueClass|FalseClass] anchor
|
7
|
-
def self.commentable_path(comment, anchor = false)
|
8
|
-
method_name = "#{comment.commentable_type}_path".downcase.to_sym
|
9
|
-
if comment.commentable.respond_to?(:url)
|
10
|
-
result = comment.commentable.url
|
11
|
-
anchor ? "#{result}#comment-#{comment.id}" : result
|
12
|
-
else
|
13
|
-
"##{method_name}"
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,7 +0,0 @@
|
|
1
|
-
Здравствуйте, <%= @comment.commentable.user.name_for_letter %>.
|
2
|
-
|
3
|
-
На вашу запись «<%= @comment.commentable.title %>»
|
4
|
-
<%= url_for @comment.commentable %>
|
5
|
-
|
6
|
-
Сам комментарий (<%= @comment.user.nil? ? 'анонимный' : @comment.user.profile_name %>):
|
7
|
-
<%= @comment.body %>
|