Skip to content

Commit

Permalink
Merge pull request #1283 from CaerCam/lunadev
Browse files Browse the repository at this point in the history
AJAX Notifications fixes
  • Loading branch information
Yannick committed May 23, 2015
2 parents 78985fb + 50b46c5 commit eab8edd
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 32 deletions.
22 changes: 15 additions & 7 deletions footer.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@
exit;

?>
<script id="tmpl-notification-nav" type="text/html">
<span id="notifications-number">{{ data.number }}</span> <span class="fa fa-fw fa-circle<# if ( ! data.number ) { #>-o<# } #>"></span> <span class="visible-xs-inline"> <?php _e('Notifications', 'luna'); ?></span>
</script>
<script id="tmpl-notification-menu" type="text/html">
<li role="presentation" class="dropdown-header no-hover"><?php _e( 'Notifications', 'luna' ); ?></li>
<li role="presentation" class="dropdown-header no-hover"><?php _e('Notifications', 'luna'); ?></li>
<li class="divider"></li>
<li class="notification-empty"><a href="notifications.php"><?php _e('No new notifications', 'luna'); ?></a></li>
<li class="divider"></li>
<li class="dropdown-footer"><a class="pull-right" href="notifications.php"><?php _e( 'More', 'luna' ); ?> <i class="fa fa-fw fa-arrow-right"></i></a></li>
<li class="dropdown-footer"><a class="pull-right" href="notifications.php"><?php _e('More', 'luna'); ?> <i class="fa fa-fw fa-arrow-right"></i></a></li>
</script>
<script id="tmpl-notification-menu-item" type="text/html">
<a href="{{ data.link }}" class="notification-link"><span class="fa fa-fw {{ data.icon }}"></span> {{ data.message }} <span class="timestamp pull-right">{{ data.time }}</span></a>
Expand All @@ -31,10 +36,13 @@
<script src="include/js/luna-notifications.js"></script>
<script type="text/javascript">
_nonces = {
heartbeat: '<?php echo LunaNonces::create( 'heartbeat-nonce' ); ?>',
fetchNotif: '<?php echo LunaNonces::create( 'fetch-notifications-nonce' ); ?>',
trashNotif: '<?php echo LunaNonces::create( 'trash-notification-nonce' ); ?>',
readNotif: '<?php echo LunaNonces::create( 'read-notification-nonce' ); ?>',
heartbeat: '<?php echo LunaNonces::create('heartbeat-nonce'); ?>',
fetchNotif: '<?php echo LunaNonces::create('fetch-notifications-nonce'); ?>',
trashNotif: '<?php echo LunaNonces::create('trash-notification-nonce'); ?>',
readNotif: '<?php echo LunaNonces::create('read-notification-nonce'); ?>',
};
ajaxurl = '<?php echo get_base_url() . '/ajax.php'; ?>';
ajaxurl = '<?php echo get_base_url().'/ajax.php'; ?>';
l10n = {
no_notification: '<?php _e('No new notifications', 'luna'); ?>'
}
</script>
4 changes: 2 additions & 2 deletions include/ajax_actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function luna_ajax_heartbeat() {
}

global $luna_user;
$notifications = get_user_unviewed_notifications($luna_user['id']);
$notifications = get_user_notifications($luna_user['id'], $viewed = 0, $count = true);
$messages = pending_messages($luna_user['id']);

// Send the current time according to the server
Expand All @@ -42,7 +42,7 @@ function luna_ajax_fetch_notifications() {

global $luna_user;

$notifications = get_user_unviewed_notifications($luna_user['id'], false);
$notifications = get_user_unviewed_notifications($luna_user['id']);
if (!empty($notifications)) {
luna_send_json_success($notifications);
}
Expand Down
61 changes: 58 additions & 3 deletions include/class/luna_notification.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,13 @@ public function __construct($notification) {
*/
private function init() {

global $luna_user;

$this->time = time();

if (isset($luna_user['id']) && !empty($luna_user['id'])) {
$this->user_id = $luna_user['id'];
}
}

/**
Expand Down Expand Up @@ -130,10 +136,40 @@ private function remove() {
return false;
}

$id = (int) $this->id;
$id = $db->escape($id);
$id = (int) $this->id;
$user_id = (int) $this->user_id;
$id = $db->escape($id);
$user_id = $db->escape($user_id);

$db->query('DELETE FROM '.$db->prefix.'notifications WHERE id='.$id) or error('Unable to remove notifications', __FILE__, __LINE__, $db->error());
$db->query('DELETE FROM '.$db->prefix.'notifications WHERE id='.$id.' AND user_id='.$user_id) or error('Unable to remove notifications', __FILE__, __LINE__, $db->error());

return $db->affected_rows();
}

/**
* Set a notification as viewed.
*
* This method always returns true except when the notification does not
* exist.
*
* @since 1.1
*
* @return int|boolean
*/
private function viewed() {

global $db;

if (empty($this->id)) {
return false;
}

$id = (int) $this->id;
$user_id = (int) $this->user_id;
$id = $db->escape($id);
$user_id = $db->escape($user_id);

$db->query('UPDATE '.$db->prefix.'notifications SET viewed=1 WHERE id='.$id.' AND user_id='.$user_id) or error('Unable to mark notification as read', __FILE__, __LINE__, $db->error());

return $db->affected_rows();
}
Expand Down Expand Up @@ -187,6 +223,25 @@ public static function add($user, $message, $link = '', $icon = '') {
return $notification->create();
}

/**
* Mark a specific notification as read. Static method.
*
* @since 1.1
*
* @param int $id Notification ID.
*
* @return boolean
*/
public static function read($id) {

$notification = LunaNotification::get_instance($id);
if (!$notification) {
return false;
}

return (boolean) $notification->viewed();
}

/**
* Delete a specific notification. Static method.
*
Expand Down
10 changes: 6 additions & 4 deletions include/js/luna-heartbeat.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@

( function( $, window ) {

var heartbeat = function() {

var luna = window.luna = window.luna || {};

luna.heartbeat = function() {
var $document = $( document ),
$window = $( window ),
options = {
Expand Down Expand Up @@ -103,9 +106,8 @@

startBeating();
}

window.luna = window.luna || {};
window.luna.heartbeat = new heartbeat();

luna.pulse = new luna.heartbeat();

}( jQuery, window ) );

102 changes: 86 additions & 16 deletions include/js/luna-notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ _.extend( notifications.Model, {
id: this.get( 'id' )
},
success: function( response ) {
self.trigger( 'read' );
// The model should self destruct, but don't actually destroy data on the server
self.trigger( 'destroy', self, self.collection, {} );
}
});

Expand Down Expand Up @@ -190,13 +191,19 @@ _.extend( notifications.Model, {
*/
sync: function( method, models, options ) {

var options = options || {},
self = this;

if ( 'read' === method ) {

var options = options || {};
_.extend( options, {
data: {
action: 'fetch-notifications',
_nonce: _nonces.fetchNotif
},
error: function( response ) {
self.trigger( 'empty' );
}
});

Expand Down Expand Up @@ -228,28 +235,39 @@ _.extend( notifications.View, {
*/
initialize: function() {

this.listenTo( this.model, 'destroying', this.destroying );
this.listenTo( this.model, 'undestroyed', this.undestroy );
this.listenTo( this.model, 'destroyed', this.remove );
this.listenTo( this.model, 'read', this.remove );
this.listenTo( this.model, 'destroying', this._destroying );
this.listenTo( this.model, 'undestroyed', this._undestroy );
this.listenTo( this.model, 'destroyed', this._remove );
this.listenTo( this.model, 'destroy', this._remove );
},

/**
* Colorize the notification while destroying.
*/
destroying: function() {
_destroying: function() {

this.$el.addClass( 'bg-danger' );
},

/**
* Destroy failed, uncolorize the notification
*/
undestroy: function() {
_undestroy: function() {

this.$el.removeClass( 'bg-danger' );
},

/**
* Remove the notification view and reload the collection to be
* sure and re-render the main view.
*/
_remove: function() {

this.remove();

this.model.collection.fetch();
},

/**
* Convert notification time to a simpler HH:mm format
*/
Expand Down Expand Up @@ -322,13 +340,15 @@ _.extend( notifications.View, {

template: luna.template( 'notification-menu' ),

_empty: true,

/**
* Initialize the View
*/
initialize: function( options ) {

_.each( this.collection.models, this.addNotification, this );
this.listenTo( this.collection, 'add', this.addNotification );
this.listenTo( this.collection, 'empty', this.render);
},

/**
Expand All @@ -337,7 +357,34 @@ _.extend( notifications.View, {
*/
addNotification: function( notification ) {

this.views.add( new luna.notifications.View.Notification({ model: notification }), { at: 2 } );
if ( this._empty ) {
this.$( '.notification-empty' ).next( '.divider' ).remove();
this.$( '.notification-empty' ).remove();
this._empty = false;
}

var view = new luna.notifications.View.Notification({ model: notification });
notification.view = view;

this.views.add( view, { at: 2 } );
},

/**
* Render the view.
*
* @since 1.1
*
* @return Return itself to allow chaining.
*/
render: function() {

if ( ! this.collection.length ) {
this._empty = true;
}

this.$el.html( this.template() );

return this;
}
})
},
Expand All @@ -349,6 +396,12 @@ _.extend( notifications.View, {

el: '#navnotification',

template: luna.template( 'notification-nav' ),

events: {
'click a[data-flyout]': '_refresh'
},

/**
* Initialize the View
*
Expand All @@ -370,7 +423,7 @@ _.extend( notifications.View, {
this.$document = $( document );
this.$document.on( 'heartbeat-tick', this.update );

this.notifications.on( 'sync', this.updateCounter, this );
this.notifications.on( 'add remove', this.render, this );
},

/**
Expand All @@ -386,6 +439,20 @@ _.extend( notifications.View, {
this.views.add( this.submenu );
},

/**
* Refetch the collection when opening the flyout.
*
* @param object JS 'click' Event
*/
_refresh: function( event ) {

if ( this.$el.hasClass( 'open' ) ) {
return;
}

this.update( event, { notifications: -1 } );
},

/**
* Update the collection on heartbeat.
*
Expand All @@ -404,15 +471,18 @@ _.extend( notifications.View, {
},

/**
* Update the menu when collection is synced.
* Render part of the view.
*
* We should override the complete view to avoid messing with
* Bootstrap on handling the flyout dropdown.
*
* @return Return itself to allow chaining.
*/
updateCounter: function() {
render: function() {

var number = this.notifications.length || '',
title = document.title.replace( /^\(\d\)\ /i, '' );
this.$( 'a[data-flyout]' ).html( this.template({ number: this.notifications.length || '' } ) );

this.$( '#notifications-number' ).text( number );
document.title = '(' + number + ') ' + title;
return this;
}
})
} );
Expand Down
14 changes: 14 additions & 0 deletions include/notifications.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ function delete_notification($id) {
return LunaNotification::delete($id);
}

/**
* Mark a specific notification as viewed.
*
* @since 1.1
*
* @param int Notification ID
*
* @return boolean
*/
function read_notification($id) {

return LunaNotification::read($id);
}

/**
* Get a specific notification.
*
Expand Down

0 comments on commit eab8edd

Please sign in to comment.