From f85d5d469233884efb18b610fdf7e64de3cd5255 Mon Sep 17 00:00:00 2001 From: Pablo Brasero Date: Mon, 20 Apr 2026 15:26:48 +0100 Subject: [PATCH] Implement web notifications for changeset comments --- app/models/user_notifications.rb | 25 ++++++++- .../notifications/_changeset_comment.html.erb | 53 +++++++++++++++++++ config/locales/en.yml | 4 ++ .../changeset_comment_view_test.rb | 50 +++++++++++++++++ test/system/web_notifications_test.rb | 29 ++++++++++ 5 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 app/views/notifications/_changeset_comment.html.erb create mode 100644 test/controllers/notifications/changeset_comment_view_test.rb diff --git a/app/models/user_notifications.rb b/app/models/user_notifications.rb index b1ef8881e..6ecc98b4b 100644 --- a/app/models/user_notifications.rb +++ b/app/models/user_notifications.rb @@ -29,9 +29,32 @@ class UserNotifications end end + class ChangesetCommentNotification < Notification + delegate :changeset, :to => :record + delegate :id, :to => :changeset, :prefix => true + + def changeset_summary + changeset.comment + end + + def commenter + record.author + end + + def comment_id + record.id + end + + def comment_body + record.body + end + end + include Enumerable - LISTABLE_NOTIFICATIONS = [].freeze + LISTABLE_NOTIFICATIONS = %w[ + ChangesetCommentNotifier::Notification + ].freeze def initialize(user) @user = user diff --git a/app/views/notifications/_changeset_comment.html.erb b/app/views/notifications/_changeset_comment.html.erb new file mode 100644 index 000000000..8b54fbb9d --- /dev/null +++ b/app/views/notifications/_changeset_comment.html.erb @@ -0,0 +1,53 @@ +<%# locals: (notification:) %> + +
+
+

+ <%= link_to( + t(".headline"), + changeset_path( + notification.changeset, + :anchor => "c#{notification.comment_id}" + ) + ) %> +

+

<%= friendly_date_ago(notification.timestamp) %>

+
+ +
+
+ <%= link_to( + user_thumbnail(notification.commenter, :class => "img-fluid"), + user_url(notification.commenter), + :target => "_blank", :rel => "noopener" + ) %> +
+
+

+ <% if notification.changeset_summary %> + <%= t( + ".description_with_summary_html", + :commenter_name_with_link => link_to( + notification.commenter.display_name, + notification.commenter + ), + :changeset_id_with_link => link_to("##{notification.changeset_id}", notification.changeset), + :changeset_summary => notification.changeset_summary + ) %> + <% else %> + <%= t( + ".description_without_summary_html", + :commenter_name_with_link => link_to( + notification.commenter.display_name, + notification.commenter + ), + :changeset_id_with_link => link_to("##{notification.changeset_id}", notification.changeset) + ) %> + <% end %> +

+
+ <%= notification.comment_body.to_html %> +
+
+
+
diff --git a/config/locales/en.yml b/config/locales/en.yml index eee55bbd8..81cc721ae 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -611,6 +611,10 @@ en: no_notifications: You have no notifications at the moment point_to_preferences_html: "You can adjust how you receive notifications in %{link}." link_text: the preferences section + changeset_comment: + headline: Changeset comment + description_with_summary_html: "User %{commenter_name_with_link} left a comment on changeset %{changeset_id_with_link} (\"%{changeset_summary}\")" + description_without_summary_html: "User %{commenter_name_with_link} left a comment on changeset %{changeset_id_with_link}" diary_entries: new: title: New Diary Entry diff --git a/test/controllers/notifications/changeset_comment_view_test.rb b/test/controllers/notifications/changeset_comment_view_test.rb new file mode 100644 index 000000000..8a82d0ea0 --- /dev/null +++ b/test/controllers/notifications/changeset_comment_view_test.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require "test_helper" + +module Notifications + class ChangesetCommentViewTest < ActionView::TestCase + def test_render_without_summary + changeset_comment = build_stubbed( + :changeset_comment, + :body => "Insightful comment" + ) + notification = build_stubbed(:notification, :record => changeset_comment) + notification_wrapper = UserNotifications::ChangesetCommentNotification.new(notification) + + render "notifications/changeset_comment", :notification => notification_wrapper + + assert_dom ".user-notification" do + assert_dom "h2", "Changeset comment" + assert_not_dom "p", /\("/ + assert_dom "time", "less than 1 minute ago" + assert_dom "blockquote", "Insightful comment" + end + end + + def test_render_with_summary + summary_tag = build_stubbed( + :changeset_tag, + :k => "comment", + :v => "This is a summary" + ) + changeset = build_stubbed(:changeset, :changeset_tags => [summary_tag]) + changeset_comment = build_stubbed( + :changeset_comment, + :changeset => changeset, + :body => "Insightful comment" + ) + notification = build_stubbed(:notification, :record => changeset_comment) + notification_wrapper = UserNotifications::ChangesetCommentNotification.new(notification) + + render "notifications/changeset_comment", :notification => notification_wrapper + + assert_dom ".user-notification" do + assert_dom "h2", "Changeset comment" + assert_dom "time", "less than 1 minute ago" + assert_dom ".event-description", /\("This is a summary"\)/ + assert_dom "blockquote", "Insightful comment" + end + end + end +end diff --git a/test/system/web_notifications_test.rb b/test/system/web_notifications_test.rb index 010bc85e9..187a4c8a4 100644 --- a/test/system/web_notifications_test.rb +++ b/test/system/web_notifications_test.rb @@ -13,4 +13,33 @@ class WebNotificationsTest < ApplicationSystemTestCase assert_text "Notifications" assert_text "You have no notifications" end + + test "read latest notifications" do + changeset_author = create(:user) + commenter = create(:user, :display_name => "Commenter") + setup_changeset_comment( + :changeset_author => changeset_author, + :commenter => commenter + ) + + sign_in_as(changeset_author) + + click_on changeset_author.display_name + click_on "My Notifications" + + assert_text "Notifications" + assert_text "Changeset comment" + assert_text "User Commenter left a comment on changeset" + end + + private + + def setup_changeset_comment(changeset_author:, commenter:, comment_attrs: {}) + changeset = create(:changeset, :user => changeset_author) + create(:changeset_subscription, :changeset => changeset, :subscriber => changeset_author) + + comment = create(:changeset_comment, :changeset => changeset, :author => commenter, **comment_attrs) + create(:changeset_subscription, :changeset => changeset, :subscriber => commenter) + ChangesetCommentNotifier.with(:record => comment).deliver + end end -- 2.47.3