decidim-comments 0.23.6 → 0.24.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/decidim/comments/bundle.js.map +1 -1
  3. data/app/assets/javascripts/decidim/comments/comments.component.js.es6 +292 -0
  4. data/app/assets/javascripts/decidim/comments/comments.component.test.js +581 -0
  5. data/app/assets/javascripts/decidim/comments/comments.js.erb +1 -1
  6. data/app/cells/decidim/comments/comment/actions.erb +7 -0
  7. data/app/cells/decidim/comments/comment/alignment_badge.erb +4 -0
  8. data/app/cells/decidim/comments/comment/author.erb +1 -0
  9. data/app/cells/decidim/comments/comment/show.erb +40 -0
  10. data/app/cells/decidim/comments/comment/utilities.erb +13 -0
  11. data/app/cells/decidim/comments/comment/votes.erb +25 -0
  12. data/app/cells/decidim/comments/comment_card_cell.rb +22 -0
  13. data/app/cells/decidim/comments/comment_cell.rb +142 -8
  14. data/app/cells/decidim/comments/comment_form/comment_as.erb +10 -0
  15. data/app/cells/decidim/comments/comment_form/show.erb +24 -0
  16. data/app/cells/decidim/comments/comment_form_cell.rb +94 -0
  17. data/app/cells/decidim/comments/comment_m/top.erb +1 -1
  18. data/app/cells/decidim/comments/comment_thread/show.erb +6 -0
  19. data/app/cells/decidim/comments/comment_thread/title.erb +3 -0
  20. data/app/cells/decidim/comments/comment_thread_cell.rb +30 -0
  21. data/app/cells/decidim/comments/comments/add_comment.erb +30 -0
  22. data/app/cells/decidim/comments/comments/blocked_comments_warning.erb +3 -0
  23. data/app/cells/decidim/comments/comments/order_control.erb +37 -0
  24. data/app/cells/decidim/comments/comments/show.erb +32 -0
  25. data/app/cells/decidim/comments/comments/single_comment_warning.erb +9 -0
  26. data/app/cells/decidim/comments/comments/user_comments_blocked_warning.erb +3 -0
  27. data/app/cells/decidim/comments/comments_cell.rb +134 -0
  28. data/app/commands/decidim/comments/vote_comment.rb +34 -10
  29. data/app/controllers/decidim/comments/application_controller.rb +16 -0
  30. data/app/controllers/decidim/comments/comments_controller.rb +122 -0
  31. data/app/controllers/decidim/comments/votes_controller.rb +41 -0
  32. data/app/events/decidim/comments/comment_created_event.rb +1 -1
  33. data/app/events/decidim/comments/comment_downvoted_event.rb +8 -0
  34. data/app/events/decidim/comments/comment_upvoted_event.rb +8 -0
  35. data/app/events/decidim/comments/comment_voted_event.rb +26 -0
  36. data/app/forms/decidim/comments/comment_form.rb +6 -2
  37. data/app/models/decidim/comments/comment.rb +22 -8
  38. data/app/models/decidim/comments/seed.rb +1 -1
  39. data/app/permissions/decidim/comments/permissions.rb +59 -0
  40. data/app/queries/decidim/comments/metrics/comment_participants_metric_measure.rb +2 -2
  41. data/app/queries/decidim/comments/metrics/comments_metric_manage.rb +5 -6
  42. data/app/queries/decidim/comments/sorted_comments.rb +18 -14
  43. data/app/views/decidim/comments/comments/_comment.html.erb +5 -0
  44. data/app/views/decidim/comments/comments/_comments.html.erb +1 -0
  45. data/app/views/decidim/comments/comments/create.js.erb +16 -0
  46. data/app/views/decidim/comments/comments/error.js.erb +1 -0
  47. data/app/views/decidim/comments/comments/index.js.erb +24 -0
  48. data/app/views/decidim/comments/comments/reload.js.erb +21 -0
  49. data/app/views/decidim/comments/votes/create.js.erb +23 -0
  50. data/app/views/decidim/comments/votes/error.js.erb +1 -0
  51. data/config/locales/ar.yml +0 -2
  52. data/config/locales/ca.yml +7 -2
  53. data/config/locales/cs.yml +24 -7
  54. data/config/locales/de.yml +17 -2
  55. data/config/locales/el.yml +0 -2
  56. data/config/locales/en.yml +17 -2
  57. data/config/locales/es-MX.yml +7 -2
  58. data/config/locales/es-PY.yml +7 -2
  59. data/config/locales/es.yml +7 -2
  60. data/config/locales/eu.yml +0 -2
  61. data/config/locales/fi-plain.yml +17 -2
  62. data/config/locales/fi.yml +17 -2
  63. data/config/locales/fr-CA.yml +17 -2
  64. data/config/locales/fr.yml +17 -2
  65. data/config/locales/gl.yml +7 -2
  66. data/config/locales/hu.yml +0 -2
  67. data/config/locales/id-ID.yml +0 -2
  68. data/config/locales/is-IS.yml +0 -1
  69. data/config/locales/it.yml +4 -2
  70. data/config/locales/ja.yml +8 -4
  71. data/config/locales/lv.yml +0 -2
  72. data/config/locales/nl.yml +0 -2
  73. data/config/locales/no.yml +0 -2
  74. data/config/locales/pl.yml +19 -2
  75. data/config/locales/pt-BR.yml +0 -2
  76. data/config/locales/pt.yml +0 -2
  77. data/config/locales/ro-RO.yml +0 -3
  78. data/config/locales/ru.yml +0 -2
  79. data/config/locales/sk.yml +0 -2
  80. data/config/locales/sv.yml +7 -2
  81. data/config/locales/tr-TR.yml +7 -2
  82. data/config/locales/uk.yml +0 -1
  83. data/config/locales/zh-CN.yml +0 -2
  84. data/lib/decidim/api/add_comment_type.rb +13 -0
  85. data/lib/decidim/api/comment_mutation_type.rb +22 -0
  86. data/lib/decidim/api/comment_type.rb +89 -0
  87. data/lib/decidim/api/commentable_interface.rb +50 -0
  88. data/lib/decidim/api/commentable_mutation_type.rb +30 -0
  89. data/{app/types/decidim/comments → lib/decidim/api}/commentable_type.rb +2 -5
  90. data/lib/decidim/comments/api.rb +12 -0
  91. data/lib/decidim/comments/comments_helper.rb +10 -52
  92. data/lib/decidim/comments/engine.rb +9 -7
  93. data/lib/decidim/comments/mutation_extensions.rb +22 -22
  94. data/lib/decidim/comments/query_extensions.rb +12 -14
  95. data/lib/decidim/comments/test/shared_examples/comment_voted_event.rb +65 -0
  96. data/lib/decidim/comments/test.rb +1 -0
  97. data/lib/decidim/comments/version.rb +1 -1
  98. data/lib/decidim/comments.rb +1 -3
  99. metadata +67 -66
  100. data/app/assets/javascripts/decidim/comments/bundle.js +0 -268
  101. data/app/frontend/application/apollo_client.ts +0 -12
  102. data/app/frontend/application/application.component.test.tsx +0 -23
  103. data/app/frontend/application/application.component.tsx +0 -35
  104. data/app/frontend/application/icon.component.test.tsx +0 -38
  105. data/app/frontend/application/icon.component.tsx +0 -46
  106. data/app/frontend/comments/add_comment_form.component.test.tsx +0 -265
  107. data/app/frontend/comments/add_comment_form.component.tsx +0 -482
  108. data/app/frontend/comments/comment.component.test.tsx +0 -490
  109. data/app/frontend/comments/comment.component.tsx +0 -677
  110. data/app/frontend/comments/comment_order_selector.component.test.tsx +0 -29
  111. data/app/frontend/comments/comment_order_selector.component.tsx +0 -106
  112. data/app/frontend/comments/comment_thread.component.test.tsx +0 -82
  113. data/app/frontend/comments/comment_thread.component.tsx +0 -81
  114. data/app/frontend/comments/comments.component.test.tsx +0 -150
  115. data/app/frontend/comments/comments.component.tsx +0 -289
  116. data/app/frontend/comments/down_vote_button.component.test.tsx +0 -59
  117. data/app/frontend/comments/down_vote_button.component.tsx +0 -133
  118. data/app/frontend/comments/up_vote_button.component.test.tsx +0 -59
  119. data/app/frontend/comments/up_vote_button.component.tsx +0 -133
  120. data/app/frontend/comments/vote_button.component.tsx +0 -50
  121. data/app/frontend/comments/vote_button_component.test.tsx +0 -64
  122. data/app/frontend/entry.ts +0 -38
  123. data/app/frontend/entry_test.ts +0 -6
  124. data/app/frontend/fragments/add_comment_form_commentable.fragment.graphql +0 -4
  125. data/app/frontend/fragments/add_comment_form_session.fragment.graphql +0 -6
  126. data/app/frontend/fragments/comment.fragment.graphql +0 -14
  127. data/app/frontend/fragments/comment_data.fragment.graphql +0 -27
  128. data/app/frontend/fragments/comment_thread.fragment.graphql +0 -6
  129. data/app/frontend/fragments/down_vote_button.fragment.graphql +0 -6
  130. data/app/frontend/fragments/up_vote_button.fragment.graphql +0 -6
  131. data/app/frontend/mutations/add_comment.mutation.graphql +0 -9
  132. data/app/frontend/mutations/down_vote.mutation.graphql +0 -9
  133. data/app/frontend/mutations/up_vote.mutation.graphql +0 -9
  134. data/app/frontend/queries/comments.query.graphql +0 -26
  135. data/app/frontend/support/asset_url.ts +0 -11
  136. data/app/frontend/support/generate_comments_data.ts +0 -49
  137. data/app/frontend/support/generate_user_data.ts +0 -14
  138. data/app/frontend/support/generate_user_group_data.ts +0 -14
  139. data/app/frontend/support/graphql_transformer.js +0 -32
  140. data/app/frontend/support/load_translations.ts +0 -48
  141. data/app/frontend/support/require_all.ts +0 -10
  142. data/app/frontend/support/resolve_graphql_query.ts +0 -37
  143. data/app/frontend/support/schema.ts +0 -2026
  144. data/app/types/decidim/comments/commentable_interface.rb +0 -61
  145. data/app/types/decidim/comments/commentable_mutation_type.rb +0 -33
  146. data/lib/decidim/comments/api/add_comment_type.rb +0 -13
  147. data/lib/decidim/comments/api/comment_mutation_type.rb +0 -20
  148. data/lib/decidim/comments/api/comment_type.rb +0 -89
@@ -0,0 +1,25 @@
1
+ <div class="comment__votes">
2
+ <% if user_signed_in? %>
3
+ <%= button_to decidim_comments.comment_votes_path(model, weight: 1), remote: true, disabled: voted_down?, class: votes_up_classes, title: t("decidim.components.up_vote_button.text") do %>
4
+ <span class="show-for-sr"><%= t("decidim.components.up_vote_button.text") %></span>
5
+ <%= icon "chevron-top", class: "icon--small", role: "none presentation" %>
6
+ <span class="comment__votes--count"><%= up_votes_count %></span>
7
+ <% end %>
8
+ <%= button_to decidim_comments.comment_votes_path(model, weight: -1), remote: true, disabled: voted_up?, class: votes_down_classes, title: t("decidim.components.down_vote_button.text") do %>
9
+ <span class="show-for-sr"><%= t("decidim.components.down_vote_button.text") %></span>
10
+ <%= icon "chevron-bottom", class: "icon--small", role: "none presentation" %>
11
+ <span class="comment__votes--count"><%= down_votes_count %></span>
12
+ <% end %>
13
+ <% else %>
14
+ <button class="<%= votes_up_classes %> " title="<%= t("decidim.components.up_vote_button.text") %>" data-open="loginModal">
15
+ <span class="show-for-sr"><%= t("decidim.components.up_vote_button.text") %></span>
16
+ <%= icon "chevron-top", class: "icon--small", role: "none presentation" %>
17
+ <span class="comment__votes--count"><%= up_votes_count %></span>
18
+ </button>
19
+ <button class="<%= votes_down_classes %> " title="<%= t("decidim.components.down_vote_button.text") %>" data-open="loginModal">
20
+ <span class="show-for-sr"><%= t("decidim.components.down_vote_button.text") %></span>
21
+ <%= icon "chevron-bottom", class: "icon--small", role: "none presentation" %>
22
+ <span class="comment__votes--count"><%= down_votes_count %></span>
23
+ </button>
24
+ <% end %>
25
+ </div>
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Comments
5
+ # This cell renders the comment card for an instance of a Comment
6
+ # the default size is the Medium Card (:m)
7
+ class CommentCardCell < Decidim::ViewModel
8
+ include CommentCellsHelper
9
+ include Cell::ViewModel::Partial
10
+
11
+ def show
12
+ cell card_size, model, options
13
+ end
14
+
15
+ private
16
+
17
+ def card_size
18
+ "decidim/comments/comment_m"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -2,20 +2,154 @@
2
2
 
3
3
  module Decidim
4
4
  module Comments
5
- # This cell renders the comment card for an instance of a Comment
6
- # the default size is the Medium Card (:m)
5
+ # A cell to display a single comment.
7
6
  class CommentCell < Decidim::ViewModel
8
- include CommentCellsHelper
9
- include Cell::ViewModel::Partial
7
+ include ActionView::Helpers::DateHelper
8
+ include Decidim::IconHelper
9
+ include Decidim::ResourceHelper
10
10
 
11
- def show
12
- cell card_size, model, options
11
+ delegate :current_user, :user_signed_in?, to: :controller
12
+
13
+ property :root_commentable
14
+ property :created_at
15
+ property :alignment
16
+ property :translated_body
17
+ property :comment_threads
18
+ property :accepts_new_comments?
19
+
20
+ def alignment_badge
21
+ return unless [-1, 1].include?(alignment)
22
+
23
+ render :alignment_badge
24
+ end
25
+
26
+ def votes
27
+ return unless root_commentable.comments_have_votes?
28
+
29
+ render :votes
13
30
  end
14
31
 
15
32
  private
16
33
 
17
- def card_size
18
- "decidim/comments/comment_m"
34
+ def decidim_comments
35
+ Decidim::Comments::Engine.routes.url_helpers
36
+ end
37
+
38
+ def comment_body
39
+ Decidim::ContentProcessor.render(translated_body)
40
+ end
41
+
42
+ def replies
43
+ SortedComments.for(model, order_by: order)
44
+ end
45
+
46
+ def order
47
+ options[:order] || "older"
48
+ end
49
+
50
+ def reply_id
51
+ "comment#{model.id}-reply"
52
+ end
53
+
54
+ def can_reply?
55
+ user_signed_in? && accepts_new_comments? &&
56
+ root_commentable.user_allowed_to_comment?(current_user)
57
+ end
58
+
59
+ def author_presenter
60
+ if model.author.respond_to?(:official?) && model.author.official?
61
+ Decidim::Core::OfficialAuthorPresenter.new
62
+ elsif model.user_group
63
+ model.user_group.presenter
64
+ else
65
+ model.author.presenter
66
+ end
67
+ end
68
+
69
+ def comment_classes
70
+ classes = ["comment"]
71
+ if nested?
72
+ classes << "comment--nested"
73
+ classes << "comment--nested--alt" if nested_level_even?
74
+ end
75
+ classes.join(" ")
76
+ end
77
+
78
+ def alignment_badge_classes
79
+ classes = %w(label alignment)
80
+ case alignment
81
+ when 1
82
+ classes << "success"
83
+ when -1
84
+ classes << "alert"
85
+ end
86
+ classes.join(" ")
87
+ end
88
+
89
+ def alignment_badge_label
90
+ if alignment == 1
91
+ I18n.t("decidim.components.comment.alignment.in_favor")
92
+ else
93
+ I18n.t("decidim.components.comment.alignment.against")
94
+ end
95
+ end
96
+
97
+ def votes_up_classes
98
+ classes = ["comment__votes--up"]
99
+ classes << "is-vote-selected" if voted_up?
100
+ classes << "is-vote-notselected" if voted_down?
101
+ classes.join(" ")
102
+ end
103
+
104
+ def votes_down_classes
105
+ classes = ["comment__votes--down"]
106
+ classes << "is-vote-selected" if voted_down?
107
+ classes << "is-vote-notselected" if voted_up?
108
+ classes.join(" ")
109
+ end
110
+
111
+ def commentable_path(params = {})
112
+ if root_commentable.is_a?(Decidim::Budgets::Project)
113
+ resource_locator([root_commentable.budget, root_commentable]).path(params)
114
+ else
115
+ resource_locator(root_commentable).path(params)
116
+ end
117
+ end
118
+
119
+ def up_votes_count
120
+ model.up_votes.count
121
+ end
122
+
123
+ def down_votes_count
124
+ model.down_votes.count
125
+ end
126
+
127
+ def root_depth
128
+ options[:root_depth] || 0
129
+ end
130
+
131
+ def depth
132
+ model.depth - root_depth
133
+ end
134
+
135
+ def voted_up?
136
+ model.up_voted_by?(current_user)
137
+ end
138
+
139
+ def voted_down?
140
+ model.down_voted_by?(current_user)
141
+ end
142
+
143
+ def nested?
144
+ depth.positive?
145
+ end
146
+
147
+ def nested_level_even?
148
+ depth.even?
149
+ end
150
+
151
+ def has_replies?
152
+ model.comment_threads.any?
19
153
  end
20
154
  end
21
155
  end
@@ -0,0 +1,10 @@
1
+ <div class="field">
2
+ <label for="<%= comment_as_id %>">
3
+ <%= t("decidim.components.add_comment_form.form.user_group_id.label") %>
4
+ </label>
5
+ <select id="<%= comment_as_id %>" name="comment[user_group_id]">
6
+ <% comment_as_options.each do |option| %>
7
+ <option value="<%= option[1] %>"><%= option[0] %></option>
8
+ <% end %>
9
+ </select>
10
+ </div>
@@ -0,0 +1,24 @@
1
+ <%= form_for(form_object, url: decidim_comments.comments_path(order: order), method: :post, remote: true, html: { id: form_id }) do |form| %>
2
+ <%= form.hidden_field :commentable_gid, id: nil %>
3
+ <%= form.hidden_field :alignment, id: nil, class: "alignment-input" %>
4
+ <%= comment_as_for(form) %>
5
+ <div class="field">
6
+ <label class="show-for-sr" for="<%= add_comment_id %>">
7
+ <%= t("decidim.components.add_comment_form.form.body.label") %>
8
+ </label>
9
+ <div class="hashtags__container">
10
+ <%= form.text_area(
11
+ :body,
12
+ id: add_comment_id,
13
+ rows: 4,
14
+ maxlength: comments_max_length,
15
+ required: true,
16
+ placeholder: t("decidim.components.add_comment_form.form.body.placeholder"),
17
+ label: false,
18
+ data: { remaining_characters: "##{add_comment_id}-remaining-characters" }
19
+ ) %>
20
+ </div>
21
+ <button type="submit" class="button button--sc" disabled="disabled"><%= t("decidim.components.add_comment_form.form.submit") %></button>
22
+ <span id="<%= add_comment_id %>-remaining-characters" class="remaining-character-count"></span>
23
+ </div>
24
+ <% end %>
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Comments
5
+ # A cell to display a form for adding a new comment.
6
+ class CommentFormCell < Decidim::ViewModel
7
+ delegate :current_user, :user_signed_in?, to: :controller
8
+
9
+ def comment_as_for(form)
10
+ return if verified_user_groups.blank?
11
+
12
+ # Note that the form.select does not seem to work correctly in the cell
13
+ # context. The Rails form builder tries to call @template.select which
14
+ # is not available for the cell objects.
15
+ render view: :comment_as, locals: { form: form }
16
+ end
17
+
18
+ private
19
+
20
+ def decidim_comments
21
+ Decidim::Comments::Engine.routes.url_helpers
22
+ end
23
+
24
+ def order
25
+ options[:order] || "older"
26
+ end
27
+
28
+ def commentable_type
29
+ model.commentable_type
30
+ end
31
+
32
+ def form_id
33
+ "new_comment_for_#{commentable_type.demodulize}_#{model.id}"
34
+ end
35
+
36
+ def add_comment_id
37
+ "add-comment-#{commentable_type.demodulize}-#{model.id}"
38
+ end
39
+
40
+ def comment_as_id
41
+ "add-comment-#{commentable_type.demodulize}-#{model.id}-user-group-id"
42
+ end
43
+
44
+ def root_depth
45
+ options[:root_depth] || 0
46
+ end
47
+
48
+ def form_object
49
+ Decidim::Comments::CommentForm.new(
50
+ commentable_gid: model.to_signed_global_id.to_s,
51
+ alignment: 0
52
+ )
53
+ end
54
+
55
+ def verified_user_groups
56
+ return [] unless current_user
57
+
58
+ @verified_user_groups ||= Decidim::UserGroups::ManageableUserGroups.for(current_user).verified
59
+ end
60
+
61
+ def comment_as_options
62
+ [[current_user.name, ""]] + verified_user_groups.map do |group|
63
+ [group.name, group.id]
64
+ end
65
+ end
66
+
67
+ def comments_max_length
68
+ return 1000 unless model.respond_to?(:component)
69
+ return component_comments_max_length if component_comments_max_length
70
+ return organization_comments_max_length if organization_comments_max_length
71
+
72
+ 1000
73
+ end
74
+
75
+ def component_comments_max_length
76
+ return unless model.component&.settings.respond_to?(:comments_max_length)
77
+
78
+ model.component.settings.comments_max_length if model.component.settings.comments_max_length.positive?
79
+ end
80
+
81
+ def organization_comments_max_length
82
+ return unless organization
83
+
84
+ organization.comments_max_length if organization.comments_max_length.positive?
85
+ end
86
+
87
+ def organization
88
+ return model.organization if model.respond_to?(:organization)
89
+
90
+ model.component.organization if model.component.organization.comments_max_length.positive?
91
+ end
92
+ end
93
+ end
94
+ end
@@ -1,7 +1,7 @@
1
1
  <div class="card__top">
2
2
  <% if render_space? %>
3
3
  <div class="card__content text-small">
4
- <span class="muted"><%= searchable_resource_human_name(model.root_commentable.class) %>:</span>&nbsp;<%= link_to root_commentable_title, resource_link_path, class: "card__link text-ellipsis" %>
4
+ <span class="muted"><%= searchable_resource_human_name(model.root_commentable.class, count: 1) %>:</span>&nbsp;<%= link_to root_commentable_title, resource_link_path, class: "card__link text-ellipsis" %>
5
5
  </div>
6
6
  <% end %>
7
7
  </div>
@@ -0,0 +1,6 @@
1
+ <div>
2
+ <%= title %>
3
+ <div class="comment-thread">
4
+ <%= cell("decidim/comments/comment", model, root_depth: model.depth, order: order) %>
5
+ </div>
6
+ </div>
@@ -0,0 +1,3 @@
1
+ <h6 class="comment-thread__title">
2
+ <%= t("decidim.components.comment_thread.title", authorName: author_name) %>
3
+ </h6>
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Comments
5
+ # A cell to display a comment thread.
6
+ class CommentThreadCell < Decidim::ViewModel
7
+ def title
8
+ return unless has_threads?
9
+
10
+ render :title
11
+ end
12
+
13
+ private
14
+
15
+ def has_threads?
16
+ model.comment_threads.any?
17
+ end
18
+
19
+ def author_name
20
+ return t("decidim.components.comment.deleted_user") if model.author.deleted?
21
+
22
+ model.author.name
23
+ end
24
+
25
+ def order
26
+ options[:order] || "older"
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ <div class="add-comment">
2
+ <h4 class="section-heading"><%= t("decidim.components.add_comment_form.title") %></h4>
3
+
4
+ <% if user_signed_in? %>
5
+ <% if alignment_enabled? %>
6
+ <div class="opinion-toggle button-group">
7
+ <button class="button tiny button--muted opinion-toggle--ok">
8
+ <%= icon "thumb-up", role: "none presentation" %>
9
+ </button>
10
+ <button class="button tiny button--muted opinion-toggle--meh is-active">
11
+ <%= t("decidim.components.add_comment_form.opinion.neutral") %>
12
+ </button>
13
+ <button class="button tiny button--muted opinion-toggle--ko">
14
+ <%= icon "thumb-down", role: "none presentation" %>
15
+ </button>
16
+ </div>
17
+ <% end %>
18
+ <%== cell("decidim/comments/comment_form", model, root_depth: root_depth) %>
19
+ <% else %>
20
+ <p>
21
+ <span>
22
+ <%== t(
23
+ "decidim.components.add_comment_form.account_message",
24
+ sign_in_url: decidim.new_user_session_path,
25
+ sign_up_url: decidim.new_user_registration_path
26
+ ) %>
27
+ </span>
28
+ </p>
29
+ <% end %>
30
+ </div>
@@ -0,0 +1,3 @@
1
+ <div class="callout warning">
2
+ <p><%= t("decidim.components.comments.blocked_comments_warning") %></p>
3
+ </div>
@@ -0,0 +1,37 @@
1
+ <div class="order-by__dropdown order-by__dropdown--right">
2
+ <span class="order-by__text"><%= t("decidim.components.comment_order_selector.title") %></span>
3
+ <ul class="dropdown menu"
4
+ data-dropdown-menu="data-dropdown-menu"
5
+ data-autoclose="false"
6
+ data-disable-hover="true"
7
+ data-click-open="true"
8
+ data-close-on-click="true"
9
+ tabindex="-1"
10
+ role="menubar">
11
+ <li class="is-dropdown-submenu-parent opens-right" tabindex="-1" role="none">
12
+ <a href="#" id="comments-order-menu-control"
13
+ aria-label="<%= t("decidim.components.comment_order_selector.title") %>"
14
+ aria-controls="comments-order-menu"
15
+ aria-haspopup="true"
16
+ role="menuitem"><%= t("decidim.components.comment_order_selector.order.#{order}") %></a>
17
+ <ul class="menu is-dropdown-submenu submenu first-sub vertical"
18
+ id="comments-order-chooser-menu"
19
+ role="menu"
20
+ aria-labelledby="comments-order-menu-control"
21
+ tabindex="-1"
22
+ data-submenu="">
23
+ <% available_orders.each do |order_value| %>
24
+ <li role="none" class="is-submenu-item is-dropdown-submenu-item">
25
+ <%= link_to(
26
+ t("decidim.components.comment_order_selector.order.#{order_value}"),
27
+ decidim_comments.comments_path(commentable_gid: model.to_signed_global_id.to_s, order: order_value, reload: 1),
28
+ tabindex: -1,
29
+ role: "menuitem",
30
+ remote: true
31
+ ) %>
32
+ </li>
33
+ <% end %>
34
+ </ul>
35
+ </li>
36
+ </ul>
37
+ </div>
@@ -0,0 +1,32 @@
1
+ <%= content_tag :div, id: node_id, data: { decidim_comments: comments_data } do %>
2
+ <div class="columns large-9 comments-container" id="comments">
3
+ <div class="comments">
4
+ <div class="row collapse order-by">
5
+ <h2 class="order-by__text section-heading">
6
+ <% if single_comment? %>
7
+ <%= t("decidim.components.comments.comment_details_title") %>
8
+ <% else %>
9
+ <span class="comments-count">
10
+ <%= t("decidim.components.comments.title", count: comments_count) %>
11
+ </span>
12
+ <% end %>
13
+ </h2>
14
+ <%= render :order_control %>
15
+ </div>
16
+ <%= single_comment_warning %>
17
+ <%= blocked_comments_warning %>
18
+ <div class="comment-threads">
19
+ <% comments.each do |comment| %>
20
+ <%= cell("decidim/comments/comment_thread", comment, order: order) %>
21
+ <% end %>
22
+ </div>
23
+ <%= add_comment %>
24
+ <%= user_comments_blocked_warning %>
25
+ </div>
26
+ <div class="callout primary loading-comments hide">
27
+ <p><%= t("decidim.components.comments.loading") %></p>
28
+ </div>
29
+ </div>
30
+ <% end %>
31
+
32
+ <%= javascript_include_tag("decidim/comments/comments") %>
@@ -0,0 +1,9 @@
1
+ <div class="callout secondary">
2
+ <h5><%= t("decidim.components.comments.single_comment_warning_title") %></h5>
3
+ <p>
4
+ <%== t(
5
+ "decidim.components.comments.single_comment_warning",
6
+ url: "#{commentable_path}##{node_id}"
7
+ ) %>
8
+ </p>
9
+ </div>
@@ -0,0 +1,3 @@
1
+ <div class="callout warning">
2
+ <p><%= t("decidim.components.comments.blocked_comments_for_user_warning") %></p>
3
+ </div>
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Comments
5
+ # A cell to display a comments section for a commentable object.
6
+ class CommentsCell < Decidim::ViewModel
7
+ include Decidim::IconHelper
8
+
9
+ delegate :user_signed_in?, to: :controller
10
+
11
+ def add_comment
12
+ return if single_comment?
13
+ return if comments_blocked?
14
+ return if user_comments_blocked?
15
+
16
+ render :add_comment
17
+ end
18
+
19
+ def single_comment_warning
20
+ return unless single_comment?
21
+
22
+ render :single_comment_warning
23
+ end
24
+
25
+ def blocked_comments_warning
26
+ return unless comments_blocked?
27
+ return unless user_comments_blocked?
28
+
29
+ render :blocked_comments_warning
30
+ end
31
+
32
+ def user_comments_blocked_warning
33
+ return if comments_blocked? # Shows already the general warning
34
+ return unless user_comments_blocked?
35
+
36
+ render :user_comments_blocked_warning
37
+ end
38
+
39
+ private
40
+
41
+ def decidim_comments
42
+ Decidim::Comments::Engine.routes.url_helpers
43
+ end
44
+
45
+ def comments
46
+ if single_comment?
47
+ [single_comment]
48
+ else
49
+ SortedComments.for(model, order_by: order)
50
+ end
51
+ end
52
+
53
+ def comments_count
54
+ model.comments.count
55
+ end
56
+
57
+ def root_depth
58
+ return 0 unless single_comment?
59
+
60
+ single_comment.depth
61
+ end
62
+
63
+ def commentable_path(params = {})
64
+ resource_locator(model).path(params)
65
+ end
66
+
67
+ def alignment_enabled?
68
+ model.comments_have_alignment?
69
+ end
70
+
71
+ def available_orders
72
+ %w(best_rated recent older most_discussed)
73
+ end
74
+
75
+ def order
76
+ options[:order] || "older"
77
+ end
78
+
79
+ def decidim
80
+ Decidim::Core::Engine.routes.url_helpers
81
+ end
82
+
83
+ def node_id
84
+ "comments-for-#{commentable_type.demodulize}-#{model.id}"
85
+ end
86
+
87
+ def commentable_type
88
+ model.commentable_type
89
+ end
90
+
91
+ def comments_data
92
+ {
93
+ singleComment: single_comment?,
94
+ toggleTranslations: machine_translations_toggled?,
95
+ commentableGid: model.to_signed_global_id.to_s,
96
+ commentsUrl: decidim_comments.comments_path,
97
+ rootDepth: root_depth,
98
+ lastCommentId: last_comment_id,
99
+ order: order
100
+ }
101
+ end
102
+
103
+ def last_comment_id
104
+ Decidim::Comments::Comment.where(
105
+ root_commentable: model
106
+ ).order(:id).pluck(:id).last
107
+ end
108
+
109
+ def single_comment?
110
+ single_comment.present?
111
+ end
112
+
113
+ def single_comment
114
+ return if options[:single_comment].blank?
115
+
116
+ @single_comment ||= model.comments.find_by(id: options[:single_comment])
117
+ end
118
+
119
+ def machine_translations_toggled?
120
+ options[:machine_translations] == true
121
+ end
122
+
123
+ def comments_blocked?
124
+ !model.accepts_new_comments?
125
+ end
126
+
127
+ def user_comments_blocked?
128
+ return false unless user_signed_in?
129
+
130
+ !model.user_allowed_to_comment?(current_user)
131
+ end
132
+ end
133
+ end
134
+ end