Merge pull request #1514 from biosistemika/features/system-notifications

Features/system notifications
This commit is contained in:
Miha Mencin 2019-02-21 16:38:58 +01:00 committed by GitHub
commit bcd0b433b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 60 additions and 75 deletions

View file

@ -113,6 +113,7 @@
button button
.on('click', function() { .on('click', function() {
noRecentText.hide(); noRecentText.hide();
$('.dropdown-system-notifications .system-notification').remove();
$.ajax({ $.ajax({
url: button.attr('data-href'), url: button.attr('data-href'),
type: 'GET', type: 'GET',
@ -120,12 +121,6 @@
beforeSend: animateSpinner($('.system-notifications-dropdown-header'), true), beforeSend: animateSpinner($('.system-notifications-dropdown-header'), true),
success: function(data) { success: function(data) {
var ul = $('.dropdown-system-notifications'); var ul = $('.dropdown-system-notifications');
// After closing system notification modal release system notifications dropdown
$('#manage-module-system-notification-modal').on('hidden.bs.modal', function() {
setTimeout(function() {
$('.dropdown.system-notifications')[0].dataset.closable = true;
}, 100);
});
$('.system-notifications-dropdown-header') $('.system-notifications-dropdown-header')
.nextAll('.system-notification') .nextAll('.system-notification')
.remove(); .remove();
@ -136,7 +131,7 @@
noRecentText.show(); noRecentText.show();
} }
bindSystemNotificationAjax(); bindSystemNotificationAjax();
SystemNotificationsMarkAsSeen('.dropdown-system-notifications'); SystemNotificationsMarkAsSeen();
} }
}); });
$('#count-system-notifications').hide(); $('#count-system-notifications').hide();
@ -146,15 +141,5 @@
// init // init
loadDropdownSystemNotifications(); loadDropdownSystemNotifications();
$('.dropdown-system-notifications').scroll(function() {
SystemNotificationsMarkAsSeen('.dropdown-system-notifications');
});
loadUnseenNotificationsNumber('system-notifications', '.fa-gift'); loadUnseenNotificationsNumber('system-notifications', '.fa-gift');
// Override dropdown menu closing action while system notification modal open
$('.dropdown.system-notifications').on('hide.bs.dropdown', function() {
if (this.dataset.closable === 'false') {
return false;
}
return true;
});
})(); })();

View file

@ -1,18 +1,9 @@
'use strict'; 'use strict';
// update selected notiifcations // update selected notiifcations
function SystemNotificationsMarkAsSeen(container = window) { function SystemNotificationsMarkAsSeen() {
var WindowSize = $(container).height(); if ($('.system-notification[data-new="1"]').length > 0) {
var NotificationsToUpdate = []; $.post('/system_notifications/mark_as_seen');
_.each($('.system-notification[data-new="1"]'), function(el) {
var NotificationTopPosition = el.getBoundingClientRect().top;
if (NotificationTopPosition > 0 && NotificationTopPosition < WindowSize) {
NotificationsToUpdate.push(el.dataset.systemNotificationId);
el.dataset.new = 0;
}
});
if (NotificationsToUpdate.length > 0) {
$.post('/system_notifications/mark_as_seen', { notifications: JSON.stringify(NotificationsToUpdate) });
} }
} }
@ -27,13 +18,15 @@ function bindSystemNotificationAjax() {
$('.modal-system-notification') $('.modal-system-notification')
.on('ajax:success', function(ev, data) { .on('ajax:success', function(ev, data) {
var SystemNotification = $('.system-notification[data-system-notification-id=' + data.id + ']')[0]; var SystemNotification = $('.system-notification[data-system-notification-id=' + data.id + ']');
SystemNotificationModalBody.html(data.modal_body); SystemNotificationModalBody.html(data.modal_body);
SystemNotificationModalTitle.text(data.modal_title); SystemNotificationModalTitle.text(data.modal_title);
$('.dropdown.system-notifications')[0].dataset.closable = false; $('.dropdown.system-notifications').removeClass('open');
// Open modal // Open modal
SystemNotificationModal.modal('show'); SystemNotificationModal.modal('show');
if (SystemNotification.dataset.unread === '1') { if (SystemNotification[0].dataset.unread === '1') {
$.each(SystemNotification, (index, e) => { e.dataset.unread = '0'; });
SystemNotification.find('.status-icon').addClass('seen');
$.post('/system_notifications/' + data.id + '/mark_as_read'); $.post('/system_notifications/' + data.id + '/mark_as_read');
} }
}); });
@ -42,7 +35,7 @@ function bindSystemNotificationAjax() {
function initSystemNotificationsButton() { function initSystemNotificationsButton() {
$('.btn-more-notifications') $('.btn-more-notifications')
.on('ajax:success', function(e, data) { .on('ajax:success', function(e, data) {
$(data.html).insertAfter($('.notifications-container .system-notification').last()); $(data.html).insertAfter($('.system-notifications-container .system-notification').last());
bindSystemNotificationAjax(); bindSystemNotificationAjax();
if (data.more_url) { if (data.more_url) {
$(this).attr('href', data.more_url); $(this).attr('href', data.more_url);
@ -52,9 +45,6 @@ function initSystemNotificationsButton() {
}); });
} }
$(window).scroll(function() {
SystemNotificationsMarkAsSeen();
});
initSystemNotificationsButton(); initSystemNotificationsButton();
SystemNotificationsMarkAsSeen(); SystemNotificationsMarkAsSeen();
bindSystemNotificationAjax(); bindSystemNotificationAjax();

View file

@ -13,6 +13,16 @@
position: relative; position: relative;
width: 100%; width: 100%;
&[data-unread="0"] {
.body-block {
.title {
font-weight: normal;
}
}
}
&:hover { &:hover {
background: $color-concrete; background: $color-concrete;
opacity: .7; opacity: .7;
@ -55,6 +65,7 @@
} }
.title { .title {
font-weight: bold;
line-height: 20px; line-height: 20px;
margin: 0; margin: 0;
} }
@ -71,9 +82,11 @@
#system-notifications-index { #system-notifications-index {
display: inline-block; display: inline-block;
position: relative; position: relative;
width: 100%;
#search-bar-notifications { #search-bar-notifications {
border-bottom: 1px solid $color-gainsboro; border-bottom: 1px solid $color-gainsboro;
display: none;
margin: 10px 0 0; margin: 10px 0 0;
padding: 0 0 10px; padding: 0 0 10px;
width: 100%; width: 100%;
@ -111,3 +124,11 @@
margin-top: 10px; margin-top: 10px;
} }
} }
#manage-module-system-notification-modal {
.modal-title {
margin-left: 20px;
}
.modal-body {
margin: 20px;
}
}

View file

@ -24,8 +24,7 @@ class SystemNotificationsController < ApplicationController
# Update seen_at parameter for system notifications # Update seen_at parameter for system notifications
def mark_as_seen def mark_as_seen
notifications = JSON.parse(params[:notifications]) current_user.user_system_notifications.mark_as_seen
current_user.user_system_notifications.mark_as_seen(notifications)
render json: { result: 'ok' } render json: { result: 'ok' }
rescue StandardError rescue StandardError
render json: { result: 'failed' } render json: { result: 'failed' }

View file

@ -9,9 +9,8 @@ class UserSystemNotification < ApplicationRecord
scope :unseen, -> { where(seen_at: nil) } scope :unseen, -> { where(seen_at: nil) }
def self.mark_as_seen(notifications_id) def self.mark_as_seen
where(system_notification_id: notifications_id) unseen.update_all(seen_at: Time.now)
.update_all(seen_at: Time.now)
end end
def self.mark_as_read(notification_id) def self.mark_as_read(notification_id)

View file

@ -1,25 +1,24 @@
<%= link_to system_notification_path(notification.id, format: :json), class: "modal-system-notification", remote: true do %> <%= link_to system_notification_path(notification.id, format: :json), {
<div class: "modal-system-notification system-notification",
class="system-notification" 'data-new': notification.seen_at ? 0 : 1,
data-new="<%= notification.seen_at ? 0 : 1 %>" 'data-unread': notification.read_at ? 0 : 1,
data-unread="<%= notification.read_at ? 0 : 1 %>" 'data-system-notification-id': notification.id,
data-system-notification-id="<%= notification.id %>" remote: true
> } do %>
<div class="status-block"> <div class="status-block">
<div class="status-icon <%= notification.seen_at ? "seen" : "" %>"> <div class="status-icon <%= notification.read_at ? "seen" : "" %>">
<i class="fas fa-gift"></i> <i class="fas fa-gift"></i>
</div>
</div> </div>
<div class="body-block"> </div>
<div class="datetime"> <div class="body-block">
<span><%= l(notification.last_time_changed_at, format: :full) %></span> <div class="datetime">
</div> <span><%= l(notification.last_time_changed_at, format: :full) %></span>
<h5 class="title"> </div>
<strong><%= notification.title %></strong> <h5 class="title">
</h5> <%= notification.title %>
<div class="message"> </h5>
<span><%= notification.description %></span> <div class="message">
</div> <span><%= notification.description %></span>
</div> </div>
</div> </div>
<% end %> <% end %>

View file

@ -17,7 +17,7 @@
</div> </div>
</div> </div>
<% end %> <% end %>
<div class="notifications-container"> <div class="system-notifications-container">
<%= render partial: "list", locals: { notifications: @system_notifications[:notifications] } %> <%= render partial: "list", locals: { notifications: @system_notifications[:notifications] } %>
</div> </div>
<div class="text-center"> <div class="text-center">

View file

@ -1297,10 +1297,10 @@ en:
intro_paragraph: "Hi %{user_name}, you've received What's new notification in SciNote:" intro_paragraph: "Hi %{user_name}, you've received What's new notification in SciNote:"
index: index:
whats_new: "What's New" whats_new: "What's New"
more_notifications: "More system notifications" more_notifications: "Show more notifications"
no_notifications: "No more system notifications" no_notifications: "No more notifications"
settings: "Settings" settings: "Settings"
see_all: "See all" see_all: "show all"
activities: activities:
index: index:
today: "Today" today: "Today"

View file

@ -41,14 +41,6 @@ describe SystemNotificationsController, type: :controller do
expect(user.user_system_notifications.where(seen_at: nil).count).to eq 0 expect(user.user_system_notifications.where(seen_at: nil).count).to eq 0
end end
it '#mark_as_seen response failed on wrong id\'s format' do
params = { notifications: 'wrong format' }
get :mark_as_seen, format: :json, params: params
expect(response).to have_http_status(:ok)
body = JSON.parse(response.body)
expect(body['result']).to eq 'failed'
end
it '#mark_as_read correctly set read_at' do it '#mark_as_read correctly set read_at' do
params = { params = {
id: user.user_system_notifications.first.system_notification_id id: user.user_system_notifications.first.system_notification_id

View file

@ -55,7 +55,7 @@ describe UserSystemNotification do
user: user, user: user,
system_notification: notifcation_one system_notification: notifcation_one
notifications_to_update = [usn.system_notification_id] notifications_to_update = [usn.system_notification_id]
user.user_system_notifications.mark_as_seen(notifications_to_update) user.user_system_notifications.mark_as_seen
expect(UserSystemNotification.find(usn.id).seen_at).not_to be_nil expect(UserSystemNotification.find(usn.id).seen_at).not_to be_nil
end end