From f7ba95439bcf3d70dcc634e719baded37f38c83d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 4 Nov 2014 07:41:12 -0500 Subject: [PATCH] add server management to web client --- dashboard-ui/css/card.css | 9 +- dashboard-ui/css/images/server.png | Bin 0 -> 3988 bytes dashboard-ui/css/librarybrowser.css | 7 + dashboard-ui/css/mediaplayer.css | 2 +- dashboard-ui/css/site.css | 2 +- dashboard-ui/scripts/medialibrarypage.js | 2 +- dashboard-ui/scripts/selectserver.js | 275 ++++++++++++++++-- dashboard-ui/scripts/site.js | 6 +- dashboard-ui/scripts/userparentalcontrol.js | 23 +- dashboard-ui/selectserver.html | 15 +- .../thirdparty/apiclient/connectionmanager.js | 68 ++++- 11 files changed, 363 insertions(+), 46 deletions(-) create mode 100644 dashboard-ui/css/images/server.png diff --git a/dashboard-ui/css/card.css b/dashboard-ui/css/card.css index cee9051ffe..6fa7ebefe7 100644 --- a/dashboard-ui/css/card.css +++ b/dashboard-ui/css/card.css @@ -89,6 +89,11 @@ background: #fff; } +.visualCardBox-b { + border-radius: 3px; + background: #111; +} + .cardScalable { position: relative; } @@ -125,7 +130,7 @@ right: 0; } - /*.cardContent:hover { +/*.cardContent:hover { -moz-box-shadow: 0 0 0 5px #38c; -webkit-box-shadow: 0 0 0 5px #38c; box-shadow: 0 0 0 5px #38c; @@ -723,4 +728,4 @@ .touch .mobileItemsContainer .homePageSquareCard { max-width: 200px; -}*/ \ No newline at end of file +}*/ diff --git a/dashboard-ui/css/images/server.png b/dashboard-ui/css/images/server.png new file mode 100644 index 0000000000000000000000000000000000000000..85818b8ef1206f45bc7a6dd7c462a52f041f6c99 GIT binary patch literal 3988 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 literal 0 HcmV?d00001 diff --git a/dashboard-ui/css/librarybrowser.css b/dashboard-ui/css/librarybrowser.css index 1f18d14891..7aab4a7950 100644 --- a/dashboard-ui/css/librarybrowser.css +++ b/dashboard-ui/css/librarybrowser.css @@ -108,6 +108,13 @@ top: 3px; } +@media all and (min-width: 600px) { + + .ehsContent { + width: 95%; + } +} + @media all and (min-width: 1200px) { .ehsContent { diff --git a/dashboard-ui/css/mediaplayer.css b/dashboard-ui/css/mediaplayer.css index 1cbb3bc10f..56f5059d90 100644 --- a/dashboard-ui/css/mediaplayer.css +++ b/dashboard-ui/css/mediaplayer.css @@ -90,7 +90,7 @@ } .sliderContainer .ui-slider-track { - margin-left: 15px !important; + margin: 0 15px !important; } .volumeSliderContainer .ui-slider-track { diff --git a/dashboard-ui/css/site.css b/dashboard-ui/css/site.css index 04aa43678a..9a5363a0f2 100644 --- a/dashboard-ui/css/site.css +++ b/dashboard-ui/css/site.css @@ -42,7 +42,7 @@ /* For some reason jquery mobile 1.4.5 wants to horitontally pad mini form fields. */ .ui-mini { - margin: .5em 0; + margin-left: 0; } * { diff --git a/dashboard-ui/scripts/medialibrarypage.js b/dashboard-ui/scripts/medialibrarypage.js index 01becfb6c8..12c0cab272 100644 --- a/dashboard-ui/scripts/medialibrarypage.js +++ b/dashboard-ui/scripts/medialibrarypage.js @@ -111,7 +111,7 @@ html += ''; if (addPathMappingInfo) { - html += '

'+Globalize.translate('LabelPathSubstitutionHelp')+'

'; + html += '
' + Globalize.translate('LabelPathSubstitutionHelp') + '
'; } html += '

'; diff --git a/dashboard-ui/scripts/selectserver.js b/dashboard-ui/scripts/selectserver.js index 3f6a66097c..286d25f884 100644 --- a/dashboard-ui/scripts/selectserver.js +++ b/dashboard-ui/scripts/selectserver.js @@ -37,6 +37,58 @@ }); } + function getServerHtml(server) { + + var html = ''; + + var cssClass = "card homePageSquareCard alternateHover bottomPaddedCard"; + + html += "

"; + + html += '
'; + html += '
'; + + html += '
'; + + var href = "#"; + html += ''; + + var imgUrl = 'css/images/server.png'; + + html += '
'; + + html += "
"; + + // cardContent + html += "
"; + + // cardScalable + html += "
"; + + html += '
'; + + html += '
'; + + //html += ''; + + html += "
"; + + html += '
'; + html += server.Name; + html += "
"; + + // cardFooter + html += "
"; + + // cardBox + html += "
"; + + // card + html += "
"; + + return html; + } + function renderServers(page, servers) { if (servers.length) { @@ -45,27 +97,9 @@ $('.noServersMessage', page).show(); } - var html = ''; + html += servers.map(getServerHtml).join(''); var elem = $('.serverList', page).html(html).trigger('create'); @@ -78,6 +112,205 @@ connectToServer(page, server); }); + + $('.btnServerMenu', elem).on('click', function () { + showServerMenu(this); + }); + } + + function showGeneralError() { + + // Need the timeout because jquery mobile will not show a popup if there's currently already one in the process of closing + setTimeout(function () { + + Dashboard.hideLoadingMsg(); + Dashboard.alert({ + message: Globalize.translate('DefaultErrorMessage') + }); + }, 300); + + } + + function acceptInvitation(page, id) { + + Dashboard.showLoadingMsg(); + + // Add/Update connect info + ConnectionManager.acceptServer(id).done(function () { + + Dashboard.hideLoadingMsg(); + loadPage(page); + + }).fail(function () { + + showGeneralError(); + }); + } + + function rejectInvitation(page, id) { + + Dashboard.showLoadingMsg(); + + // Add/Update connect info + ConnectionManager.deleteServer(id).done(function () { + + Dashboard.hideLoadingMsg(); + loadPage(page); + + }).fail(function () { + + showGeneralError(); + + }); + } + + function showServerMenu(elem) { + + var card = $(elem).parents('.card'); + var page = $(elem).parents('.page'); + var id = card.attr('data-id'); + + $('.serverMenu', page).popup("close").remove(); + + var html = '
'; + + html += ''; + + html += '
'; + + page.append(html); + + var flyout = $('.serverMenu', page).popup({ positionTo: elem || "window" }).trigger('create').popup("open").on("popupafterclose", function () { + + $(this).off("popupafterclose").remove(); + + }); + + $('.btnDelete', flyout).on('click', function () { + rejectInvitation(page, this.getAttribute('data-id')); + $('.serverMenu', page).popup("close").remove(); + }); + } + + function showPendingInviteMenu(elem) { + + var card = $(elem).parents('.card'); + var page = $(elem).parents('.page'); + var id = card.attr('data-id'); + + $('.inviteMenu', page).popup("close").remove(); + + var html = '
'; + + html += ''; + + html += '
'; + + page.append(html); + + var flyout = $('.inviteMenu', page).popup({ positionTo: elem || "window" }).trigger('create').popup("open").on("popupafterclose", function () { + + $(this).off("popupafterclose").remove(); + + }); + + $('.btnAccept', flyout).on('click', function () { + acceptInvitation(page, this.getAttribute('data-id')); + $('.inviteMenu', page).popup("close").remove(); + }); + + $('.btnReject', flyout).on('click', function () { + rejectInvitation(page, this.getAttribute('data-id')); + $('.inviteMenu', page).popup("close").remove(); + }); + } + + function getPendingInviteHtml(invite) { + + var html = ''; + + var cssClass = "card homePageSquareCard alternateHover bottomPaddedCard"; + + html += "
"; + + html += '
'; + html += '
'; + + html += '
'; + + var href = "#"; + html += ''; + + var imgUrl = 'css/images/server.png'; + + html += '
'; + + html += "
"; + + // cardContent + html += "
"; + + // cardScalable + html += "
"; + + html += '
'; + + html += '
'; + + html += ''; + html += "
"; + + html += '
'; + html += invite.Name; + html += "
"; + + // cardFooter + html += "
"; + + // cardBox + html += "
"; + + // card + html += "
"; + + return html; + } + + function renderInvitations(page, list) { + + if (list.length) { + $('.invitationSection', page).show(); + } else { + $('.invitationSection', page).hide(); + } + + var html = list.map(getPendingInviteHtml).join(''); + + var elem = $('.invitationList', page).html(html).trigger('create'); + + $('.btnInviteMenu', elem).on('click', function () { + showPendingInviteMenu(this); + }); + } + + function loadInvitations(page) { + + ConnectionManager.getUserInvitations().done(function (list) { + + renderInvitations(page, list); + + }); } function loadPage(page) { @@ -90,6 +323,8 @@ Dashboard.hideLoadingMsg(); }); + + loadInvitations(page); } $(document).on('pageshow', "#selectServerPage", function () { diff --git a/dashboard-ui/scripts/site.js b/dashboard-ui/scripts/site.js index 005dc62603..b761374ab6 100644 --- a/dashboard-ui/scripts/site.js +++ b/dashboard-ui/scripts/site.js @@ -437,7 +437,7 @@ var Dashboard = { Dashboard.alert("Settings saved."); }, - defaultErrorMessage: "There was an error processing the request.", + defaultErrorMessage: Globalize.translate('DefaultErrorMessage'), processServerConfigurationUpdateResult: function (result) { @@ -567,11 +567,13 @@ var Dashboard = { html += '
'; + var isConnectMode = Dashboard.isConnectMode(); + if (user.localUser && user.localUser.Configuration.EnableUserPreferenceAccess) { html += '

' + Globalize.translate('ButtonMyPreferences') + ''; } - if (Dashboard.isConnectMode()) { + if (isConnectMode) { html += '

' + Globalize.translate('ButtonSelectServer') + ''; } diff --git a/dashboard-ui/scripts/userparentalcontrol.js b/dashboard-ui/scripts/userparentalcontrol.js index d4bd4d5abd..521893e55d 100644 --- a/dashboard-ui/scripts/userparentalcontrol.js +++ b/dashboard-ui/scripts/userparentalcontrol.js @@ -111,12 +111,6 @@ Dashboard.hideLoadingMsg(); } - function getDisplayTime(hour) { - - return new Date(2000, 1, 1, hour, 0, 0, 0).toLocaleTimeString(); - - } - function deleteAccessSchedule(page, schedules, index) { schedules.splice(index, 1); @@ -214,6 +208,19 @@ } }; + function getDisplayTime(hours) { + + var minutes = 0; + + var pct = hours % 1; + + if (pct) { + minutes = parseInt(pct * 60); + } + + return new Date(2000, 1, 1, hours, minutes, 0, 0).toLocaleTimeString(); + } + function populateHours(page) { var html = ''; @@ -223,6 +230,8 @@ html += ''; } + html += ''; + $('#selectStart', page).html(html).selectmenu('refresh'); $('#selectEnd', page).html(html).selectmenu('refresh'); } @@ -290,7 +299,7 @@ $('.btnAddSchedule', page).on('click', function () { - showSchedulePopup(page, {}, -1); + showSchedulePopup(page, {}, -1); }); populateHours(page); diff --git a/dashboard-ui/selectserver.html b/dashboard-ui/selectserver.html index 5b9405cf8d..e1b6273b25 100644 --- a/dashboard-ui/selectserver.html +++ b/dashboard-ui/selectserver.html @@ -8,14 +8,23 @@

-
-

${HeaderSelectServer}

+
+

${HeaderSelectServer}


-
diff --git a/dashboard-ui/thirdparty/apiclient/connectionmanager.js b/dashboard-ui/thirdparty/apiclient/connectionmanager.js index f3b1aca3b9..87bed7d3f6 100644 --- a/dashboard-ui/thirdparty/apiclient/connectionmanager.js +++ b/dashboard-ui/thirdparty/apiclient/connectionmanager.js @@ -751,19 +751,25 @@ }); }; + function replaceAll(str, find, replace) { + + return str.split(find).join(replace); + + //return str.replace(new RegExp(find, 'g'), replace); + } + self.getConnectPasswordHash = function (password) { password = password || ''; - password = password - .replace("&", "&") - .replace("/", "\") - .replace("!", "!") - .replace("$", "$") - .replace("\"", """) - .replace("<", "<") - .replace(">", ">") - .replace("'", "'"); + password = replaceAll(password, "&", "&"); + password = replaceAll(password, "/", "\"); + password = replaceAll(password, "!", "!"); + password = replaceAll(password, "$", "$"); + password = replaceAll(password, "\"", """); + password = replaceAll(password, "<", "<"); + password = replaceAll(password, ">", ">"); + password = replaceAll(password, "'", "'"); return CryptoJS.MD5(password).toString(); }; @@ -784,6 +790,50 @@ })[0]; }; + + self.getUserInvitations = function () { + + var url = "https://connect.mediabrowser.tv/service/servers?userId=" + self.connectUserId() + "&status=Waiting"; + + return $.ajax({ + type: "GET", + url: url, + dataType: "json", + headers: { + "X-Connect-UserToken": self.connectToken() + } + + }); + }; + + self.deleteServer = function (serverId) { + + var url = "https://connect.mediabrowser.tv/service/serverAuthorizations?serverId=" + serverId + "&userId=" + self.connectUserId(); + + return $.ajax({ + type: "DELETE", + url: url, + headers: { + "X-Connect-UserToken": self.connectToken() + } + + }); + }; + + self.acceptServer = function (authorizationId) { + + var url = "https://connect.mediabrowser.tv/service/ServerAuthorizations/accept?id=" + authorizationId; + + return $.ajax({ + type: "GET", + url: url, + headers: { + "X-Connect-UserToken": self.connectToken() + } + + }); + }; + }; })(window, jQuery); \ No newline at end of file