From 4ff55df2e0a4e7d7d8a490c082cb4c81d53dcdaf Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Tue, 29 Apr 2025 20:30:05 +0200 Subject: [PATCH] Create system comments on events --- app/helpers/comments_helper.rb | 2 +- app/models/card/eventable.rb | 6 +- app/models/card/eventable/system_commenter.rb | 63 +++++++++++++++++++ app/models/comment/eventable.rb | 4 ++ app/views/cards/_comments.html.erb | 4 +- test/models/card/closeable_test.rb | 4 ++ 6 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 app/models/card/eventable/system_commenter.rb diff --git a/app/helpers/comments_helper.rb b/app/helpers/comments_helper.rb index 122e8d551..cda77af9c 100644 --- a/app/helpers/comments_helper.rb +++ b/app/helpers/comments_helper.rb @@ -1,6 +1,6 @@ module CommentsHelper def new_comment_placeholder(card) - if card.creator == Current.user && card.messages.comments.empty? + if card.creator == Current.user && card.comments.empty? "Next, add some notes, context, pictures, or video about this…" else "Type your comment…" diff --git a/app/models/card/eventable.rb b/app/models/card/eventable.rb index 5fd0759fb..ec5059eaa 100644 --- a/app/models/card/eventable.rb +++ b/app/models/card/eventable.rb @@ -12,7 +12,7 @@ module Card::Eventable def event_was_created(event) transaction do - # find_or_capture_event_summary.events << event + create_system_comment_for(event) touch(:last_active_at) end end @@ -43,4 +43,8 @@ module Card::Eventable track_event "card_title_changed", particulars: { old_title: title_before_last_save, new_title: title } end end + + def create_system_comment_for(event) + SystemCommenter.new(self, event).comment + end end diff --git a/app/models/card/eventable/system_commenter.rb b/app/models/card/eventable/system_commenter.rb new file mode 100644 index 000000000..6eec7089f --- /dev/null +++ b/app/models/card/eventable/system_commenter.rb @@ -0,0 +1,63 @@ +class Card::Eventable::SystemCommenter + attr_reader :card, :event + + def initialize(card, event) + @card, @event = card, event + end + + def comment + return unless comment_body.present? + + if comment = find_replaceable_system_comment + comment.update! body: comment_body + else + card.comments.create! creator: User.system, body: comment_body + end + end + + private + REPLACEABLE_EVENTS = [ + %w(card_assigned card_unassigned), + %w(card_staged card_unstaged), + %w(card_due_date_added card_due_date_changed card_due_date_removed) + ] + + def comment_body + case event.action + when "card_assigned" + "Assigned to #{card.assignees.pluck(:name).to_sentence}." + when "card_unassigned" + if card.assignees.empty? + "Unassigned from #{event.assignees.pluck(:name).to_sentence}." + else + "Assigned to #{card.assignees.pluck(:name).to_sentence}." + end + when "card_staged" + "#{event.creator.name} moved this to '#{event.stage_name}'." + when "card_closed" + "Closed by #{ event.creator.name }" + when "card_unstaged" + "#{event.creator.name} removed this from '#{event.stage_name}'." + when "card_due_date_added" + "#{event.creator.name} set due date to #{event.particulars.dig('particulars', 'due_date').to_date.strftime('%B %-d')}." + when "card_due_date_changed" + "#{event.creator.name} changed due date to #{event.particulars.dig('particulars', 'due_date').to_date.strftime('%B %-d')}." + when "card_due_date_removed" + "#{event.creator.name} removed the date." + when "card_title_changed" + "#{event.creator.name} changed title from '#{event.particulars.dig('particulars', 'old_title')}' to '#{event.particulars.dig('particulars', 'new_title')}'." + end + end + + def find_replaceable_system_comment + previous_comment, previous_event = card.comments.last, card.events[-2] + if previous_comment&.creator&.system? && replaceable_event?(previous_event, event) + previous_comment + end + end + + def replaceable_event?(candidate_event, replacement_event) + candidate_event && replacement_event && + (candidate_event.action == replacement_event.action || REPLACEABLE_EVENTS.find { |related_actions| related_actions.include?(candidate_event.action) && related_actions.include?(replacement_event.action) }) + end +end diff --git a/app/models/comment/eventable.rb b/app/models/comment/eventable.rb index 4e90777e0..f3a108505 100644 --- a/app/models/comment/eventable.rb +++ b/app/models/comment/eventable.rb @@ -12,6 +12,10 @@ module Comment::Eventable end private + def should_track_event? + !creator.system? + end + def track_creation track_event("created", collection: card.collection) end diff --git a/app/views/cards/_comments.html.erb b/app/views/cards/_comments.html.erb index fd4829974..7fc6a977a 100644 --- a/app/views/cards/_comments.html.erb +++ b/app/views/cards/_comments.html.erb @@ -1,6 +1,6 @@ <% if card.messages.comments.any? %>
- - <%= pluralize(card.messages.comments.count, "comment") %> + + <%= pluralize(card.comments.count, "comment") %>
<% end %> diff --git a/test/models/card/closeable_test.rb b/test/models/card/closeable_test.rb index 008058866..7f8b4f209 100644 --- a/test/models/card/closeable_test.rb +++ b/test/models/card/closeable_test.rb @@ -1,6 +1,10 @@ require "test_helper" class Card::CloseableTest < ActiveSupport::TestCase + setup do + Current.session = sessions(:david) + end + test "closed scope" do assert_equal [ cards(:shipping) ], Card.closed assert_not_includes Card.open, cards(:shipping)