Skip to content
Draft
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
f021144
Include pagination for comments and replies
alexrlpz Jan 29, 2026
08358f7
Update views and styles, and include translations
alexrlpz Jan 29, 2026
4c6df35
Delete comments polling
alexrlpz Jan 29, 2026
afabfa6
Merge branch 'develop' into feature/improve-comments-loading
alexrlpz Jan 29, 2026
e107d7c
Merge branch 'develop' into feature/improve-comments-loading
alexrlpz Jan 30, 2026
e9b6140
Include pagination for two columns layout and delete interleaved view
alexrlpz Feb 2, 2026
ee70456
Remove unused replies count
alexrlpz Feb 2, 2026
dcb77c9
Use comments limit for replies too
alexrlpz Feb 2, 2026
6f188c9
Lint
alexrlpz Feb 2, 2026
0e11f4e
Fix replies
alexrlpz Feb 2, 2026
0528da6
Fix replying comment issue
alexrlpz Feb 2, 2026
a1025ad
Fix i18n test
alexrlpz Feb 2, 2026
48fc530
Update comments shared examples to use new features
alexrlpz Feb 2, 2026
04cb420
Fix JS tests
fblupi Feb 2, 2026
cf594bb
Delete unnecessary re-creation of component when updating components
alexrlpz Feb 3, 2026
0dcbcbb
Update comments_example.rb
alexrlpz Feb 3, 2026
106d187
Delete interleaving tests and update comments tests
alexrlpz Feb 3, 2026
3ef3438
Update comments_examples.rb
alexrlpz Feb 3, 2026
de27579
Merge branch 'develop' into feature/improve-comments-loading
alexrlpz Feb 3, 2026
0124723
Delete interleaving tests and fix single comment test error
alexrlpz Feb 3, 2026
29c7832
Fix sorted comments tests
alexrlpz Feb 4, 2026
9272db8
Delete deprecated meeting test case
alexrlpz Feb 4, 2026
07e7f56
Update comments with two columns examples in comments_examples.rb
alexrlpz Feb 4, 2026
e47c4cb
Delete pagination of comment replies
alexrlpz Feb 10, 2026
20a270f
Update styles for load replies button and publish reply button
alexrlpz Feb 10, 2026
1f27434
Lint
alexrlpz Feb 10, 2026
f6b9259
Use has_key? instead of present?
fblupi Feb 12, 2026
ea7bce9
Order by most discussed and best rated using SQL
fblupi Feb 12, 2026
652b897
Reload comments when publishing a new comment
alexrlpz Feb 17, 2026
1e6ea0a
Improve JS
alexrlpz Feb 17, 2026
076f648
Fix comments loading for debates
alexrlpz Feb 17, 2026
7c0598f
Fix two columns layout tests
alexrlpz Feb 17, 2026
64c8795
Update tests
alexrlpz Feb 18, 2026
44dd15b
Apply CodeRabbit suggestions
alexrlpz Feb 18, 2026
ff59f76
Apply CodeRabbit suggestion
alexrlpz Feb 18, 2026
39f5560
Merge branch 'develop' of github.com:Platoniq/decidim into feature/im…
fblupi Feb 19, 2026
d6f9f31
Fix load more comments button position
alexrlpz Feb 19, 2026
40fad54
Display number of answers in load replies button
alexrlpz Feb 26, 2026
3078198
Fix tests
alexrlpz Feb 26, 2026
bb96120
Use the word reply instead of answer
fblupi Feb 26, 2026
8b7b5e3
Fix test
fblupi Feb 26, 2026
6e55ec8
Improve styles
alexrlpz Feb 27, 2026
7390516
Extract repeated code to partial
fblupi Mar 5, 2026
61555f1
Extract logic to Commentable concern and avoid repeating one query in…
fblupi Mar 5, 2026
1d43b6e
Add JSDoc to new Stimulus controllers
fblupi Mar 5, 2026
a9b4e22
Add load more comments test
fblupi Mar 5, 2026
b267fc8
Replace Rails.ajax with fetch
fblupi Mar 5, 2026
e98d54c
Lint
fblupi Mar 6, 2026
c17c9c4
Reduce the number of queries in TwoColumnsCommentsCell
fblupi Mar 6, 2026
a9dec20
Merge branch 'develop' of github.com:Platoniq/decidim into feature/im…
fblupi Mar 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
<%= render partial: "decidim/comments/comments/delete", formats: [:html], locals: { comment: model } %>

<div data-comment-footer data-controller="accordion" id="accordion-<%= model.id %>">
<div id="comment-<%= model.id %>-replies" class="<%= "comment-reply" if has_replies_in_children? %>">
<% if has_replies_in_children? %>
<%= render :replies %>
<% end %>
<% if has_replies_in_children? %>
<div data-controller="show-replies"
data-show-replies-url-value="<%= decidim_comments.comments_path %>"
data-show-replies-comment-gid-value="<%= model.to_signed_global_id.to_s %>"
data-show-replies-order-value="<%= order %>"
data-show-replies-loaded-value="false">
<div class="show-replies-button">
<button class="button button__xs button__text-secondary"
data-action="click->show-replies#toggle"
data-show-replies-target="button"
aria-expanded="false"
aria-controls="comment-<%= model.id %>-replies"
id="comment-<%= model.id %>-replies-trigger">
<span class="font-normal"><%= t("decidim.components.comment.load_replies") %></span>
<%= icon "arrow-down-s-line" %>
<%= icon "arrow-up-s-line" %>
</button>
<span data-show-replies-target="spinner" class="ml-2 hidden"><%= icon "loader-3-line", class: "animate-spin fill-secondary" %></span>
</div>
<div id="comment-<%= model.id %>-replies"
data-show-replies-target="container"
class="comment-reply hidden">
</div>
</div>
</div>
<% end %>

This file was deleted.

44 changes: 25 additions & 19 deletions decidim-comments/app/cells/decidim/comments/comment/show.erb
Original file line number Diff line number Diff line change
Expand Up @@ -90,31 +90,37 @@
<%= votes %>
</div>
</div>
<div class="comment__reply-button">
<% if depth.zero? && has_replies_in_children? %>
<button class="button button__xs button__transparent-secondary border-white absolute top-4" data-comment-hide data-controls="comment-<%= model.id %>-replies" data-open="false" id="comment-<%= model.id %>-replies-trigger">
<span data-show-comment-reply class="font-normal" aria-label="<%= t("decidim.components.comment.show_replies", count: replies.size) %>">
<%= t("decidim.components.comment.answers", count: replies.size) %>
</span>
<%= icon "arrow-down-s-line" %>
<span data-hide-comment-reply class="font-normal" aria-label="<%= t("decidim.components.comment.hide_replies", count: replies.size) %>">
<%= t("decidim.components.comment.answers", count: replies.size) %>
</span>
<%= icon "arrow-up-s-line" %>
</button>
<% end %>
</div>
<% if can_reply? %>
<div id="panel-<%= reply_id %>" class="add-comment" data-additional-reply>
<%== cell("decidim/comments/comment_form", model, root_depth:, order:) %>
</div>
<% end %>
<div id="comment-<%= model.id %>-replies" class="<%= "comment-reply" if has_replies_in_children? %>">
<% if has_replies_in_children? %>
<%= render :replies %>
<% end %>
</div>
</div>
<% if has_replies_in_children? %>
<div data-controller="show-replies"
data-show-replies-url-value="<%= decidim_comments.comments_path %>"
data-show-replies-comment-gid-value="<%= model.to_signed_global_id.to_s %>"
data-show-replies-order-value="<%= order %>"
data-show-replies-loaded-value="false">
<div class="show-replies-button">
<button class="button button__xs button__text-secondary"
data-action="click->show-replies#toggle"
data-show-replies-target="button"
aria-expanded="false"
aria-controls="comment-<%= model.id %>-replies"
id="comment-<%= model.id %>-replies-trigger">
<span class="font-normal"><%= t("decidim.components.comment.load_replies") %></span>
<%= icon "arrow-down-s-line" %>
<%= icon "arrow-up-s-line" %>
</button>
<span data-show-replies-target="spinner" class="ml-2 hidden"><%= icon "loader-3-line", class: "animate-spin fill-secondary" %></span>
</div>
<div id="comment-<%= model.id %>-replies"
data-show-replies-target="container"
class="comment-reply hidden">
</div>
</div>
<% end %>
<% end %>
<% if current_user.present? %>
<%= cell("decidim/report_button", model, modal_id: "flagModalComment#{model.id}").flag_modal %>
Expand Down
4 changes: 0 additions & 4 deletions decidim-comments/app/cells/decidim/comments/comment_cell.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,6 @@ def comment_body
formatted_body
end

def replies
SortedComments.for(model, order_by: order)
end

def order
options[:order] || "older"
end
Expand Down
23 changes: 13 additions & 10 deletions decidim-comments/app/cells/decidim/comments/comments/inline.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
<div id="comments">
<div class="comments">
<div class="comments__header">
<% if user_signed_in? %>
<button class="button button__lg button__secondary flex md:hidden w-full h-9 text-sm add-comment-mobile">
<%= t("add_comment", scope: "decidim.components.add_comment_form") %>
</button>
<% end %>
<%= add_comment %>
<%= user_comments_blocked_warning %>
<div class="comments__header mt-8">
<h2 class="h4">
<% if single_comment? %>
<%= t("decidim.components.comments.comment_details_title") %>
Expand All @@ -11,18 +18,14 @@
</span>
<% end %>
</h2>
<%= render :order_control unless two_columns_layout? %>
<% if two_columns_layout? %>
<div class="md:hidden"><%= render :order_control %></div>
<% else %>
<%= render :order_control %>
<% end %>
</div>
<%= single_comment_warning %>
<%= blocked_comments_warning %>
<%= render_comments %>
<% if user_signed_in? %>
<button class="button button__lg button__secondary flex md:hidden w-full h-9 text-sm add-comment-mobile">
<%= t("add_comment", scope: "decidim.components.add_comment_form") %>
</button>
<% end %>
<%= add_comment %>
<%= user_comments_blocked_warning %>
</div>
<%= cell("decidim/announcement", t("decidim.components.comments.loading"), callout_class: "primary loading-comments hidden") %>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@
<% @comments.each do |comment| %>
<%= cell("decidim/comments/comment_thread", comment, order:) %>
<% end %>
<% else %>
<p class="comments-section__no-comments"><%= @no_comments_message %></p>
<% elsif @top_comment.blank? %>
<p class="comments-section__no-comments"><%= t("decidim.components.comments.no_comments_yet") %></p>
<% end %>

<% if @has_more %>
<% offset = @comments.size + (@top_comment.present? ? 1 : 0) %>
<%= controller.view_context.render partial: "decidim/comments/comments/load_more_comments", locals: { commentable: model, order:, offset:, alignment: @alignment } %>
<% end %>
</div>
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<div id="desktopContainer" class="comments-two-columns card__grid-grid hidden md:grid">
<%= render_column(@top_comment_in_favor, @sorted_comments_in_favor, "thumb-up-line", t("decidim.components.comments.in_favor")) %>
<%= render_column(@top_comment_against, @sorted_comments_against, "thumb-down-line", t("decidim.components.comments.against")) %>
<%= render_column(@top_comment_in_favor, @sorted_comments_in_favor, "thumb-up-line", t("decidim.components.comments.in_favor"), 1, @has_more_in_favor) %>
<%= render_column(@top_comment_against, @sorted_comments_against, "thumb-down-line", t("decidim.components.comments.against"), -1, @has_more_against) %>
</div>

<div id="mobileContainer" class="comment-threads block md:hidden" aria-live="polite">
<%= comments_loading %>
<% @interleaved_comments.each do |comment| %>
<%= cell("decidim/comments/comment_thread", comment, order:, top_comment: (comment == @top_comment_in_favor || comment == @top_comment_against)) %>
<% @mobile_comments.each do |comment| %>
<%= cell("decidim/comments/comment_thread", comment, order:) %>
<% end %>
<% if @has_more_mobile %>
<%= controller.view_context.render partial: "decidim/comments/comments/load_more_comments", locals: { commentable: model, order:, offset: @mobile_comments.size } %>
<% end %>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,35 @@ module Comments
class TwoColumnsCommentsCell < Decidim::Comments::CommentsCell
def call
initialize_comments
@interleaved_comments = interleave_comments(@sorted_comments_in_favor, @sorted_comments_against)
render :show
end

def render_column(top_comment, comments, icon_name, title)
set_column_variables(top_comment, comments, icon_name, title)
# rubocop:disable Metrics/ParameterLists
def render_column(top_comment, comments, icon_name, title, alignment, has_more)
set_column_variables(top_comment, comments, icon_name, title, alignment, has_more)
render :column
end
# rubocop:enable Metrics/ParameterLists

private

def initialize_comments
if model.closed?
load_closed_comments
else
@sorted_comments_in_favor = comments_in_favor
@sorted_comments_against = comments_against
@sorted_comments_in_favor = comments_in_favor_query.query
@sorted_comments_against = comments_against_query.query
end

@has_more_in_favor = comments_in_favor_query.has_more?
@has_more_against = comments_against_query.has_more?

load_mobile_comments
end

def load_closed_comments
@top_comment_in_favor, @sorted_comments_in_favor = sorted_comments(comments_in_favor)
@top_comment_against, @sorted_comments_against = sorted_comments(comments_against)
@top_comment_in_favor, @sorted_comments_in_favor = sorted_comments(comments_in_favor_query.query)
@top_comment_against, @sorted_comments_against = sorted_comments(comments_against_query.query)
end

def sorted_comments(comments)
Expand All @@ -45,42 +51,30 @@ def find_top_comment(comments)
.first
end

def interleave_comments(comments_in_favor, comments_against)
interleave_top_comments + interleave_remaining_comments(comments_in_favor, comments_against)
end

def interleave_top_comments
return [] unless model.closed?

Array(@top_comment_in_favor) + Array(@top_comment_against)
end

def interleave_remaining_comments(comments_in_favor, comments_against)
interleaved = []
max_length = [comments_in_favor.size, comments_against.size].max

max_length.times do |i|
interleaved << comments_in_favor[i] if comments_in_favor[i]
interleaved << comments_against[i] if comments_against[i]
end

interleaved
def comments_in_favor_query
@comments_in_favor_query ||= SortedComments.new(model, order_by: order, alignment: 1, offset: 0)
end

def comments_in_favor
@comments_in_favor ||= model.comments.positive.order(:created_at)
def comments_against_query
@comments_against_query ||= SortedComments.new(model, order_by: order, alignment: -1, offset: 0)
end

def comments_against
@comments_against ||= model.comments.negative.order(:created_at)
def load_mobile_comments
@sorted_comments_query = SortedComments.new(model, order_by: order, offset: 0)
@mobile_comments = @sorted_comments_query.query
@has_more_mobile = @sorted_comments_query.has_more?
end

def set_column_variables(top_comment, comments, icon_name, title)
# rubocop:disable Metrics/ParameterLists
def set_column_variables(top_comment, comments, icon_name, title, alignment, has_more)
@top_comment = top_comment
@comments = comments
@icon_name = icon_name
@title = title
@alignment = alignment
@has_more = has_more
end
# rubocop:enable Metrics/ParameterLists
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,33 @@ class CommentsController < Decidim::Comments::ApplicationController
before_action :set_commentable, except: [:destroy, :update]
before_action :ensure_commentable!, except: [:destroy, :update]

helper_method :root_depth, :commentable, :order, :reply?, :reload?, :root_comment
helper_method :root_depth, :commentable, :order, :reply?, :reload?, :root_comment, :load_more?, :comments_offset, :alignment

def index
enforce_permission_to(:read, :comment, commentable:)

@comments = SortedComments.for(
@sorted_comments_query = SortedComments.new(
commentable,
order_by: order,
after: params.fetch(:after, 0).to_i
offset: comments_offset,
alignment:
)
@comments = @sorted_comments_query.query
@comments = @comments.reject do |comment|
next if comment.depth < 1
next if !comment.deleted? && !comment.hidden?

comment.commentable.descendants.where(decidim_commentable_type: "Decidim::Comments::Comment").not_hidden.not_deleted.blank?
end
@has_more_comments = @sorted_comments_query.has_more?
@comments_count = commentable.comments_count

respond_to do |format|
format.js do
if reload?
render :reload
elsif load_more?
render :load_more_comments
else
render :index
end
Expand Down Expand Up @@ -187,10 +192,25 @@ def reload?
params.fetch(:reload, 0).to_i == 1
end

def load_more?
params.fetch(:load_more, 0).to_i == 1
end

def comments_offset
params.fetch(:offset, 0).to_i
end

def root_depth
params.fetch(:root_depth, 0).to_i
end

def alignment
value = params.fetch(:alignment, nil)
return nil if value.blank?

value.to_i
end

def commentable_path
return commentable.polymorphic_resource_path({}) if commentable.respond_to?(:polymorphic_resource_path)

Expand Down
6 changes: 6 additions & 0 deletions decidim-comments/app/packs/entrypoints/decidim_comments.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,9 @@ import "stylesheets/comments.scss"
// JavaScript
import "src/decidim/comments/comments"
import "src/decidim/comments/comments_mobile_modal"

// Stimulus controllers
import { definitionsFromContext } from "src/decidim/refactor/support/stimulus"

const context = require.context("src/decidim/comments/controllers", true, /controller\.js$/)
window.Stimulus.load(definitionsFromContext(context))
Loading
Loading