Refactor user_notifications controller, remove unused code [SCI-8207]

This commit is contained in:
Oleksii Kriuchykhin 2023-04-06 14:57:00 +02:00
parent 0c76d7a9b1
commit 60579465ab
20 changed files with 56 additions and 303 deletions

View file

@ -1,21 +0,0 @@
(function() {
'use strict';
$('.btn-more-notifications')
.on('ajax:success', function(e, data) {
var list = $('.notifications-list');
var moreBtn = $('.btn-more-notifications');
if (data.html) {
// Remove button if all notifications are shown
if (data.results_number < data.per_page) {
moreBtn.remove();
// Otherwise update reference
} else {
moreBtn.attr('href', data.more_notifications_url);
}
$(list).append(data.html);
} else if (data.results_number < 1) {
moreBtn.remove();
}
});
}());

View file

@ -1,22 +1,6 @@
# frozen_string_literal: true
class SystemNotificationsController < ApplicationController
before_action :prepare_notifications, only: :index
def index
respond_to do |format|
format.json do
render json: {
more_url: @system_notifications.fetch(:more_notifications_url),
html: render_to_string(
partial: 'list.html.erb', locals: @system_notifications
)
}
end
format.html
end
end
def show
render json: current_user.system_notifications.modals
.find_by_id(params[:id]) || {}

View file

@ -1,71 +1,46 @@
# frozen_string_literal: true
class UserNotificationsController < ApplicationController
layout 'main'
def index
@last_notification_id = params[:from].to_i || 0
@per_page = Constants::ACTIVITY_AND_NOTIF_SEARCH_LIMIT
@notifications =
UserNotification.last_notifications(@current_user,
@last_notification_id,
@per_page + 1)
@more_notifications_url = ''
@overflown = @notifications.length > @per_page
@notifications =
UserNotification.last_notifications(@current_user,
@last_notification_id,
@per_page)
if @notifications.count > 0
@more_notifications_url = url_for(
controller: 'user_notifications',
action: 'index',
format: :json,
from: @notifications.last.id
)
end
page = (params[:page] || 1).to_i
notifications = load_notifications.page(page).per(Constants::INFINITE_SCROLL_LIMIT).without_count
respond_to do |format|
format.html
format.json do
render json: {
per_page: @per_page,
results_number: @notifications.length,
more_notifications_url: @more_notifications_url,
html: render_to_string(partial: 'list.html.erb')
notifications: notifications,
next_page: notifications.next_page
}
end
end
UserNotification.seen_by_user(current_user)
end
def recent_notifications
@recent_notifications = UserNotification.recent_notifications(current_user)
private
respond_to do |format|
format.json do
render json: {
html: render_to_string(
partial: 'recent_notifications.html.erb'
)
}
def load_notifications
user_notifications = current_user.notifications
.select(:id, :type_of, :title, :message, :created_at, 'user_notifications.checked')
system_notifications = current_user.system_notifications
.select(
:id,
'2 AS type_of',
:title,
'description AS message',
:created_at,
'CASE WHEN seen_at IS NULL THEN false ELSE true END AS checked'
)
notifications =
case params[:type]
when 'message'
user_notifications
when 'system'
Notification.from("(#{system_notifications.to_sql}) AS notifications")
else
Notification.from(
"((#{user_notifications.to_sql}) UNION ALL (#{system_notifications.to_sql})) AS notifications"
)
end
end
UserNotification.seen_by_user(current_user)
end
def unseen_notification
@number = UserNotification.unseen_notification_count(current_user)
respond_to do |format|
format.json do
render json: {
notificationNmber: @number
}
end
end
notifications.order(created_at: :desc)
end
end

View file

@ -6,17 +6,17 @@
</div>
<div class="sci--navigation--notificaitons-flyout-tabs">
<div class="sci--navigation--notificaitons-flyout-tab"
@click="activeTab = 'all'"
@click="setActiveTab('all')"
:class="{'active': activeTab == 'all'}">
{{ i18n.t('nav.notifications.all') }}
</div>
<div class="sci--navigation--notificaitons-flyout-tab"
@click="activeTab = 'message'"
@click="setActiveTab('message')"
:class="{'active': activeTab == 'message'}">
{{ i18n.t('nav.notifications.message') }}
</div>
<div class="sci--navigation--notificaitons-flyout-tab"
@click="activeTab = 'system'"
@click="setActiveTab('system')"
:class="{'active': activeTab == 'system'}">
{{ i18n.t('nav.notifications.system') }}
</div>
@ -26,11 +26,11 @@
<div class="sci-navigation--notificaitons-flyout-subtitle" v-if="todayNotifications.length" >
{{ i18n.t('nav.notifications.today') }}
</div>
<NotificationItem v-for="notification in todayNotifications" :key="notification.id" :notification="notification" />
<NotificationItem v-for="notification in todayNotifications" :key="notification.type_of + '-' + notification.id" :notification="notification" />
<div class="sci-navigation--notificaitons-flyout-subtitle" v-if="olderNotifications.length" >
{{ i18n.t('nav.notifications.older') }}
</div>
<NotificationItem v-for="notification in olderNotifications" :key="notification.id" :notification="notification" />
<NotificationItem v-for="notification in olderNotifications" :key="notification.type_of + '-' + notification.id" :notification="notification" />
</div>
</div>
</template>
@ -54,32 +54,31 @@ export default {
nextPage: 2
}
},
mounted() {
// fake notifications
this.notifications = [
{ id: 'N1', type_of: 'assignment', title: 'Project assigned', created_at: new Date(), message: "Project: <a href=\"/projects/1\">test</a>" },
{ id: 'SN1', type_of: 'system', title: 'New Scinote Version', created_at: new Date(), url: '/system_notificiatons' },
{ id: 'N2',type_of: 'deliver', title: 'New report', created_at: (new Date('2022-12-17T03:24:00')), message: "Report: <a href=\"/reports/1\">test</a>" }
]
created() {
this.loadNotifications();
},
computed: {
filteredNotifications() {
switch(this.activeTab) {
case 'all':
return this.notifications;
case 'system':
return this.notifications.filter(n => n.type_of === 'system');
case 'message':
return this.notifications.filter(n => n.type_of !== 'system');
}
this.loadNotifications();
},
todayNotifications() {
let startOfDay = (new Date()).setUTCHours(0, 0, 0, 0);
return this.filteredNotifications.filter(n => n.created_at >= startOfDay);
return this.notifications.filter(n => moment(n.created_at) >= startOfDay);
},
olderNotifications() {
let startOfDay = (new Date()).setUTCHours(0, 0, 0, 0);
return this.filteredNotifications.filter(n => n.created_at < startOfDay);
return this.notifications.filter(n => moment(n.created_at) < startOfDay);
}
},
methods: {
setActiveTab(selection) {
this.activeTab = selection;
this.loadNotifications();
},
loadNotifications() {
$.getJSON(this.notificationsUrl, { type: this.activeTab }, (result) => {
this.notifications = result.notifications;
});
}
}
}

View file

@ -52,7 +52,7 @@
<button class="btn btn-light icon-btn" data-toggle="dropdown" @click="notificationsOpened = !notificationsOpened">
<i class="fas fa-bell"></i>
</button>
<NotificationsFlyout v-if="notificationsOpened" :notifications_url="notificationsUrl" @close="notificationsOpened = false" />
<NotificationsFlyout v-if="notificationsOpened" :notifications-url="notificationsUrl" @close="notificationsOpened = false" />
</div>
<div v-if="user" class="dropdown">
<div class="sci--navigation--top-menu-user" data-toggle="dropdown">
@ -86,7 +86,8 @@
NotificationsFlyout
},
props: {
url: String
url: String,
notificationsUrl: String
},
data() {
return {
@ -100,8 +101,7 @@
settingsMenu: null,
userMenu: null,
showAboutModal: false,
notificationsOpened: false,
notificationsUrl: 'test'
notificationsOpened: false
}
},
created() {

View file

@ -7,11 +7,6 @@ class Notification < ApplicationRecord
enum type_of: Extends::NOTIFICATIONS_TYPES
def already_seen(user)
UserNotification.where(notification: self, user: user)
.pick(:checked)
end
def create_user_notification(user)
return if user == generator_user
return unless can_send_to_user?(user)

View file

@ -8,26 +8,6 @@ class UserNotification < ApplicationRecord
after_create :send_email
def self.last_notifications(
user,
last_notification_id = nil,
per_page = Constants::ACTIVITY_AND_NOTIF_SEARCH_LIMIT
)
last_notification_id = Constants::INFINITY if last_notification_id < 1
Notification.joins(:user_notifications)
.where('user_notifications.user_id = ?', user.id)
.where('notifications.id < ?', last_notification_id)
.order(created_at: :DESC)
.limit(per_page)
end
def self.recent_notifications(user)
Notification.joins(:user_notifications)
.where('user_notifications.user_id = ?', user.id)
.order(created_at: :DESC)
.limit(Constants::ACTIVITY_AND_NOTIF_SEARCH_LIMIT)
end
def self.unseen_notification_count(user)
where('user_id = ? AND checked = false', user.id).count
end

View file

@ -1,3 +1,3 @@
<div id="sciNavigationTopMenuContainer" data-turbolinks-permanent data-behaviour="vue">
<top-menu-container url="<%= top_menu_navigations_path %>"/>
<top-menu-container url="<%= top_menu_navigations_path %>" notifications-url="<%= notifications_path %>" />
</div>

View file

@ -1,19 +0,0 @@
<% @notifications.each do |notification| %>
<li class="notification <%= 'unseen' unless notification.already_seen(current_user) %>">
<div class="row">
<div class="col-xs-3 col-md-1">
<span style="display: none;" data-hook="user-notification-list-item"></span>
<%= render partial: "user_notifications/icons/#{notification.type_of}",
locals: { notification: notification },
formats: [:html] %>
</div>
<div class="col-xs-9 col-md-11">
<strong><%= sanitize_input(notification.title) %></strong> <br>
<% if notification.deliver? %>
<%= I18n.t('notifications.deliver.download_text') %></br>
<% end %>
<%= l(notification.created_at, format: :full) %> | <%= sanitize_input(notification.message) %>
</div>
</div>
</li>
<% end %>

View file

@ -1,19 +0,0 @@
<% @recent_notifications.each do |notification| %>
<li class="notification <%= 'unseen' unless notification.already_seen(current_user) %>">
<div class="row">
<div class="col-xs-2">
<%= render partial: "user_notifications/icons/#{notification.type_of}",
locals: { notification: notification },
formats: [:html] %>
</div>
<div class="col-xs-10">
<strong><%= sanitize_input(notification.title) %></strong> <br>
<% if notification.deliver? %>
<%= I18n.t('notifications.deliver.download_text') %></br>
<% end %>
<%= l(notification.created_at, format: :full) %> | <%= sanitize_input(notification.message) %>
</div>
</div>
<li>
<% end %>

View file

@ -1,5 +0,0 @@
<div class="text-center">
<span class="assignment">
<i class="fas fa-newspaper"></i>
</span>
</div>

View file

@ -1,5 +0,0 @@
<div class="text-center">
<span class="deliver">
<i class="fas fa-truck"></i>
</span>
</div>

View file

@ -1,5 +0,0 @@
<div class="text-center">
<span class="deliver-error">
<i class="fas fa-truck"></i>
</span>
</div>

View file

@ -1,5 +0,0 @@
<div class="text-center">
<span class='global-avatar-container'>
<%= image_tag avatar_path(notification.generator_user, :icon_small), class: 'avatar img-circle' %>
<span>
</div>

View file

@ -1,5 +0,0 @@
<div class="text-center">
<span class="system-message">
<i class="fas fa-chess-rook" aria-hidden="true"></i>
</span>
</div>

View file

@ -1,29 +0,0 @@
<% provide(:head_title, t('notifications.title')) %>
<div class="content-pane">
<div class="notifications-container">
<div class="notifications-header">
<span><%= t('notifications.title') %></span><span class="pull-right"><%= link_to t('nav.user.settings'), preferences_path %></span>
</div>
<div class="notifications-body">
<ul class="notifications-list">
<% if @notifications.count > 0 %>
<%= render 'list', notifications: @notifications %>
<% else %>
<li class="notification no-notifications">
<em><%= t('notifications.no_notifications') %></em>
</li>
<% end %>
</ul>
</div>
<% if @overflown %>
<div class="text-center">
<a class="btn btn-default btn-more-notifications" href="<%= @more_notifications_url %>" data-remote="true">
<span><%= t('notifications.show_more') %></span>
</a>
</div>
<% end %>
</div>
</div>
<%= javascript_include_tag("notifications") %>

View file

@ -166,16 +166,6 @@ Rails.application.routes.draw do
end
# Notifications
get 'users/:id/recent_notifications',
to: 'user_notifications#recent_notifications',
as: 'recent_notifications',
defaults: { format: 'json' }
get 'users/:id/unseen_notification',
to: 'user_notifications#unseen_notification',
as: 'unseen_notification',
defaults: { format: 'json' }
get 'users/notifications',
to: 'user_notifications#index',
as: 'notifications'

View file

@ -1,4 +0,0 @@
# notifications
get '/recent_notifications', to: 'notifications#recent_notifications'
get '/unread_notifications_count',
to: 'notifications#unread_notifications_count'

View file

@ -74,45 +74,4 @@ describe SystemNotification do
end
end
end
describe 'Methods' do
let(:user) { create :user }
let(:notifcation_one) { create :system_notification }
let(:notifcation_two) { create :system_notification, title: 'Special one' }
before do
create :user_system_notification,
user: user,
system_notification: notifcation_one
create :user_system_notification,
user: user,
system_notification: notifcation_two
end
it 'get last notifications without search' do
result = SystemNotification.last_notifications(user)
expect(result.length).to eq 2
expect(result.first).to respond_to(
:id,
:title,
:description,
:last_time_changed_at,
:seen_at,
:read_at
)
end
it 'get last notifications with search' do
result = SystemNotification.last_notifications(user, 'Special one')
expect(result.length).to eq 1
expect(result.first).to respond_to(
:id,
:title,
:description,
:last_time_changed_at,
:seen_at,
:read_at
)
expect(result.first.title).to eq 'Special one'
end
end
end

View file

@ -35,18 +35,6 @@ describe UserNotification, type: :model do
end
end
describe '#recent_notifications' do
let(:notifcation_one) { create :notification }
let(:notifcation_two) { create :notification }
it 'returns a list of notifications ordered by created_at DESC' do
create :user_notification, user: user, notification: notifcation_one
create :user_notification, user: user, notification: notifcation_two
notifications = UserNotification.recent_notifications(user)
expect(notifications).to eq [notifcation_two, notifcation_one]
end
end
describe '#seen_by_user' do
let!(:notification) { create :notification }
let!(:user_notification_one) do