(function(context,$) { "use strict"; context.JK = context.JK || {}; context.JK.NotificationPanel = function(app) { var EVENTS = context.JK.EVENTS; var logger = context.JK.logger; var friends = []; var rest = context.JK.Rest(); var missedNotificationsWhileAway = false; var $panel = null; var $expanded = null; var $contents = null; var $count = null; var $list = null; var $notificationTemplate = null; var sidebar = null; var darkenedColor = '#0D7B89'; var highlightedColor = 'white' var textMessageDialog = null; var queuedNotification = null; var queuedNotificationCreatedAt = null; var sessionUtils = context.JK.SessionUtils; var notificationBatchSize = 20; var currentNotificationPage = 0; var didLoadAllNotifications = false, isLoading = false; var ui = new context.JK.UIHelper(JK.app); function isNotificationsPanelVisible() { return $contents.is(':visible') } function incrementNotificationCount() { var count = parseInt($count.text()); setCount(count + 1); } function decrementNotificationCount() { var count = parseInt($count.text()); if(count > 0) { count = count - 1; setCount(count); if(count == 0) { lowlightCount(); missedNotificationsWhileAway = false; } } } // set the element to white, and pulse it down to the un-highlighted value 2x, then set function pulseToDark() { logger.debug("pulsing notification badge") lowlightCount(); $count.pulse({'background-color' : highlightedColor}, {pulses: 2}, function() { $count.removeAttr('style') setCount(0); }) } function setCount(count) { $count.text(count); } function lowlightCount() { $count.removeClass('highlighted'); } function highlightCount() { $count.addClass('highlighted'); } function queueNotificationSeen(notificationId, notificationCreatedAt, type) { var time = new Date(notificationCreatedAt); if(!notificationCreatedAt) { throw 'invalid value passed to queuedNotificationCreatedAt' } if(!queuedNotificationCreatedAt) { queuedNotification = notificationId; queuedNotificationCreatedAt = notificationCreatedAt; logger.debug("updated queuedNotificationCreatedAt with: " + notificationCreatedAt); } else if(time.getTime() > new Date(queuedNotificationCreatedAt).getTime()) { queuedNotification = notificationId; queuedNotificationCreatedAt = notificationCreatedAt; logger.debug("updated queuedNotificationCreatedAt with: " + notificationCreatedAt); } else { logger.debug("ignored queuedNotificationCreatedAt for: " + notificationCreatedAt); } } function onNotificationOccurred(payload) { if(userCanSeeNotifications(payload)) { app.updateNotificationSeen(payload.notification_id, payload.created_at); } else { if(app.layout.isNoisyNotification(payload) && !missedNotificationsWhileAway) { // this handles a special case--if a notification is too noisy while away, then don't bother // incrementing anything on the sidebar or otherwise distracting the user app.updateNotificationSeen(payload.notification_id, payload.created_at); } else { queueNotificationSeen(payload.notification_id, payload.created_at, payload.description); highlightCount(); incrementNotificationCount(); missedNotificationsWhileAway = true; } } } function userCameBack() { if(isNotificationsPanelVisible()) { if(missedNotificationsWhileAway) { // catch user's eye, then put count to 0 pulseToDark(); if(queuedNotificationCreatedAt) { app.updateNotificationSeen(queuedNotification, queuedNotificationCreatedAt); } } } queuedNotification = null; queuedNotificationCreatedAt = null; missedNotificationsWhileAway = false; } function opened() { queuedNotification = null; queuedNotificationCreatedAt = null; rest.updateUser({notification_seen_at: 'LATEST'}) .done(function(response) { lowlightCount(); setCount(0); }) .fail(app.ajaxError) } function windowBlurred() { } function events() { $(context).on(EVENTS.DIALOG_CLOSED, function(e, data) {if(data.dialogCount == 0) userCameBack(); }); $(window).focus(userCameBack); $(window).blur(windowBlurred); app.user() .done(function(user) { setCount(user.new_notifications); if(user.new_notifications > 0) { highlightCount(); } }); $panel.on('open', opened); // friend notifications registerFriendRequest(); registerFriendRequestAccepted(); registerNewUserFollower(); registerNewBandFollower(); // session notifications registerSessionInvitation(); registerSessionEnded(); registerJoinRequest(); registerJoinRequestApproved(); registerJoinRequestRejected(); registerMusicianSessionJoin(); registerBandSessionJoin(); // scheduled sessions registerScheduledSessionInvitation(); registerScheduledSessionRsvp(); registerScheduledSessionRsvpApproved(); registerScheduledSessionRsvpCancelled(); registerScheduledSessionRsvpCancelledOrg(); registerScheduledSessionCancelled(); registerScheduledSessionRescheduled(); registerScheduledSessionReminder(); registerScheduledSessionComment(); // recording notifications registerMusicianRecordingSaved(); registerBandRecordingSaved(); registerRecordingMasterMixComplete(); registerRecordingStreamMixComplete(); // band notifications registerBandInvitation(); registerBandInvitationAccepted(); // register text messages registerTextMessage(); } function buildParams() { return { offset: currentNotificationPage * notificationBatchSize, limit: notificationBatchSize}; } function populate() { if (isLoading || didLoadAllNotifications) return; isLoading = true; // retrieve pending notifications for this user rest.getNotifications(buildParams()) .done(function(response) { updateNotificationList(response); isLoading = false; }) .fail(function() { isLoading = false; app.ajaxError(); }) } function updateNotificationList(response) { $.each(response, function(index, val) { if(val.description == context.JK.MessageType.TEXT_MESSAGE) { val.formatted_msg = textMessageDialog.formatTextMessage(val.message.substring(0, 200), val.source_user_id, val.source_user.name, val.message.length > 200).html(); } // fill in template for Connect pre-click var template = $notificationTemplate.html(); var notificationHtml = context.JK.fillTemplate(template, { notificationId: val.notification_id, sessionId: val.session_id, hoveraction: val.session_id ? "session" : "", avatar_url: context.JK.resolveAvatarUrl(val.photo_url), text: val.formatted_msg, date: $.timeago(val.created_at), userId: val.source_user_id }); $list.append(notificationHtml); // val.description contains the notification record's description value from the DB (i.e., type) initializeActions(val, val.description); }); if(response.length < notificationBatchSize) { didLoadAllNotifications = true; } currentNotificationPage++; } function initializeActions(payload, type) { var $notification = $('li[notification-id=' + payload.notification_id + ']'); var $btnNotificationAction = '#btn-notification-action'; // wire up "x" button to delete notification $notification.find('#img-delete-notification').click(deleteNotificationHandler); // customize action buttons based on notification type if (type === context.JK.MessageType.FRIEND_REQUEST) { var $action_btn = $notification.find($btnNotificationAction); $action_btn.text('ACCEPT'); $action_btn.click(function() { acceptFriendRequest(payload); }); } else if (type === context.JK.MessageType.FRIEND_REQUEST_ACCEPTED) { $notification.find('#div-actions').hide(); } else if (type === context.JK.MessageType.NEW_USER_FOLLOWER || type === context.JK.MessageType.NEW_BAND_FOLLOWER) { $notification.find('#div-actions').hide(); } else if (type === context.JK.MessageType.SESSION_INVITATION) { var $action_btn = $notification.find($btnNotificationAction); $action_btn.text('JOIN'); $action_btn.click(function() { openTerms(payload); }); } else if (type === context.JK.MessageType.RECORDING_MASTER_MIX_COMPLETE) { var $action_btn = $notification.find($btnNotificationAction); $action_btn.text('SHARE'); $action_btn.click(function() { rest.getRecording({id: payload.recording_id}) .done(function(recording) { if(recording.my) { ui.launchShareDialog(recording.my.id, 'recording'); } else { context.JK.Banner.showAlert('Unable to share recording') } }) .fail(app.ajaxError) }); } else if (type === context.JK.MessageType.RECORDING_STREAM_MIX_COMPLETE) { var $action_btn = $notification.find($btnNotificationAction); $action_btn.text('SHARE'); $action_btn.click(function() { rest.getRecording({id: payload.recording_id}) .done(function(recording) { if(recording.my) { ui.launchShareDialog(recording.my.id, 'recording'); } else { context.JK.Banner.showAlert('Unable to share recording') } }) .fail(app.ajaxError) }); } else if (type === context.JK.MessageType.JOIN_REQUEST) { var $action_btn = $notification.find($btnNotificationAction); $action_btn.text('APPROVE'); $action_btn.click(function() { approveJoinRequest(payload); }); } else if (type === context.JK.MessageType.JOIN_REQUEST_APPROVED) { var $action_btn = $notification.find($btnNotificationAction); $action_btn.text('JOIN'); $action_btn.click(function() { openTerms(payload); }); } else if (type === context.JK.MessageType.JOIN_REQUEST_REJECTED) { $notification.find('#div-actions').hide(); } else if (type === context.JK.MessageType.MUSICIAN_SESSION_JOIN || type === context.JK.MessageType.BAND_SESSION_JOIN) { var actionText = ''; var callback; if (context.JK.currentUserMusician) { // user is MUSICIAN; musician_access = TRUE if (payload.musician_access) { actionText = "JOIN"; callback = joinSession; } // user is MUSICIAN; fan_access = TRUE else if (payload.fan_access) { actionText = "LISTEN"; callback = listenToSession; } } else { // user is FAN; fan_access = TRUE if (payload.fan_access) { actionText = "LISTEN"; callback = listenToSession; } } var $action_btn = $notification.find($btnNotificationAction); if (actionText === '') { $action_btn.hide(); } else { $action_btn.text(actionText); $action_btn.click(function() { callback(payload); }); } } else if (type === context.JK.MessageType.MUSICIAN_RECORDING_SAVED || type === context.JK.MessageType.BAND_RECORDING_SAVED) { var $action_btn = $notification.find($btnNotificationAction); $action_btn.text('LISTEN'); $action_btn.click(function() { listenToRecording(payload); }); } else if (type === context.JK.MessageType.RECORDING_MASTER_MIX_COMPLETE) { $notification.find('#div-actions').hide(); logger.debug("context.jamClient.OnDownloadAvailable!") context.jamClient.OnDownloadAvailable(); // poke backend, letting it know a download is available } else if (type === context.JK.MessageType.JAM_TRACK_SIGN_COMPLETE) { $notification.find('#div-actions').hide(); logger.debug("context.jamClient.OnDownloadAvailable!") context.jamClient.OnDownloadAvailable(); // poke backend, letting it know a download is available } else if (type === context.JK.MessageType.BAND_INVITATION) { var $action_btn = $notification.find($btnNotificationAction); $action_btn.text('ACCEPT'); $action_btn.click(function() { acceptBandInvitation(payload); }); } else if (type === context.JK.MessageType.BAND_INVITATION_ACCEPTED) { $notification.find('#div-actions').hide(); } else if (type === context.JK.MessageType.TEXT_MESSAGE) { var $action_btn = $notification.find($btnNotificationAction); $action_btn.text('REPLY'); $action_btn.click(function() { var userId = $notification.find('.more-text-available').attr('data-sender-id'); app.layout.showDialog('text-message', { d1: userId }); }); var moreTextLink = $notification.find('.more-text-available'); var textMessage = $notification.find('.text-message'); var clipped_msg = textMessage.attr('data-is-clipped') === 'true'; if(clipped_msg) { moreTextLink.text('more').show(); moreTextLink.click(function(e) { var userId = $(this).attr('data-sender-id'); app.layout.showDialog('text-message', { d1: userId }); return false; }); } else { moreTextLink.hide(); } } else if (type === context.JK.MessageType.SCHEDULED_SESSION_INVITATION) { linkSessionInfoNotification(payload, $notification, $btnNotificationAction); } else if (type === context.JK.MessageType.SCHEDULED_SESSION_RSVP) { var $action_btn = $notification.find($btnNotificationAction); $action_btn.text('MANAGE RSVP'); $action_btn.click(function() { context.location = "/client#/account/sessionDetail/" + payload.session_id; }); } else if (type === context.JK.MessageType.SCHEDULED_SESSION_RSVP_APPROVED) { linkSessionInfoNotification(payload, $notification, $btnNotificationAction); } else if (type === context.JK.MessageType.SCHEDULED_SESSION_RSVP_CANCELLED) { linkSessionInfoNotification(payload, $notification, $btnNotificationAction); } else if (type === context.JK.MessageType.SCHEDULED_SESSION_RSVP_CANCELLED_ORG) { linkSessionInfoNotification(payload, $notification, $btnNotificationAction); } else if (type === context.JK.MessageType.SCHEDULED_SESSION_CANCELLED) { linkSessionInfoNotification(payload, $notification, $btnNotificationAction); } else if (type === context.JK.MessageType.SCHEDULED_SESSION_RESCHEDULED) { linkSessionInfoNotification(payload, $notification, $btnNotificationAction); } else if (type === context.JK.MessageType.SCHEDULED_SESSION_REMINDER) { linkSessionInfoNotification(payload, $notification, $btnNotificationAction); } else if (type === context.JK.MessageType.SCHEDULED_SESSION_COMMENT) { linkSessionInfoNotification(payload, $notification, $btnNotificationAction); } context.JK.bindHoverEvents($("#sidebar-div")); } function linkSessionInfoNotification(payload, $notification, $btnNotificationAction) { var $action_btn = $notification.find($btnNotificationAction); $action_btn.text('SESSION DETAILS'); $action_btn.click(function() { openSessionInfoWebPage({"session_id": payload.session_id}); }); } function acceptBandInvitation(args) { rest.updateBandInvitation( args.band_id, args.band_invitation_id, true ).done(function(response) { deleteNotification(args.notification_id); // delete notification corresponding to this friend request }).error(app.ajaxError); } function deleteNotification(notificationId) { var url = "/api/users/" + context.JK.currentUserId + "/notifications/" + notificationId; $.ajax({ type: "DELETE", dataType: "json", contentType: 'application/json', url: url, processData: false, success: function(response) { var notification = $('li[notification-id=' + notificationId + ']'); if(notification.length > 0) { decrementNotificationCount(); } notification.remove(); }, error: app.ajaxError }); } function listenToSession(args) { deleteNotification(args.notification_id); context.JK.popExternalLink('/sessions/' + args.session_id); } function joinSession(args) { sessionUtils.joinSession(args.session_id); deleteNotification(args.notification_id); } function registerJoinRequestApproved() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.JOIN_REQUEST_APPROVED, function(header, payload) { logger.debug("Handling JOIN_REQUEST_APPROVED msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Join Request Approved", "text": payload.msg, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-join", text: "JOIN SESSION", "layout-action": "close", href: "#", "class": "button-orange", callback: openTerms, callback_args: { "session_id": payload.session_id, "notification_id": payload.notification_id } }] ); }); } function registerJoinRequestRejected() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.JOIN_REQUEST_REJECTED, function(header, payload) { logger.debug("Handling JOIN_REQUEST_REJECTED msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Join Request Rejected", "text": payload.msg, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }); }); } function registerJoinRequest() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.JOIN_REQUEST, function(header, payload) { logger.debug("Handling JOIN_REQUEST msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "New Join Request", "text": payload.msg, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-approve", text: "APPROVE", "layout-action": "close", href: "#", "class": "button-orange", callback: approveJoinRequest, callback_args: { "join_request_id": payload.join_request_id, "notification_id": payload.notification_id } }, { id: "btn-reject", text: "REJECT", "layout-action": "close", href: "#", "class": "button-grey", callback: rejectJoinRequest, callback_args: { "join_request_id": payload.join_request_id, "notification_id": payload.notification_id } }] ); }); } function registerFriendRequestAccepted() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.FRIEND_REQUEST_ACCEPTED, function(header, payload) { logger.debug("Handling FRIEND_REQUEST_ACCEPTED msg " + JSON.stringify(payload)); handleNotification(payload, header.type); sidebar.refreshFriends(); app.notify({ "title": "Friend Request Accepted", "text": payload.msg, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }); }); } function registerNewUserFollower() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.NEW_USER_FOLLOWER, function(header, payload) { logger.debug("Handling NEW_USER_FOLLOWER msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "New Follower", "text": payload.msg, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }); }); } function registerNewBandFollower() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.NEW_BAND_FOLLOWER, function(header, payload) { logger.debug("Handling NEW_BAND_FOLLOWER msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "New Band Follower", "text": payload.msg, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }); }); } function registerFriendRequest() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.FRIEND_REQUEST, function(header, payload) { logger.debug("Handling FRIEND_REQUEST msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "New Friend Request", "text": payload.msg, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-accept", text: "ACCEPT", "layout-action": "close", href: "#", "class": "button-orange", callback: acceptFriendRequest, callback_args: { "friend_request_id": payload.friend_request_id, "notification_id": payload.notification_id } }] ); }); } function acceptFriendRequest(args) { rest.acceptFriendRequest({ status: 'accept', friend_request_id: args.friend_request_id }).done(function(response) { deleteNotification(args.notification_id); // delete notification corresponding to this friend request sidebar.refreshFriends(); // refresh friends panel when request is accepted }).error(app.ajaxError); } function registerSessionEnded() { // TODO: this should clean up all notifications related to this session context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_ENDED, function(header, payload) { logger.debug("Handling SESSION_ENDED msg " + JSON.stringify(payload)); deleteSessionNotifications(payload.session_id); }); } // remove all notifications for this session function deleteSessionNotifications(sessionId) { $('li[session-id=' + sessionId + ']').hide(); //decrementNotificationCount(); } function registerSessionInvitation() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_INVITATION, function(header, payload) { logger.debug("Handling SESSION_INVITATION msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Session Invitation", "text": payload.msg }, [{ id: "btn-join", text: "JOIN SESSION", "layout-action": "close", href: "#", "class": "button-orange", callback: openTerms, callback_args: { "session_id": payload.session_id, "notification_id": payload.notification_id } }] ); // THERE IS A RACE CONDITION THAT CAUSES AN ERROR WHEN INVOKING THE CODE BELOW // THE ACTIVEMUSICSESSION HAS NOT YET BEEN FULLY CREATED B/C THE CREATOR'S CLIENT IS // STILL SETTING UP THE SESSION WHEN THE NOTIFICATION IS SENT // SEE ActiveMusicSession#participant_create // var participants = []; // rest.getSession(payload.session_id) // .done(function(response) { // $.each(response.participants, function(index, val) { // participants.push({"photo_url": context.JK.resolveAvatarUrl(val.user.photo_url), "name": val.user.name}); // }); // var participantHtml = "You have been invited to join a session with:

"; // participantHtml += ""; // $.each(participants, function(index, val) { // if (index < 4) { // participantHtml += ""; // } // }); // participantHtml += "
" + val.name + "
"; // app.notify({ // "title": "Session Invitation", // "text": participantHtml // }, [{ // id: "btn-join", // text: "JOIN SESSION", // "layout-action": "close", // href: "#", // "class": "button-orange", // callback: openTerms, // callback_args: { // "session_id": payload.session_id, // "notification_id": payload.notification_id // } // }] // ); // }).error(app.ajaxError); }); } function registerMusicianSessionJoin() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_JOIN, function(header, payload) { logger.debug("Handling MUSICIAN_SESSION_JOIN msg " + JSON.stringify(payload)); var okText = ''; var showNotification = false; var callback; if (context.JK.currentUserMusician) { // user is MUSICIAN; musician_access = TRUE if (payload.musician_access) { showNotification = true; okText = "JOIN"; callback = joinSession; } // user is MUSICIAN; fan_access = TRUE else if (payload.fan_access) { showNotification = true; okText = "LISTEN"; callback = listenToSession; } } else { // user is FAN; fan_access = TRUE if (payload.fan_access) { showNotification = true; okText = "LISTEN"; callback = listenToSession; } } if (showNotification) { handleNotification(payload, header.type); app.notify({ "title": "Musician Joined Session", "text": payload.msg, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-action", text: okText, "layout-action": "close", href: "#", "class": "button-orange", callback: callback, callback_args: { "session_id": payload.session_id, "fan_access": payload.fan_access, "musician_access": payload.musician_access, "approval_required": payload.approval_required, "notification_id": payload.notification_id } }] ); } }); } function registerBandSessionJoin() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_SESSION_JOIN, function(header, payload) { logger.debug("Handling BAND_SESSION_JOIN msg " + JSON.stringify(payload)); var okText = ''; var showNotification = false; var callback; if (context.JK.currentUserMusician) { // user is MUSICIAN; musician_access = TRUE if (payload.musician_access) { showNotification = true; okText = "JOIN"; callback = joinSession; } // user is MUSICIAN; fan_access = TRUE else if (payload.fan_access) { showNotification = true; okText = "LISTEN"; callback = listenToSession; } } else { // user is FAN; fan_access = TRUE if (payload.fan_access) { showNotification = true; okText = "LISTEN"; callback = listenToSession; } } if (showNotification) { handleNotification(payload, header.type); app.notify({ "title": "Band Joined Session", "text": payload.msg, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-listen", text: okText, "layout-action": "close", href: "#", "class": "button-orange", callback: callback, callback_args: { "session_id": payload.session_id, "fan_access": payload.fan_access, "musician_access": payload.musician_access, "approval_required": payload.approval_required, "notification_id": payload.notification_id } }] ); } }); } function registerScheduledSessionInvitation() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SCHEDULED_SESSION_INVITATION, function(header, payload) { logger.debug("Handling SCHEDULED_SESSION_INVITATION msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Session Invitation", "text": payload.msg + "

" + payload.session_name + "
" + payload.session_date, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-more-info", text: "MORE INFO", rel: "external", "class": "button-orange", callback: openSessionInfoWebPage, callback_args: { "session_id": payload.session_id } }] ); }); } function registerScheduledSessionRsvp() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SCHEDULED_SESSION_RSVP, function(header, payload) { logger.debug("Handling SCHEDULED_SESSION_RSVP msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Session RSVP", "text": payload.msg + "

" + payload.session_name + "
" + payload.session_date, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-manage-rsvp", text: "MANAGE RSVP", "class": "button-orange", callback: navigateToSessionDetails, callback_args: { "session_id": payload.session_id } }] ); }); } function registerScheduledSessionRsvpApproved() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SCHEDULED_SESSION_RSVP_APPROVED, function(header, payload) { logger.debug("Handling SCHEDULED_SESSION_RSVP_APPROVED msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Session RSVP Approved!", "text": payload.msg + "

" + payload.session_name + "
" + payload.session_date, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-session-details", text: "SESSION DETAILS", "layout-action": "close", rel: "external", "class": "button-orange", callback: openSessionInfoWebPage, callback_args: { "session_id": payload.session_id } }] ); }); } function registerScheduledSessionRsvpCancelled() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SCHEDULED_SESSION_RSVP_CANCELLED, function(header, payload) { logger.debug("Handling SCHEDULED_SESSION_RSVP_CANCELLED msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Session RSVP Cancelled", "text": payload.msg + "

" + payload.session_name + "
" + payload.session_date, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-session-details", text: "SESSION DETAILS", rel: "external", "class": "button-orange", callback: openSessionInfoWebPage, callback_args: { "session_id": payload.session_id } }] ); }); } function registerScheduledSessionRsvpCancelledOrg() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SCHEDULED_SESSION_RSVP_CANCELLED_ORG, function(header, payload) { logger.debug("Handling SCHEDULED_SESSION_RSVP_CANCELLED_ORG msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Session RSVP Cancelled", "text": payload.msg + "

" + payload.session_name + "
" + payload.session_date, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-session-details", text: "SESSION DETAILS", rel: "external", "class": "button-orange", callback: openSessionInfoWebPage, callback_args: { "session_id": payload.session_id } }] ); }); } function registerScheduledSessionCancelled() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SCHEDULED_SESSION_CANCELLED, function(header, payload) { logger.debug("Handling SCHEDULED_SESSION_CANCELLED msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Session Cancelled", "text": payload.msg + "

" + payload.session_name + "
" + payload.session_date, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-session-details", text: "SESSION DETAILS", rel: "external", "class": "button-orange", callback: openSessionInfoWebPage, callback_args: { "session_id": payload.session_id } }] ); }); } function registerScheduledSessionRescheduled() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SCHEDULED_SESSION_RESCHEDULED, function(header, payload) { logger.debug("Handling SCHEDULED_SESSION_RESCHEDULED msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Session Rescheduled", "text": payload.msg + "

" + payload.session_name + "
" + payload.session_date, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-session-details", text: "SESSION DETAILS", rel: "external", "class": "button-orange", callback: openSessionInfoWebPage, callback_args: { "session_id": payload.session_id } }] ); }); } function registerScheduledSessionReminder() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SCHEDULED_SESSION_REMINDER, function(header, payload) { logger.debug("Handling SCHEDULED_SESSION_REMINDER msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Session Reminder", "text": payload.msg + "

" + payload.session_name + "
" + payload.session_date, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-session-details", text: "SESSION DETAILS", rel: "external", "class": "button-orange", callback: openSessionInfoWebPage, callback_args: { "session_id": payload.session_id } }] ); }); } function registerScheduledSessionComment() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SCHEDULED_SESSION_COMMENT, function(header, payload) { logger.debug("Handling SCHEDULED_SESSION_COMMENT msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Session Comment", "text": payload.msg + "

" + payload.session_name + "
" + payload.session_date, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-session-details", text: "SESSION DETAILS", rel: "external", "class": "button-orange", callback: openSessionInfoWebPage, callback_args: { "session_id": payload.session_id } }] ); }); } function registerMusicianRecordingSaved() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.MUSICIAN_RECORDING_SAVED, function(header, payload) { logger.debug("Handling MUSICIAN_RECORDING_SAVED msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Musician Recording Saved", "text": payload.msg, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-listen", text: "LISTEN", "layout-action": "close", href: "#", "class": "button-orange", callback: listenToRecording, callback_args: { "recording_id": payload.recording_id, "notification_id": payload.notification_id } }] ); }); } function registerBandRecordingSaved() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_RECORDING_SAVED, function(header, payload) { logger.debug("Handling BAND_RECORDING_SAVED msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Band Recording Saved", "text": payload.msg, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-listen", text: "LISTEN", "layout-action": "close", href: "#", "class": "button-orange", callback: listenToRecording, callback_args: { "recording_id": payload.recording_id, "notification_id": payload.notification_id } }] ); }); } function registerRecordingMasterMixComplete() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.RECORDING_MASTER_MIX_COMPLETE, function(header, payload) { logger.debug("Handling RECORDING_MASTER_MIX_COMPLETE msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Recording Master Mix Complete", "text": payload.msg, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-share", text: "SHARE", "layout-action": "close", href: "#", "class": "button-orange", callback: shareRecording, callback_args: { "claimed_recording_id": payload.claimed_recording_id } }] ); }); } function registerRecordingStreamMixComplete() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.RECORDING_STREAM_MIX_COMPLETE, function(header, payload) { logger.debug("Handling RECORDING_STREAM_MIX_COMPLETE msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Recording Stream Mix Complete", "text": payload.msg, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-share", text: "SHARE", "layout-action": "close", href: "#", "class": "button-orange", callback: shareRecording, callback_args: { "claimed_recording_id": payload.claimed_recording_id } }] ); }); } function shareRecording(args) { var claimedRecordingId = args.claimed_recording_id; ui.launchShareDialog(claimedRecordingId, 'recording'); } function registerBandInvitation() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_INVITATION, function(header, payload) { logger.debug("Handling BAND_INVITATION msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Band Invitation", "text": payload.msg, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }, [{ id: "btn-accept", text: "ACCEPT", "layout-action": "close", href: "#", "class": "button-orange", callback: acceptBandInvitation, callback_args: { "band_invitation_id": payload.band_invitation_id, "band_id": payload.band_id, "notification_id": payload.notification_id } }] ); }); } function registerTextMessage() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.TEXT_MESSAGE, function(header, payload) { logger.debug("Handling TEXT_MESSAGE msg " + JSON.stringify(payload)); textMessageDialog.messageReceived(payload); handleNotification(payload, header.type); }); } function registerBandInvitationAccepted() { context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_INVITATION_ACCEPTED, function(header, payload) { logger.debug("Handling BAND_INVITATION_ACCEPTED msg " + JSON.stringify(payload)); handleNotification(payload, header.type); app.notify({ "title": "Band Invitation Accepted", "text": payload.msg, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) }); }); } // one important limitation; if the user is focused on an iframe, this will be false // however, if they are doing something with Facebook or the photo picker, this may actually still be desirable function userCanSeeNotifications(payload) { return document.hasFocus() && !app.layout.dialogObscuredNotification(payload); } // default handler for incoming notification function handleNotification(payload, type) { // on a load of notifications, it is possible to load a very new notification, // and get a websocket notification right after for that same notification, // so we need to protect against such duplicates if($list.find('li[notification-id="' + payload.notification_id + '"]').length > 0) { return false; } // add notification to sidebar var template = $notificationTemplate.html(); var notificationHtml = context.JK.fillTemplate(template, { notificationId: payload.notification_id, sessionId: payload.session_id, hoveraction: payload.session_id ? "session" : "", avatar_url: context.JK.resolveAvatarUrl(payload.photo_url), text: payload.msg instanceof jQuery ? payload.msg.html() : payload.msg , date: $.timeago(payload.created_at) }); $list.prepend(notificationHtml); onNotificationOccurred(payload); initializeActions(payload, type); return true; } function approveJoinRequest(args) { rest.updateJoinRequest(args.join_request_id, true) .done(function(response) { deleteNotification(args.notification_id); }).error(app.ajaxError); } function openTerms(args) { var termsDialog = new context.JK.TermsDialog(app, args, onTermsAccepted); termsDialog.initialize(); app.layout.showDialog('terms'); } function onTermsAccepted(args) { deleteNotification(args.notification_id); context.location = '/client#/session/' + args.session_id; } function rejectJoinRequest(args) { rest.updateJoinRequest(args.join_request_id, false) .done(function(response) { deleteNotification(args.notification_id); }).error(app.ajaxError); } function listenToRecording(args) { deleteNotification(args.notification_id); context.JK.popExternalLink('/recordings/' + args.recording_id); } function navigateToSessionDetails(args) { context.location = '/client#/account/sessionDetail/' + args.session_id; } function openSessionInfoWebPage(args) { context.JK.popExternalLink('/sessions/' + args.session_id + '/details'); } function deleteNotificationHandler(evt) { evt.stopPropagation(); var notificationId = $(this).attr('notification-id'); deleteNotification(notificationId); } function registerNotificationScroll() { $('.notification-scroller').scroll(function() { var wintop = $('.notification-scroller').scrollTop(); var winheight = $('.notification-scroller').height(); var docheight = $('#sidebar-notification-list').height(); var scrollTrigger = 0.90; // console.log("notification scroll: wintop="+wintop+" docheight="+docheight+" winheight="+winheight+" ratio="+(wintop / (docheight - winheight))); if ((wintop / (docheight - winheight)) > scrollTrigger) { populate(); } }); } function initialize(sidebarInstance, textMessageDialogInstance) { sidebar = sidebarInstance; textMessageDialog = textMessageDialogInstance; $panel = $('[layout-id="panelNotifications"]'); $expanded = $panel.find('.panel.expanded'); $contents = $panel.find('.panelcontents'); $count = $panel.find('#sidebar-notification-count'); $list = $panel.find('#sidebar-notification-list'); $notificationTemplate = $('#template-notification-panel'); if($panel.length == 0) throw "notifications panel not found" if($expanded.length == 0) throw "notifications expanded content not found" if($contents.length == 0) throw "notifications contents not found" if($count.length == 0) throw "notifications count element not found"; if($list.length == 0) throw "notification list element not found"; if($notificationTemplate.length == 0) throw "notification template not found"; registerNotificationScroll(); events(); populate(); }; this.initialize = initialize; this.onNotificationOccurred = onNotificationOccurred; }; })(window, jQuery);