decidim-comments 0.24.2 → 0.25.0.rc3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -20
  3. data/app/assets/javascripts/decidim/comments/bundle.js.map +1 -1
  4. data/app/cells/decidim/comments/comment/actions.erb +1 -1
  5. data/app/cells/decidim/comments/comment/deletion_data.erb +1 -0
  6. data/app/cells/decidim/comments/comment/show.erb +30 -21
  7. data/app/cells/decidim/comments/comment/utilities.erb +40 -12
  8. data/app/cells/decidim/comments/comment/votes.erb +6 -6
  9. data/app/cells/decidim/comments/comment_cell.rb +29 -0
  10. data/app/cells/decidim/comments/comment_form/show.erb +1 -1
  11. data/app/cells/decidim/comments/comments/add_comment.erb +10 -6
  12. data/app/cells/decidim/comments/comments/order_control.erb +4 -5
  13. data/app/cells/decidim/comments/comments/show.erb +2 -4
  14. data/app/cells/decidim/comments/comments/user_comments_blocked_warning.erb +5 -1
  15. data/app/cells/decidim/comments/comments_cell.rb +24 -2
  16. data/app/cells/decidim/comments/edit_comment_modal_form/show.erb +29 -0
  17. data/app/cells/decidim/comments/edit_comment_modal_form_cell.rb +53 -0
  18. data/app/commands/decidim/comments/create_comment.rb +2 -1
  19. data/app/commands/decidim/comments/delete_comment.rb +46 -0
  20. data/app/commands/decidim/comments/update_comment.rb +62 -0
  21. data/app/controllers/decidim/comments/comments_controller.rb +63 -6
  22. data/app/events/decidim/comments/comment_voted_event.rb +9 -0
  23. data/app/forms/decidim/comments/comment_form.rb +1 -1
  24. data/app/models/decidim/comments/comment.rb +24 -1
  25. data/app/packs/src/decidim/comments/comments.component.js +300 -0
  26. data/app/{assets/javascripts → packs/src}/decidim/comments/comments.component.test.js +116 -26
  27. data/app/packs/src/decidim/comments/comments.component_for_testing.js +8 -0
  28. data/app/packs/src/decidim/comments/comments.js +1 -0
  29. data/app/permissions/decidim/comments/permissions.rb +10 -1
  30. data/app/queries/decidim/comments/metrics/comment_participants_metric_measure.rb +1 -1
  31. data/app/queries/decidim/comments/metrics/comments_metric_manage.rb +1 -1
  32. data/app/queries/decidim/comments/sorted_comments.rb +8 -6
  33. data/app/views/decidim/comments/comments/_delete.html.erb +5 -0
  34. data/app/views/decidim/comments/comments/_edited_comment.html.erb +1 -0
  35. data/app/views/decidim/comments/comments/create.js.erb +4 -2
  36. data/app/views/decidim/comments/comments/delete.js.erb +17 -0
  37. data/app/views/decidim/comments/comments/deletion_error.js.erb +1 -0
  38. data/app/views/decidim/comments/comments/reload.js.erb +2 -0
  39. data/app/views/decidim/comments/comments/update.js.erb +8 -0
  40. data/app/views/decidim/comments/comments/update_error.js.erb +1 -0
  41. data/config/assets.rb +5 -0
  42. data/config/locales/ar.yml +0 -1
  43. data/config/locales/ca.yml +7 -1
  44. data/config/locales/cs.yml +25 -1
  45. data/config/locales/de.yml +7 -1
  46. data/config/locales/el.yml +0 -1
  47. data/config/locales/en.yml +25 -1
  48. data/config/locales/es-MX.yml +7 -1
  49. data/config/locales/es-PY.yml +7 -1
  50. data/config/locales/es.yml +7 -1
  51. data/config/locales/fi-plain.yml +25 -1
  52. data/config/locales/fi.yml +25 -1
  53. data/config/locales/fr-CA.yml +25 -1
  54. data/config/locales/fr-LU.yml +162 -0
  55. data/config/locales/fr.yml +25 -1
  56. data/config/locales/gl.yml +25 -1
  57. data/config/locales/hu.yml +0 -1
  58. data/config/locales/it.yml +38 -1
  59. data/config/locales/ja.yml +35 -1
  60. data/config/locales/lb-LU.yml +1 -0
  61. data/config/locales/lv.yml +0 -1
  62. data/config/locales/nl.yml +27 -2
  63. data/config/locales/no.yml +0 -1
  64. data/config/locales/pl.yml +7 -1
  65. data/config/locales/pt-BR.yml +61 -0
  66. data/config/locales/pt.yml +0 -1
  67. data/config/locales/ro-RO.yml +25 -1
  68. data/config/locales/sk.yml +0 -1
  69. data/config/locales/sr-CS.yml +0 -1
  70. data/config/locales/sv.yml +25 -1
  71. data/config/locales/tr-TR.yml +0 -1
  72. data/config/locales/zh-CN.yml +0 -1
  73. data/db/migrate/20200706123136_make_comments_handle_i18n.rb +1 -1
  74. data/db/migrate/20210402124534_add_participatory_process_to_comments.rb +12 -0
  75. data/db/migrate/20210529095942_add_deleted_at_column_to_comments.rb +7 -0
  76. data/lib/decidim/comments/commentable.rb +6 -1
  77. data/lib/decidim/comments/commentable_with_component.rb +33 -0
  78. data/lib/decidim/comments/engine.rb +1 -9
  79. data/lib/decidim/comments/test/factories.rb +1 -0
  80. data/lib/decidim/comments/version.rb +1 -1
  81. data/lib/decidim/comments.rb +1 -0
  82. data/lib/tasks/decidim_comments.rake +15 -0
  83. metadata +32 -29
  84. data/app/assets/config/decidim_comments_manifest.js +0 -1
  85. data/app/assets/javascripts/decidim/comments/comments.component.js.es6 +0 -292
  86. data/app/assets/javascripts/decidim/comments/comments.js.erb +0 -10
  87. data/config/locales/ja-JP.yml +0 -120
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable id-length, max-lines */
2
2
  /* global spyOn, jest */
3
+
3
4
  const $ = require("jquery");
4
5
 
5
6
  // Ability to spy on the jQuery methods inside the component in order to test
@@ -9,19 +10,26 @@ window.$ = jest.fn().mockImplementation((...args) => $(...args));
9
10
  window.$.ajax = jest.fn().mockImplementation((...args) => $.ajax(...args));
10
11
 
11
12
  // Quill is expected by the input character counter
12
- window.Quill = require("../../../../../../decidim-core/vendor/assets/javascripts/quill.min.js");
13
+ import Quill from "quill"
14
+ window.Quill = Quill
13
15
 
14
16
  // Fake timers for testing polling
15
17
  jest.useFakeTimers();
16
18
 
17
- require("../../../../../../decidim-core/app/assets/javascripts/decidim/input_character_counter.js.es6");
18
- require("./comments.component.js.es6");
19
+ import { createCharacterCounter } from "../../../../../../decidim-core/app/packs/src/decidim/input_character_counter";
20
+ import Configuration from "../../../../../../decidim-core/app/packs/src/decidim/configuration";
21
+ // Component is loaded with require because using import loads it before $ has been mocked
22
+ // so tests aren't able to check the spied behaviours
23
+ const CommentsComponent = require("./comments.component_for_testing.js");
19
24
 
20
- const { Decidim: { CommentsComponent, createCharacterCounter } } = window;
21
25
 
22
26
  // Create a dummy foundation jQuery method for the comments component to call
23
27
  $.fn.foundation = () => {};
24
28
 
29
+ // Create the configuration object to make the configurations available for the tests
30
+ window.Decidim = {}
31
+ window.Decidim.config = new Configuration()
32
+
25
33
  describe("CommentsComponent", () => {
26
34
  const selector = "#comments-for-Dummy-123";
27
35
  let subject = null;
@@ -163,18 +171,18 @@ describe("CommentsComponent", () => {
163
171
  </div>
164
172
  <div class="author-data__extra">
165
173
  <button type="button" class="link-alt" data-open="flagModalComment${commentId}" title="Report inappropriate content" aria-controls="flagModalComment${commentId}" aria-haspopup="true" tabindex="0">
166
- <svg role="none presentation" aria-hidden="true" class="icon--flag icon icon--small">
174
+ <svg role="img" aria-hidden="true" class="icon--flag icon icon--small">
167
175
  <title></title>
168
- <use role="none presentation" href="/assets/decidim/icons-123.svg#icon-flag"></use>
176
+ <use href="/assets/decidim/icons-123.svg#icon-flag"></use>
169
177
  </svg>
170
178
  <span class="show-for-sr">Report inappropriate content</span>
171
179
  </button>
172
180
 
173
181
  <a title="Get link to single comment" href="/path/to/dummy/123?commentId=${commentId}#comment_${commentId}">
174
182
  <span class="show-for-sr">Get link to single comment</span>
175
- <svg role="none presentation" class="icon--link-intact icon icon--small">
183
+ <svg role="img" aria-hidden="true" class="icon--link-intact icon icon--small">
176
184
  <title></title>
177
- <use role="none presentation" href="/assets/decidim/icons-123.svg#icon-link-intact"></use>
185
+ <use href="/assets/decidim/icons-123.svg#icon-link-intact"></use>
178
186
  </svg>
179
187
  </a>
180
188
  </div>
@@ -186,9 +194,9 @@ describe("CommentsComponent", () => {
186
194
  <div class="comment__footer">
187
195
  <div class="comment__actions">
188
196
  <button class="comment__reply muted-link" aria-controls="comment${commentId}-reply" data-toggle="comment${commentId}-reply" aria-expanded="true">
189
- <svg role="none presentation" class="icon--pencil icon icon--small">
197
+ <svg role="img" aria-hidden="true" class="icon--pencil icon icon--small">
190
198
  <title></title>
191
- <use role="none presentation" href="/assets/decidim/icons-123.svg#icon-pencil"></use>
199
+ <use href="/assets/decidim/icons-123.svg#icon-pencil"></use>
192
200
  </svg>
193
201
  &nbsp;Reply
194
202
  </button>
@@ -198,9 +206,9 @@ describe("CommentsComponent", () => {
198
206
  <form class="button_to" method="post" action="/comments/${commentId}/votes?weight=1" data-remote="true">
199
207
  <button class="comment__votes--up" title="I agree with this comment" type="submit">
200
208
  <span class="show-for-sr">I agree with this comment</span>
201
- <svg role="none presentation" class="icon--chevron-top icon icon--small">
209
+ <svg role="img" aria-hidden="true" class="icon--chevron-top icon icon--small">
202
210
  <title></title>
203
- <use role="none presentation" href="/assets/decidim/icons-123.svg#icon-chevron-top"></use>
211
+ <use href="/assets/decidim/icons-123.svg#icon-chevron-top"></use>
204
212
  </svg>
205
213
  <span class="comment__votes--count">0</span>
206
214
  </button>
@@ -210,9 +218,9 @@ describe("CommentsComponent", () => {
210
218
  <form class="button_to" method="post" action="/comments/${commentId}/votes?weight=-1" data-remote="true">
211
219
  <button class="comment__votes--down" title="I disagree with this comment" type="submit">
212
220
  <span class="show-for-sr">I disagree with this comment</span>
213
- <svg role="none presentation" class="icon--chevron-bottom icon icon--small">
221
+ <svg role="img" aria-hidden="true" class="icon--chevron-bottom icon icon--small">
214
222
  <title></title>
215
- <use role="none presentation" href="/assets/decidim/icons-123.svg#icon-chevron-bottom"></use>
223
+ <use href="/assets/decidim/icons-123.svg#icon-chevron-bottom"></use>
216
224
  </svg>
217
225
  <span class="comment__votes--count">0</span>
218
226
  </button>
@@ -224,9 +232,9 @@ describe("CommentsComponent", () => {
224
232
 
225
233
  <div class="comment__additionalreply hide">
226
234
  <button class="comment__reply muted-link" aria-controls="comment${commentId}-reply" data-toggle="comment${commentId}-reply" aria-expanded="true">
227
- <svg role="none presentation" class="icon--pencil icon icon--small">
235
+ <svg role="img" aria-hidden="true" class="icon--pencil icon icon--small">
228
236
  <title></title>
229
- <use role="none presentation" href="/assets/decidim/icons-123.svg#icon-pencil"></use>
237
+ <use href="/assets/decidim/icons-123.svg#icon-pencil"></use>
230
238
  </svg>
231
239
  &nbsp;Reply
232
240
  </button>
@@ -251,7 +259,7 @@ describe("CommentsComponent", () => {
251
259
 
252
260
  beforeEach(() => {
253
261
  let orderSelector = `
254
- <ul class="dropdown menu" data-dropdown-menu="data-dropdown-menu" data-autoclose="false" data-disable-hover="true" data-click-open="true" data-close-on-click="true" tabindex="-1" role="menubar">
262
+ <ul id="comments-order-menu" class="dropdown menu" data-dropdown-menu="data-dropdown-menu" data-autoclose="false" data-disable-hover="true" data-click-open="true" data-close-on-click="true" tabindex="-1" role="menubar">
255
263
  <li class="is-dropdown-submenu-parent opens-right" tabindex="-1" role="none">
256
264
  <a href="#" id="comments-order-menu-control" aria-label="Order by:" aria-controls="comments-order-menu" aria-haspopup="true" role="menuitem">Older</a>
257
265
  <ul class="menu is-dropdown-submenu submenu first-sub vertical" id="comments-order-chooser-menu" role="menu" aria-labelledby="comments-order-menu-control" tabindex="-1" data-submenu="">
@@ -304,21 +312,24 @@ describe("CommentsComponent", () => {
304
312
  <h4 class="section-heading">Add your comment</h4>
305
313
 
306
314
  <div class="opinion-toggle button-group">
307
- <button class="button tiny button--muted opinion-toggle--ok">
308
- <svg role="none presentation" class="icon--thumb-up icon">
315
+ <button aria-pressed="false" class="button tiny button--muted opinion-toggle--ok" data-selected-label="Your opinion about this topic is positive">
316
+ <svg role="img" aria-hidden="true" class="icon--thumb-up icon">
309
317
  <title></title>
310
- <use role="none presentation" href="/assets/decidim/icons-2ba788b32e181c1a7197f7a54a0f03101c146dd434b9e56191690c7c2d7bdae3.svg#icon-thumb-up"></use>
318
+ <use href="/assets/decidim/icons-2ba788b32e181c1a7197f7a54a0f03101c146dd434b9e56191690c7c2d7bdae3.svg#icon-thumb-up"></use>
311
319
  </svg>
320
+ <span class="show-for-sr">Positive</span>
312
321
  </button>
313
- <button class="button tiny button--muted opinion-toggle--meh is-active">
322
+ <button aria-pressed="true" class="button tiny button--muted opinion-toggle--meh is-active" data-selected-label="Your opinion about this topic is neutral">
314
323
  Neutral
315
324
  </button>
316
- <button class="button tiny button--muted opinion-toggle--ko">
317
- <svg role="none presentation" class="icon--thumb-down icon">
325
+ <button aria-pressed="false" class="button tiny button--muted opinion-toggle--ko" data-selected-label="Your opinion about this topic is negative">
326
+ <svg role="img" aria-hidden="true" class="icon--thumb-down icon">
318
327
  <title></title>
319
- <use role="none presentation" href="/assets/decidim/icons-2ba788b32e181c1a7197f7a54a0f03101c146dd434b9e56191690c7c2d7bdae3.svg#icon-thumb-down"></use>
328
+ <use href="/assets/decidim/icons-2ba788b32e181c1a7197f7a54a0f03101c146dd434b9e56191690c7c2d7bdae3.svg#icon-thumb-down"></use>
320
329
  </svg>
330
+ <span class="show-for-sr">Negative</span>
321
331
  </button>
332
+ <div role="alert" aria-live="assertive" aria-atomic="true" class="selected-state shot-for-sr"></div>
322
333
  </div>
323
334
 
324
335
  ${generateCommentForm("Dummy", 123)}
@@ -488,29 +499,43 @@ describe("CommentsComponent", () => {
488
499
  describe("opinion toggles", () => {
489
500
  let commentSection = null;
490
501
  let toggles = null;
502
+ let toggleContainer = null;
491
503
 
492
504
  beforeEach(() => {
493
505
  commentSection = addComment[addComment.length - 1];
494
506
  toggles = commentSection.opinionToggles;
507
+ toggleContainer = $(toggles[0]).parent();
495
508
  });
496
509
 
497
510
  it("adds the correct alignment on positive toggle", () => {
498
511
  $(toggles[0]).trigger("click");
499
512
 
513
+ expect($(toggles[0]).attr("aria-pressed")).toEqual("true");
514
+ expect($(toggles[1]).attr("aria-pressed")).toEqual("false");
515
+ expect($(toggles[2]).attr("aria-pressed")).toEqual("false");
500
516
  expect($(".alignment-input", commentSection).val()).toEqual("1");
517
+ expect($(".selected-state", toggleContainer).text()).toEqual("Your opinion about this topic is positive");
501
518
  });
502
519
 
503
520
  it("adds the correct alignment on neutral toggle", () => {
504
521
  $(toggles[0]).trigger("click");
505
522
  $(toggles[1]).trigger("click");
506
523
 
524
+ expect($(toggles[0]).attr("aria-pressed")).toEqual("false");
525
+ expect($(toggles[1]).attr("aria-pressed")).toEqual("true");
526
+ expect($(toggles[2]).attr("aria-pressed")).toEqual("false");
507
527
  expect($(".alignment-input", commentSection).val()).toEqual("0");
528
+ expect($(".selected-state", toggleContainer).text()).toEqual("Your opinion about this topic is neutral");
508
529
  });
509
530
 
510
531
  it("adds the correct alignment on negative toggle", () => {
511
532
  $(toggles[2]).trigger("click");
512
533
 
534
+ expect($(toggles[0]).attr("aria-pressed")).toEqual("false");
535
+ expect($(toggles[1]).attr("aria-pressed")).toEqual("false");
536
+ expect($(toggles[2]).attr("aria-pressed")).toEqual("true");
513
537
  expect($(".alignment-input", commentSection).val()).toEqual("-1");
538
+ expect($(".selected-state", toggleContainer).text()).toEqual("Your opinion about this topic is negative");
514
539
  });
515
540
  });
516
541
  });
@@ -533,17 +558,82 @@ describe("CommentsComponent", () => {
533
558
  "This is a dynamically added comment"
534
559
  ));
535
560
  });
561
+
562
+ it("does not clear the comment form text area", () => {
563
+ const commentSection = addComment[addComment.length - 1];
564
+ const textArea = $("textarea", commentSection);
565
+ textArea.val("I am writing a new comment...");
566
+
567
+ const newThread = generateCommentThread(999, "This is a dynamically added comment");
568
+ subject.addThread(newThread);
569
+
570
+ expect(textArea.val()).toEqual("I am writing a new comment...");
571
+ });
572
+
573
+ describe("as the current user", () => {
574
+ it("clears the comment form text area", () => {
575
+ const commentSection = addComment[addComment.length - 1];
576
+ const textArea = $("textarea", commentSection);
577
+ textArea.val("I am writing a new comment...");
578
+
579
+ const newThread = generateCommentThread(999, "This is a dynamically added comment");
580
+ subject.addThread(newThread, true);
581
+
582
+ expect(textArea.val()).toEqual("");
583
+ });
584
+ });
536
585
  });
537
586
 
538
587
  describe("addReply", () => {
588
+ const newReply = generateSingleComment(999, "This is a dynamically added reply");
589
+
539
590
  it("adds a new reply to an existing thread", () => {
540
- const newThread = generateSingleComment(999, "This is a dynamically added reply");
541
- subject.addReply(450, newThread);
591
+ subject.addReply(450, newReply);
542
592
 
543
593
  expect(subject.$element.html()).toEqual(expect.stringContaining(
544
594
  "This is a dynamically added reply"
545
595
  ));
546
596
  });
597
+
598
+ it("does not clear the reply comment form text area", () => {
599
+ const commentSection = $("#comment450-reply", subject.$element);
600
+ const textArea = $("textarea", commentSection);
601
+ textArea.val("I am writing a new comment...");
602
+
603
+ subject.addReply(450, newReply);
604
+
605
+ expect(textArea.val()).toEqual("I am writing a new comment...");
606
+ });
607
+
608
+ it("does not hide the reply form", () => {
609
+ const commentSection = $("#comment450-reply", subject.$element);
610
+ commentSection.removeClass("hide");
611
+
612
+ subject.addReply(450, newReply);
613
+
614
+ expect(commentSection.hasClass("hide")).toBeFalsy();
615
+ });
616
+
617
+ describe("as the current user", () => {
618
+ it("clears the comment form text area", () => {
619
+ const commentSection = $("#comment450-reply", subject.$element);
620
+ const textArea = $("textarea", commentSection);
621
+ textArea.val("I am writing a new comment...");
622
+
623
+ subject.addReply(450, newReply, true);
624
+
625
+ expect(textArea.val()).toEqual("");
626
+ });
627
+
628
+ it("hides the reply form", () => {
629
+ const commentSection = $("#comment450-reply", subject.$element);
630
+ commentSection.removeClass("hide");
631
+
632
+ subject.addReply(450, newReply, true);
633
+
634
+ expect(commentSection.hasClass("hide")).toBeTruthy();
635
+ });
636
+ });
547
637
  });
548
638
  });
549
639
 
@@ -0,0 +1,8 @@
1
+ /* eslint no-undef: 0 */
2
+
3
+ import CommentsComponent from "./comments.component"
4
+
5
+ // This module.exports is necessary for the tests to load
6
+ // doesn't conflict with import/export
7
+ module.exports = CommentsComponent;
8
+
@@ -0,0 +1 @@
1
+ import "src/decidim/comments/comments.component"
@@ -11,6 +11,8 @@ module Decidim
11
11
  can_read_comments?
12
12
  when :create
13
13
  can_create_comment?
14
+ when :update, :destroy
15
+ can_update_comment?
14
16
  when :vote
15
17
  can_vote_comment?
16
18
  end
@@ -34,9 +36,16 @@ module Decidim
34
36
  allow!
35
37
  end
36
38
 
39
+ def can_update_comment?
40
+ return disallow! unless user
41
+ return disallow! unless comment.authored_by?(user)
42
+
43
+ allow!
44
+ end
45
+
37
46
  def can_vote_comment?
38
47
  return disallow! unless user
39
- return disallow! unless commentable&.user_allowed_to_comment?(user)
48
+ return disallow! unless commentable&.user_allowed_to_vote_comment?(user)
40
49
 
41
50
  allow!
42
51
  end
@@ -39,7 +39,7 @@ module Decidim
39
39
 
40
40
  def retrieve_comments_for_organization
41
41
  user_ids = Decidim::User.where(organization: @resource.organization).pluck(:id)
42
- Decidim::Comments::Comment.includes(:root_commentable).not_hidden
42
+ Decidim::Comments::Comment.includes(:root_commentable).not_hidden.not_deleted
43
43
  .where("decidim_comments_comments.created_at <= ?", end_time)
44
44
  .where(decidim_comments_comments: { decidim_author_id: user_ids })
45
45
  .where(decidim_comments_comments: { decidim_author_type: "Decidim::UserBaseEntity" })
@@ -59,7 +59,7 @@ module Decidim
59
59
  def retrieve_comments
60
60
  user_ids = Decidim::User.select(:id).where(organization: @organization).collect(&:id)
61
61
  user_group_ids = Decidim::UserGroup.select(:id).where(organization: @organization).collect(&:id)
62
- Decidim::Comments::Comment.includes(:root_commentable).not_hidden
62
+ Decidim::Comments::Comment.includes(:root_commentable).not_hidden.not_deleted
63
63
  .where("decidim_comments_comments.created_at <= ?", end_time)
64
64
  .where("decidim_comments_comments.decidim_author_id IN (?) OR
65
65
  decidim_comments_comments.decidim_user_group_id IN (?)", user_ids, user_group_ids)
@@ -33,12 +33,6 @@ module Decidim
33
33
  scope = base_scope
34
34
  .not_hidden
35
35
  .includes(:author, :user_group, :up_votes, :down_votes)
36
- if @options[:after]
37
- scope = scope.where(
38
- "decidim_comments_comments.id > ?",
39
- @options[:after]
40
- )
41
- end
42
36
 
43
37
  case @options[:order_by]
44
38
  when "older"
@@ -60,6 +54,14 @@ module Decidim
60
54
  id = @options[:id]
61
55
  return Comment.where(root_commentable: commentable, id: id) if id.present?
62
56
 
57
+ after = @options[:after]
58
+ if after.present?
59
+ return Comment.where(root_commentable: commentable).where(
60
+ "decidim_comments_comments.id > ?",
61
+ after
62
+ )
63
+ end
64
+
63
65
  Comment.where(commentable: commentable)
64
66
  end
65
67
 
@@ -0,0 +1,5 @@
1
+ <div class="comment__header">
2
+ <div class="comment__deleted">
3
+ <%= t("decidim.components.comment.deleted_at", date: l(comment.deleted_at, format: :decidim_short)) %>
4
+ </div>
5
+ </div>
@@ -0,0 +1 @@
1
+ <%= cell("decidim/comments/comment", comment, reloaded: true) %>
@@ -6,11 +6,13 @@
6
6
  var $comments = $("#" + rootCommentableId);
7
7
  var component = $comments.data("comments");
8
8
  if (inReplyTo) {
9
- component.addReply(inReplyTo, commentHtml);
9
+ component.addReply(inReplyTo, commentHtml, true);
10
10
  } else {
11
- component.addThread(commentHtml);
11
+ component.addThread(commentHtml, true);
12
12
  }
13
13
 
14
14
  // Update the comments count
15
15
  $(".comments-count", $comments).text(<%== t("decidim.components.comments.title", count: @comments_count).to_json %>);
16
+
17
+ Decidim.addInputEmoji();
16
18
  }());
@@ -0,0 +1,17 @@
1
+ $(() => {
2
+ const deleteDataHtml = '<%== j(render partial: "delete", locals: { comment: @comment }).strip %>';
3
+ const rootCommentableId = <%== "comments-for-#{@comment.root_commentable.commentable_type.demodulize}-#{@comment.root_commentable.id}".to_json %>;
4
+ const commentId = <%= @comment.id.to_json %>;
5
+ const $comment = $(`#comment_${commentId}`);
6
+ const $commentReply = $(`#comment${commentId}-reply`);
7
+ const $content = $("> .comment__content", $comment);
8
+ const sectionsToDelete = ["header", "footer", "additionalreply"];
9
+
10
+ sectionsToDelete.forEach((section) => {
11
+ $(`> .comment__${section}`, $comment).remove();
12
+ });
13
+ $commentReply.remove();
14
+ $content.replaceWith(deleteDataHtml);
15
+
16
+ $(".comments-count", $(`#${rootCommentableId}`)).text(<%== t("decidim.components.comments.title", count: @comment.root_commentable.comments_count).to_json %>);
17
+ });
@@ -0,0 +1 @@
1
+ alert("<%== t("decidim.comments.comments.delete.error") %>");
@@ -18,4 +18,6 @@
18
18
 
19
19
  // Update the comments count
20
20
  $(".comments-count", $comments).text(<%== t("decidim.components.comments.title", count: @comments_count).to_json %>);
21
+
22
+ Decidim.addInputEmoji();
21
23
  }());
@@ -0,0 +1,8 @@
1
+ $(() => {
2
+ const commentHtml = '<%== j(render partial: "edited_comment", locals: { comment: @comment }).strip %>';
3
+ const commentId = <%= @comment.id.to_json %>;
4
+ const $comment = $("#comment_<%= @comment.id %>");
5
+ const $editCommentModal = $("#editCommentModal<%= @comment.id %>");
6
+
7
+ $comment.replaceWith(commentHtml);
8
+ });
@@ -0,0 +1 @@
1
+ alert("<%== t("decidim.comments.comments.update.error") %>");
data/config/assets.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ base_path = File.expand_path("..", __dir__)
4
+
5
+ Decidim::Webpacker.register_path("#{base_path}/app/packs")
@@ -63,7 +63,6 @@ ar:
63
63
  offensive: يحتوي على العنصرية والتمييز الجنسي والتشهير والهجمات الشخصية والتهديدات بالقتل أو طلبات الانتحار أو أي شكل من أشكال خطاب الكراهية.
64
64
  spam: يحتوي على clickbait أو الإعلان أو الخدع أو روبوت البرامج النصية.
65
65
  show_replies: اظهر الردود الـ %{replies_count}
66
- single_comment_link_title: الحصول على رابط نحو تعليق واحد
67
66
  comment_order_selector:
68
67
  order:
69
68
  best_rated: أفضل تصنيف