Transform the menu notification list in a widget and built-in a load more functionality and an "Mark all as seen" feature (#58)

This commit is contained in:
Andy Strobel 2014-05-17 20:02:19 +02:00
parent 55de7fce81
commit 8d22c5f410
9 changed files with 303 additions and 77 deletions

View File

@ -74,6 +74,16 @@ textarea {
padding: 3px 10px;
margin-bottom: 10px;
}
.topbar .dropdown-header .dropdown-header-link {
position: absolute;
top: 2px;
right: 10px;
}
.topbar .dropdown-header .dropdown-header-link a {
color: #428bca !important;
font-size: 12px;
font-weight: normal;
}
#topbar-first {
top: 0;
background-color: #101010;
@ -165,6 +175,10 @@ textarea {
width: 350px;
margin-left: -148px;
}
#topbar-first .notifications #dropdown-notifications ul.media-list {
max-height: 400px;
overflow: auto;
}
#topbar-first .notifications #dropdown-notifications li {
position: relative;
}

View File

@ -55,7 +55,7 @@ hr {
}
textarea {
height:1.5em;
height: 1.5em;
}
//
@ -91,6 +91,18 @@ textarea {
font-size: 16px;
padding: 3px 10px;
margin-bottom: 10px;
.dropdown-header-link {
position: absolute;
top: 2px;
right: 10px;
a {
color: #428bca !important;
font-size: 12px;
font-weight: normal;
}
}
}
}
@ -189,7 +201,7 @@ textarea {
left: 50%;
margin-left: -18px;
border-top-width: 0;
border-bottom-color: rgba(0,0,0,0.15);
border-bottom-color: rgba(0, 0, 0, 0.15);
top: -16px;
z-index: 1035;
}
@ -198,6 +210,11 @@ textarea {
width: 350px;
margin-left: -148px;
ul.media-list {
max-height: 400px;
overflow: auto;
}
li {
position: relative;
@ -654,7 +671,6 @@ input.placeholder, textarea.placeholder {
color: #999999;
}
//
// 10) Responsive modifications
// --------------------------------------------------

View File

@ -1,4 +1,4 @@
<li class="<?php if (!$notification->seen) : ?>new<?php endif; ?>">
<li class="<?php if (!$notification->seen) : ?>new<?php endif; ?>" id="notification-<?php echo $notification->id; ?>">
<a href="<?php echo $notification->getUrl(); ?>">
<div class="media">

View File

@ -6,12 +6,14 @@
* @package humhub.modules_core.notification.controllers
* @since 0.5
*/
class ListController extends Controller {
class ListController extends Controller
{
/**
* @return array action filters
*/
public function filters() {
public function filters()
{
return array(
'accessControl', // perform access control for CRUD operations
);
@ -22,7 +24,8 @@ class ListController extends Controller {
* This method is used by the 'accessControl' filter.
* @return array access control rules
*/
public function accessRules() {
public function accessRules()
{
return array(
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'users' => array('@'),
@ -34,19 +37,69 @@ class ListController extends Controller {
}
/**
* Returns a List of all Comments belong to this Model
* Returns a List of all notifications for an user
*/
public function actionIndex() {
public function actionIndex()
{
// the id from the last entry loaded
$lastEntryId = Yii::app()->request->getParam('from');
// create database query
$criteria = new CDbCriteria();
if ($lastEntryId > 0) {
// start from last entry id loaded
$criteria->condition = 'id<' . $lastEntryId;
}
$criteria->order = 'seen ASC, created_at DESC';
$criteria->limit = 6;
// safe query
$notifications = Notification::model()->findAllByAttributes(array('user_id' => Yii::app()->user->id), $criteria);
$this->renderPartial('index', array(
'notifications' => $notifications
));
// variable for notification list
$output = "";
foreach ($notifications as $notification) {
// format and save all entries
$output .= $notification->getOut();
// get the id from the last entry
$lastEntryId = $notification->id;
}
// build json array
$json = array();
$json['output'] = $output;
$json['lastEntryId'] = $lastEntryId;
$json['counter'] = count($notifications);
// return json
echo CJSON::encode($json);
// compete action
Yii::app()->end();
}
public function actionMarkAsSeen()
{
// build query
$criteria = new CDbCriteria();
$criteria->condition = 'seen=0';
// load all unseen notification for this user
$notifications = Notification::model()->findAllByAttributes(array('user_id' => Yii::app()->user->id), $criteria);
foreach ($notifications as $notification) {
// mark all unseen notification as seen
$notification->markAsSeen();
}
// compete action
Yii::app()->end();
}
}

View File

@ -0,0 +1,22 @@
<?php
/**
* NotificationListWidget shows an stream of notifications for an user at the top menu.
*
* @author andystrobel
* @package humhub.modules_core.notification
* @since 0.5
*/
class NotificationListWidget extends HWidget {
/**
* Runs the notification widget
*/
public function run() {
$this->render('list', array());
}
}
?>

View File

@ -0,0 +1,178 @@
<div class="btn-group">
<a href="#" id="icon-notifications" data-toggle="dropdown">
<i class="fa fa-bell"></i>
</a>
<span id="badge-notifications" style="display:none;" class="label label-danger label-notifications">1</span>
<!-- container for ajax response -->
<ul id="dropdown-notifications" class="dropdown-menu">
<li class="dropdown-header">
<div class="arrow"></div><?php echo Yii::t('base', 'Notifications'); ?>
<div class="dropdown-header-link"><a
href="javascript:markNotificationsAsSeen();"><?php echo Yii::t('NotificationModule', 'Mark all as seen'); ?></a>
</div>
</li>
<ul class="media-list"></ul>
<li id="loader_notifications">
<div class="loader"></div>
</li>
</ul>
</div>
<script type="text/javascript">
// set niceScroll to notification list
$("#dropdown-notifications ul.media-list").niceScroll({
cursorwidth: "7",
cursorborder:"",
cursorcolor:"#555",
cursoropacitymax:"0.2",
railpadding:{top:0,right:3,left:0,bottom:0}
});
function markNotificationsAsSeen() {
//$('#dropdown-notifications').css({display: 'block'});
// call ajax request to mark all notifications as seen
jQuery.ajax({
'type': 'GET',
'url': '<?php echo $this->createUrl('//notification/list/markAsSeen', array('ajax' => 1)); ?>',
'cache': false,
'data': jQuery(this).parents("form").serialize(),
'success': function(html) {
// hide notification badge at the top menu
$('#badge-notifications').css('display', 'none');
}});
}
$(document).ready(function () {
// set the ID for the last loaded activity entry to 1
var notificationLastLoadedEntryId = 0;
// save if the last entries are already loaded
var notificationLastEntryReached = false;
// safe action url
var _notificationUrl = '<?php echo $this->createUrl('//notification/list/index', array('from' => 'lastEntryId', 'ajax' => 1)); ?>';
// Open the notification menu
$('#icon-notifications').click(function () {
// reset variables by dropdown reopening
notificationLastLoadedEntryId = 0;
notificationLastEntryReached = false;
// remove all notification entries from dropdown
$('#dropdown-notifications ul.media-list').find('li').remove();
// checking if ajax loading is necessary or the last entries are already loaded
if (notificationLastEntryReached == false) {
// load notifications
loadNotificationEntries();
}
})
$('#dropdown-notifications ul.media-list').scroll(function () {
// save height of the overflow container
var _containerHeight = $("#dropdown-notifications ul.media-list").height();
// save scroll height
var _scrollHeight = $("#dropdown-notifications ul.media-list").prop("scrollHeight");
// save current scrollbar position
var _currentScrollPosition = $('#dropdown-notifications ul.media-list').scrollTop();
// load more activites if current scroll position is near scroll height
if (_currentScrollPosition >= (_scrollHeight - _containerHeight - 1)) {
// checking if ajax loading is necessary or the last entries are already loaded
if (notificationLastEntryReached == false) {
// load more notifications
loadNotificationEntries();
}
}
});
function loadNotificationEntries() {
// replace placeholder name with the id from the last loaded entry
var _modifiedNotificationUrl = _notificationUrl.replace('lastEntryId', notificationLastLoadedEntryId)
// show loader
$("#loader_notifications .loader").show();
// send ajax request
jQuery.getJSON(_modifiedNotificationUrl, function (json) {
// hide loader
$("#loader_notifications .loader").hide();
// save id from the last entry for the next loading
notificationLastLoadedEntryId = json.lastEntryId;
if (json.counter < 6) {
// prevent the next ajax calls, if there are no more entries
notificationLastEntryReached = true;
}
// add new entries
$("#dropdown-notifications ul.media-list").append(json.output);
// format time
$('span.time').timeago();
});
}
// load number of new notifications at page loading
getNotifications();
// load number of new notifications in a loop
setInterval(getNotifications, 60000);
// load and show new count of notifications
function getNotifications() {
var $newNotifications = parseInt(0);
// load data
jQuery.getJSON("<?php echo $this->createUrl('//dashboard/dashboard/GetFrontEndInfo'); ?>", function (json) {
// save numbers to variables
$newNotifications = parseInt(json.newNotifications);
// show or hide the badge for new notifications
if ($newNotifications == 0) {
$('#badge-notifications').css('display', 'none');
} else {
$('#badge-notifications').empty();
$('#badge-notifications').append($newNotifications);
$('#badge-notifications').fadeIn('fast');
}
})
}
})
</script>

View File

@ -100,15 +100,7 @@
<div class="notifications pull-right">
<!-- global notifications dropdown -->
<div class="btn-group">
<a href="#" id="icon-notifications" data-toggle="dropdown">
<i class="fa fa-bell"></i>
</a>
<span id="badge-notifications" style="display:none;" class="label label-danger label-notifications">1</span>
<!-- container for ajax response -->
<ul id="dropdown-notifications" class="dropdown-menu"></ul>
</div>
<?php $this->widget('application.modules_core.notification.widgets.NotificationListWidget'); ?>
<!-- Notification addon widget for modules -->
<?php $this->widget('application.widgets.NotificationAddonWidget', array('widgets' => array())); ?>
@ -181,60 +173,6 @@
$(document).ready(function () {
// Open the notification menu
$('#icon-notifications').click(function () {
// remove all <li> entries from dropdown
$('#dropdown-notifications').find('li').remove();
// append title and loader to dropdown
$('#dropdown-notifications').append('<li class="dropdown-header"><div class="arrow"></div><?php echo Yii::t('base', 'Notifications'); ?></li><li id="loader_notifications"><div class="loader"></div></li>');
// load newest notifications
$.ajax({
'type': 'GET',
'url': '<?php echo $this->createUrl('//notification/list', array('ajax' => 1)); ?>',
'cache': false,
'data': jQuery(this).parents("form").serialize(),
'success': function (html) {
$("#loader_notifications").replaceWith(html)
}});
})
// load number of new notifications at page loading
getNotifications();
// load number of new notifications in a loop
setInterval(getNotifications, 60000);
// load and show new count of notifications
function getNotifications() {
var $newNotifications = parseInt(0);
// load data
jQuery.getJSON("<?php echo $this->createUrl('//dashboard/dashboard/GetFrontEndInfo'); ?>", function (json) {
// save numbers to variables
$newNotifications = parseInt(json.newNotifications);
// show or hide the badge for new notifications
if ($newNotifications == 0) {
$('#badge-notifications').css('display', 'none');
} else {
$('#badge-notifications').empty();
$('#badge-notifications').append($newNotifications);
$('#badge-notifications').fadeIn('fast');
}
})
}
/* Ensures after hide modal content is removed. */
$('#globalModal').on('hidden.bs.modal', function (e) {
$(this).removeData('bs.modal');
@ -268,8 +206,6 @@
</script>
</body>
</html>

View File

@ -23,6 +23,9 @@ h4 {
font-weight: 300;
color: #bebebe;
}
.topbar .dropdown-header .dropdown-header-link a {
color: #4cd9c0 !important;
}
#topbar-first {
background-color: #7191a8;
color: white;

View File

@ -72,6 +72,10 @@ h4 {
.dropdown-header {
font-weight: 300;
color: @colorFont4;
.dropdown-header-link a {
color: #4cd9c0 !important;
}
}
}