mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-08 06:00:51 -07:00
Add playlist info page
This commit is contained in:
parent
11f2f8ff81
commit
b568af0a90
8 changed files with 168 additions and 62 deletions
|
@ -1753,6 +1753,7 @@ a:hover .dashboard-recent-media-cover {
|
||||||
box-shadow: inset 0 0 0 2px #e9a049;
|
box-shadow: inset 0 0 0 2px #e9a049;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity .2s;
|
transition: opacity .2s;
|
||||||
|
z-index: 2;
|
||||||
}
|
}
|
||||||
.summary-poster-face-overlay span {
|
.summary-poster-face-overlay span {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -1966,7 +1967,8 @@ a:hover .summary-poster-face-track .summary-poster-face-overlay span {
|
||||||
.item-children-instance {
|
.item-children-instance {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
overflow: hidden;
|
overflow: auto;
|
||||||
|
max-height: 875px;
|
||||||
}
|
}
|
||||||
.item-children-instance li {
|
.item-children-instance li {
|
||||||
float: left;
|
float: left;
|
||||||
|
@ -2102,7 +2104,7 @@ a:hover .item-children-poster {
|
||||||
}
|
}
|
||||||
.item-children-list-item-title {
|
.item-children-list-item-title {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: calc(100% - 110px);
|
/*width: calc(100% - 110px);*/
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
@ -2112,7 +2114,7 @@ a:hover .item-children-poster {
|
||||||
color: #777;
|
color: #777;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 40px;
|
width: 60px;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
#new_title h3 {
|
#new_title h3 {
|
||||||
|
@ -3717,6 +3719,20 @@ a:hover .overlay-refresh-image {
|
||||||
a:hover .overlay-refresh-image:hover {
|
a:hover .overlay-refresh-image:hover {
|
||||||
opacity: .9;
|
opacity: .9;
|
||||||
}
|
}
|
||||||
|
.smart-playlist-image {
|
||||||
|
float: left;
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
left: 5px;
|
||||||
|
background-color: #8e6191;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 16px;
|
||||||
|
z-index: 1;
|
||||||
|
width: 32px;
|
||||||
|
padding: 5px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
#ip_error, #isp_error {
|
#ip_error, #isp_error {
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
display: none;
|
display: none;
|
||||||
|
|
|
@ -84,8 +84,10 @@ DOCUMENTATION :: END
|
||||||
%>
|
%>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
% if data['media_type'] != 'playlist':
|
||||||
<% fallback = 'art-live-full' if data['live'] else None %>
|
<% fallback = 'art-live-full' if data['live'] else None %>
|
||||||
<div class="art-face" style="background-image:url(${page('pms_image_proxy', data['art'], data['rating_key'], 1920, 1080, fallback=fallback)})"></div>
|
<div class="art-face" style="background-image:url(${page('pms_image_proxy', data['art'], data['rating_key'], 1920, 1080, fallback=fallback)})"></div>
|
||||||
|
% endif
|
||||||
% if _session['user_group'] == 'admin':
|
% if _session['user_group'] == 'admin':
|
||||||
<span class="overlay-refresh-image info-art" title="Refresh background image"><i class="fa fa-refresh refresh_pms_image"></i></span>
|
<span class="overlay-refresh-image info-art" title="Refresh background image"><i class="fa fa-refresh refresh_pms_image"></i></span>
|
||||||
% endif
|
% endif
|
||||||
|
@ -150,6 +152,8 @@ DOCUMENTATION :: END
|
||||||
<li><a href="${page('info', data['parent_rating_key'])}">${data['parent_title']}</a></li>
|
<li><a href="${page('info', data['parent_rating_key'])}">${data['parent_title']}</a></li>
|
||||||
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
|
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
|
||||||
<li class="active metadata-xml">Track ${data['media_index']} - ${data['title']}</li>
|
<li class="active metadata-xml">Track ${data['media_index']} - ${data['title']}</li>
|
||||||
|
% elif data['media_type'] == 'playlist':
|
||||||
|
<li class="active metadata-xml">${data['title']}</li>
|
||||||
% endif
|
% endif
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -160,6 +164,8 @@ DOCUMENTATION :: END
|
||||||
<div class="summary-content-poster hidden-xs hidden-sm">
|
<div class="summary-content-poster hidden-xs hidden-sm">
|
||||||
% if data['media_type'] == 'track':
|
% if data['media_type'] == 'track':
|
||||||
<a href="${config['pms_web_url']}#!/server/${config['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${data['parent_rating_key']}" target="_blank" title="View on Plex Web">
|
<a href="${config['pms_web_url']}#!/server/${config['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${data['parent_rating_key']}" target="_blank" title="View on Plex Web">
|
||||||
|
% elif data['media_type'] == 'playlist':
|
||||||
|
<a href="${config['pms_web_url']}#!/server/${config['pms_identifier']}/playlist?key=%2Fplaylists%2F${data['rating_key']}" target="_blank" title="View on Plex Web">
|
||||||
% elif not data['live']:
|
% elif not data['live']:
|
||||||
<a href="${config['pms_web_url']}#!/server/${config['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${data['rating_key']}" target="_blank" title="View on Plex Web">
|
<a href="${config['pms_web_url']}#!/server/${config['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${data['rating_key']}" target="_blank" title="View on Plex Web">
|
||||||
% endif
|
% endif
|
||||||
|
@ -179,11 +185,14 @@ DOCUMENTATION :: END
|
||||||
% if _session['user_group'] == 'admin':
|
% if _session['user_group'] == 'admin':
|
||||||
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
|
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
|
||||||
% endif
|
% endif
|
||||||
% elif data['media_type'] == 'artist' or data['media_type'] == 'album' or data['media_type'] == 'track':
|
% elif data['media_type'] == 'artist' or data['media_type'] == 'album' or data['media_type'] == 'track' or data['media_type'] == 'playlist':
|
||||||
<div class="summary-poster-face-track" style="background-image: url(${page('pms_image_proxy', data['thumb'], data['rating_key'], 500, 500, fallback='cover')});">
|
<div class="summary-poster-face-track" style="background-image: url(${page('pms_image_proxy', data['thumb'], data['rating_key'], 500, 500, fallback='cover')});">
|
||||||
<div class="summary-poster-face-overlay">
|
<div class="summary-poster-face-overlay">
|
||||||
<span></span>
|
<span></span>
|
||||||
</div>
|
</div>
|
||||||
|
% if data['media_type'] == 'playlist' and data['smart']:
|
||||||
|
<span class="smart-playlist-image" title="Smart Playlist"><i class="fa fa-gear"></i></span>
|
||||||
|
% endif
|
||||||
</div>
|
</div>
|
||||||
% if _session['user_group'] == 'admin':
|
% if _session['user_group'] == 'admin':
|
||||||
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
|
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
|
||||||
|
@ -214,7 +223,7 @@ DOCUMENTATION :: END
|
||||||
<h3 class="hidden-xs">S${data['parent_media_index']} · E${data['media_index']}</h3>
|
<h3 class="hidden-xs">S${data['parent_media_index']} · E${data['media_index']}</h3>
|
||||||
% endif
|
% endif
|
||||||
% endif
|
% endif
|
||||||
% elif data['media_type'] in ('movie', 'show', 'artist', 'collection'):
|
% elif data['media_type'] in ('movie', 'show', 'artist', 'collection', 'playlist'):
|
||||||
<h1> </h1><h1>${data['title']}</h1>
|
<h1> </h1><h1>${data['title']}</h1>
|
||||||
% elif data['media_type'] == 'season':
|
% elif data['media_type'] == 'season':
|
||||||
<h1> </h1><h1><a href="${page('info', data['parent_rating_key'])}">${data['parent_title']}</a></h1>
|
<h1> </h1><h1><a href="${page('info', data['parent_rating_key'])}">${data['parent_title']}</a></h1>
|
||||||
|
@ -242,7 +251,7 @@ DOCUMENTATION :: END
|
||||||
<div class="summary-content-padding hidden-xs hidden-sm" style="height: 270px;">
|
<div class="summary-content-padding hidden-xs hidden-sm" style="height: 270px;">
|
||||||
% elif data['media_type'] == 'episode':
|
% elif data['media_type'] == 'episode':
|
||||||
<div class="summary-content-padding hidden-xs hidden-sm" style="height: 70px;">
|
<div class="summary-content-padding hidden-xs hidden-sm" style="height: 70px;">
|
||||||
% elif data['media_type'] == 'artist' or data['media_type'] == 'album':
|
% elif data['media_type'] in ('artist', 'album', 'playlist'):
|
||||||
<div class="summary-content-padding hidden-xs hidden-sm" style="height: 150px;">
|
<div class="summary-content-padding hidden-xs hidden-sm" style="height: 150px;">
|
||||||
% elif data['media_type'] == 'track':
|
% elif data['media_type'] == 'track':
|
||||||
<div class="summary-content-padding hidden-xs hidden-sm" style="height: 180px;">
|
<div class="summary-content-padding hidden-xs hidden-sm" style="height: 180px;">
|
||||||
|
@ -323,7 +332,12 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
<div class="summary-content-details-tag">
|
<div class="summary-content-details-tag">
|
||||||
% if data['duration']:
|
% if data['duration']:
|
||||||
Runtime <strong> <span id="runtime">${data['duration']}</span> mins</strong>
|
Items <strong> ${data['children_count']} ${'track' if data['playlist_type'] == 'audio' else 'video'}${'s' if data['children_count'] > 1 else ''} </strong>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
<div class="summary-content-details-tag">
|
||||||
|
% if data['duration']:
|
||||||
|
Runtime <strong> <span id="runtime">${data['duration']}</span></strong>
|
||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
<div class="summary-content-details-tag">
|
<div class="summary-content-details-tag">
|
||||||
|
@ -452,8 +466,19 @@ DOCUMENTATION :: END
|
||||||
</div>
|
</div>
|
||||||
<div id="collection-related-list-container" style="display: none;">
|
<div id="collection-related-list-container" style="display: none;">
|
||||||
</div>
|
</div>
|
||||||
|
% elif data['media_type'] == 'playlist':
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="table-card-header">
|
||||||
|
<div class="header-bar">
|
||||||
|
<span>${'Track' if data['playlist_type'] == 'audio' else 'Video'} List for <strong>${data['title']}</strong></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-card-back">
|
||||||
|
<div id="children-list" class="children-list"><i class="fa fa-refresh fa-spin"></i> Loading ${'track' if data['playlist_type'] == 'audio' else 'video'} list...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
% endif
|
% endif
|
||||||
% if data['media_type'] != 'collection':
|
% if data['media_type'] not in ('collection', 'playlist'):
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="table-card-header">
|
<div class="table-card-header">
|
||||||
<div class="header-bar">
|
<div class="header-bar">
|
||||||
|
@ -754,7 +779,7 @@ DOCUMENTATION :: END
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
% endif
|
% endif
|
||||||
% if data['media_type'] != 'collection':
|
% if data['media_type'] not in ('collection', 'playlist'):
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
get_history();
|
get_history();
|
||||||
|
@ -830,13 +855,16 @@ DOCUMENTATION :: END
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
% endif
|
% endif
|
||||||
% if data['media_type'] in ('show', 'season', 'artist', 'album', 'collection'):
|
% if data['media_type'] in ('show', 'season', 'artist', 'album', 'collection', 'playlist'):
|
||||||
<script>
|
<script>
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'get_item_children',
|
url: 'get_item_children',
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
async: true,
|
async: true,
|
||||||
data: { rating_key : "${data['rating_key']}" },
|
data: {
|
||||||
|
rating_key: "${data['rating_key']}",
|
||||||
|
media_type: "${data['media_type']}"
|
||||||
|
},
|
||||||
complete: function(xhr, status) {
|
complete: function(xhr, status) {
|
||||||
$("#children-list").html(xhr.responseText);
|
$("#children-list").html(xhr.responseText);
|
||||||
}
|
}
|
||||||
|
@ -850,7 +878,7 @@ DOCUMENTATION :: END
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
async: true,
|
async: true,
|
||||||
data: {
|
data: {
|
||||||
rating_key : "${data['rating_key']}",
|
rating_key: "${data['rating_key']}",
|
||||||
title: "${data['title']}"
|
title: "${data['title']}"
|
||||||
},
|
},
|
||||||
complete: function(xhr, status) {
|
complete: function(xhr, status) {
|
||||||
|
@ -865,7 +893,7 @@ DOCUMENTATION :: END
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#airdate").html(moment($("#airdate").text()).format('MMM DD, YYYY'));
|
$("#airdate").html(moment($("#airdate").text()).format('MMM DD, YYYY'));
|
||||||
$("#runtime").html(millisecondsToMinutes($("#runtime").text(), true));
|
$("#runtime").html(humanDuration($("#runtime").text(), 'dhm'));
|
||||||
$('div.art-face').animate({ opacity: 0.2 }, { duration: 1000 });
|
$('div.art-face').animate({ opacity: 0.2 }, { duration: 1000 });
|
||||||
$('#channel-icon').popover({
|
$('#channel-icon').popover({
|
||||||
selector: '[data-toggle=popover]',
|
selector: '[data-toggle=popover]',
|
||||||
|
|
|
@ -28,14 +28,14 @@ DOCUMENTATION :: END
|
||||||
|
|
||||||
% if data != None:
|
% if data != None:
|
||||||
<%
|
<%
|
||||||
from plexpy.helpers import page
|
from plexpy.helpers import cast_to_int, page
|
||||||
%>
|
%>
|
||||||
% if data['children_count'] > 0:
|
% if data['children_count'] > 0:
|
||||||
<div class="item-children-wrapper">
|
<div class="item-children-wrapper">
|
||||||
<ul class="item-children-instance list-unstyled">
|
<ul class="item-children-instance list-unstyled">
|
||||||
% for child in data['children_list']:
|
% for child in data['children_list']:
|
||||||
% if child['rating_key']:
|
% if child['rating_key']:
|
||||||
% if data['children_type'] == 'track':
|
% if data['children_type'] == 'track' or media_type == 'playlist':
|
||||||
<li class="item-children-list-item">
|
<li class="item-children-list-item">
|
||||||
% else:
|
% else:
|
||||||
<li>
|
<li>
|
||||||
|
@ -122,32 +122,21 @@ DOCUMENTATION :: END
|
||||||
<a href="${page('info', child['rating_key'])}" title="${child['title']}">${child['title']}</a>
|
<a href="${page('info', child['rating_key'])}" title="${child['title']}">${child['title']}</a>
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
% elif data['children_type'] == 'track':
|
% elif data['children_type'] == 'track' or media_type == 'playlist':
|
||||||
% if loop.index % 2 == 0:
|
<% i = 'even' if loop.index % 2 == 0 else 'odd' %>
|
||||||
<div class="item-children-list-item-even">
|
<div class="item-children-list-item-${i}">
|
||||||
<span class="item-children-list-item-index"> ${child['media_index']}</span>
|
<span class="item-children-list-item-index"> ${child['media_index'] or loop.index + 1}</span>
|
||||||
<span class="item-children-list-item-title"><a href="${page('info', child['rating_key'])}" title="${child['title']}">${child['title']}</a>
|
<span class="item-children-list-item-title">
|
||||||
% if child['original_title']:
|
<a href="${page('info', child['rating_key'])}" title="${child['title']}">${child['title']}</a>
|
||||||
|
% if child['original_title']:
|
||||||
<span class="text-muted"> - ${child['original_title']}</span>
|
<span class="text-muted"> - ${child['original_title']}</span>
|
||||||
% endif
|
% endif
|
||||||
</span>
|
</span>
|
||||||
<span class="item-children-list-item-duration" id="item-children-list-item-duration-${loop.index + 1}">
|
<span class="item-children-list-item-duration" id="item-children-list-item-duration-${loop.index + 1}">
|
||||||
<script>$('#item-children-list-item-duration-${loop.index + 1}').text(moment.utc(${child['duration']}).format("m:ss"));</script>
|
<% f = 'h:mm:ss' if cast_to_int(child['duration']) >= 3600000 else 'm:ss' %>
|
||||||
|
<script>$('#item-children-list-item-duration-${loop.index + 1}').text(moment.utc(${child['duration']}).format("${f}"));</script>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
% else:
|
|
||||||
<div class="item-children-list-item-odd">
|
|
||||||
<span class="item-children-list-item-index"> ${child['media_index']}</span>
|
|
||||||
<span class="item-children-list-item-title"><a href="${page('info', child['rating_key'])}" title="${child['title']}">${child['title']}</a>
|
|
||||||
% if child['original_title']:
|
|
||||||
<span class="text-muted"> - ${child['original_title']}</span>
|
|
||||||
% endif
|
|
||||||
</span>
|
|
||||||
<span class="item-children-list-item-duration" id="item-children-list-item-duration-${loop.index + 1}">
|
|
||||||
<script>$('#item-children-list-item-duration-${loop.index + 1}').text(moment.utc(${child['duration']}).format("m:ss"));</script>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
</li>
|
</li>
|
||||||
% endif
|
% endif
|
||||||
|
|
|
@ -330,25 +330,6 @@ function humanTime(seconds) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function humanTimeClean(seconds) {
|
|
||||||
var text;
|
|
||||||
if (seconds >= 86400) {
|
|
||||||
text = Math.floor(moment.duration(seconds, 'seconds').asDays()) + ' days ' + Math.floor(moment.duration((
|
|
||||||
seconds % 86400), 'seconds').asHours()) + ' hrs ' + Math.floor(moment.duration(
|
|
||||||
((seconds % 86400) % 3600), 'seconds').asMinutes()) + ' mins';
|
|
||||||
return text;
|
|
||||||
} else if (seconds >= 3600) {
|
|
||||||
text = Math.floor(moment.duration((seconds % 86400), 'seconds').asHours()) + ' hrs ' + Math.floor(moment.duration(
|
|
||||||
((seconds % 86400) % 3600), 'seconds').asMinutes()) + ' mins';
|
|
||||||
return text;
|
|
||||||
} else if (seconds >= 60) {
|
|
||||||
text = Math.floor(moment.duration(((seconds % 86400) % 3600), 'seconds').asMinutes()) + ' mins';
|
|
||||||
return text;
|
|
||||||
} else {
|
|
||||||
text = '0';
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String.prototype.toProperCase = function () {
|
String.prototype.toProperCase = function () {
|
||||||
return this.replace(/\w\S*/g, function (txt) {
|
return this.replace(/\w\S*/g, function (txt) {
|
||||||
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
||||||
|
@ -372,6 +353,57 @@ function millisecondsToMinutes(ms, roundToMinute) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function humanDuration(ms, sig='dhms', units='ms') {
|
||||||
|
var factors = {
|
||||||
|
d: 86400000,
|
||||||
|
h: 3600000,
|
||||||
|
m: 60000,
|
||||||
|
s: 1000,
|
||||||
|
ms: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
ms = parseInt(ms);
|
||||||
|
var d, h, m, s;
|
||||||
|
|
||||||
|
if (ms > 0) {
|
||||||
|
ms = ms * factors[units];
|
||||||
|
|
||||||
|
h = ms % factors['d'];
|
||||||
|
d = Math.trunc(ms / factors['d']);
|
||||||
|
|
||||||
|
m = h % factors['h'];
|
||||||
|
h = Math.trunc(h / factors['h']);
|
||||||
|
|
||||||
|
s = m % factors['m'];
|
||||||
|
m = Math.trunc(m / factors['m']);
|
||||||
|
|
||||||
|
ms = s % factors['s'];
|
||||||
|
s = Math.trunc(s / factors['s']);
|
||||||
|
|
||||||
|
var hd_list = [];
|
||||||
|
if (sig >= 'd' && d > 0) {
|
||||||
|
d = (sig === 'd' && h >= 12) ? d + 1 : d;
|
||||||
|
hd_list.push(d.toString() + ' day' + ((d > 1) ? 's' : ''));
|
||||||
|
}
|
||||||
|
if (sig >= 'dh' && h > 0) {
|
||||||
|
h = (sig === 'dh' && m >= 30) ? h + 1 : h;
|
||||||
|
hd_list.push(h.toString() + ' hr' + ((h > 1) ? 's' : ''));
|
||||||
|
}
|
||||||
|
if (sig >= 'dhm' && m > 0) {
|
||||||
|
m = (sig === 'dhm' && s >= 30) ? m + 1 : m;
|
||||||
|
hd_list.push(m.toString() + ' min' + ((m > 1) ? 's' : ''));
|
||||||
|
}
|
||||||
|
if (sig >= 'dhms' && s > 0) {
|
||||||
|
hd_list.push(s.toString() + ' sec' + ((s > 1) ? 's' : ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
return hd_list.join(' ')
|
||||||
|
} else {
|
||||||
|
return '0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Our countdown plugin takes a callback, a duration, and an optional message
|
// Our countdown plugin takes a callback, a duration, and an optional message
|
||||||
$.fn.countdown = function (callback, duration, message) {
|
$.fn.countdown = function (callback, duration, message) {
|
||||||
// If no message is provided, we use an empty string
|
// If no message is provided, we use an empty string
|
||||||
|
|
|
@ -192,7 +192,7 @@ libraries_list_table_options = {
|
||||||
"data": "duration",
|
"data": "duration",
|
||||||
"createdCell": function (td, cellData, rowData, row, col) {
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
if (cellData !== null && cellData !== '') {
|
if (cellData !== null && cellData !== '') {
|
||||||
$(td).html(humanTimeClean(cellData));
|
$(td).html(humanDuration(cellData, 'dhm', 's'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"searchable": false,
|
"searchable": false,
|
||||||
|
|
|
@ -212,7 +212,7 @@ users_list_table_options = {
|
||||||
"data": "duration",
|
"data": "duration",
|
||||||
"createdCell": function (td, cellData, rowData, row, col) {
|
"createdCell": function (td, cellData, rowData, row, col) {
|
||||||
if (cellData !== null && cellData !== '') {
|
if (cellData !== null && cellData !== '') {
|
||||||
$(td).html(humanTimeClean(cellData));
|
$(td).html(humanDuration(cellData, 'dhm', 's'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"searchable": false,
|
"searchable": false,
|
||||||
|
|
|
@ -173,6 +173,22 @@ class PmsConnect(object):
|
||||||
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
def get_playlist_items(self, rating_key='', output_format=''):
|
||||||
|
"""
|
||||||
|
Return metadata for items of the requested playlist.
|
||||||
|
|
||||||
|
Parameters required: rating_key { Plex ratingKey }
|
||||||
|
Optional parameters: output_format { dict, json }
|
||||||
|
|
||||||
|
Output: array
|
||||||
|
"""
|
||||||
|
uri = '/playlists/' + rating_key + '/items'
|
||||||
|
request = self.request_handler.make_request(uri=uri,
|
||||||
|
request_type='GET',
|
||||||
|
output_format=output_format)
|
||||||
|
|
||||||
|
return request
|
||||||
|
|
||||||
def get_recently_added(self, start='0', count='0', output_format=''):
|
def get_recently_added(self, start='0', count='0', output_format=''):
|
||||||
"""
|
"""
|
||||||
Return list of recently added items.
|
Return list of recently added items.
|
||||||
|
@ -654,6 +670,8 @@ class PmsConnect(object):
|
||||||
metadata_main_list = a.getElementsByTagName('Track')
|
metadata_main_list = a.getElementsByTagName('Track')
|
||||||
elif a.getElementsByTagName('Photo'):
|
elif a.getElementsByTagName('Photo'):
|
||||||
metadata_main_list = a.getElementsByTagName('Photo')
|
metadata_main_list = a.getElementsByTagName('Photo')
|
||||||
|
elif a.getElementsByTagName('Playlist'):
|
||||||
|
metadata_main_list = a.getElementsByTagName('Playlist')
|
||||||
else:
|
else:
|
||||||
logger.debug("Tautulli Pmsconnect :: Metadata failed")
|
logger.debug("Tautulli Pmsconnect :: Metadata failed")
|
||||||
return {}
|
return {}
|
||||||
|
@ -1251,6 +1269,26 @@ class PmsConnect(object):
|
||||||
'live': int(helpers.get_xml_attr(metadata_main, 'live') == '1')
|
'live': int(helpers.get_xml_attr(metadata_main, 'live') == '1')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
elif metadata_type == 'playlist':
|
||||||
|
metadata = {'media_type': metadata_type,
|
||||||
|
'section_id': section_id,
|
||||||
|
'library_name': library_name,
|
||||||
|
'rating_key': helpers.get_xml_attr(metadata_main, 'ratingKey'),
|
||||||
|
'guid': helpers.get_xml_attr(metadata_main, 'guid'),
|
||||||
|
'title': helpers.get_xml_attr(metadata_main, 'title'),
|
||||||
|
'summary': helpers.get_xml_attr(metadata_main, 'summary'),
|
||||||
|
'duration': helpers.get_xml_attr(metadata_main, 'duration'),
|
||||||
|
'composite': helpers.get_xml_attr(metadata_main, 'composite'),
|
||||||
|
'thumb': helpers.get_xml_attr(metadata_main, 'composite'),
|
||||||
|
'added_at': helpers.get_xml_attr(metadata_main, 'addedAt'),
|
||||||
|
'updated_at': helpers.get_xml_attr(metadata_main, 'updatedAt'),
|
||||||
|
'last_viewed_at': helpers.get_xml_attr(metadata_main, 'lastViewedAt'),
|
||||||
|
'children_count': helpers.cast_to_int(helpers.get_xml_attr(metadata_main, 'leafCount')),
|
||||||
|
'smart': helpers.cast_to_int(helpers.get_xml_attr(metadata_main, 'smart')),
|
||||||
|
'playlist_type': helpers.get_xml_attr(metadata_main, 'playlistType'),
|
||||||
|
'live': int(helpers.get_xml_attr(metadata_main, 'live') == '1')
|
||||||
|
}
|
||||||
|
|
||||||
elif metadata_type == 'clip':
|
elif metadata_type == 'clip':
|
||||||
metadata = {'media_type': metadata_type,
|
metadata = {'media_type': metadata_type,
|
||||||
'section_id': section_id,
|
'section_id': section_id,
|
||||||
|
@ -2241,13 +2279,15 @@ class PmsConnect(object):
|
||||||
logger.warn("Tautulli Pmsconnect :: Failed to terminate session: %s." % msg)
|
logger.warn("Tautulli Pmsconnect :: Failed to terminate session: %s." % msg)
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
def get_item_children(self, rating_key='', get_grandchildren=False):
|
def get_item_children(self, rating_key='', media_type=None, get_grandchildren=False):
|
||||||
"""
|
"""
|
||||||
Return processed and validated children list.
|
Return processed and validated children list.
|
||||||
|
|
||||||
Output: array
|
Output: array
|
||||||
"""
|
"""
|
||||||
if get_grandchildren:
|
if media_type == 'playlist':
|
||||||
|
children_data = self.get_playlist_items(rating_key, output_format='xml')
|
||||||
|
elif get_grandchildren:
|
||||||
children_data = self.get_metadata_grandchildren(rating_key, output_format='xml')
|
children_data = self.get_metadata_grandchildren(rating_key, output_format='xml')
|
||||||
else:
|
else:
|
||||||
children_data = self.get_metadata_children(rating_key, output_format='xml')
|
children_data = self.get_metadata_children(rating_key, output_format='xml')
|
||||||
|
|
|
@ -4341,13 +4341,14 @@ class WebInterface(object):
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
@requireAuth()
|
@requireAuth()
|
||||||
def get_item_children(self, rating_key='', **kwargs):
|
def get_item_children(self, rating_key='', media_type=None, **kwargs):
|
||||||
|
|
||||||
pms_connect = pmsconnect.PmsConnect()
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
result = pms_connect.get_item_children(rating_key=rating_key)
|
result = pms_connect.get_item_children(rating_key=rating_key, media_type=media_type)
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
return serve_template(templatename="info_children_list.html", data=result, title="Children List")
|
return serve_template(templatename="info_children_list.html", data=result,
|
||||||
|
media_type=media_type, title="Children List")
|
||||||
else:
|
else:
|
||||||
logger.warn("Unable to retrieve data for get_item_children.")
|
logger.warn("Unable to retrieve data for get_item_children.")
|
||||||
return serve_template(templatename="info_children_list.html", data=None, title="Children List")
|
return serve_template(templatename="info_children_list.html", data=None, title="Children List")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue