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

move around half the dashboard controllers to a subdirectory

This commit is contained in:
dkanada 2019-12-15 20:47:47 +09:00
parent e108997376
commit 34c0d6019e
12 changed files with 64 additions and 69 deletions

View file

@ -0,0 +1,849 @@
define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globalize", "loading", "connectionManager", "playMethodHelper", "cardBuilder", "imageLoader", "components/activitylog", "scripts/imagehelper", "indicators", "humanedate", "listViewStyle", "emby-button", "flexStyles", "emby-button", "emby-itemscontainer"], function (datetime, events, itemHelper, serverNotifications, dom, globalize, loading, connectionManager, playMethodHelper, cardBuilder, imageLoader, ActivityLog, imageHelper, indicators) {
"use strict";
function showPlaybackInfo(btn, session) {
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 (session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length) {
text.push("<br/>");
text.push(globalize.translate("LabelReasonForTranscoding"));
session.TranscodingInfo.TranscodeReasons.forEach(function (transcodeReason) {
text.push(globalize.translate(transcodeReason));
});
}
}
alert({
text: text.join("<br/>"),
title: title
});
});
}
function showSendMessageForm(btn, session) {
require(["prompt"], function (prompt) {
prompt({
title: globalize.translate("HeaderSendMessage"),
label: globalize.translate("LabelMessageText"),
confirmText: globalize.translate("ButtonSend")
}).then(function (text) {
if (text) {
connectionManager.getApiClient(session.ServerId).sendMessageCommand(session.Id, {
Text: text,
TimeoutMs: 5e3
});
}
});
});
}
function showOptionsMenu(btn, session) {
require(["actionsheet"], function (actionsheet) {
var menuItems = [];
if (session.ServerId && session.DeviceId !== connectionManager.deviceId()) {
menuItems.push({
name: globalize.translate("SendMessage"),
id: "sendmessage"
});
}
if (session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length) {
menuItems.push({
name: globalize.translate("ViewPlaybackInfo"),
id: "transcodinginfo"
});
}
return actionsheet.show({
items: menuItems,
positionTo: btn
}).then(function (id) {
switch (id) {
case "sendmessage":
showSendMessageForm(btn, session);
break;
case "transcodinginfo":
showPlaybackInfo(btn, session);
}
});
});
}
function onActiveDevicesClick(evt) {
var btn = dom.parentWithClass(evt.target, "sessionCardButton");
if (btn) {
var card = dom.parentWithClass(btn, "card");
if (card) {
var sessionId = card.id;
var session = (DashboardPage.sessionsList || []).filter(function (dashboardSession) {
return "session" + dashboardSession.Id === sessionId;
})[0];
if (session) {
if (btn.classList.contains("btnCardOptions")) {
showOptionsMenu(btn, session);
} else if (btn.classList.contains("btnSessionInfo")) {
showPlaybackInfo(btn, session);
} 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");
}
}
}
}
}
function filterSessions(sessions) {
var list = [];
var minActiveDate = new Date().getTime() - 9e5;
for (var i = 0, length = sessions.length; i < length; i++) {
var session = sessions[i];
if (!session.NowPlayingItem && !session.UserId) {
continue;
}
if (datetime.parseISO8601Date(session.LastActivityDate, true).getTime() >= minActiveDate) {
list.push(session);
}
}
return list;
}
function refreshActiveRecordings(view, apiClient) {
apiClient.getLiveTvRecordings({
UserId: Dashboard.getCurrentUserId(),
IsInProgress: true,
Fields: "CanDelete,PrimaryImageAspectRatio",
EnableTotalRecordCount: false,
EnableImageTypes: "Primary,Thumb,Backdrop"
}).then(function (result) {
var itemsContainer = view.querySelector(".activeRecordingItems");
if (!result.Items.length) {
view.querySelector(".activeRecordingsSection").classList.add("hide");
return void(itemsContainer.innerHTML = "");
}
view.querySelector(".activeRecordingsSection").classList.remove("hide");
itemsContainer.innerHTML = cardBuilder.getCardsHtml({
items: result.Items,
shape: "auto",
defaultShape: "backdrop",
showTitle: true,
showParentTitle: true,
coverImage: true,
cardLayout: false,
centerText: true,
preferThumb: "auto",
overlayText: false,
overlayMoreButton: true,
action: "none",
centerPlayButton: true
});
imageLoader.lazyChildren(itemsContainer);
});
}
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);
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);
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;
});
}
function renderInfo(view, sessions, forceUpdate) {
sessions = filterSessions(sessions);
renderActiveConnections(view, sessions);
loading.hide();
}
function pollForInfo(view, apiClient, forceUpdate) {
apiClient.getSessions({
ActiveWithinSeconds: 960
}).then(function (sessions) {
renderInfo(view, sessions, forceUpdate);
});
apiClient.getScheduledTasks().then(function (tasks) {
renderRunningTasks(view, tasks);
});
}
function renderActiveConnections(view, sessions) {
var html = "";
DashboardPage.sessionsList = sessions;
var parentElement = view.querySelector(".activeDevices");
var cardElem = parentElement.querySelector(".card");
if (cardElem) {
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);
if (elem) {
DashboardPage.updateSession(elem, session);
} else {
var nowPlayingItem = session.NowPlayingItem;
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">';
html += '<div class="cardPadder cardPadder-backdrop"></div>';
html += '<div class="cardContent">';
var imgUrl = DashboardPage.getNowPlayingImageUrl(nowPlayingItem);
if (imgUrl) {
html += '<div class="sessionNowPlayingContent sessionNowPlayingContent-withbackground"';
html += ' data-src="' + imgUrl + '" style="display:inline-block;background-image:url(\'' + imgUrl + "');\"></div>";
} else {
html += '<div class="sessionNowPlayingContent"></div>';
}
html += '<div class="sessionNowPlayingInnerContent">';
html += '<div class="sessionAppInfo">';
var clientImage = DashboardPage.getClientImage(session);
if (clientImage) {
html += clientImage;
}
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>";
if (session.TranscodingInfo && session.TranscodingInfo.Framerate) {
html += '<div class="sessionTranscodingFramerate">' + session.TranscodingInfo.Framerate + " fps</div>";
} else {
html += '<div class="sessionTranscodingFramerate"></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>';
if (nowPlayingItem && nowPlayingItem.RunTimeTicks) {
var percent = 100 * (session.PlayState.PositionTicks || 0) / nowPlayingItem.RunTimeTicks;
html += indicators.getProgressHtml(percent, {
containerClass: "playbackProgress"
});
} else {
// need to leave the element in just in case the device starts playback
html += indicators.getProgressHtml(0, {
containerClass: "playbackProgress hide"
});
}
if (session.TranscodingInfo && session.TranscodingInfo.CompletionPercentage) {
var percent = session.TranscodingInfo.CompletionPercentage.toFixed(1);
html += indicators.getProgressHtml(percent, {
containerClass: "transcodingProgress"
});
} else {
// same issue as playbackProgress element above
html += indicators.getProgressHtml(0, {
containerClass: "transcodingProgress hide"
});
}
html += "</div>";
html += "</div>";
html += "</div>";
html += '<div class="sessionCardFooter cardFooter">';
html += '<div class="sessionCardButtons flex align-items-center justify-content-center">';
var btnCssClass;
btnCssClass = session.ServerId && session.NowPlayingItem && session.SupportsRemoteControl && session.DeviceId !== connectionManager.deviceId() ? "" : " hide";
html += '<button is="paper-icon-button-light" class="sessionCardButton btnSessionPlayPause paper-icon-button-light ' + btnCssClass + '"><i class="md-icon">pause</i></button>';
html += '<button is="paper-icon-button-light" class="sessionCardButton btnSessionStop paper-icon-button-light ' + btnCssClass + '"><i class="md-icon">stop</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") + '"><i class="md-icon">info</i></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="md-icon">message</i></button>';
html += "</div>";
html += '<div class="sessionNowPlayingStreamInfo" style="padding:.5em 0 1em;">';
html += DashboardPage.getSessionNowPlayingStreamInfo(session);
html += "</div>";
html += '<div class="flex align-items-center justify-content-center">';
var userImage = DashboardPage.getUserImage(session);
html += userImage ? '<div class="activitylogUserPhoto" style="background-image:url(\'' + userImage + "');\"></div>" : '<div style="height:1.71em;"></div>';
html += '<div class="sessionUserName">';
html += DashboardPage.getUsersHtml(session);
html += "</div>";
html += "</div>";
html += "</div>";
html += "</div>";
html += "</div>";
}
}
parentElement.insertAdjacentHTML("beforeend", html);
var deadSessionElem = parentElement.querySelector(".deadSession");
if (deadSessionElem) {
deadSessionElem.parentNode.removeChild(deadSessionElem);
}
}
function renderRunningTasks(view, tasks) {
var html = "";
tasks = tasks.filter(function (task) {
if ("Idle" != task.State) {
return !task.IsHidden;
}
return false;
});
if (tasks.length) {
view.querySelector(".runningTasksContainer").classList.remove("hide");
} else {
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/>";
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="md-icon">cancel</i></button>';
} else if (task.State === "Cancelling") {
html += '<span style="color:#cc0000;">' + globalize.translate("LabelStopping") + "</span>";
}
html += "</p>";
}
view.querySelector("#divRunningTasks").innerHTML = html;
}
window.DashboardPage = {
startInterval: function (apiClient) {
apiClient.sendMessage("SessionsStart", "0,1500");
apiClient.sendMessage("ScheduledTasksInfoStart", "0,1000");
},
stopInterval: function (apiClient) {
apiClient.sendMessage("SessionsStop");
apiClient.sendMessage("ScheduledTasksInfoStop");
},
getSessionNowPlayingStreamInfo: function (session) {
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 (session.TranscodingInfo && session.TranscodingInfo.Framerate) {
html += " (" + session.TranscodingInfo.Framerate + " fps)";
}
showTranscodingInfo = true;
} else if (displayPlayMethod === "DirectPlay") {
html += globalize.translate("DirectPlaying");
}
if (showTranscodingInfo) {
var line = [];
if (session.TranscodingInfo) {
if (session.TranscodingInfo.Bitrate) {
if (session.TranscodingInfo.Bitrate > 1e6) {
line.push((session.TranscodingInfo.Bitrate / 1e6).toFixed(1) + " Mbps");
} else {
line.push(Math.floor(session.TranscodingInfo.Bitrate / 1e3) + " Kbps");
}
}
if (session.TranscodingInfo.Container) {
line.push(session.TranscodingInfo.Container);
}
if (session.TranscodingInfo.VideoCodec) {
line.push(session.TranscodingInfo.VideoCodec);
}
if (session.TranscodingInfo.AudioCodec && session.TranscodingInfo.AudioCodec != session.TranscodingInfo.Container) {
line.push(session.TranscodingInfo.AudioCodec);
}
}
if (line.length) {
html += " - " + line.join(" ");
}
}
return html;
},
getSessionNowPlayingTime: function (session) {
var nowPlayingItem = session.NowPlayingItem;
var html = "";
if (nowPlayingItem) {
if (session.PlayState.PositionTicks) {
html += datetime.getDisplayRunningTime(session.PlayState.PositionTicks);
} else {
html += "0:00";
}
html += " / ";
if (nowPlayingItem && nowPlayingItem.RunTimeTicks) {
html += datetime.getDisplayRunningTime(nowPlayingItem.RunTimeTicks);
} else {
html += "0:00";
}
}
return html;
},
getAppSecondaryText: function (session) {
return session.Client + " " + session.ApplicationVersion;
},
getNowPlayingName: function (session) {
var imgUrl = "";
var nowPlayingItem = session.NowPlayingItem;
if (!nowPlayingItem) {
return {
html: "Last seen " + humaneDate(session.LastActivityDate),
image: imgUrl
};
}
var topText = itemHelper.getDisplayName(nowPlayingItem);
var bottomText = "";
if (nowPlayingItem.Artists && nowPlayingItem.Artists.length) {
bottomText = topText;
topText = nowPlayingItem.Artists[0];
} else {
if (nowPlayingItem.SeriesName || nowPlayingItem.Album) {
bottomText = topText;
topText = nowPlayingItem.SeriesName || nowPlayingItem.Album;
} else if (nowPlayingItem.ProductionYear) {
bottomText = nowPlayingItem.ProductionYear;
}
}
if (nowPlayingItem.ImageTags && nowPlayingItem.ImageTags.Logo) {
imgUrl = ApiClient.getScaledImageUrl(nowPlayingItem.Id, {
tag: nowPlayingItem.ImageTags.Logo,
maxHeight: 24,
maxWidth: 130,
type: "Logo"
});
} else if (nowPlayingItem.ParentLogoImageTag) {
imgUrl = ApiClient.getScaledImageUrl(nowPlayingItem.ParentLogoItemId, {
tag: nowPlayingItem.ParentLogoImageTag,
maxHeight: 24,
maxWidth: 130,
type: "Logo"
});
}
if (imgUrl) {
topText = '<img src="' + imgUrl + '" style="max-height:24px;max-width:130px;" />';
}
return {
html: bottomText ? topText + "<br/>" + bottomText : topText,
image: imgUrl
};
},
getUsersHtml: function (session) {
var html = [];
if (session.UserId) {
html.push(session.UserName);
}
for (var i = 0, length = session.AdditionalUsers.length; i < length; i++) {
html.push(session.AdditionalUsers[i].UserName);
}
return html.join(", ");
},
getUserImage: function (session) {
if (session.UserId && session.UserPrimaryImageTag) {
return ApiClient.getUserImageUrl(session.UserId, {
tag: session.UserPrimaryImageTag,
type: "Primary"
});
}
return null;
},
updateSession: function (row, session) {
row.classList.remove("deadSession");
var nowPlayingItem = session.NowPlayingItem;
if (nowPlayingItem) {
row.classList.add("playingSession");
} else {
row.classList.remove("playingSession");
}
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");
}
if (session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons.length) {
row.querySelector(".btnSessionInfo").classList.remove("hide");
} else {
row.querySelector(".btnSessionInfo").classList.add("hide");
}
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");
} else {
btnSessionPlayPause.classList.add("hide");
row.querySelector(".btnSessionStop").classList.add("hide");
}
if (session.PlayState && session.PlayState.IsPaused) {
btnSessionPlayPause.querySelector("i").innerHTML = "play_arrow";
} else {
btnSessionPlayPause.querySelector("i").innerHTML = "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" : "";
var nowPlayingName = DashboardPage.getNowPlayingName(session);
var nowPlayingInfoElem = row.querySelector(".sessionNowPlayingInfo");
if (!(nowPlayingName.image && nowPlayingName.image == nowPlayingInfoElem.getAttribute("data-imgsrc"))) {
nowPlayingInfoElem.innerHTML = nowPlayingName.html;
nowPlayingInfoElem.setAttribute("data-imgsrc", nowPlayingName.image || "");
}
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"
});
} else {
playbackProgressElem.outerHTML = indicators.getProgressHtml(0, {
containerClass: "playbackProgress hide"
});
}
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"
});
} else {
transcodingProgress.outerHTML = indicators.getProgressHtml(0, {
containerClass: "transcodingProgress hide"
});
}
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.classList.add("sessionNowPlayingContent-withbackground");
} else {
imgElem.classList.remove("sessionNowPlayingContent-withbackground");
}
}
},
getClientImage: function (connection) {
var iconUrl = imageHelper.getDeviceIcon(connection.DeviceName);
return "<img src='" + iconUrl + "' />";
},
getNowPlayingImageUrl: function (item) {
if (item && item.BackdropImageTags && item.BackdropImageTags.length) {
return ApiClient.getScaledImageUrl(item.Id, {
type: "Backdrop",
tag: item.BackdropImageTags[0]
});
}
if (item && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) {
return ApiClient.getScaledImageUrl(item.ParentBackdropItemId, {
type: "Backdrop",
tag: item.ParentBackdropImageTags[0]
});
}
if (item && item.BackdropImageTag) {
return ApiClient.getScaledImageUrl(item.BackdropItemId, {
type: "Backdrop",
tag: item.BackdropImageTag
});
}
var imageTags = (item || {}).ImageTags || {};
if (item && imageTags.Thumb) {
return ApiClient.getScaledImageUrl(item.Id, {
type: "Thumb",
tag: imageTags.Thumb
});
}
if (item && item.ParentThumbImageTag) {
return ApiClient.getScaledImageUrl(item.ParentThumbItemId, {
type: "Thumb",
tag: item.ParentThumbImageTag
});
}
if (item && item.ThumbImageTag) {
return ApiClient.getScaledImageUrl(item.ThumbItemId, {
type: "Thumb",
tag: item.ThumbImageTag
});
}
if (item && imageTags.Primary) {
return ApiClient.getScaledImageUrl(item.Id, {
type: "Primary",
tag: imageTags.Primary
});
}
if (item && item.PrimaryImageTag) {
return ApiClient.getScaledImageUrl(item.PrimaryImageItemId, {
type: "Primary",
tag: item.PrimaryImageTag
});
}
if (item && item.AlbumPrimaryImageTag) {
return ApiClient.getScaledImageUrl(item.AlbumId, {
type: "Primary",
tag: item.AlbumPrimaryImageTag
});
}
return null;
},
systemUpdateTaskKey: "SystemUpdateTask",
stopTask: function (btn, id) {
var page = dom.parentWithClass(btn, "page");
ApiClient.stopScheduledTask(id).then(function () {
pollForInfo(page, ApiClient);
});
},
restart: function (btn) {
require(["confirm"], function (confirm) {
confirm({
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;
ApiClient.restartServer();
});
});
},
shutdown: function (btn) {
require(["confirm"], function (confirm) {
confirm({
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;
ApiClient.shutdownServer();
});
});
}
};
return function (view, params) {
function onRestartRequired(evt, apiClient) {
if (apiClient.serverId() === serverId) {
renderHasPendingRestart(view, apiClient, true);
}
}
function onServerShuttingDown(evt, apiClient) {
if (apiClient.serverId() === serverId) {
renderHasPendingRestart(view, apiClient, true);
}
}
function onServerRestarting(evt, apiClient) {
if (apiClient.serverId() === serverId) {
renderHasPendingRestart(view, apiClient, true);
}
}
function onPackageInstalling(evt, apiClient) {
if (apiClient.serverId() === serverId) {
pollForInfo(view, apiClient, true);
reloadSystemInfo(view, apiClient);
}
}
function onPackageInstallationCompleted(evt, apiClient) {
if (apiClient.serverId() === serverId) {
pollForInfo(view, apiClient, true);
reloadSystemInfo(view, apiClient);
}
}
function onSessionsUpdate(evt, apiClient, info) {
if (apiClient.serverId() === serverId) {
renderInfo(view, info);
}
}
function onScheduledTasksUpdate(evt, apiClient, info) {
if (apiClient.serverId() === serverId) {
renderRunningTasks(view, info);
}
}
var serverId = ApiClient.serverId();
view.querySelector(".activeDevices").addEventListener("click", onActiveDevicesClick);
view.addEventListener("viewshow", function () {
var page = this;
var apiClient = ApiClient;
if (apiClient) {
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);
DashboardPage.lastAppUpdateCheck = null;
reloadSystemInfo(page, ApiClient);
if (!page.userActivityLog) {
page.userActivityLog = new ActivityLog({
serverId: ApiClient.serverId(),
element: page.querySelector(".userActivityItems")
});
}
if (ApiClient.isMinServerVersion("3.4.1.25")) {
if (!page.serverActivityLog) {
page.serverActivityLog = new ActivityLog({
serverId: ApiClient.serverId(),
element: page.querySelector(".serverActivityItems")
});
}
}
refreshActiveRecordings(view, apiClient);
loading.hide();
}
});
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);
if (apiClient) {
DashboardPage.stopInterval(apiClient);
}
});
view.addEventListener("viewdestroy", function () {
var page = this;
var userActivityLog = page.userActivityLog;
if (userActivityLog) {
userActivityLog.destroy();
}
var serverActivityLog = page.serverActivityLog;
if (serverActivityLog) {
serverActivityLog.destroy();
}
});
};
});

View file

@ -0,0 +1,131 @@
define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emby-input", "emby-select", "emby-button"], function($, loading) {
"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>"
})).val(config.UICulture);
currentLanguage = config.UICulture;
if (systemInfo.CanSelfUpdate) {
page.querySelector(".fldAutomaticUpdates").classList.remove("hide");
} else {
page.querySelector(".fldAutomaticUpdates").classList.add("hide");
}
$("#chkEnableAutomaticServerUpdates", page).checked(config.EnableAutoUpdate);
$("#chkEnableAutomaticRestart", page).checked(config.EnableAutomaticRestart);
if (systemInfo.CanSelfRestart) {
page.querySelector("#fldEnableAutomaticRestart").classList.remove("hide");
} else {
page.querySelector("#fldEnableAutomaticRestart").classList.add("hide");
}
if (systemInfo.CanSelfRestart || systemInfo.CanSelfUpdate) {
$(".autoUpdatesContainer", page).removeClass("hide");
} else {
$(".autoUpdatesContainer", page).addClass("hide");
}
loading.hide();
}
function onSubmit() {
loading.show();
var form = this;
$(form).parents(".page");
return 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();
var requiresReload = (config.UICulture !== currentLanguage);
config.AutoRunWebApp = $("#chkAutoRunWebApp", form).checked();
config.EnableAutomaticRestart = $("#chkEnableAutomaticRestart", form).checked();
config.EnableAutoUpdate = $("#chkEnableAutomaticServerUpdates", 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;
if (currentBrandingOptions && brandingConfig.CustomCss !== currentBrandingOptions.CustomCss) {
requiresReload = true;
}
ApiClient.updateNamedConfiguration(brandingConfigKey, brandingConfig).then(function() {
Dashboard.processServerConfigurationUpdateResult();
if (requiresReload && !AppInfo.isNativeApp) {
window.location.reload(true);
}
});
})
})
}), !1
}
var currentBrandingOptions;
var currentLanguage;
var brandingConfigKey = "branding";
return function(view, params) {
$("#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;
}
picker.close();
},
validateWriteable: true,
header: Globalize.translate("HeaderSelectServerCachePath"),
instruction: Globalize.translate("HeaderSelectServerCachePathHelp")
})
})
});
$("#btnSelectMetadataPath", view).on("click.selectDirectory", function() {
require(["directorybrowser"], function(directoryBrowser) {
var picker = new directoryBrowser();
picker.show({
path: $("#txtMetadataPath", view).val(),
networkSharePath: $("#txtMetadataNetworkPath", view).val(),
callback: function(path, networkPath) {
if (path) {
$("#txtMetadataPath", view).val(path);
}
if (networkPath) {
$("#txtMetadataNetworkPath", view).val(networkPath);
}
picker.close();
},
validateWriteable: true,
header: Globalize.translate("HeaderSelectMetadataPath"),
instruction: Globalize.translate("HeaderSelectMetadataPathHelp"),
enableNetworkSharePath: true
})
})
});
$(".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 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 file

@ -0,0 +1,33 @@
define(["datetime", "loading", "apphost", "listViewStyle", "emby-button", "flexStyles"], function(datetime, loading, appHost) {
"use strict";
return function(view, params) {
view.addEventListener("viewbeforeshow", function() {
loading.show();
var apiClient = ApiClient;
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", {
name: log.Name
});
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>";
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>";
return logHtml;
}).join("");
html += "</div>";
view.querySelector(".serverLogs").innerHTML = html;
loading.hide();
});
});
}
});

View file

@ -0,0 +1,145 @@
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;
confirmSelections(localAddress, enableUpnp, function() {
var validationResult = getValidationAlert(form);
if (validationResult) return void alertText(validationResult);
validateHttps(form).then(function() {
loading.show();
ApiClient.getServerConfiguration().then(function(config) {
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) {
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.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.LocalNetworkAddresses = localAddress ? [localAddress] : [];
ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult, Dashboard.processErrorResponse);
})
})
}), e.preventDefault()
}
function triggerChange(select) {
var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", !1, !0), select.dispatchEvent(evt)
}
function getValidationAlert(form) {
return form.querySelector("#txtPublicPort").value === form.querySelector("#txtPublicHttpsPort").value ? "The public http and https ports must be different." : form.querySelector("#txtPortNumber").value === form.querySelector("#txtHttpsPort").value ? "The http and https ports must be different." : null
}
function validateHttps(form) {
var certPath = form.querySelector("#txtCertificatePath").value || null;
var httpsMode = form.querySelector("#selectHttpsMode").value;
return "enabled" !== httpsMode && "required" !== httpsMode || certPath ? Promise.resolve() : new Promise(function(resolve, reject) {
return alertText({
title: globalize.translate("TitleHostingSettings"),
text: globalize.translate("HttpsRequiresCert")
}).then(reject, reject)
})
}
function alertText(options) {
return new Promise(function(resolve, reject) {
require(["alert"], function(alert) {
alert(options).then(resolve, reject)
})
})
}
function confirmSelections(localAddress, enableUpnp, callback) {
localAddress || !enableUpnp ? alertText({
title: globalize.translate("TitleHostingSettings"),
text: globalize.translate("SettingsWarning")
}).then(callback) : callback()
}
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");
config.IsBehindProxy ? selectHttpsMode.value = "proxy" : config.RequireHttps ? selectHttpsMode.value = "required" : config.EnableHttps ? selectHttpsMode.value = "enabled" : 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"));
loading.hide();
}
view.querySelector("#chkRemoteAccess").addEventListener("change", function() {
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.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("#btnSelectCertPath").addEventListener("click", function() {
require(["directorybrowser"], function(directoryBrowser) {
var picker = new directoryBrowser;
picker.show({
includeFiles: !0,
includeDirectories: !0,
callback: function(path) {
path && (view.querySelector("#txtCertificatePath").value = path), picker.close()
},
header: globalize.translate("HeaderSelectCertificatePath")
})
})
});
view.querySelector(".dashboardHostingForm").addEventListener("submit", onSubmit), view.addEventListener("viewshow", function(e) {
loading.show();
ApiClient.getServerConfiguration().then(function(config) {
loadPage(view, config);
});
});
}
});

View file

@ -0,0 +1,122 @@
define(["jQuery", "emby-checkbox", "fnchecked"], 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");
}
function reload(page) {
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"));
Promise.all([promise1, promise2, promise3, promise4]).then(function (responses) {
var users = responses[0];
var notificationOptions = responses[1];
var types = responses[2];
var services = responses[3];
var notificationConfig = notificationOptions.Options.filter(function (n) {
return n.Type == type;
})[0];
var typeInfo = types.filter(function (n) {
return n.Type == type;
})[0] || {};
if (typeInfo.IsBasedOnUserEvent) {
$(".monitorUsers", page).show();
} else {
$(".monitorUsers", page).hide();
}
$(".notificationType", page).html(typeInfo.Name || "Unknown Notification");
if (!notificationConfig) {
notificationConfig = {
DisabledMonitorUsers: [],
SendToUsers: [],
DisabledServices: [],
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");
});
}
function save(page) {
var type = getParameterByName("type");
var promise1 = ApiClient.getNamedConfiguration(notificationsConfigurationKey);
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];
if (!notificationConfig) {
notificationConfig = {
Type: type
};
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) {
return !c.checked;
}).map(function (c) {
return c.getAttribute("data-itemid");
});
notificationConfig.SendToUsers = $(".chkSendTo", page).get().filter(function (c) {
return c.checked;
}).map(function (c) {
return c.getAttribute("data-itemid");
});
notificationConfig.DisabledServices = $(".chkService", page).get().filter(function (c) {
return !c.checked;
}).map(function (c) {
return c.getAttribute("data-itemid");
});
ApiClient.updateNamedConfiguration(notificationsConfigurationKey, notificationOptions).then(function (r) {
Dashboard.processServerConfigurationUpdateResult();
Dashboard.navigate("notificationsettings.html");
});
});
}
function onSubmit() {
save($(this).parents(".page"));
return false;
}
var notificationsConfigurationKey = "notifications";
$(document).on("pageinit", "#notificationSettingPage", function () {
var page = this;
$("#selectUsers", page).on("change", function () {
if ("Custom" == this.value) {
$(".selectCustomUsers", page).show();
} else {
$(".selectCustomUsers", page).hide();
}
});
$(".notificationSettingForm").off("submit", onSubmit).on("submit", onSubmit);
}).on("pageshow", "#notificationSettingPage", function () {
reload(this);
});
});

View file

@ -0,0 +1,60 @@
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 = "";
var showHelp = true;
html += list.map(function(notification) {
var itemHtml = "";
if (notification.Category !== lastCategory) {
lastCategory = notification.Category;
if (lastCategory) {
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>";
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 += "</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 md-icon">notifications_active</i>';
} else {
itemHtml += '<i class="listItemIcon md-icon" style="background-color:#999;">notifications_off</i>';
}
itemHtml += '<div class="listItemBody">';
itemHtml += '<div class="listItemBodyText">' + notification.Name + "</div>";
itemHtml += "</div>";
itemHtml += '<button type="button" is="paper-icon-button-light"><i class="md-icon">mode_edit</i></button>';
itemHtml += "</a>";
return itemHtml;
}).join("");
if (list.length) {
html += "</div>";
html += "</div>";
}
page.querySelector(".notificationList").innerHTML = html;
loading.hide();
})
}
return function(view, params) {
view.addEventListener("viewshow", function() {
reload(view);
});
}
});

View file

@ -0,0 +1,172 @@
define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "emby-button"], function ($, loading, libraryMenu, globalize, connectionManager) {
"use strict";
function populateHistory(packageInfo, page) {
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>";
}
$("#revisionHistory", page).html(html);
}
function populateVersions(packageInfo, page, installedPlugin) {
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>";
}
var selectmenu = $("#selectVersion", page).html(html);
if (!installedPlugin) {
$("#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];
if (packageVersion) {
var val = packageVersion.versionStr + "|" + packageVersion.classification;
selectmenu.val(val);
}
}
function renderPackage(pkg, installedPlugins, page) {
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");
} else {
$("#btnInstallDiv", page).addClass("hide");
$("#pSelectVersion", page).addClass("hide");
var msg = globalize.translate("MessageInstallPluginFromApp");
$("#nonServerMsg", page).html(msg).show();
}
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("");
}
if (installedPlugin) {
var currentVersionText = globalize.translate("MessageYouHaveVersionInstalled").replace("{0}", "<strong>" + installedPlugin.Version + "</strong>");
$("#pCurrentVersion", page).show().html(currentVersionText);
} else {
$("#pCurrentVersion", page).hide().html("");
}
loading.hide();
}
function alertText(options) {
require(["alert"], function (alert) {
alert(options);
});
}
function performInstallation(page, packageName, guid, updateClass, 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 () {
loading.hide();
alertText(globalize.translate("PluginInstalledMessage"));
});
};
if (developer !== 'jellyfin') {
loading.hide();
var msg = globalize.translate("MessagePluginInstallDisclaimer");
msg += "<br/>";
msg += "<br/>";
msg += globalize.translate("PleaseConfirmPluginInstallation");
require(["confirm"], function (confirm) {
confirm(msg, globalize.translate("HeaderConfirmPluginInstallation")).then(function () {
alertCallback();
}, function () {
console.log('plugin not installed');
});
});
} else {
alertCallback();
}
}
return function (view, params) {
$(".addPluginForm", view).on("submit", function () {
loading.show();
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];
if (installedPlugin) {
if (installedPlugin.Version === version) {
loading.hide();
Dashboard.alert({
message: globalize.translate("MessageAlreadyInstalled"),
title: globalize.translate("HeaderPluginInstallation")
});
}
} else {
performInstallation(page, name, guid, vals[1], version);
}
});
return false;
});
view.addEventListener("viewshow", function () {
var page = this;
loading.show();
var name = params.name;
var guid = params.guid;
var promise1 = ApiClient.getPackageInfo(name, guid);
var promise2 = ApiClient.getInstalledPlugins();
Promise.all([promise1, promise2]).then(function (responses) {
renderPackage(responses[0], responses[1], page);
});
});
};
});

View file

@ -0,0 +1,146 @@
define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-button", "emby-checkbox", "emby-select"], function (loading, libraryMenu, globalize) {
"use strict";
function reloadList(page) {
loading.show();
var promise1 = ApiClient.getAvailablePlugins();
var promise2 = ApiClient.getInstalledPlugins();
Promise.all([promise1, promise2]).then(function (responses) {
populateList({
catalogElement: page.querySelector("#pluginTiles"),
noItemsElement: page.querySelector("#noPlugins"),
availablePlugins: responses[0],
installedPlugins: responses[1]
});
});
}
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";
}
return globalize.translate(category);
}
function populateList(options) {
var availablePlugins = options.availablePlugins;
var installedPlugins = options.installedPlugins;
var categories = [];
availablePlugins.forEach(function (plugin, index, array) {
plugin.category = plugin.category || 'General';
plugin.categoryDisplayName = getHeaderText(plugin.category);
array[index] = plugin;
});
availablePlugins.sort(function (a, b) {
if (a.category > b.category) {
return 1;
} else if (b.category > a.category) {
return -1;
}
if (a.name > b.name) {
return 1;
} else if (b.name > a.name) {
return -1;
}
return 0;
});
var currentCategory = null;
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 class="verticalSection">';
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>";
if (!availablePlugins.length && options.noItemsElement) {
options.noItemsElement.classList.remove("hide");
}
options.catalogElement.innerHTML = html;
loading.hide();
}
function getPluginHtml(plugin, options, installedPlugins) {
var html = "";
var href = plugin.externalUrl ? plugin.externalUrl : "addplugin.html?name=" + encodeURIComponent(plugin.name) + "&guid=" + plugin.guid;
if (options.context) {
href += "&context=" + options.context;
}
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 md-icon">folder</i>';
}
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) {
return ip.Id == plugin.guid;
})[0];
html += "<div class='cardText cardText-secondary'>";
html += installedPlugin ? globalize.translate("LabelVersionInstalled").replace("{0}", installedPlugin.Version) : "&nbsp;";
html += "</div>";
html += "</div>";
html += "</div>";
return html += "</div>";
}
function getTabs() {
return [{
href: "installedplugins.html",
name: globalize.translate("TabMyPlugins")
}, {
href: "availableplugins.html",
name: globalize.translate("TabCatalog")
}];
}
window.PluginCatalog = {
renderCatalog: populateList
};
return function (view, params) {
view.addEventListener("viewshow", function () {
libraryMenu.setTabs("plugins", 1, getTabs);
reloadList(this);
});
};
});

View file

@ -0,0 +1,185 @@
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").replace("{0}", name);
require(["confirm"], function (confirm) {
confirm({
title: globalize.translate("UninstallPluginHeader"),
text: msg,
primary: "delete",
confirmText: globalize.translate("UninstallPluginHeader")
}).then(function () {
loading.show();
ApiClient.uninstallPlugin(uniqueid).then(function () {
reloadList(page);
});
});
});
}
function showNoConfigurationMessage() {
Dashboard.alert({
message: globalize.translate("NoPluginConfigurationMessage")
});
}
function showConnectMessage() {
Dashboard.alert({
message: globalize.translate("MessagePluginConfigurationRequiresLocalAccess")
});
}
function getPluginCardHtml(plugin, pluginConfigurationPages) {
var configPage = pluginConfigurationPages.filter(function (pluginConfigurationPage) {
return pluginConfigurationPage.PluginId == plugin.Id;
})[0];
var configPageUrl = configPage ? Dashboard.getConfigurationPageUrl(configPage.Name) : null;
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 md-icon">folder</i>';
}
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="md-icon">more_horiz</i></button>';
html += "</div>";
html += "<div class='cardText'>";
html += configPage ? configPage.DisplayName || plugin.Name : plugin.Name;
html += "</div>";
html += "<div class='cardText cardText-secondary'>";
html += plugin.Version;
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) {
populateList(page, plugins, configPages);
});
}
function populateList(page, plugins, pluginConfigurationPages) {
plugins = plugins.sort(function (plugin1, plugin2) {
if (plugin1.Name > plugin2.Name) {
return 1;
}
return -1;
});
var html = plugins.map(function (p) {
return getPluginCardHtml(p, pluginConfigurationPages);
}).join("");
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");
} else {
html += '<div style="padding:5px;">';
html += "<p>" + globalize.translate("MessageNoPluginsInstalled") + "</p>";
html += '<p><a is="emby-linkbutton" class="button-link" href="availableplugins.html">';
html += globalize.translate("BrowsePluginCatalogMessage");
html += "</a></p>";
html += "</div>";
}
installedPluginsElement.innerHTML = html;
loading.hide();
}
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 menuItems = [];
if (configHref) {
menuItems.push({
name: globalize.translate("ButtonSettings"),
id: "open",
icon: "mode_edit"
});
}
menuItems.push({
name: globalize.translate("ButtonUninstall"),
id: "delete",
icon: "delete"
});
require(["actionsheet"], function (actionsheet) {
actionsheet.show({
items: menuItems,
positionTo: elem,
callback: function (resultId) {
switch (resultId) {
case "open":
Dashboard.navigate(configHref);
break;
case "delete":
deletePlugin(page, id, name);
}
}
});
});
}
function reloadList(page) {
loading.show();
ApiClient.getInstalledPlugins().then(function (plugins) {
renderPlugins(page, plugins);
});
}
function getTabs() {
return [{
href: "installedplugins.html",
name: globalize.translate("TabMyPlugins")
}, {
href: "availableplugins.html",
name: globalize.translate("TabCatalog")
}];
}
function onInstalledPluginsClick(e) {
if (dom.parentWithClass(e.target, "noConfigPluginCard")) {
showNoConfigurationMessage();
} else if (dom.parentWithClass(e.target, "connectModePluginCard")) {
showConnectMessage();
} else {
var btnCardMenu = dom.parentWithClass(e.target, "btnCardMenu");
if (btnCardMenu) {
showPluginMenu(dom.parentWithClass(btnCardMenu, "page"), btnCardMenu);
}
}
}
pageIdOn("pageshow", "pluginsPage", function () {
libraryMenu.setTabs("plugins", 0, getTabs);
reloadList(this);
});
window.PluginsPage = {
renderPlugins: renderPlugins
};
});

View file

@ -0,0 +1,237 @@
define(["jQuery", "loading", "datetime", "dom", "globalize", "emby-input", "emby-button", "emby-select"], function ($, loading, datetime, dom, globalize) {
"use strict";
function fillTimeOfDay(select) {
var options = [];
for (var i = 0; i < 86400000; i += 900000) {
options.push({
name: ScheduledTaskPage.getDisplayTime(i * 10000),
value: i * 10000
});
}
select.innerHTML = options.map(function (o) {
return '<option value="' + o.value + '">' + o.name + '</option>';
}).join("");
}
Array.prototype.remove = function (from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
var ScheduledTaskPage = {
refreshScheduledTask: function (view) {
loading.show();
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);
require(["listViewStyle"], function () {
ScheduledTaskPage.loadTaskTriggers(view, task);
});
loading.hide();
},
loadTaskTriggers: function (context, task) {
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="md-icon listItemIcon">schedule</i>';
if (trigger.MaxRuntimeMs) {
html += '<div class="listItemBody two-line">';
} else {
html += '<div class="listItemBody">';
}
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");
} else {
html += globalize.translate("ValueTimeLimitMultiHour", hours);
}
html += "</div>";
}
html += "</div>";
html += '<button class="btnDeleteTrigger" data-index="' + i + '" type="button" is="paper-icon-button-light" title="' + globalize.translate("ButtonDelete") + '"><i class="md-icon">delete</i></button>';
html += "</div>";
}
html += "</div>";
context.querySelector(".taskTriggers").innerHTML = html;
},
getTriggerFriendlyName: function (trigger) {
if ("DailyTrigger" == trigger.Type) {
return "Daily at " + ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks);
}
if ("WeeklyTrigger" == trigger.Type) {
return trigger.DayOfWeek + "s at " + ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks);
}
if ("SystemEventTrigger" == trigger.Type && "WakeFromSleep" == trigger.SystemEvent) {
return "On wake from sleep";
}
if (trigger.Type == "IntervalTrigger") {
var hours = trigger.IntervalTicks / 36e9;
if (hours == 0.25) {
return "Every 15 minutes";
}
if (hours == 0.5) {
return "Every 30 minutes";
}
if (hours == 0.75) {
return "Every 45 minutes";
}
if (hours == 1) {
return "Every hour";
}
return "Every " + hours + " hours";
}
if (trigger.Type == "StartupTrigger") {
return "On application startup";
}
return trigger.Type;
},
getDisplayTime: function (ticks) {
var ms = ticks / 1e4;
var now = new Date();
now.setHours(0, 0, 0, 0);
now.setTime(now.getTime() + ms);
return datetime.getDisplayTime(now);
},
showAddTriggerPopup: function (view) {
$("#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 () {
ScheduledTaskPage.deleteTrigger(view, index);
});
});
},
deleteTrigger: function (view, index) {
loading.show();
var id = getParameterByName("id");
ApiClient.getScheduledTask(id).then(function (task) {
task.Triggers.remove(index);
ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).then(function () {
ScheduledTaskPage.refreshScheduledTask(view);
});
});
},
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");
}
},
getTriggerToAdd: function (page) {
var trigger = {
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();
}
var timeLimit = $("#txtTimeLimit", page).val() || "0";
timeLimit = parseFloat(timeLimit) * 3600000;
trigger.MaxRuntimeMs = timeLimit || null;
return trigger;
}
};
return function (view, params) {
function onSubmit(e) {
loading.show();
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");
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 () {
ScheduledTaskPage.refreshTriggerFields(view, this.value);
});
view.querySelector(".btnAddTrigger").addEventListener("click", function () {
ScheduledTaskPage.showAddTriggerPopup(view);
});
view.addEventListener("click", function (e) {
var btnDeleteTrigger = dom.parentWithClass(e.target, "btnDeleteTrigger");
if (btnDeleteTrigger) {
ScheduledTaskPage.confirmDeleteTrigger(view, parseInt(btnDeleteTrigger.getAttribute("data-index")));
}
});
view.addEventListener("viewshow", function () {
ScheduledTaskPage.refreshScheduledTask(view);
});
};
});

View file

@ -0,0 +1,173 @@
define(["jQuery", "loading", "events", "globalize", "serverNotifications", "humanedate", "listViewStyle", "emby-button"], function($, loading, events, globalize, serverNotifications) {
"use strict";
function reloadList(page) {
ApiClient.getScheduledTasks({
isHidden: false
}).then(function(tasks) {
populateList(page, tasks);
loading.hide();
})
}
function populateList(page, tasks) {
tasks = tasks.sort(function(a, b) {
a = a.Category + " " + a.Name;
b = b.Category + " " + b.Name;
return a == b ? 0 : a < b ? -1 : 1;
});
var currentCategory;
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 class="verticalSection verticalSection-extrabottompadding">';
html += '<div class="sectionTitleContainer" style="margin-bottom:1em;">';
html += '<h2 class="sectionTitle">';
html += currentCategory;
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 += "</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="md-icon listItemIcon">schedule</i>';
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="md-icon">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="md-icon">play_arrow</i></button>';
}
html += "</div>";
}
if (tasks.length) {
html += "</div>";
html += "</div>";
}
page.querySelector(".divScheduledTasks").innerHTML = html;
}
function getTaskProgressHtml(task) {
var html = "";
if (task.State === "Idle") {
if (task.LastExecutionResult) {
html += globalize.translate("LabelScheduledTaskLastRan").replace("{0}", humaneDate(task.LastExecutionResult.EndTimeUtc)).replace("{1}", humaneElapsed(task.LastExecutionResult.StartTimeUtc, task.LastExecutionResult.EndTimeUtc));
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") {
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>";
} else {
html += "<span style='color:#FF0000;'>" + globalize.translate("LabelStopping") + "</span>";
}
return html;
}
function updateTaskButton(elem, state) {
if (state === "Running") {
elem.classList.remove("btnStartTask");
elem.classList.add("btnStopTask");
elem.querySelector("i").innerHTML = "stop";
elem.title = globalize.translate("ButtonStop");
} else if (state === "Idle") {
elem.classList.add("btnStartTask");
elem.classList.remove("btnStopTask");
elem.querySelector("i").innerHTML = "play_arrow";
elem.title = globalize.translate("ButtonStart");
}
$(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);
}
}
function onPollIntervalFired() {
if (!ApiClient.isMessageChannelOpen()) {
reloadList(view);
}
}
function onScheduledTasksUpdate(e, apiClient, info) {
if (apiClient.serverId() === serverId) {
updateTasks(info);
}
}
function startInterval() {
ApiClient.sendMessage("ScheduledTasksInfoStart", "1000,1000");
pollInterval && clearInterval(pollInterval);
pollInterval = setInterval(onPollIntervalFired, 1e4);
}
function stopInterval() {
ApiClient.sendMessage("ScheduledTasksInfoStop");
pollInterval && clearInterval(pollInterval);
}
var pollInterval;
var serverId = ApiClient.serverId();
$(".divScheduledTasks", view).on("click", ".btnStartTask", function() {
var button = this;
var id = button.getAttribute("data-taskid");
ApiClient.startScheduledTask(id).then(function() {
updateTaskButton(button, "Running");
reloadList(view);
})
});
$(".divScheduledTasks", view).on("click", ".btnStopTask", function() {
var button = this;
var id = button.getAttribute("data-taskid");
ApiClient.stopScheduledTask(id).then(function() {
updateTaskButton(button, "");
reloadList(view);
})
});
view.addEventListener("viewbeforehide", function() {
events.off(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate);
stopInterval();
});
view.addEventListener("viewshow", function() {
loading.show();
startInterval();
reloadList(view);
events.on(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate);
});
}
});