decidim-comments 0.23.2 → 0.24.0

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 -6
  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 +17 -2
  53. data/config/locales/cs.yml +19 -2
  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 +17 -2
  58. data/config/locales/es-PY.yml +17 -2
  59. data/config/locales/es.yml +17 -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 +9 -5
  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 +21 -4
  75. data/config/locales/pt-BR.yml +0 -2
  76. data/config/locales/pt.yml +0 -2
  77. data/config/locales/ro-RO.yml +15 -2
  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.rb +1 -3
  91. data/lib/decidim/comments/api.rb +12 -0
  92. data/lib/decidim/comments/comments_helper.rb +10 -52
  93. data/lib/decidim/comments/engine.rb +9 -7
  94. data/lib/decidim/comments/mutation_extensions.rb +22 -22
  95. data/lib/decidim/comments/query_extensions.rb +12 -14
  96. data/lib/decidim/comments/test.rb +1 -0
  97. data/lib/decidim/comments/test/shared_examples/comment_voted_event.rb +65 -0
  98. data/lib/decidim/comments/version.rb +1 -1
  99. metadata +65 -64
  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,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Comments
5
+ # This type represents a comment on a commentable object.
6
+ class CommentType < Decidim::Api::Types::BaseObject
7
+ description "A comment"
8
+
9
+ implements Decidim::Comments::CommentableInterface
10
+ field :author, Decidim::Core::AuthorInterface, "The resource author", null: false
11
+
12
+ field :id, GraphQL::Types::ID, "The Comment's unique ID", null: false
13
+
14
+ field :sgid, GraphQL::Types::String, "The Comment's signed global id", null: false
15
+
16
+ field :body, GraphQL::Types::String, "The comment message", null: false
17
+
18
+ field :formatted_body, GraphQL::Types::String, "The comment message ready to display (it is expected to include HTML)", null: false
19
+
20
+ field :created_at, GraphQL::Types::String, "The creation date of the comment", null: false
21
+
22
+ field :formatted_created_at, GraphQL::Types::String, "The creation date of the comment in relative format", null: false
23
+
24
+ field :alignment, GraphQL::Types::Int, "The comment's alignment. Can be 0 (neutral), 1 (in favor) or -1 (against)'", null: true
25
+
26
+ field :up_votes, GraphQL::Types::Int, "The number of comment's upVotes", null: false
27
+
28
+ field :up_voted, GraphQL::Types::Boolean, "Check if the current user has upvoted the comment", null: false
29
+
30
+ field :down_votes, GraphQL::Types::Int, "The number of comment's downVotes", null: false
31
+
32
+ field :down_voted, GraphQL::Types::Boolean, "Check if the current user has downvoted the comment", null: false
33
+
34
+ field :has_comments, GraphQL::Types::Boolean, "Check if the commentable has comments", method: :has_comments?, null: false
35
+
36
+ field :already_reported, GraphQL::Types::Boolean, "Check if the current user has reported the comment", null: false
37
+
38
+ field :user_allowed_to_comment, GraphQL::Types::Boolean, "Check if the current user can comment", null: false
39
+
40
+ def author
41
+ object.user_group || object.author
42
+ end
43
+
44
+ def sgid
45
+ object.to_sgid.to_s
46
+ end
47
+
48
+ def body
49
+ object.translated_body
50
+ end
51
+
52
+ def created_at
53
+ object.created_at.iso8601
54
+ end
55
+
56
+ def formatted_created_at
57
+ object.friendly_created_at
58
+ end
59
+
60
+ def up_votes
61
+ object.up_votes.size
62
+ end
63
+
64
+ def up_voted
65
+ object.up_voted_by?(context[:current_user])
66
+ end
67
+
68
+ def down_votes
69
+ object.down_votes.size
70
+ end
71
+
72
+ def down_voted
73
+ object.down_voted_by?(context[:current_user])
74
+ end
75
+
76
+ def has_comments?
77
+ object.comment_threads.size.positive?
78
+ end
79
+
80
+ def already_reported
81
+ object.reported_by?(context[:current_user])
82
+ end
83
+
84
+ def user_allowed_to_comment
85
+ object.root_commentable.commentable? && object.root_commentable.user_allowed_to_comment?(context[:current_user])
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Comments
5
+ # This interface represents a commentable object.
6
+ module CommentableInterface
7
+ include Decidim::Api::Types::BaseInterface
8
+ description "A commentable interface"
9
+
10
+ field :id, GraphQL::Types::ID, "The commentable's ID", null: false
11
+
12
+ field :type, GraphQL::Types::String, "The commentable's class name. i.e. `Decidim::ParticipatoryProcess`", method: :commentable_type, null: false
13
+
14
+ field :accepts_new_comments, GraphQL::Types::Boolean, "Whether the object can have new comments or not", method: :accepts_new_comments?, null: false
15
+
16
+ field :comments_have_alignment, GraphQL::Types::Boolean, "Whether the object comments have alignment or not", method: :comments_have_alignment?, null: false
17
+
18
+ field :comments_have_votes, GraphQL::Types::Boolean, "Whether the object comments have votes or not", method: :comments_have_votes?, null: false
19
+
20
+ field :comments, [Decidim::Comments::CommentType], null: false do
21
+ argument :order_by, GraphQL::Types::String, "Order the comments", required: false
22
+ argument :single_comment_id, GraphQL::Types::String, "ID of the single comment to look at", required: false
23
+ end
24
+
25
+ field :total_comments_count, GraphQL::Types::Int, description: "The number of comments in all levels this resource holds", null: false
26
+
27
+ def comments(order_by: nil, single_comment_id: nil)
28
+ SortedComments.for(object, order_by: order_by, id: single_comment_id)
29
+ end
30
+
31
+ def total_comments_count
32
+ object.comments_count
33
+ end
34
+
35
+ field :has_comments, GraphQL::Types::Boolean, "Check if the commentable has comments", null: false
36
+
37
+ # rubocop:disable Naming/PredicateName
38
+ def has_comments
39
+ object.comment_threads.size.positive?
40
+ end
41
+ # rubocop:enable Naming/PredicateName
42
+
43
+ field :user_allowed_to_comment, GraphQL::Types::Boolean, "Check if the current user can comment", null: false
44
+
45
+ def user_allowed_to_comment
46
+ object.commentable? && object.user_allowed_to_comment?(context[:current_user])
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Comments
5
+ class CommentableMutationType < Decidim::Api::Types::BaseObject
6
+ description "A commentable which includes its available mutations"
7
+
8
+ field :id, GraphQL::Types::ID, "The Commentable's unique ID", null: false
9
+
10
+ field :add_comment, Decidim::Comments::CommentType, description: "Add a new comment to a commentable", null: true do
11
+ argument :body, GraphQL::Types::String, "The comments's body", required: true
12
+ argument :alignment, GraphQL::Types::Int, "The comment's alignment. Can be 0 (neutral), 1 (in favor) or -1 (against)'", default_value: 0, required: false
13
+ argument :user_group_id, GraphQL::Types::ID, "The comment's user group id. Replaces the author.", required: false
14
+ end
15
+
16
+ def add_comment(body:, alignment: nil, user_group_id: nil)
17
+ params = { "comment" => { "body" => body, "alignment" => alignment, "user_group_id" => user_group_id, "commentable" => object } }
18
+ form = Decidim::Comments::CommentForm.from_params(params).with_context(
19
+ current_organization: context[:current_organization],
20
+ current_component: object.component
21
+ )
22
+ Decidim::Comments::CreateComment.call(form, context[:current_user]) do
23
+ on(:ok) do |comment|
24
+ return comment
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -3,13 +3,10 @@
3
3
  module Decidim
4
4
  module Comments
5
5
  # This type represents a commentable object.
6
- CommentableType = GraphQL::ObjectType.define do
7
- name "Commentable"
6
+ class CommentableType < Decidim::Api::Types::BaseObject
8
7
  description "A commentable object"
9
8
 
10
- interfaces [
11
- -> { Decidim::Comments::CommentableInterface }
12
- ]
9
+ implements Decidim::Comments::CommentableInterface
13
10
  end
14
11
  end
15
12
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "decidim/comments/admin"
4
+ require "decidim/comments/api"
4
5
  require "decidim/comments/engine"
5
6
  require "decidim/comments/admin_engine"
6
7
 
@@ -10,9 +11,6 @@ module Decidim
10
11
  # a React component which handle all the comments render and logic.
11
12
  module Comments
12
13
  autoload :CommentsHelper, "decidim/comments/comments_helper"
13
- autoload :AddCommentType, "decidim/comments/api/add_comment_type"
14
- autoload :CommentMutationType, "decidim/comments/api/comment_mutation_type"
15
- autoload :CommentType, "decidim/comments/api/comment_type"
16
14
  autoload :Commentable, "decidim/comments/commentable"
17
15
  autoload :CommentSerializer, "decidim/comments/comment_serializer"
18
16
  autoload :CommentVoteSerializer, "decidim/comments/comment_vote_serializer"
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Comments
5
+ autoload :CommentableInterface, "decidim/api/commentable_interface"
6
+ autoload :AddCommentType, "decidim/api/add_comment_type"
7
+ autoload :CommentMutationType, "decidim/api/comment_mutation_type"
8
+ autoload :CommentType, "decidim/api/comment_type"
9
+ autoload :CommentableType, "decidim/api/commentable_type"
10
+ autoload :CommentableMutationType, "decidim/api/commentable_mutation_type"
11
+ end
12
+ end
@@ -15,63 +15,21 @@ module Decidim
15
15
  end
16
16
  end
17
17
 
18
- # Creates a Comments component which is rendered using `ReactDOM`
18
+ # Creates a Comments component through the comments cell.
19
19
  #
20
20
  # resource - A commentable resource
21
21
  #
22
- # Returns a div which contain a RectComponent
23
- def inline_comments_for(resource)
22
+ # Returns the comments cell
23
+ def inline_comments_for(resource, options = {})
24
24
  return unless resource.commentable?
25
25
 
26
- commentable_type = resource.commentable_type
27
- commentable_id = resource.id.to_s
28
- node_id = "comments-for-#{commentable_type.demodulize}-#{commentable_id}"
29
- react_comments_component(
30
- node_id, commentableType: commentable_type,
31
- commentableId: commentable_id,
32
- locale: I18n.locale,
33
- toggleTranslations: machine_translations_toggled?,
34
- commentsMaxLength: comments_max_length(resource)
35
- )
36
- end
37
-
38
- # Private: Render Comments component using inline javascript
39
- #
40
- # node_id - The id of the DOMElement to render the React component
41
- # props - A hash corresponding to Comments component props
42
- def react_comments_component(node_id, props)
43
- content_tag("div", "", id: node_id) +
44
- javascript_include_tag("decidim/comments/comments") +
45
- javascript_tag(%{
46
- window.DecidimComments.renderCommentsComponent(
47
- '#{node_id}',
48
- {
49
- commentableType: "#{props[:commentableType]}",
50
- commentableId: "#{props[:commentableId]}",
51
- locale: "#{props[:locale]}",
52
- toggleTranslations: #{props[:toggleTranslations]},
53
- commentsMaxLength: "#{props[:commentsMaxLength]}"
54
- }
55
- );
56
- })
57
- end
58
-
59
- def comments_max_length(resource)
60
- return 1000 unless resource.respond_to?(:component)
61
- return component_comments_max_length(resource) if component_comments_max_length(resource)
62
- return organization_comments_max_length(resource) if organization_comments_max_length(resource)
63
-
64
- 1000
65
- end
66
-
67
- def component_comments_max_length(resource)
68
- return unless resource.component&.settings.respond_to?(:comments_max_length)
69
-
70
- resource.component.settings.comments_max_length if resource.component.settings.comments_max_length.positive?
71
- end
72
-
73
- def organization_comments_max_length(resource)
74
- resource.component.organization.comments_max_length if resource.component.organization.comments_max_length.positive?
26
+ cell(
27
+ "decidim/comments/comments",
28
+ resource,
29
+ machine_translations: machine_translations_toggled?,
30
+ single_comment: params.fetch("commentId", nil),
31
+ order: options[:order]
32
+ ).to_s
75
33
  end
76
34
  end
77
35
  end
@@ -19,20 +19,22 @@ module Decidim
19
19
  class Engine < ::Rails::Engine
20
20
  isolate_namespace Decidim::Comments
21
21
 
22
+ routes do
23
+ resources :comments, only: [:index, :create] do
24
+ resources :votes, only: [:create]
25
+ end
26
+ end
27
+
22
28
  initializer "decidim_comments.assets" do |app|
23
29
  app.config.assets.precompile += %w(decidim_comments_manifest.js)
24
30
  end
25
31
 
26
32
  initializer "decidim_comments.query_extensions" do
27
- Decidim::Api::QueryType.define do
28
- QueryExtensions.define(self)
29
- end
33
+ Decidim::Api::QueryType.include QueryExtensions
30
34
  end
31
35
 
32
36
  initializer "decidim_comments.mutation_extensions" do
33
- Decidim::Api::MutationType.define do
34
- MutationExtensions.define(self)
35
- end
37
+ Decidim::Api::MutationType.include MutationExtensions
36
38
  end
37
39
 
38
40
  initializer "decidim.stats" do
@@ -63,7 +65,7 @@ module Decidim
63
65
  initializer "decidim_comments.register_resources" do
64
66
  Decidim.register_resource(:comment) do |resource|
65
67
  resource.model_class_name = "Decidim::Comments::Comment"
66
- resource.card = "decidim/comments/comment"
68
+ resource.card = "decidim/comments/comment_card"
67
69
  resource.searchable = true
68
70
  end
69
71
  end
@@ -10,36 +10,36 @@ module Decidim
10
10
  # type - A GraphQL::BaseType to extend.
11
11
  #
12
12
  # Returns nothing.
13
- def self.define(type)
14
- type.field :commentable, Decidim::Comments::CommentableMutationType do
13
+ def self.included(type)
14
+ type.field :commentable, Decidim::Comments::CommentableMutationType, null: false do
15
15
  description "A commentable"
16
16
 
17
- argument :id, !types.String, "The commentable's ID"
18
- argument :type, !types.String, "The commentable's class name. i.e. `Decidim::ParticipatoryProcess`"
19
- argument :locale, !types.String, "The locale for which to get the comments text"
20
- argument :toggleTranslations, !types.Boolean, "Whether the user asked to toggle the machine translations or not."
21
-
22
- resolve lambda { |_obj, args, _ctx|
23
- I18n.locale = args[:locale].presence
24
- RequestStore.store[:toggle_machine_translations] = args[:toggleTranslations]
25
- args[:type].constantize.find(args[:id])
26
- }
17
+ argument :id, GraphQL::Types::String, "The commentable's ID", required: true
18
+ argument :type, GraphQL::Types::String, "The commentable's class name. i.e. `Decidim::ParticipatoryProcess`", required: true
19
+ argument :locale, GraphQL::Types::String, "The locale for which to get the comments text", required: false
20
+ argument :toggle_translations, GraphQL::Types::Boolean, "Whether the user asked to toggle the machine translations or not.", required: false
27
21
  end
28
22
 
29
- type.field :comment, Decidim::Comments::CommentMutationType do
23
+ type.field :comment, Decidim::Comments::CommentMutationType, null: false do
30
24
  description "A comment"
31
25
 
32
- argument :id, !types.ID, "The comment's id"
33
- argument :locale, !types.String, "The locale for which to get the comments text"
34
- argument :toggleTranslations, !types.Boolean, "Whether the user asked to toggle the machine translations or not."
35
-
36
- resolve lambda { |_obj, args, _ctx|
37
- I18n.locale = args[:locale].presence
38
- RequestStore.store[:toggle_machine_translations] = args[:toggleTranslations]
39
- Comment.find(args["id"])
40
- }
26
+ argument :id, GraphQL::Types::ID, "The comment's id", required: true
27
+ argument :locale, GraphQL::Types::String, "The locale for which to get the comments text", required: false
28
+ argument :toggle_translations, GraphQL::Types::Boolean, "Whether the user asked to toggle the machine translations or not.", required: false
41
29
  end
42
30
  end
31
+
32
+ def commentable(id:, type:, locale: Decidim.default_locale, toggle_translations: false)
33
+ I18n.locale = locale.presence
34
+ RequestStore.store[:toggle_machine_translations] = toggle_translations
35
+ type.constantize.find(id)
36
+ end
37
+
38
+ def comment(id:, locale: Decidim.default_locale, toggle_translations: false)
39
+ I18n.locale = locale.presence
40
+ RequestStore.store[:toggle_machine_translations] = toggle_translations
41
+ Comment.find(id)
42
+ end
43
43
  end
44
44
  end
45
45
  end
@@ -10,22 +10,20 @@ module Decidim
10
10
  # type - A GraphQL::BaseType to extend.
11
11
  #
12
12
  # Returns nothing.
13
- def self.define(type)
14
- type.field :commentable do
15
- type !CommentableType
16
-
17
- argument :id, !types.String, "The commentable's ID"
18
- argument :type, !types.String, "The commentable's class name. i.e. `Decidim::ParticipatoryProcess`"
19
- argument :locale, !types.String, "The locale for which to get the comments text"
20
- argument :toggleTranslations, !types.Boolean, "Whether the user asked to toggle the machine translations or not."
21
-
22
- resolve lambda { |_obj, args, _ctx|
23
- I18n.locale = args[:locale].presence
24
- RequestStore.store[:toggle_machine_translations] = args[:toggleTranslations]
25
- args[:type].constantize.find(args[:id])
26
- }
13
+ def self.included(type)
14
+ type.field :commentable, CommentableType, null: false do
15
+ argument :id, GraphQL::Types::String, "The commentable's ID", required: true
16
+ argument :type, GraphQL::Types::String, "The commentable's class name. i.e. `Decidim::ParticipatoryProcess`", required: true
17
+ argument :locale, GraphQL::Types::String, "The locale for which to get the comments text", required: true
18
+ argument :toggle_translations, GraphQL::Types::Boolean, "Whether the user asked to toggle the machine translations or not.", required: true
27
19
  end
28
20
  end
21
+
22
+ def commentable(id:, locale:, toggle_translations:, type:)
23
+ I18n.locale = locale.presence
24
+ RequestStore.store[:toggle_machine_translations] = toggle_translations
25
+ type.constantize.find(id)
26
+ end
29
27
  end
30
28
  end
31
29
  end
@@ -2,3 +2,4 @@
2
2
 
3
3
  require "decidim/comments/test/shared_examples/create_comment_context"
4
4
  require "decidim/comments/test/shared_examples/comment_event"
5
+ require "decidim/comments/test/shared_examples/comment_voted_event"
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ shared_examples_for "a comment voted event" do
6
+ include_context "when it's a comment event"
7
+
8
+ let(:resource) { comment.commentable }
9
+
10
+ let(:comment) { create :comment }
11
+ let(:comment_vote) { create :comment_vote, comment: comment }
12
+ let(:comment_vote_author) { comment_vote.author }
13
+
14
+ let(:extra) { { comment_id: comment.id, author_id: comment_vote_author.id, weight: weight, downvotes: 100, upvotes: 999 } }
15
+ let(:resource_title) { decidim_html_escape(translated(resource.title)) }
16
+ let(:resource_text) { subject.resource_text }
17
+
18
+ let(:verb) { weight.positive? ? "upvoted" : "downvoted" }
19
+
20
+ describe "downvotes" do
21
+ it "outputs the total downvotes" do
22
+ expect(subject.downvotes).to eq(100)
23
+ end
24
+ end
25
+
26
+ describe "upvotes" do
27
+ it "outputs the total upvotes" do
28
+ expect(subject.upvotes).to eq(999)
29
+ end
30
+ end
31
+
32
+ describe "resource_text" do
33
+ it "outputs the comment body" do
34
+ expect(subject.resource_text).to eq comment.formatted_body
35
+ end
36
+ end
37
+
38
+ describe "email_subject" do
39
+ it "is generated correctly" do
40
+ expect(subject.email_subject).to eq("Your comment in \"#{resource_title}\" has been #{verb}.")
41
+ end
42
+ end
43
+
44
+ describe "email_intro" do
45
+ it "is generated correctly" do
46
+ expect(subject.email_intro).to eq("Your comment in \"#{resource_title}\" has been #{verb}. It now has a total of 999 upvotes and 100 downvotes.")
47
+ end
48
+ end
49
+
50
+ describe "email_outro" do
51
+ it "is generated correctly" do
52
+ expect(subject.email_outro)
53
+ .to eq("You have received this notification because you are the author of this comment.")
54
+ end
55
+ end
56
+
57
+ describe "notification_title" do
58
+ it "is generated correctly" do
59
+ expect(subject.notification_title)
60
+ .to include("Your <a href=\"#{resource_path}#comment_#{comment.id}\">comment</a> in \"#{resource_title}\" has been #{verb}")
61
+ expect(subject.notification_title)
62
+ .to include("It now has a total of 999 upvotes and 100 downvotes.")
63
+ end
64
+ end
65
+ end