From e005e3f1530291582be8325da72092c3d1ee7129 Mon Sep 17 00:00:00 2001 From: Roman Rizzi Date: Mon, 27 Dec 2021 11:25:37 -0300 Subject: [PATCH] DEV: Create post actions without creating a notification and store custom data. (#15397) I plan to use this in an upcoming discourse-reactions PR, where I want to like a post without notifying the user, so I can instead create a reaction notification. Additionally, we decouple the a11y attributes from the icon itself, which will let us extend the widget's icon without losing them. --- .../app/widgets/default-notification-item.js | 6 +++++- app/services/post_alerter.rb | 4 ++++ lib/post_action_creator.rb | 16 ++++++++++------ spec/components/post_action_creator_spec.rb | 10 ++++++++++ spec/services/post_alerter_spec.rb | 17 +++++++++++++++++ 5 files changed, 46 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/discourse/app/widgets/default-notification-item.js b/app/assets/javascripts/discourse/app/widgets/default-notification-item.js index d9ab91e2ff0..0a7a263f50d 100644 --- a/app/assets/javascripts/discourse/app/widgets/default-notification-item.js +++ b/app/assets/javascripts/discourse/app/widgets/default-notification-item.js @@ -106,7 +106,10 @@ export const DefaultNotificationItem = createWidget( }, icon(notificationName) { - let icon = iconNode(`notification.${notificationName}`); + return iconNode(`notification.${notificationName}`); + }, + + _addA11yAttrsTo(icon, notificationName) { icon.properties.attributes["aria-label"] = I18n.t( `notifications.titles.${notificationName}` ); @@ -131,6 +134,7 @@ export const DefaultNotificationItem = createWidget( let { data } = attrs; let text = emojiUnescape(this.text(notificationName, data)); let icon = this.icon(notificationName, data); + this._addA11yAttrsTo(icon, notificationName); const title = this.notificationTitle(notificationName, data); diff --git a/app/services/post_alerter.rb b/app/services/post_alerter.rb index 292cb2b33d5..f58e94872bc 100644 --- a/app/services/post_alerter.rb +++ b/app/services/post_alerter.rb @@ -473,6 +473,10 @@ class PostAlerter display_username: opts[:display_username] || post.user.username, } + if opts[:custom_data]&.is_a?(Hash) + opts[:custom_data].each { |k, v| notification_data[k] = v } + end + if group = opts[:group] notification_data[:group_id] = group.id notification_data[:group_name] = group.name diff --git a/lib/post_action_creator.rb b/lib/post_action_creator.rb index 31a037844b1..910078766f8 100644 --- a/lib/post_action_creator.rb +++ b/lib/post_action_creator.rb @@ -7,20 +7,21 @@ class PostActionCreator # Shortcut methods for easier invocation class << self - def create(created_by, post, action_key, message: nil, created_at: nil, reason: nil) + def create(created_by, post, action_key, message: nil, created_at: nil, reason: nil, silent: false) new( created_by, post, PostActionType.types[action_key], message: message, created_at: created_at, - reason: reason + reason: reason, + silent: silent ).perform end [:like, :off_topic, :spam, :inappropriate, :bookmark].each do |action| - define_method(action) do |created_by, post| - create(created_by, post, action) + define_method(action) do |created_by, post, silent = false| + create(created_by, post, action, silent: silent) end end [:notify_moderators, :notify_user].each do |action| @@ -40,7 +41,8 @@ class PostActionCreator flag_topic: false, created_at: nil, queue_for_review: false, - reason: nil + reason: nil, + silent: false ) @created_by = created_by @created_at = created_at || Time.zone.now @@ -62,6 +64,8 @@ class PostActionCreator if reason.nil? && @queue_for_review @reason = 'queued_by_staff' end + + @silent = silent end def post_can_act? @@ -113,7 +117,7 @@ class PostActionCreator create_reviewable(result) enforce_rules UserActionManager.post_action_created(post_action) - PostActionNotifier.post_action_created(post_action) + PostActionNotifier.post_action_created(post_action) if !@silent notify_subscribers # agree with other flags diff --git a/spec/components/post_action_creator_spec.rb b/spec/components/post_action_creator_spec.rb index 488b47effad..9d9d2495e6c 100644 --- a/spec/components/post_action_creator_spec.rb +++ b/spec/components/post_action_creator_spec.rb @@ -80,6 +80,16 @@ describe PostActionCreator do expect(notification_data['display_username']).to eq(user.username) expect(notification_data['username2']).to eq(nil) end + + it 'does not create a notification if silent mode is enabled' do + PostActionNotifier.enable + + expect( + PostActionCreator.new(user, post, like_type_id, silent: true).perform.success + ).to eq(true) + + expect(Notification.where(notification_type: Notification.types[:liked]).exists?).to eq(false) + end end context "flags" do diff --git a/spec/services/post_alerter_spec.rb b/spec/services/post_alerter_spec.rb index 9e03a0ba0cc..a33cb0df9e0 100644 --- a/spec/services/post_alerter_spec.rb +++ b/spec/services/post_alerter_spec.rb @@ -1869,4 +1869,21 @@ describe PostAlerter do expect(email).to eq(last_email) end end + + describe 'storing custom data' do + let(:custom_data) { 'custom_string' } + + it 'stores custom data inside a notification' do + PostAlerter.new.create_notification( + admin, + Notification.types[:liked], + post, + custom_data: { custom_key: custom_data } + ) + + liked_notification = Notification.where(notification_type: Notification.types[:liked]).last + + expect(liked_notification.data_hash[:custom_key]).to eq(custom_data) + end + end end