biovision-comment 0.1.170914 → 0.7.190905.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +68 -14
  3. data/app/assets/javascripts/biovision/comment/biovision-comments.js +118 -0
  4. data/app/assets/stylesheets/biovision/comment/comments.scss +111 -38
  5. data/app/controllers/admin/comments_controller.rb +18 -5
  6. data/app/controllers/comments_controller.rb +45 -32
  7. data/app/helpers/comments_helper.rb +20 -0
  8. data/app/models/comment.rb +88 -19
  9. data/app/models/concerns/commentable_item.rb +15 -0
  10. data/app/services/biovision/components/comments_component.rb +39 -0
  11. data/app/services/comment_handler.rb +49 -0
  12. data/app/services/comments_manager.rb +24 -0
  13. data/app/views/admin/comments/entity/_in_list.html.erb +8 -5
  14. data/app/views/admin/comments/index.html.erb +2 -1
  15. data/app/views/admin/comments/show.html.erb +25 -10
  16. data/app/views/admin/components/links/_comments.html.erb +3 -0
  17. data/app/views/comment_mailer/entry_reply.text.erb +2 -6
  18. data/app/views/comments/_comment.html.erb +66 -16
  19. data/app/views/comments/_form.html.erb +92 -19
  20. data/app/views/comments/_list.html.erb +17 -19
  21. data/app/views/comments/_reply_container.html.erb +15 -0
  22. data/app/views/comments/_section.html.erb +34 -0
  23. data/app/views/comments/edit.html.erb +6 -5
  24. data/app/views/comments/new.html.erb +2 -2
  25. data/config/locales/comments-ru.yml +32 -2
  26. data/config/routes.rb +18 -10
  27. data/db/migrate/20170914000001_create_comments.rb +48 -23
  28. data/db/migrate/20190203090909_add_fields_to_comments.rb +14 -0
  29. data/db/migrate/20190428212121_add_approved_to_comments.rb +14 -0
  30. data/db/migrate/20190428212122_create_comments_component.rb +21 -0
  31. data/db/migrate/20190628101010_add_data_to_comments.rb +15 -0
  32. data/lib/biovision/comment/engine.rb +7 -2
  33. data/lib/biovision/comment/version.rb +3 -1
  34. metadata +19 -8
  35. data/app/views/comments/show.html.erb +0 -27
@@ -1,6 +1,7 @@
1
1
  <% content_for :meta_title, t('.title', page: current_page) %>
2
2
  <% content_for :breadcrumbs do %>
3
- <span><%= t('admin.comments.nav_item.text') %></span>
3
+ <%= admin_biovision_component_link(component_handler.component) %>
4
+ <span><%= t('admin.comments.nav_item.text') %></span>
4
5
  <% end %>
5
6
 
6
7
  <article class="comments">
@@ -1,30 +1,44 @@
1
1
  <% content_for :meta_title, t('.title', id: @entity.id) %>
2
2
  <% content_for :breadcrumbs do %>
3
- <%= link_to(t('admin.comments.nav_item.text'), admin_comments_path) %>
4
- <span>
5
- <%= @entity.id %> (<%= @entity.commentable.model_name.human %>
6
- <cite><%= @entity.commentable.title %></cite>)
7
- </span>
3
+ <%= admin_biovision_component_link(component_handler.component) %>
4
+ <%= link_to(t('admin.comments.nav_item.text'), admin_comments_path) %>
5
+ <span>
6
+ <%= @entity.id %> (<%= @entity.commentable.model_name.human %>
7
+ <cite><%= @entity.commentable_title %></cite>)
8
+ </span>
8
9
  <% end %>
9
10
 
10
11
  <article>
11
- <h1><%= @entity.commentable.title %></h1>
12
+ <h1><%= @entity.commentable_title %></h1>
12
13
 
13
14
  <ul class="actions">
14
15
  <li><%= back_icon(admin_comments_path) %></li>
16
+ <% unless @entity.deleted? %>
17
+ <li><%= world_icon(CommentsManager.commentable_path(@entity, true)) %></li>
18
+ <% end %>
15
19
  <% unless @entity.locked? %>
16
- <li><%= edit_icon edit_comment_path(@entity.id) %></li>
20
+ <li><%= edit_icon edit_comment_path(id: @entity.id) %></li>
17
21
  <% end %>
18
22
  </ul>
19
23
 
20
24
  <% if @entity.deleted? %>
21
- <div class="message-box-alert"><%= t(:deleted_entity) %></div>
25
+ <div class="message-box-alert"><%= t(:deleted_entity) %></div>
22
26
  <% end %>
23
27
 
24
28
  <dl>
25
29
  <dt><%= t('activerecord.attributes.comment.user_id') %></dt>
26
30
  <dd><%= admin_user_link(@entity.user) %></dd>
27
31
 
32
+ <% unless @entity.author_name.blank? %>
33
+ <dt><%= t('activerecord.attributes.comment.author_name') %></dt>
34
+ <dd><%= @entity.author_name %></dd>
35
+ <% end %>
36
+
37
+ <% unless @entity.author_email.blank? %>
38
+ <dt><%= t('activerecord.attributes.comment.author_email') %></dt>
39
+ <dd><%= @entity.author_email %></dd>
40
+ <% end %>
41
+
28
42
  <dt><%= t('activerecord.attributes.comment.commentable') %></dt>
29
43
  <dd><%= comment_link(@entity) %></dd>
30
44
 
@@ -33,8 +47,9 @@
33
47
 
34
48
  <dt><%= t('activerecord.attributes.comment.body') %></dt>
35
49
  <dd>
36
- <%= prepare_comment_text(@entity) %>
50
+ <div class="text">
51
+ <%= simple_format(@entity.body) %>
52
+ </div>
37
53
  </dd>
38
54
  </dl>
39
-
40
55
  </article>
@@ -0,0 +1,3 @@
1
+ <% if handler.allow?('moderator') %>
2
+ <li><%= render 'admin/comments/nav_item' %></li>
3
+ <% end %>
@@ -1,11 +1,7 @@
1
1
  Здравствуйте, <%= @comment.commentable.user.name_for_letter %>.
2
2
 
3
- На вашу запись «<%= @comment.commentable.title %>» на сайте party-npk.ru
3
+ На вашу запись «<%= @comment.commentable.title %>»
4
4
  <%= url_for @comment.commentable %>
5
5
 
6
6
  Сам комментарий (<%= @comment.user.nil? ? 'анонимный' : @comment.user.profile_name %>):
7
- <%= simple_format @comment.body %>
8
-
9
- --
10
- С уважением.
11
- автоматический уведомитель
7
+ <%= @comment.body %>
@@ -1,25 +1,75 @@
1
- <div id="comment-<%= comment.id %>" itemscope itemtype="http://schema.org/Comment" class="comment">
2
- <% if comment.deleted? %>
3
- <div class="deleted"><%= t('.deleted') %></div>
1
+ <% element_id = "comment-#{comment.id}" %>
2
+ <div
3
+ id="<%= element_id %>"
4
+ itemscope
5
+ itemtype="http://schema.org/Comment"
6
+ class="comment-item"
7
+ data-id="<%= comment.id %>"
8
+ >
9
+ <% if comment.deleted? || comment.user&.deleted? %>
10
+ <div class="deleted"><%= t('.deleted') %></div>
4
11
  <% else %>
5
- <meta itemprop="url" content="<%= comment_url comment %>"/>
6
- <div class="author">
7
- <span itemprop="author" itemscope itemtype="http://schema.org/Person">
8
- <span itemprop="name"><%= user_link comment.user %></span>
9
- </span>
12
+ <meta itemprop="url" content="<%= url_for(anchor: element_id) %>"/>
13
+ <% if current_user_has_privilege?(:moderator) %>
14
+ <ul class="actions">
15
+ <li><%= edit_icon(edit_comment_path(id: comment.id)) %></li>
16
+ <li class="danger"><%= destroy_icon(comment) %></li>
17
+ </ul>
18
+ <% end %>
19
+
20
+ <div class="meta">
21
+ <div class="avatar covered">
22
+ <%= user_image_preview(comment.user) %>
23
+ </div>
24
+ <div class="info">
25
+ <div itemprop="author" itemscope itemtype="http://schema.org/Person">
26
+ <span itemprop="name">
27
+ <%= comment.user.nil? ? comment.author_name : user_link(comment.user) %>
28
+ </span>
29
+ </div>
10
30
  <%= time_tag comment.created_at %>
11
31
  </div>
32
+ </div>
33
+
34
+ <div class="comment-wrapper">
35
+ <% if Gem.loaded_specs.key?('biovision-vote') %>
36
+ <%= render(partial: 'votes/vote_block', locals: { votable: comment }) %>
37
+ <% end %>
12
38
 
13
39
  <div class="body" itemprop="about">
14
- <%= prepare_comment_text(comment) %>
15
- <% if UserPrivilege.user_has_privilege?(current_user, :moderator) %>
16
- <ul class="actions">
17
- <li><%= edit_icon(edit_comment_path(comment.id)) %></li>
18
- <li class="danger"><%= destroy_icon(comment) %></li>
19
- </ul>
20
- <% end %>
40
+ <%= simple_format(comment.body) %>
21
41
  </div>
42
+ </div>
43
+
44
+ <% if show_container %>
45
+ <div class="comment-reply-block">
46
+ <div class="comment-reply-button">
47
+ <button class="button-nav"><%= t('.reply') %></button>
48
+ </div>
49
+ <div class="container hidden">
50
+ <button class="cancel" type="button" class="button-nav">
51
+ <%= t('.cancel_reply') %>
52
+ </button>
53
+ </div>
54
+ </div>
55
+ <% end %>
56
+ <% end %>
22
57
 
23
- <%= render(partial: 'votes/vote_block', locals: { votable: comment }) if defined?(Biovision::Vote) %>
58
+ <% children = comment_tree.select { |_, item| item[:parent_id] == comment.id } %>
59
+ <% if children.any? %>
60
+ <div class="children">
61
+ <% children.each do |_, item| %>
62
+ <%=
63
+ render(
64
+ partial: 'comments/comment',
65
+ locals: {
66
+ comment: item[:comment],
67
+ show_container: show_container,
68
+ comment_tree: comment_tree
69
+ }
70
+ )
71
+ %>
72
+ <% end %>
73
+ </div>
24
74
  <% end %>
25
75
  </div>
@@ -1,23 +1,96 @@
1
- <%= render partial: 'shared/list_of_errors', locals: { entity: entity } %>
1
+ <% model_name = entity.class.to_s.underscore %>
2
+ <%=
3
+ form_with(
4
+ model: entity,
5
+ html: {
6
+ id: "#{model_name}-form",
7
+ class: 'comment-form',
8
+ data: { check_url: check_comments_path }
9
+ }
10
+ ) do |f|
11
+ %>
12
+ <%= render partial: 'shared/list_of_errors', locals: { entity: entity } %>
13
+ <div class="fields">
14
+ <% if entity.id.nil? && entity.user.nil? %>
15
+ <div class="required">
16
+ <%= f.label :author_name %>
17
+ <%=
18
+ f.text_field(
19
+ :author_name,
20
+ id: "#{model_name}_author_name",
21
+ required: true,
22
+ size: nil,
23
+ maxlength: Comment::AUTHOR_LIMIT,
24
+ data: {
25
+ check: :author_name
26
+ }
27
+ )
28
+ %>
29
+ <div class="check-result-error hidden" data-field="author_name"></div>
30
+ <div class="guideline">
31
+ <%= t('.guidelines.author_name') %>
32
+ </div>
33
+ </div>
2
34
 
3
- <%= form_for entity do |f| %>
4
- <dl>
5
- <dt><%= f.label :body %></dt>
6
- <dd><%= f.text_area :body, required: true, cols: 60, rows: 7 %></dd>
7
- </dl>
8
- <% if current_user_has_privilege?(:administrator) && !entity.id.nil? %>
9
- <ul class="flags">
10
- <li>
11
- <%= f.check_box :deleted %>
12
- <%= f.label :deleted %>
13
- </li>
14
- </ul>
35
+ <div class="required">
36
+ <%= f.label :author_email %>
37
+ <%=
38
+ f.email_field(
39
+ :author_email,
40
+ id: "#{model_name}_author_email",
41
+ required: true,
42
+ size: nil,
43
+ maxlength: Comment::AUTHOR_LIMIT,
44
+ data: {
45
+ check: :author_email
46
+ }
47
+ )
48
+ %>
49
+ <div class="check-result-error hidden" data-field="author_email"></div>
50
+ <div class="guideline">
51
+ <%= t('.guidelines.author_email') %>
52
+ </div>
53
+ </div>
54
+
55
+ <div class="disclaimer">
56
+ <%= check_box_tag :agree, '1', false, class: 'hidden', tabindex: '-1' %>
57
+ <%= t('.disclaimer') %>
58
+ </div>
15
59
  <% end %>
16
- <div class="buttons">
17
- <% if entity.id.nil? %>
18
- <%= f.hidden_field :commentable_id %>
19
- <%= f.hidden_field :commentable_type %>
20
- <% end %>
21
- <%= f.button t(:submit), type: 'submit' %>
60
+
61
+ <div class="required">
62
+ <%= f.label :body %>
63
+ <%=
64
+ f.text_area(
65
+ :body,
66
+ id: "#{model_name}_body",
67
+ required: true,
68
+ cols: 60,
69
+ rows: 5,
70
+ maxlength: Comment::BODY_LIMIT,
71
+ class: 'auto-expand',
72
+ data: {
73
+ min_rows: 5,
74
+ max_rows: 30,
75
+ check: :body
76
+ }
77
+ )
78
+ %>
79
+ <div class="check-result-error hidden" data-field="body"></div>
80
+ <div class="guideline"><%= t('.guidelines.body') %></div>
22
81
  </div>
82
+ </div>
83
+
84
+ <%= render 'shared/forms/state_container' %>
85
+
86
+ <div class="buttons">
87
+ <%= hidden_field_tag :return_url, url_for %>
88
+ <%= hidden_field_tag :entity_id, entity.id %>
89
+ <% if entity.id.nil? %>
90
+ <%= f.hidden_field :commentable_id %>
91
+ <%= f.hidden_field :commentable_type %>
92
+ <%= f.hidden_field :parent_id %>
93
+ <% end %>
94
+ <%= f.button t(:submit), type: 'submit', class: 'button-primary button-action' %>
95
+ </div>
23
96
  <% end %>
@@ -1,19 +1,17 @@
1
- <section class="comments">
2
- <% if comments.any? %>
3
- <h2><%= t(:comments_list) %></h2>
4
-
5
- <% comments.recent.each do |comment| %>
6
- <%= render comment %>
7
- <% end %>
8
- <% end %>
9
-
10
- <% if commentable.respond_to?(:commentable_by?) && commentable.commentable_by?(current_user) %>
11
- <section class="reply-container">
12
- <h2><%= t(:add_comment) %></h2>
13
-
14
- <div class="container">
15
- <%= render partial: 'comments/form', locals: { entity: Comment.new(commentable: commentable) } %>
16
- </div>
17
- </section>
18
- <% end %>
19
- </section>
1
+ <% if collection.any? %>
2
+ <div>
3
+ <% comment_tree = Comment.tree(collection) %>
4
+ <% comment_tree.select { |_, item| item[:parent_id].nil? }.each do |_, item| %>
5
+ <%=
6
+ render(
7
+ partial: 'comments/comment',
8
+ locals: {
9
+ comment: item[:comment],
10
+ show_container: show_reply_container,
11
+ comment_tree: comment_tree
12
+ }
13
+ )
14
+ %>
15
+ <% end %>
16
+ </div>
17
+ <% end %>
@@ -0,0 +1,15 @@
1
+ <section class="reply-container">
2
+ <h3><%= t(:add_comment) %></h3>
3
+
4
+ <div class="container">
5
+ <%=
6
+ render(
7
+ partial: 'comments/form',
8
+ locals: {
9
+ entity: Comment.new(commentable: entity, user: current_user),
10
+ handler: handler
11
+ }
12
+ )
13
+ %>
14
+ </div>
15
+ </section>
@@ -0,0 +1,34 @@
1
+ <%
2
+ handler = CommentHandler.new(current_user)
3
+ collection = handler.list(entity)
4
+ show_reply_container = handler.allow_reply?(entity)
5
+ %>
6
+
7
+ <section class="comments" id="comments">
8
+ <div class="comments-list">
9
+ <h3><%= t(:comment_count, count: entity.comments_count) %></h3>
10
+
11
+ <%=
12
+ render(
13
+ partial: 'comments/list',
14
+ locals: {
15
+ collection: collection.load,
16
+ handler: handler,
17
+ show_reply_container: show_reply_container
18
+ }
19
+ )
20
+ %>
21
+ </div>
22
+
23
+ <% if show_reply_container %>
24
+ <%=
25
+ render(
26
+ partial: 'comments/reply_container',
27
+ locals: {
28
+ entity: entity,
29
+ handler: handler
30
+ }
31
+ )
32
+ %>
33
+ <% end %>
34
+ </section>
@@ -1,12 +1,13 @@
1
1
  <% content_for :meta_title, t('.title') %>
2
2
  <% content_for :breadcrumbs do %>
3
- <%= link_to(t('admin.comments.nav_item.text'), admin_comments_path) %>
4
- <%= admin_comment_link(@entity) %>
5
- <span><%= t(:edit) %></span>
3
+ <%= admin_biovision_component_link(component_handler.component) %>
4
+ <%= link_to(t('admin.comments.nav_item.text'), admin_comments_path) %>
5
+ <%= admin_comment_link(@entity) %>
6
+ <span><%= t('.nav_text') %></span>
6
7
  <% end %>
7
8
 
8
- <article class="edit-comment">
9
- <h1><%= t('.title') %></h1>
9
+ <article>
10
+ <h1><%= t('.heading') %></h1>
10
11
 
11
12
  <ul class="actions">
12
13
  <li><%= return_icon(admin_comment_path(@entity.id)) %></li>
@@ -1,7 +1,7 @@
1
1
  <% content_for :meta_title, t('.title') %>
2
2
 
3
- <article class="edit-comment">
3
+ <article>
4
4
  <h1><%= t('.title') %></h1>
5
5
 
6
- <%= render partial: 'form', locals: { entity: @entity } %>
6
+ <%= render(partial: 'form', locals: { entity: @entity }) %>
7
7
  </article>
@@ -24,12 +24,17 @@ ru:
24
24
  not_commentable: "недоступен вам для комментирования"
25
25
  attributes:
26
26
  comment:
27
+ approved: "Одобрен"
28
+ author_email: "Email"
29
+ author_name: "Имя"
30
+ body: "Текст"
27
31
  commentable: "Комментируемый объект" # Comment validates_presence_of :commentable
28
32
  commentable_id: "Комментируемый объект"
29
33
  commentable_type: "Тип комментируемого объекта"
30
- user_id: "Автор"
31
34
  deleted: "Комментарий удалён"
32
- body: "Текст"
35
+ spam: "Спам"
36
+ user_id: "Автор"
37
+ visible: "Показывать"
33
38
  admin:
34
39
  comments:
35
40
  nav_item:
@@ -40,6 +45,12 @@ ru:
40
45
  heading: "Комментарии"
41
46
  show:
42
47
  title: "Комментарий №%{id}"
48
+ comment:
49
+ deleted: "Комментарий удалён"
50
+ index:
51
+ dashboard:
52
+ biovision_comment:
53
+ heading: "Комментарии"
43
54
  my:
44
55
  comments:
45
56
  index:
@@ -57,9 +68,28 @@ ru:
57
68
  title: "Добавление комментария"
58
69
  edit:
59
70
  title: "Редактирование комментария"
71
+ nav_text: "Редактировать"
72
+ heading: "Редактирование комментария"
60
73
  show:
61
74
  title: "Комментарий №%{id}"
62
75
  entry_reply:
63
76
  subject: "Новый комментарий к вашей записи"
64
77
  comment:
65
78
  deleted: "Комментарий удалён"
79
+ cancel_reply: "Отменить"
80
+ reply: "Ответить"
81
+ form:
82
+ guidelines:
83
+ author_name: "Максимум 100 символов, обязательное поле."
84
+ author_email: "Не показывается публично. Максимум 100 символов, обязательное поле."
85
+ body: "Максимум 5000 символов."
86
+ disclaimer: "Отправляя комментарий, вы принимаете пользовательское соглашение и даёте своё согласие на обработку ваших персональных данных."
87
+ biovision:
88
+ components:
89
+ comments:
90
+ name: "Комментарии"
91
+ privileges:
92
+ moderator: "Модератор"
93
+ settings:
94
+ premoderation: "Премодерация"
95
+ auto_approve_threshold: "Порог автоматического одобрения"