chore: Get all notification API improvments (#8549)

Co-authored-by: Sojan Jose <sojan@chatwoot.com>
This commit is contained in:
Muhsin Keloth
2024-01-17 09:02:18 +05:30
committed by GitHub
parent e67f8824d9
commit 818424259f
10 changed files with 176 additions and 31 deletions

View File

@@ -2,8 +2,6 @@ class NotificationBuilder
pattr_initialize [:notification_type!, :user!, :account!, :primary_actor!, :secondary_actor]
def perform
return unless user_subscribed_to_notification?
build_notification
end
@@ -16,7 +14,7 @@ class NotificationBuilder
def user_subscribed_to_notification?
notification_setting = user.notification_settings.find_by(account_id: account.id)
# added for the case where an assignee might be removed from the account but remains in conversation
return if notification_setting.blank?
return false if notification_setting.blank?
return true if notification_setting.public_send("email_#{notification_type}?")
return true if notification_setting.public_send("push_#{notification_type}?")
@@ -25,6 +23,9 @@ class NotificationBuilder
end
def build_notification
# Create conversation_creation notification only if user is subscribed to it
return if notification_type == 'conversation_creation' && !user_subscribed_to_notification?
user.notifications.create!(
notification_type: notification_type,
account: account,

View File

@@ -7,9 +7,9 @@ class Api::V1::Accounts::NotificationsController < Api::V1::Accounts::BaseContro
before_action :set_current_page, only: [:index]
def index
@unread_count = current_user.notifications.where(account_id: current_account.id, read_at: nil).count
@count = notifications.count
@notifications = notifications.page(@current_page).per(RESULTS_PER_PAGE)
@unread_count = notification_finder.unread_count
@notifications = notification_finder.perform
@count = @notifications.count
end
def read_all
@@ -35,7 +35,7 @@ class Api::V1::Accounts::NotificationsController < Api::V1::Accounts::BaseContro
end
def unread_count
@unread_count = current_user.notifications.where(account_id: current_account.id, read_at: nil).count
@unread_count = notification_finder.unread_count
render json: @unread_count
end
@@ -61,7 +61,7 @@ class Api::V1::Accounts::NotificationsController < Api::V1::Accounts::BaseContro
@current_page = params[:page] || 1
end
def notifications
@notifications ||= current_user.notifications.where(account_id: current_account.id)
def notification_finder
@notification_finder ||= NotificationFinder.new(Current.user, Current.account, params)
end
end

View File

@@ -0,0 +1,47 @@
class NotificationFinder
attr_reader :current_user, :current_account, :params
RESULTS_PER_PAGE = 15
def initialize(current_user, current_account, params = {})
@current_user = current_user
@current_account = current_account
@params = params
set_up
end
def perform
notifications
end
def unread_count
@notifications.where(read_at: nil).count
end
def count
@notifications.count
end
private
def set_up
find_all_notifications
filter_by_status
end
def find_all_notifications
@notifications = current_user.notifications.where(account_id: @current_account.id)
end
def filter_by_status
@notifications = @notifications.where('snoozed_until > ?', DateTime.now.utc) if params[:status] == 'snoozed'
end
def current_page
params[:page] || 1
end
def notifications
@notifications.page(current_page).per(RESULTS_PER_PAGE).order(last_activity_at: :desc)
end
end

View File

@@ -7,10 +7,11 @@ class Notification::RemoveDuplicateNotificationJob < ApplicationJob
user_id = notification.user_id
primary_actor_id = notification.primary_actor_id
# Find older notifications with the same user and primary_actor_id, excluding the new one
# Find older notifications with the same user and primary_actor_id
duplicate_notifications = Notification.where(user_id: user_id, primary_actor_id: primary_actor_id)
.where.not(id: notification.id)
.order(created_at: :desc)
duplicate_notifications.each(&:destroy)
# Skip the first one (the latest notification) and destroy the rest
duplicate_notifications.offset(1).each(&:destroy)
end
end

View File

@@ -8,9 +8,9 @@ class BaseListener
def extract_notification_and_account(event)
notification = event.data[:notification]
notifications_meta = notification.user.notifications_meta(notification.account_id)
unread_count = notifications_meta[:unread_count]
count = notifications_meta[:count]
notification_finder = NotificationFinder.new(notification.user, notification.account)
unread_count = notification_finder.unread_count
count = notification_finder.count
[notification, notification.account, unread_count, count]
end

View File

@@ -47,10 +47,6 @@ class Notification < ApplicationRecord
after_create_commit :process_notification_delivery, :dispatch_create_event
after_destroy_commit :dispatch_destroy_event
# TODO: Get rid of default scope
# https://stackoverflow.com/a/1834250/939299
default_scope { order(id: :desc) }
PRIMARY_ACTORS = ['Conversation'].freeze
def push_event_data
@@ -122,17 +118,24 @@ class Notification < ApplicationRecord
private
def process_notification_delivery
Notification::PushNotificationJob.perform_later(self)
Notification::PushNotificationJob.perform_later(self) if user_subscribed_to_notification?('push')
# Should we do something about the case where user subscribed to both push and email ?
# In future, we could probably add condition here to enqueue the job for 30 seconds later
# when push enabled and then check in email job whether notification has been read already.
Notification::EmailNotificationJob.perform_later(self)
Notification::EmailNotificationJob.perform_later(self) if user_subscribed_to_notification?('email')
# Remove duplicate notifications
Notification::RemoveDuplicateNotificationJob.perform_later(self)
end
def user_subscribed_to_notification?(delivery_type)
notification_setting = user.notification_settings.find_by(account_id: account.id)
return false if notification_setting.blank?
# Check if the user has subscribed to the specified type of notification
notification_setting.public_send("#{delivery_type}_#{notification_type}?")
end
def dispatch_create_event
Rails.configuration.dispatcher.dispatch(NOTIFICATION_CREATED, Time.zone.now, notification: self)
end

View File

@@ -153,13 +153,6 @@ class User < ApplicationRecord
mutations_from_database.changed?('email')
end
def notifications_meta(account_id)
{
unread_count: notifications.where(account_id: account_id, read_at: nil).count,
count: notifications.where(account_id: account_id).count
}
end
private
def remove_macros