added a notifications service

This commit is contained in:
Luke Pulverenti 2013-07-06 17:23:32 -04:00
parent 95a8a246b9
commit cfb3392c35
8 changed files with 411 additions and 4 deletions

View File

@ -243,6 +243,61 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
}); });
}; };
self.getNotificationSummary = function (userId) {
if (!userId) {
throw new Error("null userId");
}
var url = self.getUrl("Notifications/" + userId + "/Summary");
return self.ajax({
type: "GET",
url: url,
dataType: "json"
});
};
self.getNotifications = function (userId, options) {
if (!userId) {
throw new Error("null userId");
}
var url = self.getUrl("Notifications/" + userId, options || {});
return self.ajax({
type: "GET",
url: url,
dataType: "json"
});
};
self.markNotificationsRead = function (userId, idList, isRead) {
if (!userId) {
throw new Error("null userId");
}
if (!idList || !idList.length) {
throw new Error("null idList");
}
var suffix = isRead ? "Read" : "Unread";
var params = {
UserId: userId,
Ids: idList.join(',')
};
var url = self.getUrl("Notifications/" + userId + "/" + suffix, params);
return self.ajax({
type: "POST",
url: url
});
};
/** /**
* Gets the current server status * Gets the current server status
*/ */
@ -1937,7 +1992,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout) {
if (!item) { if (!item) {
throw new Error("null item"); throw new Error("null item");
} }
var url = self.getUrl("Artists/" + self.encodeName(item.Name)); var url = self.getUrl("Artists/" + self.encodeName(item.Name));
return self.ajax({ return self.ajax({

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,160 @@
.btnNotifications {
text-decoration: none;
vertical-align: middle;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
padding: 8px 12px;
text-align: center;
text-decoration: none !important;
-moz-user-select: none;
-webkit-user-select: none;
background-color: #f5f5f5;
background-image: -webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#f1f1f1));
background-image: -webkit-linear-gradient(top,#f5f5f5,#f1f1f1);
background-image: -moz-linear-gradient(top,#f5f5f5,#f1f1f1);
background-image: -ms-linear-gradient(top,#f5f5f5,#f1f1f1);
background-image: -o-linear-gradient(top,#f5f5f5,#f1f1f1);
background-image: linear-gradient(top,#f5f5f5,#f1f1f1);
border: 1px solid #dcdcdc;
color: #666;
}
.levelNormal {
background-color: #4d90fe;
background-image: -webkit-gradient(linear,left top,left bottom,from(#4d90fe),to(#4787ed));
background-image: -webkit-linear-gradient(top,#4d90fe,#4787ed);
background-image: -moz-linear-gradient(top,#4d90fe,#4787ed);
background-image: -ms-linear-gradient(top,#4d90fe,#4787ed);
background-image: -o-linear-gradient(top,#4d90fe,#4787ed);
background-image: linear-gradient(top,#4d90fe,#4787ed);
border-color: #3079ed;
color: #fff!important;
}
.levelWarning {
background-color: #FF7537;
background-image: none;
border-color: #FF7537;
color: #fff!important;
}
.levelError {
background-color: #d14836;
background-image: -webkit-gradient(linear,left top,left bottom,from(#dd4b39),to(#d14836));
background-image: -webkit-linear-gradient(top,#dd4b39,#d14836);
background-image: -moz-linear-gradient(top,#dd4b39,#d14836);
background-image: -ms-linear-gradient(top,#dd4b39,#d14836);
background-image: -o-linear-gradient(top,#dd4b39,#d14836);
background-image: linear-gradient(top,#dd4b39,#d14836);
border-color: #c6322a;
color: #fff!important;
}
.flyoutNotification {
border-top: 1px solid #ccc;
background: #f8f8f8;
color: #555;
}
.flyoutNotification p {
margin: .7em 0;
}
.notificationsFlyout {
width: 300px;
}
.notificationName {
font-weight: bold;
color: #555;
}
.notificationImage {
display: none;
}
.unreadFlyoutNotification {
background-color: #ECEEF4;
}
.btnMarkReadContainer {
padding: .5em;
}
.imgNotification, .imgNotificationInner {
width: 60px;
height: 60px;
}
.imgNotificationInner {
background-repeat: no-repeat;
background-size: contain;
background-position: center center;
}
.imgNotificationIcon {
background-size: 50% auto;
}
.imgNotificationNormal {
background-color: #4d90fe;
background-image: -webkit-gradient(linear,left top,left bottom,from(#4d90fe),to(#4787ed));
background-image: -webkit-linear-gradient(top,#4d90fe,#4787ed);
background-image: -moz-linear-gradient(top,#4d90fe,#4787ed);
background-image: -ms-linear-gradient(top,#4d90fe,#4787ed);
background-image: -o-linear-gradient(top,#4d90fe,#4787ed);
background-image: linear-gradient(top,#4d90fe,#4787ed);
}
.imgNotificationNormal .imgNotificationInner {
background-image: url(images/notifications/info.png);
}
.imgNotificationError {
background-color: #d14836;
background-image: -webkit-gradient(linear,left top,left bottom,from(#dd4b39),to(#d14836));
background-image: -webkit-linear-gradient(top,#dd4b39,#d14836);
background-image: -moz-linear-gradient(top,#dd4b39,#d14836);
background-image: -ms-linear-gradient(top,#dd4b39,#d14836);
background-image: -o-linear-gradient(top,#dd4b39,#d14836);
background-image: linear-gradient(top,#dd4b39,#d14836);
}
.imgNotificationError .imgNotificationInner {
background-image: url(images/notifications/error.png);
}
.imgNotificationWarning {
background-color: #FF7537;
}
.imgNotificationWarning .imgNotificationInner {
background-image: url(images/notifications/error.png);
}
@media all and (min-width: 500px) {
.notificationsFlyout {
width: 400px;
}
}
@media all and (min-width: 600px) {
.notificationsFlyout {
width: 500px;
}
.notificationImage {
display: inline-block;
vertical-align: top;
margin: 0 1em;
padding: .7em 0;
}
.notificationContent {
display: inline-block;
vertical-align: top;
}
}

View File

@ -35,7 +35,6 @@
text-decoration: none !important; text-decoration: none !important;
-moz-user-select: none; -moz-user-select: none;
-webkit-user-select: none; -webkit-user-select: none;
text-align: center;
} }
.txtSearch, .btnSearch { .txtSearch, .btnSearch {

View File

@ -0,0 +1,191 @@
(function ($, document, Dashboard) {
var userId;
var getNotificationsSummaryPromise;
function getNotificationsSummary() {
getNotificationsSummaryPromise = getNotificationsSummaryPromise || ApiClient.getNotificationSummary(userId);
return getNotificationsSummaryPromise;
}
function updateNotificationCount() {
getNotificationsSummary().done(function (summary) {
var elem = $('.btnNotifications').removeClass('levelNormal').removeClass('levelWarning').removeClass('levelError').html(summary.UnreadCount);
if (summary.UnreadCount) {
elem.addClass('level' + summary.MaxUnreadNotificationLevel);
}
});
}
function showNotificationsFlyout() {
var context = this;
var html = '<div data-role="popup" class="notificationsFlyout" style="min-width:200px;margin-top:30px;margin-right:20px;" class="ui-corner-all">';
html += '<a href="#" data-rel="back" data-role="button" data-theme="a" data-icon="delete" data-iconpos="notext" class="ui-btn-right">Close</a>';
html += '<div class="ui-corner-top ui-bar-a" style="text-align:center;">';
html += '<h3 style="margin: .5em 0;">Notifications</h3>';
html += '</div>';
html += '<div data-role="content" class="ui-corner-bottom ui-content" style="padding: 0;background: #f8f8f8;">';
html += '<p class="notificationsFlyoutlist">Loading...';
html += '</p>';
html += '<p style="display:none;" class="btnMarkReadContainer"><button class="btnMarkRead" type="button" data-icon="ok" data-mini="true">Mark these read</button></p>';
html += '</div>';
html += '</div>';
$(document.body).append(html);
$('.notificationsFlyout').popup({ positionTo: context }).trigger('create').popup("open").on("popupafterclose", function () {
$(this).off("popupafterclose").remove();
}).on('click', '.btnMarkRead', function () {
var ids = $('.unreadFlyoutNotification').map(function () {
return this.getAttribute('data-notificationid');
}).get();
ApiClient.markNotificationsRead(Dashboard.getCurrentUserId(), ids, true).done(function () {
$('.notificationsFlyout').popup("close");
});
});
refreshFlyoutContents();
}
function refreshFlyoutContents() {
var limit = 5;
var startIndex = 0;
ApiClient.getNotifications(Dashboard.getCurrentUserId(), { StartIndex: startIndex, Limit: limit }).done(function (result) {
listUnreadNotifications(result.Notifications, result.TotalRecordCount, startIndex, limit);
});
}
function listUnreadNotifications(notifications, totalRecordCount, startIndex, limit) {
var elem = $('.notificationsFlyoutlist');
if (!totalRecordCount) {
elem.html('<p>No unread notifications.</p>');
$('.btnMarkReadContainer').hide();
return;
}
if (notifications.filter(function(n) {
return !n.IsRead;
}).length) {
$('.btnMarkReadContainer').show();
} else {
$('.btnMarkReadContainer').hide();
}
var html = '';
for (var i = 0, length = notifications.length; i < length; i++) {
var notification = notifications[i];
html += getNotificationHtml(notification);
}
elem.html(html);
}
function getNotificationHtml(notification) {
var html = '';
var cssClass = notification.IsRead ? "flyoutNotification" : "flyoutNotification unreadFlyoutNotification";
html += '<div data-notificationid="' + notification.Id + '" class="' + cssClass + '">';
html += '<div class="notificationImage">';
html += getImageHtml(notification);
html += '</div>';
html += '<div class="notificationContent">';
html += '<p class="notificationName">' + notification.Name + '</p>';
html += '<p>' + humane_date(notification.Date) + '</p>';
if (notification.Description) {
html += '<p>' + notification.Description + '</p>';
}
html += '</div>';
html += '</div>';
return html;
}
function getImageHtml(notification) {
if (notification.Level == "Error") {
return '<div class="imgNotification imgNotificationError"><div class="imgNotificationInner imgNotificationIcon"></div></div>';
}
if (notification.Level == "Warning") {
return '<div class="imgNotification imgNotificationWarning"><div class="imgNotificationInner imgNotificationIcon"></div></div>';
}
return '<div class="imgNotification imgNotificationNormal"><div class="imgNotificationInner imgNotificationIcon"></div></div>';
}
$(Dashboard).on('interiorheaderrendered', function (e, header, user) {
if (!user || $('.notificationsButton', header).length) {
return;
}
userId = user.Id;
$('<a class="imageLink btnNotifications" href="#" title="Notifications">0</a>').insertAfter($('.btnCurrentUser', header)).on('click', showNotificationsFlyout);
updateNotificationCount();
});
$(ApiClient).on("websocketmessage", function (e, msg) {
if (msg.MessageType === "NotificationUpdated" || msg.MessageType === "NotificationAdded" || msg.MessageType === "NotificationsMarkedRead") {
getNotificationsSummaryPromise = null;
updateNotificationCount();
}
});
})(jQuery, document, Dashboard);

View File

@ -445,7 +445,7 @@ var Dashboard = {
html += '<a href="#" data-rel="back" data-role="button" data-theme="a" data-icon="delete" data-iconpos="notext" class="ui-btn-right">Close</a>'; html += '<a href="#" data-rel="back" data-role="button" data-theme="a" data-icon="delete" data-iconpos="notext" class="ui-btn-right">Close</a>';
html += '<div class="ui-corner-top ui-bar-a" style="text-align:center;">'; html += '<div class="ui-corner-top ui-bar-a" style="text-align:center;">';
html += '<h3>' + user.Name + '</h3>'; html += '<h3 style="margin: .5em 0;">' + user.Name + '</h3>';
html += '</div>'; html += '</div>';
html += '<div data-role="content" class="ui-corner-bottom ui-content">'; html += '<div data-role="content" class="ui-corner-bottom ui-content">';
@ -594,6 +594,8 @@ var Dashboard = {
} }
}); });
} }
$(Dashboard).trigger('interiorheaderrendered', [header, user]);
}, },
ensureToolsMenu: function (page) { ensureToolsMenu: function (page) {

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="MediaBrowser.ApiClient.Javascript" version="3.0.131" targetFramework="net45" /> <package id="MediaBrowser.ApiClient.Javascript" version="3.0.135" targetFramework="net45" />
<package id="ServiceStack.Common" version="3.9.54" targetFramework="net45" /> <package id="ServiceStack.Common" version="3.9.54" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.54" targetFramework="net45" /> <package id="ServiceStack.Text" version="3.9.54" targetFramework="net45" />
</packages> </packages>