1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Merge remote-tracking branch 'upstream/master' into hwaccel

This commit is contained in:
Vasily 2020-06-08 15:41:14 +03:00
commit be6c4a2ba4
506 changed files with 27834 additions and 23514 deletions

View file

@ -0,0 +1,83 @@
define(['datetime', 'loading', 'libraryMenu', 'dom', 'globalize', 'emby-button'], function (datetime, loading, libraryMenu, dom, globalize) {
'use strict';
function revoke(page, key) {
require(['confirm'], function (confirm) {
confirm(globalize.translate('MessageConfirmRevokeApiKey'), globalize.translate('HeaderConfirmRevokeApiKey')).then(function () {
loading.show();
ApiClient.ajax({
type: 'DELETE',
url: ApiClient.getUrl('Auth/Keys/' + key)
}).then(function () {
loadData(page);
});
});
});
}
function renderKeys(page, keys) {
var rows = keys.map(function (item) {
var html = '';
html += '<tr class="detailTableBodyRow detailTableBodyRow-shaded">';
html += '<td class="detailTableBodyCell">';
html += '<button type="button" is="emby-button" data-token="' + item.AccessToken + '" class="raised raised-mini btnRevoke" data-mini="true" title="' + globalize.translate('ButtonRevoke') + '" style="margin:0;">' + globalize.translate('ButtonRevoke') + '</button>';
html += '</td>';
html += '<td class="detailTableBodyCell" style="vertical-align:middle;">';
html += item.AccessToken;
html += '</td>';
html += '<td class="detailTableBodyCell" style="vertical-align:middle;">';
html += item.AppName || '';
html += '</td>';
html += '<td class="detailTableBodyCell" style="vertical-align:middle;">';
var date = datetime.parseISO8601Date(item.DateCreated, true);
html += datetime.toLocaleDateString(date) + ' ' + datetime.getDisplayTime(date);
html += '</td>';
return html += '</tr>';
}).join('');
page.querySelector('.resultBody').innerHTML = rows;
loading.hide();
}
function loadData(page) {
loading.show();
ApiClient.getJSON(ApiClient.getUrl('Auth/Keys')).then(function (result) {
renderKeys(page, result.Items);
});
}
function showNewKeyPrompt(page) {
require(['prompt'], function (prompt) {
prompt({
title: globalize.translate('HeaderNewApiKey'),
label: globalize.translate('LabelAppName'),
description: globalize.translate('LabelAppNameExample')
}).then(function (value) {
ApiClient.ajax({
type: 'POST',
url: ApiClient.getUrl('Auth/Keys', {
App: value
})
}).then(function () {
loadData(page);
});
});
});
}
pageIdOn('pageinit', 'apiKeysPage', function () {
var page = this;
page.querySelector('.btnNewKey').addEventListener('click', function () {
showNewKeyPrompt(page);
});
page.querySelector('.tblApiKeys').addEventListener('click', function (e) {
var btnRevoke = dom.parentWithClass(e.target, 'btnRevoke');
if (btnRevoke) {
revoke(page, btnRevoke.getAttribute('data-token'));
}
});
});
pageIdOn('pagebeforeshow', 'apiKeysPage', function () {
loadData(this);
});
});

View file

@ -1,24 +1,24 @@
define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globalize", "date-fns", "dfnshelper", "loading", "connectionManager", "playMethodHelper", "cardBuilder", "imageLoader", "components/activitylog", "scripts/imagehelper", "indicators", "listViewStyle", "emby-button", "flexStyles", "emby-button", "emby-itemscontainer"], function (datetime, events, itemHelper, serverNotifications, dom, globalize, datefns, dfnshelper, loading, connectionManager, playMethodHelper, cardBuilder, imageLoader, ActivityLog, imageHelper, indicators) {
"use strict";
define(['datetime', 'events', 'itemHelper', 'serverNotifications', 'dom', 'globalize', 'date-fns', 'dfnshelper', 'loading', 'connectionManager', 'playMethodHelper', 'cardBuilder', 'imageLoader', 'components/activitylog', 'scripts/imagehelper', 'indicators', 'listViewStyle', 'emby-button', 'flexStyles', 'emby-button', 'emby-itemscontainer'], function (datetime, events, itemHelper, serverNotifications, dom, globalize, datefns, dfnshelper, loading, connectionManager, playMethodHelper, cardBuilder, imageLoader, ActivityLog, imageHelper, indicators) {
'use strict';
function showPlaybackInfo(btn, session) {
require(["alert"], function (alert) {
require(['alert'], function (alert) {
var title;
var text = [];
var displayPlayMethod = playMethodHelper.getDisplayPlayMethod(session);
if (displayPlayMethod === "DirectStream") {
title = globalize.translate("DirectStreaming");
text.push(globalize.translate("DirectStreamHelp1"));
text.push("<br/>");
text.push(globalize.translate("DirectStreamHelp2"));
} else if (displayPlayMethod === "Transcode") {
title = globalize.translate("Transcoding");
text.push(globalize.translate("MediaIsBeingConverted"));
if (displayPlayMethod === 'DirectStream') {
title = globalize.translate('DirectStreaming');
text.push(globalize.translate('DirectStreamHelp1'));
text.push('<br/>');
text.push(globalize.translate('DirectStreamHelp2'));
} else if (displayPlayMethod === 'Transcode') {
title = globalize.translate('Transcoding');
text.push(globalize.translate('MediaIsBeingConverted'));
if (session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length) {
text.push("<br/>");
text.push(globalize.translate("LabelReasonForTranscoding"));
text.push('<br/>');
text.push(globalize.translate('LabelReasonForTranscoding'));
session.TranscodingInfo.TranscodeReasons.forEach(function (transcodeReason) {
text.push(globalize.translate(transcodeReason));
});
@ -26,18 +26,18 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
}
alert({
text: text.join("<br/>"),
text: text.join('<br/>'),
title: title
});
});
}
function showSendMessageForm(btn, session) {
require(["prompt"], function (prompt) {
require(['prompt'], function (prompt) {
prompt({
title: globalize.translate("HeaderSendMessage"),
label: globalize.translate("LabelMessageText"),
confirmText: globalize.translate("ButtonSend")
title: globalize.translate('HeaderSendMessage'),
label: globalize.translate('LabelMessageText'),
confirmText: globalize.translate('ButtonSend')
}).then(function (text) {
if (text) {
connectionManager.getApiClient(session.ServerId).sendMessageCommand(session.Id, {
@ -50,20 +50,20 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
}
function showOptionsMenu(btn, session) {
require(["actionsheet"], function (actionsheet) {
require(['actionsheet'], function (actionsheet) {
var menuItems = [];
if (session.ServerId && session.DeviceId !== connectionManager.deviceId()) {
menuItems.push({
name: globalize.translate("SendMessage"),
id: "sendmessage"
name: globalize.translate('SendMessage'),
id: 'sendmessage'
});
}
if (session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length) {
menuItems.push({
name: globalize.translate("ViewPlaybackInfo"),
id: "transcodinginfo"
name: globalize.translate('ViewPlaybackInfo'),
id: 'transcodinginfo'
});
}
@ -72,11 +72,11 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
positionTo: btn
}).then(function (id) {
switch (id) {
case "sendmessage":
case 'sendmessage':
showSendMessageForm(btn, session);
break;
case "transcodinginfo":
case 'transcodinginfo':
showPlaybackInfo(btn, session);
}
});
@ -84,28 +84,28 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
}
function onActiveDevicesClick(evt) {
var btn = dom.parentWithClass(evt.target, "sessionCardButton");
var btn = dom.parentWithClass(evt.target, 'sessionCardButton');
if (btn) {
var card = dom.parentWithClass(btn, "card");
var card = dom.parentWithClass(btn, 'card');
if (card) {
var sessionId = card.id;
var session = (DashboardPage.sessionsList || []).filter(function (dashboardSession) {
return "session" + dashboardSession.Id === sessionId;
return 'session' + dashboardSession.Id === sessionId;
})[0];
if (session) {
if (btn.classList.contains("btnCardOptions")) {
if (btn.classList.contains('btnCardOptions')) {
showOptionsMenu(btn, session);
} else if (btn.classList.contains("btnSessionInfo")) {
} else if (btn.classList.contains('btnSessionInfo')) {
showPlaybackInfo(btn, session);
} else if (btn.classList.contains("btnSessionSendMessage")) {
} else if (btn.classList.contains('btnSessionSendMessage')) {
showSendMessageForm(btn, session);
} else if (btn.classList.contains("btnSessionStop")) {
connectionManager.getApiClient(session.ServerId).sendPlayStateCommand(session.Id, "Stop");
} else if (btn.classList.contains("btnSessionPlayPause") && session.PlayState) {
connectionManager.getApiClient(session.ServerId).sendPlayStateCommand(session.Id, "PlayPause");
} else if (btn.classList.contains('btnSessionStop')) {
connectionManager.getApiClient(session.ServerId).sendPlayStateCommand(session.Id, 'Stop');
} else if (btn.classList.contains('btnSessionPlayPause') && session.PlayState) {
connectionManager.getApiClient(session.ServerId).sendPlayStateCommand(session.Id, 'PlayPause');
}
}
}
@ -135,31 +135,31 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
apiClient.getLiveTvRecordings({
UserId: Dashboard.getCurrentUserId(),
IsInProgress: true,
Fields: "CanDelete,PrimaryImageAspectRatio",
Fields: 'CanDelete,PrimaryImageAspectRatio',
EnableTotalRecordCount: false,
EnableImageTypes: "Primary,Thumb,Backdrop"
EnableImageTypes: 'Primary,Thumb,Backdrop'
}).then(function (result) {
var itemsContainer = view.querySelector(".activeRecordingItems");
var itemsContainer = view.querySelector('.activeRecordingItems');
if (!result.Items.length) {
view.querySelector(".activeRecordingsSection").classList.add("hide");
return void(itemsContainer.innerHTML = "");
view.querySelector('.activeRecordingsSection').classList.add('hide');
return void(itemsContainer.innerHTML = '');
}
view.querySelector(".activeRecordingsSection").classList.remove("hide");
view.querySelector('.activeRecordingsSection').classList.remove('hide');
itemsContainer.innerHTML = cardBuilder.getCardsHtml({
items: result.Items,
shape: "auto",
defaultShape: "backdrop",
shape: 'auto',
defaultShape: 'backdrop',
showTitle: true,
showParentTitle: true,
coverImage: true,
cardLayout: false,
centerText: true,
preferThumb: "auto",
preferThumb: 'auto',
overlayText: false,
overlayMoreButton: true,
action: "none",
action: 'none',
centerPlayButton: true
});
imageLoader.lazyChildren(itemsContainer);
@ -168,28 +168,22 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
function reloadSystemInfo(view, apiClient) {
apiClient.getSystemInfo().then(function (systemInfo) {
view.querySelector("#serverName").innerHTML = globalize.translate("DashboardServerName", systemInfo.ServerName);
var localizedVersion = globalize.translate("DashboardVersionNumber", systemInfo.Version);
view.querySelector('#serverName').innerHTML = globalize.translate('DashboardServerName', systemInfo.ServerName);
var localizedVersion = globalize.translate('DashboardVersionNumber', systemInfo.Version);
if (systemInfo.SystemUpdateLevel !== "Release") {
localizedVersion += " " + systemInfo.SystemUpdateLevel;
if (systemInfo.SystemUpdateLevel !== 'Release') {
localizedVersion += ' ' + systemInfo.SystemUpdateLevel;
}
view.querySelector("#versionNumber").innerHTML = localizedVersion;
view.querySelector("#operatingSystem").innerHTML = globalize.translate("DashboardOperatingSystem", systemInfo.OperatingSystem);
view.querySelector("#architecture").innerHTML = globalize.translate("DashboardArchitecture", systemInfo.SystemArchitecture);
view.querySelector('#versionNumber').innerHTML = localizedVersion;
view.querySelector('#operatingSystem').innerHTML = globalize.translate('DashboardOperatingSystem', systemInfo.OperatingSystem);
view.querySelector('#architecture').innerHTML = globalize.translate('DashboardArchitecture', systemInfo.SystemArchitecture);
if (systemInfo.CanSelfRestart) {
view.querySelector("#btnRestartServer").classList.remove("hide");
} else {
view.querySelector("#btnRestartServer").classList.add("hide");
}
view.querySelector("#cachePath").innerHTML = systemInfo.CachePath;
view.querySelector("#logPath").innerHTML = systemInfo.LogPath;
view.querySelector("#transcodePath").innerHTML = systemInfo.TranscodingTempPath;
view.querySelector("#metadataPath").innerHTML = systemInfo.InternalMetadataPath;
view.querySelector("#webPath").innerHTML = systemInfo.WebPath;
view.querySelector('#cachePath').innerHTML = systemInfo.CachePath;
view.querySelector('#logPath').innerHTML = systemInfo.LogPath;
view.querySelector('#transcodePath').innerHTML = systemInfo.TranscodingTempPath;
view.querySelector('#metadataPath').innerHTML = systemInfo.InternalMetadataPath;
view.querySelector('#webPath').innerHTML = systemInfo.WebPath;
});
}
@ -211,25 +205,25 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
}
function renderActiveConnections(view, sessions) {
var html = "";
var html = '';
DashboardPage.sessionsList = sessions;
var parentElement = view.querySelector(".activeDevices");
var cardElem = parentElement.querySelector(".card");
var parentElement = view.querySelector('.activeDevices');
var cardElem = parentElement.querySelector('.card');
if (cardElem) {
cardElem.classList.add("deadSession");
cardElem.classList.add('deadSession');
}
for (var i = 0, length = sessions.length; i < length; i++) {
var session = sessions[i];
var rowId = "session" + session.Id;
var elem = view.querySelector("#" + rowId);
var rowId = 'session' + session.Id;
var elem = view.querySelector('#' + rowId);
if (elem) {
DashboardPage.updateSession(elem, session);
} else {
var nowPlayingItem = session.NowPlayingItem;
var className = "scalableCard card activeSession backdropCard backdropCard-scalable";
var className = 'scalableCard card activeSession backdropCard backdropCard-scalable';
html += '<div class="' + className + '" id="' + rowId + '">';
html += '<div class="cardBox visualCardBox">';
html += '<div class="cardScalable visualCardBox-cardScalable">';
@ -253,65 +247,65 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
}
html += '<div class="sessionAppName" style="display:inline-block;">';
html += '<div class="sessionDeviceName">' + session.DeviceName + "</div>";
html += '<div class="sessionAppSecondaryText">' + DashboardPage.getAppSecondaryText(session) + "</div>";
html += "</div>";
html += "</div>";
html += '<div class="sessionDeviceName">' + session.DeviceName + '</div>';
html += '<div class="sessionAppSecondaryText">' + DashboardPage.getAppSecondaryText(session) + '</div>';
html += '</div>';
html += '</div>';
html += '<div class="sessionNowPlayingDetails">';
var nowPlayingName = DashboardPage.getNowPlayingName(session);
html += '<div class="sessionNowPlayingInfo" data-imgsrc="' + nowPlayingName.image + '">';
html += nowPlayingName.html;
html += "</div>";
html += '<div class="sessionNowPlayingTime">' + DashboardPage.getSessionNowPlayingTime(session) + "</div>";
html += '</div>';
html += '<div class="sessionNowPlayingTime">' + DashboardPage.getSessionNowPlayingTime(session) + '</div>';
html += '</div>';
if (nowPlayingItem && nowPlayingItem.RunTimeTicks) {
var percent = 100 * (session.PlayState.PositionTicks || 0) / nowPlayingItem.RunTimeTicks;
html += indicators.getProgressHtml(percent, {
containerClass: "playbackProgress"
containerClass: 'playbackProgress'
});
} else {
// need to leave the element in just in case the device starts playback
html += indicators.getProgressHtml(0, {
containerClass: "playbackProgress hide"
containerClass: 'playbackProgress hide'
});
}
if (session.TranscodingInfo && session.TranscodingInfo.CompletionPercentage) {
var percent = session.TranscodingInfo.CompletionPercentage.toFixed(1);
html += indicators.getProgressHtml(percent, {
containerClass: "transcodingProgress"
containerClass: 'transcodingProgress'
});
} else {
// same issue as playbackProgress element above
html += indicators.getProgressHtml(0, {
containerClass: "transcodingProgress hide"
containerClass: 'transcodingProgress hide'
});
}
html += "</div>";
html += "</div>";
html += "</div>";
html += '</div>';
html += '</div>';
html += '</div>';
html += '<div class="sessionCardFooter cardFooter">';
html += '<div class="sessionCardButtons flex align-items-center justify-content-center">';
var btnCssClass = session.ServerId && session.NowPlayingItem && session.SupportsRemoteControl ? "" : " hide";
var playIcon = session.PlayState.IsPaused ? 'pause' : 'play';
var btnCssClass = session.ServerId && session.NowPlayingItem && session.SupportsRemoteControl ? '' : ' hide';
const playIcon = session.PlayState.IsPaused ? 'pause' : 'play_arrow';
html += '<button is="paper-icon-button-light" class="sessionCardButton btnSessionPlayPause paper-icon-button-light ' + btnCssClass + '"><i class="material-icons">' + playIcon + '</i></button>';
html += '<button is="paper-icon-button-light" class="sessionCardButton btnSessionStop paper-icon-button-light ' + btnCssClass + '"><i class="material-icons">stop</i></button>';
html += '<button is="paper-icon-button-light" class="sessionCardButton btnSessionPlayPause paper-icon-button-light ' + btnCssClass + '"><span class="material-icons ' + playIcon + '"></span></button>';
html += '<button is="paper-icon-button-light" class="sessionCardButton btnSessionStop paper-icon-button-light ' + btnCssClass + '"><span class="material-icons stop"></span></button>';
btnCssClass = session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length ? "" : " hide";
html += '<button is="paper-icon-button-light" class="sessionCardButton btnSessionInfo paper-icon-button-light ' + btnCssClass + '" title="' + globalize.translate("ViewPlaybackInfo") + '"><i class="material-icons">info</i></button>';
btnCssClass = session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length ? '' : ' hide';
html += '<button is="paper-icon-button-light" class="sessionCardButton btnSessionInfo paper-icon-button-light ' + btnCssClass + '" title="' + globalize.translate('ViewPlaybackInfo') + '"><span class="material-icons info"></span></button>';
btnCssClass = session.ServerId && -1 !== session.SupportedCommands.indexOf("DisplayMessage") && session.DeviceId !== connectionManager.deviceId() ? "" : " hide";
html += '<button is="paper-icon-button-light" class="sessionCardButton btnSessionSendMessage paper-icon-button-light ' + btnCssClass + '" title="' + globalize.translate("SendMessage") + '"><i class="material-icons">message</i></button>';
html += "</div>";
btnCssClass = session.ServerId && -1 !== session.SupportedCommands.indexOf('DisplayMessage') && session.DeviceId !== connectionManager.deviceId() ? '' : ' hide';
html += '<button is="paper-icon-button-light" class="sessionCardButton btnSessionSendMessage paper-icon-button-light ' + btnCssClass + '" title="' + globalize.translate('SendMessage') + '"><span class="material-icons message"></span></button>';
html += '</div>';
html += '<div class="sessionNowPlayingStreamInfo" style="padding:.5em 0 1em;">';
html += DashboardPage.getSessionNowPlayingStreamInfo(session);
html += "</div>";
html += '</div>';
html += '<div class="flex align-items-center justify-content-center">';
var userImage = DashboardPage.getUserImage(session);
@ -319,16 +313,16 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
html += '<div class="sessionUserName">';
html += DashboardPage.getUsersHtml(session);
html += "</div>";
html += "</div>";
html += "</div>";
html += "</div>";
html += "</div>";
html += '</div>';
html += '</div>';
html += '</div>';
html += '</div>';
html += '</div>';
}
}
parentElement.insertAdjacentHTML("beforeend", html);
var deadSessionElem = parentElement.querySelector(".deadSession");
parentElement.insertAdjacentHTML('beforeend', html);
var deadSessionElem = parentElement.querySelector('.deadSession');
if (deadSessionElem) {
deadSessionElem.parentNode.removeChild(deadSessionElem);
@ -336,9 +330,9 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
}
function renderRunningTasks(view, tasks) {
var html = "";
var html = '';
tasks = tasks.filter(function (task) {
if ("Idle" != task.State) {
if ('Idle' != task.State) {
return !task.IsHidden;
}
@ -346,59 +340,59 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
});
if (tasks.length) {
view.querySelector(".runningTasksContainer").classList.remove("hide");
view.querySelector('.runningTasksContainer').classList.remove('hide');
} else {
view.querySelector(".runningTasksContainer").classList.add("hide");
view.querySelector('.runningTasksContainer').classList.add('hide');
}
for (var i = 0, length = tasks.length; i < length; i++) {
var task = tasks[i];
html += "<p>";
html += task.Name + "<br/>";
html += '<p>';
html += task.Name + '<br/>';
if (task.State === "Running") {
if (task.State === 'Running') {
var progress = (task.CurrentProgressPercentage || 0).toFixed(1);
html += '<progress max="100" value="' + progress + '" title="' + progress + '%">';
html += progress + "%";
html += "</progress>";
html += "<span style='color:#00a4dc;margin-left:5px;margin-right:5px;'>" + progress + "%</span>";
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate("ButtonStop") + '" onclick="DashboardPage.stopTask(this, \'' + task.Id + '\');" class="autoSize"><i class="material-icons">cancel</i></button>';
} else if (task.State === "Cancelling") {
html += '<span style="color:#cc0000;">' + globalize.translate("LabelStopping") + "</span>";
html += progress + '%';
html += '</progress>';
html += "<span style='color:#00a4dc;margin-left:5px;margin-right:5px;'>" + progress + '%</span>';
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonStop') + '" onclick="DashboardPage.stopTask(this, \'' + task.Id + '\');" class="autoSize"><span class="material-icons cancel"></span></button>';
} else if (task.State === 'Cancelling') {
html += '<span style="color:#cc0000;">' + globalize.translate('LabelStopping') + '</span>';
}
html += "</p>";
html += '</p>';
}
view.querySelector("#divRunningTasks").innerHTML = html;
view.querySelector('#divRunningTasks').innerHTML = html;
}
window.DashboardPage = {
startInterval: function (apiClient) {
apiClient.sendMessage("SessionsStart", "0,1500");
apiClient.sendMessage("ScheduledTasksInfoStart", "0,1000");
apiClient.sendMessage('SessionsStart', '0,1500');
apiClient.sendMessage('ScheduledTasksInfoStart', '0,1000');
},
stopInterval: function (apiClient) {
apiClient.sendMessage("SessionsStop");
apiClient.sendMessage("ScheduledTasksInfoStop");
apiClient.sendMessage('SessionsStop');
apiClient.sendMessage('ScheduledTasksInfoStop');
},
getSessionNowPlayingStreamInfo: function (session) {
var html = "";
var html = '';
var showTranscodingInfo = false;
var displayPlayMethod = playMethodHelper.getDisplayPlayMethod(session);
if (displayPlayMethod === "DirectStream") {
html += globalize.translate("DirectStreaming");
} else if (displayPlayMethod === "Transcode") {
html += globalize.translate("Transcoding");
if (displayPlayMethod === 'DirectStream') {
html += globalize.translate('DirectStreaming');
} else if (displayPlayMethod === 'Transcode') {
html += globalize.translate('Transcoding');
if (session.TranscodingInfo && session.TranscodingInfo.Framerate) {
html += " (" + session.TranscodingInfo.Framerate + " fps)";
html += ' (' + session.TranscodingInfo.Framerate + ' fps)';
}
showTranscodingInfo = true;
} else if (displayPlayMethod === "DirectPlay") {
html += globalize.translate("DirectPlaying");
} else if (displayPlayMethod === 'DirectPlay') {
html += globalize.translate('DirectPlaying');
}
if (showTranscodingInfo) {
@ -407,9 +401,9 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
if (session.TranscodingInfo) {
if (session.TranscodingInfo.Bitrate) {
if (session.TranscodingInfo.Bitrate > 1e6) {
line.push((session.TranscodingInfo.Bitrate / 1e6).toFixed(1) + " Mbps");
line.push((session.TranscodingInfo.Bitrate / 1e6).toFixed(1) + ' Mbps');
} else {
line.push(Math.floor(session.TranscodingInfo.Bitrate / 1e3) + " Kbps");
line.push(Math.floor(session.TranscodingInfo.Bitrate / 1e3) + ' Kbps');
}
}
@ -427,7 +421,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
}
if (line.length) {
html += " - " + line.join(" ");
html += ' - ' + line.join(' ');
}
}
@ -435,43 +429,43 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
},
getSessionNowPlayingTime: function (session) {
var nowPlayingItem = session.NowPlayingItem;
var html = "";
var html = '';
if (nowPlayingItem) {
if (session.PlayState.PositionTicks) {
html += datetime.getDisplayRunningTime(session.PlayState.PositionTicks);
} else {
html += "0:00";
html += '0:00';
}
html += " / ";
html += ' / ';
if (nowPlayingItem && nowPlayingItem.RunTimeTicks) {
html += datetime.getDisplayRunningTime(nowPlayingItem.RunTimeTicks);
} else {
html += "0:00";
html += '0:00';
}
}
return html;
},
getAppSecondaryText: function (session) {
return session.Client + " " + session.ApplicationVersion;
return session.Client + ' ' + session.ApplicationVersion;
},
getNowPlayingName: function (session) {
var imgUrl = "";
var imgUrl = '';
var nowPlayingItem = session.NowPlayingItem;
// FIXME: It seems that, sometimes, server sends date in the future, so date-fns displays messages like 'in less than a minute'. We should fix
// how dates are returned by the server when the session is active and show something like 'Active now', instead of past/future sentences
if (!nowPlayingItem) {
return {
html: globalize.translate("LastSeen", datefns.formatDistanceToNow(Date.parse(session.LastActivityDate), dfnshelper.localeWithSuffix)),
html: globalize.translate('LastSeen', datefns.formatDistanceToNow(Date.parse(session.LastActivityDate), dfnshelper.localeWithSuffix)),
image: imgUrl
};
}
var topText = itemHelper.getDisplayName(nowPlayingItem);
var bottomText = "";
var bottomText = '';
if (nowPlayingItem.Artists && nowPlayingItem.Artists.length) {
bottomText = topText;
@ -490,14 +484,14 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
tag: nowPlayingItem.ImageTags.Logo,
maxHeight: 24,
maxWidth: 130,
type: "Logo"
type: 'Logo'
});
} else if (nowPlayingItem.ParentLogoImageTag) {
imgUrl = ApiClient.getScaledImageUrl(nowPlayingItem.ParentLogoItemId, {
tag: nowPlayingItem.ParentLogoImageTag,
maxHeight: 24,
maxWidth: 130,
type: "Logo"
type: 'Logo'
});
}
@ -506,7 +500,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
}
return {
html: bottomText ? topText + "<br/>" + bottomText : topText,
html: bottomText ? topText + '<br/>' + bottomText : topText,
image: imgUrl
};
},
@ -521,106 +515,104 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
html.push(session.AdditionalUsers[i].UserName);
}
return html.join(", ");
return html.join(', ');
},
getUserImage: function (session) {
if (session.UserId && session.UserPrimaryImageTag) {
return ApiClient.getUserImageUrl(session.UserId, {
tag: session.UserPrimaryImageTag,
type: "Primary"
type: 'Primary'
});
}
return null;
},
updateSession: function (row, session) {
row.classList.remove("deadSession");
row.classList.remove('deadSession');
var nowPlayingItem = session.NowPlayingItem;
if (nowPlayingItem) {
row.classList.add("playingSession");
row.classList.add('playingSession');
} else {
row.classList.remove("playingSession");
row.classList.remove('playingSession');
}
if (session.ServerId && -1 !== session.SupportedCommands.indexOf("DisplayMessage") && session.DeviceId !== connectionManager.deviceId()) {
row.querySelector(".btnSessionSendMessage").classList.remove("hide");
if (session.ServerId && -1 !== session.SupportedCommands.indexOf('DisplayMessage') && session.DeviceId !== connectionManager.deviceId()) {
row.querySelector('.btnSessionSendMessage').classList.remove('hide');
} else {
row.querySelector(".btnSessionSendMessage").classList.add("hide");
row.querySelector('.btnSessionSendMessage').classList.add('hide');
}
if (session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons.length) {
row.querySelector(".btnSessionInfo").classList.remove("hide");
row.querySelector('.btnSessionInfo').classList.remove('hide');
} else {
row.querySelector(".btnSessionInfo").classList.add("hide");
row.querySelector('.btnSessionInfo').classList.add('hide');
}
var btnSessionPlayPause = row.querySelector(".btnSessionPlayPause");
var btnSessionPlayPause = row.querySelector('.btnSessionPlayPause');
if (session.ServerId && nowPlayingItem && session.SupportsRemoteControl && session.DeviceId !== connectionManager.deviceId()) {
btnSessionPlayPause.classList.remove("hide");
row.querySelector(".btnSessionStop").classList.remove("hide");
btnSessionPlayPause.classList.remove('hide');
row.querySelector('.btnSessionStop').classList.remove('hide');
} else {
btnSessionPlayPause.classList.add("hide");
row.querySelector(".btnSessionStop").classList.add("hide");
btnSessionPlayPause.classList.add('hide');
row.querySelector('.btnSessionStop').classList.add('hide');
}
if (session.PlayState && session.PlayState.IsPaused) {
btnSessionPlayPause.querySelector("i").innerHTML = "&#xE037;";
} else {
btnSessionPlayPause.querySelector("i").innerHTML = "pause";
}
const btnSessionPlayPauseIcon = btnSessionPlayPause.querySelector('.material-icons');
btnSessionPlayPauseIcon.classList.remove('play_arrow', 'pause');
btnSessionPlayPauseIcon.classList.add(session.PlayState && session.PlayState.IsPaused ? 'play_arrow' : 'pause');
row.querySelector(".sessionNowPlayingStreamInfo").innerHTML = DashboardPage.getSessionNowPlayingStreamInfo(session);
row.querySelector(".sessionNowPlayingTime").innerHTML = DashboardPage.getSessionNowPlayingTime(session);
row.querySelector(".sessionUserName").innerHTML = DashboardPage.getUsersHtml(session);
row.querySelector(".sessionAppSecondaryText").innerHTML = DashboardPage.getAppSecondaryText(session);
row.querySelector(".sessionTranscodingFramerate").innerHTML = session.TranscodingInfo && session.TranscodingInfo.Framerate ? session.TranscodingInfo.Framerate + " fps" : "";
row.querySelector('.sessionNowPlayingStreamInfo').innerHTML = DashboardPage.getSessionNowPlayingStreamInfo(session);
row.querySelector('.sessionNowPlayingTime').innerHTML = DashboardPage.getSessionNowPlayingTime(session);
row.querySelector('.sessionUserName').innerHTML = DashboardPage.getUsersHtml(session);
row.querySelector('.sessionAppSecondaryText').innerHTML = DashboardPage.getAppSecondaryText(session);
row.querySelector('.sessionTranscodingFramerate').innerHTML = session.TranscodingInfo && session.TranscodingInfo.Framerate ? session.TranscodingInfo.Framerate + ' fps' : '';
var nowPlayingName = DashboardPage.getNowPlayingName(session);
var nowPlayingInfoElem = row.querySelector(".sessionNowPlayingInfo");
var nowPlayingInfoElem = row.querySelector('.sessionNowPlayingInfo');
if (!(nowPlayingName.image && nowPlayingName.image == nowPlayingInfoElem.getAttribute("data-imgsrc"))) {
if (!(nowPlayingName.image && nowPlayingName.image == nowPlayingInfoElem.getAttribute('data-imgsrc'))) {
nowPlayingInfoElem.innerHTML = nowPlayingName.html;
nowPlayingInfoElem.setAttribute("data-imgsrc", nowPlayingName.image || "");
nowPlayingInfoElem.setAttribute('data-imgsrc', nowPlayingName.image || '');
}
var playbackProgressElem = row.querySelector(".playbackProgress");
var playbackProgressElem = row.querySelector('.playbackProgress');
if (nowPlayingItem && nowPlayingItem.RunTimeTicks) {
var percent = 100 * (session.PlayState.PositionTicks || 0) / nowPlayingItem.RunTimeTicks;
playbackProgressElem.outerHTML = indicators.getProgressHtml(percent, {
containerClass: "playbackProgress"
containerClass: 'playbackProgress'
});
} else {
playbackProgressElem.outerHTML = indicators.getProgressHtml(0, {
containerClass: "playbackProgress hide"
containerClass: 'playbackProgress hide'
});
}
var transcodingProgress = row.querySelector(".transcodingProgress");
var transcodingProgress = row.querySelector('.transcodingProgress');
if (session.TranscodingInfo && session.TranscodingInfo.CompletionPercentage) {
var percent = session.TranscodingInfo.CompletionPercentage.toFixed(1);
transcodingProgress.outerHTML = indicators.getProgressHtml(percent, {
containerClass: "transcodingProgress"
containerClass: 'transcodingProgress'
});
} else {
transcodingProgress.outerHTML = indicators.getProgressHtml(0, {
containerClass: "transcodingProgress hide"
containerClass: 'transcodingProgress hide'
});
}
var imgUrl = DashboardPage.getNowPlayingImageUrl(nowPlayingItem) || "";
var imgElem = row.querySelector(".sessionNowPlayingContent");
var imgUrl = DashboardPage.getNowPlayingImageUrl(nowPlayingItem) || '';
var imgElem = row.querySelector('.sessionNowPlayingContent');
if (imgUrl != imgElem.getAttribute("data-src")) {
imgElem.style.backgroundImage = imgUrl ? "url('" + imgUrl + "')" : "";
imgElem.setAttribute("data-src", imgUrl);
if (imgUrl != imgElem.getAttribute('data-src')) {
imgElem.style.backgroundImage = imgUrl ? "url('" + imgUrl + "')" : '';
imgElem.setAttribute('data-src', imgUrl);
if (imgUrl) {
imgElem.classList.add("sessionNowPlayingContent-withbackground");
imgElem.classList.add('sessionNowPlayingContent-withbackground');
} else {
imgElem.classList.remove("sessionNowPlayingContent-withbackground");
imgElem.classList.remove('sessionNowPlayingContent-withbackground');
}
}
},
@ -634,7 +626,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
if (item && item.BackdropImageTags && item.BackdropImageTags.length) {
return ApiClient.getScaledImageUrl(item.Id, {
maxWidth: Math.round(dom.getScreenWidth() * 0.20),
type: "Backdrop",
type: 'Backdrop',
tag: item.BackdropImageTags[0]
});
}
@ -642,7 +634,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
if (item && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) {
return ApiClient.getScaledImageUrl(item.ParentBackdropItemId, {
maxWidth: Math.round(dom.getScreenWidth() * 0.20),
type: "Backdrop",
type: 'Backdrop',
tag: item.ParentBackdropImageTags[0]
});
}
@ -650,7 +642,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
if (item && item.BackdropImageTag) {
return ApiClient.getScaledImageUrl(item.BackdropItemId, {
maxWidth: Math.round(dom.getScreenWidth() * 0.20),
type: "Backdrop",
type: 'Backdrop',
tag: item.BackdropImageTag
});
}
@ -660,7 +652,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
if (item && imageTags.Thumb) {
return ApiClient.getScaledImageUrl(item.Id, {
maxWidth: Math.round(dom.getScreenWidth() * 0.20),
type: "Thumb",
type: 'Thumb',
tag: imageTags.Thumb
});
}
@ -668,7 +660,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
if (item && item.ParentThumbImageTag) {
return ApiClient.getScaledImageUrl(item.ParentThumbItemId, {
maxWidth: Math.round(dom.getScreenWidth() * 0.20),
type: "Thumb",
type: 'Thumb',
tag: item.ParentThumbImageTag
});
}
@ -676,7 +668,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
if (item && item.ThumbImageTag) {
return ApiClient.getScaledImageUrl(item.ThumbItemId, {
maxWidth: Math.round(dom.getScreenWidth() * 0.20),
type: "Thumb",
type: 'Thumb',
tag: item.ThumbImageTag
});
}
@ -684,7 +676,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
if (item && imageTags.Primary) {
return ApiClient.getScaledImageUrl(item.Id, {
maxWidth: Math.round(dom.getScreenWidth() * 0.20),
type: "Primary",
type: 'Primary',
tag: imageTags.Primary
});
}
@ -692,7 +684,7 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
if (item && item.PrimaryImageTag) {
return ApiClient.getScaledImageUrl(item.PrimaryImageItemId, {
maxWidth: Math.round(dom.getScreenWidth() * 0.20),
type: "Primary",
type: 'Primary',
tag: item.PrimaryImageTag
});
}
@ -700,46 +692,46 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
if (item && item.AlbumPrimaryImageTag) {
return ApiClient.getScaledImageUrl(item.AlbumId, {
maxWidth: Math.round(dom.getScreenWidth() * 0.20),
type: "Primary",
type: 'Primary',
tag: item.AlbumPrimaryImageTag
});
}
return null;
},
systemUpdateTaskKey: "SystemUpdateTask",
systemUpdateTaskKey: 'SystemUpdateTask',
stopTask: function (btn, id) {
var page = dom.parentWithClass(btn, "page");
var page = dom.parentWithClass(btn, 'page');
ApiClient.stopScheduledTask(id).then(function () {
pollForInfo(page, ApiClient);
});
},
restart: function (btn) {
require(["confirm"], function (confirm) {
require(['confirm'], function (confirm) {
confirm({
title: globalize.translate("HeaderRestart"),
text: globalize.translate("MessageConfirmRestart"),
confirmText: globalize.translate("ButtonRestart"),
primary: "delete"
title: globalize.translate('HeaderRestart'),
text: globalize.translate('MessageConfirmRestart'),
confirmText: globalize.translate('ButtonRestart'),
primary: 'delete'
}).then(function () {
var page = dom.parentWithClass(btn, "page");
page.querySelector("#btnRestartServer").disabled = true;
page.querySelector("#btnShutdown").disabled = true;
var page = dom.parentWithClass(btn, 'page');
page.querySelector('#btnRestartServer').disabled = true;
page.querySelector('#btnShutdown').disabled = true;
ApiClient.restartServer();
});
});
},
shutdown: function (btn) {
require(["confirm"], function (confirm) {
require(['confirm'], function (confirm) {
confirm({
title: globalize.translate("HeaderShutdown"),
text: globalize.translate("MessageConfirmShutdown"),
confirmText: globalize.translate("ButtonShutdown"),
primary: "delete"
title: globalize.translate('HeaderShutdown'),
text: globalize.translate('MessageConfirmShutdown'),
confirmText: globalize.translate('ButtonShutdown'),
primary: 'delete'
}).then(function () {
var page = dom.parentWithClass(btn, "page");
page.querySelector("#btnRestartServer").disabled = true;
page.querySelector("#btnShutdown").disabled = true;
var page = dom.parentWithClass(btn, 'page');
page.querySelector('#btnRestartServer').disabled = true;
page.querySelector('#btnShutdown').disabled = true;
ApiClient.shutdownServer();
});
});
@ -785,8 +777,8 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
}
var serverId = ApiClient.serverId();
view.querySelector(".activeDevices").addEventListener("click", onActiveDevicesClick);
view.addEventListener("viewshow", function () {
view.querySelector('.activeDevices').addEventListener('click', onActiveDevicesClick);
view.addEventListener('viewshow', function () {
var page = this;
var apiClient = ApiClient;
@ -794,28 +786,28 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
loading.show();
pollForInfo(page, apiClient);
DashboardPage.startInterval(apiClient);
events.on(serverNotifications, "RestartRequired", onRestartRequired);
events.on(serverNotifications, "ServerShuttingDown", onServerShuttingDown);
events.on(serverNotifications, "ServerRestarting", onServerRestarting);
events.on(serverNotifications, "PackageInstalling", onPackageInstalling);
events.on(serverNotifications, "PackageInstallationCompleted", onPackageInstallationCompleted);
events.on(serverNotifications, "Sessions", onSessionsUpdate);
events.on(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate);
events.on(serverNotifications, 'RestartRequired', onRestartRequired);
events.on(serverNotifications, 'ServerShuttingDown', onServerShuttingDown);
events.on(serverNotifications, 'ServerRestarting', onServerRestarting);
events.on(serverNotifications, 'PackageInstalling', onPackageInstalling);
events.on(serverNotifications, 'PackageInstallationCompleted', onPackageInstallationCompleted);
events.on(serverNotifications, 'Sessions', onSessionsUpdate);
events.on(serverNotifications, 'ScheduledTasksInfo', onScheduledTasksUpdate);
DashboardPage.lastAppUpdateCheck = null;
reloadSystemInfo(page, ApiClient);
if (!page.userActivityLog) {
page.userActivityLog = new ActivityLog({
serverId: ApiClient.serverId(),
element: page.querySelector(".userActivityItems")
element: page.querySelector('.userActivityItems')
});
}
if (ApiClient.isMinServerVersion("3.4.1.25")) {
if (ApiClient.isMinServerVersion('3.4.1.25')) {
if (!page.serverActivityLog) {
page.serverActivityLog = new ActivityLog({
serverId: ApiClient.serverId(),
element: page.querySelector(".serverActivityItems")
element: page.querySelector('.serverActivityItems')
});
}
}
@ -824,21 +816,21 @@ define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globa
loading.hide();
}
});
view.addEventListener("viewbeforehide", function () {
view.addEventListener('viewbeforehide', function () {
var apiClient = ApiClient;
events.off(serverNotifications, "RestartRequired", onRestartRequired);
events.off(serverNotifications, "ServerShuttingDown", onServerShuttingDown);
events.off(serverNotifications, "ServerRestarting", onServerRestarting);
events.off(serverNotifications, "PackageInstalling", onPackageInstalling);
events.off(serverNotifications, "PackageInstallationCompleted", onPackageInstallationCompleted);
events.off(serverNotifications, "Sessions", onSessionsUpdate);
events.off(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate);
events.off(serverNotifications, 'RestartRequired', onRestartRequired);
events.off(serverNotifications, 'ServerShuttingDown', onServerShuttingDown);
events.off(serverNotifications, 'ServerRestarting', onServerRestarting);
events.off(serverNotifications, 'PackageInstalling', onPackageInstalling);
events.off(serverNotifications, 'PackageInstallationCompleted', onPackageInstallationCompleted);
events.off(serverNotifications, 'Sessions', onSessionsUpdate);
events.off(serverNotifications, 'ScheduledTasksInfo', onScheduledTasksUpdate);
if (apiClient) {
DashboardPage.stopInterval(apiClient);
}
});
view.addEventListener("viewdestroy", function () {
view.addEventListener('viewdestroy', function () {
var page = this;
var userActivityLog = page.userActivityLog;

View file

@ -0,0 +1,50 @@
define(['loading', 'libraryMenu', 'dom', 'emby-input', 'emby-button'], function (loading, libraryMenu, dom) {
'use strict';
function load(page, device, deviceOptions) {
page.querySelector('#txtCustomName', page).value = deviceOptions.CustomName || '';
page.querySelector('.reportedName', page).innerHTML = device.Name || '';
}
function loadData() {
var page = this;
loading.show();
var id = getParameterByName('id');
var promise1 = ApiClient.getJSON(ApiClient.getUrl('Devices/Info', {
Id: id
}));
var promise2 = ApiClient.getJSON(ApiClient.getUrl('Devices/Options', {
Id: id
}));
Promise.all([promise1, promise2]).then(function (responses) {
load(page, responses[0], responses[1]);
loading.hide();
});
}
function save(page) {
var id = getParameterByName('id');
ApiClient.ajax({
url: ApiClient.getUrl('Devices/Options', {
Id: id
}),
type: 'POST',
data: JSON.stringify({
CustomName: page.querySelector('#txtCustomName').value
}),
contentType: 'application/json'
}).then(Dashboard.processServerConfigurationUpdateResult);
}
function onSubmit(e) {
var form = this;
save(dom.parentWithClass(form, 'page'));
e.preventDefault();
return false;
}
return function (view, params) {
view.querySelector('form').addEventListener('submit', onSubmit);
view.addEventListener('viewshow', loadData);
};
});

View file

@ -0,0 +1,140 @@
define(['loading', 'dom', 'libraryMenu', 'globalize', 'scripts/imagehelper', 'date-fns', 'dfnshelper', 'emby-button', 'emby-itemscontainer', 'cardStyle'], function (loading, dom, libraryMenu, globalize, imageHelper, datefns, dfnshelper) {
'use strict';
function canDelete(deviceId) {
return deviceId !== ApiClient.deviceId();
}
function deleteDevice(page, id) {
var msg = globalize.translate('DeleteDeviceConfirmation');
require(['confirm'], function (confirm) {
confirm({
text: msg,
title: globalize.translate('HeaderDeleteDevice'),
confirmText: globalize.translate('ButtonDelete'),
primary: 'delete'
}).then(function () {
loading.show();
ApiClient.ajax({
type: 'DELETE',
url: ApiClient.getUrl('Devices', {
Id: id
})
}).then(function () {
loadData(page);
});
});
});
}
function showDeviceMenu(view, btn, deviceId) {
var menuItems = [];
if (canEdit) {
menuItems.push({
name: globalize.translate('Edit'),
id: 'open',
icon: 'mode_edit'
});
}
if (canDelete(deviceId)) {
menuItems.push({
name: globalize.translate('Delete'),
id: 'delete',
icon: 'delete'
});
}
require(['actionsheet'], function (actionsheet) {
actionsheet.show({
items: menuItems,
positionTo: btn,
callback: function (id) {
switch (id) {
case 'open':
Dashboard.navigate('device.html?id=' + deviceId);
break;
case 'delete':
deleteDevice(view, deviceId);
}
}
});
});
}
function load(page, devices) {
var html = '';
html += devices.map(function (device) {
var deviceHtml = '';
deviceHtml += "<div data-id='" + device.Id + "' class='card backdropCard'>";
deviceHtml += '<div class="cardBox visualCardBox">';
deviceHtml += '<div class="cardScalable">';
deviceHtml += '<div class="cardPadder cardPadder-backdrop"></div>';
deviceHtml += '<a is="emby-linkbutton" href="' + (canEdit ? 'device.html?id=' + device.Id : '#') + '" class="cardContent cardImageContainer">';
var iconUrl = imageHelper.getDeviceIcon(device);
if (iconUrl) {
deviceHtml += '<div class="cardImage" style="background-image:url(\'' + iconUrl + "');background-size: auto 64%;background-position:center center;\">";
deviceHtml += '</div>';
} else {
deviceHtml += '<span class="cardImageIcon material-icons tablet_android"></span>';
}
deviceHtml += '</a>';
deviceHtml += '</div>';
deviceHtml += '<div class="cardFooter">';
if (canEdit || canDelete(device.Id)) {
deviceHtml += '<div style="text-align:right; float:right;padding-top:5px;">';
deviceHtml += '<button type="button" is="paper-icon-button-light" data-id="' + device.Id + '" title="' + globalize.translate('Menu') + '" class="btnDeviceMenu"><span class="material-icons more_vert"></span></button>';
deviceHtml += '</div>';
}
deviceHtml += "<div class='cardText'>";
deviceHtml += device.Name;
deviceHtml += '</div>';
deviceHtml += "<div class='cardText cardText-secondary'>";
deviceHtml += device.AppName + ' ' + device.AppVersion;
deviceHtml += '</div>';
deviceHtml += "<div class='cardText cardText-secondary'>";
if (device.LastUserName) {
deviceHtml += device.LastUserName;
deviceHtml += ', ' + datefns.formatDistanceToNow(Date.parse(device.DateLastActivity), dfnshelper.localeWithSuffix);
}
deviceHtml += '&nbsp;';
deviceHtml += '</div>';
deviceHtml += '</div>';
deviceHtml += '</div>';
deviceHtml += '</div>';
return deviceHtml;
}).join('');
page.querySelector('.devicesList').innerHTML = html;
}
function loadData(page) {
loading.show();
ApiClient.getJSON(ApiClient.getUrl('Devices')).then(function (result) {
load(page, result.Items);
loading.hide();
});
}
var canEdit = ApiClient.isMinServerVersion('3.4.1.31');
return function (view, params) {
view.querySelector('.devicesList').addEventListener('click', function (e) {
var btnDeviceMenu = dom.parentWithClass(e.target, 'btnDeviceMenu');
if (btnDeviceMenu) {
showDeviceMenu(view, btnDeviceMenu, btnDeviceMenu.getAttribute('data-id'));
}
});
view.addEventListener('viewshow', function () {
loadData(this);
});
};
});

View file

@ -0,0 +1,829 @@
define(['jQuery', 'loading', 'globalize', 'emby-select', 'emby-button', 'emby-input', 'emby-checkbox', 'listViewStyle', 'emby-button'], function ($, loading, globalize) {
'use strict';
function loadProfile(page) {
loading.show();
var promise1 = getProfile();
var promise2 = ApiClient.getUsers();
Promise.all([promise1, promise2]).then(function (responses) {
currentProfile = responses[0];
renderProfile(page, currentProfile, responses[1]);
loading.hide();
});
}
function getProfile() {
var id = getParameterByName('id');
var url = id ? 'Dlna/Profiles/' + id : 'Dlna/Profiles/Default';
return ApiClient.getJSON(ApiClient.getUrl(url));
}
function renderProfile(page, profile, users) {
$('#txtName', page).val(profile.Name);
$('.chkMediaType', page).each(function () {
this.checked = -1 != (profile.SupportedMediaTypes || '').split(',').indexOf(this.getAttribute('data-value'));
});
$('#chkEnableAlbumArtInDidl', page).checked = profile.EnableAlbumArtInDidl;
$('#chkEnableSingleImageLimit', page).checked = profile.EnableSingleAlbumArtLimit;
renderXmlDocumentAttributes(page, profile.XmlRootAttributes || []);
var idInfo = profile.Identification || {};
renderIdentificationHeaders(page, idInfo.Headers || []);
renderSubtitleProfiles(page, profile.SubtitleProfiles || []);
$('#txtInfoFriendlyName', page).val(profile.FriendlyName || '');
$('#txtInfoModelName', page).val(profile.ModelName || '');
$('#txtInfoModelNumber', page).val(profile.ModelNumber || '');
$('#txtInfoModelDescription', page).val(profile.ModelDescription || '');
$('#txtInfoModelUrl', page).val(profile.ModelUrl || '');
$('#txtInfoManufacturer', page).val(profile.Manufacturer || '');
$('#txtInfoManufacturerUrl', page).val(profile.ManufacturerUrl || '');
$('#txtInfoSerialNumber', page).val(profile.SerialNumber || '');
$('#txtIdFriendlyName', page).val(idInfo.FriendlyName || '');
$('#txtIdModelName', page).val(idInfo.ModelName || '');
$('#txtIdModelNumber', page).val(idInfo.ModelNumber || '');
$('#txtIdModelDescription', page).val(idInfo.ModelDescription || '');
$('#txtIdModelUrl', page).val(idInfo.ModelUrl || '');
$('#txtIdManufacturer', page).val(idInfo.Manufacturer || '');
$('#txtIdManufacturerUrl', page).val(idInfo.ManufacturerUrl || '');
$('#txtIdSerialNumber', page).val(idInfo.SerialNumber || '');
$('#txtIdDeviceDescription', page).val(idInfo.DeviceDescription || '');
$('#txtAlbumArtPn', page).val(profile.AlbumArtPn || '');
$('#txtAlbumArtMaxWidth', page).val(profile.MaxAlbumArtWidth || '');
$('#txtAlbumArtMaxHeight', page).val(profile.MaxAlbumArtHeight || '');
$('#txtIconMaxWidth', page).val(profile.MaxIconWidth || '');
$('#txtIconMaxHeight', page).val(profile.MaxIconHeight || '');
$('#chkIgnoreTranscodeByteRangeRequests', page).checked = profile.IgnoreTranscodeByteRangeRequests;
$('#txtMaxAllowedBitrate', page).val(profile.MaxStreamingBitrate || '');
$('#txtMusicStreamingTranscodingBitrate', page).val(profile.MusicStreamingTranscodingBitrate || '');
$('#chkRequiresPlainFolders', page).checked = profile.RequiresPlainFolders;
$('#chkRequiresPlainVideoItems', page).checked = profile.RequiresPlainVideoItems;
$('#txtProtocolInfo', page).val(profile.ProtocolInfo || '');
$('#txtXDlnaCap', page).val(profile.XDlnaCap || '');
$('#txtXDlnaDoc', page).val(profile.XDlnaDoc || '');
$('#txtSonyAggregationFlags', page).val(profile.SonyAggregationFlags || '');
profile.DirectPlayProfiles = profile.DirectPlayProfiles || [];
profile.TranscodingProfiles = profile.TranscodingProfiles || [];
profile.ContainerProfiles = profile.ContainerProfiles || [];
profile.CodecProfiles = profile.CodecProfiles || [];
profile.ResponseProfiles = profile.ResponseProfiles || [];
var usersHtml = '<option></option>' + users.map(function (u) {
return '<option value="' + u.Id + '">' + u.Name + '</option>';
}).join('');
$('#selectUser', page).html(usersHtml).val(profile.UserId || '');
renderSubProfiles(page, profile);
}
function renderIdentificationHeaders(page, headers) {
var index = 0;
var html = '<div class="paperList">' + headers.map(function (h) {
var li = '<div class="listItem">';
li += '<span class="material-icons listItemIcon info"></span>';
li += '<div class="listItemBody">';
li += '<h3 class="listItemBodyText">' + h.Name + ': ' + (h.Value || '') + '</h3>';
li += '<div class="listItemBodyText secondary">' + (h.Match || '') + '</div>';
li += '</div>';
li += '<button type="button" is="paper-icon-button-light" class="btnDeleteIdentificationHeader listItemButton" data-index="' + index + '"><span class="material-icons delete"></span></button>';
li += '</div>';
index++;
return li;
}).join('') + '</div>';
var elem = $('.httpHeaderIdentificationList', page).html(html).trigger('create');
$('.btnDeleteIdentificationHeader', elem).on('click', function () {
var itemIndex = parseInt(this.getAttribute('data-index'));
currentProfile.Identification.Headers.splice(itemIndex, 1);
renderIdentificationHeaders(page, currentProfile.Identification.Headers);
});
}
function openPopup(elem) {
elem.classList.remove('hide');
}
function closePopup(elem) {
elem.classList.add('hide');
}
function editIdentificationHeader(page, header) {
isSubProfileNew = null == header;
header = header || {};
currentSubProfile = header;
var popup = $('#identificationHeaderPopup', page);
$('#txtIdentificationHeaderName', popup).val(header.Name || '');
$('#txtIdentificationHeaderValue', popup).val(header.Value || '');
$('#selectMatchType', popup).val(header.Match || 'Equals');
openPopup(popup[0]);
}
function saveIdentificationHeader(page) {
currentSubProfile.Name = $('#txtIdentificationHeaderName', page).val();
currentSubProfile.Value = $('#txtIdentificationHeaderValue', page).val();
currentSubProfile.Match = $('#selectMatchType', page).val();
if (isSubProfileNew) {
currentProfile.Identification = currentProfile.Identification || {};
currentProfile.Identification.Headers = currentProfile.Identification.Headers || [];
currentProfile.Identification.Headers.push(currentSubProfile);
}
renderIdentificationHeaders(page, currentProfile.Identification.Headers);
currentSubProfile = null;
closePopup($('#identificationHeaderPopup', page)[0]);
}
function renderXmlDocumentAttributes(page, attribute) {
var html = '<div class="paperList">' + attribute.map(function (h) {
var li = '<div class="listItem">';
li += '<span class="material-icons listItemIcon info"></span>';
li += '<div class="listItemBody">';
li += '<h3 class="listItemBodyText">' + h.Name + ' = ' + (h.Value || '') + '</h3>';
li += '</div>';
li += '<button type="button" is="paper-icon-button-light" class="btnDeleteXmlAttribute listItemButton" data-index="0"><span class="material-icons delete"></span></button>';
return li += '</div>';
}).join('') + '</div>';
var elem = $('.xmlDocumentAttributeList', page).html(html).trigger('create');
$('.btnDeleteXmlAttribute', elem).on('click', function () {
var itemIndex = parseInt(this.getAttribute('data-index'));
currentProfile.XmlRootAttributes.splice(itemIndex, 1);
renderXmlDocumentAttributes(page, currentProfile.XmlRootAttributes);
});
}
function editXmlDocumentAttribute(page, attribute) {
isSubProfileNew = null == attribute;
attribute = attribute || {};
currentSubProfile = attribute;
var popup = $('#xmlAttributePopup', page);
$('#txtXmlAttributeName', popup).val(attribute.Name || '');
$('#txtXmlAttributeValue', popup).val(attribute.Value || '');
openPopup(popup[0]);
}
function saveXmlDocumentAttribute(page) {
currentSubProfile.Name = $('#txtXmlAttributeName', page).val();
currentSubProfile.Value = $('#txtXmlAttributeValue', page).val();
if (isSubProfileNew) {
currentProfile.XmlRootAttributes.push(currentSubProfile);
}
renderXmlDocumentAttributes(page, currentProfile.XmlRootAttributes);
currentSubProfile = null;
closePopup($('#xmlAttributePopup', page)[0]);
}
function renderSubtitleProfiles(page, profiles) {
var index = 0;
var html = '<div class="paperList">' + profiles.map(function (h) {
var li = '<div class="listItem lnkEditSubProfile" data-index="' + index + '">';
li += '<span class="material-icons listItemIcon info"></span>';
li += '<div class="listItemBody">';
li += '<h3 class="listItemBodyText">' + (h.Format || '') + '</h3>';
li += '</div>';
li += '<button type="button" is="paper-icon-button-light" class="btnDeleteProfile listItemButton" data-index="' + index + '"><span class="material-icons delete"></span></button>';
li += '</div>';
index++;
return li;
}).join('') + '</div>';
var elem = $('.subtitleProfileList', page).html(html).trigger('create');
$('.btnDeleteProfile', elem).on('click', function () {
var itemIndex = parseInt(this.getAttribute('data-index'));
currentProfile.SubtitleProfiles.splice(itemIndex, 1);
renderSubtitleProfiles(page, currentProfile.SubtitleProfiles);
});
$('.lnkEditSubProfile', elem).on('click', function () {
var itemIndex = parseInt(this.getAttribute('data-index'));
editSubtitleProfile(page, currentProfile.SubtitleProfiles[itemIndex]);
});
}
function editSubtitleProfile(page, profile) {
isSubProfileNew = null == profile;
profile = profile || {};
currentSubProfile = profile;
var popup = $('#subtitleProfilePopup', page);
$('#txtSubtitleProfileFormat', popup).val(profile.Format || '');
$('#selectSubtitleProfileMethod', popup).val(profile.Method || '');
$('#selectSubtitleProfileDidlMode', popup).val(profile.DidlMode || '');
openPopup(popup[0]);
}
function saveSubtitleProfile(page) {
currentSubProfile.Format = $('#txtSubtitleProfileFormat', page).val();
currentSubProfile.Method = $('#selectSubtitleProfileMethod', page).val();
currentSubProfile.DidlMode = $('#selectSubtitleProfileDidlMode', page).val();
if (isSubProfileNew) {
currentProfile.SubtitleProfiles.push(currentSubProfile);
}
renderSubtitleProfiles(page, currentProfile.SubtitleProfiles);
currentSubProfile = null;
closePopup($('#subtitleProfilePopup', page)[0]);
}
function renderSubProfiles(page, profile) {
renderDirectPlayProfiles(page, profile.DirectPlayProfiles);
renderTranscodingProfiles(page, profile.TranscodingProfiles);
renderContainerProfiles(page, profile.ContainerProfiles);
renderCodecProfiles(page, profile.CodecProfiles);
renderResponseProfiles(page, profile.ResponseProfiles);
}
function saveDirectPlayProfile(page) {
currentSubProfile.Type = $('#selectDirectPlayProfileType', page).val();
currentSubProfile.Container = $('#txtDirectPlayContainer', page).val();
currentSubProfile.AudioCodec = $('#txtDirectPlayAudioCodec', page).val();
currentSubProfile.VideoCodec = $('#txtDirectPlayVideoCodec', page).val();
if (isSubProfileNew) {
currentProfile.DirectPlayProfiles.push(currentSubProfile);
}
renderSubProfiles(page, currentProfile);
currentSubProfile = null;
closePopup($('#popupEditDirectPlayProfile', page)[0]);
}
function renderDirectPlayProfiles(page, profiles) {
var html = '';
html += '<ul data-role="listview" data-inset="true" data-split-icon="delete">';
var currentType;
for (var i = 0, length = profiles.length; i < length; i++) {
var profile = profiles[i];
if (profile.Type !== currentType) {
html += '<li data-role="list-divider">' + profile.Type + '</li>';
currentType = profile.Type;
}
html += '<div>';
html += '<a is="emby-linkbutton" href="#" class="lnkEditSubProfile" data-profileindex="' + i + '">';
html += '<p>' + globalize.translate('ValueContainer', profile.Container || allText) + '</p>';
if ('Video' == profile.Type) {
html += '<p>' + globalize.translate('ValueVideoCodec', profile.VideoCodec || allText) + '</p>';
html += '<p>' + globalize.translate('ValueAudioCodec', profile.AudioCodec || allText) + '</p>';
} else {
if ('Audio' == profile.Type) {
html += '<p>' + globalize.translate('ValueCodec', profile.AudioCodec || allText) + '</p>';
}
}
html += '</a>';
html += '<button type="button" is="paper-icon-button-light" class="btnDeleteProfile listItemButton" data-profileindex="' + i + '"><span class="material-icons delete"></span></button>';
html += '</div>';
}
html += '</ul>';
var elem = $('.directPlayProfiles', page).html(html).trigger('create');
$('.btnDeleteProfile', elem).on('click', function () {
var index = this.getAttribute('data-profileindex');
deleteDirectPlayProfile(page, index);
});
$('.lnkEditSubProfile', elem).on('click', function () {
var index = parseInt(this.getAttribute('data-profileindex'));
editDirectPlayProfile(page, currentProfile.DirectPlayProfiles[index]);
});
}
function deleteDirectPlayProfile(page, index) {
currentProfile.DirectPlayProfiles.splice(index, 1);
renderDirectPlayProfiles(page, currentProfile.DirectPlayProfiles);
}
function editDirectPlayProfile(page, directPlayProfile) {
isSubProfileNew = null == directPlayProfile;
directPlayProfile = directPlayProfile || {};
currentSubProfile = directPlayProfile;
var popup = $('#popupEditDirectPlayProfile', page);
$('#selectDirectPlayProfileType', popup).val(directPlayProfile.Type || 'Video').trigger('change');
$('#txtDirectPlayContainer', popup).val(directPlayProfile.Container || '');
$('#txtDirectPlayAudioCodec', popup).val(directPlayProfile.AudioCodec || '');
$('#txtDirectPlayVideoCodec', popup).val(directPlayProfile.VideoCodec || '');
openPopup(popup[0]);
}
function renderTranscodingProfiles(page, profiles) {
var html = '';
html += '<ul data-role="listview" data-inset="true" data-split-icon="delete">';
var currentType;
for (var i = 0, length = profiles.length; i < length; i++) {
var profile = profiles[i];
if (profile.Type !== currentType) {
html += '<li data-role="list-divider">' + profile.Type + '</li>';
currentType = profile.Type;
}
html += '<div>';
html += '<a is="emby-linkbutton" href="#" class="lnkEditSubProfile" data-profileindex="' + i + '">';
html += '<p>Protocol: ' + (profile.Protocol || 'Http') + '</p>';
html += '<p>' + globalize.translate('ValueContainer', profile.Container || allText) + '</p>';
if ('Video' == profile.Type) {
html += '<p>' + globalize.translate('ValueVideoCodec', profile.VideoCodec || allText) + '</p>';
html += '<p>' + globalize.translate('ValueAudioCodec', profile.AudioCodec || allText) + '</p>';
} else {
if ('Audio' == profile.Type) {
html += '<p>' + globalize.translate('ValueCodec', profile.AudioCodec || allText) + '</p>';
}
}
html += '</a>';
html += '<button type="button" is="paper-icon-button-light" class="btnDeleteProfile listItemButton" data-profileindex="' + i + '"><span class="material-icons delete"></span></button>';
html += '</div>';
}
html += '</ul>';
var elem = $('.transcodingProfiles', page).html(html).trigger('create');
$('.btnDeleteProfile', elem).on('click', function () {
var index = this.getAttribute('data-profileindex');
deleteTranscodingProfile(page, index);
});
$('.lnkEditSubProfile', elem).on('click', function () {
var index = parseInt(this.getAttribute('data-profileindex'));
editTranscodingProfile(page, currentProfile.TranscodingProfiles[index]);
});
}
function editTranscodingProfile(page, transcodingProfile) {
isSubProfileNew = null == transcodingProfile;
transcodingProfile = transcodingProfile || {};
currentSubProfile = transcodingProfile;
var popup = $('#transcodingProfilePopup', page);
$('#selectTranscodingProfileType', popup).val(transcodingProfile.Type || 'Video').trigger('change');
$('#txtTranscodingContainer', popup).val(transcodingProfile.Container || '');
$('#txtTranscodingAudioCodec', popup).val(transcodingProfile.AudioCodec || '');
$('#txtTranscodingVideoCodec', popup).val(transcodingProfile.VideoCodec || '');
$('#selectTranscodingProtocol', popup).val(transcodingProfile.Protocol || 'Http');
$('#chkEnableMpegtsM2TsMode', popup).checked = transcodingProfile.EnableMpegtsM2TsMode || false;
$('#chkEstimateContentLength', popup).checked = transcodingProfile.EstimateContentLength || false;
$('#chkReportByteRangeRequests', popup).checked = 'Bytes' == transcodingProfile.TranscodeSeekInfo;
$('.radioTabButton:first', popup).trigger('click');
openPopup(popup[0]);
}
function deleteTranscodingProfile(page, index) {
currentProfile.TranscodingProfiles.splice(index, 1);
renderTranscodingProfiles(page, currentProfile.TranscodingProfiles);
}
function saveTranscodingProfile(page) {
currentSubProfile.Type = $('#selectTranscodingProfileType', page).val();
currentSubProfile.Container = $('#txtTranscodingContainer', page).val();
currentSubProfile.AudioCodec = $('#txtTranscodingAudioCodec', page).val();
currentSubProfile.VideoCodec = $('#txtTranscodingVideoCodec', page).val();
currentSubProfile.Protocol = $('#selectTranscodingProtocol', page).val();
currentSubProfile.Context = 'Streaming';
currentSubProfile.EnableMpegtsM2TsMode = $('#chkEnableMpegtsM2TsMode', page).checked;
currentSubProfile.EstimateContentLength = $('#chkEstimateContentLength', page).checked;
currentSubProfile.TranscodeSeekInfo = $('#chkReportByteRangeRequests', page).checked ? 'Bytes' : 'Auto';
if (isSubProfileNew) {
currentProfile.TranscodingProfiles.push(currentSubProfile);
}
renderSubProfiles(page, currentProfile);
currentSubProfile = null;
closePopup($('#transcodingProfilePopup', page)[0]);
}
function renderContainerProfiles(page, profiles) {
var html = '';
html += '<ul data-role="listview" data-inset="true" data-split-icon="delete">';
var currentType;
for (var i = 0, length = profiles.length; i < length; i++) {
var profile = profiles[i];
if (profile.Type !== currentType) {
html += '<li data-role="list-divider">' + profile.Type + '</li>';
currentType = profile.Type;
}
html += '<div>';
html += '<a is="emby-linkbutton" href="#" class="lnkEditSubProfile" data-profileindex="' + i + '">';
html += '<p>' + globalize.translate('ValueContainer', profile.Container || allText) + '</p>';
if (profile.Conditions && profile.Conditions.length) {
html += '<p>';
html += globalize.translate('ValueConditions', profile.Conditions.map(function (c) {
return c.Property;
}).join(', '));
html += '</p>';
}
html += '</a>';
html += '<button type="button" is="paper-icon-button-light" class="btnDeleteProfile listItemButton" data-profileindex="' + i + '"><span class="material-icons delete"></span></button>';
html += '</div>';
}
html += '</ul>';
var elem = $('.containerProfiles', page).html(html).trigger('create');
$('.btnDeleteProfile', elem).on('click', function () {
var index = this.getAttribute('data-profileindex');
deleteContainerProfile(page, index);
});
$('.lnkEditSubProfile', elem).on('click', function () {
var index = parseInt(this.getAttribute('data-profileindex'));
editContainerProfile(page, currentProfile.ContainerProfiles[index]);
});
}
function deleteContainerProfile(page, index) {
currentProfile.ContainerProfiles.splice(index, 1);
renderContainerProfiles(page, currentProfile.ContainerProfiles);
}
function editContainerProfile(page, containerProfile) {
isSubProfileNew = null == containerProfile;
containerProfile = containerProfile || {};
currentSubProfile = containerProfile;
var popup = $('#containerProfilePopup', page);
$('#selectContainerProfileType', popup).val(containerProfile.Type || 'Video').trigger('change');
$('#txtContainerProfileContainer', popup).val(containerProfile.Container || '');
$('.radioTabButton:first', popup).trigger('click');
openPopup(popup[0]);
}
function saveContainerProfile(page) {
currentSubProfile.Type = $('#selectContainerProfileType', page).val();
currentSubProfile.Container = $('#txtContainerProfileContainer', page).val();
if (isSubProfileNew) {
currentProfile.ContainerProfiles.push(currentSubProfile);
}
renderSubProfiles(page, currentProfile);
currentSubProfile = null;
closePopup($('#containerProfilePopup', page)[0]);
}
function renderCodecProfiles(page, profiles) {
var html = '';
html += '<ul data-role="listview" data-inset="true" data-split-icon="delete">';
var currentType;
for (var i = 0, length = profiles.length; i < length; i++) {
var profile = profiles[i];
var type = profile.Type.replace('VideoAudio', 'Video Audio');
if (type !== currentType) {
html += '<li data-role="list-divider">' + type + '</li>';
currentType = type;
}
html += '<div>';
html += '<a is="emby-linkbutton" href="#" class="lnkEditSubProfile" data-profileindex="' + i + '">';
html += '<p>' + globalize.translate('ValueCodec', profile.Codec || allText) + '</p>';
if (profile.Conditions && profile.Conditions.length) {
html += '<p>';
html += globalize.translate('ValueConditions', profile.Conditions.map(function (c) {
return c.Property;
}).join(', '));
html += '</p>';
}
html += '</a>';
html += '<button type="button" is="paper-icon-button-light" class="btnDeleteProfile listItemButton" data-profileindex="' + i + '"><span class="material-icons delete"></span></button>';
html += '</div>';
}
html += '</ul>';
var elem = $('.codecProfiles', page).html(html).trigger('create');
$('.btnDeleteProfile', elem).on('click', function () {
var index = this.getAttribute('data-profileindex');
deleteCodecProfile(page, index);
});
$('.lnkEditSubProfile', elem).on('click', function () {
var index = parseInt(this.getAttribute('data-profileindex'));
editCodecProfile(page, currentProfile.CodecProfiles[index]);
});
}
function deleteCodecProfile(page, index) {
currentProfile.CodecProfiles.splice(index, 1);
renderCodecProfiles(page, currentProfile.CodecProfiles);
}
function editCodecProfile(page, codecProfile) {
isSubProfileNew = null == codecProfile;
codecProfile = codecProfile || {};
currentSubProfile = codecProfile;
var popup = $('#codecProfilePopup', page);
$('#selectCodecProfileType', popup).val(codecProfile.Type || 'Video').trigger('change');
$('#txtCodecProfileCodec', popup).val(codecProfile.Codec || '');
$('.radioTabButton:first', popup).trigger('click');
openPopup(popup[0]);
}
function saveCodecProfile(page) {
currentSubProfile.Type = $('#selectCodecProfileType', page).val();
currentSubProfile.Codec = $('#txtCodecProfileCodec', page).val();
if (isSubProfileNew) {
currentProfile.CodecProfiles.push(currentSubProfile);
}
renderSubProfiles(page, currentProfile);
currentSubProfile = null;
closePopup($('#codecProfilePopup', page)[0]);
}
function renderResponseProfiles(page, profiles) {
var html = '';
html += '<ul data-role="listview" data-inset="true" data-split-icon="delete">';
var currentType;
for (var i = 0, length = profiles.length; i < length; i++) {
var profile = profiles[i];
if (profile.Type !== currentType) {
html += '<li data-role="list-divider">' + profile.Type + '</li>';
currentType = profile.Type;
}
html += '<div>';
html += '<a is="emby-linkbutton" href="#" class="lnkEditSubProfile" data-profileindex="' + i + '">';
html += '<p>' + globalize.translate('ValueContainer', profile.Container || allText) + '</p>';
if ('Video' == profile.Type) {
html += '<p>' + globalize.translate('ValueVideoCodec', profile.VideoCodec || allText) + '</p>';
html += '<p>' + globalize.translate('ValueAudioCodec', profile.AudioCodec || allText) + '</p>';
} else {
if ('Audio' == profile.Type) {
html += '<p>' + globalize.translate('ValueCodec', profile.AudioCodec || allText) + '</p>';
}
}
if (profile.Conditions && profile.Conditions.length) {
html += '<p>';
html += globalize.translate('ValueConditions', profile.Conditions.map(function (c) {
return c.Property;
}).join(', '));
html += '</p>';
}
html += '</a>';
html += '<button type="button" is="paper-icon-button-light" class="btnDeleteProfile listItemButton" data-profileindex="' + i + '"><span class="material-icons delete"></span></button>';
html += '</div>';
}
html += '</ul>';
var elem = $('.mediaProfiles', page).html(html).trigger('create');
$('.btnDeleteProfile', elem).on('click', function () {
var index = this.getAttribute('data-profileindex');
deleteResponseProfile(page, index);
});
$('.lnkEditSubProfile', elem).on('click', function () {
var index = parseInt(this.getAttribute('data-profileindex'));
editResponseProfile(page, currentProfile.ResponseProfiles[index]);
});
}
function deleteResponseProfile(page, index) {
currentProfile.ResponseProfiles.splice(index, 1);
renderResponseProfiles(page, currentProfile.ResponseProfiles);
}
function editResponseProfile(page, responseProfile) {
isSubProfileNew = null == responseProfile;
responseProfile = responseProfile || {};
currentSubProfile = responseProfile;
var popup = $('#responseProfilePopup', page);
$('#selectResponseProfileType', popup).val(responseProfile.Type || 'Video').trigger('change');
$('#txtResponseProfileContainer', popup).val(responseProfile.Container || '');
$('#txtResponseProfileAudioCodec', popup).val(responseProfile.AudioCodec || '');
$('#txtResponseProfileVideoCodec', popup).val(responseProfile.VideoCodec || '');
$('.radioTabButton:first', popup).trigger('click');
openPopup(popup[0]);
}
function saveResponseProfile(page) {
currentSubProfile.Type = $('#selectResponseProfileType', page).val();
currentSubProfile.Container = $('#txtResponseProfileContainer', page).val();
currentSubProfile.AudioCodec = $('#txtResponseProfileAudioCodec', page).val();
currentSubProfile.VideoCodec = $('#txtResponseProfileVideoCodec', page).val();
if (isSubProfileNew) {
currentProfile.ResponseProfiles.push(currentSubProfile);
}
renderSubProfiles(page, currentProfile);
currentSubProfile = null;
closePopup($('#responseProfilePopup', page)[0]);
}
function saveProfile(page, profile) {
updateProfile(page, profile);
var id = getParameterByName('id');
if (id) {
ApiClient.ajax({
type: 'POST',
url: ApiClient.getUrl('Dlna/Profiles/' + id),
data: JSON.stringify(profile),
contentType: 'application/json'
}).then(function () {
require(['toast'], function (toast) {
toast('Settings saved.');
});
}, Dashboard.processErrorResponse);
} else {
ApiClient.ajax({
type: 'POST',
url: ApiClient.getUrl('Dlna/Profiles'),
data: JSON.stringify(profile),
contentType: 'application/json'
}).then(function () {
Dashboard.navigate('dlnaprofiles.html');
}, Dashboard.processErrorResponse);
}
loading.hide();
}
function updateProfile(page, profile) {
profile.Name = $('#txtName', page).val();
profile.EnableAlbumArtInDidl = $('#chkEnableAlbumArtInDidl', page).checked;
profile.EnableSingleAlbumArtLimit = $('#chkEnableSingleImageLimit', page).checked;
profile.SupportedMediaTypes = $('.chkMediaType:checked', page).get().map(function (c) {
return c.getAttribute('data-value');
}).join(',');
profile.Identification = profile.Identification || {};
profile.FriendlyName = $('#txtInfoFriendlyName', page).val();
profile.ModelName = $('#txtInfoModelName', page).val();
profile.ModelNumber = $('#txtInfoModelNumber', page).val();
profile.ModelDescription = $('#txtInfoModelDescription', page).val();
profile.ModelUrl = $('#txtInfoModelUrl', page).val();
profile.Manufacturer = $('#txtInfoManufacturer', page).val();
profile.ManufacturerUrl = $('#txtInfoManufacturerUrl', page).val();
profile.SerialNumber = $('#txtInfoSerialNumber', page).val();
profile.Identification.FriendlyName = $('#txtIdFriendlyName', page).val();
profile.Identification.ModelName = $('#txtIdModelName', page).val();
profile.Identification.ModelNumber = $('#txtIdModelNumber', page).val();
profile.Identification.ModelDescription = $('#txtIdModelDescription', page).val();
profile.Identification.ModelUrl = $('#txtIdModelUrl', page).val();
profile.Identification.Manufacturer = $('#txtIdManufacturer', page).val();
profile.Identification.ManufacturerUrl = $('#txtIdManufacturerUrl', page).val();
profile.Identification.SerialNumber = $('#txtIdSerialNumber', page).val();
profile.Identification.DeviceDescription = $('#txtIdDeviceDescription', page).val();
profile.AlbumArtPn = $('#txtAlbumArtPn', page).val();
profile.MaxAlbumArtWidth = $('#txtAlbumArtMaxWidth', page).val();
profile.MaxAlbumArtHeight = $('#txtAlbumArtMaxHeight', page).val();
profile.MaxIconWidth = $('#txtIconMaxWidth', page).val();
profile.MaxIconHeight = $('#txtIconMaxHeight', page).val();
profile.RequiresPlainFolders = $('#chkRequiresPlainFolders', page).checked;
profile.RequiresPlainVideoItems = $('#chkRequiresPlainVideoItems', page).checked;
profile.IgnoreTranscodeByteRangeRequests = $('#chkIgnoreTranscodeByteRangeRequests', page).checked;
profile.MaxStreamingBitrate = $('#txtMaxAllowedBitrate', page).val();
profile.MusicStreamingTranscodingBitrate = $('#txtMusicStreamingTranscodingBitrate', page).val();
profile.ProtocolInfo = $('#txtProtocolInfo', page).val();
profile.XDlnaCap = $('#txtXDlnaCap', page).val();
profile.XDlnaDoc = $('#txtXDlnaDoc', page).val();
profile.SonyAggregationFlags = $('#txtSonyAggregationFlags', page).val();
profile.UserId = $('#selectUser', page).val();
}
var currentProfile;
var currentSubProfile;
var isSubProfileNew;
var allText = globalize.translate('LabelAll');
$(document).on('pageinit', '#dlnaProfilePage', function () {
var page = this;
$('.radioTabButton', page).on('click', function () {
$(this).siblings().removeClass('ui-btn-active');
$(this).addClass('ui-btn-active');
var value = 'A' == this.tagName ? this.getAttribute('data-value') : this.value;
var elem = $('.' + value, page);
elem.siblings('.tabContent').hide();
elem.show();
});
$('#selectDirectPlayProfileType', page).on('change', function () {
if ('Video' == this.value) {
$('#fldDirectPlayVideoCodec', page).show();
} else {
$('#fldDirectPlayVideoCodec', page).hide();
}
if ('Photo' == this.value) {
$('#fldDirectPlayAudioCodec', page).hide();
} else {
$('#fldDirectPlayAudioCodec', page).show();
}
});
$('#selectTranscodingProfileType', page).on('change', function () {
if ('Video' == this.value) {
$('#fldTranscodingVideoCodec', page).show();
$('#fldTranscodingProtocol', page).show();
$('#fldEnableMpegtsM2TsMode', page).show();
} else {
$('#fldTranscodingVideoCodec', page).hide();
$('#fldTranscodingProtocol', page).hide();
$('#fldEnableMpegtsM2TsMode', page).hide();
}
if ('Photo' == this.value) {
$('#fldTranscodingAudioCodec', page).hide();
$('#fldEstimateContentLength', page).hide();
$('#fldReportByteRangeRequests', page).hide();
} else {
$('#fldTranscodingAudioCodec', page).show();
$('#fldEstimateContentLength', page).show();
$('#fldReportByteRangeRequests', page).show();
}
});
$('#selectResponseProfileType', page).on('change', function () {
if ('Video' == this.value) {
$('#fldResponseProfileVideoCodec', page).show();
} else {
$('#fldResponseProfileVideoCodec', page).hide();
}
if ('Photo' == this.value) {
$('#fldResponseProfileAudioCodec', page).hide();
} else {
$('#fldResponseProfileAudioCodec', page).show();
}
});
$('.btnAddDirectPlayProfile', page).on('click', function () {
editDirectPlayProfile(page);
});
$('.btnAddTranscodingProfile', page).on('click', function () {
editTranscodingProfile(page);
});
$('.btnAddContainerProfile', page).on('click', function () {
editContainerProfile(page);
});
$('.btnAddCodecProfile', page).on('click', function () {
editCodecProfile(page);
});
$('.btnAddResponseProfile', page).on('click', function () {
editResponseProfile(page);
});
$('.btnAddIdentificationHttpHeader', page).on('click', function () {
editIdentificationHeader(page);
});
$('.btnAddXmlDocumentAttribute', page).on('click', function () {
editXmlDocumentAttribute(page);
});
$('.btnAddSubtitleProfile', page).on('click', function () {
editSubtitleProfile(page);
});
$('.dlnaProfileForm').off('submit', DlnaProfilePage.onSubmit).on('submit', DlnaProfilePage.onSubmit);
$('.editDirectPlayProfileForm').off('submit', DlnaProfilePage.onDirectPlayFormSubmit).on('submit', DlnaProfilePage.onDirectPlayFormSubmit);
$('.transcodingProfileForm').off('submit', DlnaProfilePage.onTranscodingProfileFormSubmit).on('submit', DlnaProfilePage.onTranscodingProfileFormSubmit);
$('.containerProfileForm').off('submit', DlnaProfilePage.onContainerProfileFormSubmit).on('submit', DlnaProfilePage.onContainerProfileFormSubmit);
$('.codecProfileForm').off('submit', DlnaProfilePage.onCodecProfileFormSubmit).on('submit', DlnaProfilePage.onCodecProfileFormSubmit);
$('.editResponseProfileForm').off('submit', DlnaProfilePage.onResponseProfileFormSubmit).on('submit', DlnaProfilePage.onResponseProfileFormSubmit);
$('.identificationHeaderForm').off('submit', DlnaProfilePage.onIdentificationHeaderFormSubmit).on('submit', DlnaProfilePage.onIdentificationHeaderFormSubmit);
$('.xmlAttributeForm').off('submit', DlnaProfilePage.onXmlAttributeFormSubmit).on('submit', DlnaProfilePage.onXmlAttributeFormSubmit);
$('.subtitleProfileForm').off('submit', DlnaProfilePage.onSubtitleProfileFormSubmit).on('submit', DlnaProfilePage.onSubtitleProfileFormSubmit);
}).on('pageshow', '#dlnaProfilePage', function () {
var page = this;
$('#radioInfo', page).trigger('click');
loadProfile(page);
});
window.DlnaProfilePage = {
onSubmit: function () {
loading.show();
saveProfile($(this).parents('.page'), currentProfile);
return false;
},
onDirectPlayFormSubmit: function () {
saveDirectPlayProfile($(this).parents('.page'));
return false;
},
onTranscodingProfileFormSubmit: function () {
saveTranscodingProfile($(this).parents('.page'));
return false;
},
onContainerProfileFormSubmit: function () {
saveContainerProfile($(this).parents('.page'));
return false;
},
onCodecProfileFormSubmit: function () {
saveCodecProfile($(this).parents('.page'));
return false;
},
onResponseProfileFormSubmit: function () {
saveResponseProfile($(this).parents('.page'));
return false;
},
onIdentificationHeaderFormSubmit: function () {
saveIdentificationHeader($(this).parents('.page'));
return false;
},
onXmlAttributeFormSubmit: function () {
saveXmlDocumentAttribute($(this).parents('.page'));
return false;
},
onSubtitleProfileFormSubmit: function () {
saveSubtitleProfile($(this).parents('.page'));
return false;
}
};
});

View file

@ -0,0 +1,89 @@
define(['jQuery', 'globalize', 'loading', 'libraryMenu', 'listViewStyle', 'emby-button'], function ($, globalize, loading, libraryMenu) {
'use strict';
function loadProfiles(page) {
loading.show();
ApiClient.getJSON(ApiClient.getUrl('Dlna/ProfileInfos')).then(function (result) {
renderUserProfiles(page, result);
renderSystemProfiles(page, result);
loading.hide();
});
}
function renderUserProfiles(page, profiles) {
renderProfiles(page, page.querySelector('.customProfiles'), profiles.filter(function (p) {
return 'User' == p.Type;
}));
}
function renderSystemProfiles(page, profiles) {
renderProfiles(page, page.querySelector('.systemProfiles'), profiles.filter(function (p) {
return 'System' == p.Type;
}));
}
function renderProfiles(page, element, profiles) {
var html = '';
if (profiles.length) {
html += '<div class="paperList">';
}
for (var i = 0, length = profiles.length; i < length; i++) {
var profile = profiles[i];
html += '<div class="listItem listItem-border">';
html += '<span class="listItemIcon material-icons live_tv"></span>';
html += '<div class="listItemBody two-line">';
html += "<a is='emby-linkbutton' style='padding:0;margin:0;' data-ripple='false' class='clearLink' href='dlnaprofile.html?id=" + profile.Id + "'>";
html += '<div>' + profile.Name + '</div>';
html += '</a>';
html += '</div>';
if ('User' == profile.Type) {
html += '<button type="button" is="paper-icon-button-light" class="btnDeleteProfile" data-profileid="' + profile.Id + '" title="' + globalize.translate('ButtonDelete') + '"><span class="material-icons delete"></span></button>';
}
html += '</div>';
}
if (profiles.length) {
html += '</div>';
}
element.innerHTML = html;
$('.btnDeleteProfile', element).on('click', function () {
var id = this.getAttribute('data-profileid');
deleteProfile(page, id);
});
}
function deleteProfile(page, id) {
require(['confirm'], function (confirm) {
confirm(globalize.translate('MessageConfirmProfileDeletion'), globalize.translate('HeaderConfirmProfileDeletion')).then(function () {
loading.show();
ApiClient.ajax({
type: 'DELETE',
url: ApiClient.getUrl('Dlna/Profiles/' + id)
}).then(function () {
loading.hide();
loadProfiles(page);
});
});
});
}
function getTabs() {
return [{
href: 'dlnasettings.html',
name: globalize.translate('TabSettings')
}, {
href: 'dlnaprofiles.html',
name: globalize.translate('TabProfiles')
}];
}
$(document).on('pageshow', '#dlnaProfilesPage', function () {
libraryMenu.setTabs('dlna', 1, getTabs);
loadProfiles(this);
});
});

View file

@ -0,0 +1,56 @@
define(['jQuery', 'loading', 'libraryMenu', 'globalize'], function ($, loading, libraryMenu, globalize) {
'use strict';
function loadPage(page, config, users) {
page.querySelector('#chkEnablePlayTo').checked = config.EnablePlayTo;
page.querySelector('#chkEnableDlnaDebugLogging').checked = config.EnableDebugLog;
$('#txtClientDiscoveryInterval', page).val(config.ClientDiscoveryIntervalSeconds);
$('#chkEnableServer', page).checked = config.EnableServer;
$('#chkBlastAliveMessages', page).checked = config.BlastAliveMessages;
$('#txtBlastInterval', page).val(config.BlastAliveMessageIntervalSeconds);
var usersHtml = users.map(function (u) {
return '<option value="' + u.Id + '">' + u.Name + '</option>';
}).join('');
$('#selectUser', page).html(usersHtml).val(config.DefaultUserId || '');
loading.hide();
}
function onSubmit() {
loading.show();
var form = this;
ApiClient.getNamedConfiguration('dlna').then(function (config) {
config.EnablePlayTo = form.querySelector('#chkEnablePlayTo').checked;
config.EnableDebugLog = form.querySelector('#chkEnableDlnaDebugLogging').checked;
config.ClientDiscoveryIntervalSeconds = $('#txtClientDiscoveryInterval', form).val();
config.EnableServer = $('#chkEnableServer', form).checked;
config.BlastAliveMessages = $('#chkBlastAliveMessages', form).checked;
config.BlastAliveMessageIntervalSeconds = $('#txtBlastInterval', form).val();
config.DefaultUserId = $('#selectUser', form).val();
ApiClient.updateNamedConfiguration('dlna', config).then(Dashboard.processServerConfigurationUpdateResult);
});
return false;
}
function getTabs() {
return [{
href: 'dlnasettings.html',
name: globalize.translate('TabSettings')
}, {
href: 'dlnaprofiles.html',
name: globalize.translate('TabProfiles')
}];
}
$(document).on('pageinit', '#dlnaSettingsPage', function () {
$('.dlnaSettingsForm').off('submit', onSubmit).on('submit', onSubmit);
}).on('pageshow', '#dlnaSettingsPage', function () {
libraryMenu.setTabs('dlna', 0, getTabs);
loading.show();
var page = this;
var promise1 = ApiClient.getNamedConfiguration('dlna');
var promise2 = ApiClient.getUsers();
Promise.all([promise1, promise2]).then(function (responses) {
loadPage(page, responses[0], responses[1]);
});
});
});

View file

@ -0,0 +1,194 @@
define(['jQuery', 'loading', 'globalize', 'dom', 'libraryMenu'], function ($, loading, globalize, dom, libraryMenu) {
'use strict';
function loadPage(page, config, systemInfo) {
Array.prototype.forEach.call(page.querySelectorAll('.chkDecodeCodec'), function (c) {
c.checked = -1 !== (config.HardwareDecodingCodecs || []).indexOf(c.getAttribute('data-codec'));
});
page.querySelector('#chkDecodingColorDepth10').checked = config.EnableDecodingColorDepth10;
page.querySelector('#chkHardwareEncoding').checked = config.EnableHardwareEncoding;
$('#selectVideoDecoder', page).val(config.HardwareAccelerationType);
$('#selectThreadCount', page).val(config.EncodingThreadCount);
$('#txtDownMixAudioBoost', page).val(config.DownMixAudioBoost);
page.querySelector('.txtEncoderPath').value = config.EncoderAppPathDisplay || '';
$('#txtTranscodingTempPath', page).val(systemInfo.TranscodingTempPath || '');
$('#txtVaapiDevice', page).val(config.VaapiDevice || '');
page.querySelector('#selectEncoderPreset').value = config.EncoderPreset || '';
page.querySelector('#txtH264Crf').value = config.H264Crf || '';
page.querySelector('#selectDeinterlaceMethod').value = config.DeinterlaceMethod || '';
page.querySelector('#chkEnableSubtitleExtraction').checked = config.EnableSubtitleExtraction || false;
page.querySelector('#chkEnableThrottling').checked = config.EnableThrottling || false;
page.querySelector('#selectVideoDecoder').dispatchEvent(new CustomEvent('change', {
bubbles: true
}));
loading.hide();
}
function onSaveEncodingPathFailure(response) {
loading.hide();
var msg = '';
msg = globalize.translate('FFmpegSavePathNotFound');
require(['alert'], function (alert) {
alert(msg);
});
}
function updateEncoder(form) {
return ApiClient.getSystemInfo().then(function (systemInfo) {
return ApiClient.ajax({
url: ApiClient.getUrl('System/MediaEncoder/Path'),
type: 'POST',
data: {
Path: form.querySelector('.txtEncoderPath').value,
PathType: 'Custom'
}
}).then(Dashboard.processServerConfigurationUpdateResult, onSaveEncodingPathFailure);
});
}
function onSubmit() {
var form = this;
var onDecoderConfirmed = function () {
loading.show();
ApiClient.getNamedConfiguration('encoding').then(function (config) {
config.DownMixAudioBoost = $('#txtDownMixAudioBoost', form).val();
config.TranscodingTempPath = $('#txtTranscodingTempPath', form).val();
config.EncodingThreadCount = $('#selectThreadCount', form).val();
config.HardwareAccelerationType = $('#selectVideoDecoder', form).val();
config.VaapiDevice = $('#txtVaapiDevice', form).val();
config.EncoderPreset = form.querySelector('#selectEncoderPreset').value;
config.H264Crf = parseInt(form.querySelector('#txtH264Crf').value || '0');
config.DeinterlaceMethod = form.querySelector('#selectDeinterlaceMethod').value;
config.EnableSubtitleExtraction = form.querySelector('#chkEnableSubtitleExtraction').checked;
config.EnableThrottling = form.querySelector('#chkEnableThrottling').checked;
config.HardwareDecodingCodecs = Array.prototype.map.call(Array.prototype.filter.call(form.querySelectorAll('.chkDecodeCodec'), function (c) {
return c.checked;
}), function (c) {
return c.getAttribute('data-codec');
});
config.EnableDecodingColorDepth10 = form.querySelector('#chkDecodingColorDepth10').checked;
config.EnableHardwareEncoding = form.querySelector('#chkHardwareEncoding').checked;
ApiClient.updateNamedConfiguration('encoding', config).then(function () {
updateEncoder(form);
}, function () {
require(['alert'], function (alert) {
alert(globalize.translate('DefaultErrorMessage'));
});
Dashboard.processServerConfigurationUpdateResult();
});
});
};
if ($('#selectVideoDecoder', form).val()) {
require(['alert'], function (alert) {
alert({
title: globalize.translate('TitleHardwareAcceleration'),
text: globalize.translate('HardwareAccelerationWarning')
}).then(onDecoderConfirmed);
});
} else {
onDecoderConfirmed();
}
return false;
}
function setDecodingCodecsVisible(context, value) {
value = value || '';
var any;
Array.prototype.forEach.call(context.querySelectorAll('.chkDecodeCodec'), function (c) {
if (-1 === c.getAttribute('data-types').split(',').indexOf(value)) {
dom.parentWithTag(c, 'LABEL').classList.add('hide');
} else {
dom.parentWithTag(c, 'LABEL').classList.remove('hide');
any = true;
}
});
if (any) {
context.querySelector('.decodingCodecsList').classList.remove('hide');
} else {
context.querySelector('.decodingCodecsList').classList.add('hide');
}
}
function getTabs() {
return [{
href: 'encodingsettings.html',
name: globalize.translate('Transcoding')
}, {
href: 'playbackconfiguration.html',
name: globalize.translate('TabResumeSettings')
}, {
href: 'streamingsettings.html',
name: globalize.translate('TabStreaming')
}];
}
$(document).on('pageinit', '#encodingSettingsPage', function () {
var page = this;
page.querySelector('#selectVideoDecoder').addEventListener('change', function () {
if ('vaapi' == this.value) {
page.querySelector('.fldVaapiDevice').classList.remove('hide');
page.querySelector('#txtVaapiDevice').setAttribute('required', 'required');
} else {
page.querySelector('.fldVaapiDevice').classList.add('hide');
page.querySelector('#txtVaapiDevice').removeAttribute('required');
}
if (this.value) {
page.querySelector('.hardwareAccelerationOptions').classList.remove('hide');
} else {
page.querySelector('.hardwareAccelerationOptions').classList.add('hide');
}
setDecodingCodecsVisible(page, this.value);
});
$('#btnSelectEncoderPath', page).on('click.selectDirectory', function () {
require(['directorybrowser'], function (directoryBrowser) {
var picker = new directoryBrowser();
picker.show({
includeFiles: true,
callback: function (path) {
if (path) {
$('.txtEncoderPath', page).val(path);
}
picker.close();
}
});
});
});
$('#btnSelectTranscodingTempPath', page).on('click.selectDirectory', function () {
require(['directorybrowser'], function (directoryBrowser) {
var picker = new directoryBrowser();
picker.show({
callback: function (path) {
if (path) {
$('#txtTranscodingTempPath', page).val(path);
}
picker.close();
},
validateWriteable: true,
header: globalize.translate('HeaderSelectTranscodingPath'),
instruction: globalize.translate('HeaderSelectTranscodingPathHelp')
});
});
});
$('.encodingSettingsForm').off('submit', onSubmit).on('submit', onSubmit);
}).on('pageshow', '#encodingSettingsPage', function () {
loading.show();
libraryMenu.setTabs('playback', 0, getTabs);
var page = this;
ApiClient.getNamedConfiguration('encoding').then(function (config) {
ApiClient.getSystemInfo().then(function (systemInfo) {
loadPage(page, config, systemInfo);
});
});
});
});

View file

@ -1,28 +1,15 @@
define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emby-input", "emby-select", "emby-button"], function ($, loading) {
"use strict";
define(['jQuery', 'loading', 'globalize', 'emby-checkbox', 'emby-textarea', 'emby-input', 'emby-select', 'emby-button'], function ($, loading, globalize) {
'use strict';
function loadPage(page, config, languageOptions, systemInfo) {
page.querySelector("#txtServerName").value = systemInfo.ServerName;
$("#chkAutoRunWebApp", page).checked(config.AutoRunWebApp);
if (systemInfo.CanLaunchWebBrowser) {
page.querySelector("#fldAutoRunWebApp").classList.remove("hide");
} else {
page.querySelector("#fldAutoRunWebApp").classList.add("hide");
}
page.querySelector("#txtCachePath").value = systemInfo.CachePath || "";
$("#txtMetadataPath", page).val(systemInfo.InternalMetadataPath || "");
$("#txtMetadataNetworkPath", page).val(systemInfo.MetadataNetworkPath || "");
$("#selectLocalizationLanguage", page).html(languageOptions.map(function (language) {
return '<option value="' + language.Value + '">' + language.Name + "</option>";
page.querySelector('#txtServerName').value = systemInfo.ServerName;
page.querySelector('#txtCachePath').value = systemInfo.CachePath || '';
$('#txtMetadataPath', page).val(systemInfo.InternalMetadataPath || '');
$('#txtMetadataNetworkPath', page).val(systemInfo.MetadataNetworkPath || '');
$('#selectLocalizationLanguage', page).html(languageOptions.map(function (language) {
return '<option value="' + language.Value + '">' + language.Name + '</option>';
})).val(config.UICulture);
currentLanguage = config.UICulture;
if (systemInfo.CanSelfRestart || systemInfo.CanSelfUpdate) {
$(".autoUpdatesContainer", page).removeClass("hide");
} else {
$(".autoUpdatesContainer", page).addClass("hide");
}
loading.hide();
}
@ -30,19 +17,18 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb
function onSubmit() {
loading.show();
var form = this;
$(form).parents(".page");
$(form).parents('.page');
ApiClient.getServerConfiguration().then(function (config) {
config.ServerName = $("#txtServerName", form).val();
config.UICulture = $("#selectLocalizationLanguage", form).val();
config.CachePath = form.querySelector("#txtCachePath").value;
config.MetadataPath = $("#txtMetadataPath", form).val();
config.MetadataNetworkPath = $("#txtMetadataNetworkPath", form).val();
config.ServerName = $('#txtServerName', form).val();
config.UICulture = $('#selectLocalizationLanguage', form).val();
config.CachePath = form.querySelector('#txtCachePath').value;
config.MetadataPath = $('#txtMetadataPath', form).val();
config.MetadataNetworkPath = $('#txtMetadataNetworkPath', form).val();
var requiresReload = config.UICulture !== currentLanguage;
config.AutoRunWebApp = $("#chkAutoRunWebApp", form).checked();
ApiClient.updateServerConfiguration(config).then(function() {
ApiClient.getNamedConfiguration(brandingConfigKey).then(function(brandingConfig) {
brandingConfig.LoginDisclaimer = form.querySelector("#txtLoginDisclaimer").value;
brandingConfig.CustomCss = form.querySelector("#txtCustomCss").value;
brandingConfig.LoginDisclaimer = form.querySelector('#txtLoginDisclaimer').value;
brandingConfig.CustomCss = form.querySelector('#txtCustomCss').value;
if (currentBrandingOptions && brandingConfig.CustomCss !== currentBrandingOptions.CustomCss) {
requiresReload = true;
@ -57,8 +43,8 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb
});
});
}, function () {
require(["alert"], function (alert) {
alert(Globalize.translate("DefaultErrorMessage"));
require(['alert'], function (alert) {
alert(globalize.translate('DefaultErrorMessage'));
});
Dashboard.processServerConfigurationUpdateResult();
@ -69,61 +55,61 @@ define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emb
var currentBrandingOptions;
var currentLanguage;
var brandingConfigKey = "branding";
var brandingConfigKey = 'branding';
return function (view, params) {
$("#btnSelectCachePath", view).on("click.selectDirectory", function () {
require(["directorybrowser"], function (directoryBrowser) {
$('#btnSelectCachePath', view).on('click.selectDirectory', function () {
require(['directorybrowser'], function (directoryBrowser) {
var picker = new directoryBrowser();
picker.show({
callback: function (path) {
if (path) {
view.querySelector("#txtCachePath").value = path;
view.querySelector('#txtCachePath').value = path;
}
picker.close();
},
validateWriteable: true,
header: Globalize.translate("HeaderSelectServerCachePath"),
instruction: Globalize.translate("HeaderSelectServerCachePathHelp")
header: globalize.translate('HeaderSelectServerCachePath'),
instruction: globalize.translate('HeaderSelectServerCachePathHelp')
});
});
});
$("#btnSelectMetadataPath", view).on("click.selectDirectory", function () {
require(["directorybrowser"], function (directoryBrowser) {
$('#btnSelectMetadataPath', view).on('click.selectDirectory', function () {
require(['directorybrowser'], function (directoryBrowser) {
var picker = new directoryBrowser();
picker.show({
path: $("#txtMetadataPath", view).val(),
networkSharePath: $("#txtMetadataNetworkPath", view).val(),
path: $('#txtMetadataPath', view).val(),
networkSharePath: $('#txtMetadataNetworkPath', view).val(),
callback: function (path, networkPath) {
if (path) {
$("#txtMetadataPath", view).val(path);
$('#txtMetadataPath', view).val(path);
}
if (networkPath) {
$("#txtMetadataNetworkPath", view).val(networkPath);
$('#txtMetadataNetworkPath', view).val(networkPath);
}
picker.close();
},
validateWriteable: true,
header: Globalize.translate("HeaderSelectMetadataPath"),
instruction: Globalize.translate("HeaderSelectMetadataPathHelp"),
header: globalize.translate('HeaderSelectMetadataPath'),
instruction: globalize.translate('HeaderSelectMetadataPathHelp'),
enableNetworkSharePath: true
});
});
});
$(".dashboardGeneralForm", view).off("submit", onSubmit).on("submit", onSubmit);
view.addEventListener("viewshow", function () {
$('.dashboardGeneralForm', view).off('submit', onSubmit).on('submit', onSubmit);
view.addEventListener('viewshow', function () {
var promiseConfig = ApiClient.getServerConfiguration();
var promiseLanguageOptions = ApiClient.getJSON(ApiClient.getUrl("Localization/Options"));
var promiseLanguageOptions = ApiClient.getJSON(ApiClient.getUrl('Localization/Options'));
var promiseSystemInfo = ApiClient.getSystemInfo();
Promise.all([promiseConfig, promiseLanguageOptions, promiseSystemInfo]).then(function (responses) {
loadPage(view, responses[0], responses[1], responses[2]);
});
ApiClient.getNamedConfiguration(brandingConfigKey).then(function (config) {
currentBrandingOptions = config;
view.querySelector("#txtLoginDisclaimer").value = config.LoginDisclaimer || "";
view.querySelector("#txtCustomCss").value = config.CustomCss || "";
view.querySelector('#txtLoginDisclaimer').value = config.LoginDisclaimer || '';
view.querySelector('#txtCustomCss').value = config.CustomCss || '';
});
});
};

View file

@ -0,0 +1,67 @@
define(['globalize', 'loading', 'libraryMenu', 'emby-checkbox', 'emby-button', 'emby-button'], function(globalize, loading, libraryMenu) {
'use strict';
function getTabs() {
return [{
href: 'library.html',
name: globalize.translate('HeaderLibraries')
}, {
href: 'librarydisplay.html',
name: globalize.translate('TabDisplay')
}, {
href: 'metadataimages.html',
name: globalize.translate('TabMetadata')
}, {
href: 'metadatanfo.html',
name: globalize.translate('TabNfoSettings')
}];
}
return function(view, params) {
function loadData() {
ApiClient.getServerConfiguration().then(function(config) {
view.querySelector('.chkFolderView').checked = config.EnableFolderView;
view.querySelector('.chkGroupMoviesIntoCollections').checked = config.EnableGroupingIntoCollections;
view.querySelector('.chkDisplaySpecialsWithinSeasons').checked = config.DisplaySpecialsWithinSeasons;
view.querySelector('.chkExternalContentInSuggestions').checked = config.EnableExternalContentInSuggestions;
view.querySelector('#chkSaveMetadataHidden').checked = config.SaveMetadataHidden;
});
ApiClient.getNamedConfiguration('metadata').then(function(metadata) {
view.querySelector('#selectDateAdded').selectedIndex = metadata.UseFileCreationTimeForDateAdded ? 1 : 0;
});
}
view.querySelector('form').addEventListener('submit', function(e) {
loading.show();
var form = this;
ApiClient.getServerConfiguration().then(function(config) {
config.EnableFolderView = form.querySelector('.chkFolderView').checked;
config.EnableGroupingIntoCollections = form.querySelector('.chkGroupMoviesIntoCollections').checked;
config.DisplaySpecialsWithinSeasons = form.querySelector('.chkDisplaySpecialsWithinSeasons').checked;
config.EnableExternalContentInSuggestions = form.querySelector('.chkExternalContentInSuggestions').checked;
config.SaveMetadataHidden = form.querySelector('#chkSaveMetadataHidden').checked;
ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult);
});
ApiClient.getNamedConfiguration('metadata').then(function(config) {
config.UseFileCreationTimeForDateAdded = '1' === $('#selectDateAdded', form).val();
ApiClient.updateNamedConfiguration('metadata', config);
});
e.preventDefault();
loading.hide();
return false;
});
view.addEventListener('viewshow', function() {
libraryMenu.setTabs('librarysetup', 1, getTabs);
loadData();
ApiClient.getSystemInfo().then(function(info) {
if ('Windows' === info.OperatingSystem) {
view.querySelector('.fldSaveMetadataHidden').classList.remove('hide');
} else {
view.querySelector('.fldSaveMetadataHidden').classList.add('hide');
}
});
});
};
});

View file

@ -1,31 +1,31 @@
define(["datetime", "loading", "apphost", "listViewStyle", "emby-button", "flexStyles"], function(datetime, loading, appHost) {
"use strict";
define(['datetime', 'loading', 'apphost', 'listViewStyle', 'emby-button', 'flexStyles'], function(datetime, loading, appHost) {
'use strict';
return function(view, params) {
view.addEventListener("viewbeforeshow", function() {
view.addEventListener('viewbeforeshow', function() {
loading.show();
var apiClient = ApiClient;
apiClient.getJSON(apiClient.getUrl("System/Logs")).then(function(logs) {
var html = "";
apiClient.getJSON(apiClient.getUrl('System/Logs')).then(function(logs) {
var html = '';
html += '<div class="paperList">';
html += logs.map(function(log) {
var logUrl = apiClient.getUrl("System/Logs/Log", {
var logUrl = apiClient.getUrl('System/Logs/Log', {
name: log.Name
});
logUrl += "&api_key=" + apiClient.accessToken();
var logHtml = "";
logUrl += '&api_key=' + apiClient.accessToken();
var logHtml = '';
logHtml += '<a is="emby-linkbutton" href="' + logUrl + '" target="_blank" class="listItem listItem-border" style="color:inherit;">';
logHtml += '<div class="listItemBody two-line">';
logHtml += "<h3 class='listItemBodyText'>" + log.Name + "</h3>";
logHtml += "<h3 class='listItemBodyText'>" + log.Name + '</h3>';
var date = datetime.parseISO8601Date(log.DateModified, true);
var text = datetime.toLocaleDateString(date);
text += " " + datetime.getDisplayTime(date);
logHtml += '<div class="listItemBodyText secondary">' + text + "</div>";
logHtml += "</div>";
logHtml += "</a>";
text += ' ' + datetime.getDisplayTime(date);
logHtml += '<div class="listItemBodyText secondary">' + text + '</div>';
logHtml += '</div>';
logHtml += '</a>';
return logHtml;
}).join("");
html += "</div>";
view.querySelector(".serverLogs").innerHTML = html;
}).join('');
html += '</div>';
view.querySelector('.serverLogs').innerHTML = html;
loading.hide();
});
});

View file

@ -0,0 +1,391 @@
define(['jQuery', 'apphost', 'scripts/taskbutton', 'loading', 'libraryMenu', 'globalize', 'dom', 'indicators', 'scripts/imagehelper', 'cardStyle', 'emby-itemrefreshindicator'], function ($, appHost, taskButton, loading, libraryMenu, globalize, dom, indicators, imageHelper) {
'use strict';
function addVirtualFolder(page) {
require(['medialibrarycreator'], function (medialibrarycreator) {
new medialibrarycreator().show({
collectionTypeOptions: getCollectionTypeOptions().filter(function (f) {
return !f.hidden;
}),
refresh: shouldRefreshLibraryAfterChanges(page)
}).then(function (hasChanges) {
if (hasChanges) {
reloadLibrary(page);
}
});
});
}
function editVirtualFolder(page, virtualFolder) {
require(['medialibraryeditor'], function (medialibraryeditor) {
new medialibraryeditor().show({
refresh: shouldRefreshLibraryAfterChanges(page),
library: virtualFolder
}).then(function (hasChanges) {
if (hasChanges) {
reloadLibrary(page);
}
});
});
}
function deleteVirtualFolder(page, virtualFolder) {
var msg = globalize.translate('MessageAreYouSureYouWishToRemoveMediaFolder');
if (virtualFolder.Locations.length) {
msg += '<br/><br/>' + globalize.translate('MessageTheFollowingLocationWillBeRemovedFromLibrary') + '<br/><br/>';
msg += virtualFolder.Locations.join('<br/>');
}
require(['confirm'], function (confirm) {
confirm({
text: msg,
title: globalize.translate('HeaderRemoveMediaFolder'),
confirmText: globalize.translate('Delete'),
primary: 'delete'
}).then(function () {
var refreshAfterChange = shouldRefreshLibraryAfterChanges(page);
ApiClient.removeVirtualFolder(virtualFolder.Name, refreshAfterChange).then(function () {
reloadLibrary(page);
});
});
});
}
function refreshVirtualFolder(page, virtualFolder) {
require(['refreshDialog'], function (refreshDialog) {
new refreshDialog({
itemIds: [virtualFolder.ItemId],
serverId: ApiClient.serverId(),
mode: 'scan'
}).show();
});
}
function renameVirtualFolder(page, virtualFolder) {
require(['prompt'], function (prompt) {
prompt({
label: globalize.translate('LabelNewName'),
confirmText: globalize.translate('ButtonRename')
}).then(function (newName) {
if (newName && newName != virtualFolder.Name) {
var refreshAfterChange = shouldRefreshLibraryAfterChanges(page);
ApiClient.renameVirtualFolder(virtualFolder.Name, newName, refreshAfterChange).then(function () {
reloadLibrary(page);
});
}
});
});
}
function showCardMenu(page, elem, virtualFolders) {
var card = dom.parentWithClass(elem, 'card');
var index = parseInt(card.getAttribute('data-index'));
var virtualFolder = virtualFolders[index];
var menuItems = [];
menuItems.push({
name: globalize.translate('ButtonEditImages'),
id: 'editimages',
icon: 'photo'
});
menuItems.push({
name: globalize.translate('ManageLibrary'),
id: 'edit',
icon: 'folder_open'
});
menuItems.push({
name: globalize.translate('ButtonRemove'),
id: 'delete',
icon: 'delete'
});
menuItems.push({
name: globalize.translate('ButtonRename'),
id: 'rename',
icon: 'mode_edit'
});
menuItems.push({
name: globalize.translate('ScanLibrary'),
id: 'refresh',
icon: 'refresh'
});
require(['actionsheet'], function (actionsheet) {
actionsheet.show({
items: menuItems,
positionTo: elem,
callback: function (resultId) {
switch (resultId) {
case 'edit':
editVirtualFolder(page, virtualFolder);
break;
case 'editimages':
editImages(page, virtualFolder);
break;
case 'rename':
renameVirtualFolder(page, virtualFolder);
break;
case 'delete':
deleteVirtualFolder(page, virtualFolder);
break;
case 'refresh':
refreshVirtualFolder(page, virtualFolder);
}
}
});
});
}
function reloadLibrary(page) {
loading.show();
ApiClient.getVirtualFolders().then(function (result) {
reloadVirtualFolders(page, result);
});
}
function shouldRefreshLibraryAfterChanges(page) {
return 'mediaLibraryPage' === page.id;
}
function reloadVirtualFolders(page, virtualFolders) {
var html = '';
virtualFolders.push({
Name: globalize.translate('ButtonAddMediaLibrary'),
icon: 'add_circle',
Locations: [],
showType: false,
showLocations: false,
showMenu: false,
showNameWithIcon: true
});
for (var i = 0; i < virtualFolders.length; i++) {
var virtualFolder = virtualFolders[i];
html += getVirtualFolderHtml(page, virtualFolder, i);
}
var divVirtualFolders = page.querySelector('#divVirtualFolders');
divVirtualFolders.innerHTML = html;
divVirtualFolders.classList.add('itemsContainer');
divVirtualFolders.classList.add('vertical-wrap');
$('.btnCardMenu', divVirtualFolders).on('click', function () {
showCardMenu(page, this, virtualFolders);
});
divVirtualFolders.querySelector('.addLibrary').addEventListener('click', function () {
addVirtualFolder(page);
});
$('.editLibrary', divVirtualFolders).on('click', function () {
var card = $(this).parents('.card')[0];
var index = parseInt(card.getAttribute('data-index'));
var virtualFolder = virtualFolders[index];
if (virtualFolder.ItemId) {
editVirtualFolder(page, virtualFolder);
}
});
loading.hide();
}
function editImages(page, virtualFolder) {
require(['imageEditor'], function (imageEditor) {
imageEditor.show({
itemId: virtualFolder.ItemId,
serverId: ApiClient.serverId()
}).then(function () {
reloadLibrary(page);
});
});
}
function getLink(text, url) {
return globalize.translate(text, '<a is="emby-linkbutton" class="button-link" href="' + url + '" target="_blank" data-autohide="true">', '</a>');
}
function getCollectionTypeOptions() {
return [{
name: '',
value: ''
}, {
name: globalize.translate('FolderTypeMovies'),
value: 'movies',
message: getLink('MovieLibraryHelp', 'https://docs.jellyfin.org/general/server/media/movies.html')
}, {
name: globalize.translate('FolderTypeMusic'),
value: 'music',
message: getLink('MusicLibraryHelp', 'https://docs.jellyfin.org/general/server/media/music.html')
}, {
name: globalize.translate('FolderTypeTvShows'),
value: 'tvshows',
message: getLink('TvLibraryHelp', 'https://docs.jellyfin.org/general/server/media/shows.html')
}, {
name: globalize.translate('FolderTypeBooks'),
value: 'books',
message: getLink('BookLibraryHelp', 'https://docs.jellyfin.org/general/server/media/books.html')
}, {
name: globalize.translate('OptionHomeVideos'),
value: 'homevideos'
}, {
name: globalize.translate('FolderTypeMusicVideos'),
value: 'musicvideos'
}, {
name: globalize.translate('FolderTypeUnset'),
value: 'mixed',
message: globalize.translate('MessageUnsetContentHelp')
}];
}
function getVirtualFolderHtml(page, virtualFolder, index) {
var html = '';
var style = '';
if (page.classList.contains('wizardPage')) {
style += 'min-width:33.3%;';
}
html += '<div class="card backdropCard scalableCard backdropCard-scalable" style="' + style + '" data-index="' + index + '" data-id="' + virtualFolder.ItemId + '">';
html += '<div class="cardBox visualCardBox">';
html += '<div class="cardScalable visualCardBox-cardScalable">';
html += '<div class="cardPadder cardPadder-backdrop"></div>';
html += '<div class="cardContent">';
var imgUrl = '';
if (virtualFolder.PrimaryImageItemId) {
imgUrl = ApiClient.getScaledImageUrl(virtualFolder.PrimaryImageItemId, {
maxWidth: Math.round(dom.getScreenWidth() * 0.40),
type: 'Primary'
});
}
var hasCardImageContainer;
if (imgUrl) {
html += '<div class="cardImageContainer editLibrary" style="cursor:pointer;background-image:url(\'' + imgUrl + "');\">";
hasCardImageContainer = true;
} else if (!virtualFolder.showNameWithIcon) {
html += '<div class="cardImageContainer editLibrary" style="cursor:pointer;">';
html += '<span class="cardImageIcon-small material-icons ' + (virtualFolder.icon || imageHelper.getLibraryIcon(virtualFolder.CollectionType)) + '"></span>';
hasCardImageContainer = true;
}
if (hasCardImageContainer) {
html += '<div class="cardIndicators backdropCardIndicators">';
html += '<div is="emby-itemrefreshindicator"' + (virtualFolder.RefreshProgress || virtualFolder.RefreshStatus && 'Idle' !== virtualFolder.RefreshStatus ? '' : ' class="hide"') + ' data-progress="' + (virtualFolder.RefreshProgress || 0) + '" data-status="' + virtualFolder.RefreshStatus + '"></div>';
html += '</div>';
html += '</div>';
}
if (!imgUrl && virtualFolder.showNameWithIcon) {
html += '<h3 class="cardImageContainer addLibrary" style="position:absolute;top:0;left:0;right:0;bottom:0;cursor:pointer;flex-direction:column;">';
html += '<span class="cardImageIcon-small material-icons ' + (virtualFolder.icon || imageHelper.getLibraryIcon(virtualFolder.CollectionType)) + '"></span>';
if (virtualFolder.showNameWithIcon) {
html += '<div style="margin:1em 0;position:width:100%;">';
html += virtualFolder.Name;
html += '</div>';
}
html += '</h3>';
}
html += '</div>';
html += '</div>';
html += '<div class="cardFooter visualCardBox-cardFooter">'; // always show menu unless explicitly hidden
if (virtualFolder.showMenu !== false) {
html += '<div style="text-align:right; float:right;padding-top:5px;">';
html += '<button type="button" is="paper-icon-button-light" class="btnCardMenu autoSize"><span class="material-icons more_vert"></span></button>';
html += '</div>';
}
html += "<div class='cardText'>";
if (virtualFolder.showNameWithIcon) {
html += '&nbsp;';
} else {
html += virtualFolder.Name;
}
html += '</div>';
var typeName = getCollectionTypeOptions().filter(function (t) {
return t.value == virtualFolder.CollectionType;
})[0];
typeName = typeName ? typeName.name : globalize.translate('FolderTypeUnset');
html += "<div class='cardText cardText-secondary'>";
if (virtualFolder.showType === false) {
html += '&nbsp;';
} else {
html += typeName;
}
html += '</div>';
if (virtualFolder.showLocations === false) {
html += "<div class='cardText cardText-secondary'>";
html += '&nbsp;';
html += '</div>';
} else if (virtualFolder.Locations.length && virtualFolder.Locations.length === 1) {
html += "<div class='cardText cardText-secondary'>";
html += virtualFolder.Locations[0];
html += '</div>';
} else {
html += "<div class='cardText cardText-secondary'>";
html += globalize.translate('NumLocationsValue', virtualFolder.Locations.length);
html += '</div>';
}
html += '</div>';
html += '</div>';
html += '</div>';
return html;
}
function getTabs() {
return [{
href: 'library.html',
name: globalize.translate('HeaderLibraries')
}, {
href: 'librarydisplay.html',
name: globalize.translate('TabDisplay')
}, {
href: 'metadataimages.html',
name: globalize.translate('TabMetadata')
}, {
href: 'metadatanfo.html',
name: globalize.translate('TabNfoSettings')
}];
}
window.WizardLibraryPage = {
next: function () {
Dashboard.navigate('wizardsettings.html');
}
};
pageClassOn('pageshow', 'mediaLibraryPage', function () {
reloadLibrary(this);
});
pageIdOn('pageshow', 'mediaLibraryPage', function () {
libraryMenu.setTabs('librarysetup', 0, getTabs);
var page = this;
taskButton({
mode: 'on',
progressElem: page.querySelector('.refreshProgress'),
taskKey: 'RefreshLibrary',
button: page.querySelector('.btnRefresh')
});
});
pageIdOn('pagebeforehide', 'mediaLibraryPage', function () {
var page = this;
taskButton({
mode: 'off',
progressElem: page.querySelector('.refreshProgress'),
taskKey: 'RefreshLibrary',
button: page.querySelector('.btnRefresh')
});
});
});

View file

@ -0,0 +1,70 @@
define(['jQuery', 'dom', 'loading', 'libraryMenu', 'globalize', 'listViewStyle'], function($, dom, loading, libraryMenu, globalize) {
'use strict';
function populateLanguages(select) {
return ApiClient.getCultures().then(function(languages) {
var html = '';
html += "<option value=''></option>";
for (var i = 0, length = languages.length; i < length; i++) {
var culture = languages[i];
html += "<option value='" + culture.TwoLetterISOLanguageName + "'>" + culture.DisplayName + '</option>';
}
select.innerHTML = html;
});
}
function populateCountries(select) {
return ApiClient.getCountries().then(function(allCountries) {
var html = '';
html += "<option value=''></option>";
for (var i = 0, length = allCountries.length; i < length; i++) {
var culture = allCountries[i];
html += "<option value='" + culture.TwoLetterISORegionName + "'>" + culture.DisplayName + '</option>';
}
select.innerHTML = html;
});
}
function loadPage(page) {
var promises = [ApiClient.getServerConfiguration(), populateLanguages(page.querySelector('#selectLanguage')), populateCountries(page.querySelector('#selectCountry'))];
Promise.all(promises).then(function(responses) {
var config = responses[0];
page.querySelector('#selectLanguage').value = config.PreferredMetadataLanguage || '';
page.querySelector('#selectCountry').value = config.MetadataCountryCode || '';
loading.hide();
});
}
function onSubmit() {
var form = this;
return loading.show(), ApiClient.getServerConfiguration().then(function(config) {
config.PreferredMetadataLanguage = form.querySelector('#selectLanguage').value;
config.MetadataCountryCode = form.querySelector('#selectCountry').value;
ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult);
}), !1;
}
function getTabs() {
return [{
href: 'library.html',
name: globalize.translate('HeaderLibraries')
}, {
href: 'librarydisplay.html',
name: globalize.translate('TabDisplay')
}, {
href: 'metadataimages.html',
name: globalize.translate('TabMetadata')
}, {
href: 'metadatanfo.html',
name: globalize.translate('TabNfoSettings')
}];
}
$(document).on('pageinit', '#metadataImagesConfigurationPage', function() {
$('.metadataImagesConfigurationForm').off('submit', onSubmit).on('submit', onSubmit);
}).on('pageshow', '#metadataImagesConfigurationPage', function() {
libraryMenu.setTabs('metadata', 2, getTabs);
loading.show();
loadPage(this);
});
});

View file

@ -0,0 +1,74 @@
define(['jQuery', 'loading', 'libraryMenu', 'globalize'], function ($, loading, libraryMenu, globalize) {
'use strict';
function loadPage(page, config, users) {
var html = '<option value="" selected="selected">' + globalize.translate('OptionNone') + '</option>';
html += users.map(function (user) {
return '<option value="' + user.Id + '">' + user.Name + '</option>';
}).join('');
$('#selectUser', page).html(html).val(config.UserId || '');
$('#selectReleaseDateFormat', page).val(config.ReleaseDateFormat);
page.querySelector('#chkSaveImagePaths').checked = config.SaveImagePathsInNfo;
page.querySelector('#chkEnablePathSubstitution').checked = config.EnablePathSubstitution;
page.querySelector('#chkEnableExtraThumbs').checked = config.EnableExtraThumbsDuplication;
loading.hide();
}
function onSubmit() {
loading.show();
var form = this;
ApiClient.getNamedConfiguration(metadataKey).then(function (config) {
config.UserId = $('#selectUser', form).val() || null;
config.ReleaseDateFormat = $('#selectReleaseDateFormat', form).val();
config.SaveImagePathsInNfo = form.querySelector('#chkSaveImagePaths').checked;
config.EnablePathSubstitution = form.querySelector('#chkEnablePathSubstitution').checked;
config.EnableExtraThumbsDuplication = form.querySelector('#chkEnableExtraThumbs').checked;
ApiClient.updateNamedConfiguration(metadataKey, config).then(function () {
Dashboard.processServerConfigurationUpdateResult();
showConfirmMessage(config);
});
});
return false;
}
function showConfirmMessage(config) {
var msg = [];
msg.push(globalize.translate('MetadataSettingChangeHelp'));
require(['alert'], function (alert) {
alert({
text: msg.join('<br/><br/>')
});
});
}
function getTabs() {
return [{
href: 'library.html',
name: globalize.translate('HeaderLibraries')
}, {
href: 'librarydisplay.html',
name: globalize.translate('TabDisplay')
}, {
href: 'metadataimages.html',
name: globalize.translate('TabMetadata')
}, {
href: 'metadatanfo.html',
name: globalize.translate('TabNfoSettings')
}];
}
var metadataKey = 'xbmcmetadata';
$(document).on('pageinit', '#metadataNfoPage', function () {
$('.metadataNfoForm').off('submit', onSubmit).on('submit', onSubmit);
}).on('pageshow', '#metadataNfoPage', function () {
libraryMenu.setTabs('metadata', 3, getTabs);
loading.show();
var page = this;
var promise1 = ApiClient.getUsers();
var promise2 = ApiClient.getNamedConfiguration(metadataKey);
Promise.all([promise1, promise2]).then(function (responses) {
loadPage(page, responses[1], responses[0]);
});
});
});

View file

@ -1,68 +1,43 @@
define(["loading", "libraryMenu", "globalize", "emby-checkbox", "emby-select"], function (loading, libraryMenu, globalize) {
"use strict";
define(['loading', 'libraryMenu', 'globalize', 'emby-checkbox', 'emby-select'], function (loading, libraryMenu, globalize) {
'use strict';
function onSubmit(e) {
var form = this;
var localAddress = form.querySelector("#txtLocalAddress").value;
var enableUpnp = form.querySelector("#chkEnableUpnp").checked;
var localAddress = form.querySelector('#txtLocalAddress').value;
var enableUpnp = form.querySelector('#chkEnableUpnp').checked;
confirmSelections(localAddress, enableUpnp, function () {
var validationResult = getValidationAlert(form);
if (validationResult) {
alertText(validationResult);
showAlertText(validationResult);
return;
}
validateHttps(form).then(function () {
loading.show();
ApiClient.getServerConfiguration().then(function (config) {
config.LocalNetworkSubnets = form.querySelector("#txtLanNetworks").value.split(",").map(function (s) {
config.LocalNetworkSubnets = form.querySelector('#txtLanNetworks').value.split(',').map(function (s) {
return s.trim();
}).filter(function (s) {
return s.length > 0;
});
config.RemoteIPFilter = form.querySelector("#txtExternalAddressFilter").value.split(",").map(function (s) {
config.RemoteIPFilter = form.querySelector('#txtExternalAddressFilter').value.split(',').map(function (s) {
return s.trim();
}).filter(function (s) {
return s.length > 0;
});
config.IsRemoteIPFilterBlacklist = "blacklist" === form.querySelector("#selectExternalAddressFilterMode").value;
config.PublicPort = form.querySelector("#txtPublicPort").value;
config.PublicHttpsPort = form.querySelector("#txtPublicHttpsPort").value;
var httpsMode = form.querySelector("#selectHttpsMode").value;
switch (httpsMode) {
case "proxy":
config.EnableHttps = true;
config.RequireHttps = false;
config.IsBehindProxy = true;
break;
case "required":
config.EnableHttps = true;
config.RequireHttps = true;
config.IsBehindProxy = false;
break;
case "enabled":
config.EnableHttps = true;
config.RequireHttps = false;
config.IsBehindProxy = false;
break;
default:
config.EnableHttps = false;
config.RequireHttps = false;
config.IsBehindProxy = false;
}
config.HttpsPortNumber = form.querySelector("#txtHttpsPort").value;
config.HttpServerPortNumber = form.querySelector("#txtPortNumber").value;
config.IsRemoteIPFilterBlacklist = 'blacklist' === form.querySelector('#selectExternalAddressFilterMode').value;
config.PublicPort = form.querySelector('#txtPublicPort').value;
config.PublicHttpsPort = form.querySelector('#txtPublicHttpsPort').value;
config.HttpServerPortNumber = form.querySelector('#txtPortNumber').value;
config.HttpsPortNumber = form.querySelector('#txtHttpsPort').value;
config.EnableHttps = form.querySelector('#chkEnableHttps').checked;
config.RequireHttps = form.querySelector('#chkRequireHttps').checked;
config.EnableUPnP = enableUpnp;
config.BaseUrl = form.querySelector("#txtBaseUrl").value;
config.EnableRemoteAccess = form.querySelector("#chkRemoteAccess").checked;
config.CertificatePath = form.querySelector("#txtCertificatePath").value || null;
config.CertificatePassword = form.querySelector("#txtCertPassword").value || null;
config.BaseUrl = form.querySelector('#txtBaseUrl').value;
config.EnableRemoteAccess = form.querySelector('#chkRemoteAccess').checked;
config.CertificatePath = form.querySelector('#txtCertificatePath').value || null;
config.CertificatePassword = form.querySelector('#txtCertPassword').value || null;
config.LocalNetworkAddresses = localAddress ? [localAddress] : [];
ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult, Dashboard.processErrorResponse);
});
@ -72,43 +47,40 @@ define(["loading", "libraryMenu", "globalize", "emby-checkbox", "emby-select"],
}
function triggerChange(select) {
var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", false, true);
var evt = document.createEvent('HTMLEvents');
evt.initEvent('change', false, true);
select.dispatchEvent(evt);
}
function getValidationAlert(form) {
if (form.querySelector("#txtPublicPort").value === form.querySelector("#txtPublicHttpsPort").value) {
return "The public http and https ports must be different.";
if (form.querySelector('#txtPublicPort').value === form.querySelector('#txtPublicHttpsPort').value) {
return 'The public http and https ports must be different.';
}
if (form.querySelector("#txtPortNumber").value === form.querySelector("#txtHttpsPort").value) {
return "The http and https ports must be different.";
if (form.querySelector('#txtPortNumber').value === form.querySelector('#txtHttpsPort').value) {
return 'The http and https ports must be different.';
}
return null;
}
function validateHttps(form) {
var remoteAccess = form.querySelector("#chkRemoteAccess").checked;
var certPath = form.querySelector("#txtCertificatePath").value || null;
var httpsMode = form.querySelector("#selectHttpsMode").value;
var certPath = form.querySelector('#txtCertificatePath').value || null;
var httpsEnabled = form.querySelector('#chkEnableHttps').checked;
if (!remoteAccess || ("enabled" !== httpsMode && "required" !== httpsMode || certPath)) {
return Promise.resolve();
if (httpsEnabled && !certPath) {
return showAlertText({
title: globalize.translate('TitleHostingSettings'),
text: globalize.translate('HttpsRequiresCert')
}).then(Promise.reject);
}
return new Promise(function (resolve, reject) {
return alertText({
title: globalize.translate("TitleHostingSettings"),
text: globalize.translate("HttpsRequiresCert")
}).then(reject, reject);
});
return Promise.resolve();
}
function alertText(options) {
function showAlertText(options) {
return new Promise(function (resolve, reject) {
require(["alert"], function (alert) {
require(['alert'], function (alert) {
alert(options).then(resolve, reject);
});
});
@ -116,9 +88,9 @@ define(["loading", "libraryMenu", "globalize", "emby-checkbox", "emby-select"],
function confirmSelections(localAddress, enableUpnp, callback) {
if (localAddress || !enableUpnp) {
alertText({
title: globalize.translate("TitleHostingSettings"),
text: globalize.translate("SettingsWarning")
showAlertText({
title: globalize.translate('TitleHostingSettings'),
text: globalize.translate('SettingsWarning')
}).then(callback);
} else {
callback();
@ -127,76 +99,60 @@ define(["loading", "libraryMenu", "globalize", "emby-checkbox", "emby-select"],
return function (view, params) {
function loadPage(page, config) {
page.querySelector("#txtPortNumber").value = config.HttpServerPortNumber;
page.querySelector("#txtPublicPort").value = config.PublicPort;
page.querySelector("#txtPublicHttpsPort").value = config.PublicHttpsPort;
page.querySelector("#txtLocalAddress").value = config.LocalNetworkAddresses[0] || "";
page.querySelector("#txtLanNetworks").value = (config.LocalNetworkSubnets || []).join(", ");
page.querySelector("#txtExternalAddressFilter").value = (config.RemoteIPFilter || []).join(", ");
page.querySelector("#selectExternalAddressFilterMode").value = config.IsRemoteIPFilterBlacklist ? "blacklist" : "whitelist";
page.querySelector("#chkRemoteAccess").checked = null == config.EnableRemoteAccess || config.EnableRemoteAccess;
var selectHttpsMode = page.querySelector("#selectHttpsMode");
if (config.IsBehindProxy) {
selectHttpsMode.value = "proxy";
} else if (config.RequireHttps) {
selectHttpsMode.value = "required";
} else if (config.EnableHttps) {
selectHttpsMode.value = "enabled";
} else {
selectHttpsMode.value = "disabled";
}
page.querySelector("#txtHttpsPort").value = config.HttpsPortNumber;
page.querySelector("#txtBaseUrl").value = config.BaseUrl || "";
var txtCertificatePath = page.querySelector("#txtCertificatePath");
txtCertificatePath.value = config.CertificatePath || "";
page.querySelector("#txtCertPassword").value = config.CertificatePassword || "";
page.querySelector("#chkEnableUpnp").checked = config.EnableUPnP;
triggerChange(page.querySelector("#chkRemoteAccess"));
page.querySelector('#txtPortNumber').value = config.HttpServerPortNumber;
page.querySelector('#txtPublicPort').value = config.PublicPort;
page.querySelector('#txtPublicHttpsPort').value = config.PublicHttpsPort;
page.querySelector('#txtLocalAddress').value = config.LocalNetworkAddresses[0] || '';
page.querySelector('#txtLanNetworks').value = (config.LocalNetworkSubnets || []).join(', ');
page.querySelector('#txtExternalAddressFilter').value = (config.RemoteIPFilter || []).join(', ');
page.querySelector('#selectExternalAddressFilterMode').value = config.IsRemoteIPFilterBlacklist ? 'blacklist' : 'whitelist';
page.querySelector('#chkRemoteAccess').checked = null == config.EnableRemoteAccess || config.EnableRemoteAccess;
page.querySelector('#txtHttpsPort').value = config.HttpsPortNumber;
page.querySelector('#chkEnableHttps').checked = config.EnableHttps;
page.querySelector('#chkRequireHttps').checked = config.RequireHttps;
page.querySelector('#txtBaseUrl').value = config.BaseUrl || '';
var txtCertificatePath = page.querySelector('#txtCertificatePath');
txtCertificatePath.value = config.CertificatePath || '';
page.querySelector('#txtCertPassword').value = config.CertificatePassword || '';
page.querySelector('#chkEnableUpnp').checked = config.EnableUPnP;
triggerChange(page.querySelector('#chkRemoteAccess'));
loading.hide();
}
view.querySelector("#chkRemoteAccess").addEventListener("change", function () {
view.querySelector('#chkRemoteAccess').addEventListener('change', function () {
if (this.checked) {
view.querySelector(".fldExternalAddressFilter").classList.remove("hide");
view.querySelector(".fldExternalAddressFilterMode").classList.remove("hide");
view.querySelector(".fldPublicPort").classList.remove("hide");
view.querySelector(".fldPublicHttpsPort").classList.remove("hide");
view.querySelector(".fldCertificatePath").classList.remove("hide");
view.querySelector(".fldCertPassword").classList.remove("hide");
view.querySelector(".fldHttpsMode").classList.remove("hide");
view.querySelector(".fldEnableUpnp").classList.remove("hide");
view.querySelector('.fldExternalAddressFilter').classList.remove('hide');
view.querySelector('.fldExternalAddressFilterMode').classList.remove('hide');
view.querySelector('.fldPublicPort').classList.remove('hide');
view.querySelector('.fldPublicHttpsPort').classList.remove('hide');
view.querySelector('.fldEnableUpnp').classList.remove('hide');
} else {
view.querySelector(".fldExternalAddressFilter").classList.add("hide");
view.querySelector(".fldExternalAddressFilterMode").classList.add("hide");
view.querySelector(".fldPublicPort").classList.add("hide");
view.querySelector(".fldPublicHttpsPort").classList.add("hide");
view.querySelector(".fldCertificatePath").classList.add("hide");
view.querySelector(".fldCertPassword").classList.add("hide");
view.querySelector(".fldHttpsMode").classList.add("hide");
view.querySelector(".fldEnableUpnp").classList.add("hide");
view.querySelector('.fldExternalAddressFilter').classList.add('hide');
view.querySelector('.fldExternalAddressFilterMode').classList.add('hide');
view.querySelector('.fldPublicPort').classList.add('hide');
view.querySelector('.fldPublicHttpsPort').classList.add('hide');
view.querySelector('.fldEnableUpnp').classList.add('hide');
}
});
view.querySelector("#btnSelectCertPath").addEventListener("click", function () {
require(["directorybrowser"], function (directoryBrowser) {
view.querySelector('#btnSelectCertPath').addEventListener('click', function () {
require(['directorybrowser'], function (directoryBrowser) {
var picker = new directoryBrowser();
picker.show({
includeFiles: true,
includeDirectories: true,
callback: function (path) {
if (path) {
view.querySelector("#txtCertificatePath").value = path;
view.querySelector('#txtCertificatePath').value = path;
}
picker.close();
},
header: globalize.translate("HeaderSelectCertificatePath")
header: globalize.translate('HeaderSelectCertificatePath')
});
});
});
view.querySelector(".dashboardHostingForm").addEventListener("submit", onSubmit);
view.addEventListener("viewshow", function (e) {
view.querySelector('.dashboardHostingForm').addEventListener('submit', onSubmit);
view.addEventListener('viewshow', function (e) {
loading.show();
ApiClient.getServerConfiguration().then(function (config) {
loadPage(view, config);

View file

@ -1,23 +1,23 @@
define(["jQuery", "emby-checkbox", "fnchecked"], function ($) {
"use strict";
define(['jQuery', 'emby-checkbox'], function ($) {
'use strict';
function fillItems(elem, items, cssClass, idPrefix, currentList, isEnabledList) {
var html = '<div class="checkboxList paperList" style="padding: .5em 1em;">';
html += items.map(function (u) {
var isChecked = isEnabledList ? currentList.indexOf(u.Id) != -1 : currentList.indexOf(u.Id) == -1;
var checkedHtml = isChecked ? ' checked="checked"' : "";
return '<label><input is="emby-checkbox" class="' + cssClass + '" type="checkbox" data-itemid="' + u.Id + '"' + checkedHtml + "/><span>" + u.Name + "</span></label>";
}).join("");
html += "</div>";
elem.html(html).trigger("create");
var checkedHtml = isChecked ? ' checked="checked"' : '';
return '<label><input is="emby-checkbox" class="' + cssClass + '" type="checkbox" data-itemid="' + u.Id + '"' + checkedHtml + '/><span>' + u.Name + '</span></label>';
}).join('');
html += '</div>';
elem.html(html).trigger('create');
}
function reload(page) {
var type = getParameterByName("type");
var type = getParameterByName('type');
var promise1 = ApiClient.getUsers();
var promise2 = ApiClient.getNamedConfiguration(notificationsConfigurationKey);
var promise3 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Types"));
var promise4 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Services"));
var promise3 = ApiClient.getJSON(ApiClient.getUrl('Notifications/Types'));
var promise4 = ApiClient.getJSON(ApiClient.getUrl('Notifications/Services'));
Promise.all([promise1, promise2, promise3, promise4]).then(function (responses) {
var users = responses[0];
var notificationOptions = responses[1];
@ -31,37 +31,37 @@ define(["jQuery", "emby-checkbox", "fnchecked"], function ($) {
})[0] || {};
if (typeInfo.IsBasedOnUserEvent) {
$(".monitorUsers", page).show();
$('.monitorUsers', page).show();
} else {
$(".monitorUsers", page).hide();
$('.monitorUsers', page).hide();
}
$(".notificationType", page).html(typeInfo.Name || "Unknown Notification");
$('.notificationType', page).html(typeInfo.Name || 'Unknown Notification');
if (!notificationConfig) {
notificationConfig = {
DisabledMonitorUsers: [],
SendToUsers: [],
DisabledServices: [],
SendToUserMode: "Admins"
SendToUserMode: 'Admins'
};
}
fillItems($(".monitorUsersList", page), users, "chkMonitor", "chkMonitor", notificationConfig.DisabledMonitorUsers);
fillItems($(".sendToUsersList", page), users, "chkSendTo", "chkSendTo", notificationConfig.SendToUsers, true);
fillItems($(".servicesList", page), services, "chkService", "chkService", notificationConfig.DisabledServices);
$("#chkEnabled", page).checked(notificationConfig.Enabled || false);
$("#selectUsers", page).val(notificationConfig.SendToUserMode).trigger("change");
fillItems($('.monitorUsersList', page), users, 'chkMonitor', 'chkMonitor', notificationConfig.DisabledMonitorUsers);
fillItems($('.sendToUsersList', page), users, 'chkSendTo', 'chkSendTo', notificationConfig.SendToUsers, true);
fillItems($('.servicesList', page), services, 'chkService', 'chkService', notificationConfig.DisabledServices);
$('#chkEnabled', page).checked = notificationConfig.Enabled || false;
$('#selectUsers', page).val(notificationConfig.SendToUserMode).trigger('change');
});
}
function save(page) {
var type = getParameterByName("type");
var type = getParameterByName('type');
var promise1 = ApiClient.getNamedConfiguration(notificationsConfigurationKey);
var promise2 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Types"));
// TODO: Check if this promise is really needed, as it's unused.
var promise2 = ApiClient.getJSON(ApiClient.getUrl('Notifications/Types'));
Promise.all([promise1, promise2]).then(function (responses) {
var notificationOptions = responses[0];
var types = responses[1];
var notificationConfig = notificationOptions.Options.filter(function (n) {
return n.Type == type;
})[0];
@ -73,50 +73,47 @@ define(["jQuery", "emby-checkbox", "fnchecked"], function ($) {
notificationOptions.Options.push(notificationConfig);
}
types.filter(function (n) {
return n.Type == type;
})[0];
notificationConfig.Enabled = $("#chkEnabled", page).checked();
notificationConfig.SendToUserMode = $("#selectUsers", page).val();
notificationConfig.DisabledMonitorUsers = $(".chkMonitor", page).get().filter(function (c) {
notificationConfig.Enabled = $('#chkEnabled', page).checked;
notificationConfig.SendToUserMode = $('#selectUsers', page).val();
notificationConfig.DisabledMonitorUsers = $('.chkMonitor', page).get().filter(function (c) {
return !c.checked;
}).map(function (c) {
return c.getAttribute("data-itemid");
return c.getAttribute('data-itemid');
});
notificationConfig.SendToUsers = $(".chkSendTo", page).get().filter(function (c) {
notificationConfig.SendToUsers = $('.chkSendTo', page).get().filter(function (c) {
return c.checked;
}).map(function (c) {
return c.getAttribute("data-itemid");
return c.getAttribute('data-itemid');
});
notificationConfig.DisabledServices = $(".chkService", page).get().filter(function (c) {
notificationConfig.DisabledServices = $('.chkService', page).get().filter(function (c) {
return !c.checked;
}).map(function (c) {
return c.getAttribute("data-itemid");
return c.getAttribute('data-itemid');
});
ApiClient.updateNamedConfiguration(notificationsConfigurationKey, notificationOptions).then(function (r) {
Dashboard.processServerConfigurationUpdateResult();
Dashboard.navigate("notificationsettings.html");
Dashboard.navigate('notificationsettings.html');
});
});
}
function onSubmit() {
save($(this).parents(".page"));
save($(this).parents('.page'));
return false;
}
var notificationsConfigurationKey = "notifications";
$(document).on("pageinit", "#notificationSettingPage", function () {
var notificationsConfigurationKey = 'notifications';
$(document).on('pageinit', '#notificationSettingPage', function () {
var page = this;
$("#selectUsers", page).on("change", function () {
if ("Custom" == this.value) {
$(".selectCustomUsers", page).show();
$('#selectUsers', page).on('change', function () {
if ('Custom' == this.value) {
$('.selectCustomUsers', page).show();
} else {
$(".selectCustomUsers", page).hide();
$('.selectCustomUsers', page).hide();
}
});
$(".notificationSettingForm").off("submit", onSubmit).on("submit", onSubmit);
}).on("pageshow", "#notificationSettingPage", function () {
$('.notificationSettingForm').off('submit', onSubmit).on('submit', onSubmit);
}).on('pageshow', '#notificationSettingPage', function () {
reload(this);
});
});

View file

@ -1,59 +1,59 @@
define(["loading", "libraryMenu", "globalize", "listViewStyle", "emby-button"], function(loading, libraryMenu, globalize) {
"use strict";
define(['loading', 'libraryMenu', 'globalize', 'listViewStyle', 'emby-button'], function(loading, libraryMenu, globalize) {
'use strict';
function reload(page) {
loading.show();
ApiClient.getJSON(ApiClient.getUrl("Notifications/Types")).then(function(list) {
var html = "";
var lastCategory = "";
ApiClient.getJSON(ApiClient.getUrl('Notifications/Types')).then(function(list) {
var html = '';
var lastCategory = '';
var showHelp = true;
html += list.map(function(notification) {
var itemHtml = "";
var itemHtml = '';
if (notification.Category !== lastCategory) {
lastCategory = notification.Category;
if (lastCategory) {
itemHtml += "</div>";
itemHtml += "</div>";
itemHtml += '</div>';
itemHtml += '</div>';
}
itemHtml += '<div class="verticalSection verticalSection-extrabottompadding">';
itemHtml += '<div class="sectionTitleContainer" style="margin-bottom:1em;">';
itemHtml += '<h2 class="sectionTitle">';
itemHtml += notification.Category;
itemHtml += "</h2>";
itemHtml += '</h2>';
if (showHelp) {
showHelp = false;
itemHtml += '<a is="emby-linkbutton" class="raised button-alt headerHelpButton" target="_blank" href="https://docs.jellyfin.org/general/server/notifications.html">';
itemHtml += globalize.translate("Help");
itemHtml += "</a>";
itemHtml += globalize.translate('Help');
itemHtml += '</a>';
}
itemHtml += "</div>";
itemHtml += '</div>';
itemHtml += '<div class="paperList">';
}
itemHtml += '<a class="listItem listItem-border" is="emby-linkbutton" data-ripple="false" href="notificationsetting.html?type=' + notification.Type + '">';
if (notification.Enabled) {
itemHtml += '<i class="listItemIcon material-icons notifications_active"></i>';
itemHtml += '<span class="listItemIcon material-icons notifications_active"></span>';
} else {
itemHtml += '<i class="listItemIcon material-icons notifications_off" style="background-color:#999;"></i>';
itemHtml += '<span class="listItemIcon material-icons notifications_off" style="background-color:#999;"></span>';
}
itemHtml += '<div class="listItemBody">';
itemHtml += '<div class="listItemBodyText">' + notification.Name + "</div>";
itemHtml += "</div>";
itemHtml += '<button type="button" is="paper-icon-button-light"><i class="material-icons mode_edit"></i></button>';
itemHtml += "</a>";
itemHtml += '<div class="listItemBodyText">' + notification.Name + '</div>';
itemHtml += '</div>';
itemHtml += '<button type="button" is="paper-icon-button-light"><span class="material-icons mode_edit"></span></button>';
itemHtml += '</a>';
return itemHtml;
}).join("");
}).join('');
if (list.length) {
html += "</div>";
html += "</div>";
html += '</div>';
html += '</div>';
}
page.querySelector(".notificationList").innerHTML = html;
page.querySelector('.notificationList').innerHTML = html;
loading.hide();
});
}
return function(view, params) {
view.addEventListener("viewshow", function() {
view.addEventListener('viewshow', function() {
reload(view);
});
};

View file

@ -0,0 +1,48 @@
define(['jQuery', 'loading', 'libraryMenu', 'globalize'], function ($, loading, libraryMenu, globalize) {
'use strict';
function loadPage(page, config) {
$('#txtMinResumePct', page).val(config.MinResumePct);
$('#txtMaxResumePct', page).val(config.MaxResumePct);
$('#txtMinResumeDuration', page).val(config.MinResumeDurationSeconds);
loading.hide();
}
function onSubmit() {
loading.show();
var form = this;
ApiClient.getServerConfiguration().then(function (config) {
config.MinResumePct = $('#txtMinResumePct', form).val();
config.MaxResumePct = $('#txtMaxResumePct', form).val();
config.MinResumeDurationSeconds = $('#txtMinResumeDuration', form).val();
ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult);
});
return false;
}
function getTabs() {
return [{
href: 'encodingsettings.html',
name: globalize.translate('Transcoding')
}, {
href: 'playbackconfiguration.html',
name: globalize.translate('TabResumeSettings')
}, {
href: 'streamingsettings.html',
name: globalize.translate('TabStreaming')
}];
}
$(document).on('pageinit', '#playbackConfigurationPage', function () {
$('.playbackConfigurationForm').off('submit', onSubmit).on('submit', onSubmit);
}).on('pageshow', '#playbackConfigurationPage', function () {
loading.show();
libraryMenu.setTabs('playback', 1, getTabs);
var page = this;
ApiClient.getServerConfiguration().then(function (config) {
loadPage(page, config);
});
});
});

View file

@ -1,43 +1,36 @@
define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "emby-button"], function ($, loading, libraryMenu, globalize, connectionManager) {
"use strict";
define(['jQuery', 'loading', 'libraryMenu', 'globalize', 'connectionManager', 'emby-button'], function ($, loading, libraryMenu, globalize, connectionManager) {
'use strict';
function populateHistory(packageInfo, page) {
var html = "";
var html = '';
var length = Math.min(packageInfo.versions.length, 10);
for (var i = 0; i < length; i++) {
var version = packageInfo.versions[i];
html += '<h2 style="margin:.5em 0;">' + version.versionStr + " (" + version.classification + ")</h2>";
html += '<div style="margin-bottom:1.5em;">' + version.description + "</div>";
html += '<h2 style="margin:.5em 0;">' + version.version + '</h2>';
html += '<div style="margin-bottom:1.5em;">' + version.changelog + '</div>';
}
$("#revisionHistory", page).html(html);
$('#revisionHistory', page).html(html);
}
function populateVersions(packageInfo, page, installedPlugin) {
var html = "";
var html = '';
for (var i = 0; i < packageInfo.versions.length; i++) {
var version = packageInfo.versions[i];
html += '<option value="' + version.versionStr + "|" + version.classification + '">' + version.versionStr + " (" + version.classification + ")</option>";
html += '<option value="' + version.version + '">' + version.version + '</option>';
}
var selectmenu = $("#selectVersion", page).html(html);
var selectmenu = $('#selectVersion', page).html(html);
if (!installedPlugin) {
$("#pCurrentVersion", page).hide().html("");
$('#pCurrentVersion', page).hide().html('');
}
var packageVersion = packageInfo.versions.filter(function (current) {
return "Release" == current.classification;
})[0];
packageVersion = packageVersion || packageInfo.versions.filter(function (current) {
return "Beta" == current.classification;
})[0];
var packageVersion = packageInfo.versions[0];
if (packageVersion) {
var val = packageVersion.versionStr + "|" + packageVersion.classification;
selectmenu.val(val);
selectmenu.val(packageVersion.version);
}
}
@ -45,81 +38,60 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e
var installedPlugin = installedPlugins.filter(function (ip) {
return ip.Name == pkg.name;
})[0];
populateVersions(pkg, page, installedPlugin);
populateHistory(pkg, page);
$(".pluginName", page).html(pkg.name);
if ("Server" == pkg.targetSystem) {
$("#btnInstallDiv", page).removeClass("hide");
$("#nonServerMsg", page).hide();
$("#pSelectVersion", page).removeClass("hide");
$('.pluginName', page).html(pkg.name);
$('#btnInstallDiv', page).removeClass('hide');
$('#pSelectVersion', page).removeClass('hide');
if (pkg.overview) {
$('#overview', page).show().html(pkg.overview);
} else {
$("#btnInstallDiv", page).addClass("hide");
$("#pSelectVersion", page).addClass("hide");
var msg = globalize.translate("MessageInstallPluginFromApp");
$("#nonServerMsg", page).html(msg).show();
$('#overview', page).hide();
}
if (pkg.shortDescription) {
$("#tagline", page).show().html(pkg.shortDescription);
} else {
$("#tagline", page).hide();
}
$("#overview", page).html(pkg.overview || "");
$("#developer", page).html(pkg.owner);
if (pkg.richDescUrl) {
$("#pViewWebsite", page).show();
$("#pViewWebsite a", page).attr("href", pkg.richDescUrl);
} else {
$("#pViewWebsite", page).hide();
}
if (pkg.previewImage || pkg.thumbImage) {
var img = pkg.previewImage ? pkg.previewImage : pkg.thumbImage;
$("#pPreviewImage", page).show().html("<img class='pluginPreviewImg' src='" + img + "' style='max-width: 100%;' />");
} else {
$("#pPreviewImage", page).hide().html("");
}
$('#description', page).html(pkg.description);
$('#developer', page).html(pkg.owner);
if (installedPlugin) {
var currentVersionText = globalize.translate("MessageYouHaveVersionInstalled", "<strong>" + installedPlugin.Version + "</strong>");
$("#pCurrentVersion", page).show().html(currentVersionText);
var currentVersionText = globalize.translate('MessageYouHaveVersionInstalled', '<strong>' + installedPlugin.Version + '</strong>');
$('#pCurrentVersion', page).show().html(currentVersionText);
} else {
$("#pCurrentVersion", page).hide().html("");
$('#pCurrentVersion', page).hide().html('');
}
loading.hide();
}
function alertText(options) {
require(["alert"], function (alert) {
require(['alert'], function (alert) {
alert(options);
});
}
function performInstallation(page, packageName, guid, updateClass, version) {
var developer = $("#developer", page).html().toLowerCase();
function performInstallation(page, name, guid, version) {
var developer = $('#developer', page).html().toLowerCase();
var alertCallback = function () {
loading.show();
page.querySelector("#btnInstall").disabled = true;
ApiClient.installPlugin(packageName, guid, updateClass, version).then(function () {
page.querySelector('#btnInstall').disabled = true;
ApiClient.installPlugin(name, guid, version).then(function () {
loading.hide();
alertText(globalize.translate("PluginInstalledMessage"));
alertText(globalize.translate('PluginInstalledMessage'));
});
};
if (developer !== 'jellyfin') {
loading.hide();
var msg = globalize.translate("MessagePluginInstallDisclaimer");
msg += "<br/>";
msg += "<br/>";
msg += globalize.translate("PleaseConfirmPluginInstallation");
var msg = globalize.translate('MessagePluginInstallDisclaimer');
msg += '<br/>';
msg += '<br/>';
msg += globalize.translate('PleaseConfirmPluginInstallation');
require(["confirm"], function (confirm) {
confirm(msg, globalize.translate("HeaderConfirmPluginInstallation")).then(function () {
require(['confirm'], function (confirm) {
confirm(msg, globalize.translate('HeaderConfirmPluginInstallation')).then(function () {
alertCallback();
}, function () {
console.debug('plugin not installed');
@ -131,33 +103,32 @@ define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "e
}
return function (view, params) {
$(".addPluginForm", view).on("submit", function () {
$('.addPluginForm', view).on('submit', function () {
loading.show();
var page = $(this).parents("#addPluginPage")[0];
var page = $(this).parents('#addPluginPage')[0];
var name = params.name;
var guid = params.guid;
ApiClient.getInstalledPlugins().then(function (plugins) {
var installedPlugin = plugins.filter(function (plugin) {
return plugin.Name == name;
})[0];
var vals = $("#selectVersion", page).val().split("|");
var version = vals[0];
var version = $('#selectVersion', page).val();
if (installedPlugin) {
if (installedPlugin.Version === version) {
loading.hide();
Dashboard.alert({
message: globalize.translate("MessageAlreadyInstalled"),
title: globalize.translate("HeaderPluginInstallation")
message: globalize.translate('MessageAlreadyInstalled'),
title: globalize.translate('HeaderPluginInstallation')
});
}
} else {
performInstallation(page, name, guid, vals[1], version);
performInstallation(page, name, guid, version);
}
});
return false;
});
view.addEventListener("viewshow", function () {
view.addEventListener('viewshow', function () {
var page = this;
loading.show();
var name = params.name;

View file

@ -1,5 +1,5 @@
define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-button", "emby-checkbox", "emby-select"], function (loading, libraryMenu, globalize) {
"use strict";
define(['loading', 'libraryMenu', 'globalize', 'cardStyle', 'emby-button', 'emby-checkbox', 'emby-select'], function (loading, libraryMenu, globalize) {
'use strict';
function reloadList(page) {
loading.show();
@ -7,8 +7,8 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-button", "emby
var promise2 = ApiClient.getInstalledPlugins();
Promise.all([promise1, promise2]).then(function (responses) {
populateList({
catalogElement: page.querySelector("#pluginTiles"),
noItemsElement: page.querySelector("#noPlugins"),
catalogElement: page.querySelector('#pluginTiles'),
noItemsElement: page.querySelector('#noPlugins'),
availablePlugins: responses[0],
installedPlugins: responses[1]
});
@ -16,15 +16,15 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-button", "emby
}
function getHeaderText(category) {
category = category.replace(" ", "");
if ("Channel" === category) {
category = "Channels";
} else if ("Theme" === category) {
category = "Themes";
} else if ("LiveTV" === category) {
category = "HeaderLiveTV";
} else if ("ScreenSaver" === category) {
category = "HeaderScreenSavers";
category = category.replace(' ', '');
if ('Channel' === category) {
category = 'Channels';
} else if ('Theme' === category) {
category = 'Themes';
} else if ('LiveTV' === category) {
category = 'HeaderLiveTV';
} else if ('ScreenSaver' === category) {
category = 'HeaderScreenSavers';
}
return globalize.translate(category);
@ -56,28 +56,28 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-button", "emby
});
var currentCategory = null;
var html = "";
var html = '';
for (var i = 0; i < availablePlugins.length; i++) {
var plugin = availablePlugins[i];
var category = plugin.categoryDisplayName;
if (category != currentCategory) {
if (currentCategory) {
html += "</div>";
html += "</div>";
html += '</div>';
html += '</div>';
}
html += '<div class="verticalSection">';
html += '<h2 class="sectionTitle sectionTitle-cards">' + category + "</h2>";
html += '<h2 class="sectionTitle sectionTitle-cards">' + category + '</h2>';
html += '<div class="itemsContainer vertical-wrap">';
currentCategory = category;
}
html += getPluginHtml(plugin, options, installedPlugins);
}
html += "</div>";
html += "</div>";
html += '</div>';
html += '</div>';
if (!availablePlugins.length && options.noItemsElement) {
options.noItemsElement.classList.remove("hide");
options.noItemsElement.classList.remove('hide');
}
options.catalogElement.innerHTML = html;
@ -85,51 +85,44 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-button", "emby
}
function getPluginHtml(plugin, options, installedPlugins) {
var html = "";
var href = plugin.externalUrl ? plugin.externalUrl : "addplugin.html?name=" + encodeURIComponent(plugin.name) + "&guid=" + plugin.guid;
var html = '';
var href = plugin.externalUrl ? plugin.externalUrl : 'addplugin.html?name=' + encodeURIComponent(plugin.name) + '&guid=' + plugin.guid;
if (options.context) {
href += "&context=" + options.context;
href += '&context=' + options.context;
}
var target = plugin.externalUrl ? ' target="_blank"' : "";
var target = plugin.externalUrl ? ' target="_blank"' : '';
html += "<div class='card backdropCard'>";
html += '<div class="cardBox visualCardBox">';
html += '<div class="cardScalable visualCardBox-cardScalable">';
html += '<div class="cardPadder cardPadder-backdrop"></div>';
html += '<a class="cardContent cardImageContainer" is="emby-linkbutton" href="' + href + '"' + target + ">";
if (plugin.thumbImage) {
html += '<div class="cardImage coveredImage" style="background-image:url(\'' + plugin.thumbImage + "');\">";
html += "</div>";
} else {
html += '<i class="cardImageIcon material-icons">folder</i>';
}
html += "</a>";
html += "</div>";
html += '<a class="cardContent cardImageContainer" is="emby-linkbutton" href="' + href + '"' + target + '>';
html += '<span class="cardImageIcon material-icons folder"></span>';
html += '</a>';
html += '</div>';
html += '<div class="cardFooter">';
html += "<div class='cardText'>";
html += plugin.name;
html += "</div>";
var installedPlugin = plugin.isApp ? null : installedPlugins.filter(function (ip) {
html += '</div>';
var installedPlugin = installedPlugins.filter(function (ip) {
return ip.Id == plugin.guid;
})[0];
html += "<div class='cardText cardText-secondary'>";
html += installedPlugin ? globalize.translate("LabelVersionInstalled", installedPlugin.Version) : "&nbsp;";
html += "</div>";
html += "</div>";
html += "</div>";
return html += "</div>";
html += installedPlugin ? globalize.translate('LabelVersionInstalled', installedPlugin.Version) : '&nbsp;';
html += '</div>';
html += '</div>';
html += '</div>';
return html += '</div>';
}
function getTabs() {
return [{
href: "installedplugins.html",
name: globalize.translate("TabMyPlugins")
href: 'installedplugins.html',
name: globalize.translate('TabMyPlugins')
}, {
href: "availableplugins.html",
name: globalize.translate("TabCatalog")
href: 'availableplugins.html',
name: globalize.translate('TabCatalog')
}];
}
@ -138,8 +131,8 @@ define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-button", "emby
};
return function (view, params) {
view.addEventListener("viewshow", function () {
libraryMenu.setTabs("plugins", 1, getTabs);
view.addEventListener('viewshow', function () {
libraryMenu.setTabs('plugins', 1, getTabs);
reloadList(this);
});
};

View file

@ -1,15 +1,15 @@
define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button"], function (loading, libraryMenu, dom, globalize) {
"use strict";
define(['loading', 'libraryMenu', 'dom', 'globalize', 'cardStyle', 'emby-button'], function (loading, libraryMenu, dom, globalize) {
'use strict';
function deletePlugin(page, uniqueid, name) {
var msg = globalize.translate("UninstallPluginConfirmation", name);
var msg = globalize.translate('UninstallPluginConfirmation', name);
require(["confirm"], function (confirm) {
require(['confirm'], function (confirm) {
confirm({
title: globalize.translate("UninstallPluginHeader"),
title: globalize.translate('UninstallPluginHeader'),
text: msg,
primary: "delete",
confirmText: globalize.translate("UninstallPluginHeader")
primary: 'delete',
confirmText: globalize.translate('UninstallPluginHeader')
}).then(function () {
loading.show();
ApiClient.uninstallPlugin(uniqueid).then(function () {
@ -21,13 +21,13 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button"
function showNoConfigurationMessage() {
Dashboard.alert({
message: globalize.translate("NoPluginConfigurationMessage")
message: globalize.translate('NoPluginConfigurationMessage')
});
}
function showConnectMessage() {
Dashboard.alert({
message: globalize.translate("MessagePluginConfigurationRequiresLocalAccess")
message: globalize.translate('MessagePluginConfigurationRequiresLocalAccess')
});
}
@ -36,40 +36,33 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button"
return pluginConfigurationPage.PluginId == plugin.Id;
})[0];
var configPageUrl = configPage ? Dashboard.getConfigurationPageUrl(configPage.Name) : null;
var html = "";
var html = '';
html += "<div data-id='" + plugin.Id + "' data-name='" + plugin.Name + "' class='card backdropCard'>";
html += '<div class="cardBox visualCardBox">';
html += '<div class="cardScalable">';
html += '<div class="cardPadder cardPadder-backdrop"></div>';
html += configPageUrl ? '<a class="cardContent cardImageContainer" is="emby-linkbutton" href="' + configPageUrl + '">' : '<div class="cardContent noConfigPluginCard noHoverEffect cardImageContainer">';
if (plugin.ImageUrl) {
html += '<div class="cardImage coveredImage" style="background-image:url(\'' + plugin.ImageUrl + "');\">";
html += "</div>";
} else {
html += '<i class="cardImageIcon material-icons">folder</i>';
}
html += configPageUrl ? "</a>" : "</div>";
html += "</div>";
html += '<span class="cardImageIcon material-icons folder"></span>';
html += configPageUrl ? '</a>' : '</div>';
html += '</div>';
html += '<div class="cardFooter">';
html += '<div style="text-align:right; float:right;padding-top:5px;">';
html += '<button type="button" is="paper-icon-button-light" class="btnCardMenu autoSize"><i class="material-icons more_horiz"></i></button>';
html += "</div>";
html += '<button type="button" is="paper-icon-button-light" class="btnCardMenu autoSize"><span class="material-icons more_vert"></span></button>';
html += '</div>';
html += "<div class='cardText'>";
html += configPage ? configPage.DisplayName || plugin.Name : plugin.Name;
html += "</div>";
html += configPage && configPage.DisplayName ? configPage.DisplayName : plugin.Name;
html += '</div>';
html += "<div class='cardText cardText-secondary'>";
html += plugin.Version;
html += "</div>";
html += "</div>";
html += "</div>";
html += "</div>";
html += '</div>';
html += '</div>';
html += '</div>';
html += '</div>';
return html;
}
function renderPlugins(page, plugins) {
ApiClient.getJSON(ApiClient.getUrl("web/configurationpages") + "?pageType=PluginConfiguration").then(function (configPages) {
ApiClient.getJSON(ApiClient.getUrl('web/configurationpages') + '?pageType=PluginConfiguration').then(function (configPages) {
populateList(page, plugins, configPages);
});
}
@ -85,22 +78,22 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button"
var html = plugins.map(function (p) {
return getPluginCardHtml(p, pluginConfigurationPages);
}).join("");
}).join('');
var installedPluginsElement = page.querySelector(".installedPlugins");
installedPluginsElement.removeEventListener("click", onInstalledPluginsClick);
installedPluginsElement.addEventListener("click", onInstalledPluginsClick);
var installedPluginsElement = page.querySelector('.installedPlugins');
installedPluginsElement.removeEventListener('click', onInstalledPluginsClick);
installedPluginsElement.addEventListener('click', onInstalledPluginsClick);
if (plugins.length) {
installedPluginsElement.classList.add("itemsContainer");
installedPluginsElement.classList.add("vertical-wrap");
installedPluginsElement.classList.add('itemsContainer');
installedPluginsElement.classList.add('vertical-wrap');
} else {
html += '<div class="centerMessage">';
html += "<h1>" + globalize.translate("MessageNoPluginsInstalled") + "</h1>";
html += '<h1>' + globalize.translate('MessageNoPluginsInstalled') + '</h1>';
html += '<p><a is="emby-linkbutton" class="button-link" href="availableplugins.html">';
html += globalize.translate("BrowsePluginCatalogMessage");
html += "</a></p>";
html += "</div>";
html += globalize.translate('BrowsePluginCatalogMessage');
html += '</a></p>';
html += '</div>';
}
installedPluginsElement.innerHTML = html;
@ -108,36 +101,36 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button"
}
function showPluginMenu(page, elem) {
var card = dom.parentWithClass(elem, "card");
var id = card.getAttribute("data-id");
var name = card.getAttribute("data-name");
var configHref = card.querySelector(".cardContent").getAttribute("href");
var card = dom.parentWithClass(elem, 'card');
var id = card.getAttribute('data-id');
var name = card.getAttribute('data-name');
var configHref = card.querySelector('.cardContent').getAttribute('href');
var menuItems = [];
if (configHref) {
menuItems.push({
name: globalize.translate("ButtonSettings"),
id: "open",
icon: "mode_edit"
name: globalize.translate('ButtonSettings'),
id: 'open',
icon: 'mode_edit'
});
}
menuItems.push({
name: globalize.translate("ButtonUninstall"),
id: "delete",
icon: "delete"
name: globalize.translate('ButtonUninstall'),
id: 'delete',
icon: 'delete'
});
require(["actionsheet"], function (actionsheet) {
require(['actionsheet'], function (actionsheet) {
actionsheet.show({
items: menuItems,
positionTo: elem,
callback: function (resultId) {
switch (resultId) {
case "open":
case 'open':
Dashboard.navigate(configHref);
break;
case "delete":
case 'delete':
deletePlugin(page, id, name);
break;
}
@ -155,29 +148,29 @@ define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-button"
function getTabs() {
return [{
href: "installedplugins.html",
name: globalize.translate("TabMyPlugins")
href: 'installedplugins.html',
name: globalize.translate('TabMyPlugins')
}, {
href: "availableplugins.html",
name: globalize.translate("TabCatalog")
href: 'availableplugins.html',
name: globalize.translate('TabCatalog')
}];
}
function onInstalledPluginsClick(e) {
if (dom.parentWithClass(e.target, "noConfigPluginCard")) {
if (dom.parentWithClass(e.target, 'noConfigPluginCard')) {
showNoConfigurationMessage();
} else if (dom.parentWithClass(e.target, "connectModePluginCard")) {
} else if (dom.parentWithClass(e.target, 'connectModePluginCard')) {
showConnectMessage();
} else {
var btnCardMenu = dom.parentWithClass(e.target, "btnCardMenu");
var btnCardMenu = dom.parentWithClass(e.target, 'btnCardMenu');
if (btnCardMenu) {
showPluginMenu(dom.parentWithClass(btnCardMenu, "page"), btnCardMenu);
showPluginMenu(dom.parentWithClass(btnCardMenu, 'page'), btnCardMenu);
}
}
}
pageIdOn("pageshow", "pluginsPage", function () {
libraryMenu.setTabs("plugins", 0, getTabs);
pageIdOn('pageshow', 'pluginsPage', function () {
libraryMenu.setTabs('plugins', 0, getTabs);
reloadList(this);
});

View file

@ -1,5 +1,5 @@
define(["jQuery", "loading", "datetime", "dom", "globalize", "emby-input", "emby-button", "emby-select"], function ($, loading, datetime, dom, globalize) {
"use strict";
define(['jQuery', 'loading', 'datetime', 'dom', 'globalize', 'emby-input', 'emby-button', 'emby-select'], function ($, loading, datetime, dom, globalize) {
'use strict';
function fillTimeOfDay(select) {
@ -14,7 +14,7 @@ define(["jQuery", "loading", "datetime", "dom", "globalize", "emby-input", "emby
select.innerHTML = options.map(function (o) {
return '<option value="' + o.value + '">' + o.name + '</option>';
}).join("");
}).join('');
}
Array.prototype.remove = function (from, to) {
@ -26,92 +26,92 @@ define(["jQuery", "loading", "datetime", "dom", "globalize", "emby-input", "emby
var ScheduledTaskPage = {
refreshScheduledTask: function (view) {
loading.show();
var id = getParameterByName("id");
var id = getParameterByName('id');
ApiClient.getScheduledTask(id).then(function (task) {
ScheduledTaskPage.loadScheduledTask(view, task);
});
},
loadScheduledTask: function (view, task) {
$(".taskName", view).html(task.Name);
$("#pTaskDescription", view).html(task.Description);
$('.taskName', view).html(task.Name);
$('#pTaskDescription', view).html(task.Description);
require(["listViewStyle"], function () {
require(['listViewStyle'], function () {
ScheduledTaskPage.loadTaskTriggers(view, task);
});
loading.hide();
},
loadTaskTriggers: function (context, task) {
var html = "";
var html = '';
html += '<div class="paperList">';
for (var i = 0, length = task.Triggers.length; i < length; i++) {
var trigger = task.Triggers[i];
html += '<div class="listItem listItem-border">';
html += '<i class="material-icons listItemIcon">schedule</i>';
html += '<span class="material-icons listItemIcon schedule"></span>';
if (trigger.MaxRuntimeMs) {
html += '<div class="listItemBody two-line">';
} else {
html += '<div class="listItemBody">';
}
html += "<div class='listItemBodyText'>" + ScheduledTaskPage.getTriggerFriendlyName(trigger) + "</div>";
html += "<div class='listItemBodyText'>" + ScheduledTaskPage.getTriggerFriendlyName(trigger) + '</div>';
if (trigger.MaxRuntimeMs) {
html += '<div class="listItemBodyText secondary">';
var hours = trigger.MaxRuntimeTicks / 36e9;
if (hours == 1) {
html += globalize.translate("ValueTimeLimitSingleHour");
html += globalize.translate('ValueTimeLimitSingleHour');
} else {
html += globalize.translate("ValueTimeLimitMultiHour", hours);
html += globalize.translate('ValueTimeLimitMultiHour', hours);
}
html += "</div>";
html += '</div>';
}
html += "</div>";
html += '<button class="btnDeleteTrigger" data-index="' + i + '" type="button" is="paper-icon-button-light" title="' + globalize.translate("ButtonDelete") + '"><i class="material-icons">delete</i></button>';
html += "</div>";
html += '</div>';
html += '<button class="btnDeleteTrigger" data-index="' + i + '" type="button" is="paper-icon-button-light" title="' + globalize.translate('ButtonDelete') + '"><span class="material-icons delete"></span></button>';
html += '</div>';
}
html += "</div>";
context.querySelector(".taskTriggers").innerHTML = html;
html += '</div>';
context.querySelector('.taskTriggers').innerHTML = html;
},
// TODO: Replace this mess with date-fns and remove datetime completely
getTriggerFriendlyName: function (trigger) {
if ("DailyTrigger" == trigger.Type) {
return globalize.translate("DailyAt", ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks));
if ('DailyTrigger' == trigger.Type) {
return globalize.translate('DailyAt', ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks));
}
if ("WeeklyTrigger" == trigger.Type) {
if ('WeeklyTrigger' == trigger.Type) {
// TODO: The day of week isn't localised as well
return globalize.translate("WeeklyAt", trigger.DayOfWeek, ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks));
return globalize.translate('WeeklyAt', trigger.DayOfWeek, ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks));
}
if ("SystemEventTrigger" == trigger.Type && "WakeFromSleep" == trigger.SystemEvent) {
return globalize.translate("OnWakeFromSleep");
if ('SystemEventTrigger' == trigger.Type && 'WakeFromSleep' == trigger.SystemEvent) {
return globalize.translate('OnWakeFromSleep');
}
if (trigger.Type == "IntervalTrigger") {
if (trigger.Type == 'IntervalTrigger') {
var hours = trigger.IntervalTicks / 36e9;
if (hours == 0.25) {
return globalize.translate("EveryXMinutes", "15");
return globalize.translate('EveryXMinutes', '15');
}
if (hours == 0.5) {
return globalize.translate("EveryXMinutes", "30");
return globalize.translate('EveryXMinutes', '30');
}
if (hours == 0.75) {
return globalize.translate("EveryXMinutes", "45");
return globalize.translate('EveryXMinutes', '45');
}
if (hours == 1) {
return globalize.translate("EveryHour");
return globalize.translate('EveryHour');
}
return globalize.translate("EveryXHours", hours);
return globalize.translate('EveryXHours', hours);
}
if (trigger.Type == "StartupTrigger") {
return globalize.translate("OnApplicationStartup");
if (trigger.Type == 'StartupTrigger') {
return globalize.translate('OnApplicationStartup');
}
return trigger.Type;
@ -124,20 +124,20 @@ define(["jQuery", "loading", "datetime", "dom", "globalize", "emby-input", "emby
return datetime.getDisplayTime(now);
},
showAddTriggerPopup: function (view) {
$("#selectTriggerType", view).val("DailyTrigger");
view.querySelector("#selectTriggerType").dispatchEvent(new CustomEvent("change", {}));
$("#popupAddTrigger", view).removeClass("hide");
$('#selectTriggerType', view).val('DailyTrigger');
view.querySelector('#selectTriggerType').dispatchEvent(new CustomEvent('change', {}));
$('#popupAddTrigger', view).removeClass('hide');
},
confirmDeleteTrigger: function (view, index) {
require(["confirm"], function (confirm) {
confirm(globalize.translate("MessageDeleteTaskTrigger"), globalize.translate("HeaderDeleteTaskTrigger")).then(function () {
require(['confirm'], function (confirm) {
confirm(globalize.translate('MessageDeleteTaskTrigger'), globalize.translate('HeaderDeleteTaskTrigger')).then(function () {
ScheduledTaskPage.deleteTrigger(view, index);
});
});
},
deleteTrigger: function (view, index) {
loading.show();
var id = getParameterByName("id");
var id = getParameterByName('id');
ApiClient.getScheduledTask(id).then(function (task) {
task.Triggers.remove(index);
ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).then(function () {
@ -146,55 +146,55 @@ define(["jQuery", "loading", "datetime", "dom", "globalize", "emby-input", "emby
});
},
refreshTriggerFields: function (page, triggerType) {
if (triggerType == "DailyTrigger") {
$("#fldTimeOfDay", page).show();
$("#fldDayOfWeek", page).hide();
$("#fldSelectSystemEvent", page).hide();
$("#fldSelectInterval", page).hide();
$("#selectTimeOfDay", page).attr("required", "required");
} else if (triggerType == "WeeklyTrigger") {
$("#fldTimeOfDay", page).show();
$("#fldDayOfWeek", page).show();
$("#fldSelectSystemEvent", page).hide();
$("#fldSelectInterval", page).hide();
$("#selectTimeOfDay", page).attr("required", "required");
} else if (triggerType == "SystemEventTrigger") {
$("#fldTimeOfDay", page).hide();
$("#fldDayOfWeek", page).hide();
$("#fldSelectSystemEvent", page).show();
$("#fldSelectInterval", page).hide();
$("#selectTimeOfDay", page).removeAttr("required");
} else if (triggerType == "IntervalTrigger") {
$("#fldTimeOfDay", page).hide();
$("#fldDayOfWeek", page).hide();
$("#fldSelectSystemEvent", page).hide();
$("#fldSelectInterval", page).show();
$("#selectTimeOfDay", page).removeAttr("required");
} else if (triggerType == "StartupTrigger") {
$("#fldTimeOfDay", page).hide();
$("#fldDayOfWeek", page).hide();
$("#fldSelectSystemEvent", page).hide();
$("#fldSelectInterval", page).hide();
$("#selectTimeOfDay", page).removeAttr("required");
if (triggerType == 'DailyTrigger') {
$('#fldTimeOfDay', page).show();
$('#fldDayOfWeek', page).hide();
$('#fldSelectSystemEvent', page).hide();
$('#fldSelectInterval', page).hide();
$('#selectTimeOfDay', page).attr('required', 'required');
} else if (triggerType == 'WeeklyTrigger') {
$('#fldTimeOfDay', page).show();
$('#fldDayOfWeek', page).show();
$('#fldSelectSystemEvent', page).hide();
$('#fldSelectInterval', page).hide();
$('#selectTimeOfDay', page).attr('required', 'required');
} else if (triggerType == 'SystemEventTrigger') {
$('#fldTimeOfDay', page).hide();
$('#fldDayOfWeek', page).hide();
$('#fldSelectSystemEvent', page).show();
$('#fldSelectInterval', page).hide();
$('#selectTimeOfDay', page).removeAttr('required');
} else if (triggerType == 'IntervalTrigger') {
$('#fldTimeOfDay', page).hide();
$('#fldDayOfWeek', page).hide();
$('#fldSelectSystemEvent', page).hide();
$('#fldSelectInterval', page).show();
$('#selectTimeOfDay', page).removeAttr('required');
} else if (triggerType == 'StartupTrigger') {
$('#fldTimeOfDay', page).hide();
$('#fldDayOfWeek', page).hide();
$('#fldSelectSystemEvent', page).hide();
$('#fldSelectInterval', page).hide();
$('#selectTimeOfDay', page).removeAttr('required');
}
},
getTriggerToAdd: function (page) {
var trigger = {
Type: $("#selectTriggerType", page).val()
Type: $('#selectTriggerType', page).val()
};
if (trigger.Type == "DailyTrigger") {
trigger.TimeOfDayTicks = $("#selectTimeOfDay", page).val();
} else if (trigger.Type == "WeeklyTrigger") {
trigger.DayOfWeek = $("#selectDayOfWeek", page).val();
trigger.TimeOfDayTicks = $("#selectTimeOfDay", page).val();
} else if (trigger.Type == "SystemEventTrigger") {
trigger.SystemEvent = $("#selectSystemEvent", page).val();
} else if (trigger.Type == "IntervalTrigger") {
trigger.IntervalTicks = $("#selectInterval", page).val();
if (trigger.Type == 'DailyTrigger') {
trigger.TimeOfDayTicks = $('#selectTimeOfDay', page).val();
} else if (trigger.Type == 'WeeklyTrigger') {
trigger.DayOfWeek = $('#selectDayOfWeek', page).val();
trigger.TimeOfDayTicks = $('#selectTimeOfDay', page).val();
} else if (trigger.Type == 'SystemEventTrigger') {
trigger.SystemEvent = $('#selectSystemEvent', page).val();
} else if (trigger.Type == 'IntervalTrigger') {
trigger.IntervalTicks = $('#selectInterval', page).val();
}
var timeLimit = $("#txtTimeLimit", page).val() || "0";
var timeLimit = $('#txtTimeLimit', page).val() || '0';
timeLimit = parseFloat(timeLimit) * 3600000;
trigger.MaxRuntimeMs = timeLimit || null;
@ -205,34 +205,34 @@ define(["jQuery", "loading", "datetime", "dom", "globalize", "emby-input", "emby
return function (view, params) {
function onSubmit(e) {
loading.show();
var id = getParameterByName("id");
var id = getParameterByName('id');
ApiClient.getScheduledTask(id).then(function (task) {
task.Triggers.push(ScheduledTaskPage.getTriggerToAdd(view));
ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).then(function () {
$("#popupAddTrigger").addClass("hide");
$('#popupAddTrigger').addClass('hide');
ScheduledTaskPage.refreshScheduledTask(view);
});
});
e.preventDefault();
}
view.querySelector(".addTriggerForm").addEventListener("submit", onSubmit);
fillTimeOfDay(view.querySelector("#selectTimeOfDay"));
$(view.querySelector("#popupAddTrigger").parentNode).trigger("create");
view.querySelector(".selectTriggerType").addEventListener("change", function () {
view.querySelector('.addTriggerForm').addEventListener('submit', onSubmit);
fillTimeOfDay(view.querySelector('#selectTimeOfDay'));
$(view.querySelector('#popupAddTrigger').parentNode).trigger('create');
view.querySelector('.selectTriggerType').addEventListener('change', function () {
ScheduledTaskPage.refreshTriggerFields(view, this.value);
});
view.querySelector(".btnAddTrigger").addEventListener("click", function () {
view.querySelector('.btnAddTrigger').addEventListener('click', function () {
ScheduledTaskPage.showAddTriggerPopup(view);
});
view.addEventListener("click", function (e) {
var btnDeleteTrigger = dom.parentWithClass(e.target, "btnDeleteTrigger");
view.addEventListener('click', function (e) {
var btnDeleteTrigger = dom.parentWithClass(e.target, 'btnDeleteTrigger');
if (btnDeleteTrigger) {
ScheduledTaskPage.confirmDeleteTrigger(view, parseInt(btnDeleteTrigger.getAttribute("data-index")));
ScheduledTaskPage.confirmDeleteTrigger(view, parseInt(btnDeleteTrigger.getAttribute('data-index')));
}
});
view.addEventListener("viewshow", function () {
view.addEventListener('viewshow', function () {
ScheduledTaskPage.refreshScheduledTask(view);
});
};

View file

@ -1,5 +1,5 @@
define(["jQuery", "loading", "events", "globalize", "serverNotifications", "date-fns", "dfnshelper", "listViewStyle", "emby-button"], function ($, loading, events, globalize, serverNotifications, datefns, dfnshelper) {
"use strict";
define(['jQuery', 'loading', 'events', 'globalize', 'serverNotifications', 'date-fns', 'dfnshelper', 'listViewStyle', 'emby-button'], function ($, loading, events, globalize, serverNotifications, datefns, dfnshelper) {
'use strict';
function reloadList(page) {
ApiClient.getScheduledTasks({
@ -12,114 +12,114 @@ define(["jQuery", "loading", "events", "globalize", "serverNotifications", "date
function populateList(page, tasks) {
tasks = tasks.sort(function(a, b) {
a = a.Category + " " + a.Name;
b = b.Category + " " + b.Name;
a = a.Category + ' ' + a.Name;
b = b.Category + ' ' + b.Name;
return a == b ? 0 : a < b ? -1 : 1;
});
var currentCategory;
var html = "";
var html = '';
for (var i = 0; i < tasks.length; i++) {
var task = tasks[i];
if (task.Category != currentCategory) {
currentCategory = task.Category;
if (currentCategory) {
html += "</div>";
html += "</div>";
html += '</div>';
html += '</div>';
}
html += '<div class="verticalSection verticalSection-extrabottompadding">';
html += '<div class="sectionTitleContainer" style="margin-bottom:1em;">';
html += '<h2 class="sectionTitle">';
html += currentCategory;
html += "</h2>";
html += '</h2>';
if (i === 0) {
html += '<a is="emby-linkbutton" class="raised button-alt headerHelpButton" target="_blank" href="https://docs.jellyfin.org/general/server/tasks.html">' + globalize.translate("Help") + "</a>";
html += '<a is="emby-linkbutton" class="raised button-alt headerHelpButton" target="_blank" href="https://docs.jellyfin.org/general/server/tasks.html">' + globalize.translate('Help') + '</a>';
}
html += "</div>";
html += '</div>';
html += '<div class="paperList">';
}
html += '<div class="listItem listItem-border scheduledTaskPaperIconItem" data-status="' + task.State + '">';
html += "<a is='emby-linkbutton' style='margin:0;padding:0;' class='clearLink listItemIconContainer' href='scheduledtask.html?id=" + task.Id + "'>";
html += '<i class="material-icons listItemIcon">schedule</i>';
html += "</a>";
html += '<span class="material-icons listItemIcon schedule"></span>';
html += '</a>';
html += '<div class="listItemBody two-line">';
html += "<a class='clearLink' style='margin:0;padding:0;display:block;text-align:left;' is='emby-linkbutton' href='scheduledtask.html?id=" + task.Id + "'>";
html += "<h3 class='listItemBodyText'>" + task.Name + "</h3>";
html += "<div class='secondary listItemBodyText' id='taskProgress" + task.Id + "'>" + getTaskProgressHtml(task) + "</div>";
html += "</a>";
html += "</div>";
if (task.State === "Running") {
html += '<button type="button" is="paper-icon-button-light" id="btnTask' + task.Id + '" class="btnStopTask" data-taskid="' + task.Id + '" title="' + globalize.translate("ButtonStop") + '"><i class="material-icons stop"></i></button>';
} else if (task.State === "Idle") {
html += '<button type="button" is="paper-icon-button-light" id="btnTask' + task.Id + '" class="btnStartTask" data-taskid="' + task.Id + '" title="' + globalize.translate("ButtonStart") + '"><i class="material-icons play_arrow"></i></button>';
html += "<h3 class='listItemBodyText'>" + task.Name + '</h3>';
html += "<div class='secondary listItemBodyText' id='taskProgress" + task.Id + "'>" + getTaskProgressHtml(task) + '</div>';
html += '</a>';
html += '</div>';
if (task.State === 'Running') {
html += '<button type="button" is="paper-icon-button-light" id="btnTask' + task.Id + '" class="btnStopTask" data-taskid="' + task.Id + '" title="' + globalize.translate('ButtonStop') + '"><span class="material-icons stop"></span></button>';
} else if (task.State === 'Idle') {
html += '<button type="button" is="paper-icon-button-light" id="btnTask' + task.Id + '" class="btnStartTask" data-taskid="' + task.Id + '" title="' + globalize.translate('ButtonStart') + '"><span class="material-icons play_arrow"></span></button>';
}
html += "</div>";
html += '</div>';
}
if (tasks.length) {
html += "</div>";
html += "</div>";
html += '</div>';
html += '</div>';
}
page.querySelector(".divScheduledTasks").innerHTML = html;
page.querySelector('.divScheduledTasks').innerHTML = html;
}
function getTaskProgressHtml(task) {
var html = "";
if (task.State === "Idle") {
var html = '';
if (task.State === 'Idle') {
if (task.LastExecutionResult) {
var endtime = Date.parse(task.LastExecutionResult.EndTimeUtc);
var starttime = Date.parse(task.LastExecutionResult.StartTimeUtc);
html += globalize.translate("LabelScheduledTaskLastRan", datefns.formatDistanceToNow(endtime, dfnshelper.localeWithSuffix),
html += globalize.translate('LabelScheduledTaskLastRan', datefns.formatDistanceToNow(endtime, dfnshelper.localeWithSuffix),
datefns.formatDistance(starttime, endtime, { locale: dfnshelper.getLocale() }));
if (task.LastExecutionResult.Status === "Failed") {
html += " <span style='color:#FF0000;'>(" + globalize.translate("LabelFailed") + ")</span>";
} else if (task.LastExecutionResult.Status === "Cancelled") {
html += " <span style='color:#0026FF;'>(" + globalize.translate("LabelCancelled") + ")</span>";
} else if (task.LastExecutionResult.Status === "Aborted") {
html += " <span style='color:#FF0000;'>" + globalize.translate("LabelAbortedByServerShutdown") + "</span>";
if (task.LastExecutionResult.Status === 'Failed') {
html += " <span style='color:#FF0000;'>(" + globalize.translate('LabelFailed') + ')</span>';
} else if (task.LastExecutionResult.Status === 'Cancelled') {
html += " <span style='color:#0026FF;'>(" + globalize.translate('LabelCancelled') + ')</span>';
} else if (task.LastExecutionResult.Status === 'Aborted') {
html += " <span style='color:#FF0000;'>" + globalize.translate('LabelAbortedByServerShutdown') + '</span>';
}
}
} else if (task.State === "Running") {
} else if (task.State === 'Running') {
var progress = (task.CurrentProgressPercentage || 0).toFixed(1);
html += '<div style="display:flex;align-items:center;">';
html += '<div class="taskProgressOuter" title="' + progress + '%" style="flex-grow:1;">';
html += '<div class="taskProgressInner" style="width:' + progress + '%;">';
html += "</div>";
html += "</div>";
html += "<span style='color:#00a4dc;margin-left:5px;'>" + progress + "%</span>";
html += "</div>";
html += '</div>';
html += '</div>';
html += "<span style='color:#00a4dc;margin-left:5px;'>" + progress + '%</span>';
html += '</div>';
} else {
html += "<span style='color:#FF0000;'>" + globalize.translate("LabelStopping") + "</span>";
html += "<span style='color:#FF0000;'>" + globalize.translate('LabelStopping') + '</span>';
}
return html;
}
function setTaskButtonIcon(button, icon) {
var inner = button.querySelector("i");
inner.classList.remove("stop", "play_arrow");
var inner = button.querySelector('.material-icons');
inner.classList.remove('stop', 'play_arrow');
inner.classList.add(icon);
}
function updateTaskButton(elem, state) {
if (state === "Running") {
elem.classList.remove("btnStartTask");
elem.classList.add("btnStopTask");
setTaskButtonIcon(elem, "stop");
elem.title = globalize.translate("ButtonStop");
} else if (state === "Idle") {
elem.classList.add("btnStartTask");
elem.classList.remove("btnStopTask");
setTaskButtonIcon(elem, "play_arrow");
elem.title = globalize.translate("ButtonStart");
if (state === 'Running') {
elem.classList.remove('btnStartTask');
elem.classList.add('btnStopTask');
setTaskButtonIcon(elem, 'stop');
elem.title = globalize.translate('ButtonStop');
} else if (state === 'Idle') {
elem.classList.add('btnStartTask');
elem.classList.remove('btnStopTask');
setTaskButtonIcon(elem, 'play_arrow');
elem.title = globalize.translate('ButtonStart');
}
$(elem).parents(".listItem")[0].setAttribute("data-status", state);
$(elem).parents('.listItem')[0].setAttribute('data-status', state);
}
return function(view, params) {
function updateTasks(tasks) {
for (var i = 0; i < tasks.length; i++) {
var task = tasks[i];
view.querySelector("#taskProgress" + task.Id).innerHTML = getTaskProgressHtml(task);
updateTaskButton(view.querySelector("#btnTask" + task.Id), task.State);
view.querySelector('#taskProgress' + task.Id).innerHTML = getTaskProgressHtml(task);
updateTaskButton(view.querySelector('#btnTask' + task.Id), task.State);
}
}
@ -136,47 +136,47 @@ define(["jQuery", "loading", "events", "globalize", "serverNotifications", "date
}
function startInterval() {
ApiClient.sendMessage("ScheduledTasksInfoStart", "1000,1000");
ApiClient.sendMessage('ScheduledTasksInfoStart', '1000,1000');
pollInterval && clearInterval(pollInterval);
pollInterval = setInterval(onPollIntervalFired, 1e4);
}
function stopInterval() {
ApiClient.sendMessage("ScheduledTasksInfoStop");
ApiClient.sendMessage('ScheduledTasksInfoStop');
pollInterval && clearInterval(pollInterval);
}
var pollInterval;
var serverId = ApiClient.serverId();
$(".divScheduledTasks", view).on("click", ".btnStartTask", function() {
$('.divScheduledTasks', view).on('click', '.btnStartTask', function() {
var button = this;
var id = button.getAttribute("data-taskid");
var id = button.getAttribute('data-taskid');
ApiClient.startScheduledTask(id).then(function() {
updateTaskButton(button, "Running");
updateTaskButton(button, 'Running');
reloadList(view);
});
});
$(".divScheduledTasks", view).on("click", ".btnStopTask", function() {
$('.divScheduledTasks', view).on('click', '.btnStopTask', function() {
var button = this;
var id = button.getAttribute("data-taskid");
var id = button.getAttribute('data-taskid');
ApiClient.stopScheduledTask(id).then(function() {
updateTaskButton(button, "");
updateTaskButton(button, '');
reloadList(view);
});
});
view.addEventListener("viewbeforehide", function() {
events.off(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate);
view.addEventListener('viewbeforehide', function() {
events.off(serverNotifications, 'ScheduledTasksInfo', onScheduledTasksUpdate);
stopInterval();
});
view.addEventListener("viewshow", function() {
view.addEventListener('viewshow', function() {
loading.show();
startInterval();
reloadList(view);
events.on(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate);
events.on(serverNotifications, 'ScheduledTasksInfo', onScheduledTasksUpdate);
});
};
});

View file

@ -0,0 +1,31 @@
define(['components/activitylog', 'globalize'], function (ActivityLog, globalize) {
'use strict';
return function (view, params) {
var activityLog;
if (params.useractivity !== 'false') {
view.querySelector('.activityItems').setAttribute('data-useractivity', 'true');
view.querySelector('.sectionTitle').innerHTML = globalize.translate('HeaderActivity');
} else {
view.querySelector('.activityItems').setAttribute('data-useractivity', 'false');
view.querySelector('.sectionTitle').innerHTML = globalize.translate('Alerts');
}
view.addEventListener('viewshow', function () {
if (!activityLog) {
activityLog = new ActivityLog({
serverId: ApiClient.serverId(),
element: view.querySelector('.activityItems')
});
}
});
view.addEventListener('viewdestroy', function () {
if (activityLog) {
activityLog.destroy();
}
activityLog = null;
});
};
});

View file

@ -0,0 +1,43 @@
define(['jQuery', 'libraryMenu', 'loading', 'globalize'], function ($, libraryMenu, loading, globalize) {
'use strict';
function loadPage(page, config) {
$('#txtRemoteClientBitrateLimit', page).val(config.RemoteClientBitrateLimit / 1e6 || '');
loading.hide();
}
function onSubmit() {
loading.show();
var form = this;
ApiClient.getServerConfiguration().then(function (config) {
config.RemoteClientBitrateLimit = parseInt(1e6 * parseFloat($('#txtRemoteClientBitrateLimit', form).val() || '0'));
ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult);
});
return false;
}
function getTabs() {
return [{
href: 'encodingsettings.html',
name: globalize.translate('Transcoding')
}, {
href: 'playbackconfiguration.html',
name: globalize.translate('TabResumeSettings')
}, {
href: 'streamingsettings.html',
name: globalize.translate('TabStreaming')
}];
}
$(document).on('pageinit', '#streamingSettingsPage', function () {
$('.streamingSettingsForm').off('submit', onSubmit).on('submit', onSubmit);
}).on('pageshow', '#streamingSettingsPage', function () {
loading.show();
libraryMenu.setTabs('playback', 2, getTabs);
var page = this;
ApiClient.getServerConfiguration().then(function (config) {
loadPage(page, config);
});
});
});

View file

@ -0,0 +1,200 @@
define(['jQuery', 'loading', 'libraryMenu', 'globalize'], function ($, loading, libraryMenu, globalize) {
'use strict';
function loadDeleteFolders(page, user, mediaFolders) {
ApiClient.getJSON(ApiClient.getUrl('Channels', {
SupportsMediaDeletion: true
})).then(function (channelsResult) {
var i;
var length;
var folder;
var isChecked;
var checkedAttribute;
var html = '';
for (i = 0, length = mediaFolders.length; i < length; i++) {
folder = mediaFolders[i];
isChecked = user.Policy.EnableContentDeletion || -1 != user.Policy.EnableContentDeletionFromFolders.indexOf(folder.Id);
checkedAttribute = isChecked ? ' checked="checked"' : '';
html += '<label><input type="checkbox" is="emby-checkbox" class="chkFolder" data-id="' + folder.Id + '" ' + checkedAttribute + '><span>' + folder.Name + '</span></label>';
}
for (i = 0, length = channelsResult.Items.length; i < length; i++) {
folder = channelsResult.Items[i];
isChecked = user.Policy.EnableContentDeletion || -1 != user.Policy.EnableContentDeletionFromFolders.indexOf(folder.Id);
checkedAttribute = isChecked ? ' checked="checked"' : '';
html += '<label><input type="checkbox" is="emby-checkbox" class="chkFolder" data-id="' + folder.Id + '" ' + checkedAttribute + '><span>' + folder.Name + '</span></label>';
}
$('.deleteAccess', page).html(html).trigger('create');
$('#chkEnableDeleteAllFolders', page).checked = user.Policy.EnableContentDeletion;
});
}
function loadAuthProviders(page, user, providers) {
if (providers.length > 1) {
page.querySelector('.fldSelectLoginProvider').classList.remove('hide');
} else {
page.querySelector('.fldSelectLoginProvider').classList.add('hide');
}
var currentProviderId = user.Policy.AuthenticationProviderId;
page.querySelector('.selectLoginProvider').innerHTML = providers.map(function (provider) {
var selected = provider.Id === currentProviderId || providers.length < 2 ? ' selected' : '';
return '<option value="' + provider.Id + '"' + selected + '>' + provider.Name + '</option>';
});
}
function loadPasswordResetProviders(page, user, providers) {
if (providers.length > 1) {
page.querySelector('.fldSelectPasswordResetProvider').classList.remove('hide');
} else {
page.querySelector('.fldSelectPasswordResetProvider').classList.add('hide');
}
var currentProviderId = user.Policy.PasswordResetProviderId;
page.querySelector('.selectPasswordResetProvider').innerHTML = providers.map(function (provider) {
var selected = provider.Id === currentProviderId || providers.length < 2 ? ' selected' : '';
return '<option value="' + provider.Id + '"' + selected + '>' + provider.Name + '</option>';
});
}
function loadUser(page, user) {
currentUser = user;
ApiClient.getJSON(ApiClient.getUrl('Auth/Providers')).then(function (providers) {
loadAuthProviders(page, user, providers);
});
ApiClient.getJSON(ApiClient.getUrl('Auth/PasswordResetProviders')).then(function (providers) {
loadPasswordResetProviders(page, user, providers);
});
ApiClient.getJSON(ApiClient.getUrl('Library/MediaFolders', {
IsHidden: false
})).then(function (folders) {
loadDeleteFolders(page, user, folders.Items);
});
if (user.Policy.IsDisabled) {
$('.disabledUserBanner', page).show();
} else {
$('.disabledUserBanner', page).hide();
}
$('#txtUserName', page).prop('disabled', '').removeAttr('disabled');
$('#fldConnectInfo', page).show();
$('.lnkEditUserPreferences', page).attr('href', 'mypreferencesmenu.html?userId=' + user.Id);
libraryMenu.setTitle(user.Name);
page.querySelector('.username').innerHTML = user.Name;
$('#txtUserName', page).val(user.Name);
$('#chkIsAdmin', page).checked = user.Policy.IsAdministrator;
$('#chkDisabled', page).checked = user.Policy.IsDisabled;
$('#chkIsHidden', page).checked = user.Policy.IsHidden;
$('#chkRemoteControlSharedDevices', page).checked = user.Policy.EnableSharedDeviceControl;
$('#chkEnableRemoteControlOtherUsers', page).checked = user.Policy.EnableRemoteControlOfOtherUsers;
$('#chkEnableDownloading', page).checked = user.Policy.EnableContentDownloading;
$('#chkManageLiveTv', page).checked = user.Policy.EnableLiveTvManagement;
$('#chkEnableLiveTvAccess', page).checked = user.Policy.EnableLiveTvAccess;
$('#chkEnableMediaPlayback', page).checked = user.Policy.EnableMediaPlayback;
$('#chkEnableAudioPlaybackTranscoding', page).checked = user.Policy.EnableAudioPlaybackTranscoding;
$('#chkEnableVideoPlaybackTranscoding', page).checked = user.Policy.EnableVideoPlaybackTranscoding;
$('#chkEnableVideoPlaybackRemuxing', page).checked = user.Policy.EnablePlaybackRemuxing;
$('#chkForceRemoteSourceTranscoding', page).checked = user.Policy.ForceRemoteSourceTranscoding;
$('#chkRemoteAccess', page).checked = null == user.Policy.EnableRemoteAccess || user.Policy.EnableRemoteAccess;
$('#chkEnableSyncTranscoding', page).checked = user.Policy.EnableSyncTranscoding;
$('#chkEnableConversion', page).checked = user.Policy.EnableMediaConversion || false;
$('#chkEnableSharing', page).checked = user.Policy.EnablePublicSharing;
$('#txtRemoteClientBitrateLimit', page).val(user.Policy.RemoteClientBitrateLimit / 1e6 || '');
$('#txtLoginAttemptsBeforeLockout', page).val(user.Policy.LoginAttemptsBeforeLockout || '0');
$('#selectSyncPlayAccess').val(user.Policy.SyncPlayAccess);
loading.hide();
}
function onSaveComplete(page, user) {
Dashboard.navigate('userprofiles.html');
loading.hide();
require(['toast'], function (toast) {
toast(globalize.translate('SettingsSaved'));
});
}
function saveUser(user, page) {
user.Name = $('#txtUserName', page).val();
user.Policy.IsAdministrator = $('#chkIsAdmin', page).checked;
user.Policy.IsHidden = $('#chkIsHidden', page).checked;
user.Policy.IsDisabled = $('#chkDisabled', page).checked;
user.Policy.EnableRemoteControlOfOtherUsers = $('#chkEnableRemoteControlOtherUsers', page).checked;
user.Policy.EnableLiveTvManagement = $('#chkManageLiveTv', page).checked;
user.Policy.EnableLiveTvAccess = $('#chkEnableLiveTvAccess', page).checked;
user.Policy.EnableSharedDeviceControl = $('#chkRemoteControlSharedDevices', page).checked;
user.Policy.EnableMediaPlayback = $('#chkEnableMediaPlayback', page).checked;
user.Policy.EnableAudioPlaybackTranscoding = $('#chkEnableAudioPlaybackTranscoding', page).checked;
user.Policy.EnableVideoPlaybackTranscoding = $('#chkEnableVideoPlaybackTranscoding', page).checked;
user.Policy.EnablePlaybackRemuxing = $('#chkEnableVideoPlaybackRemuxing', page).checked;
user.Policy.ForceRemoteSourceTranscoding = $('#chkForceRemoteSourceTranscoding', page).checked;
user.Policy.EnableContentDownloading = $('#chkEnableDownloading', page).checked;
user.Policy.EnableSyncTranscoding = $('#chkEnableSyncTranscoding', page).checked;
user.Policy.EnableMediaConversion = $('#chkEnableConversion', page).checked;
user.Policy.EnablePublicSharing = $('#chkEnableSharing', page).checked;
user.Policy.EnableRemoteAccess = $('#chkRemoteAccess', page).checked;
user.Policy.RemoteClientBitrateLimit = parseInt(1e6 * parseFloat($('#txtRemoteClientBitrateLimit', page).val() || '0'));
user.Policy.LoginAttemptsBeforeLockout = parseInt($('#txtLoginAttemptsBeforeLockout', page).val() || '0');
user.Policy.AuthenticationProviderId = page.querySelector('.selectLoginProvider').value;
user.Policy.PasswordResetProviderId = page.querySelector('.selectPasswordResetProvider').value;
user.Policy.EnableContentDeletion = $('#chkEnableDeleteAllFolders', page).checked;
user.Policy.EnableContentDeletionFromFolders = user.Policy.EnableContentDeletion ? [] : $('.chkFolder', page).get().filter(function (c) {
return c.checked;
}).map(function (c) {
return c.getAttribute('data-id');
});
user.Policy.SyncPlayAccess = page.querySelector('#selectSyncPlayAccess').value;
ApiClient.updateUser(user).then(function () {
ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () {
onSaveComplete(page, user);
});
});
}
function onSubmit() {
var page = $(this).parents('.page')[0];
loading.show();
getUser().then(function (result) {
saveUser(result, page);
});
return false;
}
function getUser() {
var userId = getParameterByName('userId');
return ApiClient.getUser(userId);
}
function loadData(page) {
loading.show();
getUser().then(function (user) {
loadUser(page, user);
});
}
var currentUser;
$(document).on('pageinit', '#editUserPage', function () {
$('.editUserProfileForm').off('submit', onSubmit).on('submit', onSubmit);
this.querySelector('.sharingHelp').innerHTML = globalize.translate('OptionAllowLinkSharingHelp', 30);
var page = this;
$('#chkEnableDeleteAllFolders', this).on('change', function () {
if (this.checked) {
$('.deleteAccess', page).hide();
} else {
$('.deleteAccess', page).show();
}
});
ApiClient.getServerConfiguration().then(function (config) {
if (config.EnableRemoteAccess) {
page.querySelector('.fldRemoteAccess').classList.remove('hide');
} else {
page.querySelector('.fldRemoteAccess').classList.add('hide');
}
});
}).on('pagebeforeshow', '#editUserPage', function () {
loadData(this);
});
});

View file

@ -0,0 +1,178 @@
define(['jQuery', 'loading', 'libraryMenu', 'globalize'], function ($, loading, libraryMenu, globalize) {
'use strict';
function triggerChange(select) {
var evt = document.createEvent('HTMLEvents');
evt.initEvent('change', false, true);
select.dispatchEvent(evt);
}
function loadMediaFolders(page, user, mediaFolders) {
var html = '';
html += '<h3 class="checkboxListLabel">' + globalize.translate('HeaderLibraries') + '</h3>';
html += '<div class="checkboxList paperList checkboxList-paperList">';
for (var i = 0, length = mediaFolders.length; i < length; i++) {
var folder = mediaFolders[i];
var isChecked = user.Policy.EnableAllFolders || -1 != user.Policy.EnabledFolders.indexOf(folder.Id);
var checkedAttribute = isChecked ? ' checked="checked"' : '';
html += '<label><input type="checkbox" is="emby-checkbox" class="chkFolder" data-id="' + folder.Id + '" ' + checkedAttribute + '><span>' + folder.Name + '</span></label>';
}
html += '</div>';
page.querySelector('.folderAccess').innerHTML = html;
var chkEnableAllFolders = page.querySelector('#chkEnableAllFolders');
chkEnableAllFolders.checked = user.Policy.EnableAllFolders;
triggerChange(chkEnableAllFolders);
}
function loadChannels(page, user, channels) {
var html = '';
html += '<h3 class="checkboxListLabel">' + globalize.translate('HeaderChannels') + '</h3>';
html += '<div class="checkboxList paperList checkboxList-paperList">';
for (var i = 0, length = channels.length; i < length; i++) {
var folder = channels[i];
var isChecked = user.Policy.EnableAllChannels || -1 != user.Policy.EnabledChannels.indexOf(folder.Id);
var checkedAttribute = isChecked ? ' checked="checked"' : '';
html += '<label><input type="checkbox" is="emby-checkbox" class="chkChannel" data-id="' + folder.Id + '" ' + checkedAttribute + '><span>' + folder.Name + '</span></label>';
}
html += '</div>';
$('.channelAccess', page).show().html(html);
if (channels.length) {
$('.channelAccessContainer', page).show();
} else {
$('.channelAccessContainer', page).hide();
}
$('#chkEnableAllChannels', page).checked = user.Policy.EnableAllChannels;
}
function loadDevices(page, user, devices) {
var html = '';
html += '<h3 class="checkboxListLabel">' + globalize.translate('HeaderDevices') + '</h3>';
html += '<div class="checkboxList paperList checkboxList-paperList">';
for (var i = 0, length = devices.length; i < length; i++) {
var device = devices[i];
var checkedAttribute = user.Policy.EnableAllDevices || -1 != user.Policy.EnabledDevices.indexOf(device.Id) ? ' checked="checked"' : '';
html += '<label><input type="checkbox" is="emby-checkbox" class="chkDevice" data-id="' + device.Id + '" ' + checkedAttribute + '><span>' + device.Name + ' - ' + device.AppName + '</span></label>';
}
html += '</div>';
$('.deviceAccess', page).show().html(html);
$('#chkEnableAllDevices', page).checked = user.Policy.EnableAllDevices;
if (user.Policy.IsAdministrator) {
page.querySelector('.deviceAccessContainer').classList.add('hide');
} else {
page.querySelector('.deviceAccessContainer').classList.remove('hide');
}
}
function loadUser(page, user, loggedInUser, mediaFolders, channels, devices) {
page.querySelector('.username').innerHTML = user.Name;
libraryMenu.setTitle(user.Name);
loadChannels(page, user, channels);
loadMediaFolders(page, user, mediaFolders);
loadDevices(page, user, devices);
loading.hide();
}
function onSaveComplete(page) {
loading.hide();
require(['toast'], function (toast) {
toast(globalize.translate('SettingsSaved'));
});
}
function saveUser(user, page) {
user.Policy.EnableAllFolders = $('#chkEnableAllFolders', page).checked;
user.Policy.EnabledFolders = user.Policy.EnableAllFolders ? [] : $('.chkFolder', page).get().filter(function (c) {
return c.checked;
}).map(function (c) {
return c.getAttribute('data-id');
});
user.Policy.EnableAllChannels = $('#chkEnableAllChannels', page).checked;
user.Policy.EnabledChannels = user.Policy.EnableAllChannels ? [] : $('.chkChannel', page).get().filter(function (c) {
return c.checked;
}).map(function (c) {
return c.getAttribute('data-id');
});
user.Policy.EnableAllDevices = $('#chkEnableAllDevices', page).checked;
user.Policy.EnabledDevices = user.Policy.EnableAllDevices ? [] : $('.chkDevice', page).get().filter(function (c) {
return c.checked;
}).map(function (c) {
return c.getAttribute('data-id');
});
user.Policy.BlockedChannels = null;
user.Policy.BlockedMediaFolders = null;
ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () {
onSaveComplete(page);
});
}
function onSubmit() {
var page = $(this).parents('.page');
loading.show();
var userId = getParameterByName('userId');
ApiClient.getUser(userId).then(function (result) {
saveUser(result, page);
});
return false;
}
$(document).on('pageinit', '#userLibraryAccessPage', function () {
var page = this;
$('#chkEnableAllDevices', page).on('change', function () {
if (this.checked) {
$('.deviceAccessListContainer', page).hide();
} else {
$('.deviceAccessListContainer', page).show();
}
});
$('#chkEnableAllChannels', page).on('change', function () {
if (this.checked) {
$('.channelAccessListContainer', page).hide();
} else {
$('.channelAccessListContainer', page).show();
}
});
page.querySelector('#chkEnableAllFolders').addEventListener('change', function () {
if (this.checked) {
page.querySelector('.folderAccessListContainer').classList.add('hide');
} else {
page.querySelector('.folderAccessListContainer').classList.remove('hide');
}
});
$('.userLibraryAccessForm').off('submit', onSubmit).on('submit', onSubmit);
}).on('pageshow', '#userLibraryAccessPage', function () {
var page = this;
loading.show();
var promise1;
var userId = getParameterByName('userId');
if (userId) {
promise1 = ApiClient.getUser(userId);
} else {
var deferred = $.Deferred();
deferred.resolveWith(null, [{
Configuration: {}
}]);
promise1 = deferred.promise();
}
var promise2 = Dashboard.getCurrentUser();
var promise4 = ApiClient.getJSON(ApiClient.getUrl('Library/MediaFolders', {
IsHidden: false
}));
var promise5 = ApiClient.getJSON(ApiClient.getUrl('Channels'));
var promise6 = ApiClient.getJSON(ApiClient.getUrl('Devices'));
Promise.all([promise1, promise2, promise4, promise5, promise6]).then(function (responses) {
loadUser(page, responses[0], responses[1], responses[2].Items, responses[3].Items, responses[4].Items);
});
});
});

View file

@ -0,0 +1,126 @@
define(['jQuery', 'loading', 'globalize', 'emby-checkbox'], function ($, loading, globalize) {
'use strict';
function loadMediaFolders(page, mediaFolders) {
var html = '';
html += '<h3 class="checkboxListLabel">' + globalize.translate('HeaderLibraries') + '</h3>';
html += '<div class="checkboxList paperList" style="padding:.5em 1em;">';
for (var i = 0; i < mediaFolders.length; i++) {
var folder = mediaFolders[i];
html += '<label><input type="checkbox" is="emby-checkbox" class="chkFolder" data-id="' + folder.Id + '"/><span>' + folder.Name + '</span></label>';
}
html += '</div>';
$('.folderAccess', page).html(html).trigger('create');
$('#chkEnableAllFolders', page).checked = false;
}
function loadChannels(page, channels) {
var html = '';
html += '<h3 class="checkboxListLabel">' + globalize.translate('HeaderChannels') + '</h3>';
html += '<div class="checkboxList paperList" style="padding:.5em 1em;">';
for (var i = 0; i < channels.length; i++) {
var folder = channels[i];
html += '<label><input type="checkbox" is="emby-checkbox" class="chkChannel" data-id="' + folder.Id + '"/><span>' + folder.Name + '</span></label>';
}
html += '</div>';
$('.channelAccess', page).show().html(html).trigger('create');
if (channels.length) {
$('.channelAccessContainer', page).show();
} else {
$('.channelAccessContainer', page).hide();
}
$('#chkEnableAllChannels', page).checked = false;
}
function loadUser(page) {
$('#txtUsername', page).val('');
$('#txtPassword', page).val('');
loading.show();
var promiseFolders = ApiClient.getJSON(ApiClient.getUrl('Library/MediaFolders', {
IsHidden: false
}));
var promiseChannels = ApiClient.getJSON(ApiClient.getUrl('Channels'));
Promise.all([promiseFolders, promiseChannels]).then(function (responses) {
loadMediaFolders(page, responses[0].Items);
loadChannels(page, responses[1].Items);
loading.hide();
});
}
function saveUser(page) {
var user = {};
user.Name = $('#txtUsername', page).val();
user.Password = $('#txtPassword', page).val();
ApiClient.createUser(user).then(function (user) {
user.Policy.EnableAllFolders = $('#chkEnableAllFolders', page).checked;
user.Policy.EnabledFolders = [];
if (!user.Policy.EnableAllFolders) {
user.Policy.EnabledFolders = $('.chkFolder', page).get().filter(function (i) {
return i.checked;
}).map(function (i) {
return i.getAttribute('data-id');
});
}
user.Policy.EnableAllChannels = $('#chkEnableAllChannels', page).checked;
user.Policy.EnabledChannels = [];
if (!user.Policy.EnableAllChannels) {
user.Policy.EnabledChannels = $('.chkChannel', page).get().filter(function (i) {
return i.checked;
}).map(function (i) {
return i.getAttribute('data-id');
});
}
ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () {
Dashboard.navigate('useredit.html?userId=' + user.Id);
});
}, function (response) {
require(['toast'], function (toast) {
toast(globalize.translate('DefaultErrorMessage'));
});
loading.hide();
});
}
function onSubmit() {
var page = $(this).parents('.page')[0];
loading.show();
saveUser(page);
return false;
}
function loadData(page) {
loadUser(page);
}
$(document).on('pageinit', '#newUserPage', function () {
var page = this;
$('#chkEnableAllChannels', page).on('change', function () {
if (this.checked) {
$('.channelAccessListContainer', page).hide();
} else {
$('.channelAccessListContainer', page).show();
}
});
$('#chkEnableAllFolders', page).on('change', function () {
if (this.checked) {
$('.folderAccessListContainer', page).hide();
} else {
$('.folderAccessListContainer', page).show();
}
});
$('.newUserProfileForm').off('submit', onSubmit).on('submit', onSubmit);
}).on('pageshow', '#newUserPage', function () {
loadData(this);
});
});

View file

@ -0,0 +1,271 @@
define(['jQuery', 'datetime', 'loading', 'libraryMenu', 'globalize', 'listViewStyle', 'paper-icon-button-light'], function ($, datetime, loading, libraryMenu, globalize) {
'use strict';
function populateRatings(allParentalRatings, page) {
var html = '';
html += "<option value=''></option>";
var i;
var length;
var rating;
var ratings = [];
for (i = 0, length = allParentalRatings.length; i < length; i++) {
if (rating = allParentalRatings[i], ratings.length) {
var lastRating = ratings[ratings.length - 1];
if (lastRating.Value === rating.Value) {
lastRating.Name += '/' + rating.Name;
continue;
}
}
ratings.push({
Name: rating.Name,
Value: rating.Value
});
}
for (i = 0, length = ratings.length; i < length; i++) {
rating = ratings[i];
html += "<option value='" + rating.Value + "'>" + rating.Name + '</option>';
}
$('#selectMaxParentalRating', page).html(html);
}
function loadUnratedItems(page, user) {
var items = [{
name: globalize.translate('OptionBlockBooks'),
value: 'Book'
}, {
name: globalize.translate('OptionBlockChannelContent'),
value: 'ChannelContent'
}, {
name: globalize.translate('OptionBlockLiveTvChannels'),
value: 'LiveTvChannel'
}, {
name: globalize.translate('OptionBlockMovies'),
value: 'Movie'
}, {
name: globalize.translate('OptionBlockMusic'),
value: 'Music'
}, {
name: globalize.translate('OptionBlockTrailers'),
value: 'Trailer'
}, {
name: globalize.translate('OptionBlockTvShows'),
value: 'Series'
}];
var html = '';
html += '<h3 class="checkboxListLabel">' + globalize.translate('HeaderBlockItemsWithNoRating') + '</h3>';
html += '<div class="checkboxList paperList checkboxList-paperList">';
for (var i = 0, length = items.length; i < length; i++) {
var item = items[i];
var checkedAttribute = -1 != user.Policy.BlockUnratedItems.indexOf(item.value) ? ' checked="checked"' : '';
html += '<label><input type="checkbox" is="emby-checkbox" class="chkUnratedItem" data-itemtype="' + item.value + '" type="checkbox"' + checkedAttribute + '><span>' + item.name + '</span></label>';
}
html += '</div>';
$('.blockUnratedItems', page).html(html).trigger('create');
}
function loadUser(page, user, allParentalRatings) {
page.querySelector('.username').innerHTML = user.Name;
libraryMenu.setTitle(user.Name);
loadUnratedItems(page, user);
loadBlockedTags(page, user.Policy.BlockedTags);
populateRatings(allParentalRatings, page);
var ratingValue = '';
if (user.Policy.MaxParentalRating) {
for (var i = 0, length = allParentalRatings.length; i < length; i++) {
var rating = allParentalRatings[i];
if (user.Policy.MaxParentalRating >= rating.Value) {
ratingValue = rating.Value;
}
}
}
$('#selectMaxParentalRating', page).val(ratingValue);
if (user.Policy.IsAdministrator) {
$('.accessScheduleSection', page).hide();
} else {
$('.accessScheduleSection', page).show();
}
renderAccessSchedule(page, user.Policy.AccessSchedules || []);
loading.hide();
}
function loadBlockedTags(page, tags) {
var html = tags.map(function (h) {
var li = '<div class="listItem">';
li += '<div class="listItemBody">';
li += '<h3 class="listItemBodyText">';
li += h;
li += '</h3>';
li += '</div>';
li += '<button type="button" is="paper-icon-button-light" class="blockedTag btnDeleteTag listItemButton" data-tag="' + h + '"><span class="material-icons delete"></span></button>';
return li += '</div>';
}).join('');
if (html) {
html = '<div class="paperList">' + html + '</div>';
}
var elem = $('.blockedTags', page).html(html).trigger('create');
$('.btnDeleteTag', elem).on('click', function () {
var tag = this.getAttribute('data-tag');
var newTags = tags.filter(function (t) {
return t != tag;
});
loadBlockedTags(page, newTags);
});
}
function deleteAccessSchedule(page, schedules, index) {
schedules.splice(index, 1);
renderAccessSchedule(page, schedules);
}
function renderAccessSchedule(page, schedules) {
var html = '';
var index = 0;
html += schedules.map(function (a) {
var itemHtml = '';
itemHtml += '<div class="liSchedule listItem" data-day="' + a.DayOfWeek + '" data-start="' + a.StartHour + '" data-end="' + a.EndHour + '">';
itemHtml += '<div class="listItemBody two-line">';
itemHtml += '<h3 class="listItemBodyText">';
itemHtml += globalize.translate('Option' + a.DayOfWeek);
itemHtml += '</h3>';
itemHtml += '<div class="listItemBodyText secondary">' + getDisplayTime(a.StartHour) + ' - ' + getDisplayTime(a.EndHour) + '</div>';
itemHtml += '</div>';
itemHtml += '<button type="button" is="paper-icon-button-light" class="btnDelete listItemButton" data-index="' + index + '"><span class="material-icons delete"></span></button>';
itemHtml += '</div>';
index++;
return itemHtml;
}).join('');
var accessScheduleList = page.querySelector('.accessScheduleList');
accessScheduleList.innerHTML = html;
$('.btnDelete', accessScheduleList).on('click', function () {
deleteAccessSchedule(page, schedules, parseInt(this.getAttribute('data-index')));
});
}
function onSaveComplete(page) {
loading.hide();
require(['toast'], function (toast) {
toast(globalize.translate('SettingsSaved'));
});
}
function saveUser(user, page) {
user.Policy.MaxParentalRating = $('#selectMaxParentalRating', page).val() || null;
user.Policy.BlockUnratedItems = $('.chkUnratedItem', page).get().filter(function (i) {
return i.checked;
}).map(function (i) {
return i.getAttribute('data-itemtype');
});
user.Policy.AccessSchedules = getSchedulesFromPage(page);
user.Policy.BlockedTags = getBlockedTagsFromPage(page);
ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () {
onSaveComplete(page);
});
}
function getDisplayTime(hours) {
var minutes = 0;
var pct = hours % 1;
if (pct) {
minutes = parseInt(60 * pct);
}
return datetime.getDisplayTime(new Date(2000, 1, 1, hours, minutes, 0, 0));
}
function showSchedulePopup(page, schedule, index) {
schedule = schedule || {};
require(['components/accessSchedule/accessSchedule'], function (accessschedule) {
accessschedule.show({
schedule: schedule
}).then(function (updatedSchedule) {
var schedules = getSchedulesFromPage(page);
if (-1 == index) {
index = schedules.length;
}
schedules[index] = updatedSchedule;
renderAccessSchedule(page, schedules);
});
});
}
function getSchedulesFromPage(page) {
return $('.liSchedule', page).map(function () {
return {
DayOfWeek: this.getAttribute('data-day'),
StartHour: this.getAttribute('data-start'),
EndHour: this.getAttribute('data-end')
};
}).get();
}
function getBlockedTagsFromPage(page) {
return $('.blockedTag', page).map(function () {
return this.getAttribute('data-tag');
}).get();
}
function showBlockedTagPopup(page) {
require(['prompt'], function (prompt) {
prompt({
label: globalize.translate('LabelTag')
}).then(function (value) {
var tags = getBlockedTagsFromPage(page);
if (-1 == tags.indexOf(value)) {
tags.push(value);
loadBlockedTags(page, tags);
}
});
});
}
window.UserParentalControlPage = {
onSubmit: function () {
var page = $(this).parents('.page');
loading.show();
var userId = getParameterByName('userId');
ApiClient.getUser(userId).then(function (result) {
saveUser(result, page);
});
return false;
}
};
$(document).on('pageinit', '#userParentalControlPage', function () {
var page = this;
$('.btnAddSchedule', page).on('click', function () {
showSchedulePopup(page, {}, -1);
});
$('.btnAddBlockedTag', page).on('click', function () {
showBlockedTagPopup(page);
});
$('.userParentalControlForm').off('submit', UserParentalControlPage.onSubmit).on('submit', UserParentalControlPage.onSubmit);
}).on('pageshow', '#userParentalControlPage', function () {
var page = this;
loading.show();
var userId = getParameterByName('userId');
var promise1 = ApiClient.getUser(userId);
var promise2 = ApiClient.getParentalRatings();
Promise.all([promise1, promise2]).then(function (responses) {
loadUser(page, responses[0], responses[1]);
});
});
});

View file

@ -0,0 +1,187 @@
define(['loading', 'libraryMenu', 'globalize', 'emby-button'], function (loading, libraryMenu, globalize) {
'use strict';
function loadUser(page, params) {
var userid = params.userId;
ApiClient.getUser(userid).then(function (user) {
Dashboard.getCurrentUser().then(function (loggedInUser) {
libraryMenu.setTitle(user.Name);
page.querySelector('.username').innerHTML = user.Name;
var showPasswordSection = true;
var showLocalAccessSection = false;
if ('Guest' == user.ConnectLinkType) {
page.querySelector('.localAccessSection').classList.add('hide');
showPasswordSection = false;
} else if (user.HasConfiguredPassword) {
page.querySelector('#btnResetPassword').classList.remove('hide');
page.querySelector('#fldCurrentPassword').classList.remove('hide');
showLocalAccessSection = true;
} else {
page.querySelector('#btnResetPassword').classList.add('hide');
page.querySelector('#fldCurrentPassword').classList.add('hide');
}
if (showPasswordSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) {
page.querySelector('.passwordSection').classList.remove('hide');
} else {
page.querySelector('.passwordSection').classList.add('hide');
}
if (showLocalAccessSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) {
page.querySelector('.localAccessSection').classList.remove('hide');
} else {
page.querySelector('.localAccessSection').classList.add('hide');
}
var txtEasyPassword = page.querySelector('#txtEasyPassword');
txtEasyPassword.value = '';
if (user.HasConfiguredEasyPassword) {
txtEasyPassword.placeholder = '******';
page.querySelector('#btnResetEasyPassword').classList.remove('hide');
} else {
txtEasyPassword.removeAttribute('placeholder');
txtEasyPassword.placeholder = '';
page.querySelector('#btnResetEasyPassword').classList.add('hide');
}
page.querySelector('.chkEnableLocalEasyPassword').checked = user.Configuration.EnableLocalPassword;
require(['autoFocuser'], function (autoFocuser) {
autoFocuser.autoFocus(page);
});
});
});
page.querySelector('#txtCurrentPassword').value = '';
page.querySelector('#txtNewPassword').value = '';
page.querySelector('#txtNewPasswordConfirm').value = '';
}
return function (view, params) {
function saveEasyPassword() {
var userId = params.userId;
var easyPassword = view.querySelector('#txtEasyPassword').value;
if (easyPassword) {
ApiClient.updateEasyPassword(userId, easyPassword).then(function () {
onEasyPasswordSaved(userId);
});
} else {
onEasyPasswordSaved(userId);
}
}
function onEasyPasswordSaved(userId) {
ApiClient.getUser(userId).then(function (user) {
user.Configuration.EnableLocalPassword = view.querySelector('.chkEnableLocalEasyPassword').checked;
ApiClient.updateUserConfiguration(user.Id, user.Configuration).then(function () {
loading.hide();
require(['toast'], function (toast) {
toast(globalize.translate('MessageSettingsSaved'));
});
loadUser(view, params);
});
});
}
function savePassword() {
var userId = params.userId;
var currentPassword = view.querySelector('#txtCurrentPassword').value;
var newPassword = view.querySelector('#txtNewPassword').value;
if (view.querySelector('#fldCurrentPassword').classList.contains('hide')) {
// Firefox does not respect autocomplete=off, so clear it if the field is supposed to be hidden (and blank)
// This should only happen when user.HasConfiguredPassword is false, but this information is not passed on
currentPassword = '';
}
ApiClient.updateUserPassword(userId, currentPassword, newPassword).then(function () {
loading.hide();
require(['toast'], function (toast) {
toast(globalize.translate('PasswordSaved'));
});
loadUser(view, params);
}, function () {
loading.hide();
Dashboard.alert({
title: globalize.translate('HeaderLoginFailure'),
message: globalize.translate('MessageInvalidUser')
});
});
}
function onSubmit(e) {
var form = this;
if (form.querySelector('#txtNewPassword').value != form.querySelector('#txtNewPasswordConfirm').value) {
require(['toast'], function (toast) {
toast(globalize.translate('PasswordMatchError'));
});
} else {
loading.show();
savePassword();
}
e.preventDefault();
return false;
}
function onLocalAccessSubmit(e) {
loading.show();
saveEasyPassword();
e.preventDefault();
return false;
}
function resetPassword() {
var msg = globalize.translate('PasswordResetConfirmation');
require(['confirm'], function (confirm) {
confirm(msg, globalize.translate('PasswordResetHeader')).then(function () {
var userId = params.userId;
loading.show();
ApiClient.resetUserPassword(userId).then(function () {
loading.hide();
Dashboard.alert({
message: globalize.translate('PasswordResetComplete'),
title: globalize.translate('PasswordResetHeader')
});
loadUser(view, params);
});
});
});
}
function resetEasyPassword() {
var msg = globalize.translate('PinCodeResetConfirmation');
require(['confirm'], function (confirm) {
confirm(msg, globalize.translate('HeaderPinCodeReset')).then(function () {
var userId = params.userId;
loading.show();
ApiClient.resetEasyPassword(userId).then(function () {
loading.hide();
Dashboard.alert({
message: globalize.translate('PinCodeResetComplete'),
title: globalize.translate('HeaderPinCodeReset')
});
loadUser(view, params);
});
});
});
}
view.querySelector('.updatePasswordForm').addEventListener('submit', onSubmit);
view.querySelector('.localAccessForm').addEventListener('submit', onLocalAccessSubmit);
view.querySelector('#btnResetEasyPassword').addEventListener('click', resetEasyPassword);
view.querySelector('#btnResetPassword').addEventListener('click', resetPassword);
view.addEventListener('viewshow', function () {
loadUser(view, params);
});
};
});

View file

@ -0,0 +1,269 @@
define(['loading', 'dom', 'globalize', 'date-fns', 'dfnshelper', 'paper-icon-button-light', 'cardStyle', 'emby-button', 'indicators', 'flexStyles'], function (loading, dom, globalize, datefns, dfnshelper) {
'use strict';
function deleteUser(page, id) {
var msg = globalize.translate('DeleteUserConfirmation');
require(['confirm'], function (confirm) {
confirm({
title: globalize.translate('DeleteUser'),
text: msg,
confirmText: globalize.translate('ButtonDelete'),
primary: 'delete'
}).then(function () {
loading.show();
ApiClient.deleteUser(id).then(function () {
loadData(page);
});
});
});
}
function showUserMenu(elem) {
var card = dom.parentWithClass(elem, 'card');
var page = dom.parentWithClass(card, 'page');
var userId = card.getAttribute('data-userid');
var menuItems = [];
menuItems.push({
name: globalize.translate('ButtonOpen'),
id: 'open',
icon: 'mode_edit'
});
menuItems.push({
name: globalize.translate('ButtonLibraryAccess'),
id: 'access',
icon: 'lock'
});
menuItems.push({
name: globalize.translate('ButtonParentalControl'),
id: 'parentalcontrol',
icon: 'person'
});
menuItems.push({
name: globalize.translate('ButtonDelete'),
id: 'delete',
icon: 'delete'
});
require(['actionsheet'], function (actionsheet) {
actionsheet.show({
items: menuItems,
positionTo: card,
callback: function (id) {
switch (id) {
case 'open':
Dashboard.navigate('useredit.html?userId=' + userId);
break;
case 'access':
Dashboard.navigate('userlibraryaccess.html?userId=' + userId);
break;
case 'parentalcontrol':
Dashboard.navigate('userparentalcontrol.html?userId=' + userId);
break;
case 'delete':
deleteUser(page, userId);
}
}
});
});
}
function getUserHtml(user, addConnectIndicator) {
var html = '';
var cssClass = 'card squareCard scalableCard squareCard-scalable';
if (user.Policy.IsDisabled) {
cssClass += ' grayscale';
}
html += "<div data-userid='" + user.Id + "' class='" + cssClass + "'>";
html += '<div class="cardBox visualCardBox">';
html += '<div class="cardScalable visualCardBox-cardScalable">';
html += '<div class="cardPadder cardPadder-square"></div>';
html += '<a is="emby-linkbutton" class="cardContent" href="useredit.html?userId=' + user.Id + '">';
var imgUrl;
if (user.PrimaryImageTag) {
imgUrl = ApiClient.getUserImageUrl(user.Id, {
width: 300,
tag: user.PrimaryImageTag,
type: 'Primary'
});
}
var imageClass = 'cardImage';
if (user.Policy.IsDisabled) {
imageClass += ' disabledUser';
}
if (imgUrl) {
html += '<div class="' + imageClass + '" style="background-image:url(\'' + imgUrl + "');\">";
} else {
html += '<div class="' + imageClass + ' flex align-items-center justify-content-center">';
html += '<span class="material-icons cardImageIcon person"></span>';
}
html += '</div>';
html += '</a>';
html += '</div>';
html += '<div class="cardFooter visualCardBox-cardFooter">';
html += '<div class="cardText flex align-items-center">';
html += '<div class="flex-grow" style="overflow:hidden;text-overflow:ellipsis;">';
html += user.Name;
html += '</div>';
html += '<button type="button" is="paper-icon-button-light" class="btnUserMenu flex-shrink-zero"><span class="material-icons more_vert"></span></button>';
html += '</div>';
html += '<div class="cardText cardText-secondary">';
var lastSeen = getLastSeenText(user.LastActivityDate);
html += '' != lastSeen ? lastSeen : '&nbsp;';
html += '</div>';
html += '</div>';
html += '</div>';
return html + '</div>';
}
// FIXME: It seems that, sometimes, server sends date in the future, so date-fns displays messages like 'in less than a minute'. We should fix
// how dates are returned by the server when the session is active and show something like 'Active now', instead of past/future sentences
function getLastSeenText(lastActivityDate) {
if (lastActivityDate) {
return globalize.translate('LastSeen', datefns.formatDistanceToNow(Date.parse(lastActivityDate), dfnshelper.localeWithSuffix));
}
return '';
}
function getUserSectionHtml(users, addConnectIndicator) {
return users.map(function (u__q) {
return getUserHtml(u__q, addConnectIndicator);
}).join('');
}
function renderUsers(page, users) {
page.querySelector('.localUsers').innerHTML = getUserSectionHtml(users, true);
}
function showPendingUserMenu(elem) {
var menuItems = [];
menuItems.push({
name: globalize.translate('ButtonCancel'),
id: 'delete',
icon: 'delete'
});
require(['actionsheet'], function (actionsheet) {
var card = dom.parentWithClass(elem, 'card');
var page = dom.parentWithClass(card, 'page');
var id = card.getAttribute('data-id');
actionsheet.show({
items: menuItems,
positionTo: card,
callback: function (menuItemId) {
switch (menuItemId) {
case 'delete':
cancelAuthorization(page, id);
}
}
});
});
}
function getPendingUserHtml(user) {
var html = '';
html += "<div data-id='" + user.Id + "' class='card squareCard scalableCard squareCard-scalable'>";
html += '<div class="cardBox cardBox-bottompadded visualCardBox">';
html += '<div class="cardScalable visualCardBox-cardScalable">';
html += '<div class="cardPadder cardPadder-square"></div>';
html += '<a class="cardContent cardImageContainer" is="emby-linkbutton" href="#">';
if (user.ImageUrl) {
html += '<div class="cardImage" style="background-image:url(\'' + user.ImageUrl + "');\">";
html += '</div>';
} else {
html += '<span class="cardImageIcon material-icons person"></span>';
}
html += '</a>';
html += '</div>';
html += '<div class="cardFooter visualCardBox-cardFooter">';
html += '<div class="cardText" style="text-align:right; float:right;padding:0;">';
html += '<button type="button" is="paper-icon-button-light" class="btnUserMenu"><span class="material-icons more_vert"></span></button>';
html += '</div>';
html += '<div class="cardText" style="padding-top:10px;padding-bottom:10px;">';
html += user.UserName;
html += '</div>';
html += '</div>';
html += '</div>';
return html + '</div>';
}
function renderPendingGuests(page, users) {
if (users.length) {
page.querySelector('.sectionPendingGuests').classList.remove('hide');
} else {
page.querySelector('.sectionPendingGuests').classList.add('hide');
}
page.querySelector('.pending').innerHTML = users.map(getPendingUserHtml).join('');
}
// TODO cvium: maybe reuse for invitation system
function cancelAuthorization(page, id) {
loading.show();
ApiClient.ajax({
type: 'DELETE',
url: ApiClient.getUrl('Connect/Pending', {
Id: id
})
}).then(function () {
loadData(page);
});
}
function loadData(page) {
loading.show();
ApiClient.getUsers().then(function (users) {
renderUsers(page, users);
loading.hide();
});
// TODO cvium
renderPendingGuests(page, []);
// ApiClient.getJSON(ApiClient.getUrl("Connect/Pending")).then(function (pending) {
//
// });
}
function showInvitePopup(page) {
require(['components/guestinviter/guestinviter'], function (guestinviter) {
guestinviter.show().then(function () {
loadData(page);
});
});
}
pageIdOn('pageinit', 'userProfilesPage', function () {
var page = this;
page.querySelector('.btnAddUser').addEventListener('click', function() {
Dashboard.navigate('usernew.html');
});
page.querySelector('.localUsers').addEventListener('click', function (e__e) {
var btnUserMenu = dom.parentWithClass(e__e.target, 'btnUserMenu');
if (btnUserMenu) {
showUserMenu(btnUserMenu);
}
});
page.querySelector('.pending').addEventListener('click', function (e__r) {
var btnUserMenu = dom.parentWithClass(e__r.target, 'btnUserMenu');
if (btnUserMenu) {
showPendingUserMenu(btnUserMenu);
}
});
});
pageIdOn('pagebeforeshow', 'userProfilesPage', function () {
loadData(this);
});
});